- Moved ntdll's atom table implementation to rtl, rewrote it to use proper structures and share the generic implementation between ntoskrnl and ntdll

- Updated the rtl handle table implementation to use proper structures. Reserved handles are not yet supported correctly.

svn path=/trunk/; revision=16257
This commit is contained in:
Thomas Bluemel 2005-06-24 18:11:16 +00:00
parent ff3d5dbe7d
commit 469c016da3
18 changed files with 1243 additions and 1764 deletions

View file

@ -86,7 +86,7 @@ typedef struct _HANDLE_TABLE
ERESOURCE HandleTableLock;
LIST_ENTRY HandleTableList;
KEVENT HandleContentionEvent;
} HANDLE_TABLE;
} HANDLE_TABLE, *PHANDLE_TABLE;
#endif

View file

@ -859,6 +859,14 @@ RtlUnicodeStringToInteger(
PULONG Value
);
NTSTATUS
STDCALL
RtlHashUnicodeString(
IN CONST UNICODE_STRING *String,
IN BOOLEAN CaseInSensitive,
IN ULONG HashAlgorithm,
OUT PULONG HashValue);
/*
* Ansi String Functions
*/
@ -1333,7 +1341,7 @@ DbgBreakPoint(VOID);
/*
* Handle Table Functions
*/
PRTL_HANDLE
PRTL_HANDLE_TABLE_ENTRY
STDCALL
RtlAllocateHandle (
IN PRTL_HANDLE_TABLE HandleTable,
@ -1348,7 +1356,7 @@ BOOLEAN
STDCALL
RtlFreeHandle (
IN PRTL_HANDLE_TABLE HandleTable,
IN PRTL_HANDLE Handle
IN PRTL_HANDLE_TABLE_ENTRY Handle
);
VOID
@ -1363,15 +1371,15 @@ BOOLEAN
STDCALL
RtlIsValidHandle (
IN PRTL_HANDLE_TABLE HandleTable,
IN PRTL_HANDLE Handle
IN PRTL_HANDLE_TABLE_ENTRY Handle
);
BOOLEAN
STDCALL
RtlIsValidIndexHandle (
IN PRTL_HANDLE_TABLE HandleTable,
IN OUT PRTL_HANDLE *Handle,
IN ULONG Index
IN PRTL_HANDLE_TABLE HandleTable,
IN OUT PRTL_HANDLE_TABLE_ENTRY *Handle,
IN ULONG Index
);
/*

View file

@ -50,6 +50,13 @@
#define PDI_HEAP_TAGS 0x08 /* The heap tags */
#define PDI_HEAP_BLOCKS 0x10 /* The heap blocks */
#define PDI_LOCKS 0x20 /* The locks created by the process */
/* RTL Handle Flags */
#define RTL_HANDLE_VALID 0x1
/* RTL Atom Flags */
#define RTL_ATOM_IS_PINNED 0x1
/* ENUMERATIONS **************************************************************/
typedef enum
@ -173,20 +180,23 @@ typedef struct _DEBUG_LOCK_INFORMATION
ULONG NumberOfSharedWaiters;
ULONG NumberOfExclusiveWaiters;
} DEBUG_LOCK_INFORMATION, *PDEBUG_LOCK_INFORMATION;
typedef struct _RTL_HANDLE
{
struct _RTL_HANDLE *Next; /* pointer to next free handle */
} RTL_HANDLE, *PRTL_HANDLE;
typedef struct _RTL_HANDLE_TABLE_ENTRY
{
ULONG Flags;
struct _RTL_HANDLE_TABLE_ENTRY *NextFree;
} RTL_HANDLE_TABLE_ENTRY, *PRTL_HANDLE_TABLE_ENTRY;
typedef struct _RTL_HANDLE_TABLE
{
ULONG TableSize; /* maximum number of handles */
ULONG HandleSize; /* size of handle in bytes */
PRTL_HANDLE Handles; /* pointer to handle array */
PRTL_HANDLE Limit; /* limit of pointers */
PRTL_HANDLE FirstFree; /* pointer to first free handle */
PRTL_HANDLE LastUsed; /* pointer to last allocated handle */
ULONG MaximumNumberOfHandles;
ULONG SizeOfHandleTableEntry;
ULONG Reserved[2];
PRTL_HANDLE_TABLE_ENTRY FreeHandles;
PRTL_HANDLE_TABLE_ENTRY CommittedHandles;
PRTL_HANDLE_TABLE_ENTRY UnCommittedHandles;
PRTL_HANDLE_TABLE_ENTRY MaxReservedHandles;
} RTL_HANDLE_TABLE, *PRTL_HANDLE_TABLE;
typedef struct _LOCK_INFORMATION
{
ULONG LockCount;
@ -346,15 +356,32 @@ typedef struct _RTL_PROCESS_INFO
SECTION_IMAGE_INFORMATION ImageInfo;
} RTL_PROCESS_INFO, *PRTL_PROCESS_INFO;
/* FIXME: This is a Windows Type which which we are not implementing properly
The type below however is our own implementation. We will eventually use Windows' */
typedef struct _RTL_ATOM_TABLE
typedef struct _RTL_ATOM_TABLE_ENTRY
{
ULONG TableSize;
ULONG NumberOfAtoms;
PVOID Lock; /* fast mutex (kernel mode)/ critical section (user mode) */
PVOID HandleTable;
LIST_ENTRY Slot[0];
struct _RTL_ATOM_TABLE_ENTRY *HashLink;
USHORT HandleIndex;
USHORT Atom;
USHORT ReferenceCount;
UCHAR Flags;
UCHAR NameLength;
WCHAR Name[1];
} RTL_ATOM_TABLE_ENTRY, *PRTL_ATOM_TABLE_ENTRY;
typedef struct _RTL_ATOM_TABLE
{
ULONG Signature;
union
{
RTL_CRITICAL_SECTION CriticalSection;
FAST_MUTEX FastMutex;
};
union
{
RTL_HANDLE_TABLE RtlHandleTable;
PHANDLE_TABLE ExHandleTable;
};
ULONG NumberOfBuckets;
PRTL_ATOM_TABLE_ENTRY Buckets[1];
} RTL_ATOM_TABLE, *PRTL_ATOM_TABLE;
/* Let Kernel Drivers use this */

View file

@ -1382,6 +1382,10 @@ typedef struct _UNICODE_PREFIX_TABLE
PUNICODE_PREFIX_TABLE_ENTRY LastNextEntry;
} UNICODE_PREFIX_TABLE, *PUNICODE_PREFIX_TABLE;
/* FIXME - need FAST_MUTEX and PHANDLE_TABLE for RTL_ATOM_TABLE in umode! */
typedef void *FAST_MUTEX;
typedef void *PHANDLE_TABLE;
typedef OSVERSIONINFOW RTL_OSVERSIONINFOW;
typedef LPOSVERSIONINFOW PRTL_OSVERSIONINFOW;
typedef OSVERSIONINFOEXW RTL_OSVERSIONINFOEXW;

View file

