📄 wsahwnd.c
字号:
for (ptr = lpSrcHostent->h_aliases; ptr && *ptr != NULL; ptr++) {
total_size += DWORDALIGN(strlen(*ptr) + 1);
num_aliases ++;
}
total_size += DWORDALIGN((num_aliases + 1) * sizeof(char *));
// count the number of entries in h_addr_list
num_addrs = 0;
for (ptr = lpSrcHostent->h_addr_list; *ptr != NULL; ptr++) {
num_addrs ++;
}
// each addr occupies (sizeof(char*) + h_length) bytes
total_size += DWORDALIGN(num_addrs * (sizeof(char*) + lpSrcHostent->h_length));
// now, check to see that there's enough room in the destination buffer
if (total_size > *lpBufSize) {
*lpBufSize = total_size; // inform async caller how big the buffer should be.
return WSAENOBUFS;
}
// now we can actually start copying stuff, safe in the knowledge it will all fit
// the lpWritePointer pointer tracks the current write position in the destination buffer
lpWritePointer = lpDstBuffer;
lpDstHostent = (PHOSTENT) lpDstBuffer;
// copy the absolute data first, then the strings
lpDstHostent->h_length = lpSrcHostent->h_length;
lpDstHostent->h_addrtype = lpSrcHostent->h_addrtype;
// account for the HOSTENT structure itself
lpWritePointer += sizeof(HOSTENT);
ALNPTR(lpWritePointer);
lpDstHostent->h_name = lpWritePointer;
lpWritePointer +=strlen(lpSrcHostent->h_name) + 1;
ALNPTR(lpWritePointer);
ASSERT(lpWritePointer - lpDstBuffer <= *lpBufSize);
// copy the host name
strcpy(lpDstHostent->h_name, lpSrcHostent->h_name);
// copy the aliases table
if (lpSrcHostent->h_aliases)
{
lpDstHostent->h_aliases = (char **) lpWritePointer;
lpWritePointer += (num_aliases+1) * sizeof(char*);
ALNPTR(lpWritePointer);
src = lpSrcHostent->h_aliases;
dst = lpDstHostent->h_aliases;
for (i = 0; i < num_aliases; i++) {
*dst = lpWritePointer;
lpWritePointer += strlen(*src) + 1;
ALNPTR(lpWritePointer);
ASSERT(lpWritePointer - lpDstBuffer <= *lpBufSize);
strcpy(*dst, *src);
dst++;
src++;
}
// null-terminate the aliases table
*dst = NULL;
ASSERT(*src == NULL);
// copy the address table
}
else
{
lpDstHostent->h_aliases = NULL;
}
// now copy the address table
lpDstHostent->h_addr_list = (char **) lpWritePointer;
lpWritePointer += (num_addrs+1) * sizeof(char*);
ALNPTR(lpWritePointer);
ASSERT(lpWritePointer - lpDstBuffer <= *lpBufSize);
src = lpSrcHostent->h_addr_list;
dst = lpDstHostent->h_addr_list;
addr_size = lpSrcHostent->h_length;
for (i = 0; i < num_addrs; i++) {
*dst = lpWritePointer;
lpWritePointer += addr_size;
ALNPTR(lpWritePointer);
ASSERT(lpWritePointer - lpDstBuffer <= *lpBufSize);
memcpy(*dst, *src, addr_size);
dst++;
src++;
}
*dst = NULL;
ASSERT(*src == NULL);
return ERROR_SUCCESS;
} // cpyhent
//
// WSAAsyncSelect based on WSAEventSelect and WSAEnumNetworkEvents
//
//
// WS2FindWsaAsyncSocket: Find async socket structure based on either the associated
// socket handle or event handle
//
// Note: call with g_WSAAsyncCS taken
//
PWSAASYNC_SOCKET
WS2FindWsaAsyncSocket(
SOCKET s,
WSAEVENT e
)
{
PWSAASYNC_SOCKET pwsa;
for (pwsa = g_WSAAsyncSelectList; pwsa; pwsa = pwsa->ws_next) {
if (s) {
if (pwsa->ws_socket == s) {
return pwsa;
}
}
if (e) {
if (pwsa->ws_hevent == e) {
return pwsa;
}
}
}
return NULL;
} // WS2FindWsaAsyncSocket
// Note: call with g_WSAAsyncCS taken
void
WS2DeleteWsaAsyncSocket(
PWSAASYNC_SOCKET pwsa
)
{
PWSAASYNC_SOCKET pcur, pprev;
for (pcur = pprev = g_WSAAsyncSelectList; pcur;) {
if (pcur == pwsa) {
if (pcur == g_WSAAsyncSelectList) {
g_WSAAsyncSelectList = pcur->ws_next;
} else {
pprev->ws_next = pcur->ws_next;
}
break;
}
pprev = pcur;
pcur = pcur->ws_next;
}
if (pcur == pwsa) {
g_cWSAAsyncSelectSockets--;
WSAEventSelect(pwsa->ws_socket, pwsa->ws_hevent, 0); // Cancel notifications
CloseHandle(pwsa->ws_hevent);
LocalFree(pwsa);
}
} // WS2DeleteWsaAsyncSocket
DWORD WS2AsyncSelectThread(LPVOID Nothing);
// Note: call with g_WSAAsyncCS taken
PWSAASYNC_SOCKET
WS2CreateWsaAsyncSocket(
SOCKET s,
long lEvents
)
{
PWSAASYNC_SOCKET pwsa;
HANDLE hThd;
// Start thread if needed
if (FALSE == g_bWSAAsyncSelectThreadRunning) {
g_bWSAAsyncSelectThreadRunning = TRUE;
hThd = CreateThread(NULL, 0, WS2AsyncSelectThread, NULL, 0, NULL);
if (hThd) {
MatchCurrentThreadPriority(hThd);
CloseHandle(hThd);
} else {
g_bWSAAsyncSelectThreadRunning = FALSE;
return NULL;
}
}
if ((MAXIMUM_WAIT_OBJECTS-2) < g_cWSAAsyncSelectSockets) {
return NULL;
}
if (pwsa = LocalAlloc(0, sizeof(WSAASYNC_SOCKET))) {
if (WSA_INVALID_EVENT != (pwsa->ws_hevent = WSACreateEvent())) {
if (0 == WSAEventSelect(s, pwsa->ws_hevent, lEvents)) {
g_cWSAAsyncSelectSockets++;
return pwsa;
} else {
CloseHandle(pwsa->ws_hevent);
}
}
LocalFree(pwsa);
}
return NULL;
} // WS2CreateWsaAsyncSocket
//
// Process signalled network events by posting windows messages as appropriate
//
void
WS2ProcessWsaAsyncSocket(
WSAEVENT hEvent
)
{
PWSAASYNC_SOCKET pwsa;
WSANETWORKEVENTS NetworkEvents;
long EventMask;
DWORD lParam;
int i;
if (NULL == (pwsa = WS2FindWsaAsyncSocket(0, hEvent))) {
//
// The socket must have been closed and had WSAAsyncSelect(s,0,0,0) called
// on it before this thread could process any of its events.
//
return;
}
if (SOCKET_ERROR == WSAEnumNetworkEvents(pwsa->ws_socket, pwsa->ws_hevent, &NetworkEvents)) {
WS2DeleteWsaAsyncSocket(pwsa);
return;
}
for (i = 0, EventMask = FD_READ; i < FD_MAX_EVENTS; i++, EventMask <<= 1) {
if (EventMask & NetworkEvents.lNetworkEvents & pwsa->ws_levents) {
lParam = WSAMAKESELECTREPLY(EventMask, NetworkEvents.iErrorCode[i]);
g_pfnPostMessageW(pwsa->ws_hwnd, pwsa->ws_wmsg, pwsa->ws_socket, lParam);
}
}
if (FD_CLOSE & NetworkEvents.lNetworkEvents) {
WS2DeleteWsaAsyncSocket(pwsa);
}
} // WS2ProcessWsaAsyncSocket
DWORD
WS2AsyncSelectThread(
LPVOID Nothing
)
{
int cAlloc, cCurr;
DWORD ret;
HANDLE * pList, * pHnd;
PWSAASYNC_SOCKET pwsa;
pList = NULL;
cAlloc = 0;
EnterCriticalSection(&g_WSAAsyncCS);
while (1) {
//
// Count async sockets and allocate handle array if needed (include 1 extra for signal)
//
for (cCurr = 1, pwsa = g_WSAAsyncSelectList; pwsa; pwsa = pwsa->ws_next) {
cCurr++;
}
if (1 == cCurr) {
// No sockets to process
goto wast_exit;
}
if (cCurr > cAlloc) {
cAlloc = cCurr;
if (pList) {
LocalFree(pList);
}
pList = LocalAlloc(0, sizeof(pList) * cCurr);
ASSERT(pList);
if (NULL == pList) {
goto wast_exit;
}
}
pHnd = pList;
*pHnd = g_WSAAsyncSelectSignal; // Signal event is first in the list
pHnd++;
//
// Build array of event handles
//
for (pwsa = g_WSAAsyncSelectList; pwsa; pHnd++, pwsa = pwsa->ws_next) {
*pHnd = pwsa->ws_hevent;
}
LeaveCriticalSection(&g_WSAAsyncCS);
ret = WaitForMultipleObjects(cCurr, pList, FALSE, INFINITE);
EnterCriticalSection(&g_WSAAsyncCS);
if (WAIT_OBJECT_0 == ret) {
// We got signalled by WSAAsyncSelect. Continuing will cause rebuild of event array
continue;
} else {
if (ret < (DWORD)cCurr) {
WS2ProcessWsaAsyncSocket(pList[ret]);
} else {
DEBUGMSG(1, (L"WS2AsyncSelectThread - WaitForMultipleObjects returned %d, error %d\n",
ret, GetLastError()));
goto wast_exit;
}
}
}
wast_exit:
if (pList) {
LocalFree(pList);
}
g_bWSAAsyncSelectThreadRunning = FALSE;
LeaveCriticalSection(&g_WSAAsyncCS);
return 0;
} // WS2AsyncSelectThread
//
// Enable/disable notification of networks events via windows messages
//
int
WSAAPI
WSAAsyncSelect(
IN SOCKET s,
IN HWND hWnd,
IN u_int wMsg,
IN long lEvent
)
{
PWSAASYNC_SOCKET pwsa;
int ret;
DWORD dwLastError = 0;
if (!WS2AsyncInit()) {
return SOCKET_ERROR;
}
EnterCriticalSection(&g_WSAAsyncCS);
pwsa = WS2FindWsaAsyncSocket(s, NULL);
if (0 == lEvent) {
// Remove socket from async system
if (pwsa) {
WS2DeleteWsaAsyncSocket(pwsa);
} else {
dwLastError = WSAEINVAL;
}
goto was_exit;
}
if (NULL == pwsa) {
if (pwsa = WS2CreateWsaAsyncSocket(s, lEvent)) {
//
// set socket to non-blocking
//
ret = 1;
if (SOCKET_ERROR == ioctlsocket(s, FIONBIO, &ret)) {
// failed to set non-blocking
WS2DeleteWsaAsyncSocket(pwsa);
dwLastError = WSAENOBUFS;
goto was_exit;
}
pwsa->ws_socket = s;
pwsa->ws_next = g_WSAAsyncSelectList;
g_WSAAsyncSelectList = pwsa;
} else {
dwLastError = WSAENOBUFS;
goto was_exit;
}
}
pwsa->ws_hwnd = hWnd;
pwsa->ws_wmsg = wMsg;
pwsa->ws_levents = lEvent;
was_exit:
if (dwLastError) {
SetLastError(dwLastError);
ret = SOCKET_ERROR;
} else {
SetEvent(g_WSAAsyncSelectSignal);
ret = 0;
}
LeaveCriticalSection(&g_WSAAsyncCS);
return ret;
} // WSAAsyncSelect
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -