📄 wsahwnd.c
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// This source code is licensed under Microsoft Shared Source License
// Version 1.0 for Windows CE.
// For a copy of the license visit http://go.microsoft.com/fwlink/?LinkId=3223.
//
//
// wsahwnd.c
//
// async winsock implementation of
// WSAAsyncSelect
// WSAAsyncGetHostByName
// WSAAsyncGetAddrInfo
// WSACancelAsyncRequest
//
#include <winsock2p.h>
#include <ws2tcpip.h>
int WSACancelAsyncRequest (HANDLE hAsyncTaskHandle);
HANDLE WSAAsyncGetHostByName (HWND hWnd, unsigned int wMsg, const char FAR * name, char FAR * buf, int buflen );
int WSAAsyncSelect (SOCKET s, HWND hWnd, unsigned int wMsg, long lEvent );
HANDLE WSAAsyncGetAddrInfo(HWND hWnd, unsigned int uMsg, const char * name, unsigned short port, ADDRINFO **ppai);
int cpyhent(char * lpDstBuffer, const PHOSTENT lpSrcHostent, int * lpBufSize );
typedef struct _WSAASYNC_SOCKET {
struct _WSAASYNC_SOCKET * ws_next;
SOCKET ws_socket;
HWND ws_hwnd;
u_int ws_wmsg;
long ws_levents;
WSAEVENT ws_hevent;
} WSAASYNC_SOCKET, * PWSAASYNC_SOCKET;
typedef struct WSAREQ {
struct WSAREQ *pNext;
HWND hWnd;
uint wMsg;
char *pBuf;
DWORD dwBufLen;
char *pName;
DWORD Status;
unsigned short port;
ADDRINFO **ppAI;
} WSAREQ;
BOOL g_bWSAAsyncCSInit;
CRITICAL_SECTION g_WSAAsyncCS;
PWSAASYNC_SOCKET g_WSAAsyncSelectList;
int g_cWSAAsyncSelectSockets;
BOOL g_bWSAAsyncSelectThreadRunning;
WSAEVENT g_WSAAsyncSelectSignal;
WSAREQ * g_WSAReqList;
HANDLE g_hCoreDll;
typedef BOOL (*pfnPostMessageW)(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
pfnPostMessageW g_pfnPostMessageW;
BOOL IsAPIReady(DWORD PSL);
//
// Initialize async winsocket globals
//
BOOL WS2AsyncInit(void)
{
BOOL bRet;
if (!IsAPIReady(SH_WMGR)) {
// Window manager not available
SetLastError(WSASYSNOTREADY);
return FALSE;
}
// Init async select globals
if (FALSE == g_bWSAAsyncCSInit) {
g_bWSAAsyncCSInit = TRUE;
InitializeCriticalSection(&g_WSAAsyncCS);
EnterCriticalSection(&g_WSAAsyncCS);
g_WSAAsyncSelectSignal = CreateEvent(NULL, FALSE, FALSE, NULL);
g_bWSAAsyncSelectThreadRunning = FALSE;
g_cWSAAsyncSelectSockets = 0;
} else {
EnterCriticalSection(&g_WSAAsyncCS);
}
bRet = TRUE;
// Init PostMessage function pointer
if (NULL == g_hCoreDll) {
g_hCoreDll = (HINSTANCE )GetModuleHandle(L"coredll");
if (g_hCoreDll) {
g_pfnPostMessageW = (pfnPostMessageW)GetProcAddress(g_hCoreDll, L"PostMessageW");
if (NULL == g_pfnPostMessageW) {
// Window manager APIs not in this config
FreeLibrary(g_hCoreDll);
g_hCoreDll = NULL;
SetLastError(WSASYSNOTREADY);
bRet = FALSE;
}
} else {
// If we can't load coredll, it is likely an out of memory condition
SetLastError(WSAENOBUFS);
bRet = FALSE;
}
}
LeaveCriticalSection(&g_WSAAsyncCS);
return bRet;
} // WS2AsyncInit
DWORD
WS2AsyncResolverThread(
LPVOID lpContext
)
{
WSAREQ *pReq = (WSAREQ *)lpContext;
WSAREQ *pPrev;
WSAREQ *pCurr;
HOSTENT *pHostent;
DWORD lParm = 0;
DWORD dwLen;
DWORD dwStatus;
if (pReq->pName) {
if (pReq->pBuf) {
// gethostbyname request
DEBUGMSG(ZONE_MISC, (L"WS2:WS2AsyncResolverThread: calling gethostbyname(%a)\n", pReq->pName));
if (!(pHostent = gethostbyname(pReq->pName))) {
lParm = GetLastError();
DEBUGMSG(ZONE_MISC, (L"WS2:WS2AsyncResolverThread: gethostbyname(%a) failed %d\n", pReq->pName, lParm));
}
} else {
// getaddrinfo request
char szPort[16];
sprintf(szPort, "%hu", pReq->port);
DEBUGMSG(ZONE_MISC, (L"WS2:WS2AsyncResolverThread: calling getaddrinfo(%a)\n", pReq->pName));
if (getaddrinfo(pReq->pName, szPort, NULL, pReq->ppAI)) {
lParm = GetLastError();
DEBUGMSG(ZONE_MISC, (L"WS2:WS2AsyncResolverThread: getaddrinfo(%a) failed %d\n", pReq->pName, lParm));
}
}
} else {
lParm = WSAEINVAL; // No name specified!
}
EnterCriticalSection(&g_WSAAsyncCS);
// Remove request from list
if (pReq == g_WSAReqList) {
g_WSAReqList = pReq->pNext;
} else {
pPrev = pCurr = g_WSAReqList;
while (pCurr) {
if (pCurr == pReq) {
break;
}
pPrev = pCurr;
pCurr = pCurr->pNext;
}
ASSERT(pCurr == pReq);
pPrev->pNext = pReq->pNext;
}
LeaveCriticalSection(&g_WSAAsyncCS);
if (pReq->Status != SOCKET_ERROR) {
if (lParm) {
lParm <<= 16;
} else {
if (pReq->pBuf) {
// gethostbyname request
dwLen = pReq->dwBufLen;
dwStatus = cpyhent(pReq->pBuf, pHostent, &dwLen);
// cpyhent might fail for lack of buffer space
// but that's not our problem - just forward the condition to
// the async caller
lParm = (dwStatus << 16)|dwLen;
}
}
DEBUGMSG(ZONE_MISC, (L"WS2:WS2AsyncResolverThread: Posting results for %a (%d)\n", pReq->pName, lParm));
g_pfnPostMessageW(pReq->hWnd, pReq->wMsg, (WPARAM)pReq, lParm);
}
if (pReq->pName) {
LocalFree(pReq->pName);
}
LocalFree(pReq);
return 0;
} // WS2AsyncResolverThread
//
// Try to match the specified thread's priority to the current thread's priority
//
void
MatchCurrentThreadPriority(
HANDLE hThd
)
{
switch (CeGetCallerTrust()) {
case OEM_CERTIFY_TRUST:
CeSetThreadPriority(hThd, CeGetThreadPriority(GetCurrentThread()));
break;
case OEM_CERTIFY_RUN:
SetThreadPriority(hThd, GetThreadPriority(GetCurrentThread()));
break;
default:
ASSERT(0);
}
}
//
// Common worker for WSAAsyncGetHostByName and WSAGetAddrInfo
//
HANDLE
WS2StartAsyncRequest(
HWND hWnd,
unsigned int wMsg,
const char * name,
char * buf,
int buflen,
unsigned short port,
ADDRINFO ** ppAI
)
{
HANDLE hThread;
DWORD ThreadId;
WSAREQ *pReq;
DWORD dwLen;
DWORD Status;
if (!WS2AsyncInit()) {
return NULL;
}
Status = WSAENOBUFS;
if (pReq = (WSAREQ *)LocalAlloc(LPTR, sizeof(*pReq))) {
pReq->hWnd = hWnd;
pReq->wMsg = wMsg;
pReq->pBuf = buf;
pReq->dwBufLen = (DWORD)buflen;
pReq->port = port;
pReq->ppAI = ppAI;
dwLen = strlen(name) + 1;
if (pReq->pName = (char *)LocalAlloc(LPTR, dwLen)) {
memcpy(pReq->pName, name, dwLen);
pReq->Status = 0;
EnterCriticalSection(&g_WSAAsyncCS);
hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)WS2AsyncResolverThread,
pReq, CREATE_SUSPENDED, &ThreadId);
if (hThread) {
// put it in list of pending items
pReq->pNext = g_WSAReqList;
g_WSAReqList = pReq;
LeaveCriticalSection(&g_WSAAsyncCS);
DEBUGMSG(ZONE_MISC, (L"WS2:WS2StartAsyncRequest: Started search for %a\n", pReq->pName));
MatchCurrentThreadPriority(hThread);
ResumeThread(hThread);
CloseHandle(hThread);
return (HANDLE)pReq;
} else {
LeaveCriticalSection(&g_WSAAsyncCS);
LocalFree(pReq->pName);
LocalFree(pReq);
}
} else {
LocalFree(pReq);
}
}
DEBUGMSG(ZONE_MISC, (L"WS2:WS2StartAsyncRequest: Starting search for %a failed %d\n", name, Status));
SetLastError(Status);
return NULL;
} // WS2StartAsyncRequest
HANDLE
WSAAsyncGetHostByName(
HWND hWnd,
unsigned int wMsg,
const char * name,
char * buf,
int buflen
)
{
return (HANDLE)WS2StartAsyncRequest(hWnd, wMsg, name, buf, buflen, 0, NULL);
} // WSAAsyncGetHostByName
HANDLE
WSAAsyncGetAddrInfo(
HWND hWnd,
unsigned int uMsg,
const char * name,
unsigned short port,
ADDRINFO ** ppAI
)
{
return (HANDLE)WS2StartAsyncRequest(hWnd, uMsg, name, NULL, 0, port, ppAI);
} // WSAAsyncGetAddrInfo
int
WSACancelAsyncRequest(
HANDLE hAsyncTaskHandle
)
{
WSAREQ *pReq;
int Status;
if (!WS2AsyncInit()) {
return SOCKET_ERROR;
}
EnterCriticalSection(&g_WSAAsyncCS);
pReq = g_WSAReqList;
while (pReq) {
if (pReq == (WSAREQ *)hAsyncTaskHandle) {
break;
}
pReq = pReq->pNext;
}
if (pReq) {
pReq->Status = SOCKET_ERROR;
LeaveCriticalSection(&g_WSAAsyncCS);
Status = 0;
} else {
LeaveCriticalSection(&g_WSAAsyncCS);
Status = SOCKET_ERROR;
SetLastError(WSAEINVAL);
}
return Status;
} // WSACancelAsyncRequest
// cpyhent - copy a hostent structure to a new buffer.
// lpBuf - [out] destination buffer
// lpSrc - [in] source hostent buffer
// lpBufSize - [in/out] comes in with size of lpBuf, goes out with resulting hostent size
//
// here's what we have to copy...
//struct hostent
//{
// char * h_name; /* official name of host */
// char * * h_aliases; /* alias list */
// short h_addrtype; /* host address type */
// short h_length; /* length of address */
// char * * h_addr_list; /* list of addresses */
//};
// Need to dword-align the sub-structures inside the HOSTENT buffer,
// because some processors (actually, most other than x86) don't like
// unaligned pointers.
// I'm not too happy about this - seems we should be able to devise
// syntax that would tell the compiler what we want, without making
// this explicit noise about DWORD alignment.
// (e.g. this code will break on a device that requires QWORD alignment)
// the difficulty is that we're implementing a miniature memory allocator
// inside the HOSTENT buffer, where we carve out chunks of memory and
// advance a byte pointer.
#define DWORDALIGN(i) (((i)+3)&~3)
#define ALNPTR(ptr) ptr=(char*)DWORDALIGN((int)(ptr))
int cpyhent(char * lpDstBuffer, const PHOSTENT lpSrcHostent, int * lpBufSize )
{
int total_size;
PHOSTENT lpDstHostent;
char * lpWritePointer;
int num_aliases;
int num_addrs;
int addr_size;
char ** ptr;
char ** src, **dst;
int i;
total_size = DWORDALIGN(sizeof(HOSTENT));
// first, step through the sources HOSTENT and figure out how big it is
total_size += DWORDALIGN(strlen(lpSrcHostent->h_name) + 1);
// count the number entries in h_aliases
num_aliases = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -