reactos/dll/win32/ws2_32/misc/catalog.c
2013-06-16 22:01:41 +00:00

356 lines
9.7 KiB
C

/*
* 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 */