PCATALOG_ENTRY LocateProviderById(DWORD CatalogEntryId) { PLIST_ENTRY CurrentEntry; PCATALOG_ENTRY Provider; WS_DbgPrint(MAX_TRACE, ("CatalogEntryId (%d).\n", CatalogEntryId)); //EnterCriticalSection(&CatalogLock); CurrentEntry = CatalogListHead.Flink; while (CurrentEntry != &CatalogListHead) { Provider = CONTAINING_RECORD(CurrentEntry, CATALOG_ENTRY, ListEntry); if (Provider->ProtocolInfo.dwCatalogEntryId == CatalogEntryId) { //LeaveCriticalSection(&CatalogLock); WS_DbgPrint(MID_TRACE, ("Returning provider at (0x%X) Name (%wZ).\n", Provider, &Provider->LibraryName)); return Provider; } CurrentEntry = CurrentEntry->Flink; } //LeaveCriticalSection(&CatalogLock); WS_DbgPrint(MID_TRACE, ("Provider was not found.\n")); return NULL; }
VOID DereferenceProviderByPointer(PCATALOG_ENTRY Provider) { WS_DbgPrint(MAX_TRACE, ("Provider (0x%X).\n", Provider)); #if DBG if (Provider->ReferenceCount <= 0) { WS_DbgPrint(MIN_TRACE, ("Provider at 0x%X has invalid reference count (%ld).\n", Provider, Provider->ReferenceCount)); } #endif //EnterCriticalSection(&Provider->Lock); Provider->ReferenceCount--; //LeaveCriticalSection(&Provider->Lock); if (Provider->ReferenceCount == 0) { WS_DbgPrint(MAX_TRACE, ("Provider at 0x%X has reference count 0 (unloading).\n", Provider)); DestroyCatalogEntry(Provider); } }
INT UnloadProvider(PCATALOG_ENTRY Provider) { INT Status = NO_ERROR; WS_DbgPrint(MAX_TRACE, ("Unloading provider at (0x%X)\n", Provider)); if (NULL != Provider->hModule) { WS_DbgPrint(MAX_TRACE, ("Calling WSPCleanup at (0x%X).\n", Provider->ProcTable.lpWSPCleanup)); Provider->ProcTable.lpWSPCleanup(&Status); WS_DbgPrint(MAX_TRACE, ("Calling FreeLibrary(0x%X).\n", Provider->hModule)); if (!FreeLibrary(Provider->hModule)) { WS_DbgPrint(MIN_TRACE, ("Could not free library at (0x%X).\n", Provider->hModule)); Status = GetLastError(); } Provider->hModule = NULL; } WS_DbgPrint(MAX_TRACE, ("Status (%d).\n", Status)); return Status; }
BOOL ReferenceProviderByHandle(HANDLE Handle, PCATALOG_ENTRY* Provider) /* * FUNCTION: Increments the reference count for a provider and returns a pointer to it * ARGUMENTS: * Handle = Handle for the provider * Provider = Address of buffer to place pointer to provider * RETURNS: * TRUE if handle was valid, FALSE if not */ { PPROVIDER_HANDLE ProviderHandle; WS_DbgPrint(MID_TRACE, ("Handle (0x%X) Provider (0x%X).\n", Handle, Provider)); EnterCriticalSection(&ProviderHandleTableLock); ProviderHandle = GetProviderByHandle(ProviderHandleTable, Handle); WS_DbgPrint(MID_TRACE, ("ProviderHandle is %x\n", ProviderHandle)); LeaveCriticalSection(&ProviderHandleTableLock); if (ProviderHandle) { ReferenceProviderByPointer(ProviderHandle->Provider); *Provider = ProviderHandle->Provider; } return (ProviderHandle != NULL); }
/* * @implemented */ SOCKET EXPORT WSAAccept(IN SOCKET s, OUT LPSOCKADDR addr, IN OUT LPINT addrlen, IN LPCONDITIONPROC lpfnCondition, IN DWORD_PTR dwCallbackData) { PCATALOG_ENTRY Provider; SOCKET Socket; INT Errno; if (!WSAINITIALIZED) { WSASetLastError(WSANOTINITIALISED); return SOCKET_ERROR; } if (!ReferenceProviderByHandle((HANDLE)s, &Provider)) { WSASetLastError(WSAENOTSOCK); return SOCKET_ERROR; } WS_DbgPrint(MAX_TRACE,("Calling provider accept\n")); Socket = Provider->ProcTable.lpWSPAccept(s, addr, addrlen, lpfnCondition, dwCallbackData, &Errno); WS_DbgPrint(MAX_TRACE,("Calling provider accept -> Socket %x, Errno %x\n", Socket, Errno)); DereferenceProviderByPointer(Provider); if (Socket == INVALID_SOCKET) WSASetLastError(Errno); if ( addr && addrlen ) { #if DBG LPSOCKADDR_IN sa = (LPSOCKADDR_IN)addr; WS_DbgPrint(MAX_TRACE,("Returned address: %d %s:%d (len %d)\n", sa->sin_family, inet_ntoa(sa->sin_addr), ntohs(sa->sin_port), *addrlen)); #endif } return Socket; }
VOID ReferenceProviderByPointer(PCATALOG_ENTRY Provider) { WS_DbgPrint(MAX_TRACE, ("Provider (0x%X).\n", Provider)); //EnterCriticalSection(&Provider->Lock); Provider->ReferenceCount++; //LeaveCriticalSection(&Provider->Lock); WS_DbgPrint(MAX_TRACE, ("Leaving\n")); }
HANDLE CreateProviderHandleTable(PPROVIDER_HANDLE_BLOCK HandleTable, HANDLE Handle, PCATALOG_ENTRY Provider) { PPROVIDER_HANDLE_BLOCK NewBlock; PLIST_ENTRY CurrentEntry; ULONG i; WS_DbgPrint(MAX_TRACE, ("HandleTable (0x%X) Handle (0x%X) Provider (0x%X).\n", HandleTable, Handle, Provider)); /* Scan through the currently allocated handle blocks looking for a free slot */ CurrentEntry = HandleTable->Entry.Flink; while (CurrentEntry != &HandleTable->Entry) { PPROVIDER_HANDLE_BLOCK Block = CONTAINING_RECORD(CurrentEntry, PROVIDER_HANDLE_BLOCK, Entry); for (i = 0; i < HANDLE_BLOCK_ENTRIES; i++) { WS_DbgPrint(MAX_TRACE, ("Considering slot %ld containing 0x%X.\n", i, Block->Handles[i].Provider)); if (Block->Handles[i].Provider == NULL) { Block->Handles[i].Handle = Handle; Block->Handles[i].Provider = Provider; return Handle; } } CurrentEntry = CurrentEntry->Flink; } /* Add a new handle block to the end of the list */ NewBlock = (PPROVIDER_HANDLE_BLOCK)HeapAlloc(GlobalHeap, 0, sizeof(PROVIDER_HANDLE_BLOCK)); WS_DbgPrint(MID_TRACE,("using table entry %x\n", NewBlock)); if (!NewBlock) return (HANDLE)0; ZeroMemory(NewBlock, sizeof(PROVIDER_HANDLE_BLOCK)); InsertTailList(&HandleTable->Entry, &NewBlock->Entry); NewBlock->Handles[0].Handle = Handle; NewBlock->Handles[0].Provider = Provider; return Handle; }
/* * @implemented */ INT EXPORT WSAEnumNetworkEvents(IN SOCKET s, IN WSAEVENT hEventObject, OUT LPWSANETWORKEVENTS lpNetworkEvents) { PCATALOG_ENTRY Provider; INT Status; INT Errno; WS_DbgPrint(MID_TRACE,("Called (Socket %x, hEventObject %x, " "lpNetworkEvents %x)\n", s, hEventObject, lpNetworkEvents)); if (!lpNetworkEvents) { WSASetLastError(WSAEINVAL); return SOCKET_ERROR; } if (!WSAINITIALIZED) { WSASetLastError(WSANOTINITIALISED); return SOCKET_ERROR; } if (!ReferenceProviderByHandle((HANDLE)s, &Provider)) { WSASetLastError(WSAENOTSOCK); return SOCKET_ERROR; } Status = Provider->ProcTable.lpWSPEnumNetworkEvents(s, hEventObject, lpNetworkEvents, &Errno); DereferenceProviderByPointer(Provider); if (Status == SOCKET_ERROR) WSASetLastError(Errno); WS_DbgPrint(MID_TRACE,("Leaving %x\n", Status)); return Status; }
/* * @implemented */ INT EXPORT closesocket(IN SOCKET s) /* * FUNCTION: Closes a socket descriptor * ARGUMENTS: * s = Socket descriptor * RETURNS: * 0, or SOCKET_ERROR if an error ocurred */ { PCATALOG_ENTRY Provider; INT Status; INT Errno; WS_DbgPrint(MAX_TRACE, ("s (0x%X).\n", s)); if (!WSAINITIALIZED) { WSASetLastError(WSANOTINITIALISED); return SOCKET_ERROR; } if (!ReferenceProviderByHandle((HANDLE)s, &Provider)) { WSASetLastError(WSAENOTSOCK); return SOCKET_ERROR; } CloseProviderHandle((HANDLE)s); WS_DbgPrint(MAX_TRACE,("DereferenceProviderByHandle\n")); DereferenceProviderByPointer(Provider); WS_DbgPrint(MAX_TRACE,("DereferenceProviderByHandle Done\n")); Status = Provider->ProcTable.lpWSPCloseSocket(s, &Errno); WS_DbgPrint(MAX_TRACE,("Provider Close Done\n")); if (Status == SOCKET_ERROR) WSASetLastError(Errno); WS_DbgPrint(MAX_TRACE,("Returning success\n")); return 0; }
VOID CloseAllHandles(PPROVIDER_HANDLE_BLOCK HandleTable) { PPROVIDER_HANDLE_BLOCK Current; PLIST_ENTRY CurrentEntry; PCATALOG_ENTRY Provider; ULONG i; WS_DbgPrint(MAX_TRACE, ("HandleTable (0x%X).\n", HandleTable)); CurrentEntry = HandleTable->Entry.Flink; while (CurrentEntry != &HandleTable->Entry) { Current = CONTAINING_RECORD(CurrentEntry, PROVIDER_HANDLE_BLOCK, Entry); for (i = 0; i < HANDLE_BLOCK_ENTRIES; i++) { Provider = Current->Handles[i].Provider; if (Provider != NULL) { DereferenceProviderByPointer(Provider); Current->Handles[i].Handle = (HANDLE)0; Current->Handles[i].Provider = NULL; } } CurrentEntry = CurrentEntry->Flink; } }
VOID CreateCatalog(VOID) { PCATALOG_ENTRY Provider; InitializeCriticalSection(&CatalogLock); InitializeListHead(&CatalogListHead); /* FIXME: Read service provider catalog from registry Catalog info is saved somewhere under HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\WinSock2 */ #if 1 Provider = CreateCatalogEntry(L"msafd.dll"); if (!Provider) { WS_DbgPrint(MIN_TRACE, ("Could not create catalog entry.\n")); return; } /* Assume one Service Provider with id 1 */ Provider->ProtocolInfo.dwCatalogEntryId = 1; Provider->Mapping = HeapAlloc(GlobalHeap, 0, 6 * sizeof(WINSOCK_MAPPING) + 3 * sizeof(DWORD)); if (!Provider->Mapping) return; Provider->Mapping->Rows = 6; Provider->Mapping->Columns = 3; Provider->Mapping->Mapping[0].AddressFamily = AF_INET; Provider->Mapping->Mapping[0].SocketType = SOCK_STREAM; Provider->Mapping->Mapping[0].Protocol = 0; Provider->Mapping->Mapping[1].AddressFamily = AF_INET; Provider->Mapping->Mapping[1].SocketType = SOCK_STREAM; Provider->Mapping->Mapping[1].Protocol = IPPROTO_TCP; Provider->Mapping->Mapping[2].AddressFamily = AF_INET; Provider->Mapping->Mapping[2].SocketType = SOCK_DGRAM; Provider->Mapping->Mapping[2].Protocol = 0; Provider->Mapping->Mapping[3].AddressFamily = AF_INET; Provider->Mapping->Mapping[3].SocketType = SOCK_DGRAM; Provider->Mapping->Mapping[3].Protocol = IPPROTO_UDP; Provider->Mapping->Mapping[4].AddressFamily = AF_INET; Provider->Mapping->Mapping[4].SocketType = SOCK_RAW; Provider->Mapping->Mapping[4].Protocol = IPPROTO_ICMP; Provider->Mapping->Mapping[5].AddressFamily = AF_INET; Provider->Mapping->Mapping[5].SocketType = SOCK_RAW; Provider->Mapping->Mapping[5].Protocol = 0; #endif }
PCATALOG_ENTRY CreateCatalogEntry(LPWSTR LibraryName) { PCATALOG_ENTRY Provider; WS_DbgPrint(MAX_TRACE, ("LibraryName (%S).\n", LibraryName)); Provider = HeapAlloc(GlobalHeap, 0, sizeof(CATALOG_ENTRY)); if (!Provider) return NULL; ZeroMemory(Provider, sizeof(CATALOG_ENTRY)); if (!RtlCreateUnicodeString(&Provider->LibraryName, LibraryName)) { RtlFreeHeap(GlobalHeap, 0, Provider); return NULL; } Provider->ReferenceCount = 1; InitializeCriticalSection(&Provider->Lock); Provider->hModule = NULL; Provider->Mapping = NULL; //EnterCriticalSection(&CatalogLock); InsertTailList(&CatalogListHead, &Provider->ListEntry); //LeaveCriticalSection(&CatalogLock); return Provider; }
INT DestroyCatalogEntry(PCATALOG_ENTRY Provider) { INT Status; WS_DbgPrint(MAX_TRACE, ("Provider (0x%X).\n", Provider)); //EnterCriticalSection(&CatalogLock); RemoveEntryList(&Provider->ListEntry); //LeaveCriticalSection(&CatalogLock); HeapFree(GlobalHeap, 0, Provider->Mapping); if (NULL != Provider->hModule) { Status = UnloadProvider(Provider); } else { Status = NO_ERROR; } //DeleteCriticalSection(&Provider->Lock); HeapFree(GlobalHeap, 0, Provider); return Status; }
INT LoadProvider(PCATALOG_ENTRY Provider, LPWSAPROTOCOL_INFOW lpProtocolInfo) { INT Status; WS_DbgPrint(MID_TRACE, ("Loading provider at (0x%X) Name (%wZ).\n", Provider, &Provider->LibraryName)); if (NULL == Provider->hModule) { /* DLL is not loaded so load it now * UNICODE_STRING objects are not null-terminated, but LoadLibraryW * expects a null-terminated string */ Provider->LibraryName.Buffer[Provider->LibraryName.Length / sizeof(WCHAR)] = L'\0'; Provider->hModule = LoadLibraryW(Provider->LibraryName.Buffer); if (NULL != Provider->hModule) { Provider->WSPStartup = (LPWSPSTARTUP)GetProcAddress(Provider->hModule, "WSPStartup"); if (Provider->WSPStartup) { WS_DbgPrint(MAX_TRACE, ("Calling WSPStartup at (0x%X).\n", Provider->WSPStartup)); Status = Provider->WSPStartup(MAKEWORD(2, 2), &Provider->WSPData, lpProtocolInfo, UpcallTable, &Provider->ProcTable); /* FIXME: Validate the procedure table */ } else Status = ERROR_BAD_PROVIDER; } else Status = ERROR_DLL_NOT_FOUND; } else Status = NO_ERROR; WS_DbgPrint(MID_TRACE, ("Status (%d).\n", Status)); return Status; }
PCATALOG_ENTRY LocateProvider(LPWSAPROTOCOL_INFOW lpProtocolInfo) { PLIST_ENTRY CurrentEntry; PCATALOG_ENTRY Provider; UINT i; WS_DbgPrint(MAX_TRACE, ("lpProtocolInfo (0x%X).\n", lpProtocolInfo)); //EnterCriticalSection(&CatalogLock); CurrentEntry = CatalogListHead.Flink; while (CurrentEntry != &CatalogListHead) { Provider = CONTAINING_RECORD(CurrentEntry, CATALOG_ENTRY, ListEntry); for (i = 0; i < Provider->Mapping->Rows; i++) { if ((lpProtocolInfo->iAddressFamily == (INT) Provider->Mapping->Mapping[i].AddressFamily) && (lpProtocolInfo->iSocketType == (INT) Provider->Mapping->Mapping[i].SocketType) && ((lpProtocolInfo->iProtocol == (INT) Provider->Mapping->Mapping[i].Protocol) || (lpProtocolInfo->iSocketType == SOCK_RAW))) { //LeaveCriticalSection(&CatalogLock); lpProtocolInfo->dwCatalogEntryId = Provider->ProtocolInfo.dwCatalogEntryId; WS_DbgPrint(MID_TRACE, ("Returning provider at (0x%X).\n", Provider)); return Provider; } } CurrentEntry = CurrentEntry->Flink; } //LeaveCriticalSection(&CatalogLock); return NULL; }
/* * @implemented */ INT EXPORT WSACleanup(VOID) { WS_DbgPrint(MAX_TRACE, ("WSACleanup of ws2_32.dll\n")); if (!WSAINITIALIZED) { WSASetLastError(WSANOTINITIALISED); return WSANOTINITIALISED; } return NO_ERROR; }
PCATALOG_ENTRY DeleteProviderHandle(PPROVIDER_HANDLE_BLOCK HandleTable, HANDLE Handle) { PPROVIDER_HANDLE Entry; PCATALOG_ENTRY Provider; WS_DbgPrint(MAX_TRACE, ("HandleTable (0x%X) Handle (0x%X).\n", HandleTable, Handle)); Entry = GetProviderByHandle(HandleTable, Handle); if (!Entry) return NULL; Provider = Entry->Provider; Entry->Handle = (HANDLE)0; Entry->Provider = NULL; return Provider; }
/* * @implemented */ SOCKET EXPORT WSASocketA(IN INT af, IN INT type, IN INT protocol, IN LPWSAPROTOCOL_INFOA lpProtocolInfo, IN GROUP g, IN DWORD dwFlags) /* * FUNCTION: Creates a new socket */ { WSAPROTOCOL_INFOW ProtocolInfoW; LPWSAPROTOCOL_INFOW p; UNICODE_STRING StringU; ANSI_STRING StringA; WS_DbgPrint(MAX_TRACE, ("af (%d) type (%d) protocol (%d).\n", af, type, protocol)); if (lpProtocolInfo) { memcpy(&ProtocolInfoW, lpProtocolInfo, sizeof(WSAPROTOCOL_INFOA) - sizeof(CHAR) * (WSAPROTOCOL_LEN + 1)); RtlInitAnsiString(&StringA, (LPSTR)lpProtocolInfo->szProtocol); RtlInitUnicodeString(&StringU, (LPWSTR)&ProtocolInfoW.szProtocol); RtlAnsiStringToUnicodeString(&StringU, &StringA, FALSE); p = &ProtocolInfoW; } else { p = NULL; } return WSASocketW(af, type, protocol, p, g, dwFlags); }
BOOL CloseProviderHandle(HANDLE Handle) { PCATALOG_ENTRY Provider; WS_DbgPrint(MAX_TRACE, ("Handle (0x%X).\n", Handle)); EnterCriticalSection(&ProviderHandleTableLock); Provider = DeleteProviderHandle(ProviderHandleTable, Handle); LeaveCriticalSection(&ProviderHandleTableLock); if (!Provider) return FALSE; DereferenceProviderByPointer(Provider); return TRUE; }
BOOL InitProviderHandleTable(VOID) { ProviderHandleTable = (PPROVIDER_HANDLE_BLOCK)HeapAlloc(GlobalHeap, 0, sizeof(PROVIDER_HANDLE_BLOCK)); if (!ProviderHandleTable) return FALSE; WS_DbgPrint(MID_TRACE,("Called\n")); ZeroMemory(ProviderHandleTable, sizeof(PROVIDER_HANDLE_BLOCK)); InitializeListHead(&ProviderHandleTable->Entry); InitializeCriticalSection(&ProviderHandleTableLock); return TRUE; }
PPROVIDER_HANDLE GetProviderByHandle(PPROVIDER_HANDLE_BLOCK HandleTable, HANDLE Handle) /* * FUNCTION: Get the data structure for a handle * ARGUMENTS: * HandleTable = Pointer to handle table * Handle = Handle to get data structure for * RETURNS: * Pointer to the data structure identified by the handle on success, * NULL on failure */ { PPROVIDER_HANDLE_BLOCK Current; PLIST_ENTRY CurrentEntry; ULONG i; WS_DbgPrint(MAX_TRACE, ("HandleTable (0x%X) Handle (0x%X).\n", HandleTable, Handle)); CurrentEntry = HandleTable->Entry.Flink; while (CurrentEntry != &HandleTable->Entry) { Current = CONTAINING_RECORD(CurrentEntry, PROVIDER_HANDLE_BLOCK, Entry); for (i = 0; i < HANDLE_BLOCK_ENTRIES; i++) { if ((Current->Handles[i].Provider != NULL) && (Current->Handles[i].Handle == Handle)) { return &Current->Handles[i]; } } CurrentEntry = CurrentEntry->Flink; } return NULL; }
/* * @implemented */ INT EXPORT WSAStartup(IN WORD wVersionRequested, OUT LPWSADATA lpWSAData) { WORD VersionReturned = 0; DWORD ErrorCode = ERROR_SUCCESS; WS_DbgPrint(MAX_TRACE, ("WSAStartup of ws2_32.dll\n")); if (!g_hInstDll) return WSASYSNOTREADY; if (lpWSAData == NULL) return WSAEFAULT; /* Check which version is being requested */ switch (LOBYTE(wVersionRequested)) { case 0: /* We don't support this unknown version */ ErrorCode = WSAVERNOTSUPPORTED; break; case 1: /* We support only 1.0 and 1.1 */ if (HIBYTE(wVersionRequested) == 0) { /* Caller wants 1.0, return it */ VersionReturned = wVersionRequested; } else { /* The only other version we support is 1.1 */ VersionReturned = MAKEWORD(1, 1); } break; case 2: /* We support only 2.0, 2.1 and 2.2 */ if (HIBYTE(wVersionRequested) <= 2) { /* Caller wants 2.0-2.2, return it */ VersionReturned = MAKEWORD(2, HIBYTE(wVersionRequested)); } else { /* The highest version we support is 2.2 */ VersionReturned = MAKEWORD(2, 2); } break; default: /* Return 2.2 */ VersionReturned = MAKEWORD(2, 2);; break; } /* Return the Version Requested, unless error */ lpWSAData->wVersion = VersionReturned; lpWSAData->wHighVersion = MAKEWORD(2,2); lstrcpyA(lpWSAData->szDescription, "WinSock 2.0"); lstrcpyA(lpWSAData->szSystemStatus, "Running"); if (LOBYTE(wVersionRequested) == 1) { lpWSAData->iMaxSockets = 32767; lpWSAData->iMaxUdpDg = 65467; } else { lpWSAData->iMaxSockets = 0; lpWSAData->iMaxUdpDg = 0; } /*FIXME: increment internal counter */ if (ErrorCode == ERROR_SUCCESS) WSASETINITIALIZED; return ErrorCode; }
/* * @implemented */ SOCKET EXPORT WSASocketW(IN INT af, IN INT type, IN INT protocol, IN LPWSAPROTOCOL_INFOW lpProtocolInfo, IN GROUP g, IN DWORD dwFlags) /* * FUNCTION: Creates a new socket descriptor * ARGUMENTS: * af = Address family * type = Socket type * protocol = Protocol type * lpProtocolInfo = Pointer to protocol information * g = Reserved * dwFlags = Socket flags * RETURNS: * Created socket descriptor, or INVALID_SOCKET if it could not be created */ { INT Status; SOCKET Socket; PCATALOG_ENTRY Provider; WSAPROTOCOL_INFOW ProtocolInfo; WS_DbgPrint(MAX_TRACE, ("af (%d) type (%d) protocol (%d).\n", af, type, protocol)); if (!WSAINITIALIZED) { WS_DbgPrint(MAX_TRACE, ("af (%d) type (%d) protocol (%d) = WSANOTINITIALISED.\n", af, type, protocol)); WSASetLastError(WSANOTINITIALISED); return INVALID_SOCKET; } if (!lpProtocolInfo) { lpProtocolInfo = &ProtocolInfo; ZeroMemory(&ProtocolInfo, sizeof(WSAPROTOCOL_INFOW)); ProtocolInfo.iAddressFamily = af; ProtocolInfo.iSocketType = type; ProtocolInfo.iProtocol = protocol; } Provider = LocateProvider(lpProtocolInfo); if (!Provider) { WS_DbgPrint(MAX_TRACE, ("af (%d) type (%d) protocol (%d) = WSAEAFNOSUPPORT.\n", af, type, protocol)); WSASetLastError(WSAEAFNOSUPPORT); return INVALID_SOCKET; } Status = LoadProvider(Provider, lpProtocolInfo); if (Status != NO_ERROR) { WS_DbgPrint(MAX_TRACE, ("af (%d) type (%d) protocol (%d) = %d.\n", af, type, protocol, Status)); WSASetLastError(Status); return INVALID_SOCKET; } WS_DbgPrint(MAX_TRACE, ("Calling WSPSocket at (0x%X).\n", Provider->ProcTable.lpWSPSocket)); assert(Provider->ProcTable.lpWSPSocket); WS_DbgPrint(MAX_TRACE,("About to call provider socket fn\n")); Socket = Provider->ProcTable.lpWSPSocket(af, type, protocol, lpProtocolInfo, g, dwFlags, &Status); WS_DbgPrint(MAX_TRACE,("Socket: %x, Status: %x\n", Socket, Status)); if (Status != NO_ERROR) { WSASetLastError(Status); return INVALID_SOCKET; } WS_DbgPrint(MAX_TRACE,("Status: %x\n", Status)); return Socket; }
/* * @implemented */ INT EXPORT select(IN INT nfds, IN OUT LPFD_SET readfds, IN OUT LPFD_SET writefds, IN OUT LPFD_SET exceptfds, IN CONST struct timeval *timeout) /* * FUNCTION: Returns status of one or more sockets * ARGUMENTS: * nfds = Always ignored * readfds = Pointer to socket set to be checked for readability (optional) * writefds = Pointer to socket set to be checked for writability (optional) * exceptfds = Pointer to socket set to be checked for errors (optional) * timeout = Pointer to a TIMEVAL structure indicating maximum wait time * (NULL means wait forever) * RETURNS: * Number of ready socket descriptors, or SOCKET_ERROR if an error ocurred */ { PCATALOG_ENTRY Provider = NULL; INT Count; INT Errno; WS_DbgPrint(MAX_TRACE, ("readfds (0x%X) writefds (0x%X) exceptfds (0x%X).\n", readfds, writefds, exceptfds)); if (!WSAINITIALIZED) { WSASetLastError(WSANOTINITIALISED); WS_DbgPrint(MID_TRACE,("Not initialized\n")); return SOCKET_ERROR; } /* FIXME: Sockets in FD_SETs should be sorted by their provider */ /* FIXME: For now, assume only one service provider */ if ((readfds != NULL) && (readfds->fd_count > 0)) { if (!ReferenceProviderByHandle((HANDLE)readfds->fd_array[0], &Provider)) { WSASetLastError(WSAENOTSOCK); WS_DbgPrint(MID_TRACE,("No provider (read)\n")); return SOCKET_ERROR; } } else if ((writefds != NULL) && (writefds->fd_count > 0)) { if (!ReferenceProviderByHandle((HANDLE)writefds->fd_array[0], &Provider)) { WSASetLastError(WSAENOTSOCK); WS_DbgPrint(MID_TRACE,("No provider (write)\n")); return SOCKET_ERROR; } } else if ((exceptfds != NULL) && (exceptfds->fd_count > 0)) { if (!ReferenceProviderByHandle((HANDLE)exceptfds->fd_array[0], &Provider)) { WSASetLastError(WSAENOTSOCK); WS_DbgPrint(MID_TRACE,("No provider (err)\n")); return SOCKET_ERROR; } #if 0 /* XXX empty select is not an error */ } else { WSASetLastError(WSAEINVAL); return SOCKET_ERROR; #endif } if ( !Provider ) { if ( timeout ) { WS_DbgPrint(MID_TRACE,("Select: used as timer\n")); Sleep( timeout->tv_sec * 1000 + (timeout->tv_usec / 1000) ); } return 0; } else if (Provider->ProcTable.lpWSPSelect) { WS_DbgPrint(MID_TRACE,("Calling WSPSelect:%x\n", Provider->ProcTable.lpWSPSelect)); Count = Provider->ProcTable.lpWSPSelect(nfds, readfds, writefds, exceptfds, (LPTIMEVAL)timeout, &Errno); WS_DbgPrint(MAX_TRACE, ("[%x] Select: Count %d Errno %x\n", Provider, Count, Errno)); DereferenceProviderByPointer(Provider); if (Count == SOCKET_ERROR) { WSASetLastError(Errno); return SOCKET_ERROR; } } else { WSASetLastError(WSAEINVAL); return SOCKET_ERROR; } return Count; }
BOOL WINAPI DllMain(HANDLE hInstDll, ULONG dwReason, LPVOID lpReserved) { PWINSOCK_THREAD_BLOCK p; WS_DbgPrint(MAX_TRACE, ("DllMain of ws2_32.dll.\n")); switch (dwReason) { case DLL_PROCESS_ATTACH: { GlobalHeap = GetProcessHeap(); g_hInstDll = hInstDll; CreateCatalog(); InitProviderHandleTable(); UpcallTable.lpWPUCloseEvent = WPUCloseEvent; UpcallTable.lpWPUCloseSocketHandle = WPUCloseSocketHandle; UpcallTable.lpWPUCreateEvent = WPUCreateEvent; UpcallTable.lpWPUCreateSocketHandle = WPUCreateSocketHandle; UpcallTable.lpWPUFDIsSet = WPUFDIsSet; UpcallTable.lpWPUGetProviderPath = WPUGetProviderPath; UpcallTable.lpWPUModifyIFSHandle = WPUModifyIFSHandle; UpcallTable.lpWPUPostMessage = PostMessageW; UpcallTable.lpWPUQueryBlockingCallback = WPUQueryBlockingCallback; UpcallTable.lpWPUQuerySocketHandleContext = WPUQuerySocketHandleContext; UpcallTable.lpWPUQueueApc = WPUQueueApc; UpcallTable.lpWPUResetEvent = WPUResetEvent; UpcallTable.lpWPUSetEvent = WPUSetEvent; UpcallTable.lpWPUOpenCurrentThread = WPUOpenCurrentThread; UpcallTable.lpWPUCloseThread = WPUCloseThread; /* Fall through to thread attachment handler */ } case DLL_THREAD_ATTACH: { p = HeapAlloc(GlobalHeap, 0, sizeof(WINSOCK_THREAD_BLOCK)); WS_DbgPrint(MAX_TRACE, ("Thread block at 0x%X.\n", p)); if (!p) { return FALSE; } p->Hostent = NULL; p->LastErrorValue = NO_ERROR; p->Getservbyname = NULL; p->Getservbyport = NULL; NtCurrentTeb()->WinSockData = p; } break; case DLL_PROCESS_DETACH: { DestroyCatalog(); FreeProviderHandleTable(); } break; case DLL_THREAD_DETACH: { p = NtCurrentTeb()->WinSockData; if (p) HeapFree(GlobalHeap, 0, p); } break; } WS_DbgPrint(MAX_TRACE, ("DllMain of ws2_32.dll. Leaving.\n")); return TRUE; }