mirror of
https://github.com/reactos/reactos.git
synced 2025-04-15 10:03:56 +00:00
- 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:
parent
ff3d5dbe7d
commit
469c016da3
18 changed files with 1243 additions and 1764 deletions
|
@ -86,7 +86,7 @@ typedef struct _HANDLE_TABLE
|
|||
ERESOURCE HandleTableLock;
|
||||
LIST_ENTRY HandleTableList;
|
||||
KEVENT HandleContentionEvent;
|
||||
} HANDLE_TABLE;
|
||||
} HANDLE_TABLE, *PHANDLE_TABLE;
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -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
|
||||
);
|
||||
|
||||
/*
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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 */
|
|
@ -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);
|
||||
|
|
|
@ -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
732
reactos/lib/rtl/atom.c
Normal 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;
|
||||
}
|
||||
|
|
@ -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>
|
||||
|
|
|
@ -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 */
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in a new issue