/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS WinSock 2 DLL * FILE: misc/catalog.c * PURPOSE: Service Provider Catalog * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) * REVISIONS: * CSH 01/09-2000 Created */ #include "ws2_32.h" LIST_ENTRY CatalogListHead; CRITICAL_SECTION CatalogLock; 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")); } 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); } } 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; } 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; } 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; } 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; } 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; } 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 } VOID DestroyCatalog(VOID) { PLIST_ENTRY CurrentEntry; PLIST_ENTRY NextEntry; PCATALOG_ENTRY Provider; CurrentEntry = CatalogListHead.Flink; while (CurrentEntry != &CatalogListHead) { NextEntry = CurrentEntry->Flink; Provider = CONTAINING_RECORD(CurrentEntry, CATALOG_ENTRY, ListEntry); DestroyCatalogEntry(Provider); CurrentEntry = NextEntry; } //DeleteCriticalSection(&CatalogLock); } /* EOF */