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

297 lines
7.6 KiB
C

/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS WinSock 2 DLL
* FILE: misc/handle.c
* PURPOSE: Provider handle management
* PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
* REVISIONS:
* CSH 01/09-2000 Created
*/
#include "ws2_32.h"
PPROVIDER_HANDLE_BLOCK ProviderHandleTable;
CRITICAL_SECTION ProviderHandleTableLock;
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;
}
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
DeleteHandleTable(PPROVIDER_HANDLE_BLOCK HandleTable)
{
PPROVIDER_HANDLE_BLOCK Current;
PLIST_ENTRY CurrentEntry;
CloseAllHandles(HandleTable);
CurrentEntry = RemoveHeadList(&HandleTable->Entry);
while (CurrentEntry != &HandleTable->Entry)
{
Current = CONTAINING_RECORD(CurrentEntry,
PROVIDER_HANDLE_BLOCK,
Entry);
HeapFree(GlobalHeap, 0, Current);
CurrentEntry = RemoveHeadList(&HandleTable->Entry);
}
}
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;
}
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;
}
HANDLE
CreateProviderHandle(HANDLE Handle,
PCATALOG_ENTRY Provider)
{
HANDLE h;
EnterCriticalSection(&ProviderHandleTableLock);
h = CreateProviderHandleTable(ProviderHandleTable,
Handle,
Provider);
LeaveCriticalSection(&ProviderHandleTableLock);
if (h != NULL)
ReferenceProviderByPointer(Provider);
return h;
}
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);
}
BOOL
CloseProviderHandle(HANDLE Handle)
{
PCATALOG_ENTRY Provider;
WS_DbgPrint(MAX_TRACE, ("Handle (0x%X).\n", Handle));
EnterCriticalSection(&ProviderHandleTableLock);
Provider = DeleteProviderHandle(ProviderHandleTable,
Handle);
if (!Provider)
return FALSE;
LeaveCriticalSection(&ProviderHandleTableLock);
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;
}
VOID
FreeProviderHandleTable(VOID)
{
DeleteHandleTable(ProviderHandleTable);
DeleteCriticalSection(&ProviderHandleTableLock);
}
/* EOF */