mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
498 lines
14 KiB
498 lines
14 KiB
/*++
|
|
|
|
Copyright (c) 1989 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
shandle.c
|
|
|
|
Abstract:
|
|
|
|
This module contains the semaphore handle primitives shared by
|
|
the OS/2 Client and Server.
|
|
|
|
Author:
|
|
|
|
Steve Wood (stevewo) 07-Nov-1989
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "os2ssrtl.h"
|
|
|
|
CCHAR ByteLog2Table[256] = {
|
|
1, 1, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, // 00
|
|
4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, // 10
|
|
5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, // 20
|
|
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, // 30
|
|
6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 40
|
|
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 50
|
|
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 60
|
|
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 70
|
|
7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, // 80
|
|
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, // 90
|
|
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, // A0
|
|
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, // B0
|
|
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, // C0
|
|
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, // D0
|
|
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, // E0
|
|
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}; // F0
|
|
|
|
ULONG
|
|
RtlLog2(
|
|
IN ULONG Value
|
|
)
|
|
{
|
|
if (Value & 0xFF000000) {
|
|
return( 24 + ByteLog2Table[ Value >> 24 ] );
|
|
}
|
|
else
|
|
if (Value & 0x00FF0000) {
|
|
return( 16 + ByteLog2Table[ Value >> 16 ] );
|
|
}
|
|
else
|
|
if (Value & 0x0000FF00) {
|
|
return( 8 + ByteLog2Table[ Value >> 8 ] );
|
|
}
|
|
else {
|
|
return( ByteLog2Table[ Value ] );
|
|
}
|
|
}
|
|
|
|
POR2_HANDLE_TABLE
|
|
Or2CreateHandleTable(
|
|
IN PVOID Heap,
|
|
IN ULONG SizeOfEntry,
|
|
IN ULONG CountFixedEntries
|
|
)
|
|
{
|
|
POR2_HANDLE_TABLE HandleTable;
|
|
ULONG LogSizeOfEntry;
|
|
PVOID HandleEntries;
|
|
NTSTATUS Status;
|
|
|
|
LogSizeOfEntry = RtlLog2( (UCHAR)SizeOfEntry );
|
|
SizeOfEntry = 1 << LogSizeOfEntry;
|
|
HandleTable = RtlAllocateHeap( Heap, 0,
|
|
sizeof( *HandleTable ) +
|
|
(CountFixedEntries * SizeOfEntry)
|
|
);
|
|
if (HandleTable == NULL) {
|
|
return( NULL );
|
|
}
|
|
|
|
HandleEntries = (PVOID)(HandleTable+1);
|
|
if (CountFixedEntries != 0) {
|
|
RtlZeroMemory( HandleEntries, CountFixedEntries * SizeOfEntry );
|
|
}
|
|
|
|
Status = RtlInitializeCriticalSection( &HandleTable->Lock );
|
|
ASSERT( NT_SUCCESS( Status ) );
|
|
if (!NT_SUCCESS( Status )) {
|
|
RtlFreeHeap( Heap, 0,
|
|
HandleTable
|
|
);
|
|
return( NULL );
|
|
}
|
|
|
|
HandleTable->Length = sizeof( *HandleTable );
|
|
HandleTable->Heap = Heap;
|
|
HandleTable->LogEntrySize = LogSizeOfEntry;
|
|
HandleTable->CountEntries = CountFixedEntries;
|
|
HandleTable->CountFixedEntries = CountFixedEntries;
|
|
HandleTable->CountFreeEntries = CountFixedEntries;
|
|
HandleTable->FixedEntries = HandleEntries;
|
|
HandleTable->Entries = 0;
|
|
return( HandleTable );
|
|
}
|
|
|
|
BOOLEAN
|
|
Or2DestroyHandleTable(
|
|
IN POR2_HANDLE_TABLE HandleTable,
|
|
IN OR2_DESTROY_HANDLE_ROUTINE DestroyHandleProcedure
|
|
)
|
|
{
|
|
PULONG HandleTableEntry;
|
|
ULONG SizeOfEntry;
|
|
ULONG CurrentHandle;
|
|
|
|
SizeOfEntry = 1 << HandleTable->LogEntrySize;
|
|
CurrentHandle = 0;
|
|
HandleTableEntry = HandleTable->FixedEntries;
|
|
while (CurrentHandle < HandleTable->CountFixedEntries) {
|
|
if (*HandleTableEntry) {
|
|
(*DestroyHandleProcedure)( HandleTableEntry, CurrentHandle );
|
|
}
|
|
|
|
HandleTableEntry = (PVOID)((PCH)HandleTableEntry + SizeOfEntry);
|
|
CurrentHandle++;
|
|
}
|
|
|
|
if ((HandleTableEntry = HandleTable->Entries) != NULL) {
|
|
while (CurrentHandle < HandleTable->CountEntries) {
|
|
if (*HandleTableEntry) {
|
|
(*DestroyHandleProcedure)( HandleTableEntry, CurrentHandle );
|
|
}
|
|
|
|
HandleTableEntry = (PVOID)((PCH)HandleTableEntry + SizeOfEntry);
|
|
CurrentHandle++;
|
|
}
|
|
|
|
RtlFreeHeap( HandleTable->Heap, 0,
|
|
HandleTable->Entries
|
|
);
|
|
}
|
|
|
|
RtlDeleteCriticalSection( &HandleTable->Lock );
|
|
|
|
RtlFreeHeap( HandleTable->Heap, 0,
|
|
HandleTable
|
|
);
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
Or2CreateHandle(
|
|
IN POR2_HANDLE_TABLE HandleTable,
|
|
IN OUT PULONG Handle,
|
|
IN PVOID Value
|
|
)
|
|
{
|
|
PVOID HandleEntries;
|
|
PULONG HandleTableEntry;
|
|
ULONG NewHandle;
|
|
ULONG CountOldEntries;
|
|
ULONG CountNewEntries;
|
|
ULONG SizeOfEntry;
|
|
ULONG cbOldEntries;
|
|
ULONG cbNewEntries;
|
|
BOOLEAN Result;
|
|
|
|
NewHandle = *Handle;
|
|
|
|
AcquireHandleTableLock( HandleTable );
|
|
|
|
SizeOfEntry = 1 << HandleTable->LogEntrySize;
|
|
if ((NewHandle == -1 && HandleTable->CountFreeEntries == 0) ||
|
|
(NewHandle != -1 && NewHandle >= HandleTable->CountEntries)
|
|
) {
|
|
CountOldEntries = HandleTable->CountEntries -
|
|
HandleTable->CountFixedEntries;
|
|
if (NewHandle == -1) {
|
|
NewHandle = HandleTable->CountEntries;
|
|
if (CountOldEntries) {
|
|
CountNewEntries = CountOldEntries << 1;
|
|
}
|
|
else {
|
|
CountNewEntries = 16;
|
|
}
|
|
}
|
|
else {
|
|
CountNewEntries = NewHandle -
|
|
HandleTable->CountFixedEntries + 1;
|
|
}
|
|
|
|
cbNewEntries = CountNewEntries << HandleTable->LogEntrySize;
|
|
cbOldEntries = CountOldEntries << HandleTable->LogEntrySize;
|
|
|
|
HandleEntries = RtlAllocateHeap( HandleTable->Heap, 0,
|
|
cbNewEntries
|
|
);
|
|
if (HandleEntries == NULL) {
|
|
ReleaseHandleTableLock( HandleTable );
|
|
return( FALSE );
|
|
}
|
|
|
|
RtlZeroMemory( (PCH)HandleEntries + cbOldEntries,
|
|
cbNewEntries - cbOldEntries
|
|
);
|
|
|
|
if (cbOldEntries) {
|
|
RtlMoveMemory( HandleEntries,
|
|
HandleTable->Entries,
|
|
cbOldEntries
|
|
);
|
|
|
|
RtlFreeHeap( HandleTable->Heap, 0,
|
|
HandleTable->Entries
|
|
);
|
|
}
|
|
|
|
HandleTable->Entries = HandleEntries;
|
|
|
|
HandleTable->CountEntries =
|
|
CountNewEntries + HandleTable->CountFixedEntries;
|
|
|
|
HandleTable->CountFreeEntries += CountNewEntries -
|
|
CountOldEntries;
|
|
|
|
HandleTableEntry = (PVOID)((PCH)HandleEntries +
|
|
((NewHandle - HandleTable->CountFixedEntries)
|
|
<< HandleTable->LogEntrySize) );
|
|
}
|
|
else {
|
|
if (NewHandle == -1) {
|
|
NewHandle = 0;
|
|
HandleTableEntry = HandleTable->FixedEntries;
|
|
while (NewHandle < HandleTable->CountFixedEntries) {
|
|
if (*(PULONG)HandleTableEntry == 0) {
|
|
break;
|
|
}
|
|
else {
|
|
HandleTableEntry = (PVOID)((PCH)HandleTableEntry + SizeOfEntry);
|
|
NewHandle++;
|
|
}
|
|
}
|
|
|
|
if (NewHandle == HandleTable->CountFixedEntries) {
|
|
HandleTableEntry = HandleTable->Entries;
|
|
while (NewHandle < HandleTable->CountEntries) {
|
|
if (*(PULONG)HandleTableEntry == 0) {
|
|
break;
|
|
}
|
|
else {
|
|
HandleTableEntry = (PVOID)((PCH)HandleTableEntry + SizeOfEntry);
|
|
NewHandle++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
if (NewHandle < HandleTable->CountFixedEntries) {
|
|
HandleTableEntry =
|
|
(PVOID)((PCH)HandleTable->FixedEntries +
|
|
(SizeOfEntry * NewHandle)
|
|
);
|
|
}
|
|
else
|
|
if (NewHandle < HandleTable->CountEntries) {
|
|
HandleTableEntry =
|
|
(PVOID)((PCH)HandleTable->Entries +
|
|
(SizeOfEntry * (NewHandle -
|
|
HandleTable->CountFixedEntries
|
|
)
|
|
)
|
|
);
|
|
}
|
|
else {
|
|
HandleTableEntry = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (HandleTableEntry != NULL && *(PULONG)HandleTableEntry == 0) {
|
|
if (*Handle != -1 && *Handle != NewHandle) {
|
|
Result = FALSE;
|
|
}
|
|
else {
|
|
RtlMoveMemory( HandleTableEntry, Value, SizeOfEntry );
|
|
HandleTable->CountFreeEntries -= 1;
|
|
*Handle = NewHandle;
|
|
Result = TRUE;
|
|
}
|
|
}
|
|
else {
|
|
Result = FALSE;
|
|
}
|
|
|
|
ReleaseHandleTableLock( HandleTable );
|
|
return( Result );
|
|
}
|
|
|
|
|
|
PVOID
|
|
Or2MapHandle(
|
|
IN POR2_HANDLE_TABLE HandleTable,
|
|
IN ULONG Handle,
|
|
IN BOOLEAN TableLocked
|
|
)
|
|
{
|
|
PVOID HandleTableEntry;
|
|
|
|
if (!TableLocked) {
|
|
AcquireHandleTableLock( HandleTable );
|
|
}
|
|
|
|
if (Handle < HandleTable->CountFixedEntries) {
|
|
HandleTableEntry = (PVOID)((PCH)HandleTable->FixedEntries +
|
|
(Handle << HandleTable->LogEntrySize));
|
|
}
|
|
else
|
|
if (Handle < HandleTable->CountEntries) {
|
|
Handle -= HandleTable->CountFixedEntries;
|
|
HandleTableEntry = (PVOID)((PCH)HandleTable->Entries +
|
|
(Handle << HandleTable->LogEntrySize)
|
|
);
|
|
}
|
|
else {
|
|
if (!TableLocked) {
|
|
ReleaseHandleTableLock( HandleTable );
|
|
}
|
|
|
|
HandleTableEntry = NULL;
|
|
}
|
|
|
|
return( HandleTableEntry );
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
Or2DestroyHandle(
|
|
IN POR2_HANDLE_TABLE HandleTable,
|
|
IN ULONG Handle
|
|
)
|
|
{
|
|
BOOLEAN Result;
|
|
PULONG HandleTableEntry;
|
|
|
|
if (Handle < HandleTable->CountFixedEntries) {
|
|
HandleTableEntry = (PULONG)((PCH)HandleTable->FixedEntries +
|
|
(Handle << HandleTable->LogEntrySize));
|
|
}
|
|
else
|
|
if (Handle < HandleTable->CountEntries) {
|
|
Handle -= HandleTable->CountFixedEntries;
|
|
HandleTableEntry = (PULONG)((PCH)HandleTable->Entries +
|
|
(Handle << HandleTable->LogEntrySize)
|
|
);
|
|
}
|
|
else {
|
|
HandleTableEntry = NULL;
|
|
}
|
|
|
|
if (HandleTableEntry != NULL) {
|
|
RtlZeroMemory( HandleTableEntry,
|
|
1 << HandleTable->LogEntrySize
|
|
);
|
|
HandleTable->CountFreeEntries++;
|
|
Result = TRUE;
|
|
}
|
|
else {
|
|
Result = FALSE;
|
|
}
|
|
|
|
ReleaseHandleTableLock( HandleTable );
|
|
|
|
return( Result );
|
|
}
|
|
|
|
|
|
|
|
BOOLEAN
|
|
Or2EnumHandleTable(
|
|
IN POR2_HANDLE_TABLE HandleTable,
|
|
IN OR2_ENUMERATE_HANDLE_ROUTINE EnumHandleProcedure,
|
|
IN PVOID EnumParameter,
|
|
OUT PULONG Handle OPTIONAL
|
|
)
|
|
{
|
|
PULONG HandleTableEntry;
|
|
ULONG SizeOfEntry;
|
|
ULONG CurrentHandle;
|
|
BOOLEAN Result;
|
|
|
|
AcquireHandleTableLock( HandleTable );
|
|
|
|
Result = FALSE;
|
|
SizeOfEntry = 1 << HandleTable->LogEntrySize;
|
|
CurrentHandle = 0;
|
|
HandleTableEntry = HandleTable->FixedEntries;
|
|
while (CurrentHandle < HandleTable->CountFixedEntries) {
|
|
if ((*EnumHandleProcedure)( HandleTableEntry,
|
|
EnumParameter ? EnumParameter :
|
|
(PVOID)CurrentHandle
|
|
)
|
|
) {
|
|
if (ARGUMENT_PRESENT( Handle )) {
|
|
*Handle = CurrentHandle;
|
|
}
|
|
|
|
Result = TRUE;
|
|
break;
|
|
}
|
|
else {
|
|
HandleTableEntry = (PVOID)((PCH)HandleTableEntry + SizeOfEntry);
|
|
CurrentHandle++;
|
|
}
|
|
}
|
|
|
|
if (!Result && CurrentHandle == HandleTable->CountFixedEntries) {
|
|
HandleTableEntry = HandleTable->Entries;
|
|
while (CurrentHandle < HandleTable->CountEntries) {
|
|
if ((*EnumHandleProcedure)( HandleTableEntry,
|
|
EnumParameter ? EnumParameter :
|
|
(PVOID)CurrentHandle
|
|
)
|
|
) {
|
|
if (ARGUMENT_PRESENT( Handle )) {
|
|
*Handle = CurrentHandle;
|
|
}
|
|
|
|
Result = TRUE;
|
|
break;
|
|
}
|
|
else {
|
|
HandleTableEntry = (PVOID)((PCH)HandleTableEntry + SizeOfEntry);
|
|
CurrentHandle++;
|
|
}
|
|
}
|
|
}
|
|
|
|
ReleaseHandleTableLock( HandleTable );
|
|
|
|
return( Result );
|
|
}
|
|
|
|
|
|
#if DBG
|
|
|
|
ULONG
|
|
Or2DumpHandleTable(
|
|
IN POR2_HANDLE_TABLE HandleTable,
|
|
IN OR2_DUMP_HANDLE_ROUTINE DumpHandleProcedure,
|
|
IN PVOID DumpParameter
|
|
)
|
|
{
|
|
PULONG HandleTableEntry;
|
|
ULONG SizeOfEntry;
|
|
ULONG CurrentHandle;
|
|
ULONG NumberOfHandles = 0;
|
|
|
|
SizeOfEntry = 1 << HandleTable->LogEntrySize;
|
|
CurrentHandle = 0;
|
|
HandleTableEntry = HandleTable->FixedEntries;
|
|
while (CurrentHandle < HandleTable->CountFixedEntries) {
|
|
if (*HandleTableEntry) {
|
|
(*DumpHandleProcedure)( HandleTableEntry,
|
|
CurrentHandle,
|
|
DumpParameter
|
|
);
|
|
NumberOfHandles++;
|
|
}
|
|
|
|
HandleTableEntry = (PVOID)((PCH)HandleTableEntry + SizeOfEntry);
|
|
CurrentHandle++;
|
|
}
|
|
|
|
if ((HandleTableEntry = HandleTable->Entries) != NULL) {
|
|
while (CurrentHandle < HandleTable->CountEntries) {
|
|
if (*HandleTableEntry) {
|
|
(*DumpHandleProcedure)( HandleTableEntry,
|
|
CurrentHandle,
|
|
DumpParameter
|
|
);
|
|
NumberOfHandles++;
|
|
}
|
|
|
|
HandleTableEntry = (PVOID)((PCH)HandleTableEntry + SizeOfEntry);
|
|
CurrentHandle++;
|
|
}
|
|
}
|
|
|
|
return( NumberOfHandles );
|
|
}
|
|
|
|
#endif // DBG
|