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

📄 wsahwnd.c

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