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 + -
显示快捷键?