|
|
/*++
Copyright (c) 1990 Microsoft Corporation
Module Name:
atom.c
Abstract:
This file contains the common code to implement atom tables. It is called by both the user mode Win32 Atom API functions (Local/GlobalxxxAtom) and by the kernel mode window manager code to access global atoms.
Author:
Steve Wood (stevewo) 26-Oct-1990
Revision History:
--*/
#include "ntrtlp.h"
#include "atom.h"
#if defined(ALLOC_PRAGMA) && defined(NTOS_KERNEL_RUNTIME)
PVOID RtlpAllocateAtom( IN ULONG NumberOfBytes, IN ULONG Tag ); void RtlpFreeAtom( IN PVOID p ); void RtlpInitializeLockAtomTable( IN OUT PRTL_ATOM_TABLE AtomTable ); BOOLEAN RtlpLockAtomTable( IN PRTL_ATOM_TABLE AtomTable ); void RtlpUnlockAtomTable( IN PRTL_ATOM_TABLE AtomTable ); void RtlpDestroyLockAtomTable( IN OUT PRTL_ATOM_TABLE AtomTable ); BOOLEAN RtlpInitializeHandleTableForAtomTable( PRTL_ATOM_TABLE AtomTable ); void RtlpDestroyHandleTableForAtomTable( PRTL_ATOM_TABLE AtomTable ); PRTL_ATOM_TABLE_ENTRY RtlpAtomMapAtomToHandleEntry( IN PRTL_ATOM_TABLE AtomTable, IN ULONG HandleIndex ); BOOLEAN RtlpCreateHandleForAtom( PRTL_ATOM_TABLE p, PRTL_ATOM_TABLE_ENTRY a ); void RtlpFreeHandleForAtom( PRTL_ATOM_TABLE p, PRTL_ATOM_TABLE_ENTRY a ); BOOLEAN RtlpGetIntegerAtom( PWSTR Name, PRTL_ATOM Atom OPTIONAL ); PRTL_ATOM_TABLE_ENTRY RtlpHashStringToAtom( IN PRTL_ATOM_TABLE p, IN PWSTR Name, OUT PRTL_ATOM_TABLE_ENTRY **PreviousAtom OPTIONAL, OUT PULONG NameLength ); #pragma alloc_text(PAGE,RtlpAllocateAtom)
#pragma alloc_text(PAGE,RtlpFreeAtom)
#pragma alloc_text(PAGE,RtlpInitializeLockAtomTable)
#pragma alloc_text(PAGE,RtlInitializeAtomPackage)
#pragma alloc_text(PAGE,RtlpLockAtomTable)
#pragma alloc_text(PAGE,RtlpUnlockAtomTable)
#pragma alloc_text(PAGE,RtlpDestroyLockAtomTable)
#pragma alloc_text(PAGE,RtlpInitializeHandleTableForAtomTable)
#pragma alloc_text(PAGE,RtlpDestroyHandleTableForAtomTable)
#pragma alloc_text(PAGE,RtlpAtomMapAtomToHandleEntry)
#pragma alloc_text(PAGE,RtlpCreateHandleForAtom)
#pragma alloc_text(PAGE,RtlpFreeHandleForAtom)
#pragma alloc_text(PAGE,RtlInitializeAtomPackage)
#pragma alloc_text(PAGE,RtlCreateAtomTable)
#pragma alloc_text(PAGE,RtlDestroyAtomTable)
#pragma alloc_text(PAGE,RtlEmptyAtomTable)
#pragma alloc_text(PAGE,RtlpGetIntegerAtom)
#pragma alloc_text(PAGE,RtlpHashStringToAtom)
#pragma alloc_text(PAGE,RtlAddAtomToAtomTable)
#pragma alloc_text(PAGE,RtlLookupAtomInAtomTable)
#pragma alloc_text(PAGE,RtlDeleteAtomFromAtomTable)
#pragma alloc_text(PAGE,RtlPinAtomInAtomTable)
#pragma alloc_text(PAGE,RtlQueryAtomInAtomTable)
#pragma alloc_text(PAGE,RtlQueryAtomsInAtomTable)
#endif
#if defined(ALLOC_DATA_PRAGMA) && defined(NTOS_KERNEL_RUNTIME)
#pragma data_seg("PAGEDATA")
#endif
ULONG RtlpAtomAllocateTag;
#if defined(NTOS_KERNEL_RUNTIME)
typedef struct _RTLP_ATOM_QUOTA { PEPROCESS_QUOTA_BLOCK QuotaBlock; SIZE_T PagedAmount; } RTLP_ATOM_QUOTA, *PRTLP_ATOM_QUOTA;
#endif
PVOID RtlpAllocateAtom( IN ULONG NumberOfBytes, IN ULONG Tag ) { #if defined(NTOS_KERNEL_RUNTIME)
PRTLP_ATOM_QUOTA AllocatedBlock;
NumberOfBytes += sizeof(RTLP_ATOM_QUOTA);
AllocatedBlock = ExAllocatePoolWithTag( PagedPool, NumberOfBytes, Tag ); if (AllocatedBlock) { AllocatedBlock->QuotaBlock = PsChargeSharedPoolQuota( PsGetCurrentProcess(), NumberOfBytes, 0 ); if (! AllocatedBlock->QuotaBlock) { ExFreePoolWithTag( AllocatedBlock, Tag ); AllocatedBlock = NULL; } else { AllocatedBlock->PagedAmount = NumberOfBytes; AllocatedBlock++; } }
return AllocatedBlock; #else
return RtlAllocateHeap( RtlProcessHeap(), RtlpAtomAllocateTag, NumberOfBytes ); #endif
}
void RtlpFreeAtom( IN PVOID p ) { #if defined(NTOS_KERNEL_RUNTIME)
PRTLP_ATOM_QUOTA AllocatedBlock = (PRTLP_ATOM_QUOTA) p;
ASSERT( AllocatedBlock ); AllocatedBlock--; ASSERT( AllocatedBlock ); ASSERT( AllocatedBlock->QuotaBlock ); ASSERT( AllocatedBlock->PagedAmount ); PsReturnSharedPoolQuota( AllocatedBlock->QuotaBlock, AllocatedBlock->PagedAmount, 0 ); ExFreePool( AllocatedBlock ); #else
RtlFreeHeap( RtlProcessHeap(), 0, p ); #endif
return; }
void RtlpInitializeLockAtomTable( IN OUT PRTL_ATOM_TABLE AtomTable ) { #if defined(NTOS_KERNEL_RUNTIME)
// ExInitializeFastMutex( &AtomTable->FastMutex );
ExInitializePushLock( &AtomTable->PushLock ); #else
RtlInitializeCriticalSection( &AtomTable->CriticalSection ); #endif
return; }
BOOLEAN RtlpLockAtomTable( IN PRTL_ATOM_TABLE AtomTable ) { if (AtomTable == NULL || AtomTable->Signature != RTL_ATOM_TABLE_SIGNATURE) { return FALSE; }
#if defined(NTOS_KERNEL_RUNTIME)
KeEnterCriticalRegion (); ExAcquirePushLockExclusive( &AtomTable->PushLock ); #else
RtlEnterCriticalSection( &AtomTable->CriticalSection ); #endif
return TRUE; }
void RtlpUnlockAtomTable( IN PRTL_ATOM_TABLE AtomTable ) { #if defined(NTOS_KERNEL_RUNTIME)
ExReleasePushLockExclusive( &AtomTable->PushLock ); KeLeaveCriticalRegion (); #else
RtlLeaveCriticalSection( &AtomTable->CriticalSection ); #endif
}
void RtlpDestroyLockAtomTable( IN OUT PRTL_ATOM_TABLE AtomTable ) { #if defined(NTOS_KERNEL_RUNTIME)
#else
RtlDeleteCriticalSection( &AtomTable->CriticalSection ); #endif
}
BOOLEAN RtlpInitializeHandleTableForAtomTable( PRTL_ATOM_TABLE AtomTable ) { #if defined(NTOS_KERNEL_RUNTIME)
AtomTable->ExHandleTable = ExCreateHandleTable( NULL ); if (AtomTable->ExHandleTable != NULL) { //
// Make sure atom handle tables are NOT part of object handle enumeration
//
ExRemoveHandleTable( AtomTable->ExHandleTable ); return TRUE; } else { return FALSE; } #else
RtlInitializeHandleTable( (ULONG)(USHORT)~RTL_ATOM_MAXIMUM_INTEGER_ATOM, sizeof( RTL_ATOM_HANDLE_TABLE_ENTRY ), &AtomTable->RtlHandleTable ); return TRUE; #endif
}
void RtlpDestroyHandleTableForAtomTable( PRTL_ATOM_TABLE AtomTable ) { #if defined(NTOS_KERNEL_RUNTIME)
ExDestroyHandleTable( AtomTable->ExHandleTable, NULL ); #else
RtlDestroyHandleTable( &AtomTable->RtlHandleTable ); #endif
return; }
PRTL_ATOM_TABLE_ENTRY RtlpAtomMapAtomToHandleEntry( IN PRTL_ATOM_TABLE AtomTable, IN ULONG HandleIndex ) { #if defined(NTOS_KERNEL_RUNTIME)
PHANDLE_TABLE_ENTRY ExHandleEntry; PRTL_ATOM_TABLE_ENTRY a; EXHANDLE ExHandle;
ExHandle.GenericHandleOverlay = 0; ExHandle.Index = HandleIndex;
ExHandleEntry = ExMapHandleToPointer( AtomTable->ExHandleTable, ExHandle.GenericHandleOverlay ); if (ExHandleEntry != NULL) { a = ExHandleEntry->Object; ExUnlockHandleTableEntry( AtomTable->ExHandleTable, ExHandleEntry ); return a; } #else
PRTL_ATOM_HANDLE_TABLE_ENTRY HandleEntry;
if (RtlIsValidIndexHandle( &AtomTable->RtlHandleTable, HandleIndex, (PRTL_HANDLE_TABLE_ENTRY *)&HandleEntry ) ) { return HandleEntry->Atom; } #endif
return NULL; }
BOOLEAN RtlpCreateHandleForAtom( PRTL_ATOM_TABLE p, PRTL_ATOM_TABLE_ENTRY a ) { #if defined(NTOS_KERNEL_RUNTIME)
EXHANDLE ExHandle; HANDLE_TABLE_ENTRY ExHandleEntry;
ExHandleEntry.Object = a; ExHandleEntry.GrantedAccess = 0; ExHandle.GenericHandleOverlay = ExCreateHandle( p->ExHandleTable, &ExHandleEntry ); if (ExHandle.GenericHandleOverlay != NULL) { a->HandleIndex = (USHORT)ExHandle.Index; a->Atom = (RTL_ATOM)((USHORT)a->HandleIndex | RTL_ATOM_MAXIMUM_INTEGER_ATOM); return TRUE; } #else
PRTL_ATOM_HANDLE_TABLE_ENTRY HandleEntry; ULONG HandleIndex;
HandleEntry = (PRTL_ATOM_HANDLE_TABLE_ENTRY)RtlAllocateHandle( &p->RtlHandleTable, &HandleIndex ); if (HandleEntry != NULL) { if (HandleIndex < RTL_ATOM_MAXIMUM_INTEGER_ATOM) { a->HandleIndex = (USHORT)HandleIndex; a->Atom = (RTL_ATOM)((USHORT)HandleIndex | RTL_ATOM_MAXIMUM_INTEGER_ATOM); HandleEntry->Atom = a; HandleEntry->LockCount = 0; HandleEntry->Flags = RTL_HANDLE_ALLOCATED; return TRUE; }
RtlFreeHandle( &p->RtlHandleTable, (PRTL_HANDLE_TABLE_ENTRY)HandleEntry ); } #endif
return FALSE; }
void RtlpFreeHandleForAtom( PRTL_ATOM_TABLE p, PRTL_ATOM_TABLE_ENTRY a ) { #if defined(NTOS_KERNEL_RUNTIME)
EXHANDLE ExHandle;
ExHandle.GenericHandleOverlay = 0; ExHandle.Index = a->HandleIndex; ExDestroyHandle( p->ExHandleTable, ExHandle.GenericHandleOverlay, NULL ); #else
PRTL_ATOM_HANDLE_TABLE_ENTRY HandleEntry;
if (RtlIsValidIndexHandle( &p->RtlHandleTable, a->HandleIndex, (PRTL_HANDLE_TABLE_ENTRY *)&HandleEntry ) ) { RtlFreeHandle( &p->RtlHandleTable, (PRTL_HANDLE_TABLE_ENTRY)HandleEntry ); } #endif
return; }
NTSTATUS RtlInitializeAtomPackage( IN ULONG AllocationTag ) { RTL_PAGED_CODE(); RtlpAtomAllocateTag = AllocationTag; return STATUS_SUCCESS; }
NTSTATUS RtlCreateAtomTable( IN ULONG NumberOfBuckets, OUT PVOID *AtomTableHandle ) { NTSTATUS Status; PRTL_ATOM_TABLE p; ULONG Size;
RTL_PAGED_CODE(); Status = STATUS_SUCCESS; if (*AtomTableHandle == NULL) { if (NumberOfBuckets <= 1) { NumberOfBuckets = RTL_ATOM_TABLE_DEFAULT_NUMBER_OF_BUCKETS; }
Size = sizeof( RTL_ATOM_TABLE ) + (sizeof( RTL_ATOM_TABLE_ENTRY ) * (NumberOfBuckets-1));
p = (PRTL_ATOM_TABLE)RtlpAllocateAtom( Size, 'TmtA' ); if (p == NULL) { Status = STATUS_NO_MEMORY; } else { RtlZeroMemory( p, Size ); p->NumberOfBuckets = NumberOfBuckets; if (RtlpInitializeHandleTableForAtomTable( p )) { RtlpInitializeLockAtomTable( p ); p->Signature = RTL_ATOM_TABLE_SIGNATURE; *AtomTableHandle = p; } else { Status = STATUS_NO_MEMORY; RtlpFreeAtom( p ); } } }
return Status; }
NTSTATUS RtlDestroyAtomTable( IN PVOID AtomTableHandle ) { NTSTATUS Status; PRTL_ATOM_TABLE p = (PRTL_ATOM_TABLE)AtomTableHandle; PRTL_ATOM_TABLE_ENTRY a, aNext, *pa; ULONG i;
RTL_PAGED_CODE(); Status = STATUS_SUCCESS; if (!RtlpLockAtomTable( p )) { return STATUS_INVALID_PARAMETER; } try { pa = &p->Buckets[ 0 ]; for (i=0; i<p->NumberOfBuckets; i++) { aNext = *pa; *pa++ = NULL; while ((a = aNext) != NULL) { aNext = a->HashLink; a->HashLink = NULL; RtlpFreeAtom( a ); } } p->Signature = 0; RtlpUnlockAtomTable( p );
RtlpDestroyHandleTableForAtomTable( p ); RtlpDestroyLockAtomTable( p ); RtlZeroMemory( p, sizeof( RTL_ATOM_TABLE ) ); RtlpFreeAtom( p ); } except (EXCEPTION_EXECUTE_HANDLER) { Status = GetExceptionCode(); }
return Status; }
NTSTATUS RtlEmptyAtomTable( IN PVOID AtomTableHandle, IN BOOLEAN IncludePinnedAtoms ) { NTSTATUS Status; PRTL_ATOM_TABLE p = (PRTL_ATOM_TABLE)AtomTableHandle; PRTL_ATOM_TABLE_ENTRY a, aNext, *pa, *pa1; ULONG i;
RTL_PAGED_CODE(); Status = STATUS_SUCCESS; if (!RtlpLockAtomTable( p )) { return STATUS_INVALID_PARAMETER; } try { pa = &p->Buckets[ 0 ]; for (i=0; i<p->NumberOfBuckets; i++) { pa1 = pa++; while ((a = *pa1) != NULL) { if (IncludePinnedAtoms || !(a->Flags & RTL_ATOM_PINNED)) { *pa1 = a->HashLink; a->HashLink = NULL; RtlpFreeHandleForAtom( p, a ); RtlpFreeAtom( a ); } else { pa1 = &a->HashLink; } } }
RtlpUnlockAtomTable( p ); } except (EXCEPTION_EXECUTE_HANDLER) { Status = GetExceptionCode(); }
return Status; }
BOOLEAN RtlpGetIntegerAtom( PWSTR Name, PRTL_ATOM Atom OPTIONAL ) { NTSTATUS Status; UNICODE_STRING UnicodeString; PWSTR s; ULONG n; RTL_ATOM Temp;
if (((ULONG_PTR)Name & -0x10000) == 0) { Temp = (RTL_ATOM)(USHORT)PtrToUlong(Name); if (Temp >= RTL_ATOM_MAXIMUM_INTEGER_ATOM) { return FALSE; } else { if (Temp == RTL_ATOM_INVALID_ATOM) { Temp = RTL_ATOM_MAXIMUM_INTEGER_ATOM; }
if (ARGUMENT_PRESENT( Atom )) { *Atom = Temp; }
return TRUE; } } else if (*Name != L'#') { return FALSE; }
s = ++Name; while (*s != UNICODE_NULL) { if (*s < L'0' || *s > L'9') { return FALSE; } else { s++; } }
n = 0; UnicodeString.Buffer = Name; UnicodeString.Length = (USHORT)((PCHAR)s - (PCHAR)Name); UnicodeString.MaximumLength = UnicodeString.Length; Status = RtlUnicodeStringToInteger( &UnicodeString, 10, &n ); if (NT_SUCCESS( Status )) { if (ARGUMENT_PRESENT( Atom )) { if (n == 0 || n > RTL_ATOM_MAXIMUM_INTEGER_ATOM) { *Atom = RTL_ATOM_MAXIMUM_INTEGER_ATOM; } else { *Atom = (RTL_ATOM)n; } }
return TRUE; } else { return FALSE; } }
PRTL_ATOM_TABLE_ENTRY RtlpHashStringToAtom( IN PRTL_ATOM_TABLE p, IN PWSTR Name, OUT PRTL_ATOM_TABLE_ENTRY **PreviousAtom OPTIONAL, OUT PULONG NameLength ) { ULONG Length, Hash; WCHAR c; PWCH s; RTL_ATOM Atom; PRTL_ATOM_TABLE_ENTRY *pa, a;
if (((ULONG_PTR)Name & -0x10000) == 0) { Atom = (RTL_ATOM)(USHORT)PtrToUlong(Name); a = NULL; if (Atom >= RTL_ATOM_MAXIMUM_INTEGER_ATOM) { a = RtlpAtomMapAtomToHandleEntry( p, (ULONG)(Atom & (USHORT)~RTL_ATOM_MAXIMUM_INTEGER_ATOM) ); }
if (ARGUMENT_PRESENT( PreviousAtom )) { *PreviousAtom = NULL; }
return a; }
s = Name; Hash = 0; while (*s != UNICODE_NULL) { c = RtlUpcaseUnicodeChar( *s++ ); Hash = Hash + (c << 1) + (c >> 1) + c; } Length = (ULONG) (s - Name); if (Length > RTL_ATOM_MAXIMUM_NAME_LENGTH) { pa = NULL; a = NULL; } else { pa = &p->Buckets[ Hash % p->NumberOfBuckets ]; while (a = *pa) { if (a->NameLength == Length && !_wcsicmp( a->Name, Name )) { break; } else { pa = &a->HashLink; } } }
if (ARGUMENT_PRESENT( PreviousAtom )) { *PreviousAtom = pa; }
if (a == NULL && ARGUMENT_PRESENT( NameLength )) { *NameLength = Length * sizeof( WCHAR ); }
return a; }
NTSTATUS RtlAddAtomToAtomTable( IN PVOID AtomTableHandle, IN PWSTR AtomName OPTIONAL, IN OUT PRTL_ATOM Atom OPTIONAL ) { NTSTATUS Status; PRTL_ATOM_TABLE p = (PRTL_ATOM_TABLE)AtomTableHandle; PRTL_ATOM_TABLE_ENTRY a, *pa; ULONG NameLength; RTL_ATOM Temp;
RTL_PAGED_CODE(); if (!RtlpLockAtomTable( p )) { return STATUS_INVALID_PARAMETER; } try { if (RtlpGetIntegerAtom( AtomName, &Temp )) { if (Temp >= RTL_ATOM_MAXIMUM_INTEGER_ATOM) { Temp = RTL_ATOM_INVALID_ATOM; Status = STATUS_INVALID_PARAMETER; } else { Status = STATUS_SUCCESS; }
if (ARGUMENT_PRESENT( Atom )) { *Atom = Temp; } } else if (*AtomName == UNICODE_NULL) { Status = STATUS_OBJECT_NAME_INVALID; } else { a = RtlpHashStringToAtom( p, AtomName, &pa, &NameLength ); if (a == NULL) { if (pa != NULL) { Status = STATUS_NO_MEMORY; a = RtlpAllocateAtom( FIELD_OFFSET( RTL_ATOM_TABLE_ENTRY, Name ) + NameLength + sizeof( UNICODE_NULL ), 'AmtA' ); if (a != NULL) { a->HashLink = NULL; a->ReferenceCount = 1; a->Flags = 0; RtlCopyMemory( a->Name, AtomName, NameLength ); a->NameLength = (UCHAR)(NameLength / sizeof( WCHAR )); a->Name[ a->NameLength ] = UNICODE_NULL; if (RtlpCreateHandleForAtom( p, a )) { a->Atom = (RTL_ATOM)a->HandleIndex | RTL_ATOM_MAXIMUM_INTEGER_ATOM; *pa = a; if (ARGUMENT_PRESENT( Atom )) { *Atom = a->Atom; }
Status = STATUS_SUCCESS; } else { RtlpFreeAtom( a ); } } } else { Status = STATUS_INVALID_PARAMETER; } } else { if (!(a->Flags & RTL_ATOM_PINNED)) { if (a->ReferenceCount == 0xFFFF) { KdPrint(( "RTL: Pinning atom (%x) as reference count about to wrap\n", Atom )); a->Flags |= RTL_ATOM_PINNED; } else { a->ReferenceCount += 1; } }
if (ARGUMENT_PRESENT( Atom )) { *Atom = a->Atom; }
Status = STATUS_SUCCESS; } } } except (EXCEPTION_EXECUTE_HANDLER) { Status = GetExceptionCode(); }
RtlpUnlockAtomTable( p );
return Status; }
NTSTATUS RtlLookupAtomInAtomTable( IN PVOID AtomTableHandle, IN PWSTR AtomName, OUT PRTL_ATOM Atom OPTIONAL ) { NTSTATUS Status; PRTL_ATOM_TABLE p = (PRTL_ATOM_TABLE)AtomTableHandle; PRTL_ATOM_TABLE_ENTRY a; RTL_ATOM Temp;
RTL_PAGED_CODE(); if (!RtlpLockAtomTable( p )) { return STATUS_INVALID_PARAMETER; } try { if (RtlpGetIntegerAtom( AtomName, &Temp )) { if (Temp >= RTL_ATOM_MAXIMUM_INTEGER_ATOM) { Temp = RTL_ATOM_INVALID_ATOM; Status = STATUS_INVALID_PARAMETER; } else { Status = STATUS_SUCCESS; }
if (ARGUMENT_PRESENT( Atom )) { *Atom = Temp; } } else if (*AtomName == UNICODE_NULL) { Status = STATUS_OBJECT_NAME_INVALID; } else { a = RtlpHashStringToAtom( p, AtomName, NULL, NULL ); if (a == NULL) { Status = STATUS_OBJECT_NAME_NOT_FOUND; } else { if (RtlpAtomMapAtomToHandleEntry( p, (ULONG)a->HandleIndex ) != NULL) { Status = STATUS_SUCCESS; if (ARGUMENT_PRESENT( Atom )) { *Atom = a->Atom; } } else { Status = STATUS_INVALID_HANDLE; } } } } except (EXCEPTION_EXECUTE_HANDLER) { Status = GetExceptionCode(); }
RtlpUnlockAtomTable( p );
return Status; }
NTSTATUS RtlDeleteAtomFromAtomTable( IN PVOID AtomTableHandle, IN RTL_ATOM Atom ) { NTSTATUS Status; PRTL_ATOM_TABLE p = (PRTL_ATOM_TABLE)AtomTableHandle; PRTL_ATOM_TABLE_ENTRY a, *pa;
RTL_PAGED_CODE(); if (!RtlpLockAtomTable( p )) { return STATUS_INVALID_PARAMETER; } try { Status = STATUS_INVALID_HANDLE; if (Atom >= RTL_ATOM_MAXIMUM_INTEGER_ATOM) { a = RtlpAtomMapAtomToHandleEntry( p, (ULONG)(Atom & (USHORT)~RTL_ATOM_MAXIMUM_INTEGER_ATOM) ); if (a != NULL && a->Atom == Atom) { Status = STATUS_SUCCESS; if (a->Flags & RTL_ATOM_PINNED) { KdPrint(( "RTL: Ignoring attempt to delete a pinned atom (%x)\n", Atom )); Status = STATUS_WAS_LOCKED; // This is a success status code!
} else if (--a->ReferenceCount == 0) { a = RtlpHashStringToAtom( p, a->Name, &pa, NULL ); if (a != NULL) { if (pa != NULL) { *pa = a->HashLink; } RtlpFreeHandleForAtom( p, a ); RtlpFreeAtom( a ); } } } } else if (Atom != RTL_ATOM_INVALID_ATOM) { Status = STATUS_SUCCESS; } } except (EXCEPTION_EXECUTE_HANDLER) { Status = GetExceptionCode(); }
RtlpUnlockAtomTable( p );
return Status; }
NTSTATUS RtlPinAtomInAtomTable( IN PVOID AtomTableHandle, IN RTL_ATOM Atom ) { NTSTATUS Status; PRTL_ATOM_TABLE p = (PRTL_ATOM_TABLE)AtomTableHandle; PRTL_ATOM_TABLE_ENTRY a, *pa;
RTL_PAGED_CODE(); if (!RtlpLockAtomTable( p )) { return STATUS_INVALID_PARAMETER; } try { Status = STATUS_INVALID_HANDLE; if (Atom >= RTL_ATOM_MAXIMUM_INTEGER_ATOM) { a = RtlpAtomMapAtomToHandleEntry( p, (ULONG)(Atom & (USHORT)~RTL_ATOM_MAXIMUM_INTEGER_ATOM) ); if (a != NULL && a->Atom == Atom) { Status = STATUS_SUCCESS; a->Flags |= RTL_ATOM_PINNED; } } else if (Atom != RTL_ATOM_INVALID_ATOM) { Status = STATUS_SUCCESS; } } except (EXCEPTION_EXECUTE_HANDLER) { Status = GetExceptionCode(); }
RtlpUnlockAtomTable( p );
return Status; }
NTSTATUS RtlQueryAtomInAtomTable( IN PVOID AtomTableHandle, IN RTL_ATOM Atom, OUT PULONG AtomUsage OPTIONAL, OUT PULONG AtomFlags OPTIONAL, IN OUT PWSTR AtomName OPTIONAL, IN OUT PULONG AtomNameLength OPTIONAL ) { NTSTATUS Status; PRTL_ATOM_TABLE p = (PRTL_ATOM_TABLE)AtomTableHandle; PRTL_ATOM_TABLE_ENTRY a; WCHAR AtomNameBuffer[ 16 ]; ULONG CopyLength;
RTL_PAGED_CODE(); if (!RtlpLockAtomTable( p )) { return STATUS_INVALID_PARAMETER; } try { if (Atom < RTL_ATOM_MAXIMUM_INTEGER_ATOM) { if (Atom == RTL_ATOM_INVALID_ATOM) { Status = STATUS_INVALID_PARAMETER; } else { Status = STATUS_SUCCESS; if (ARGUMENT_PRESENT( AtomUsage )) { *AtomUsage = 1; }
if (ARGUMENT_PRESENT( AtomFlags )) { *AtomFlags = RTL_ATOM_PINNED; }
if (ARGUMENT_PRESENT( AtomName )) { CopyLength = _snwprintf( AtomNameBuffer, sizeof( AtomNameBuffer ) / sizeof( WCHAR ), L"#%u", Atom ) * sizeof( WCHAR ); if (CopyLength >= *AtomNameLength) { if (*AtomNameLength >= sizeof( UNICODE_NULL )) { CopyLength = *AtomNameLength - sizeof( UNICODE_NULL ); } else { CopyLength = 0; } }
if (CopyLength != 0) { RtlCopyMemory( AtomName, AtomNameBuffer, CopyLength ); AtomName[ CopyLength / sizeof( WCHAR ) ] = UNICODE_NULL; *AtomNameLength = CopyLength; } else { Status = STATUS_BUFFER_TOO_SMALL; } } } } else { a = RtlpAtomMapAtomToHandleEntry( p, (ULONG)(Atom & (USHORT)~RTL_ATOM_MAXIMUM_INTEGER_ATOM) ); if (a != NULL && a->Atom == Atom) { Status = STATUS_SUCCESS; if (ARGUMENT_PRESENT( AtomUsage )) { *AtomUsage = a->ReferenceCount; }
if (ARGUMENT_PRESENT( AtomFlags )) { *AtomFlags = a->Flags; }
if (ARGUMENT_PRESENT( AtomName )) { //
// Fill in as much of the atom string as possible, and
// always zero terminate. This is what win3.1 does.
//
CopyLength = a->NameLength * sizeof( WCHAR ); if (CopyLength >= *AtomNameLength) { if (*AtomNameLength >= sizeof( UNICODE_NULL )) { CopyLength = *AtomNameLength - sizeof( UNICODE_NULL ); } else { *AtomNameLength = CopyLength; CopyLength = 0; } } if (CopyLength != 0) { RtlCopyMemory( AtomName, a->Name, CopyLength ); AtomName[ CopyLength / sizeof( WCHAR ) ] = UNICODE_NULL; *AtomNameLength = CopyLength; } else { Status = STATUS_BUFFER_TOO_SMALL; } } } else { Status = STATUS_INVALID_HANDLE; } } } except (EXCEPTION_EXECUTE_HANDLER) { Status = GetExceptionCode(); }
RtlpUnlockAtomTable( p );
return Status; }
NTSTATUS RtlQueryAtomsInAtomTable( IN PVOID AtomTableHandle, IN ULONG MaximumNumberOfAtoms, OUT PULONG NumberOfAtoms, OUT PRTL_ATOM Atoms ) { NTSTATUS Status; PRTL_ATOM_TABLE p = (PRTL_ATOM_TABLE)AtomTableHandle; PRTL_ATOM_TABLE_ENTRY a; ULONG i; ULONG CurrentAtomIndex;
RTL_PAGED_CODE(); if (!RtlpLockAtomTable( p )) { return STATUS_INVALID_PARAMETER; }
Status = STATUS_SUCCESS; try { CurrentAtomIndex = 0; for (i=0; i<p->NumberOfBuckets; i++) { a = p->Buckets[ i ]; while (a) { if (CurrentAtomIndex < MaximumNumberOfAtoms) { Atoms[ CurrentAtomIndex ] = a->Atom; } else { Status = STATUS_INFO_LENGTH_MISMATCH; }
CurrentAtomIndex += 1; a = a->HashLink; } }
*NumberOfAtoms = CurrentAtomIndex; } except (EXCEPTION_EXECUTE_HANDLER) { Status = GetExceptionCode(); }
RtlpUnlockAtomTable( p );
return Status; }
#if defined(ALLOC_DATA_PRAGMA) && defined(NTOS_KERNEL_RUNTIME)
#pragma data_seg()
#endif
|