ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

atom.c
Go to the documentation of this file.
00001 /* COPYRIGHT:       See COPYING in the top level directory
00002  * PROJECT:         ReactOS system libraries
00003  * FILE:            lib/rtl/atom.c
00004  * PURPOSE:         Atom managment
00005  * PROGRAMMER:      Thomas Weidenmueller
00006  */
00007 
00008 /* INCLUDES *****************************************************************/
00009 
00010 #include <rtl.h>
00011 
00012 #define NDEBUG
00013 #include <debug.h>
00014 
00015 /* PROTOTYPES ****************************************************************/
00016 
00017 extern NTSTATUS RtlpInitAtomTableLock(PRTL_ATOM_TABLE AtomTable);
00018 extern VOID RtlpDestroyAtomTableLock(PRTL_ATOM_TABLE AtomTable);
00019 extern BOOLEAN RtlpLockAtomTable(PRTL_ATOM_TABLE AtomTable);
00020 extern VOID RtlpUnlockAtomTable(PRTL_ATOM_TABLE AtomTable);
00021 
00022 extern BOOLEAN RtlpCreateAtomHandleTable(PRTL_ATOM_TABLE AtomTable);
00023 extern VOID RtlpDestroyAtomHandleTable(PRTL_ATOM_TABLE AtomTable);
00024 
00025 extern PRTL_ATOM_TABLE RtlpAllocAtomTable(ULONG Size);
00026 extern VOID RtlpFreeAtomTable(PRTL_ATOM_TABLE AtomTable);
00027 extern PRTL_ATOM_TABLE_ENTRY RtlpAllocAtomTableEntry(ULONG Size);
00028 extern VOID RtlpFreeAtomTableEntry(PRTL_ATOM_TABLE_ENTRY Entry);
00029 
00030 extern BOOLEAN RtlpCreateAtomHandle(PRTL_ATOM_TABLE AtomTable, PRTL_ATOM_TABLE_ENTRY Entry);
00031 extern VOID RtlpFreeAtomHandle(PRTL_ATOM_TABLE AtomTable, PRTL_ATOM_TABLE_ENTRY Entry);
00032 extern PRTL_ATOM_TABLE_ENTRY RtlpGetAtomEntry(PRTL_ATOM_TABLE AtomTable, ULONG Index);
00033 
00034 /* FUNCTIONS *****************************************************************/
00035 
00036 static PRTL_ATOM_TABLE_ENTRY
00037 RtlpHashAtomName(IN PRTL_ATOM_TABLE AtomTable,
00038                  IN PWSTR AtomName,
00039                  OUT PRTL_ATOM_TABLE_ENTRY **HashLink)
00040 {
00041    UNICODE_STRING Name;
00042    ULONG Hash;
00043 
00044    RtlInitUnicodeString(&Name,
00045                         AtomName);
00046 
00047    if (Name.Length != 0 &&
00048        NT_SUCCESS(RtlHashUnicodeString(&Name,
00049                                        TRUE,
00050                                        HASH_STRING_ALGORITHM_X65599,
00051                                        &Hash)))
00052      {
00053         PRTL_ATOM_TABLE_ENTRY Current;
00054         PRTL_ATOM_TABLE_ENTRY *Link;
00055 
00056         Link = &AtomTable->Buckets[Hash % AtomTable->NumberOfBuckets];
00057 
00058         /* search for an existing entry */
00059         Current = *Link;
00060         while (Current != NULL)
00061           {
00062              if (Current->NameLength == Name.Length / sizeof(WCHAR) &&
00063                  !_wcsicmp(Current->Name, Name.Buffer))
00064                {
00065                   *HashLink = Link;
00066                   return Current;
00067                }
00068              Link = &Current->HashLink;
00069              Current = Current->HashLink;
00070           }
00071 
00072         /* no matching atom found, return the hash link */
00073         *HashLink = Link;
00074      }
00075    else
00076      *HashLink = NULL;
00077 
00078    return NULL;
00079 }
00080 
00081 static BOOLEAN
00082 RtlpCheckIntegerAtom(PWSTR AtomName,
00083                      PUSHORT AtomValue)
00084 {
00085    UNICODE_STRING AtomString;
00086    ULONG LongValue;
00087    USHORT LoValue;
00088    PWCHAR p;
00089 
00090    DPRINT("RtlpCheckIntegerAtom(AtomName '%S' AtomValue %p)\n",
00091           AtomName, AtomValue);
00092 
00093    if (!((ULONG_PTR)AtomName & 0xFFFF0000))
00094      {
00095         LoValue = (USHORT)((ULONG_PTR)AtomName & 0xFFFF);
00096 
00097         if (LoValue == 0)
00098           LoValue = 0xC000;
00099 
00100         if (AtomValue != NULL)
00101           *AtomValue = LoValue;
00102 
00103         return TRUE;
00104      }
00105 
00106    if (*AtomName != L'#')
00107      return FALSE;
00108 
00109    p = AtomName;
00110    p++;
00111    while (*p)
00112      {
00113         if ((*p < L'0') || (*p > L'9'))
00114           return FALSE;
00115         p++;
00116      }
00117 
00118    p = AtomName;
00119    p++;
00120    RtlInitUnicodeString(&AtomString,
00121                         p);
00122 
00123    DPRINT("AtomString: %wZ\n", &AtomString);
00124 
00125    RtlUnicodeStringToInteger(&AtomString,10, &LongValue);
00126 
00127    DPRINT("LongValue: %lu\n", LongValue);
00128 
00129    *AtomValue = (USHORT)(LongValue & 0x0000FFFF);
00130 
00131    return TRUE;
00132 }
00133 
00134 
00135 /*
00136  * @implemented
00137  */
00138 NTSTATUS NTAPI
00139 RtlCreateAtomTable(IN ULONG TableSize,
00140                    IN OUT PRTL_ATOM_TABLE *AtomTable)
00141 {
00142    PRTL_ATOM_TABLE Table;
00143    NTSTATUS Status;
00144 
00145    DPRINT("RtlCreateAtomTable(TableSize %lu AtomTable %p)\n",
00146           TableSize, AtomTable);
00147 
00148    if (*AtomTable != NULL)
00149      {
00150         return STATUS_SUCCESS;
00151      }
00152 
00153    /* Use default if size was incorrect */
00154    if (TableSize <= 1) TableSize = 37;
00155 
00156    /* allocate atom table */
00157    Table = RtlpAllocAtomTable(((TableSize - 1) * sizeof(PRTL_ATOM_TABLE_ENTRY)) +
00158                               sizeof(RTL_ATOM_TABLE));
00159    if (Table == NULL)
00160      {
00161         return STATUS_NO_MEMORY;
00162      }
00163 
00164    /* initialize atom table */
00165    Table->NumberOfBuckets = TableSize;
00166 
00167    Status = RtlpInitAtomTableLock(Table);
00168    if (!NT_SUCCESS(Status))
00169      {
00170         RtlpFreeAtomTable(Table);
00171         return Status;
00172      }
00173 
00174    if (!RtlpCreateAtomHandleTable(Table))
00175      {
00176         RtlpDestroyAtomTableLock(Table);
00177         RtlpFreeAtomTable(Table);
00178         return STATUS_NO_MEMORY;
00179      }
00180 
00181    *AtomTable = Table;
00182    return STATUS_SUCCESS;
00183 }
00184 
00185 
00186 /*
00187  * @implemented
00188  */
00189 NTSTATUS NTAPI
00190 RtlDestroyAtomTable(IN PRTL_ATOM_TABLE AtomTable)
00191 {
00192    PRTL_ATOM_TABLE_ENTRY *CurrentBucket, *LastBucket;
00193    PRTL_ATOM_TABLE_ENTRY CurrentEntry, NextEntry;
00194 
00195    DPRINT("RtlDestroyAtomTable (AtomTable %p)\n", AtomTable);
00196 
00197    if (!RtlpLockAtomTable(AtomTable))
00198      {
00199         return (STATUS_INVALID_PARAMETER);
00200      }
00201 
00202    /* delete all atoms */
00203    LastBucket = AtomTable->Buckets + AtomTable->NumberOfBuckets;
00204    for (CurrentBucket = AtomTable->Buckets;
00205         CurrentBucket != LastBucket;
00206         CurrentBucket++)
00207      {
00208         NextEntry = *CurrentBucket;
00209         *CurrentBucket = NULL;
00210 
00211         while (NextEntry != NULL)
00212           {
00213              CurrentEntry = NextEntry;
00214              NextEntry = NextEntry->HashLink;
00215 
00216              /* no need to delete the atom handle, the handles will all be freed
00217                 up when destroying the atom handle table! */
00218 
00219              RtlpFreeAtomTableEntry(CurrentEntry);
00220           }
00221      }
00222 
00223    RtlpDestroyAtomHandleTable(AtomTable);
00224 
00225    RtlpUnlockAtomTable(AtomTable);
00226 
00227    RtlpDestroyAtomTableLock(AtomTable);
00228 
00229    RtlpFreeAtomTable(AtomTable);
00230 
00231    return STATUS_SUCCESS;
00232 }
00233 
00234 
00235 /*
00236  * @implemented
00237  */
00238 NTSTATUS NTAPI
00239 RtlEmptyAtomTable(PRTL_ATOM_TABLE AtomTable,
00240                   BOOLEAN DeletePinned)
00241 {
00242    PRTL_ATOM_TABLE_ENTRY *CurrentBucket, *LastBucket;
00243    PRTL_ATOM_TABLE_ENTRY CurrentEntry, NextEntry, *PtrEntry;
00244 
00245    DPRINT("RtlEmptyAtomTable (AtomTable %p DeletePinned %x)\n",
00246           AtomTable, DeletePinned);
00247 
00248    if (RtlpLockAtomTable(AtomTable) == FALSE)
00249      {
00250         return (STATUS_INVALID_PARAMETER);
00251      }
00252 
00253    /* delete all atoms */
00254    LastBucket = AtomTable->Buckets + AtomTable->NumberOfBuckets;
00255    for (CurrentBucket = AtomTable->Buckets;
00256         CurrentBucket != LastBucket;
00257         CurrentBucket++)
00258      {
00259         NextEntry = *CurrentBucket;
00260         PtrEntry = CurrentBucket;
00261 
00262         while (NextEntry != NULL)
00263           {
00264              CurrentEntry = NextEntry;
00265              NextEntry = NextEntry->HashLink;
00266 
00267              if (DeletePinned || !(CurrentEntry->Flags & RTL_ATOM_IS_PINNED))
00268                {
00269                  *PtrEntry = NextEntry;
00270 
00271                  RtlpFreeAtomHandle(AtomTable,
00272                                     CurrentEntry);
00273 
00274                  RtlpFreeAtomTableEntry(CurrentEntry);
00275                }
00276              else
00277                {
00278                  PtrEntry = &CurrentEntry->HashLink;
00279                }
00280           }
00281      }
00282 
00283    RtlpUnlockAtomTable(AtomTable);
00284 
00285    return STATUS_SUCCESS;
00286 }
00287 
00288 
00289 /*
00290  * @implemented
00291  */
00292 NTSTATUS NTAPI
00293 RtlAddAtomToAtomTable(IN PRTL_ATOM_TABLE AtomTable,
00294                       IN PWSTR AtomName,
00295                       OUT PRTL_ATOM Atom)
00296 {
00297    USHORT AtomValue;
00298    PRTL_ATOM_TABLE_ENTRY *HashLink;
00299    PRTL_ATOM_TABLE_ENTRY Entry = NULL;
00300    NTSTATUS Status = STATUS_SUCCESS;
00301 
00302    DPRINT("RtlAddAtomToAtomTable (AtomTable %p AtomName %S Atom %p)\n",
00303           AtomTable, AtomName, Atom);
00304 
00305    if (RtlpCheckIntegerAtom (AtomName, &AtomValue))
00306      {
00307         /* integer atom */
00308         if (AtomValue >= 0xC000)
00309           {
00310              Status = STATUS_INVALID_PARAMETER;
00311           }
00312         else if (Atom != NULL)
00313           {
00314              *Atom = (RTL_ATOM)AtomValue;
00315           }
00316 
00317         return Status;
00318      }
00319 
00320    RtlpLockAtomTable(AtomTable);
00321 
00322    /* string atom, hash it and try to find an existing atom with the same name */
00323    Entry = RtlpHashAtomName(AtomTable,
00324                             AtomName,
00325                             &HashLink);
00326 
00327    if (Entry != NULL)
00328      {
00329         /* found another atom, increment the reference counter unless it's pinned */
00330 
00331         if (!(Entry->Flags & RTL_ATOM_IS_PINNED))
00332           {
00333              if (++Entry->ReferenceCount == 0)
00334                {
00335                   /* FIXME - references overflowed, pin the atom? */
00336                   Entry->Flags |= RTL_ATOM_IS_PINNED;
00337                }
00338           }
00339 
00340         if (Atom != NULL)
00341           {
00342              *Atom = (RTL_ATOM)Entry->Atom;
00343           }
00344      }
00345    else
00346      {
00347         /* couldn't find an existing atom, HashLink now points to either the
00348            HashLink pointer of the previous atom or to the bucket so we can
00349            simply add it to the list */
00350         if (HashLink != NULL)
00351           {
00352              ULONG AtomNameLen = (ULONG)wcslen(AtomName);
00353 
00354              if (AtomNameLen > RTL_MAXIMUM_ATOM_LENGTH)
00355              {
00356                 Status = STATUS_INVALID_PARAMETER;
00357                 goto end;
00358              }
00359 
00360              Entry = RtlpAllocAtomTableEntry(sizeof(RTL_ATOM_TABLE_ENTRY) -
00361                                              sizeof(Entry->Name) +
00362                                              (AtomNameLen + 1) * sizeof(WCHAR));
00363              if (Entry != NULL)
00364                {
00365                   Entry->HashLink = NULL;
00366                   Entry->ReferenceCount = 1;
00367                   Entry->Flags = 0x0;
00368 
00369                   Entry->NameLength = (UCHAR)AtomNameLen;
00370                   RtlCopyMemory(Entry->Name,
00371                                 AtomName,
00372                                 (AtomNameLen + 1) * sizeof(WCHAR));
00373 
00374                   if (RtlpCreateAtomHandle(AtomTable,
00375                                            Entry))
00376                     {
00377                        /* append the atom to the list */
00378                        *HashLink = Entry;
00379 
00380                        if (Atom != NULL)
00381                          {
00382                             *Atom = (RTL_ATOM)Entry->Atom;
00383                          }
00384                     }
00385                   else
00386                     {
00387                        RtlpFreeAtomTableEntry(Entry);
00388                        Status = STATUS_NO_MEMORY;
00389                     }
00390                }
00391              else
00392                {
00393                   Status = STATUS_NO_MEMORY;
00394                }
00395           }
00396         else
00397           {
00398              /* The caller supplied an empty atom name! */
00399              Status = STATUS_OBJECT_NAME_INVALID;
00400           }
00401      }
00402 end:
00403    RtlpUnlockAtomTable(AtomTable);
00404 
00405    return Status;
00406 }
00407 
00408 
00409 /*
00410  * @implemented
00411  */
00412 NTSTATUS NTAPI
00413 RtlDeleteAtomFromAtomTable(IN PRTL_ATOM_TABLE AtomTable,
00414                            IN RTL_ATOM Atom)
00415 {
00416    PRTL_ATOM_TABLE_ENTRY Entry;
00417    NTSTATUS Status = STATUS_SUCCESS;
00418 
00419    DPRINT("RtlDeleteAtomFromAtomTable (AtomTable %p Atom %x)\n",
00420           AtomTable, Atom);
00421 
00422    if (Atom >= 0xC000)
00423      {
00424         RtlpLockAtomTable(AtomTable);
00425 
00426         Entry = RtlpGetAtomEntry(AtomTable,
00427                                  (ULONG)((USHORT)Atom - 0xC000));
00428 
00429         if (Entry != NULL && Entry->Atom == (USHORT)Atom)
00430           {
00431              if (!(Entry->Flags & RTL_ATOM_IS_PINNED))
00432                {
00433                   if (--Entry->ReferenceCount == 0)
00434                     {
00435                        PRTL_ATOM_TABLE_ENTRY *HashLink;
00436 
00437                        /* it's time to delete the atom. we need to unlink it from
00438                           the list. The easiest way is to take the atom name and
00439                           hash it again, this way we get the pointer to either
00440                           the hash bucket or the previous atom that links to the
00441                           one we want to delete. This way we can easily bypass
00442                           this item. */
00443                        if (RtlpHashAtomName(AtomTable,
00444                                             Entry->Name,
00445                                             &HashLink) != NULL)
00446                          {
00447                             /* bypass this atom */
00448                             *HashLink = Entry->HashLink;
00449 
00450                             RtlpFreeAtomHandle(AtomTable,
00451                                                Entry);
00452 
00453                             RtlpFreeAtomTableEntry(Entry);
00454                          }
00455                        else
00456                          {
00457                             /* WTF?! This should never happen!!! */
00458                             ASSERT(FALSE);
00459                          }
00460                     }
00461                }
00462              else
00463                {
00464                   /* tried to delete a pinned atom, do nothing and return
00465                      STATUS_WAS_LOCKED, which is NOT a failure code! */
00466                   Status = STATUS_WAS_LOCKED;
00467                }
00468           }
00469         else
00470           {
00471              Status = STATUS_INVALID_HANDLE;
00472           }
00473 
00474         RtlpUnlockAtomTable(AtomTable);
00475      }
00476 
00477    return Status;
00478 }
00479 
00480 
00481 /*
00482  * @implemented
00483  */
00484 NTSTATUS NTAPI
00485 RtlLookupAtomInAtomTable(IN PRTL_ATOM_TABLE AtomTable,
00486                          IN PWSTR AtomName,
00487                          OUT PRTL_ATOM Atom)
00488 {
00489    PRTL_ATOM_TABLE_ENTRY Entry, *HashLink;
00490    USHORT AtomValue;
00491    RTL_ATOM FoundAtom = 0;
00492    NTSTATUS Status = STATUS_SUCCESS;
00493 
00494    DPRINT("RtlLookupAtomInAtomTable (AtomTable %p AtomName %S Atom %p)\n",
00495           AtomTable, AtomName, Atom);
00496 
00497    if (RtlpCheckIntegerAtom (AtomName, &AtomValue))
00498      {
00499         /* integer atom */
00500         if (AtomValue >= 0xC000)
00501           {
00502              Status = STATUS_INVALID_PARAMETER;
00503           }
00504         else if (Atom != NULL)
00505           {
00506              *Atom = (RTL_ATOM)AtomValue;
00507           }
00508 
00509         return Status;
00510      }
00511 
00512    RtlpLockAtomTable(AtomTable);
00513    Status = STATUS_OBJECT_NAME_NOT_FOUND;
00514 
00515    /* string atom */
00516    Entry = RtlpHashAtomName(AtomTable,
00517                             AtomName,
00518                             &HashLink);
00519    if (Entry != NULL)
00520      {
00521         Status = STATUS_SUCCESS;
00522         FoundAtom = (RTL_ATOM)Entry->Atom;
00523      }
00524    RtlpUnlockAtomTable(AtomTable);
00525    if (NT_SUCCESS(Status) && Atom != NULL)
00526      {
00527         *Atom = FoundAtom;
00528      }
00529    return Status;
00530 }
00531 
00532 
00533 /*
00534  * @implemented
00535  */
00536 NTSTATUS NTAPI
00537 RtlPinAtomInAtomTable(IN PRTL_ATOM_TABLE AtomTable,
00538                       IN RTL_ATOM Atom)
00539 {
00540    NTSTATUS Status = STATUS_SUCCESS;
00541 
00542    DPRINT("RtlPinAtomInAtomTable (AtomTable %p Atom %x)\n",
00543           AtomTable, Atom);
00544 
00545    if (Atom >= 0xC000)
00546      {
00547         PRTL_ATOM_TABLE_ENTRY Entry;
00548 
00549         RtlpLockAtomTable(AtomTable);
00550 
00551         Entry = RtlpGetAtomEntry(AtomTable,
00552                                  (ULONG)((USHORT)Atom - 0xC000));
00553 
00554         if (Entry != NULL && Entry->Atom == (USHORT)Atom)
00555           {
00556              Entry->Flags |= RTL_ATOM_IS_PINNED;
00557           }
00558         else
00559           {
00560              Status = STATUS_INVALID_HANDLE;
00561           }
00562 
00563         RtlpUnlockAtomTable(AtomTable);
00564      }
00565 
00566    return Status;
00567 }
00568 
00569 
00570 /*
00571  * @implemented
00572  *
00573  * This API is really messed up with regards to NameLength. If you pass in a
00574  * valid buffer for AtomName, NameLength should be the size of the buffer
00575  * (in bytes, not characters). So if you expect the string to be 6 char long,
00576  * you need to allocate a buffer of 7 WCHARs and pass 14 for NameLength.
00577  * The AtomName returned is always null terminated. If the NameLength you pass
00578  * is smaller than 4 (4 would leave room for 1 character) the function will
00579  * return with status STATUS_BUFFER_TOO_SMALL. If you pass more than 4, the
00580  * return status will be STATUS_SUCCESS, even if the buffer is not large enough
00581  * to hold the complete string. In that case, the string is silently truncated
00582  * and made to fit in the provided buffer. On return NameLength is set to the
00583  * number of bytes (but EXCLUDING the bytes for the null terminator) copied.
00584  * So, if the string is 6 char long, you pass a buffer of 10 bytes, on return
00585  * NameLength will be set to 8.
00586  * If you pass in a NULL value for AtomName, the length of the string in bytes
00587  * (again EXCLUDING the null terminator) is returned in NameLength, at least
00588  * on Win2k, XP and ReactOS. NT4 will return 0 in that case.
00589  */
00590 NTSTATUS NTAPI
00591 RtlQueryAtomInAtomTable(PRTL_ATOM_TABLE AtomTable,
00592                         RTL_ATOM Atom,
00593                         PULONG RefCount,
00594                         PULONG PinCount,
00595                         PWSTR AtomName,
00596                         PULONG NameLength)
00597 {
00598    ULONG Length;
00599    BOOL Unlock = FALSE;
00600 
00601    union
00602      {
00603      /* A RTL_ATOM_TABLE_ENTRY has a "WCHAR Name[1]" entry at the end.
00604       * Make sure we reserve enough room to facilitate a 12 character name */
00605      RTL_ATOM_TABLE_ENTRY AtomTableEntry;
00606      WCHAR StringBuffer[sizeof(RTL_ATOM_TABLE_ENTRY) / sizeof(WCHAR) + 12];
00607      } NumberEntry;
00608    PRTL_ATOM_TABLE_ENTRY Entry;
00609    NTSTATUS Status = STATUS_SUCCESS;
00610 
00611    if (Atom < 0xC000)
00612      {
00613         /* Synthesize an entry */
00614         NumberEntry.AtomTableEntry.Atom = Atom;
00615         NumberEntry.AtomTableEntry.NameLength = swprintf(NumberEntry.AtomTableEntry.Name,
00616                                                          L"#%lu",
00617                                                          (ULONG)Atom);
00618         NumberEntry.AtomTableEntry.ReferenceCount = 1;
00619         NumberEntry.AtomTableEntry.Flags = RTL_ATOM_IS_PINNED;
00620         Entry = &NumberEntry.AtomTableEntry;
00621      }
00622    else
00623      {
00624         RtlpLockAtomTable(AtomTable);
00625         Unlock = TRUE;
00626 
00627         Entry = RtlpGetAtomEntry(AtomTable,
00628                                  (ULONG)((USHORT)Atom - 0xC000));
00629      }
00630 
00631    if (Entry != NULL && Entry->Atom == (USHORT)Atom)
00632      {
00633         DPRINT("Atom name: %wZ\n", &Entry->Name);
00634 
00635         if (RefCount != NULL)
00636           {
00637              *RefCount = Entry->ReferenceCount;
00638           }
00639 
00640         if (PinCount != NULL)
00641           {
00642              *PinCount = ((Entry->Flags & RTL_ATOM_IS_PINNED) != 0);
00643           }
00644 
00645         if (NULL != NameLength)
00646           {
00647              Length = Entry->NameLength * sizeof(WCHAR);
00648              if (NULL != AtomName)
00649                {
00650                   if (*NameLength < Length + sizeof(WCHAR))
00651                     {
00652                        if (*NameLength < 4)
00653                          {
00654                             *NameLength = Length;
00655                             Status = STATUS_BUFFER_TOO_SMALL;
00656                          }
00657                        else
00658                          {
00659                             Length = *NameLength - sizeof(WCHAR);
00660                          }
00661                     }
00662                   if (NT_SUCCESS(Status))
00663                     {
00664                        RtlCopyMemory(AtomName,
00665                                      Entry->Name,
00666                                      Length);
00667                        AtomName[Length / sizeof(WCHAR)] = L'\0';
00668                        *NameLength = Length;
00669                     }
00670                }
00671              else
00672                {
00673                   *NameLength = Length;
00674                }
00675           }
00676         else if (NULL != AtomName)
00677           {
00678              Status = STATUS_INVALID_PARAMETER;
00679           }
00680      }
00681    else
00682      {
00683         Status = STATUS_INVALID_HANDLE;
00684      }
00685 
00686    if (Unlock) RtlpUnlockAtomTable(AtomTable);
00687 
00688    return Status;
00689 }
00690 
00691 
00692 /*
00693  * @private - only used by NtQueryInformationAtom
00694  */
00695 NTSTATUS NTAPI
00696 RtlQueryAtomListInAtomTable(IN PRTL_ATOM_TABLE AtomTable,
00697                             IN ULONG MaxAtomCount,
00698                             OUT ULONG *AtomCount,
00699                             OUT RTL_ATOM *AtomList)
00700 {
00701    PRTL_ATOM_TABLE_ENTRY *CurrentBucket, *LastBucket;
00702    PRTL_ATOM_TABLE_ENTRY CurrentEntry;
00703    ULONG Atoms = 0;
00704    NTSTATUS Status = STATUS_SUCCESS;
00705 
00706    RtlpLockAtomTable(AtomTable);
00707 
00708    LastBucket = AtomTable->Buckets + AtomTable->NumberOfBuckets;
00709    for (CurrentBucket = AtomTable->Buckets;
00710         CurrentBucket != LastBucket;
00711         CurrentBucket++)
00712      {
00713         CurrentEntry = *CurrentBucket;
00714 
00715         while (CurrentEntry != NULL)
00716           {
00717              if (MaxAtomCount > 0)
00718                {
00719                   *(AtomList++) = (RTL_ATOM)CurrentEntry->Atom;
00720                   MaxAtomCount--;
00721                }
00722              else
00723                {
00724                   /* buffer too small, but don't bail. we need to determine the
00725                      total number of atoms in the table! */
00726                   Status = STATUS_INFO_LENGTH_MISMATCH;
00727                }
00728 
00729              Atoms++;
00730              CurrentEntry = CurrentEntry->HashLink;
00731           }
00732      }
00733 
00734    *AtomCount = Atoms;
00735 
00736    RtlpUnlockAtomTable(AtomTable);
00737 
00738    return Status;
00739 }
00740 

Generated on Sat May 26 2012 04:22:56 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.