@ -132,19 +132,21 @@ typedef struct _RTL_RESOURCE
PVOID DebugInfo; /* ?? */
} RTL_RESOURCE, *PRTL_RESOURCE;
typedef struct _RTL_HANDLE
typedef struct _RTL_HANDLE_TABLE_ENTRY
{
struct _RTL_HANDLE *Next; /* pointer to next free handle */
} RTL_HANDLE, *PRTL_HANDLE;
ULONG Flags;
struct _RTL_HANDLE_TABLE_ENTRY *NextFree;
} RTL_HANDLE_TABLE_ENTRY, *PRTL_HANDLE_TABLE_ENTRY;
typedef struct _RTL_HANDLE_TABLE
{
ULONG TableSize; /* maximum number of handles */
ULONG HandleSize; /* size of handle in bytes */
PRTL_HANDLE Handles; /* pointer to handle array */
PRTL_HANDLE Limit; /* limit of pointers */
PRTL_HANDLE FirstFree; /* pointer to first free handle */
PRTL_HANDLE LastUsed; /* pointer to last allocated handle */
ULONG MaximumNumberOfHandles;
ULONG SizeOfHandleTableEntry;
ULONG Reserved[2];
PRTL_HANDLE_TABLE_ENTRY FreeHandles;
PRTL_HANDLE_TABLE_ENTRY CommittedHandles;
PRTL_HANDLE_TABLE_ENTRY UnCommittedHandles;
PRTL_HANDLE_TABLE_ENTRY MaxReservedHandles;
} RTL_HANDLE_TABLE, *PRTL_HANDLE_TABLE;
@ -594,7 +596,7 @@ RtlReleaseResource (
/* handle table functions */
PRTL_HANDLE
PRTL_HANDLE_TABLE_ENTRY
STDCALL
RtlAllocateHandle (
IN PRTL_HANDLE_TABLE HandleTable,
@ -611,7 +613,7 @@ BOOLEAN
STDCALL
RtlFreeHandle (
IN PRTL_HANDLE_TABLE HandleTable,
IN PRTL_HANDLE Handle
IN PRTL_HANDLE_TABLE_ENTRY Handle
);
VOID
@ -626,14 +628,14 @@ BOOLEAN
STDCALL
RtlIsValidHandle (
IN PRTL_HANDLE_TABLE HandleTable,
IN PRTL_HANDLE Handle
IN PRTL_HANDLE_TABLE_ENTRY Handle
);
BOOLEAN
STDCALL
RtlIsValidIndexHandle (
IN PRTL_HANDLE_TABLE HandleTable,
IN OUT PRTL_HANDLE *Handle,
IN OUT PRTL_HANDLE_TABLE_ENTRY *Handle,
IN ULONG Index
);

View file

@ -227,18 +227,51 @@ typedef struct _RTL_HEAP_DEFINITION
ULONG Unknown[11];
} RTL_HEAP_DEFINITION, *PRTL_HEAP_DEFINITION;
typedef struct _RTL_HANDLE_TABLE_ENTRY
{
ULONG Flags;
struct _RTL_HANDLE_TABLE_ENTRY *NextFree;
} RTL_HANDLE_TABLE_ENTRY, *PRTL_HANDLE_TABLE_ENTRY;
typedef struct _RTL_HANDLE_TABLE
{
ULONG MaximumNumberOfHandles;
ULONG SizeOfHandleTableEntry;
ULONG Reserved[2];
PRTL_HANDLE_TABLE_ENTRY FreeHandles;
PRTL_HANDLE_TABLE_ENTRY CommittedHandles;
PRTL_HANDLE_TABLE_ENTRY UnCommittedHandles;
PRTL_HANDLE_TABLE_ENTRY MaxReservedHandles;
} RTL_HANDLE_TABLE, *PRTL_HANDLE_TABLE;
typedef struct _RTL_ATOM_TABLE_ENTRY
{
struct _RTL_ATOM_TABLE_ENTRY *HashLink;
USHORT HandleIndex;
USHORT Atom;
USHORT ReferenceCount;
UCHAR Flags;
UCHAR NameLength;
WCHAR Name[1];
} RTL_ATOM_TABLE_ENTRY, *PRTL_ATOM_TABLE_ENTRY;
typedef struct _RTL_ATOM_TABLE
{
ULONG TableSize;
ULONG NumberOfAtoms;
PVOID Lock; /* fast mutex (kernel mode)/ critical section (user mode) */
PVOID HandleTable;
LIST_ENTRY Slot[0];
ULONG Signature;
union
{
RTL_CRITICAL_SECTION CriticalSection;
FAST_MUTEX FastMutex;
};
union
{
RTL_HANDLE_TABLE RtlHandleTable;
PHANDLE_TABLE ExHandleTable;
};
ULONG NumberOfBuckets;
PRTL_ATOM_TABLE_ENTRY Buckets[1];
} RTL_ATOM_TABLE, *PRTL_ATOM_TABLE;
#include <pshpack1.h>
typedef struct _NLS_FILE_HEADER

View file

@ -36,7 +36,6 @@
<file>ftol.c</file>
</directory>
<file>apc.c</file>
<file>atom.c</file>
<file>callback.c</file>
<file>crc32.c</file>
<file>critical.c</file>

View file

@ -1,722 +0,0 @@
/* $Id$
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: lib/ntdll/rtl/atom.c
* PURPOSE: Atom managment
* PROGRAMMER: Nobody
* UPDATE HISTORY:
* Created 22/05/98
*/
/* INCLUDES *****************************************************************/
#include <ntdll.h>
#define NDEBUG
#include <debug.h>
/* LOCAL TYPES ***************************************************************/
typedef struct _RTL_ATOM_ENTRY
{
LIST_ENTRY List;
UNICODE_STRING Name;
ULONG RefCount;
BOOLEAN Locked;
ULONG Index;
PRTL_HANDLE Handle;
} RTL_ATOM_ENTRY, *PRTL_ATOM_ENTRY;
typedef struct _RTL_ATOM_HANDLE
{
RTL_HANDLE Handle;
PRTL_ATOM_ENTRY Entry;
} RTL_ATOM_HANDLE, *PRTL_ATOM_HANDLE;
/* PROTOTYPES ****************************************************************/
static ULONG RtlpHashAtomName(ULONG TableSize, PWSTR AtomName);
static BOOLEAN RtlpCheckIntegerAtom(PWSTR AtomName, PUSHORT AtomValue);
static NTSTATUS RtlpInitAtomTableLock(PRTL_ATOM_TABLE AtomTable);
static VOID RtlpDestroyAtomTableLock(PRTL_ATOM_TABLE AtomTable);
static BOOLEAN RtlpLockAtomTable(PRTL_ATOM_TABLE AtomTable);
static VOID RtlpUnlockAtomTable(PRTL_ATOM_TABLE AtomTable);
static BOOLEAN RtlpCreateAtomHandleTable(PRTL_ATOM_TABLE AtomTable);
static VOID RtlpDestroyAtomHandleTable(PRTL_ATOM_TABLE AtomTable);
/* FUNCTIONS *****************************************************************/
/*
* @implemented
*/
NTSTATUS STDCALL
RtlCreateAtomTable(ULONG TableSize,
PRTL_ATOM_TABLE *AtomTable)
{
PRTL_ATOM_TABLE Table;
ULONG i;
NTSTATUS Status;
DPRINT("RtlCreateAtomTable(TableSize %lu AtomTable %p)\n",
TableSize, AtomTable);
if (*AtomTable != NULL)
{
return STATUS_SUCCESS;
}
/* allocate atom table */
Table = RtlAllocateHeap(RtlGetProcessHeap(),
HEAP_ZERO_MEMORY,
TableSize * sizeof(LIST_ENTRY) +
sizeof(RTL_ATOM_TABLE));
if (Table == NULL)
{
return STATUS_NO_MEMORY;
}
/* initialize atom table */
Table->TableSize = TableSize;
for (i = 0; i < TableSize; i++)
{
InitializeListHead(&Table->Slot[i]);
}
Status = RtlpInitAtomTableLock(Table);
if (!NT_SUCCESS(Status))
{
RtlFreeHeap(RtlGetProcessHeap(),
0,
Table);
return Status;
}
if (RtlpCreateAtomHandleTable(Table) == FALSE)
{
RtlpDestroyAtomTableLock(Table);
RtlFreeHeap(RtlGetProcessHeap(),
0,
Table);
return STATUS_NO_MEMORY;
}
*AtomTable = Table;
return STATUS_SUCCESS;
}
/*
* @implemented
*/
NTSTATUS STDCALL
RtlDestroyAtomTable(IN PRTL_ATOM_TABLE AtomTable)
{
PLIST_ENTRY Current;
PRTL_ATOM_ENTRY AtomEntry;
ULONG i;
if (RtlpLockAtomTable(AtomTable) == FALSE)
{
return (STATUS_INVALID_PARAMETER);
}
/* delete all atoms */
for (i = 0; i < AtomTable->TableSize; i++)
{
Current = AtomTable->Slot[i].Flink;
while (Current != &AtomTable->Slot[i])
{
AtomEntry = (PRTL_ATOM_ENTRY)Current;
RtlFreeUnicodeString(&AtomEntry->Name);
RemoveEntryList(&AtomEntry->List);
RtlFreeHeap(RtlGetProcessHeap(),
0,
AtomEntry);
Current = AtomTable->Slot[i].Flink;
}
}
RtlpDestroyAtomHandleTable(AtomTable);
RtlpUnlockAtomTable(AtomTable);
RtlpDestroyAtomTableLock(AtomTable);
RtlFreeHeap(RtlGetProcessHeap(),
0,
AtomTable);
return STATUS_SUCCESS;
}
/*
* @implemented
*/
NTSTATUS STDCALL
RtlEmptyAtomTable(PRTL_ATOM_TABLE AtomTable,
BOOLEAN DeletePinned)
{
PLIST_ENTRY Current, Next;
PRTL_ATOM_ENTRY AtomEntry;
ULONG i;
DPRINT("RtlEmptyAtomTable (AtomTable %p DeletePinned %x)\n",
AtomTable, DeletePinned);
if (RtlpLockAtomTable(AtomTable) == FALSE)
{
return (STATUS_INVALID_PARAMETER);
}
/* delete all atoms */
for (i = 0; i < AtomTable->TableSize; i++)
{
Current = AtomTable->Slot[i].Flink;
while (Current != &AtomTable->Slot[i])
{
Next = Current->Flink;
AtomEntry = (PRTL_ATOM_ENTRY)Current;
if ((AtomEntry->Locked == FALSE) ||
((AtomEntry->Locked == TRUE) && (DeletePinned == TRUE)))
{
RtlFreeUnicodeString(&AtomEntry->Name);
RtlFreeHandle(AtomTable->HandleTable,
AtomEntry->Handle);
RemoveEntryList(&AtomEntry->List);
RtlFreeHeap(RtlGetProcessHeap(),
0,
AtomEntry);
}
Current = Next;
}
}
RtlpUnlockAtomTable(AtomTable);
return STATUS_SUCCESS;
}
/*
* @implemented
*/
NTSTATUS STDCALL
RtlAddAtomToAtomTable(IN PRTL_ATOM_TABLE AtomTable,
IN PWSTR AtomName,
OUT PRTL_ATOM Atom)
{
ULONG Hash;
PLIST_ENTRY Current;
PRTL_ATOM_ENTRY Entry;
USHORT AtomValue;
NTSTATUS Status;
PRTL_ATOM_HANDLE AtomHandle;
ULONG AtomIndex;
DPRINT("RtlAddAtomToAtomTable (AtomTable %p AtomName %S Atom %p)\n",
AtomTable, AtomName, Atom);
if (RtlpCheckIntegerAtom (AtomName, &AtomValue))
{
/* integer atom */
if (AtomValue >= 0xC000)
{
AtomValue = 0;
Status = STATUS_INVALID_PARAMETER;
}
else
{
Status = STATUS_SUCCESS;
}
if (Atom)
*Atom = (RTL_ATOM)AtomValue;
return Status;
}
RtlpLockAtomTable(AtomTable);
/* string atom */
Hash = RtlpHashAtomName(AtomTable->TableSize, AtomName);
/* search for existing atom */
Current = AtomTable->Slot[Hash].Flink;
while (Current != &AtomTable->Slot[Hash])
{
Entry = (PRTL_ATOM_ENTRY)Current;
DPRINT("Comparing %S and %S\n", Entry->Name.Buffer, AtomName);
if (_wcsicmp(Entry->Name.Buffer, AtomName) == 0)
{
Entry->RefCount++;
if (Atom)
*Atom = (RTL_ATOM)(Entry->Index + 0xC000);
RtlpUnlockAtomTable(AtomTable);
return STATUS_SUCCESS;
}
Current = Current->Flink;
}
/* insert new atom */
Entry = RtlAllocateHeap(RtlGetProcessHeap(),
HEAP_ZERO_MEMORY,
sizeof(RTL_ATOM_ENTRY));
if (Entry == NULL)
{
RtlpUnlockAtomTable(AtomTable);
return STATUS_NO_MEMORY;
}
InsertTailList(&AtomTable->Slot[Hash], &Entry->List);
RtlCreateUnicodeString (&Entry->Name,
AtomName);
Entry->RefCount = 1;
Entry->Locked = FALSE;
/* FIXME: use general function instead !! */
AtomHandle = (PRTL_ATOM_HANDLE)RtlAllocateHandle(AtomTable->HandleTable,
&AtomIndex);
DPRINT("AtomHandle %p AtomIndex %x\n", AtomHandle, AtomIndex);
AtomHandle->Entry = Entry;
Entry->Index = AtomIndex;
Entry->Handle = (PRTL_HANDLE)AtomHandle;
if (Atom)
*Atom = (RTL_ATOM)(AtomIndex + 0xC000);
RtlpUnlockAtomTable(AtomTable);
return STATUS_SUCCESS;
}
/*
* @implemented
*/
NTSTATUS STDCALL
RtlDeleteAtomFromAtomTable(IN PRTL_ATOM_TABLE AtomTable,
IN RTL_ATOM Atom)
{
PRTL_ATOM_HANDLE AtomHandle;
PRTL_ATOM_ENTRY AtomEntry;
DPRINT("RtlDeleteAtomFromAtomTable (AtomTable %p Atom %x)\n",
AtomTable, Atom);
if (Atom < 0xC000)
{
return STATUS_SUCCESS;
}
RtlpLockAtomTable(AtomTable);
/* FIXME: use general function instead !! */
if (!RtlIsValidIndexHandle(AtomTable->HandleTable,
(PRTL_HANDLE *)&AtomHandle,
(ULONG)Atom - 0xC000))
{
RtlpUnlockAtomTable(AtomTable);
return STATUS_INVALID_HANDLE;
}
DPRINT("AtomHandle %x\n", AtomHandle);
DPRINT("AtomHandle->Entry %x\n", AtomHandle->Entry);
AtomEntry = AtomHandle->Entry;
DPRINT("Atom name: %wZ\n", &AtomEntry->Name);
AtomEntry->RefCount--;
if (AtomEntry->RefCount == 0)
{
if (AtomEntry->Locked == TRUE)
{
DPRINT("Atom %wZ is locked!\n", &AtomEntry->Name);
RtlpUnlockAtomTable(AtomTable);
return STATUS_WAS_LOCKED;
}
DPRINT("Removing atom: %wZ\n", &AtomEntry->Name);
RtlFreeUnicodeString(&AtomEntry->Name);
RemoveEntryList(&AtomEntry->List);
RtlFreeHeap(RtlGetProcessHeap(),
0,
AtomEntry);
RtlFreeHandle(AtomTable->HandleTable,
(PRTL_HANDLE)AtomHandle);
}
RtlpUnlockAtomTable(AtomTable);
return STATUS_SUCCESS;
}
/*
* @implemented
*/
NTSTATUS STDCALL
RtlLookupAtomInAtomTable(IN PRTL_ATOM_TABLE AtomTable,
IN PWSTR AtomName,
OUT PRTL_ATOM Atom)
{
ULONG Hash;
PLIST_ENTRY Current;
PRTL_ATOM_ENTRY Entry;
USHORT AtomValue;
NTSTATUS Status;
DPRINT("RtlLookupAtomInAtomTable (AtomTable %p AtomName %S Atom %p)\n",
AtomTable, AtomName, Atom);
if (RtlpCheckIntegerAtom (AtomName, &AtomValue))
{
/* integer atom */
if (AtomValue >= 0xC000)
{
AtomValue = 0;
Status = STATUS_INVALID_PARAMETER;
}
else
{
Status = STATUS_SUCCESS;
}
if (Atom)
*Atom = (RTL_ATOM)AtomValue;
return Status;
}
RtlpLockAtomTable(AtomTable);
/* string atom */
Hash = RtlpHashAtomName(AtomTable->TableSize, AtomName);
/* search for existing atom */
Current = AtomTable->Slot[Hash].Flink;
while (Current != &AtomTable->Slot[Hash])
{
Entry = (PRTL_ATOM_ENTRY)Current;
DPRINT("Comparing %S and %S\n", Entry->Name.Buffer, AtomName);
if (_wcsicmp(Entry->Name.Buffer, AtomName) == 0)
{
if (Atom)
*Atom = (RTL_ATOM)(Entry->Index + 0xC000);
RtlpUnlockAtomTable(AtomTable);
return STATUS_SUCCESS;
}
Current = Current->Flink;
}
RtlpUnlockAtomTable(AtomTable);
return STATUS_OBJECT_NAME_NOT_FOUND;
}
/*
* @implemented
*/
NTSTATUS STDCALL
RtlPinAtomInAtomTable(IN PRTL_ATOM_TABLE AtomTable,
IN RTL_ATOM Atom)
{
PRTL_ATOM_HANDLE AtomHandle;
PRTL_ATOM_ENTRY AtomEntry;
DPRINT("RtlPinAtomInAtomTable (AtomTable %p Atom %x)\n",
AtomTable, Atom);
if (Atom < 0xC000)
{
return STATUS_SUCCESS;
}
RtlpLockAtomTable(AtomTable);
/* FIXME: use general function instead !! */
if (!RtlIsValidIndexHandle(AtomTable->HandleTable,
(PRTL_HANDLE *)&AtomHandle,
(ULONG)Atom - 0xC000))
{
RtlpUnlockAtomTable(AtomTable);
return STATUS_INVALID_HANDLE;
}
DPRINT("AtomHandle %x\n", AtomHandle);
DPRINT("AtomHandle->Entry %x\n", AtomHandle->Entry);
AtomEntry = AtomHandle->Entry;
DPRINT("Atom name: %wZ\n", &AtomEntry->Name);
AtomEntry->Locked = TRUE;
RtlpUnlockAtomTable(AtomTable);
return STATUS_SUCCESS;
}
/*
* @implemented
*/
NTSTATUS STDCALL
RtlQueryAtomInAtomTable(PRTL_ATOM_TABLE AtomTable,
RTL_ATOM Atom,
PULONG RefCount,
PULONG PinCount,
PWSTR AtomName,
PULONG NameLength)
{
ULONG Length;
PRTL_ATOM_HANDLE AtomHandle;
PRTL_ATOM_ENTRY AtomEntry;
if (Atom < 0xC000)
{
if (RefCount != NULL)
{
*RefCount = 1;
}
if (PinCount != NULL)
{
*PinCount = 1;
}
if ((AtomName != NULL) && (NameLength != NULL) && (NameLength > 0))
{
Length = swprintf(AtomName, L"#%lu", (ULONG)Atom);
*NameLength = Length * sizeof(WCHAR);
}
return STATUS_SUCCESS;
}
RtlpLockAtomTable(AtomTable);
/* FIXME: use general function instead !! */
if (!RtlIsValidIndexHandle(AtomTable->HandleTable,
(PRTL_HANDLE *)&AtomHandle,
(ULONG)Atom - 0xC000))
{
RtlpUnlockAtomTable(AtomTable);
return STATUS_INVALID_HANDLE;
}
DPRINT("AtomHandle %x\n", AtomHandle);
DPRINT("AtomHandle->Entry %x\n", AtomHandle->Entry);
AtomEntry = AtomHandle->Entry;
DPRINT("Atom name: %wZ\n", &AtomEntry->Name);
if (RefCount != NULL)
{
*RefCount = AtomEntry->RefCount;
}
if (PinCount != NULL)
{
*PinCount = (ULONG)AtomEntry->Locked;
}
if ((AtomName != NULL) && (NameLength != NULL))
{
if (*NameLength < AtomEntry->Name.Length)
{
*NameLength = AtomEntry->Name.Length;
RtlpUnlockAtomTable(AtomTable);
return STATUS_BUFFER_TOO_SMALL;
}
Length = swprintf(AtomName, L"%s", AtomEntry->Name.Buffer);
*NameLength = Length * sizeof(WCHAR);
}
RtlpUnlockAtomTable(AtomTable);
return STATUS_SUCCESS;
}
/* INTERNAL FUNCTIONS ********************************************************/
static ULONG
RtlpHashAtomName(ULONG TableSize,
PWSTR AtomName)
{
ULONG q = 0;
PWCHAR p;
DPRINT("RtlpHashAtomName(TableSize %ld AtomName '%S')\n",
TableSize, AtomName);
/* convert the string to an internal representation */
p = AtomName;
while (*p != 0)
{
q += (ULONG)towupper(*p);
p++;
}
DPRINT("q %lu Hash %lu\n", q, q % TableSize);
return (q % TableSize);
}
static BOOLEAN
RtlpCheckIntegerAtom(PWSTR AtomName,
PUSHORT AtomValue)
{
UNICODE_STRING AtomString;
USHORT LoValue;
ULONG LongValue;
PWCHAR p;
DPRINT("RtlpCheckIntegerAtom(AtomName '%S' AtomValue %p)\n",
AtomName, AtomValue);
if (!((ULONG)AtomName & 0xFFFF0000))
{
LoValue = (USHORT)((ULONG)AtomName & 0xFFFF);
if (LoValue >= 0xC000)
return FALSE;
if (LoValue == 0)
LoValue = 0xC000;
if (AtomValue != NULL)
*AtomValue = LoValue;
return TRUE;
}
if (*AtomName != L'#')
return FALSE;
p = AtomName;
p++;
while (*p)
{
if ((*p < L'0') || (*p > L'9'))
return FALSE;
p++;
}
p = AtomName;
p++;
RtlInitUnicodeString(&AtomString,
p);
RtlUnicodeStringToInteger(&AtomString,10, &LongValue);
*AtomValue = (USHORT)(LongValue & 0x0000FFFF);
return TRUE;
}
/* lock functions */
static NTSTATUS
RtlpInitAtomTableLock(PRTL_ATOM_TABLE AtomTable)
{
AtomTable->Lock = RtlAllocateHeap(RtlGetProcessHeap(),
HEAP_ZERO_MEMORY,
sizeof(RTL_CRITICAL_SECTION));
if (AtomTable->Lock == NULL)
return STATUS_NO_MEMORY;
RtlInitializeCriticalSection((PRTL_CRITICAL_SECTION)AtomTable->Lock);
return STATUS_SUCCESS;
}
static VOID
RtlpDestroyAtomTableLock(PRTL_ATOM_TABLE AtomTable)
{
if (AtomTable->Lock)
{
RtlDeleteCriticalSection((PRTL_CRITICAL_SECTION)AtomTable->Lock);
RtlFreeHeap(RtlGetProcessHeap(),
0,
AtomTable->Lock);
AtomTable->Lock = NULL;
}
}
static BOOLEAN
RtlpLockAtomTable(PRTL_ATOM_TABLE AtomTable)
{
RtlEnterCriticalSection((PRTL_CRITICAL_SECTION)AtomTable->Lock);
return TRUE;
}
static VOID
RtlpUnlockAtomTable(PRTL_ATOM_TABLE AtomTable)
{
RtlLeaveCriticalSection((PRTL_CRITICAL_SECTION)AtomTable->Lock);
}
/* handle functions */
static BOOLEAN
RtlpCreateAtomHandleTable(PRTL_ATOM_TABLE AtomTable)
{
AtomTable->HandleTable = RtlAllocateHeap(RtlGetProcessHeap(),
HEAP_ZERO_MEMORY,
sizeof(RTL_HANDLE_TABLE));
if (AtomTable->HandleTable == NULL)
return FALSE;
RtlInitializeHandleTable(0xCFFF,
sizeof(RTL_ATOM_HANDLE),
(PRTL_HANDLE_TABLE)AtomTable->HandleTable);
return TRUE;
}
static VOID
RtlpDestroyAtomHandleTable(PRTL_ATOM_TABLE AtomTable)
{
if (AtomTable->HandleTable)
{
RtlDestroyHandleTable((PRTL_HANDLE_TABLE)AtomTable->HandleTable);
RtlFreeHeap(RtlGetProcessHeap(),
0,
AtomTable->HandleTable);
AtomTable->HandleTable = NULL;
}
}
/* EOF */

View file

@ -24,8 +24,8 @@ RtlInitializeHandleTable(ULONG TableSize,
memset(HandleTable,
0,
sizeof(RTL_HANDLE_TABLE));
HandleTable->TableSize = TableSize;
HandleTable->HandleSize = HandleSize;
HandleTable->MaximumNumberOfHandles = TableSize;
HandleTable->SizeOfHandleTableEntry = HandleSize;
}
@ -39,38 +39,43 @@ RtlDestroyHandleTable(PRTL_HANDLE_TABLE HandleTable)
ULONG ArraySize;
/* free handle array */
ArrayPointer = (PVOID)HandleTable->Handles;
ArraySize = (ULONG)HandleTable->Limit - (ULONG)HandleTable->Handles;
NtFreeVirtualMemory(NtCurrentProcess(),
&ArrayPointer,
&ArraySize,
MEM_RELEASE);
if (HandleTable->CommittedHandles)
{
ArrayPointer = (PVOID)HandleTable->CommittedHandles;
ArraySize = HandleTable->SizeOfHandleTableEntry * HandleTable->MaximumNumberOfHandles;
NtFreeVirtualMemory(NtCurrentProcess(),
&ArrayPointer,
&ArraySize,
MEM_RELEASE);
}
}
/*
* @implemented
*/
PRTL_HANDLE STDCALL
PRTL_HANDLE_TABLE_ENTRY STDCALL
RtlAllocateHandle(PRTL_HANDLE_TABLE HandleTable,
PULONG Index)
{
RTL_HANDLE **pp_new,**pph,*ph;
PRTL_HANDLE_TABLE_ENTRY *pp_new, *pph, ph;
NTSTATUS Status;
PRTL_HANDLE retval;
PRTL_HANDLE_TABLE_ENTRY retval;
PVOID ArrayPointer;
ULONG ArraySize;
pp_new = &HandleTable->FirstFree;
pp_new = &HandleTable->FreeHandles;
if (HandleTable->FirstFree == NULL)
if (HandleTable->FreeHandles == NULL)
{
/* no free handle available */
if (HandleTable->LastUsed == NULL)
if (HandleTable->UnCommittedHandles == NULL)
{
/* allocate handle array */
ArraySize = HandleTable->HandleSize * HandleTable->TableSize;
ArraySize = HandleTable->SizeOfHandleTableEntry * HandleTable->MaximumNumberOfHandles;
ArrayPointer = NULL;
/* FIXME - only reserve handles here! */
Status = NtAllocateVirtualMemory(NtCurrentProcess(),
(PVOID*)&ArrayPointer,
0,
@ -81,30 +86,34 @@ RtlAllocateHandle(PRTL_HANDLE_TABLE HandleTable,
return NULL;
/* update handle array pointers */
HandleTable->Handles = (PRTL_HANDLE)ArrayPointer;
HandleTable->Limit = (PRTL_HANDLE)(ArrayPointer + ArraySize);
HandleTable->LastUsed = (PRTL_HANDLE)ArrayPointer;
HandleTable->FreeHandles = (PRTL_HANDLE_TABLE_ENTRY)ArrayPointer;
HandleTable->MaxReservedHandles = (PRTL_HANDLE_TABLE_ENTRY)((ULONG_PTR)ArrayPointer + ArraySize);
HandleTable->CommittedHandles = (PRTL_HANDLE_TABLE_ENTRY)ArrayPointer;
HandleTable->UnCommittedHandles = (PRTL_HANDLE_TABLE_ENTRY)ArrayPointer;
}
/* FIXME - should check if handles need to be committed */
/* build free list in handle array */
ph = HandleTable->LastUsed;
ph = HandleTable->FreeHandles;
pph = pp_new;
while (ph < HandleTable->Limit)
while (ph < HandleTable->MaxReservedHandles)
{
*pph = ph;
pph = &ph->Next;
ph = (PRTL_HANDLE)((ULONG)ph + HandleTable->HandleSize);
pph = &ph->NextFree;
ph = (PRTL_HANDLE_TABLE_ENTRY)((ULONG_PTR)ph + HandleTable->SizeOfHandleTableEntry);
}
*pph = 0;
}
/* remove handle from free list */
retval = *pp_new;
*pp_new = retval->Next;
retval->Next = NULL;
*pp_new = retval->NextFree;
retval->NextFree = NULL;
if (Index)
*Index = ((ULONG)retval - (ULONG)HandleTable->Handles) / HandleTable->HandleSize;
*Index = ((ULONG)((ULONG_PTR)retval - (ULONG_PTR)HandleTable->CommittedHandles) /
HandleTable->SizeOfHandleTableEntry);
return retval;
}
@ -115,18 +124,18 @@ RtlAllocateHandle(PRTL_HANDLE_TABLE HandleTable,
*/
BOOLEAN STDCALL
RtlFreeHandle(PRTL_HANDLE_TABLE HandleTable,
PRTL_HANDLE Handle)
PRTL_HANDLE_TABLE_ENTRY Handle)
{
/* check if handle is valid */
if (RtlIsValidHandle(HandleTable, Handle))
return FALSE;
/* clear handle */
memset(Handle, 0, HandleTable->HandleSize);
memset(Handle, 0, HandleTable->SizeOfHandleTableEntry);
/* add handle to free list */
Handle->Next = HandleTable->FirstFree;
HandleTable->FirstFree = Handle;
Handle->NextFree = HandleTable->FreeHandles;
HandleTable->FreeHandles = Handle;
return TRUE;
}
@ -137,12 +146,12 @@ RtlFreeHandle(PRTL_HANDLE_TABLE HandleTable,
*/
BOOLEAN STDCALL
RtlIsValidHandle(PRTL_HANDLE_TABLE HandleTable,
PRTL_HANDLE Handle)
PRTL_HANDLE_TABLE_ENTRY Handle)
{
if ((HandleTable != NULL)
&& (Handle != NULL)
&& (Handle >= HandleTable->Handles)
&& (Handle < HandleTable->Limit))
&& (Handle >= HandleTable->CommittedHandles)
&& (Handle < HandleTable->MaxReservedHandles)
&& (Handle->Flags & RTL_HANDLE_VALID))
return TRUE;
return FALSE;
}
@ -153,10 +162,10 @@ RtlIsValidHandle(PRTL_HANDLE_TABLE HandleTable,
*/
BOOLEAN STDCALL
RtlIsValidIndexHandle(PRTL_HANDLE_TABLE HandleTable,
PRTL_HANDLE *Handle,
PRTL_HANDLE_TABLE_ENTRY *Handle,
ULONG Index)
{
PRTL_HANDLE InternalHandle;
PRTL_HANDLE_TABLE_ENTRY InternalHandle;
DPRINT("RtlIsValidIndexHandle(HandleTable %p Handle %p Index %x)\n", HandleTable, Handle, Index);
@ -164,10 +173,11 @@ RtlIsValidIndexHandle(PRTL_HANDLE_TABLE HandleTable,
return FALSE;
DPRINT("Handles %p HandleSize %x\n",
HandleTable->Handles, HandleTable->HandleSize);
HandleTable->CommittedHandles, HandleTable->SizeOfHandleTableEntry);
InternalHandle = (PRTL_HANDLE)((ULONG)HandleTable->Handles + (HandleTable->HandleSize * Index));
if (RtlIsValidHandle(HandleTable, InternalHandle) == FALSE)
InternalHandle = (PRTL_HANDLE_TABLE_ENTRY)((ULONG_PTR)HandleTable->CommittedHandles +
(HandleTable->SizeOfHandleTableEntry * Index));
if (!RtlIsValidHandle(HandleTable, InternalHandle))
return FALSE;
DPRINT("InternalHandle %p\n", InternalHandle);

View file

@ -77,3 +77,159 @@ CHECK_PAGED_CODE_RTL(char *file, int line)
/* meaningless in user mode */
}
#endif
/* RTL Atom Tables ************************************************************/
typedef struct _RTL_ATOM_HANDLE
{
RTL_HANDLE_TABLE_ENTRY Handle;
PRTL_ATOM_TABLE_ENTRY AtomEntry;
} RTL_ATOM_HANDLE, *PRTL_ATOM_HANDLE;
NTSTATUS
RtlpInitAtomTableLock(PRTL_ATOM_TABLE AtomTable)
{
RtlInitializeCriticalSection(&AtomTable->CriticalSection);
return STATUS_SUCCESS;
}
VOID
RtlpDestroyAtomTableLock(PRTL_ATOM_TABLE AtomTable)
{
RtlDeleteCriticalSection(&AtomTable->CriticalSection);
}
BOOLEAN
RtlpLockAtomTable(PRTL_ATOM_TABLE AtomTable)
{
RtlEnterCriticalSection(&AtomTable->CriticalSection);
return TRUE;
}
VOID
RtlpUnlockAtomTable(PRTL_ATOM_TABLE AtomTable)
{
RtlLeaveCriticalSection(&AtomTable->CriticalSection);
}
/* handle functions */
BOOLEAN
RtlpCreateAtomHandleTable(PRTL_ATOM_TABLE AtomTable)
{
RtlInitializeHandleTable(0xCFFF,
sizeof(RTL_ATOM_HANDLE),
&AtomTable->RtlHandleTable);
return TRUE;
}
VOID
RtlpDestroyAtomHandleTable(PRTL_ATOM_TABLE AtomTable)
{
RtlDestroyHandleTable(&AtomTable->RtlHandleTable);
}
PRTL_ATOM_TABLE
RtlpAllocAtomTable(ULONG Size)
{
return (PRTL_ATOM_TABLE)RtlAllocateHeap(RtlGetProcessHeap(),
HEAP_ZERO_MEMORY,
Size);
}
VOID
RtlpFreeAtomTable(PRTL_ATOM_TABLE AtomTable)
{
RtlFreeHeap(RtlGetProcessHeap(),
0,
AtomTable);
}
PRTL_ATOM_TABLE_ENTRY
RtlpAllocAtomTableEntry(ULONG Size)
{
return (PRTL_ATOM_TABLE_ENTRY)RtlAllocateHeap(RtlGetProcessHeap(),
HEAP_ZERO_MEMORY,
Size);
}
VOID
RtlpFreeAtomTableEntry(PRTL_ATOM_TABLE_ENTRY Entry)
{
RtlFreeHeap(RtlGetProcessHeap(),
0,
Entry);
}
VOID
RtlpFreeAtomHandle(PRTL_ATOM_TABLE AtomTable, PRTL_ATOM_TABLE_ENTRY Entry)
{
PRTL_HANDLE_TABLE_ENTRY RtlHandleEntry;
if (RtlIsValidIndexHandle(&AtomTable->RtlHandleTable,
&RtlHandleEntry,
(ULONG)Entry->HandleIndex))
{
RtlFreeHandle(&AtomTable->RtlHandleTable,
RtlHandleEntry);
}
}
BOOLEAN
RtlpCreateAtomHandle(PRTL_ATOM_TABLE AtomTable, PRTL_ATOM_TABLE_ENTRY Entry)
{
ULONG HandleIndex;
PRTL_HANDLE_TABLE_ENTRY RtlHandle;
RtlHandle = RtlAllocateHandle(&AtomTable->RtlHandleTable,
&HandleIndex);
if (RtlHandle != NULL)
{
PRTL_ATOM_HANDLE AtomHandle = (PRTL_ATOM_HANDLE)RtlHandle;
/* FIXME - Handle Indexes >= 0xC000 ?! */
if (HandleIndex < 0xC000)
{
Entry->HandleIndex = (USHORT)HandleIndex;
Entry->Atom = 0xC000 + (USHORT)HandleIndex;
AtomHandle->AtomEntry = Entry;
AtomHandle->Handle.Flags = RTL_HANDLE_VALID;
return TRUE;
}
else
{
/* set the valid flag, otherwise RtlFreeHandle will fail! */
AtomHandle->Handle.Flags = RTL_HANDLE_VALID;
RtlFreeHandle(&AtomTable->RtlHandleTable,
RtlHandle);
}
}
return FALSE;
}
PRTL_ATOM_TABLE_ENTRY
RtlpGetAtomEntry(PRTL_ATOM_TABLE AtomTable, ULONG Index)
{
PRTL_HANDLE_TABLE_ENTRY RtlHandle;
if (RtlIsValidIndexHandle(&AtomTable->RtlHandleTable,
&RtlHandle,
Index))
{
PRTL_ATOM_HANDLE AtomHandle = (PRTL_ATOM_HANDLE)RtlHandle;
return AtomHandle->AtomEntry;
}
return NULL;
}

732
reactos/lib/rtl/atom.c Normal file
View file

@ -0,0 +1,732 @@
/* $Id$
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: lib/rtl/atom.c
* PURPOSE: Atom managment
* PROGRAMMER: Nobody
* UPDATE HISTORY:
* Created 22/05/98
*/
/* INCLUDES *****************************************************************/
#include "rtl.h"
#define NDEBUG
#include <debug.h>
/* PROTOTYPES ****************************************************************/
extern NTSTATUS RtlpInitAtomTableLock(PRTL_ATOM_TABLE AtomTable);
extern VOID RtlpDestroyAtomTableLock(PRTL_ATOM_TABLE AtomTable);
extern BOOLEAN RtlpLockAtomTable(PRTL_ATOM_TABLE AtomTable);
extern VOID RtlpUnlockAtomTable(PRTL_ATOM_TABLE AtomTable);
extern BOOLEAN RtlpCreateAtomHandleTable(PRTL_ATOM_TABLE AtomTable);
extern VOID RtlpDestroyAtomHandleTable(PRTL_ATOM_TABLE AtomTable);
extern PRTL_ATOM_TABLE RtlpAllocAtomTable(ULONG Size);
extern VOID RtlpFreeAtomTable(PRTL_ATOM_TABLE AtomTable);
extern PRTL_ATOM_TABLE_ENTRY RtlpAllocAtomTableEntry(ULONG Size);
extern VOID RtlpFreeAtomTableEntry(PRTL_ATOM_TABLE_ENTRY Entry);
extern BOOLEAN RtlpCreateAtomHandle(PRTL_ATOM_TABLE AtomTable, PRTL_ATOM_TABLE_ENTRY Entry);
extern VOID RtlpFreeAtomHandle(PRTL_ATOM_TABLE AtomTable, PRTL_ATOM_TABLE_ENTRY Entry);
extern PRTL_ATOM_TABLE_ENTRY RtlpGetAtomEntry(PRTL_ATOM_TABLE AtomTable, ULONG Index);
/* FUNCTIONS *****************************************************************/
static PRTL_ATOM_TABLE_ENTRY
RtlpHashAtomName(IN PRTL_ATOM_TABLE AtomTable,
IN PWSTR AtomName,
OUT PRTL_ATOM_TABLE_ENTRY **HashLink)
{
UNICODE_STRING Name;
ULONG Hash;
RtlInitUnicodeString(&Name,
AtomName);
if (Name.Length != 0 &&
NT_SUCCESS(RtlHashUnicodeString(&Name,
TRUE,
HASH_STRING_ALGORITHM_X65599,
&Hash)))
{
PRTL_ATOM_TABLE_ENTRY Current;
PRTL_ATOM_TABLE_ENTRY *Link;
Link = &AtomTable->Buckets[Hash % AtomTable->NumberOfBuckets];
/* search for an existing entry */
Current = *Link;
while (Current != NULL)
{
if (Current->NameLength == Name.Length / sizeof(WCHAR) &&
!_wcsicmp(Current->Name, Name.Buffer))
{
*HashLink = Link;
return Current;
}
Link = &Current->HashLink;
Current = Current->HashLink;
}
/* no matching atom found, return the hash link */
*HashLink = Link;
}
else
*HashLink = NULL;
return NULL;
}
static BOOLEAN
RtlpCheckIntegerAtom(PWSTR AtomName,
PUSHORT AtomValue)
{
UNICODE_STRING AtomString;
ULONG LongValue;
USHORT LoValue;
PWCHAR p;
DPRINT("RtlpCheckIntegerAtom(AtomName '%S' AtomValue %p)\n",
AtomName, AtomValue);
if (!((ULONG)AtomName & 0xFFFF0000))
{
LoValue = (USHORT)((ULONG)AtomName & 0xFFFF);
if (LoValue >= 0xC000)
return FALSE;
if (LoValue == 0)
LoValue = 0xC000;
if (AtomValue != NULL)
*AtomValue = LoValue;
return TRUE;
}
if (*AtomName != L'#')
return FALSE;
p = AtomName;
p++;
while (*p)
{
if ((*p < L'0') || (*p > L'9'))
return FALSE;
p++;
}
p = AtomName;
p++;
RtlInitUnicodeString(&AtomString,
p);
DPRINT("AtomString: %wZ\n", &AtomString);
RtlUnicodeStringToInteger(&AtomString,10, &LongValue);
DPRINT("LongValue: %lu\n", LongValue);
*AtomValue = (USHORT)(LongValue & 0x0000FFFF);
return TRUE;
}
/*
* @implemented
*/
NTSTATUS STDCALL
RtlCreateAtomTable(IN ULONG TableSize,
IN OUT PRTL_ATOM_TABLE *AtomTable)
{
PRTL_ATOM_TABLE Table;
NTSTATUS Status;
DPRINT("RtlCreateAtomTable(TableSize %lu AtomTable %p)\n",
TableSize, AtomTable);
if (*AtomTable != NULL)
{
return STATUS_SUCCESS;
}
/* allocate atom table */
Table = RtlpAllocAtomTable(((TableSize - 1) * sizeof(PRTL_ATOM_TABLE_ENTRY)) +
sizeof(RTL_ATOM_TABLE));
if (Table == NULL)
{
return STATUS_NO_MEMORY;
}
/* initialize atom table */
Table->NumberOfBuckets = TableSize;
Status = RtlpInitAtomTableLock(Table);
if (!NT_SUCCESS(Status))
{
RtlpFreeAtomTable(Table);
return Status;
}
if (!RtlpCreateAtomHandleTable(Table))
{
RtlpDestroyAtomTableLock(Table);
RtlpFreeAtomTable(Table);
return STATUS_NO_MEMORY;
}
*AtomTable = Table;
return STATUS_SUCCESS;
}
/*
* @implemented
*/
NTSTATUS STDCALL
RtlDestroyAtomTable(IN PRTL_ATOM_TABLE AtomTable)
{
PRTL_ATOM_TABLE_ENTRY *CurrentBucket, *LastBucket;
PRTL_ATOM_TABLE_ENTRY CurrentEntry, NextEntry;
DPRINT("RtlDestroyAtomTable (AtomTable %p)\n", AtomTable);
if (!RtlpLockAtomTable(AtomTable))
{
return (STATUS_INVALID_PARAMETER);
}
/* delete all atoms */
LastBucket = AtomTable->Buckets + AtomTable->NumberOfBuckets;
for (CurrentBucket = AtomTable->Buckets;
CurrentBucket != LastBucket;
CurrentBucket++)
{
NextEntry = *CurrentBucket;
*CurrentBucket = NULL;
while (NextEntry != NULL)
{
CurrentEntry = NextEntry;
NextEntry = NextEntry->HashLink;
/* no need to delete the atom handle, the handles will all be freed
up when destroying the atom handle table! */
RtlpFreeAtomTableEntry(CurrentEntry);
}
}
RtlpDestroyAtomHandleTable(AtomTable);
RtlpUnlockAtomTable(AtomTable);
RtlpDestroyAtomTableLock(AtomTable);
RtlpFreeAtomTable(AtomTable);
return STATUS_SUCCESS;
}
/*
* @implemented
*/
NTSTATUS STDCALL
RtlEmptyAtomTable(PRTL_ATOM_TABLE AtomTable,
BOOLEAN DeletePinned)
{
PRTL_ATOM_TABLE_ENTRY *CurrentBucket, *LastBucket;
PRTL_ATOM_TABLE_ENTRY CurrentEntry, NextEntry;
DPRINT("RtlEmptyAtomTable (AtomTable %p DeletePinned %x)\n",
AtomTable, DeletePinned);
if (RtlpLockAtomTable(AtomTable) == FALSE)
{
return (STATUS_INVALID_PARAMETER);
}
/* delete all atoms */
LastBucket = AtomTable->Buckets + AtomTable->NumberOfBuckets;
for (CurrentBucket = AtomTable->Buckets;
CurrentBucket != LastBucket;
CurrentBucket++)
{
NextEntry = *CurrentBucket;
*CurrentBucket = NULL;
while (NextEntry != NULL)
{
CurrentEntry = NextEntry;
NextEntry = NextEntry->HashLink;
RtlpFreeAtomHandle(AtomTable,
CurrentEntry);
RtlpFreeAtomTableEntry(CurrentEntry);
}
}
RtlpUnlockAtomTable(AtomTable);
return STATUS_SUCCESS;
}
/*
* @implemented
*/
NTSTATUS STDCALL
RtlAddAtomToAtomTable(IN PRTL_ATOM_TABLE AtomTable,
IN PWSTR AtomName,
OUT PRTL_ATOM Atom)
{
USHORT AtomValue;
PRTL_ATOM_TABLE_ENTRY *HashLink;
PRTL_ATOM_TABLE_ENTRY Entry = NULL;
NTSTATUS Status = STATUS_SUCCESS;
DPRINT("RtlAddAtomToAtomTable (AtomTable %p AtomName %S Atom %p)\n",
AtomTable, AtomName, Atom);
if (RtlpCheckIntegerAtom (AtomName, &AtomValue))
{
/* integer atom */
if (AtomValue >= 0xC000)
{
Status = STATUS_INVALID_PARAMETER;
}
else if (Atom != NULL)
{
*Atom = (RTL_ATOM)AtomValue;
}
return Status;
}
RtlpLockAtomTable(AtomTable);
/* string atom, hash it and try to find an existing atom with the same name */
Entry = RtlpHashAtomName(AtomTable,
AtomName,
&HashLink);
if (Entry != NULL)
{
/* found another atom, increment the reference counter unless it's pinned */
if (!(Entry->Flags & RTL_ATOM_IS_PINNED))
{
if (++Entry->ReferenceCount == 0)
{
/* FIXME - references overflowed, pin the atom? */
Entry->Flags |= RTL_ATOM_IS_PINNED;
}
}
if (Atom != NULL)
{
*Atom = (RTL_ATOM)Entry->Atom;
}
}
else
{
/* couldn't find an existing atom, HashLink now points to either the
HashLink pointer of the previous atom or to the bucket so we can
simply add it to the list */
if (HashLink != NULL)
{
ULONG AtomNameLen = wcslen(AtomName);
Entry = RtlpAllocAtomTableEntry(sizeof(RTL_ATOM_TABLE_ENTRY) -
sizeof(Entry->Name) +
(AtomNameLen + 1) * sizeof(WCHAR));
if (Entry != NULL)
{
Entry->HashLink = NULL;
Entry->ReferenceCount = 0;
Entry->Flags = 0x0;
Entry->NameLength = AtomNameLen;
RtlCopyMemory(Entry->Name,
AtomName,
(AtomNameLen + 1) * sizeof(WCHAR));
if (RtlpCreateAtomHandle(AtomTable,
Entry))
{
/* append the atom to the list */
*HashLink = Entry;
if (Atom != NULL)
{
*Atom = (RTL_ATOM)Entry->Atom;
}
}
else
{
RtlpFreeAtomTableEntry(Entry);
Status = STATUS_NO_MEMORY;
}
}
else
{
Status = STATUS_NO_MEMORY;
}
}
else
{
/* The caller supplied an empty atom name! */
Status = STATUS_INVALID_PARAMETER;
}
}
RtlpUnlockAtomTable(AtomTable);
return Status;
}
/*
* @implemented
*/
NTSTATUS STDCALL
RtlDeleteAtomFromAtomTable(IN PRTL_ATOM_TABLE AtomTable,
IN RTL_ATOM Atom)
{
PRTL_ATOM_TABLE_ENTRY Entry;
NTSTATUS Status = STATUS_SUCCESS;
DPRINT("RtlDeleteAtomFromAtomTable (AtomTable %p Atom %x)\n",
AtomTable, Atom);
if (Atom >= 0xC000)
{
RtlpLockAtomTable(AtomTable);
Entry = RtlpGetAtomEntry(AtomTable,
(ULONG)((USHORT)Atom - 0xC000));
if (Entry != NULL && Entry->Atom == (USHORT)Atom)
{
if (!(Entry->Flags & RTL_ATOM_IS_PINNED))
{
if (--Entry->ReferenceCount == 0)
{
PRTL_ATOM_TABLE_ENTRY *HashLink;
/* it's time to delete the atom. we need to unlink it from
the list. The easiest way is to take the atom name and
hash it again, this way we get the pointer to either
the hash bucket or the previous atom that links to the
one we want to delete. This way we can easily bypass
this item. */
if (RtlpHashAtomName(AtomTable,
Entry->Name,
&HashLink) != NULL)
{
/* bypass this atom */
*HashLink = Entry->HashLink;
RtlpFreeAtomHandle(AtomTable,
Entry);
RtlpFreeAtomTableEntry(Entry);
}
else
{
/* WTF?! This should never happen!!! */
ASSERT(FALSE);
}
}
}
else
{
/* tried to delete a pinned atom, do nothing and return
STATUS_WAS_LOCKED, which is NOT a failure code! */
Status = STATUS_WAS_LOCKED;
}
}
else
{
Status = STATUS_INVALID_HANDLE;
}
RtlpUnlockAtomTable(AtomTable);
}
return Status;
}
/*
* @implemented
*/
NTSTATUS STDCALL
RtlLookupAtomInAtomTable(IN PRTL_ATOM_TABLE AtomTable,
IN PWSTR AtomName,
OUT PRTL_ATOM Atom)
{
PRTL_ATOM_TABLE_ENTRY Entry, *HashLink;
USHORT AtomValue;
RTL_ATOM FoundAtom = 0;
NTSTATUS Status = STATUS_SUCCESS;
DPRINT("RtlLookupAtomInAtomTable (AtomTable %p AtomName %S Atom %p)\n",
AtomTable, AtomName, Atom);
if (RtlpCheckIntegerAtom (AtomName, &AtomValue))
{
/* integer atom */
if (AtomValue >= 0xC000)
{
Status = STATUS_INVALID_PARAMETER;
}
else if (Atom != NULL)
{
*Atom = (RTL_ATOM)AtomValue;
}
return Status;
}
RtlpLockAtomTable(AtomTable);
Status = STATUS_OBJECT_NAME_NOT_FOUND;
/* string atom */
Entry = RtlpHashAtomName(AtomTable,
AtomName,
&HashLink);
if (Entry != NULL)
{
Status = STATUS_SUCCESS;
FoundAtom = (RTL_ATOM)Entry->Atom;
}
RtlpUnlockAtomTable(AtomTable);
if (NT_SUCCESS(Status) && Atom != NULL)
{
*Atom = FoundAtom;
}
return Status;
}
/*
* @implemented
*/
NTSTATUS STDCALL
RtlPinAtomInAtomTable(IN PRTL_ATOM_TABLE AtomTable,
IN RTL_ATOM Atom)
{
NTSTATUS Status = STATUS_SUCCESS;
DPRINT("RtlPinAtomInAtomTable (AtomTable %p Atom %x)\n",
AtomTable, Atom);
if (Atom >= 0xC000)
{
PRTL_ATOM_TABLE_ENTRY Entry;
RtlpLockAtomTable(AtomTable);
Entry = RtlpGetAtomEntry(AtomTable,
(ULONG)((USHORT)Atom - 0xC000));
if (Entry != NULL && Entry->Atom == (USHORT)Atom)
{
Entry->Flags |= RTL_ATOM_IS_PINNED;
}
else
{
Status = STATUS_INVALID_HANDLE;
}
RtlpUnlockAtomTable(AtomTable);
}
RtlpLockAtomTable(AtomTable);
return Status;
}
/*
* @implemented
*/
NTSTATUS STDCALL
RtlQueryAtomInAtomTable(PRTL_ATOM_TABLE AtomTable,
RTL_ATOM Atom,
PULONG RefCount,
PULONG PinCount,
PWSTR AtomName,
PULONG NameLength)
{
ULONG Length;
PRTL_ATOM_TABLE_ENTRY Entry;
NTSTATUS Status = STATUS_SUCCESS;
if (Atom < 0xC000)
{
if (RefCount != NULL)
{
*RefCount = 1;
}
if (PinCount != NULL)
{
*PinCount = 1;
}
if ((AtomName != NULL) && (NameLength != NULL) && (NameLength > 0))
{
WCHAR NameString[12];
Length = swprintf(NameString, L"#%lu", (ULONG)Atom) * sizeof(WCHAR);
if (*NameLength < Length + sizeof(WCHAR))
{
/* prevent underflow! */
if (*NameLength >= sizeof(WCHAR))
{
Length = *NameLength - sizeof(WCHAR);
}
else
{
Length = 0;
Status = STATUS_BUFFER_TOO_SMALL;
}
}
if (Length)
{
RtlCopyMemory(AtomName,
NameString,
Length);
AtomName[Length / sizeof(WCHAR)] = L'\0';
*NameLength = Length;
}
}
return Status;
}
RtlpLockAtomTable(AtomTable);
Entry = RtlpGetAtomEntry(AtomTable,
(ULONG)((USHORT)Atom - 0xC000));
if (Entry != NULL && Entry->Atom == (USHORT)Atom)
{
DPRINT("Atom name: %wZ\n", &Entry->Name);
if (RefCount != NULL)
{
*RefCount = Entry->ReferenceCount;
}
if (PinCount != NULL)
{
*PinCount = ((Entry->Flags & RTL_ATOM_IS_PINNED) != 0);
}
if ((AtomName != NULL) && (NameLength != NULL))
{
Length = Entry->NameLength * sizeof(WCHAR);
if (*NameLength < Length + sizeof(WCHAR))
{
/* prevent underflow! */
if (*NameLength >= sizeof(WCHAR))
{
Length = *NameLength - sizeof(WCHAR);
}
else
{
Length = 0;
Status = STATUS_BUFFER_TOO_SMALL;
}
}
if (Length)
{
RtlCopyMemory(AtomName,
Entry->Name,
Length);
AtomName[Length / sizeof(WCHAR)] = L'\0';
*NameLength = Length;
}
}
}
else
{
Status = STATUS_INVALID_HANDLE;
}
RtlpUnlockAtomTable(AtomTable);
return Status;
}
/*
* @private - only used by NtQueryInformationAtom
*/
NTSTATUS STDCALL
RtlQueryAtomListInAtomTable(IN PRTL_ATOM_TABLE AtomTable,
IN ULONG MaxAtomCount,
OUT ULONG *AtomCount,
OUT RTL_ATOM *AtomList)
{
PRTL_ATOM_TABLE_ENTRY *CurrentBucket, *LastBucket;
PRTL_ATOM_TABLE_ENTRY CurrentEntry;
ULONG Atoms = 0;
NTSTATUS Status = STATUS_SUCCESS;
RtlpLockAtomTable(AtomTable);
LastBucket = AtomTable->Buckets + AtomTable->NumberOfBuckets;
for (CurrentBucket = AtomTable->Buckets;
CurrentBucket != LastBucket;
CurrentBucket++)
{
CurrentEntry = *CurrentBucket;
while (CurrentEntry != NULL)
{
if (MaxAtomCount > 0)
{
*(AtomList++) = (RTL_ATOM)CurrentEntry->Atom;
MaxAtomCount--;
}
else
{
/* buffer too small, but don't bail. we need to determine the
total number of atoms in the table! */
Status = STATUS_INFO_LENGTH_MISMATCH;
}
Atoms++;
CurrentEntry = CurrentEntry->HashLink;
}
}
*AtomCount = Atoms;
RtlpUnlockAtomTable(AtomTable);
return Status;
}

View file

@ -17,6 +17,7 @@
</directory>
<file>access.c</file>
<file>acl.c</file>
<file>atom.c</file>
<file>bit.c</file>
<file>bitmap.c</file>
<file>bootdata.c</file>

View file

@ -1,26 +0,0 @@
#ifndef __INTERNAL_HANDLE_H
#define __INTERNAL_HANDLE_H
typedef struct _RTL_HANDLE
{
struct _RTL_HANDLE *Next; /* pointer to next free handle */
PVOID Object; /* pointer to object */
} RTL_HANDLE, *PRTL_HANDLE;
typedef struct _RTL_HANDLE_TABLE
{
ULONG TableSize; /* maximum number of handles */
PRTL_HANDLE Handles; /* pointer to handle array */
PRTL_HANDLE Limit; /* limit of pointers */
PRTL_HANDLE FirstFree; /* pointer to first free handle */
PRTL_HANDLE LastUsed; /* pointer to last allocated handle */
} RTL_HANDLE_TABLE, *PRTL_HANDLE_TABLE;
VOID RtlpInitializeHandleTable(ULONG TableSize, PRTL_HANDLE_TABLE HandleTable);
VOID RtlpDestroyHandleTable(PRTL_HANDLE_TABLE HandleTable);
BOOLEAN RtlpAllocateHandle(PRTL_HANDLE_TABLE HandleTable, PVOID Object, PULONG Index);
BOOLEAN RtlpFreeHandle(PRTL_HANDLE_TABLE HandleTable, ULONG Index);
PVOID RtlpMapHandleToPointer(PRTL_HANDLE_TABLE HandleTable, ULONG Index);
#endif /* __INTERNAL_HANDLE_H */

View file

@ -43,7 +43,6 @@
#include <internal/i386/mm.h>
#include <internal/i386/fpu.h>
#include <internal/module.h>
#include <internal/handle.h>
#include <internal/pool.h>
#include <internal/ob.h>
#include <internal/mm.h>

View file

@ -322,7 +322,6 @@
<file>capture.c</file>
<file>ctype.c</file>
<file>debug.c</file>
<file>handle.c</file>
<file>libsupp.c</file>
<file>message.c</file>
<file>misc.c</file>

View file

@ -14,43 +14,27 @@
#define NDEBUG
#include <internal/debug.h>
typedef struct _RTL_ATOM_ENTRY
{
LIST_ENTRY List;
UNICODE_STRING Name;
ULONG RefCount;
BOOLEAN Locked;
ULONG Index;
} RTL_ATOM_ENTRY, *PRTL_ATOM_ENTRY;
/* PROTOTYPES ****************************************************************/
static PRTL_ATOM_TABLE RtlpGetGlobalAtomTable(VOID);
static NTSTATUS
RtlpQueryAtomInformation(PRTL_ATOM_TABLE AtomTable,
RTL_ATOM Atom,
PATOM_BASIC_INFORMATION AtomInformation,
ULONG AtomInformationLength,
PULONG ReturnLength);
static NTSTATUS
RtlpQueryAtomTableInformation(PRTL_ATOM_TABLE AtomTable,
RTL_ATOM Atom,
PATOM_TABLE_INFORMATION AtomInformation,
ULONG AtomInformationLength,
PULONG ReturnLength);
static ULONG RtlpHashAtomName(ULONG TableSize, PWSTR AtomName);
static BOOLEAN RtlpCheckIntegerAtom(PWSTR AtomName, PUSHORT AtomValue);
static NTSTATUS RtlpInitAtomTableLock(PRTL_ATOM_TABLE AtomTable);
static VOID RtlpDestroyAtomTableLock(PRTL_ATOM_TABLE AtomTable);
static BOOLEAN RtlpLockAtomTable(PRTL_ATOM_TABLE AtomTable);
static VOID RtlpUnlockAtomTable(PRTL_ATOM_TABLE AtomTable);
static BOOLEAN RtlpCreateAtomHandleTable(PRTL_ATOM_TABLE AtomTable);
static VOID RtlpDestroyAtomHandleTable(PRTL_ATOM_TABLE AtomTable);
static NTSTATUS RtlpQueryAtomInformation(PRTL_ATOM_TABLE AtomTable,
RTL_ATOM Atom,
PATOM_BASIC_INFORMATION AtomInformation,
ULONG AtomInformationLength,
PULONG ReturnLength);
static NTSTATUS RtlpQueryAtomTableInformation(PRTL_ATOM_TABLE AtomTable,
RTL_ATOM Atom,
PATOM_TABLE_INFORMATION AtomInformation,
ULONG AtomInformationLength,
PULONG ReturnLength);
extern NTSTATUS STDCALL
RtlQueryAtomListInAtomTable(IN PRTL_ATOM_TABLE AtomTable,
IN ULONG MaxAtomCount,
OUT ULONG *AtomCount,
OUT RTL_ATOM *AtomList);
/* GLOBALS *******************************************************************/
@ -158,505 +142,6 @@ NtQueryInformationAtom(RTL_ATOM Atom,
}
/*
* @implemented
*/
NTSTATUS STDCALL
RtlCreateAtomTable(ULONG TableSize,
PRTL_ATOM_TABLE *AtomTable)
{
PRTL_ATOM_TABLE Table;
ULONG i;
NTSTATUS Status;
DPRINT("RtlCreateAtomTable(TableSize %lu AtomTable %p)\n",
TableSize, AtomTable);
if (*AtomTable != NULL)
{
return STATUS_SUCCESS;
}
/* allocate atom table */
Table = ExAllocatePool(NonPagedPool,
TableSize * sizeof(RTL_ATOM_ENTRY) +
sizeof(RTL_ATOM_TABLE));
if (Table == NULL)
return STATUS_NO_MEMORY;
/* initialize atom table */
Table->TableSize = TableSize;
Table->NumberOfAtoms = 0;
for (i = 0; i < TableSize; i++)
{
InitializeListHead(&Table->Slot[i]);
}
Status = RtlpInitAtomTableLock(Table);
if (!NT_SUCCESS(Status))
{
ExFreePool(Table);
return Status;
}
if (RtlpCreateAtomHandleTable(Table) == FALSE)
{
RtlpDestroyAtomTableLock(Table);
ExFreePool(Table);
return STATUS_NO_MEMORY;
}
*AtomTable = Table;
return STATUS_SUCCESS;
}
/*
* @implemented
*/
NTSTATUS STDCALL
RtlDestroyAtomTable(IN PRTL_ATOM_TABLE AtomTable)
{
PLIST_ENTRY Current;
PRTL_ATOM_ENTRY AtomEntry;
ULONG i;
if (RtlpLockAtomTable(AtomTable) == FALSE)
{
return (STATUS_INVALID_PARAMETER);
}
/* delete all atoms */
for (i = 0; i < AtomTable->TableSize; i++)
{
Current = AtomTable->Slot[i].Flink;
while (Current != &AtomTable->Slot[i])
{
AtomEntry = (PRTL_ATOM_ENTRY)Current;
RtlFreeUnicodeString(&AtomEntry->Name);
RemoveEntryList(&AtomEntry->List);
ExFreePool(AtomEntry);
Current = AtomTable->Slot[i].Flink;
}
}
RtlpDestroyAtomHandleTable(AtomTable);
RtlpUnlockAtomTable(AtomTable);
RtlpDestroyAtomTableLock(AtomTable);
ExFreePool(AtomTable);
return STATUS_SUCCESS;
}
/*
* @implemented
*/
NTSTATUS STDCALL
RtlEmptyAtomTable(IN PRTL_ATOM_TABLE AtomTable,
IN BOOLEAN DeletePinned)
{
PLIST_ENTRY Current, Next;
PRTL_ATOM_ENTRY AtomEntry;
ULONG i;
DPRINT("RtlEmptyAtomTable (AtomTable %p DeletePinned %x)\n",
AtomTable, DeletePinned);
if (RtlpLockAtomTable(AtomTable) == FALSE)
{
return (STATUS_INVALID_PARAMETER);
}
/* delete all atoms */
for (i = 0; i < AtomTable->TableSize; i++)
{
Current = AtomTable->Slot[i].Flink;
while (Current != &AtomTable->Slot[i])
{
Next = Current->Flink;
AtomEntry = (PRTL_ATOM_ENTRY)Current;
if ((AtomEntry->Locked == FALSE) ||
((AtomEntry->Locked == TRUE) && (DeletePinned == TRUE)))
{
RtlFreeUnicodeString(&AtomEntry->Name);
RtlpFreeHandle(AtomTable->HandleTable,
AtomEntry->Index);
RemoveEntryList(&AtomEntry->List);
ExFreePool(AtomEntry);
}
Current = Next;
}
}
AtomTable->NumberOfAtoms = 0;
RtlpUnlockAtomTable(AtomTable);
return STATUS_SUCCESS;
}
/*
* @implemented
*/
NTSTATUS STDCALL
RtlAddAtomToAtomTable(IN PRTL_ATOM_TABLE AtomTable,
IN PWSTR AtomName,
OUT PRTL_ATOM Atom)
{
ULONG Hash;
PLIST_ENTRY Current;
PRTL_ATOM_ENTRY Entry;
USHORT AtomValue;
NTSTATUS Status;
ULONG AtomIndex;
DPRINT("RtlAddAtomToAtomTable (AtomTable %p AtomName %S Atom %p)\n",
AtomTable, AtomName, Atom);
if (RtlpCheckIntegerAtom (AtomName, &AtomValue))
{
/* integer atom */
if (AtomValue >= 0xC000)
{
AtomValue = 0;
Status = STATUS_INVALID_PARAMETER;
}
else
{
Status = STATUS_SUCCESS;
}
if (Atom)
*Atom = (RTL_ATOM)AtomValue;
return Status;
}
RtlpLockAtomTable(AtomTable);
/* string atom */
Hash = RtlpHashAtomName(AtomTable->TableSize, AtomName);
/* search for existing atom */
Current = AtomTable->Slot[Hash].Flink;
while (Current != &AtomTable->Slot[Hash])
{
Entry = (PRTL_ATOM_ENTRY)Current;
DPRINT("Comparing %S and %S\n", Entry->Name.Buffer, AtomName);
if (_wcsicmp(Entry->Name.Buffer, AtomName) == 0)
{
Entry->RefCount++;
if (Atom)
*Atom = (RTL_ATOM)(Entry->Index + 0xC000);
RtlpUnlockAtomTable(AtomTable);
return STATUS_SUCCESS;
}
Current = Current->Flink;
}
/* insert new atom */
Entry = ExAllocatePool(NonPagedPool,
sizeof(RTL_ATOM_ENTRY));
if (Entry == NULL)
{
RtlpUnlockAtomTable(AtomTable);
return STATUS_NO_MEMORY;
}
InsertTailList(&AtomTable->Slot[Hash], &Entry->List);
RtlpCreateUnicodeString (&Entry->Name,
AtomName, NonPagedPool);
Entry->RefCount = 1;
Entry->Locked = FALSE;
/* FIXME: use general function instead !! */
RtlpAllocateHandle(AtomTable->HandleTable,
(PVOID)Entry,
&AtomIndex);
DPRINT("AtomIndex %x\n", AtomIndex);
Entry->Index = AtomIndex;
AtomTable->NumberOfAtoms++;
if (Atom)
*Atom = (RTL_ATOM)(AtomIndex + 0xC000);
RtlpUnlockAtomTable(AtomTable);
return STATUS_SUCCESS;
}
/*
* @implemented
*/
NTSTATUS STDCALL
RtlDeleteAtomFromAtomTable(IN PRTL_ATOM_TABLE AtomTable,
IN RTL_ATOM Atom)
{
PRTL_ATOM_ENTRY AtomEntry;
DPRINT("RtlDeleteAtomFromAtomTable (AtomTable %p Atom %x)\n",
AtomTable, Atom);
if (Atom < 0xC000)
{
return STATUS_SUCCESS;
}
RtlpLockAtomTable(AtomTable);
/* FIXME: use general function instead !! */
AtomEntry = (PRTL_ATOM_ENTRY)RtlpMapHandleToPointer(AtomTable->HandleTable,
(ULONG)Atom - 0xC000);
if (AtomEntry == NULL)
{
RtlpUnlockAtomTable(AtomTable);
return STATUS_INVALID_HANDLE;
}
DPRINT("AtomEntry %x\n", AtomEntry);
DPRINT("Atom name: %wZ\n", &AtomEntry->Name);
AtomEntry->RefCount--;
if (AtomEntry->RefCount == 0)
{
if (AtomEntry->Locked == TRUE)
{
DPRINT("Atom %wZ is locked!\n", &AtomEntry->Name);
RtlpUnlockAtomTable(AtomTable);
return STATUS_WAS_LOCKED;
}
DPRINT("Removing atom: %wZ\n", &AtomEntry->Name);
RtlFreeUnicodeString(&AtomEntry->Name);
RemoveEntryList(&AtomEntry->List);
ExFreePool(AtomEntry);
RtlpFreeHandle(AtomTable->HandleTable,
(ULONG)Atom - 0xC000);
AtomTable->NumberOfAtoms++;
}
RtlpUnlockAtomTable(AtomTable);
return STATUS_SUCCESS;
}
/*
* @implemented
*/
NTSTATUS STDCALL
RtlLookupAtomInAtomTable(IN PRTL_ATOM_TABLE AtomTable,
IN PWSTR AtomName,
OUT PRTL_ATOM Atom)
{
ULONG Hash;
PLIST_ENTRY Current;
PRTL_ATOM_ENTRY Entry;
USHORT AtomValue;
NTSTATUS Status;
DPRINT("RtlLookupAtomInAtomTable (AtomTable %p AtomName %S Atom %p)\n",
AtomTable, AtomName, Atom);
if (RtlpCheckIntegerAtom (AtomName, &AtomValue))
{
/* integer atom */
if (AtomValue >= 0xC000)
{
AtomValue = 0;
Status = STATUS_INVALID_PARAMETER;
}
else
{
Status = STATUS_SUCCESS;
}
if (Atom)
*Atom = (RTL_ATOM)AtomValue;
return Status;
}
RtlpLockAtomTable(AtomTable);
/* string atom */
Hash = RtlpHashAtomName(AtomTable->TableSize, AtomName);
/* search for existing atom */
Current = AtomTable->Slot[Hash].Flink;
while (Current != &AtomTable->Slot[Hash])
{
Entry = (PRTL_ATOM_ENTRY)Current;
DPRINT("Comparing %S and %S\n", Entry->Name.Buffer, AtomName);
if (_wcsicmp(Entry->Name.Buffer, AtomName) == 0)
{
if (Atom)
*Atom = (RTL_ATOM)(Entry->Index + 0xC000);
RtlpUnlockAtomTable(AtomTable);
return STATUS_SUCCESS;
}
Current = Current->Flink;
}
return STATUS_OBJECT_NAME_NOT_FOUND;
}
/*
* @unimplemented
*/
NTSTATUS STDCALL
RtlPinAtomInAtomTable(IN PRTL_ATOM_TABLE AtomTable,
IN RTL_ATOM Atom)
{
PRTL_ATOM_ENTRY AtomEntry;
DPRINT("RtlPinAtomInAtomTable (AtomTable %p Atom %x)\n",
AtomTable, Atom);
if (Atom < 0xC000)
{
return STATUS_SUCCESS;
}
RtlpLockAtomTable(AtomTable);
/* FIXME: use general function instead !! */
AtomEntry = (PRTL_ATOM_ENTRY)RtlpMapHandleToPointer(AtomTable->HandleTable,
(ULONG)Atom - 0xC000);
if (AtomEntry == NULL)
{
RtlpUnlockAtomTable(AtomTable);
return STATUS_INVALID_HANDLE;
}
DPRINT("AtomEntry %x\n", AtomEntry);
DPRINT("Atom name: %wZ\n", &AtomEntry->Name);
AtomEntry->Locked = TRUE;
RtlpUnlockAtomTable(AtomTable);
return STATUS_SUCCESS;
}
/*
* @implemented
*/
NTSTATUS STDCALL
RtlQueryAtomInAtomTable(IN PRTL_ATOM_TABLE AtomTable,
IN RTL_ATOM Atom,
IN OUT PULONG RefCount,
IN OUT PULONG PinCount,
IN OUT PWSTR AtomName,
IN OUT PULONG NameLength)
{
ULONG Length;
PRTL_ATOM_ENTRY AtomEntry;
WCHAR TempAtomName[12];
if (Atom == 0)
{
return STATUS_INVALID_HANDLE;
}
if (Atom < 0xC000)
{
if (RefCount != NULL)
{
*RefCount = 1;
}
if (PinCount != NULL)
{
*PinCount = 1;
}
Length = swprintf(TempAtomName, L"#%lu", (ULONG)Atom);
if (NameLength != NULL)
{
*NameLength = Length * sizeof(WCHAR);
if (AtomName != NULL && *NameLength >= Length)
{
wcscpy(AtomName, TempAtomName);
}
else
{
return STATUS_BUFFER_TOO_SMALL;
}
}
return STATUS_SUCCESS;
}
RtlpLockAtomTable(AtomTable);
/* FIXME: use general function instead !! */
AtomEntry = (PRTL_ATOM_ENTRY)RtlpMapHandleToPointer(AtomTable->HandleTable,
(ULONG)Atom - 0xC000);
if (AtomEntry == NULL)
{
RtlpUnlockAtomTable(AtomTable);
return STATUS_INVALID_HANDLE;
}
DPRINT("AtomEntry %x\n", AtomEntry);
DPRINT("Atom name: %wZ\n", &AtomEntry->Name);
if (RefCount != NULL)
{
*RefCount = AtomEntry->RefCount;
}
if (PinCount != NULL)
{
*PinCount = (ULONG)AtomEntry->Locked;
}
if (NameLength != NULL)
{
if (AtomName != NULL && *NameLength >= AtomEntry->Name.Length)
{
*NameLength = AtomEntry->Name.Length;
memcpy(AtomName, AtomEntry->Name.Buffer, AtomEntry->Name.Length);
}
else
{
*NameLength = AtomEntry->Name.Length;
RtlpUnlockAtomTable(AtomTable);
return STATUS_BUFFER_TOO_SMALL;
}
}
RtlpUnlockAtomTable(AtomTable);
return STATUS_SUCCESS;
}
/* INTERNAL FUNCTIONS ********************************************************/
static PRTL_ATOM_TABLE
@ -674,199 +159,6 @@ RtlpGetGlobalAtomTable(VOID)
return GlobalAtomTable;
}
static ULONG
RtlpHashAtomName(ULONG TableSize,
PWSTR AtomName)
{
ULONG q = 0;
PWCHAR p;
DPRINT("RtlpHashAtomName(TableSize %ld AtomName '%S')\n",
TableSize, AtomName);
/* convert the string to an internal representation */
p = AtomName;
while (*p != 0)
{
q += (ULONG)towupper(*p);
p++;
}
DPRINT("q %lu Hash %lu\n", q, q % TableSize);
return (q % TableSize);
}
static BOOLEAN
RtlpCheckIntegerAtom(PWSTR AtomName,
PUSHORT AtomValue)
{
UNICODE_STRING AtomString;
ULONG LongValue;
USHORT LoValue;
PWCHAR p;
DPRINT("RtlpCheckIntegerAtom(AtomName '%S' AtomValue %p)\n",
AtomName, AtomValue);
if (!((ULONG)AtomName & 0xFFFF0000))
{
LoValue = (USHORT)((ULONG)AtomName & 0xFFFF);
if (LoValue >= 0xC000)
return FALSE;
if (LoValue == 0)
LoValue = 0xC000;
if (AtomValue != NULL)
*AtomValue = LoValue;
return TRUE;
}
if (*AtomName != L'#')
return FALSE;
p = AtomName;
p++;
while (*p)
{
if ((*p < L'0') || (*p > L'9'))
return FALSE;
p++;
}
p = AtomName;
p++;
RtlInitUnicodeString(&AtomString,
p);
DPRINT("AtomString: %wZ\n", &AtomString);
RtlUnicodeStringToInteger(&AtomString,10, &LongValue);
DPRINT("LongValue: %lu\n", LongValue);
*AtomValue = (USHORT)(LongValue & 0x0000FFFF);
return TRUE;
}
/* lock functions */
static NTSTATUS
RtlpInitAtomTableLock(PRTL_ATOM_TABLE AtomTable)
{
AtomTable->Lock = ExAllocatePool(NonPagedPool,
sizeof(FAST_MUTEX));
if (AtomTable->Lock == NULL)
return STATUS_NO_MEMORY;
ExInitializeFastMutex((PFAST_MUTEX)AtomTable->Lock);
return STATUS_SUCCESS;
}
static VOID
RtlpDestroyAtomTableLock(PRTL_ATOM_TABLE AtomTable)
{
if (AtomTable->Lock)
ExFreePool(AtomTable->Lock);
}
static BOOLEAN
RtlpLockAtomTable(PRTL_ATOM_TABLE AtomTable)
{
// ExAcquireFastMutex((PFAST_MUTEX)AtomTable->Lock);
return TRUE;
}
static VOID
RtlpUnlockAtomTable(PRTL_ATOM_TABLE AtomTable)
{
// ExReleaseFastMutex((PFAST_MUTEX)AtomTable->Lock);
}
#if 0
static NTSTATUS
RtlpInitAtomTableLock(PRTL_ATOM_TABLE AtomTable)
{
AtomTable->Lock = RtlAllocateHeap(RtlGetProcessHeap(),
HEAP_ZERO_MEMORY,
sizeof(CRITICAL_SECTION));
if (AtomTable->Lock == NULL)
return STATUS_NO_MEMORY;
RtlInitializeCriticalSection((PCRITICAL_SECTION)AtomTable->Lock);
return STATUS_SUCCESS;
}
static VOID
RtlpDestroyAtomTableLock(PRTL_ATOM_TABLE AtomTable)
{
if (AtomTable->Lock)
{
RtlDeleteCriticalSection((PCRITICAL_SECTION)AtomTable->Lock);
RtlFreeHeap(RtlGetProcessHeap(),
0,
AtomTable->Lock);
AtomTable->Lock = NULL;
}
}
static BOOLEAN
RtlpLockAtomTable(PRTL_ATOM_TABLE AtomTable)
{
RtlEnterCriticalSection((PCRITICAL_SECTION)AtomTable->Lock);
return TRUE;
}
static VOID
RtlpUnlockAtomTable(PRTL_ATOM_TABLE AtomTable)
{
RtlLeaveCriticalSection((PCRITICAL_SECTION)AtomTable->Lock);
}
#endif
/* handle functions */
static BOOLEAN
RtlpCreateAtomHandleTable(PRTL_ATOM_TABLE AtomTable)
{
AtomTable->HandleTable = ExAllocatePool(NonPagedPool,
sizeof(RTL_HANDLE_TABLE));
if (AtomTable->HandleTable == NULL)
return FALSE;
RtlpInitializeHandleTable(0xCFFF,
(PRTL_HANDLE_TABLE)AtomTable->HandleTable);
return TRUE;
}
static VOID
RtlpDestroyAtomHandleTable(PRTL_ATOM_TABLE AtomTable)
{
if (AtomTable->HandleTable)
{
RtlpDestroyHandleTable((PRTL_HANDLE_TABLE)AtomTable->HandleTable);
ExFreePool(AtomTable->HandleTable);
AtomTable->HandleTable = NULL;
}
}
static NTSTATUS
RtlpQueryAtomInformation(PRTL_ATOM_TABLE AtomTable,
RTL_ATOM Atom,
@ -901,7 +193,7 @@ RtlpQueryAtomInformation(PRTL_ATOM_TABLE AtomTable,
if (NameLength + sizeof(ATOM_BASIC_INFORMATION) > AtomInformationLength)
{
return STATUS_BUFFER_TOO_SMALL;
return STATUS_INFO_LENGTH_MISMATCH;
}
AtomInformation->UsageCount = (USHORT)UsageCount;
@ -919,16 +211,10 @@ RtlpQueryAtomTableInformation(PRTL_ATOM_TABLE AtomTable,
ULONG AtomInformationLength,
PULONG ReturnLength)
{
PLIST_ENTRY Current, Next;
PRTL_ATOM_ENTRY AtomEntry;
ULONG Length;
ULONG i, j;
NTSTATUS Status;
Length = sizeof(ATOM_TABLE_INFORMATION);
if (AtomTable->NumberOfAtoms > 1)
{
Length += ((AtomTable->NumberOfAtoms - 1)* sizeof(RTL_ATOM));
}
DPRINT("RequiredLength: %lu\n", Length);
@ -939,28 +225,24 @@ RtlpQueryAtomTableInformation(PRTL_ATOM_TABLE AtomTable,
if (Length > AtomInformationLength)
{
return STATUS_BUFFER_TOO_SMALL;
return STATUS_INFO_LENGTH_MISMATCH;
}
AtomInformation->NumberOfAtoms = AtomTable->NumberOfAtoms;
j = 0;
for (i = 0; i < AtomTable->TableSize; i++)
Status = RtlQueryAtomListInAtomTable(AtomTable,
(AtomInformationLength - Length) / sizeof(RTL_ATOM),
&AtomInformation->NumberOfAtoms,
AtomInformation->Atoms);
if (NT_SUCCESS(Status))
{
Current = AtomTable->Slot[i].Flink;
while (Current != &AtomTable->Slot[i])
{
Next = Current->Flink;
AtomEntry = (PRTL_ATOM_ENTRY)Current;
AtomInformation->Atoms[j] = AtomEntry->Index + 0xC000;
j++;
Current = Next;
}
ReturnLength += AtomInformation->NumberOfAtoms * sizeof(RTL_ATOM);
if (ReturnLength != NULL)
{
*ReturnLength = Length;
}
}
return STATUS_SUCCESS;
return Status;
}
/* EOF */

View file

@ -1,180 +0,0 @@
/* $Id$
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/rtl/handle.c
* PURPOSE: Handle table
*
* PROGRAMMERS: Eric Kohl <ekohl@rz-online.de>
*/
/* INCLUDES ******************************************************************/
#include <ntoskrnl.h>
#define NDEBUG
#include <internal/debug.h>
static BOOLEAN
RtlpIsValidHandle(PRTL_HANDLE_TABLE HandleTable, PRTL_HANDLE Handle);
static BOOLEAN
RtlpIsValidIndexHandle(PRTL_HANDLE_TABLE HandleTable, PRTL_HANDLE *Handle, ULONG Index);
/* FUNCTIONS *****************************************************************/
VOID
RtlpInitializeHandleTable(ULONG TableSize,
PRTL_HANDLE_TABLE HandleTable)
{
/* initialize handle table */
memset(HandleTable,
0,
sizeof(RTL_HANDLE_TABLE));
HandleTable->TableSize = TableSize;
}
VOID
RtlpDestroyHandleTable(PRTL_HANDLE_TABLE HandleTable)
{
ExFreePool((PVOID)HandleTable->Handles);
}
BOOLEAN
RtlpAllocateHandle(PRTL_HANDLE_TABLE HandleTable,
PVOID Object,
PULONG Index)
{
RTL_HANDLE **pp_new,**pph,*ph;
PRTL_HANDLE retval;
PVOID ArrayPointer;
ULONG ArraySize;
if (Index == NULL)
return FALSE;
pp_new = &HandleTable->FirstFree;
if (HandleTable->FirstFree == NULL)
{
/* no free handle available */
if (HandleTable->LastUsed == NULL)
{
/* allocate handle array */
ArraySize = sizeof(RTL_HANDLE) * HandleTable->TableSize;
ArrayPointer = ExAllocatePoolWithTag(PagedPool,
ArraySize,
TAG_HDTB);
if (ArrayPointer == NULL)
return FALSE;
/* update handle array pointers */
HandleTable->Handles = (PRTL_HANDLE)ArrayPointer;
HandleTable->Limit = (PRTL_HANDLE)((char*)ArrayPointer + ArraySize);
HandleTable->LastUsed = (PRTL_HANDLE)ArrayPointer;
}
/* build free list in handle array */
ph = HandleTable->LastUsed;
pph = pp_new;
while (ph < HandleTable->Limit)
{
*pph = ph;
pph = &ph->Next;
ph = (PRTL_HANDLE)((ULONG)ph + sizeof(RTL_HANDLE));
}
*pph = 0;
}
/* remove handle from free list */
retval = *pp_new;
*pp_new = retval->Next;
retval->Next = NULL;
retval->Object = Object;
*Index = ((ULONG)retval - (ULONG)HandleTable->Handles) / sizeof(RTL_HANDLE);
return TRUE;
}
BOOLEAN
RtlpFreeHandle(PRTL_HANDLE_TABLE HandleTable,
ULONG Index)
{
PRTL_HANDLE Handle;
/* check if handle is valid */
if (! RtlpIsValidIndexHandle(HandleTable,
&Handle,
Index))
return FALSE;
/* clear handle */
memset(Handle, 0, sizeof(RTL_HANDLE));
/* add handle to free list */
Handle->Next = HandleTable->FirstFree;
HandleTable->FirstFree = Handle;
return TRUE;
}
static BOOLEAN
RtlpIsValidHandle(PRTL_HANDLE_TABLE HandleTable,
PRTL_HANDLE Handle)
{
if ((HandleTable != NULL)
&& (Handle != NULL)
&& (Handle >= HandleTable->Handles)
&& (Handle < HandleTable->Limit))
return TRUE;
return FALSE;
}
static BOOLEAN
RtlpIsValidIndexHandle(PRTL_HANDLE_TABLE HandleTable,
PRTL_HANDLE *Handle,
ULONG Index)
{
PRTL_HANDLE InternalHandle;
DPRINT("RtlpIsValidIndexHandle(HandleTable %p Handle %p Index %x)\n", HandleTable, Handle, Index);
if (HandleTable == NULL)
return FALSE;
DPRINT("Handles %p\n", HandleTable->Handles);
InternalHandle = (PRTL_HANDLE)((ULONG)HandleTable->Handles + sizeof(RTL_HANDLE) * Index);
if (RtlpIsValidHandle(HandleTable, InternalHandle) == FALSE)
return FALSE;
DPRINT("InternalHandle %p\n", InternalHandle);
if (Handle != NULL)
*Handle = InternalHandle;
return TRUE;
}
PVOID
RtlpMapHandleToPointer(PRTL_HANDLE_TABLE HandleTable,
ULONG Index)
{
PRTL_HANDLE Handle;
if (!RtlpIsValidIndexHandle(HandleTable,
&Handle,
Index))
{
return NULL;
}
return Handle->Object;
}
/* EOF */

View file

@ -130,4 +130,159 @@ CHECK_PAGED_CODE_RTL(char *file, int line)
}
#endif
/* RTL Atom Tables ************************************************************/
NTSTATUS
RtlpInitAtomTableLock(PRTL_ATOM_TABLE AtomTable)
{
ExInitializeFastMutex(&AtomTable->FastMutex);
return STATUS_SUCCESS;
}
VOID
RtlpDestroyAtomTableLock(PRTL_ATOM_TABLE AtomTable)
{
}
BOOLEAN
RtlpLockAtomTable(PRTL_ATOM_TABLE AtomTable)
{
ExAcquireFastMutex(&AtomTable->FastMutex);
return TRUE;
}
VOID
RtlpUnlockAtomTable(PRTL_ATOM_TABLE AtomTable)
{
ExReleaseFastMutex(&AtomTable->FastMutex);
}
BOOLEAN
RtlpCreateAtomHandleTable(PRTL_ATOM_TABLE AtomTable)
{
AtomTable->ExHandleTable = ExCreateHandleTable(NULL);
return (AtomTable->ExHandleTable != NULL);
}
static VOID STDCALL
AtomDeleteHandleCallback(PHANDLE_TABLE HandleTable,
PVOID Object,
ULONG GrantedAccess,
PVOID Context)
{
return;
}
VOID
RtlpDestroyAtomHandleTable(PRTL_ATOM_TABLE AtomTable)
{
if (AtomTable->ExHandleTable)
{
ExDestroyHandleTable(AtomTable->ExHandleTable,
AtomDeleteHandleCallback,
AtomTable);
AtomTable->ExHandleTable = NULL;
}
}
PRTL_ATOM_TABLE
RtlpAllocAtomTable(ULONG Size)
{
PRTL_ATOM_TABLE Table = ExAllocatePool(NonPagedPool,
Size);
if (Table != NULL)
{
RtlZeroMemory(Table,
Size);
}
return Table;
}
VOID
RtlpFreeAtomTable(PRTL_ATOM_TABLE AtomTable)
{
ExFreePool(AtomTable);
}
PRTL_ATOM_TABLE_ENTRY
RtlpAllocAtomTableEntry(ULONG Size)
{
PRTL_ATOM_TABLE_ENTRY Entry = ExAllocatePool(NonPagedPool,
Size);
if (Entry != NULL)
{
RtlZeroMemory(Entry,
Size);
}
return Entry;
}
VOID
RtlpFreeAtomTableEntry(PRTL_ATOM_TABLE_ENTRY Entry)
{
ExFreePool(Entry);
}
VOID
RtlpFreeAtomHandle(PRTL_ATOM_TABLE AtomTable, PRTL_ATOM_TABLE_ENTRY Entry)
{
ExDestroyHandle(AtomTable->ExHandleTable,
(LONG)Entry->HandleIndex);
}
BOOLEAN
RtlpCreateAtomHandle(PRTL_ATOM_TABLE AtomTable, PRTL_ATOM_TABLE_ENTRY Entry)
{
HANDLE_TABLE_ENTRY ExEntry;
LONG HandleIndex;
ExEntry.u1.Object = Entry;
ExEntry.u2.GrantedAccess = 0x1; /* FIXME - valid handle */
HandleIndex = ExCreateHandle(AtomTable->ExHandleTable,
&ExEntry);
if (HandleIndex != 0)
{
/* FIXME - Handle Indexes >= 0xC000 ?! */
if (HandleIndex < 0xC000)
{
Entry->HandleIndex = (USHORT)HandleIndex;
Entry->Atom = 0xC000 + (USHORT)HandleIndex;
return TRUE;
}
else
ExDestroyHandle(AtomTable->ExHandleTable,
HandleIndex);
}
return FALSE;
}
PRTL_ATOM_TABLE_ENTRY
RtlpGetAtomEntry(PRTL_ATOM_TABLE AtomTable, ULONG Index)
{
PHANDLE_TABLE_ENTRY ExEntry;
ExEntry = ExMapHandleToPointer(AtomTable->ExHandleTable,
(LONG)Index);
if (ExEntry != NULL)
{
PRTL_ATOM_TABLE_ENTRY Entry;
Entry = ExEntry->u1.Object;
ExUnlockHandleTableEntry(AtomTable->ExHandleTable,
ExEntry);
return Entry;
}
return NULL;
}
/* EOF */