socket.c
来自「WinCE5.0部分核心源码」· C语言 代码 · 共 1,081 行 · 第 1/2 页
C
1,081 行
//
// 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.
//
/*****************************************************************************/
/** Microsoft Windows **/
/*****************************************************************************/
/*
socket.c
FILE HISTORY:
OmarM 14-Sep-2000
*/
#include "winsock2p.h"
#include <cxport.h>
extern void SetErrorCode(int Code, LPINT pErr);
//
// Private constants.
//
//
// Private types.
//
//
// Private globals.
//
//
// Private prototypes.
//
#if defined(WIN32) && !defined(UNDER_CE)
BOOL APIENTRY SetHandleContext(HANDLE s, DWORD context); // in kernel32.dll
#endif
//
// Public functions.
//
WSPUPCALLTABLE UpCalls = {
WPUCloseEvent,
WPUCloseSocketHandle,
WPUCreateEvent,
WPUCreateSocketHandle,
WPUFDIsSet,
WPUGetProviderPath,
WPUModifyIFSHandle,
WPUPostMessage,
WPUQueryBlockingCallback,
WPUQuerySocketHandleContext,
WPUQueueApc,
WPUResetEvent,
WPUSetEvent,
WPUOpenCurrentThread,
WPUCloseThread
};
DEFINE_LOCK_STRUCTURE(s_ProviderListLock);
#define MAX_SOCKETS 256
#define SOCK_HASH_SIZE 64
WsSocket *v_apWsSocks[SOCK_HASH_SIZE];
WsProvider *s_pProviderList;
int v_fClosingAll;
extern int v_fProcessDetached;
extern DWORD s_cDllRefs;
// owner must lock...
SOCKET NewSocketHandle(WsSocket *pNewSock) {
static SOCKET LastUsed;
SOCKET i;
WsSocket *pSock;
unsigned int Max = MAX_SOCKETS;
for (i = 1; i <= Max; i++) {
if (INVALID_SOCKET == LastUsed + i) {
Max++;
continue;
}
pSock = v_apWsSocks[(LastUsed + i) % SOCK_HASH_SIZE];
for (; pSock; pSock = pSock->pNext) {
if (pSock->hSock == (LastUsed + i))
break;
} // for ()
if (!pSock)
break;
}
if (i > Max)
return INVALID_SOCKET;
LastUsed += i;
pNewSock->hSock = LastUsed;
pNewSock->pNext = v_apWsSocks[LastUsed % SOCK_HASH_SIZE];
v_apWsSocks[LastUsed % SOCK_HASH_SIZE] = pNewSock;
return LastUsed;
} // NewSocketHandle()
WsSocket **_FindSocketHandle(SOCKET hSock) {
WsSocket **ppSock;
ppSock = &v_apWsSocks[hSock % SOCK_HASH_SIZE];
while (*ppSock) {
if ((*ppSock)->hSock == hSock)
break;
ppSock = &(*ppSock)->pNext;
}
return ppSock;
} // _FindSocketHandle()
int RefSocketHandle(SOCKET hSock, WsSocket **ppSock) {
WsSocket *pSock;
int Err;
if (! v_fProcessDetached) {
CTEGetLock(&v_DllCS, 0);
if (s_cDllRefs > 0) {
pSock = v_apWsSocks[hSock % SOCK_HASH_SIZE];
while (pSock) {
if (hSock == pSock->hSock)
break;
pSock = pSock->pNext;
}
if (pSock && !(pSock->Flags & WS_SOCK_FL_CLOSED)) {
pSock->cRefs++;
Err = 0;
} else {
Err = WSAENOTSOCK;
}
} else {
Err = WSANOTINITIALISED;
}
CTEFreeLock(&v_DllCS, 0);
if (! Err) {
*ppSock = pSock;
}
} else {
Err = WSAENETDOWN;
}
return Err;
} // RefSocketHandle()
int DerefProvider(GUID *pId, WsProvider *pDelProv);
int DerefSocket(WsSocket *pSock) {
WsSocket **ppSock;
int i;
WsProvider *pProv;
GUID Id;
CTEGetLock(&v_DllCS, 0);
i = --pSock->cRefs;
ASSERT(i >= 0);
if (i <= 0) {
ASSERT(pSock->Flags & WS_SOCK_FL_CLOSED);
ppSock = _FindSocketHandle(pSock->hSock);
if (*ppSock) {
ASSERT(*ppSock == pSock);
*ppSock = pSock->pNext;
}
pProv = pSock->pProvider;
CTEFreeLock(&v_DllCS, 0);
LocalFree(pSock);
if (pProv) {
memcpy(&Id, &pProv->Id, sizeof(Id));
DerefProvider(&Id, pProv);
}
} else
CTEFreeLock(&v_DllCS, 0);
return i;
} // DerefSocket()
int DerefSocketHandle(SOCKET hSock) {
WsSocket *pSock, **ppSock;
int i, fLocked;
WsProvider *pProv;
GUID Id;
CTEGetLock(&v_DllCS, 0);
fLocked = TRUE;
ppSock = _FindSocketHandle(hSock);
if (pSock = *ppSock) {
i = --pSock->cRefs;
ASSERT(i >= 0);
if (i <= 0) {
ASSERT(pSock->Flags & WS_SOCK_FL_CLOSED);
*ppSock = pSock->pNext;
pProv = pSock->pProvider;
LocalFree(pSock);
CTEFreeLock(&v_DllCS, 0);
fLocked = FALSE;
if (pProv) {
memcpy(&Id, &pProv->Id, sizeof(Id));
DerefProvider(&Id, pProv);
}
}
} else {
i = -1;
}
if (fLocked)
CTEFreeLock(&v_DllCS, 0);
return i;
} // DerefSocketHandle()
WsProvider **_FindProvider(GUID *pId) {
WsProvider **ppProv;
for (ppProv = &s_pProviderList; *ppProv; ppProv = &((*ppProv)->pNext))
if (0 == memcmp(&(*ppProv)->Id, pId, sizeof(GUID)))
break;
return ppProv;
}
// is called without the lock held and returns with lock held!
WsProvider *FindProvider(GUID *pId) {
WsProvider *pProv;
CTEGetLock(&s_ProviderListLock, 0);
pProv = *_FindProvider(pId);
return pProv;
} // FindProvider();
void FreeProvider(WsProvider *pProv) {
if (! v_fProcessDetached) {
int Err;
if (SOCKET_ERROR == pProv->ProcTable.lpWSPCleanup(&Err)) {
DEBUGMSG(ZONE_WARN,
(TEXT("FreeProvider: WSPCleanup Err %d\r\n"), Err));
}
if (pProv->hLibrary)
FreeLibrary(pProv->hLibrary);
}
LocalFree(pProv);
} // FreeProvider()
int FreeProviders(uint Flags) {
WsProvider *pProv, **ppProv;
CTEGetLock(&s_ProviderListLock, 0);
ppProv = &s_pProviderList;
while (pProv = *ppProv) {
ASSERT(0 <= pProv->cRefs);
if (0 >= pProv->cRefs) {
*ppProv = pProv->pNext;
FreeProvider(pProv);
} else {
ppProv = &pProv->pNext;
}
}
CTEFreeLock(&s_ProviderListLock, 0);
// ignore errors here, not much we can do at this stage anyway
return 0;
} // FreeProviders()
int DerefProvider(GUID *pId, WsProvider *pProv) {
int Status, fDelete;
WsProvider **ppProv;
CTEGetLock(&v_DllCS, 0);
if (Started() || v_fProcessDetached)
fDelete = TRUE;
else
fDelete = FALSE;
CTEFreeLock(&v_DllCS, 0);
CTEGetLock(&s_ProviderListLock, 0);
if (! pProv || fDelete) {
ppProv = _FindProvider(pId);
pProv = *ppProv;
}
if (pProv) {
Status = TRUE;
pProv->cRefs--;
ASSERT(0 <= pProv->cRefs);
if (fDelete && (0 == pProv->cRefs)) {
*ppProv = pProv->pNext;
FreeProvider(pProv);
}
} else
Status = FALSE;
CTEFreeLock(&s_ProviderListLock, 0);
return Status;
} // DerefProvider();
int GetProvider(int af, int type, int protocol,
LPWSAPROTOCOL_INFOW pOrigProtInfo, LPWSAPROTOCOL_INFOW pProtInfo,
WsProvider **ppProv) {
WsProvider *pProv;
int Err;
LPWSPSTARTUP pfnStartup;
WSPDATA WSPData;
WCHAR sDllPath[MAX_PATH];
int Flags;
DWORD CatEntryId;
WSPUPCALLTABLE UCTbl; // compiler
Err = Flags = 0;
if (pOrigProtInfo) {
Flags |= 1;
__try {
CatEntryId = pOrigProtInfo->dwCatalogEntryId;
memcpy(pProtInfo , pOrigProtInfo, sizeof(*pProtInfo));
}
__except(EXCEPTION_EXECUTE_HANDLER) {
Err = WSAEFAULT;
}
}
if ( (! Err) &&
(! (Err = PMFindProvider(af, type, protocol, CatEntryId, Flags,
pProtInfo, sDllPath)))) {
if (pProv = FindProvider(&pProtInfo->ProviderId)) {
pProv->cRefs++;
} else {
if (pProv = LocalAlloc(LPTR, sizeof(*pProv))) {
pProv->pNext = s_pProviderList;
pProv->cRefs = 1;
pProv->Id = pProtInfo->ProviderId;
if (pProv->hLibrary = LoadLibrary(sDllPath)) {
pfnStartup = (LPWSPSTARTUP)GetProcAddress(pProv->hLibrary,
TEXT("WSPStartup"));
// compiler
memcpy(&UCTbl, &UpCalls, sizeof(WSPUPCALLTABLE));
if (!pfnStartup) {
Err = WSAEPROVIDERFAILEDINIT;
} else if (Err = (*pfnStartup) (WINSOCK_VERSION, &WSPData,
pProtInfo, UCTbl, &pProv->ProcTable)) { // compiler
;
} else if (WSPData.wVersion != WINSOCK_VERSION) {
pProv->ProcTable.lpWSPCleanup(&Err);
ASSERT(0 == Err);
Err = WSAEINVALIDPROVIDER;
} else {
// Partial SUCCESS
s_pProviderList = pProv;
wcscpy(pProv->sDllPath, sDllPath);
}
} else
Err = WSAEPROVIDERFAILEDINIT;
if (Err) {
if (pProv->hLibrary)
CloseHandle(pProv->hLibrary);
LocalFree(pProv);
pProv = NULL;
}
} else
Err = WSAENOBUFS;
} // else (pProv)
CTEFreeLock(&s_ProviderListLock, 0);
}
if (! Err)
*ppProv = pProv;
return Err;
} // GetProvider()
SOCKET WSAAPI WSASocket (
IN int af,
IN int type,
IN int protocol,
IN LPWSAPROTOCOL_INFOW lpProtocolInfo,
IN GROUP g,
IN DWORD dwFlags) {
int cRefs, Err;
DWORD Flags = 0;
WSAPROTOCOL_INFO ProtInfo, *pProtInfo;
WsProvider *pProv;
SOCKET hSock = INVALID_SOCKET;
WsSocket *pSock;
DEBUGMSG(ZONE_FUNCTION || ZONE_SOCKET,
(TEXT("+WS2!WSASocket: %d, %d, %d ProtInfo %X %d %d\r\n"),
af, type, protocol, lpProtocolInfo, g, dwFlags ));
// if (Err = EnterDll()) {
// goto Exit;
// }
if (v_fProcessDetached) {
Err = WSAENETDOWN;
} else {
CTEGetLock(&v_DllCS, 0);
Err = Started();
CTEFreeLock(&v_DllCS, 0);
}
if (Err)
goto Exit;
if (lpProtocolInfo)
pProtInfo = lpProtocolInfo;
else
pProtInfo = &ProtInfo;
if (! (Err = GetProvider(af, type, protocol, lpProtocolInfo,
&ProtInfo, &pProv))) {
// now check the flags...
if ((WSA_FLAG_MULTIPOINT_C_LEAF | WSA_FLAG_MULTIPOINT_C_ROOT)&dwFlags){
if (! (XP1_SUPPORT_MULTIPOINT & ProtInfo.dwServiceFlags1)) {
Err = WSAEINVAL;
} else if ((WSA_FLAG_MULTIPOINT_C_ROOT & dwFlags) &&
((WSA_FLAG_MULTIPOINT_C_LEAF & dwFlags) ||
! (XP1_MULTIPOINT_CONTROL_PLANE & ProtInfo.dwServiceFlags1)))
Err = WSAEINVAL;
if (WSA_FLAG_MULTIPOINT_D_ROOT & dwFlags) {
if (! (XP1_MULTIPOINT_DATA_PLANE & ProtInfo.dwServiceFlags1) ||
(WSA_FLAG_MULTIPOINT_D_LEAF & dwFlags))
Err = WSAEINVAL;
} else if (! (WSA_FLAG_MULTIPOINT_D_LEAF & dwFlags))
Err = WSAEINVAL;
} else if ((WSA_FLAG_MULTIPOINT_D_LEAF | WSA_FLAG_MULTIPOINT_D_ROOT) &
dwFlags) {
Err = WSAEINVAL;
}
// ok this means that the provider is up...
if ( (! Err) && (pSock = LocalAlloc(LPTR, sizeof(*pSock)))) {
pSock->cRefs = 1;
CTEGetLock(&v_DllCS, 0);
hSock = NewSocketHandle(pSock);
CTEFreeLock(&v_DllCS, 0);
if (INVALID_SOCKET != hSock) {
pSock->hWSPSock = pProv->ProcTable.lpWSPSocket(af, type,
protocol, pProtInfo, g, dwFlags, &Err);
if (INVALID_SOCKET != pSock->hWSPSock) {
pSock->pProvider = pProv;
// should we copy from ProtInfo or pProtInfo?
memcpy(&pSock->ProtInfo, &ProtInfo, sizeof(ProtInfo));
// SUCCESS !!!
} else {
// oh oh, close and delete everything
pSock->Flags |= WS_SOCK_FL_CLOSED;
cRefs = DerefSocketHandle(pSock->hSock);
hSock = INVALID_SOCKET;
ASSERT(cRefs == 0);
}
} else { // if (INVALID_SOCKET != hSock)
LocalFree(pSock);
DerefProvider(&pProtInfo->ProviderId, pProv);
Err = WSAEMFILE;
}
} else { // if (! Err && pSock = LocalAlloc...)
DerefProvider(&pProtInfo->ProviderId, pProv);
if (! Err)
Err = WSAENOBUFS;
}
} // if (! (Err = GetProvider(...)))
Exit:
if (Err) {
ASSERT(INVALID_SOCKET == hSock);
SetLastError(Err);
}
DEBUGMSG(ZONE_FUNCTION || ZONE_SOCKET,
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?