test: atom.c Source File

Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

# atom.c

Go to the documentation of this file.

    00001 /*++
    00002
    00003 Copyright (c) 1990  Microsoft Corporation
    00004
    00005 Module Name:
    00006
    00007     atom.c
    00008
    00009 Abstract:
    00010
    00011     This file contains the common code to implement atom tables.  It is called
    00012     by both the user mode Win32 Atom API functions (Local/GlobalxxxAtom) and
    00013     by the kernel mode window manager code to access global atoms.
    00014
    00015 Author:
    00016
    00017     Steve Wood (stevewo) 26-Oct-1990
    00018
    00019 Revision History:
    00020
    00021 --*/
    00022
    00023 #include "ntrtlp.h"
    00024 #include "atom.h"
    00025
    00026 ULONG RtlpAtomAllocateTag;
    00027
    00028 PVOID
    00029 RtlpAllocateAtom(
    00030     IN ULONG NumberOfBytes
    00031     )
    00032 {
    00033 #if defined(NTOS_KERNEL_RUNTIME)
    00034     return ExAllocatePoolWithTag( NonPagedPool, NumberOfBytes, RtlpAtomAllocateTag );
    00035 #else
    00036     return RtlAllocateHeap( RtlProcessHeap(), RtlpAtomAllocateTag, NumberOfBytes );
    00037 #endif
    00038 }
    00039
    00040
    00041 void
    00042 RtlpFreeAtom(
    00043     IN PVOID p
    00044     )
    00045 {
    00046 #if defined(NTOS_KERNEL_RUNTIME)
    00047     ExFreePool( p );
    00048 #else
    00049     RtlFreeHeap( RtlProcessHeap(), 0, p );
    00050 #endif
    00051     return;
    00052 }
    00053
    00054
    00055 void
    00056 RtlpInitializeLockAtomTable(
    00057     IN OUT PRTL_ATOM_TABLE AtomTable
    00058     )
    00059 {
    00060 #if defined(NTOS_KERNEL_RUNTIME)
    00061     ExInitializeFastMutex( &AtomTable->FastMutex );
    00062 #else
    00063     RtlInitializeCriticalSection( &AtomTable->CriticalSection );
    00064 #endif
    00065     return;
    00066 }
    00067
    00068 BOOLEAN
    00069 RtlpLockAtomTable(
    00070     IN PRTL_ATOM_TABLE AtomTable
    00071     )
    00072 {
    00073     if (AtomTable == NULL || AtomTable->Signature != RTL_ATOM_TABLE_SIGNATURE) {
    00074         return FALSE;
    00075         }
    00076
    00077 #if defined(NTOS_KERNEL_RUNTIME)
    00078     ExAcquireFastMutex( &AtomTable->FastMutex );
    00079 #else
    00080     RtlEnterCriticalSection( &AtomTable->CriticalSection );
    00081 #endif
    00082
    00083     return TRUE;
    00084 }
    00085
    00086 void
    00087 RtlpUnlockAtomTable(
    00088     IN PRTL_ATOM_TABLE AtomTable
    00089     )
    00090 {
    00091 #if defined(NTOS_KERNEL_RUNTIME)
    00092     ExReleaseFastMutex( &AtomTable->FastMutex );
    00093 #else
    00094     RtlLeaveCriticalSection( &AtomTable->CriticalSection );
    00095 #endif
    00096 }
    00097
    00098
    00099 void
    00100 RtlpDestroyLockAtomTable(
    00101     IN OUT PRTL_ATOM_TABLE AtomTable
    00102     )
    00103 {
    00104 #if defined(NTOS_KERNEL_RUNTIME)
    00105 #else
    00106     RtlDeleteCriticalSection( &AtomTable->CriticalSection );
    00107 #endif
    00108 }
    00109
    00110
    00111 BOOLEAN
    00112 RtlpInitializeHandleTableForAtomTable(
    00113     PRTL_ATOM_TABLE AtomTable
    00114     )
    00115 {
    00116 #if defined(NTOS_KERNEL_RUNTIME)
    00117     AtomTable->ExHandleTable = ExCreateHandleTable( NULL );
    00118     if (AtomTable->ExHandleTable != NULL) {
    00119         //
    00120         // Make sure atom handle tables are NOT part of object handle enumeration
    00121         //
    00122
    00123         ExRemoveHandleTable( AtomTable->ExHandleTable );
    00124         return TRUE;
    00125         }
    00126     else {
    00127         return FALSE;
    00128         }
    00129 #else
    00130     RtlInitializeHandleTable( (ULONG)(USHORT)~RTL_ATOM_MAXIMUM_INTEGER_ATOM,
    00131                               sizeof( RTL_ATOM_HANDLE_TABLE_ENTRY ),
    00132                               &AtomTable->RtlHandleTable
    00133                             );
    00134     return TRUE;
    00135 #endif
    00136 }
    00137
    00138 void
    00139 RtlpDestroyHandleTableForAtomTable(
    00140     PRTL_ATOM_TABLE AtomTable
    00141     )
    00142 {
    00143 #if defined(NTOS_KERNEL_RUNTIME)
    00144     ExDestroyHandleTable( AtomTable->ExHandleTable, NULL );
    00145 #else
    00146     RtlDestroyHandleTable( &AtomTable->RtlHandleTable );
    00147 #endif
    00148     return;
    00149 }
    00150
    00151 PRTL_ATOM_TABLE_ENTRY
    00152 RtlpAtomMapAtomToHandleEntry(
    00153     IN PRTL_ATOM_TABLE AtomTable,
    00154     IN ULONG HandleIndex
    00155     )
    00156 {
    00157 #if defined(NTOS_KERNEL_RUNTIME)
    00158     PHANDLE_TABLE_ENTRY ExHandleEntry;
    00159     PRTL_ATOM_TABLE_ENTRY a;
    00160     EXHANDLE ExHandle;
    00161
    00162     ExHandle.Index = HandleIndex;
    00163
    00164     ExHandleEntry = ExMapHandleToPointer( AtomTable->ExHandleTable,
    00165                                           ExHandle.GenericHandleOverlay
    00166                                         );
    00167     if (ExHandleEntry != NULL) {
    00168         a = ExHandleEntry->Object;
    00169         ExUnlockHandleTableEntry( AtomTable->ExHandleTable, ExHandleEntry );
    00170         return a;
    00171         }
    00172 #else
    00173     PRTL_ATOM_HANDLE_TABLE_ENTRY HandleEntry;
    00174
    00175     if (RtlIsValidIndexHandle( &AtomTable->RtlHandleTable,
    00176                                HandleIndex,
    00177                                (PRTL_HANDLE_TABLE_ENTRY *)&HandleEntry
    00178                              )
    00179        ) {
    00180         return HandleEntry->Atom;
    00181         }
    00182 #endif
    00183     return NULL;
    00184 }
    00185
    00186 BOOLEAN
    00187 RtlpCreateHandleForAtom(
    00188     PRTL_ATOM_TABLE p,
    00189     PRTL_ATOM_TABLE_ENTRY a
    00190     )
    00191 {
    00192 #if defined(NTOS_KERNEL_RUNTIME)
    00193     EXHANDLE ExHandle;
    00194     HANDLE_TABLE_ENTRY ExHandleEntry;
    00195
    00196     ExHandleEntry.Object = a;
    00197     ExHandleEntry.GrantedAccess = 0;
    00198     ExHandle.GenericHandleOverlay = ExCreateHandle( p->ExHandleTable, &ExHandleEntry );
    00199     if (ExHandle.GenericHandleOverlay != NULL) {
    00200         a->HandleIndex = (USHORT)ExHandle.Index;
    00201         a->Atom = (RTL_ATOM)((USHORT)a->HandleIndex | RTL_ATOM_MAXIMUM_INTEGER_ATOM);
    00202         return TRUE;
    00203         }
    00204 #else
    00205     PRTL_ATOM_HANDLE_TABLE_ENTRY HandleEntry;
    00206     ULONG HandleIndex;
    00207
    00208     HandleEntry = (PRTL_ATOM_HANDLE_TABLE_ENTRY)RtlAllocateHandle( &p->RtlHandleTable,
    00209                                                                    &HandleIndex
    00210                                                                  );
    00211     if (HandleEntry != NULL) {
    00212         if (HandleIndex < RTL_ATOM_MAXIMUM_INTEGER_ATOM) {
    00213             a->HandleIndex = (USHORT)HandleIndex;
    00214             a->Atom = (RTL_ATOM)((USHORT)HandleIndex | RTL_ATOM_MAXIMUM_INTEGER_ATOM);
    00215             HandleEntry->Atom = a;
    00216             HandleEntry->LockCount = 0;
    00217             HandleEntry->Flags = RTL_HANDLE_ALLOCATED;
    00218             return TRUE;
    00219             }
    00220
    00221         RtlFreeHandle( &p->RtlHandleTable, (PRTL_HANDLE_TABLE_ENTRY)HandleEntry );
    00222         }
    00223 #endif
    00224     return FALSE;
    00225 }
    00226
    00227 void
    00228 RtlpFreeHandleForAtom(
    00229     PRTL_ATOM_TABLE p,
    00230     PRTL_ATOM_TABLE_ENTRY a
    00231     )
    00232 {
    00233 #if defined(NTOS_KERNEL_RUNTIME)
    00234     EXHANDLE ExHandle;
    00235
    00236     ExHandle.Index = a->HandleIndex;
    00237     ExDestroyHandle( p->ExHandleTable, ExHandle.GenericHandleOverlay, NULL );
    00238 #else
    00239     PRTL_ATOM_HANDLE_TABLE_ENTRY HandleEntry;
    00240
    00241     if (RtlIsValidIndexHandle( &p->RtlHandleTable,
    00242                                a->HandleIndex,
    00243                                (PRTL_HANDLE_TABLE_ENTRY *)&HandleEntry
    00244                              )
    00245        ) {
    00246         RtlFreeHandle( &p->RtlHandleTable, (PRTL_HANDLE_TABLE_ENTRY)HandleEntry );
    00247         }
    00248 #endif
    00249     return;
    00250 }
    00251
    00252 NTSTATUS
    00253 RtlInitializeAtomPackage(
    00254     IN ULONG AllocationTag
    00255     )
    00256 {
    00257     RtlpAtomAllocateTag = AllocationTag;
    00258     return STATUS_SUCCESS;
    00259 }
    00260
    00261 NTSTATUS
    00262 RtlCreateAtomTable(
    00263     IN ULONG NumberOfBuckets,
    00264     OUT PVOID *AtomTableHandle
    00265     )
    00266 {
    00267     NTSTATUS Status;
    00268     PRTL_ATOM_TABLE p;
    00269     ULONG Size;
    00270
    00271     Status = STATUS_SUCCESS;
    00272     if (*AtomTableHandle == NULL) {
    00273         if (NumberOfBuckets <= 1) {
    00274             NumberOfBuckets = RTL_ATOM_TABLE_DEFAULT_NUMBER_OF_BUCKETS;
    00275             }
    00276
    00277         Size = sizeof( RTL_ATOM_TABLE ) +
    00278                (sizeof( RTL_ATOM_TABLE_ENTRY ) * (NumberOfBuckets-1));
    00279
    00280         p = (PRTL_ATOM_TABLE)RtlpAllocateAtom( Size );
    00281         if (p == NULL) {
    00282             Status = STATUS_NO_MEMORY;
    00283             }
    00284         else {
    00285             RtlZeroMemory( p, Size );
    00286             p->NumberOfBuckets = NumberOfBuckets;
    00287             if (RtlpInitializeHandleTableForAtomTable( p )) {
    00288                 RtlpInitializeLockAtomTable( p );
    00289                 p->Signature = RTL_ATOM_TABLE_SIGNATURE;
    00290                 *AtomTableHandle = p;
    00291                 }
    00292             else {
    00293                 Status = STATUS_NO_MEMORY;
    00294                 RtlpFreeAtom( p );
    00295                 }
    00296             }
    00297         }
    00298
    00299     return Status;
    00300 }
    00301
    00302
    00303 NTSTATUS
    00304 RtlDestroyAtomTable(
    00305     IN PVOID AtomTableHandle
    00306     )
    00307 {
    00308     NTSTATUS Status;
    00309     PRTL_ATOM_TABLE p = (PRTL_ATOM_TABLE)AtomTableHandle;
    00310     PRTL_ATOM_TABLE_ENTRY a, aNext, *pa;
    00311     ULONG i;
    00312
    00313     Status = STATUS_SUCCESS;
    00314     if (!RtlpLockAtomTable( p )) {
    00315         return STATUS_INVALID_PARAMETER;
    00316         }
    00317     try {
    00318         pa = &p->Buckets[ 0 ];
    00319         for (i=0; i<p->NumberOfBuckets; i++) {
    00320             aNext = *pa;
    00321             *pa++ = NULL;
    00322             while ((a = aNext) != NULL) {
    00323                 aNext = a->HashLink;
    00324                 a->HashLink = NULL;
    00325                 RtlpFreeAtom( a );
    00326                 }
    00327             }
    00328         p->Signature = 0;
    00329         RtlpUnlockAtomTable( p );
    00330
    00331         RtlpDestroyHandleTableForAtomTable( p );
    00332         RtlpDestroyLockAtomTable( p );
    00333         RtlZeroMemory( p, sizeof( RTL_ATOM_TABLE ) );
    00334         RtlpFreeAtom( p );
    00335         }
    00336     except (EXCEPTION_EXECUTE_HANDLER) {
    00337         Status = GetExceptionCode();
    00338         }
    00339
    00340     return Status;
    00341 }
    00342
    00343 NTSTATUS
    00344 RtlEmptyAtomTable(
    00345     IN PVOID AtomTableHandle,
    00346     IN BOOLEAN IncludePinnedAtoms
    00347     )
    00348 {
    00349     NTSTATUS Status;
    00350     PRTL_ATOM_TABLE p = (PRTL_ATOM_TABLE)AtomTableHandle;
    00351     PRTL_ATOM_TABLE_ENTRY a, aNext, *pa, *pa1;
    00352     ULONG i;
    00353
    00354     Status = STATUS_SUCCESS;
    00355     if (!RtlpLockAtomTable( p )) {
    00356         return STATUS_INVALID_PARAMETER;
    00357         }
    00358     try {
    00359         pa = &p->Buckets[ 0 ];
    00360         for (i=0; i<p->NumberOfBuckets; i++) {
    00361             pa1 = pa++;
    00362             while ((a = *pa1) != NULL) {
    00363                 if (IncludePinnedAtoms || !(a->Flags & RTL_ATOM_PINNED)) {
    00364                     *pa1 = a->HashLink;
    00365                     a->HashLink = NULL;
    00366                     RtlpFreeHandleForAtom( p, a );
    00367                     RtlpFreeAtom( a );
    00368                     }
    00369                 else {
    00370                     pa1 = &a->HashLink;
    00371                     }
    00372                 }
    00373             }
    00374
    00375         RtlpUnlockAtomTable( p );
    00376         }
    00377     except (EXCEPTION_EXECUTE_HANDLER) {
    00378         Status = GetExceptionCode();
    00379         }
    00380
    00381     return Status;
    00382 }
    00383
    00384 BOOLEAN
    00385 RtlpGetIntegerAtom(
    00386     PWSTR Name,
    00387     PRTL_ATOM Atom OPTIONAL
    00388     )
    00389 {
    00390     NTSTATUS Status;
    00391     UNICODE_STRING UnicodeString;
    00392     PWSTR s;
    00393     ULONG n;
    00394     RTL_ATOM Temp;
    00395
    00396     if (((ULONG_PTR)Name & -0x10000) == 0) {
    00397         Temp = (RTL_ATOM)(USHORT)PtrToUlong(Name);
    00398         if (Temp >= RTL_ATOM_MAXIMUM_INTEGER_ATOM) {
    00399             return FALSE;
    00400             }
    00401         else {
    00402             if (Temp == RTL_ATOM_INVALID_ATOM) {
    00403                 Temp = RTL_ATOM_MAXIMUM_INTEGER_ATOM;
    00404                 }
    00405
    00406             if (ARGUMENT_PRESENT( Atom )) {
    00407                 *Atom = Temp;
    00408                 }
    00409
    00410             return TRUE;
    00411             }
    00412         }
    00413     else
    00414     if (*Name != L'#') {
    00415         return FALSE;
    00416         }
    00417
    00418     s = ++Name;
    00419     while (*s != UNICODE_NULL) {
    00420         if (*s < L'0' || *s > L'9') {
    00421             return FALSE;
    00422             }
    00423         else {
    00424             s++;
    00425             }
    00426         }
    00427
    00428     n = 0;
    00429     UnicodeString.Buffer = Name;
    00430     UnicodeString.Length = (USHORT)((PCHAR)s - (PCHAR)Name);
    00431     UnicodeString.MaximumLength = UnicodeString.Length;
    00432     Status = RtlUnicodeStringToInteger( &UnicodeString, 10, &n );
    00433     if (NT_SUCCESS( Status )) {
    00434         if (ARGUMENT_PRESENT( Atom )) {
    00435             if (n == 0 || n > RTL_ATOM_MAXIMUM_INTEGER_ATOM) {
    00436                 *Atom = RTL_ATOM_MAXIMUM_INTEGER_ATOM;
    00437                 }
    00438             else {
    00439                 *Atom = (RTL_ATOM)n;
    00440                 }
    00441             }
    00442
    00443         return TRUE;
    00444         }
    00445     else {
    00446         return FALSE;
    00447         }
    00448 }
    00449
    00450 PRTL_ATOM_TABLE_ENTRY
    00451 RtlpHashStringToAtom(
    00452     IN PRTL_ATOM_TABLE p,
    00453     IN PWSTR Name,
    00454     OUT PRTL_ATOM_TABLE_ENTRY **PreviousAtom OPTIONAL,
    00455     OUT PULONG NameLength
    00456     )
    00457 {
    00458     ULONG Length, Hash;
    00459     WCHAR c;
    00460     PWCH s;
    00461     RTL_ATOM Atom;
    00462     PRTL_ATOM_TABLE_ENTRY *pa, a;
    00463
    00464     if (((ULONG_PTR)Name & -0x10000) == 0) {
    00465         Atom = (RTL_ATOM)(USHORT)PtrToUlong(Name);
    00466         a = NULL;
    00467         if (Atom >= RTL_ATOM_MAXIMUM_INTEGER_ATOM) {
    00468             a = RtlpAtomMapAtomToHandleEntry( p,
    00469                                               (ULONG)(Atom & (USHORT)~RTL_ATOM_MAXIMUM_INTEGER_ATOM)
    00470                                             );
    00471             }
    00472
    00473         if (ARGUMENT_PRESENT( PreviousAtom )) {
    00474             *PreviousAtom = NULL;
    00475             }
    00476
    00477         return a;
    00478         }
    00479
    00480     s = Name;
    00481     Hash = 0;
    00482     while (*s != UNICODE_NULL) {
    00483         c = RtlUpcaseUnicodeChar( *s++ );
    00484         Hash = Hash + (c << 1) + (c >> 1) + c;
    00485         }
    00486     Length = (ULONG) (s - Name);
    00487     if (Length > RTL_ATOM_MAXIMUM_NAME_LENGTH) {
    00488         pa = NULL;
    00489         a = NULL;
    00490         }
    00491     else {
    00492         pa = &p->Buckets[ Hash % p->NumberOfBuckets ];
    00493         while (a = *pa) {
    00494             if (a->NameLength == Length && !_wcsicmp( a->Name, Name )) {
    00495                 break;
    00496                 }
    00497             else {
    00498                 pa = &a->HashLink;
    00499                 }
    00500             }
    00501         }
    00502
    00503     if (ARGUMENT_PRESENT( PreviousAtom )) {
    00504         *PreviousAtom = pa;
    00505         }
    00506
    00507     if (a == NULL && ARGUMENT_PRESENT( NameLength )) {
    00508         *NameLength = Length * sizeof( WCHAR );
    00509         }
    00510
    00511     return a;
    00512 }
    00513
    00514
    00515 NTSTATUS
    00516 RtlAddAtomToAtomTable(
    00517     IN PVOID AtomTableHandle,
    00518     IN PWSTR AtomName OPTIONAL,
    00519     IN OUT PRTL_ATOM Atom OPTIONAL
    00520     )
    00521 {
    00522     NTSTATUS Status;
    00523     PRTL_ATOM_TABLE p = (PRTL_ATOM_TABLE)AtomTableHandle;
    00524     PRTL_ATOM_TABLE_ENTRY a, *pa;
    00525     ULONG NameLength;
    00526     RTL_ATOM Temp;
    00527
    00528     if (!RtlpLockAtomTable( p )) {
    00529         return STATUS_INVALID_PARAMETER;
    00530         }
    00531     try {
    00532         if (RtlpGetIntegerAtom( AtomName, &Temp )) {
    00533             if (Temp >= RTL_ATOM_MAXIMUM_INTEGER_ATOM) {
    00534                 Temp = RTL_ATOM_INVALID_ATOM;
    00535                 Status = STATUS_INVALID_PARAMETER;
    00536                 }
    00537             else {
    00538                 Status = STATUS_SUCCESS;
    00539                 }
    00540
    00541             if (ARGUMENT_PRESENT( Atom )) {
    00542                 *Atom = Temp;
    00543                 }
    00544             }
    00545         else
    00546         if (*AtomName == UNICODE_NULL) {
    00547             Status = STATUS_OBJECT_NAME_INVALID;
    00548             }
    00549         else {
    00550             a = RtlpHashStringToAtom( p, AtomName, &pa, &NameLength );
    00551             if (a == NULL) {
    00552                 if (pa != NULL) {
    00553                     Status = STATUS_NO_MEMORY;
    00554                     a = RtlpAllocateAtom( FIELD_OFFSET( RTL_ATOM_TABLE_ENTRY, Name ) +
    00555                                           NameLength + sizeof( UNICODE_NULL )
    00556                                         );
    00557                     if (a != NULL) {
    00558                         a->HashLink = NULL;
    00559                         a->ReferenceCount = 1;
    00560                         a->Flags = 0;
    00561                         RtlMoveMemory( a->Name, AtomName, NameLength );
    00562                         a->NameLength = (UCHAR)(NameLength / sizeof( WCHAR ));
    00563                         a->Name[ a->NameLength ] = UNICODE_NULL;
    00564                         if (RtlpCreateHandleForAtom( p, a )) {
    00565                             a->Atom = (RTL_ATOM)a->HandleIndex | RTL_ATOM_MAXIMUM_INTEGER_ATOM;
    00566                             *pa = a;
    00567                             if (ARGUMENT_PRESENT( Atom )) {
    00568                                 *Atom = a->Atom;
    00569                                 }
    00570
    00571                             Status = STATUS_SUCCESS;
    00572                             }
    00573                         else {
    00574                             RtlpFreeAtom( a );
    00575                             }
    00576                         }
    00577                     }
    00578                 else {
    00579                     Status = STATUS_INVALID_PARAMETER;
    00580                     }
    00581                 }
    00582             else {
    00583                 if (!(a->Flags & RTL_ATOM_PINNED)) {
    00584                     if (a->ReferenceCount == 0xFFFF) {
    00585                         KdPrint(( "RTL: Pinning atom (%x) as reference count about to wrap\n", Atom ));
    00586                         a->Flags |= RTL_ATOM_PINNED;
    00587                         }
    00588                     else {
    00589                         a->ReferenceCount += 1;
    00590                         }
    00591                     }
    00592
    00593                 if (ARGUMENT_PRESENT( Atom )) {
    00594                     *Atom = a->Atom;
    00595                     }
    00596
    00597                 Status = STATUS_SUCCESS;
    00598                 }
    00599             }
    00600         }
    00601     except (EXCEPTION_EXECUTE_HANDLER) {
    00602         Status = GetExceptionCode();
    00603         }
    00604
    00605     RtlpUnlockAtomTable( p );
    00606
    00607     return Status;
    00608 }
    00609
    00610 NTSTATUS
    00611 RtlLookupAtomInAtomTable(
    00612     IN PVOID AtomTableHandle,
    00613     IN PWSTR AtomName,
    00614     OUT PRTL_ATOM Atom OPTIONAL
    00615     )
    00616 {
    00617     NTSTATUS Status;
    00618     PRTL_ATOM_TABLE p = (PRTL_ATOM_TABLE)AtomTableHandle;
    00619     PRTL_ATOM_TABLE_ENTRY a;
    00620     RTL_ATOM Temp;
    00621
    00622     if (!RtlpLockAtomTable( p )) {
    00623         return STATUS_INVALID_PARAMETER;
    00624         }
    00625     try {
    00626         if (RtlpGetIntegerAtom( AtomName, &Temp )) {
    00627             if (Temp >= RTL_ATOM_MAXIMUM_INTEGER_ATOM) {
    00628                 Temp = RTL_ATOM_INVALID_ATOM;
    00629                 Status = STATUS_INVALID_PARAMETER;
    00630                 }
    00631             else {
    00632                 Status = STATUS_SUCCESS;
    00633                 }
    00634
    00635             if (ARGUMENT_PRESENT( Atom )) {
    00636                 *Atom = Temp;
    00637                 }
    00638             }
    00639         else
    00640         if (*AtomName == UNICODE_NULL) {
    00641             Status = STATUS_OBJECT_NAME_INVALID;
    00642             }
    00643         else {
    00644             a = RtlpHashStringToAtom( p, AtomName, NULL, NULL );
    00645             if (a == NULL) {
    00646                 Status = STATUS_OBJECT_NAME_NOT_FOUND;
    00647                 }
    00648             else {
    00649                 if (RtlpAtomMapAtomToHandleEntry( p, (ULONG)a->HandleIndex ) != NULL) {
    00650                     Status = STATUS_SUCCESS;
    00651                     if (ARGUMENT_PRESENT( Atom )) {
    00652                         *Atom = a->Atom;
    00653                         }
    00654                     }
    00655                 else {
    00656                     Status = STATUS_INVALID_HANDLE;
    00657                     }
    00658                 }
    00659             }
    00660         }
    00661     except (EXCEPTION_EXECUTE_HANDLER) {
    00662         Status = GetExceptionCode();
    00663         }
    00664
    00665     RtlpUnlockAtomTable( p );
    00666
    00667     return Status;
    00668 }
    00669
    00670
    00671 NTSTATUS
    00672 RtlDeleteAtomFromAtomTable(
    00673     IN PVOID AtomTableHandle,
    00674     IN RTL_ATOM Atom
    00675     )
    00676 {
    00677     NTSTATUS Status;
    00678     PRTL_ATOM_TABLE p = (PRTL_ATOM_TABLE)AtomTableHandle;
    00679     PRTL_ATOM_TABLE_ENTRY a, *pa;
    00680
    00681     if (!RtlpLockAtomTable( p )) {
    00682         return STATUS_INVALID_PARAMETER;
    00683         }
    00684     try {
    00685         Status = STATUS_INVALID_HANDLE;
    00686         if (Atom >= RTL_ATOM_MAXIMUM_INTEGER_ATOM) {
    00687             a = RtlpAtomMapAtomToHandleEntry( p,
    00688                                               (ULONG)(Atom & (USHORT)~RTL_ATOM_MAXIMUM_INTEGER_ATOM)
    00689                                             );
    00690             if (a != NULL && a->Atom == Atom) {
    00691                 Status = STATUS_SUCCESS;
    00692                 if (a->Flags & RTL_ATOM_PINNED) {
    00693                     KdPrint(( "RTL: Ignoring attempt to delete a pinned atom (%x)\n", Atom ));
    00694                     Status = STATUS_WAS_LOCKED;        // This is a success status code!
    00695                     }
    00696                 else
    00697                 if (--a->ReferenceCount == 0) {
    00698                     a = RtlpHashStringToAtom( p, a->Name, &pa, NULL );
    00699                     if (a != NULL) {
    00700                         *pa = a->HashLink;
    00701                         RtlpFreeHandleForAtom( p, a );
    00702                         RtlpFreeAtom( a );
    00703                         }
    00704                     }
    00705                 }
    00706             }
    00707         else
    00708         if (Atom != RTL_ATOM_INVALID_ATOM) {
    00709             Status = STATUS_SUCCESS;
    00710             }
    00711         }
    00712     except (EXCEPTION_EXECUTE_HANDLER) {
    00713         Status = GetExceptionCode();
    00714         }
    00715
    00716     RtlpUnlockAtomTable( p );
    00717
    00718     return Status;
    00719 }
    00720
    00721 NTSTATUS
    00722 RtlPinAtomInAtomTable(
    00723     IN PVOID AtomTableHandle,
    00724     IN RTL_ATOM Atom
    00725     )
    00726 {
    00727     NTSTATUS Status;
    00728     PRTL_ATOM_TABLE p = (PRTL_ATOM_TABLE)AtomTableHandle;
    00729     PRTL_ATOM_TABLE_ENTRY a, *pa;
    00730
    00731     if (!RtlpLockAtomTable( p )) {
    00732         return STATUS_INVALID_PARAMETER;
    00733         }
    00734     try {
    00735         Status = STATUS_INVALID_HANDLE;
    00736         if (Atom >= RTL_ATOM_MAXIMUM_INTEGER_ATOM) {
    00737             a = RtlpAtomMapAtomToHandleEntry( p,
    00738                                               (ULONG)(Atom & (USHORT)~RTL_ATOM_MAXIMUM_INTEGER_ATOM)
    00739                                             );
    00740             if (a != NULL && a->Atom == Atom) {
    00741                 Status = STATUS_SUCCESS;
    00742                 a->Flags |= RTL_ATOM_PINNED;
    00743                 }
    00744             }
    00745         else
    00746         if (Atom != RTL_ATOM_INVALID_ATOM) {
    00747             Status = STATUS_SUCCESS;
    00748             }
    00749         }
    00750     except (EXCEPTION_EXECUTE_HANDLER) {
    00751         Status = GetExceptionCode();
    00752         }
    00753
    00754     RtlpUnlockAtomTable( p );
    00755
    00756     return Status;
    00757 }
    00758
    00759 NTSTATUS
    00760 RtlQueryAtomInAtomTable(
    00761     IN PVOID AtomTableHandle,
    00762     IN RTL_ATOM Atom,
    00763     OUT PULONG AtomUsage OPTIONAL,
    00764     OUT PULONG AtomFlags OPTIONAL,
    00765     IN OUT PWSTR AtomName OPTIONAL,
    00766     IN OUT PULONG AtomNameLength OPTIONAL
    00767     )
    00768 {
    00769     NTSTATUS Status;
    00770     PRTL_ATOM_TABLE p = (PRTL_ATOM_TABLE)AtomTableHandle;
    00771     PRTL_ATOM_TABLE_ENTRY a;
    00772     WCHAR AtomNameBuffer[ 16 ];
    00773     ULONG CopyLength;
    00774
    00775     if (!RtlpLockAtomTable( p )) {
    00776         return STATUS_INVALID_PARAMETER;
    00777         }
    00778     try {
    00779         if (Atom < RTL_ATOM_MAXIMUM_INTEGER_ATOM) {
    00780             if (Atom == RTL_ATOM_INVALID_ATOM) {
    00781                 Status = STATUS_INVALID_PARAMETER;
    00782                 }
    00783             else {
    00784                 Status = STATUS_SUCCESS;
    00785                 if (ARGUMENT_PRESENT( AtomUsage )) {
    00786                     *AtomUsage = 1;
    00787                     }
    00788
    00789                 if (ARGUMENT_PRESENT( AtomFlags )) {
    00790                     *AtomFlags = RTL_ATOM_PINNED;
    00791                     }
    00792
    00793                 if (ARGUMENT_PRESENT( AtomName )) {
    00794                     CopyLength = _snwprintf( AtomNameBuffer,
    00795                                              sizeof( AtomNameBuffer ) / sizeof( WCHAR ),
    00796                                              L"#%u",
    00797                                              Atom
    00798                                            ) * sizeof( WCHAR );
    00799                     if (CopyLength >= *AtomNameLength) {
    00800                         if (*AtomNameLength >= sizeof( UNICODE_NULL )) {
    00801                             CopyLength = *AtomNameLength - sizeof( UNICODE_NULL );
    00802                             }
    00803                         else {
    00804                             CopyLength = 0;
    00805                             }
    00806                         }
    00807
    00808                     if (CopyLength != 0) {
    00809                         RtlMoveMemory( AtomName, AtomNameBuffer, CopyLength );
    00810                         AtomName[ CopyLength / sizeof( WCHAR ) ] = UNICODE_NULL;
    00811                         *AtomNameLength = CopyLength;
    00812                         }
    00813                     else {
    00814                         Status = STATUS_BUFFER_TOO_SMALL;
    00815                         }
    00816                     }
    00817                 }
    00818             }
    00819         else {
    00820             a = RtlpAtomMapAtomToHandleEntry( p,
    00821                                               (ULONG)(Atom & (USHORT)~RTL_ATOM_MAXIMUM_INTEGER_ATOM)
    00822                                             );
    00823             if (a != NULL && a->Atom == Atom) {
    00824                 Status = STATUS_SUCCESS;
    00825                 if (ARGUMENT_PRESENT( AtomUsage )) {
    00826                     *AtomUsage = a->ReferenceCount;
    00827                     }
    00828
    00829                 if (ARGUMENT_PRESENT( AtomFlags )) {
    00830                     *AtomFlags = a->Flags;
    00831                     }
    00832
    00833                 if (ARGUMENT_PRESENT( AtomName )) {
    00834                     //
    00835                     // Fill in as much of the atom string as possible, and
    00836                     // always zero terminate. This is what win3.1 does.
    00837                     //
    00838
    00839                     CopyLength = a->NameLength * sizeof( WCHAR );
    00840                     if (CopyLength >= *AtomNameLength) {
    00841                         if (*AtomNameLength >= sizeof( UNICODE_NULL )) {
    00842                             CopyLength = *AtomNameLength - sizeof( UNICODE_NULL );
    00843                             }
    00844                         else {
    00845                             *AtomNameLength = CopyLength;
    00846                             CopyLength = 0;
    00847                             }
    00848                         }
    00849                     if (CopyLength != 0) {
    00850                         RtlMoveMemory( AtomName, a->Name, CopyLength );
    00851                         AtomName[ CopyLength / sizeof( WCHAR ) ] = UNICODE_NULL;
    00852                         *AtomNameLength = CopyLength;
    00853                         }
    00854                     else {
    00855                         Status = STATUS_BUFFER_TOO_SMALL;
    00856                         }
    00857                     }
    00858                 }
    00859             else {
    00860                 Status = STATUS_INVALID_HANDLE;
    00861                 }
    00862             }
    00863         }
    00864     except (EXCEPTION_EXECUTE_HANDLER) {
    00865         Status = GetExceptionCode();
    00866         }
    00867
    00868     RtlpUnlockAtomTable( p );
    00869
    00870     return Status;
    00871 }
    00872
    00873 NTSTATUS
    00874 RtlQueryAtomsInAtomTable(
    00875     IN PVOID AtomTableHandle,
    00876     IN ULONG MaximumNumberOfAtoms,
    00877     OUT PULONG NumberOfAtoms,
    00878     OUT PRTL_ATOM Atoms
    00879     )
    00880 {
    00881     NTSTATUS Status;
    00882     PRTL_ATOM_TABLE p = (PRTL_ATOM_TABLE)AtomTableHandle;
    00883     PRTL_ATOM_TABLE_ENTRY a;
    00884     ULONG i;
    00885     ULONG CurrentAtomIndex;
    00886
    00887     if (!RtlpLockAtomTable( p )) {
    00888         return STATUS_INVALID_PARAMETER;
    00889         }
    00890
    00891     Status = STATUS_SUCCESS;
    00892     try {
    00893         CurrentAtomIndex = 0;
    00894         for (i=0; i<p->NumberOfBuckets; i++) {
    00895             a = p->Buckets[ i ];
    00896             while (a) {
    00897                 if (CurrentAtomIndex < MaximumNumberOfAtoms) {
    00898                     Atoms[ CurrentAtomIndex ] = a->Atom;
    00899                     }
    00900                 else {
    00901                     Status = STATUS_INFO_LENGTH_MISMATCH;
    00902                     }
    00903
    00904                 CurrentAtomIndex += 1;
    00905                 a = a->HashLink;
    00906                 }
    00907             }
    00908
    00909         *NumberOfAtoms = CurrentAtomIndex;
    00910         }
    00911     except (EXCEPTION_EXECUTE_HANDLER) {
    00912         Status = GetExceptionCode();
    00913         }
    00914
    00915     RtlpUnlockAtomTable( p );
    00916
    00917     return Status;
    00918 }