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.
314 lines
9.0 KiB
314 lines
9.0 KiB
/*++
|
|
|
|
Copyright (c) 1989 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
qhandle.c
|
|
|
|
Abstract:
|
|
|
|
This module contains the queue handle primitives shared by
|
|
the OS/2 Client and Server. This file was created because the
|
|
file shandle.c which used to handle the queues was not suitable
|
|
for the job and caused the system to break.
|
|
|
|
Author:
|
|
|
|
Beni Lavi (BeniL) 9-Jun-92
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "os2ssrtl.h"
|
|
|
|
#define ALLOCATION_UNITS 32 // ALLOCATION_UNITS must be a power of 2
|
|
|
|
POR2_QHANDLE_TABLE
|
|
Or2CreateQHandleTable(
|
|
IN PVOID Heap,
|
|
IN ULONG SizeOfEntry,
|
|
IN ULONG Reserved
|
|
)
|
|
{
|
|
POR2_QHANDLE_TABLE HandleTable;
|
|
POR2_QHANDLE_ENTRY QHandles;
|
|
PCHAR Entries;
|
|
int i;
|
|
NTSTATUS Status;
|
|
|
|
HandleTable = (POR2_QHANDLE_TABLE)RtlAllocateHeap(Heap, 0,
|
|
sizeof( *HandleTable ));
|
|
if (HandleTable == NULL) {
|
|
return (NULL);
|
|
}
|
|
|
|
QHandles = (POR2_QHANDLE_ENTRY)RtlAllocateHeap( Heap, 0,
|
|
ALLOCATION_UNITS * sizeof(OR2_QHANDLE_ENTRY));
|
|
if (QHandles == NULL) {
|
|
RtlFreeHeap(Heap, 0, (PVOID)HandleTable);
|
|
return (NULL);
|
|
}
|
|
|
|
Entries = (PCHAR)RtlAllocateHeap(Heap, 0, ALLOCATION_UNITS * SizeOfEntry);
|
|
if (Entries == NULL) {
|
|
RtlFreeHeap(Heap, 0, (PVOID)QHandles);
|
|
RtlFreeHeap(Heap, 0, (PVOID)HandleTable);
|
|
return (NULL);
|
|
}
|
|
for (i = 0; i < ALLOCATION_UNITS; i++) {
|
|
QHandles[i].Entry = (PVOID)(Entries + (i * SizeOfEntry));
|
|
QHandles[i].EntryIsAllocated = FALSE;
|
|
QHandles[i].EntryIsChunkPointer = FALSE;
|
|
}
|
|
QHandles[0].EntryIsChunkPointer = TRUE;
|
|
HandleTable->Heap = Heap;
|
|
HandleTable->EntrySize = SizeOfEntry;
|
|
HandleTable->CountEntries = ALLOCATION_UNITS;
|
|
HandleTable->CountFreeEntries = ALLOCATION_UNITS;
|
|
HandleTable->NextToAllocate = 0;
|
|
HandleTable->QHandles = QHandles;
|
|
|
|
Status = RtlInitializeCriticalSection( &HandleTable->Lock );
|
|
ASSERT( NT_SUCCESS( Status ) );
|
|
if (!NT_SUCCESS(Status)) {
|
|
RtlFreeHeap(Heap, 0, (PVOID)Entries);
|
|
RtlFreeHeap(Heap, 0, (PVOID)QHandles);
|
|
RtlFreeHeap(Heap, 0, (PVOID)HandleTable);
|
|
return( NULL );
|
|
}
|
|
|
|
return( HandleTable );
|
|
}
|
|
|
|
BOOLEAN
|
|
Or2DestroyQHandleTable(
|
|
IN POR2_QHANDLE_TABLE HandleTable,
|
|
IN OR2_DESTROY_QHANDLE_ROUTINE DestroyQHandleProcedure
|
|
)
|
|
{
|
|
PVOID Heap;
|
|
POR2_QHANDLE_ENTRY QHandles;
|
|
int i; // must be int - Don't change to ULONG
|
|
|
|
Heap = HandleTable->Heap;
|
|
QHandles = HandleTable->QHandles;
|
|
//
|
|
// Scan in reverse order so that we don't free memory before
|
|
// all handles which access this memory are destroyed.
|
|
//
|
|
for (i = (int)HandleTable->CountEntries - 1; i >= 0; i--) {
|
|
if (QHandles[i].EntryIsAllocated) {
|
|
//
|
|
// Pass i+1, because outside world enumerate handles starting from 1 and not 0.
|
|
//
|
|
(*DestroyQHandleProcedure)(QHandles[i].Entry, (ULONG)i+1);
|
|
}
|
|
if (QHandles[i].EntryIsChunkPointer) {
|
|
RtlFreeHeap(Heap, 0, QHandles[i].Entry);
|
|
}
|
|
}
|
|
RtlFreeHeap(Heap, 0, (PVOID)HandleTable->QHandles);
|
|
|
|
RtlDeleteCriticalSection( &HandleTable->Lock );
|
|
|
|
RtlFreeHeap(Heap, 0, (PVOID)HandleTable);
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
Or2CreateQHandle(
|
|
IN POR2_QHANDLE_TABLE HandleTable,
|
|
IN OUT PULONG Handle,
|
|
IN PVOID Value
|
|
)
|
|
{
|
|
PVOID Heap;
|
|
ULONG NewHandle;
|
|
ULONG NewMaxHandles;
|
|
POR2_QHANDLE_ENTRY QHandles;
|
|
POR2_QHANDLE_ENTRY NewQHandles;
|
|
PCHAR Entries;
|
|
ULONG NewNextToAllocate;
|
|
ULONG i,j;
|
|
|
|
//
|
|
// The handle can be or valid ( >=1 ) or -1 (means - create the new one).
|
|
//
|
|
ASSERT(*Handle);
|
|
//
|
|
// Outside world enumerate handles starting from 1 and not 0.
|
|
//
|
|
NewHandle = *Handle - 1;
|
|
Heap = HandleTable->Heap;
|
|
|
|
AcquireHandleTableLock( HandleTable );
|
|
|
|
//
|
|
// If the handle passed as parameter wasn't valid, create new handle.
|
|
//
|
|
if ((LONG)NewHandle >= 0) {
|
|
if (NewHandle < HandleTable->CountEntries) {
|
|
if (HandleTable->QHandles[NewHandle].EntryIsAllocated) {
|
|
ReleaseHandleTableLock(HandleTable);
|
|
return (FALSE);
|
|
}
|
|
else {
|
|
HandleTable->QHandles[NewHandle].EntryIsAllocated = TRUE;
|
|
RtlMoveMemory(HandleTable->QHandles[NewHandle].Entry,
|
|
Value, HandleTable->EntrySize);
|
|
ReleaseHandleTableLock(HandleTable);
|
|
return (TRUE);
|
|
}
|
|
}
|
|
else {
|
|
NewMaxHandles = (NewHandle + ALLOCATION_UNITS) &
|
|
~(ALLOCATION_UNITS - 1);
|
|
}
|
|
}
|
|
else {
|
|
if (HandleTable->CountFreeEntries != 0) {
|
|
while (TRUE) {
|
|
j = HandleTable->NextToAllocate;
|
|
NewNextToAllocate = j + 1;
|
|
if (NewNextToAllocate == HandleTable->CountEntries) {
|
|
NewNextToAllocate = 0;
|
|
}
|
|
HandleTable->NextToAllocate = NewNextToAllocate;
|
|
if (!HandleTable->QHandles[j].EntryIsAllocated) {
|
|
HandleTable->QHandles[j].EntryIsAllocated = TRUE;
|
|
HandleTable->CountFreeEntries--;
|
|
//
|
|
// For the outside world the enumeration of handles is starting from 1 and not from 0.
|
|
//
|
|
*Handle = j + 1;
|
|
ReleaseHandleTableLock(HandleTable);
|
|
return (TRUE);
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
NewMaxHandles = HandleTable->CountEntries + ALLOCATION_UNITS;
|
|
NewHandle = HandleTable->CountEntries;
|
|
}
|
|
}
|
|
NewQHandles = (POR2_QHANDLE_ENTRY)RtlAllocateHeap(Heap, 0,
|
|
NewMaxHandles * sizeof(OR2_QHANDLE_ENTRY));
|
|
if (NewQHandles == NULL) {
|
|
ReleaseHandleTableLock(HandleTable);
|
|
return (FALSE);
|
|
}
|
|
QHandles = HandleTable->QHandles;
|
|
Entries = (PCHAR)RtlAllocateHeap(Heap, 0,
|
|
(NewMaxHandles - HandleTable->CountEntries) *
|
|
HandleTable->EntrySize);
|
|
if (Entries == NULL) {
|
|
RtlFreeHeap(Heap, 0, (PVOID)QHandles);
|
|
ReleaseHandleTableLock(HandleTable);
|
|
return (FALSE);
|
|
}
|
|
RtlMoveMemory(NewQHandles, QHandles,
|
|
HandleTable->CountEntries * sizeof(OR2_QHANDLE_ENTRY));
|
|
for (i = HandleTable->CountEntries, j = 0;
|
|
i < NewMaxHandles;
|
|
i++, j++) {
|
|
NewQHandles[i].Entry = (PVOID)(Entries + (j * HandleTable->EntrySize));
|
|
NewQHandles[i].EntryIsAllocated = FALSE;
|
|
NewQHandles[i].EntryIsChunkPointer = FALSE;
|
|
}
|
|
NewQHandles[HandleTable->CountEntries].EntryIsChunkPointer = TRUE;
|
|
HandleTable->CountFreeEntries +=
|
|
NewMaxHandles - HandleTable->CountEntries - 1;
|
|
HandleTable->CountEntries = NewMaxHandles;
|
|
RtlFreeHeap(Heap, 0, HandleTable->QHandles);
|
|
HandleTable->QHandles = NewQHandles;
|
|
HandleTable->QHandles[NewHandle].EntryIsAllocated = TRUE;
|
|
RtlMoveMemory(HandleTable->QHandles[NewHandle].Entry,
|
|
Value, HandleTable->EntrySize);
|
|
//
|
|
// For the outside world the enumeration of handles is starting from 1 and not from 0.
|
|
//
|
|
*Handle = NewHandle + 1;
|
|
NewNextToAllocate = NewHandle + 1;
|
|
if (NewNextToAllocate == HandleTable->CountEntries) {
|
|
NewNextToAllocate = 0;
|
|
}
|
|
HandleTable->NextToAllocate = NewNextToAllocate;
|
|
ReleaseHandleTableLock(HandleTable);
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
PVOID
|
|
Or2MapQHandle(
|
|
IN POR2_QHANDLE_TABLE HandleTable,
|
|
IN ULONG Handle,
|
|
IN BOOLEAN TableLocked
|
|
)
|
|
{
|
|
PVOID HandleTableEntry;
|
|
|
|
//
|
|
// For the outside world the enumeration of handles is starting from 1 and not from 0.
|
|
//
|
|
Handle--;
|
|
|
|
if (!TableLocked) {
|
|
AcquireHandleTableLock( HandleTable );
|
|
}
|
|
|
|
if (Handle >= HandleTable->CountEntries) {
|
|
HandleTableEntry = NULL;
|
|
if (!TableLocked) {
|
|
ReleaseHandleTableLock( HandleTable );
|
|
}
|
|
}
|
|
else if (HandleTable->QHandles[Handle].EntryIsAllocated) {
|
|
HandleTableEntry = HandleTable->QHandles[Handle].Entry;
|
|
}
|
|
else {
|
|
HandleTableEntry = NULL;
|
|
if (!TableLocked) {
|
|
ReleaseHandleTableLock( HandleTable );
|
|
}
|
|
}
|
|
|
|
return( HandleTableEntry );
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
Or2DestroyQHandle(
|
|
IN POR2_QHANDLE_TABLE HandleTable,
|
|
IN ULONG Handle
|
|
)
|
|
{
|
|
BOOLEAN Result;
|
|
PVOID HandleTableEntry;
|
|
|
|
//
|
|
// For the outside world the enumeration of handles is starting from 1 and not from 0.
|
|
//
|
|
Handle--;
|
|
|
|
if (Handle >= HandleTable->CountEntries) {
|
|
Result = FALSE;
|
|
}
|
|
else if (HandleTable->QHandles[Handle].EntryIsAllocated) {
|
|
HandleTableEntry = HandleTable->QHandles[Handle].Entry;
|
|
RtlZeroMemory(HandleTableEntry, HandleTable->EntrySize);
|
|
HandleTable->QHandles[Handle].EntryIsAllocated = FALSE;
|
|
HandleTable->CountFreeEntries++;
|
|
Result = TRUE;
|
|
}
|
|
else {
|
|
Result = FALSE;
|
|
}
|
|
|
|
ReleaseHandleTableLock( HandleTable );
|
|
|
|
return Result;
|
|
}
|