⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wsahwnd.c

📁 WinCE5.0部分核心源码
💻 C
📖 第 1 页 / 共 2 页
字号:
    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 + -