:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[reactos.git] / ntoskrnl / rtl / atom.c
1 /* $Id$
2  *
3  * COPYRIGHT:       See COPYING in the top level directory
4  * PROJECT:         ReactOS kernel
5  * FILE:            ntoskrnl/nt/atom.c
6  * PURPOSE:         Atom managment
7  * PROGRAMMER:      Nobody
8  * UPDATE HISTORY:
9  *                  Created 22/05/98
10  */
11
12 /* INCLUDES *****************************************************************/
13
14 #include <ddk/ntddk.h>
15 #include <internal/handle.h>
16 #include <internal/pool.h>
17
18 #define NDEBUG
19 #include <internal/debug.h>
20
21
22
23 typedef struct _RTL_ATOM_ENTRY
24 {
25    LIST_ENTRY List;
26    UNICODE_STRING Name;
27    ULONG RefCount;
28    BOOLEAN Locked;
29    ULONG Index;
30 } RTL_ATOM_ENTRY, *PRTL_ATOM_ENTRY;
31
32
33 /* PROTOTYPES ****************************************************************/
34
35 static PRTL_ATOM_TABLE RtlpGetGlobalAtomTable(VOID);
36
37 static ULONG RtlpHashAtomName(ULONG TableSize, PWSTR AtomName);
38 static BOOLEAN RtlpCheckIntegerAtom(PWSTR AtomName, PUSHORT AtomValue);
39
40 static NTSTATUS RtlpInitAtomTableLock(PRTL_ATOM_TABLE AtomTable);
41 static VOID RtlpDestroyAtomTableLock(PRTL_ATOM_TABLE AtomTable);
42 static BOOLEAN RtlpLockAtomTable(PRTL_ATOM_TABLE AtomTable);
43 static VOID RtlpUnlockAtomTable(PRTL_ATOM_TABLE AtomTable);
44
45 static BOOLEAN RtlpCreateAtomHandleTable(PRTL_ATOM_TABLE AtomTable);
46 static VOID RtlpDestroyAtomHandleTable(PRTL_ATOM_TABLE AtomTable);
47
48 static NTSTATUS RtlpQueryAtomInformation(PRTL_ATOM_TABLE AtomTable,
49                                          RTL_ATOM Atom,
50                                          PATOM_BASIC_INFORMATION AtomInformation,
51                                          ULONG AtomInformationLength,
52                                          PULONG ReturnLength);
53
54 static NTSTATUS RtlpQueryAtomTableInformation(PRTL_ATOM_TABLE AtomTable,
55                                               RTL_ATOM Atom,
56                                               PATOM_TABLE_INFORMATION AtomInformation,
57                                               ULONG AtomInformationLength,
58                                               PULONG ReturnLength);
59
60
61 /* GLOBALS *******************************************************************/
62
63 static PRTL_ATOM_TABLE GlobalAtomTable = NULL;
64
65 /* FUNCTIONS *****************************************************************/
66
67
68 NTSTATUS STDCALL
69 NtAddAtom(IN PWSTR AtomName,
70           OUT PRTL_ATOM Atom)
71 {
72    PRTL_ATOM_TABLE AtomTable;
73
74    AtomTable = RtlpGetGlobalAtomTable();
75    if (AtomTable == NULL)
76      return STATUS_ACCESS_DENIED;
77
78    return (RtlAddAtomToAtomTable(AtomTable,
79                                  AtomName,
80                                  Atom));
81 }
82
83
84 NTSTATUS STDCALL
85 NtDeleteAtom(IN RTL_ATOM Atom)
86 {
87    PRTL_ATOM_TABLE AtomTable;
88
89    AtomTable = RtlpGetGlobalAtomTable();
90    if (AtomTable == NULL)
91      return STATUS_ACCESS_DENIED;
92
93    return (RtlDeleteAtomFromAtomTable(AtomTable,
94                                       Atom));
95 }
96
97
98 NTSTATUS STDCALL
99 NtFindAtom(IN PWSTR AtomName,
100            OUT PRTL_ATOM Atom)
101 {
102    PRTL_ATOM_TABLE AtomTable;
103
104    AtomTable = RtlpGetGlobalAtomTable();
105    if (AtomTable == NULL)
106      return STATUS_ACCESS_DENIED;
107
108    return (RtlLookupAtomInAtomTable(AtomTable,
109                                     AtomName,
110                                     Atom));
111 }
112
113
114 NTSTATUS STDCALL
115 NtQueryInformationAtom(RTL_ATOM Atom,
116                        ATOM_INFORMATION_CLASS AtomInformationClass,
117                        PVOID AtomInformation,
118                        ULONG AtomInformationLength,
119                        PULONG ReturnLength)
120 {
121    PRTL_ATOM_TABLE AtomTable;
122    NTSTATUS Status;
123
124    AtomTable = RtlpGetGlobalAtomTable();
125    if (AtomTable == NULL)
126      return STATUS_ACCESS_DENIED;
127
128    switch (AtomInformationClass)
129      {
130      case AtomBasicInformation:
131         Status = RtlpQueryAtomInformation(AtomTable,
132                                           Atom,
133                                           AtomInformation,
134                                           AtomInformationLength,
135                                           ReturnLength);
136         break;
137
138      case AtomTableInformation:
139         Status = RtlpQueryAtomTableInformation(AtomTable,
140                                                Atom,
141                                                AtomInformation,
142                                                AtomInformationLength,
143                                                ReturnLength);
144         break;
145
146      default:
147         Status = STATUS_INVALID_INFO_CLASS;
148      }
149
150    return Status;
151 }
152
153
154 NTSTATUS STDCALL
155 RtlCreateAtomTable(ULONG TableSize,
156                    PRTL_ATOM_TABLE *AtomTable)
157 {
158    PRTL_ATOM_TABLE Table;
159    ULONG i;
160    NTSTATUS Status;
161
162    DPRINT("RtlCreateAtomTable(TableSize %lu AtomTable %p)\n",
163           TableSize, AtomTable);
164
165    if (*AtomTable != NULL)
166      {
167         return STATUS_SUCCESS;
168      }
169
170    /* allocate atom table */
171    Table = ExAllocatePool(NonPagedPool,
172                           TableSize * sizeof(RTL_ATOM_ENTRY) +
173                           sizeof(RTL_ATOM_TABLE));
174    if (Table == NULL)
175      return STATUS_NO_MEMORY;
176
177    /* initialize atom table */
178    Table->TableSize = TableSize;
179    Table->NumberOfAtoms = 0;
180
181    for (i = 0; i < TableSize; i++)
182      {
183         InitializeListHead(&Table->Slot[i]);
184      }
185
186    Status = RtlpInitAtomTableLock(Table);
187    if (!NT_SUCCESS(Status))
188      {
189         ExFreePool(Table);
190         return Status;
191      }
192
193    if (RtlpCreateAtomHandleTable(Table) == FALSE)
194      {
195         RtlpDestroyAtomTableLock(Table);
196         ExFreePool(Table);
197         return STATUS_NO_MEMORY;
198      }
199
200    *AtomTable = Table;
201    return STATUS_SUCCESS;
202 }
203
204
205 NTSTATUS STDCALL
206 RtlDestroyAtomTable(IN PRTL_ATOM_TABLE AtomTable)
207 {
208    PLIST_ENTRY Current;
209    PRTL_ATOM_ENTRY AtomEntry;
210    ULONG i;
211
212    if (RtlpLockAtomTable(AtomTable) == FALSE)
213      {
214         return (STATUS_INVALID_PARAMETER);
215      }
216
217    /* delete all atoms */
218    for (i = 0; i < AtomTable->TableSize; i++)
219      {
220
221         Current = AtomTable->Slot[i].Flink;
222         while (Current != &AtomTable->Slot[i])
223           {
224              AtomEntry = (PRTL_ATOM_ENTRY)Current;
225              RtlFreeUnicodeString(&AtomEntry->Name);
226              RemoveEntryList(&AtomEntry->List);
227              ExFreePool(AtomEntry);
228              Current = AtomTable->Slot[i].Flink;
229           }
230
231      }
232
233    RtlpDestroyAtomHandleTable(AtomTable);
234
235    RtlpUnlockAtomTable(AtomTable);
236
237    RtlpDestroyAtomTableLock(AtomTable);
238
239    ExFreePool(AtomTable);
240
241    return STATUS_SUCCESS;
242 }
243
244
245 NTSTATUS STDCALL
246 RtlEmptyAtomTable(IN PRTL_ATOM_TABLE AtomTable,
247                   IN BOOLEAN DeletePinned)
248 {
249    PLIST_ENTRY Current, Next;
250    PRTL_ATOM_ENTRY AtomEntry;
251    ULONG i;
252
253    DPRINT("RtlEmptyAtomTable (AtomTable %p DeletePinned %x)\n",
254           AtomTable, DeletePinned);
255
256    if (RtlpLockAtomTable(AtomTable) == FALSE)
257      {
258         return (STATUS_INVALID_PARAMETER);
259      }
260
261    /* delete all atoms */
262    for (i = 0; i < AtomTable->TableSize; i++)
263      {
264         Current = AtomTable->Slot[i].Flink;
265         while (Current != &AtomTable->Slot[i])
266           {
267              Next = Current->Flink;
268              AtomEntry = (PRTL_ATOM_ENTRY)Current;
269
270              if ((AtomEntry->Locked == FALSE) ||
271                  ((AtomEntry->Locked == TRUE) && (DeletePinned == TRUE)))
272                {
273                   RtlFreeUnicodeString(&AtomEntry->Name);
274
275                   RtlpFreeHandle(AtomTable->HandleTable,
276                                  AtomEntry->Index);
277
278                   RemoveEntryList(&AtomEntry->List);
279                   ExFreePool(AtomEntry);
280                }
281              Current = Next;
282           }
283
284      }
285
286    AtomTable->NumberOfAtoms = 0;
287
288    RtlpUnlockAtomTable(AtomTable);
289
290    return STATUS_SUCCESS;
291 }
292
293
294 NTSTATUS STDCALL
295 RtlAddAtomToAtomTable(IN PRTL_ATOM_TABLE AtomTable,
296                       IN PWSTR AtomName,
297                       OUT PRTL_ATOM Atom)
298 {
299    ULONG Hash;
300    PLIST_ENTRY Current;
301    PRTL_ATOM_ENTRY Entry;
302    USHORT AtomValue;
303    NTSTATUS Status;
304    ULONG AtomIndex;
305
306    DPRINT("RtlAddAtomToAtomTable (AtomTable %p AtomName %S Atom %p)\n",
307           AtomTable, AtomName, Atom);
308
309    if (RtlpCheckIntegerAtom (AtomName, &AtomValue))
310      {
311         /* integer atom */
312         if (AtomValue >= 0xC000)
313           {
314              AtomValue = 0;
315              Status = STATUS_INVALID_PARAMETER;
316           }
317         else
318           {
319              Status = STATUS_SUCCESS;
320           }
321
322         if (Atom)
323           *Atom = (RTL_ATOM)AtomValue;
324
325         return Status;
326      }
327
328    RtlpLockAtomTable(AtomTable);
329
330    /* string atom */
331    Hash = RtlpHashAtomName(AtomTable->TableSize, AtomName);
332
333    /* search for existing atom */
334    Current = AtomTable->Slot[Hash].Flink;
335    while (Current != &AtomTable->Slot[Hash])
336      {
337         Entry = (PRTL_ATOM_ENTRY)Current;
338
339         DPRINT("Comparing %S and %S\n", Entry->Name.Buffer, AtomName);
340         if (_wcsicmp(Entry->Name.Buffer, AtomName) == 0)
341           {
342              Entry->RefCount++;
343              if (Atom)
344                *Atom = (RTL_ATOM)(Entry->Index + 0xC000);
345              RtlpUnlockAtomTable(AtomTable);
346              return STATUS_SUCCESS;
347           }
348         Current = Current->Flink;
349      }
350
351    /* insert new atom */
352    Entry = ExAllocatePool(NonPagedPool,
353                           sizeof(RTL_ATOM_ENTRY));
354    if (Entry == NULL)
355      {
356         RtlpUnlockAtomTable(AtomTable);
357         return STATUS_NO_MEMORY;
358      }
359
360    InsertTailList(&AtomTable->Slot[Hash], &Entry->List)
361    RtlCreateUnicodeString (&Entry->Name,
362                            AtomName);
363    Entry->RefCount = 1;
364    Entry->Locked = FALSE;
365
366    /* FIXME: use general function instead !! */
367    RtlpAllocateHandle(AtomTable->HandleTable,
368                       (PVOID)Entry,
369                       &AtomIndex);
370
371    DPRINT("AtomIndex %x\n", AtomIndex);
372
373    Entry->Index = AtomIndex;
374    AtomTable->NumberOfAtoms++;
375
376    if (Atom)
377      *Atom = (RTL_ATOM)(AtomIndex + 0xC000);
378
379    RtlpUnlockAtomTable(AtomTable);
380
381    return STATUS_SUCCESS;
382 }
383
384
385 NTSTATUS STDCALL
386 RtlDeleteAtomFromAtomTable(IN PRTL_ATOM_TABLE AtomTable,
387                            IN RTL_ATOM Atom)
388 {
389    PRTL_ATOM_ENTRY AtomEntry;
390
391    DPRINT("RtlDeleteAtomFromAtomTable (AtomTable %p Atom %x)\n",
392           AtomTable, Atom);
393
394    if (Atom < 0xC000)
395      {
396         return STATUS_SUCCESS;
397      }
398
399    RtlpLockAtomTable(AtomTable);
400
401    /* FIXME: use general function instead !! */
402    AtomEntry = (PRTL_ATOM_ENTRY)RtlpMapHandleToPointer(AtomTable->HandleTable,
403                                                        (ULONG)Atom - 0xC000);
404    if (AtomEntry == NULL)
405      {
406         RtlpUnlockAtomTable(AtomTable);
407         return STATUS_INVALID_HANDLE;
408      }
409
410    DPRINT("AtomEntry %x\n", AtomEntry);
411    DPRINT("Atom name: %wZ\n", &AtomEntry->Name);
412
413    AtomEntry->RefCount--;
414
415    if (AtomEntry->RefCount == 0)
416      {
417         if (AtomEntry->Locked == TRUE)
418           {
419              DPRINT("Atom %wZ is locked!\n", &AtomEntry->Name);
420
421              RtlpUnlockAtomTable(AtomTable);
422              return STATUS_WAS_LOCKED;
423           }
424
425         DPRINT("Removing atom: %wZ\n", &AtomEntry->Name);
426
427         RtlFreeUnicodeString(&AtomEntry->Name);
428         RemoveEntryList(&AtomEntry->List);
429         ExFreePool(AtomEntry);
430         RtlpFreeHandle(AtomTable->HandleTable,
431                        (ULONG)Atom - 0xC000);
432         AtomTable->NumberOfAtoms++;
433      }
434
435    RtlpUnlockAtomTable(AtomTable);
436
437    return STATUS_SUCCESS;
438 }
439
440
441 NTSTATUS STDCALL
442 RtlLookupAtomInAtomTable(IN PRTL_ATOM_TABLE AtomTable,
443                          IN PWSTR AtomName,
444                          OUT PRTL_ATOM Atom)
445 {
446    ULONG Hash;
447    PLIST_ENTRY Current;
448    PRTL_ATOM_ENTRY Entry;
449    USHORT AtomValue;
450    NTSTATUS Status;
451
452    DPRINT("RtlLookupAtomInAtomTable (AtomTable %p AtomName %S Atom %p)\n",
453           AtomTable, AtomName, Atom);
454
455    if (RtlpCheckIntegerAtom (AtomName, &AtomValue))
456      {
457         /* integer atom */
458         if (AtomValue >= 0xC000)
459           {
460              AtomValue = 0;
461              Status = STATUS_INVALID_PARAMETER;
462           }
463         else
464           {
465              Status = STATUS_SUCCESS;
466           }
467
468         if (Atom)
469           *Atom = (RTL_ATOM)AtomValue;
470
471         return Status;
472      }
473
474    RtlpLockAtomTable(AtomTable);
475
476    /* string atom */
477    Hash = RtlpHashAtomName(AtomTable->TableSize, AtomName);
478
479    /* search for existing atom */
480    Current = AtomTable->Slot[Hash].Flink;
481    while (Current != &AtomTable->Slot[Hash])
482      {
483         Entry = (PRTL_ATOM_ENTRY)Current;
484
485         DPRINT("Comparing %S and %S\n", Entry->Name.Buffer, AtomName);
486         if (_wcsicmp(Entry->Name.Buffer, AtomName) == 0)
487           {
488              if (Atom)
489                *Atom = (RTL_ATOM)(Entry->Index + 0xC000);
490              RtlpUnlockAtomTable(AtomTable);
491              return STATUS_SUCCESS;
492           }
493
494         Current = Current->Flink;
495      }
496
497    return STATUS_OBJECT_NAME_NOT_FOUND;
498 }
499
500
501 NTSTATUS STDCALL
502 RtlPinAtomInAtomTable(IN PRTL_ATOM_TABLE AtomTable,
503                       IN RTL_ATOM Atom)
504 {
505    PRTL_ATOM_ENTRY AtomEntry;
506
507    DPRINT("RtlPinAtomInAtomTable (AtomTable %p Atom %x)\n",
508           AtomTable, Atom);
509
510    if (Atom < 0xC000)
511      {
512         return STATUS_SUCCESS;
513      }
514
515    RtlpLockAtomTable(AtomTable);
516
517    /* FIXME: use general function instead !! */
518    AtomEntry = (PRTL_ATOM_ENTRY)RtlpMapHandleToPointer(AtomTable->HandleTable,
519                                                        (ULONG)Atom - 0xC000);
520    if (AtomEntry == NULL)
521      {
522         RtlpUnlockAtomTable(AtomTable);
523         return STATUS_INVALID_HANDLE;
524      }
525
526    DPRINT("AtomEntry %x\n", AtomEntry);
527    DPRINT("Atom name: %wZ\n", &AtomEntry->Name);
528
529    AtomEntry->Locked = TRUE;
530
531    RtlpUnlockAtomTable(AtomTable);
532
533    return STATUS_SUCCESS;
534 }
535
536
537 NTSTATUS STDCALL
538 RtlQueryAtomInAtomTable(IN PRTL_ATOM_TABLE AtomTable,
539                         IN RTL_ATOM Atom,
540                         IN OUT PULONG RefCount,
541                         IN OUT PULONG PinCount,
542                         IN OUT PWSTR AtomName,
543                         IN OUT PULONG NameLength)
544 {
545    ULONG Length;
546    PRTL_ATOM_ENTRY AtomEntry;
547
548    if (Atom < 0xC000)
549      {
550         if (RefCount != NULL)
551           {
552              *RefCount = 1;
553           }
554
555         if (PinCount != NULL)
556           {
557              *PinCount = 1;
558           }
559
560         if ((AtomName != NULL) && (NameLength != NULL) && (NameLength > 0))
561           {
562              Length = swprintf(AtomName, L"#%lu", (ULONG)Atom);
563              *NameLength = Length * sizeof(WCHAR);
564           }
565
566         return STATUS_SUCCESS;
567      }
568
569    RtlpLockAtomTable(AtomTable);
570
571    /* FIXME: use general function instead !! */
572    AtomEntry = (PRTL_ATOM_ENTRY)RtlpMapHandleToPointer(AtomTable->HandleTable,
573                                                        (ULONG)Atom - 0xC000);
574    if (AtomEntry == NULL)
575      {
576         RtlpUnlockAtomTable(AtomTable);
577         return STATUS_INVALID_HANDLE;
578      }
579
580    DPRINT("AtomEntry %x\n", AtomEntry);
581    DPRINT("Atom name: %wZ\n", &AtomEntry->Name);
582
583    if (RefCount != NULL)
584      {
585         *RefCount = AtomEntry->RefCount;
586      }
587
588    if (PinCount != NULL)
589      {
590         *PinCount = (ULONG)AtomEntry->Locked;
591      }
592
593    if ((AtomName != NULL) && (NameLength != NULL))
594      {
595         if (*NameLength < AtomEntry->Name.Length)
596           {
597              *NameLength = AtomEntry->Name.Length;
598              RtlpUnlockAtomTable(AtomTable);
599              return STATUS_BUFFER_TOO_SMALL;
600           }
601
602         Length = swprintf(AtomName, L"%s", AtomEntry->Name.Buffer);
603         *NameLength = Length * sizeof(WCHAR);
604      }
605
606    RtlpUnlockAtomTable(AtomTable);
607
608    return STATUS_SUCCESS;
609 }
610
611
612 /* INTERNAL FUNCTIONS ********************************************************/
613
614 static PRTL_ATOM_TABLE
615 RtlpGetGlobalAtomTable(VOID)
616 {
617    NTSTATUS Status;
618
619    if (GlobalAtomTable != NULL)
620      return GlobalAtomTable;
621
622    Status = RtlCreateAtomTable(37, &GlobalAtomTable);
623    if (!NT_SUCCESS(Status))
624      return NULL;
625
626    return GlobalAtomTable;
627 }
628
629
630 static ULONG
631 RtlpHashAtomName(ULONG TableSize,
632                  PWSTR AtomName)
633 {
634    ULONG q = 0;
635    PWCHAR p;
636
637    DPRINT("RtlpHashAtomName(TableSize %ld AtomName '%S')\n",
638           TableSize, AtomName);
639
640    /* convert the string to an internal representation */
641    p = AtomName;
642    while (*p != 0)
643      {
644         q += (ULONG)towupper(*p);
645         p++;
646      }
647
648    DPRINT("q %lu Hash %lu\n", q, q % TableSize);
649
650    return (q % TableSize);
651 }
652
653
654 static BOOLEAN
655 RtlpCheckIntegerAtom(PWSTR AtomName,
656                      PUSHORT AtomValue)
657 {
658    UNICODE_STRING AtomString;
659    ULONG LongValue;
660    USHORT LoValue;
661    PWCHAR p;
662
663    DPRINT("RtlpCheckIntegerAtom(AtomName '%S' AtomValue %p)\n",
664           AtomName, AtomValue);
665
666    if (!((ULONG)AtomName & 0xFFFF0000))
667      {
668         LoValue = (USHORT)((ULONG)AtomName & 0xFFFF);
669
670         if (LoValue >= 0xC000)
671           return FALSE;
672
673         if (LoValue == 0)
674           LoValue = 0xC000;
675
676         if (AtomValue != NULL)
677           *AtomValue = LoValue;
678
679         return TRUE;
680      }
681
682    if (*AtomName != L'#')
683      return FALSE;
684
685    p = AtomName;
686    p++;
687    while (*p)
688      {
689         if ((*p < L'0') || (*p > L'9'))
690           return FALSE;
691         p++;
692      }
693
694    p = AtomName;
695    p++;
696    RtlInitUnicodeString(&AtomString,
697                         p);
698
699    DPRINT1("AtomString: %wZ\n", &AtomString);
700
701    RtlUnicodeStringToInteger(&AtomString,10, &LongValue);
702
703    DPRINT1("LongValue: %lu\n", LongValue);
704
705    *AtomValue = (USHORT)(LongValue & 0x0000FFFF);
706
707    return TRUE;
708 }
709
710
711 /* lock functions */
712
713 static NTSTATUS
714 RtlpInitAtomTableLock(PRTL_ATOM_TABLE AtomTable)
715 {
716    AtomTable->Lock = ExAllocatePool(NonPagedPool,
717                                     sizeof(FAST_MUTEX));
718    if (AtomTable->Lock == NULL)
719      return STATUS_NO_MEMORY;
720
721    ExInitializeFastMutex((PFAST_MUTEX)AtomTable->Lock);
722
723    return STATUS_SUCCESS;
724 }
725
726
727 static VOID
728 RtlpDestroyAtomTableLock(PRTL_ATOM_TABLE AtomTable)
729 {
730    if (AtomTable->Lock)
731      ExFreePool(AtomTable->Lock);
732 }
733
734
735 static BOOLEAN
736 RtlpLockAtomTable(PRTL_ATOM_TABLE AtomTable)
737 {
738 //   ExAcquireFastMutex((PFAST_MUTEX)AtomTable->Lock);
739    return TRUE;
740 }
741
742 static VOID
743 RtlpUnlockAtomTable(PRTL_ATOM_TABLE AtomTable)
744 {
745 //   ExReleaseFastMutex((PFAST_MUTEX)AtomTable->Lock);
746 }
747
748 #if 0
749 static NTSTATUS
750 RtlpInitAtomTableLock(PRTL_ATOM_TABLE AtomTable)
751 {
752    AtomTable->Lock = RtlAllocateHeap(RtlGetProcessHeap(),
753                                      HEAP_ZERO_MEMORY,
754                                      sizeof(CRITICAL_SECTION));
755    if (AtomTable->Lock == NULL)
756      return STATUS_NO_MEMORY;
757
758    RtlInitializeCriticalSection((PCRITICAL_SECTION)AtomTable->Lock);
759
760    return STATUS_SUCCESS;
761 }
762
763
764 static VOID
765 RtlpDestroyAtomTableLock(PRTL_ATOM_TABLE AtomTable)
766 {
767    if (AtomTable->Lock)
768      {
769         RtlDeleteCriticalSection((PCRITICAL_SECTION)AtomTable->Lock);
770         RtlFreeHeap(RtlGetProcessHeap(),
771                     0,
772                     AtomTable->Lock);
773         AtomTable->Lock = NULL;
774      }
775 }
776
777
778 static BOOLEAN
779 RtlpLockAtomTable(PRTL_ATOM_TABLE AtomTable)
780 {
781    RtlEnterCriticalSection((PCRITICAL_SECTION)AtomTable->Lock);
782    return TRUE;
783 }
784
785
786 static VOID
787 RtlpUnlockAtomTable(PRTL_ATOM_TABLE AtomTable)
788 {
789    RtlLeaveCriticalSection((PCRITICAL_SECTION)AtomTable->Lock);
790 }
791 #endif
792
793 /* handle functions */
794
795 static BOOLEAN
796 RtlpCreateAtomHandleTable(PRTL_ATOM_TABLE AtomTable)
797 {
798    AtomTable->HandleTable = ExAllocatePool(NonPagedPool,
799                                            sizeof(RTL_HANDLE_TABLE));
800    if (AtomTable->HandleTable == NULL)
801      return FALSE;
802
803    RtlpInitializeHandleTable(0xCFFF,
804                              (PRTL_HANDLE_TABLE)AtomTable->HandleTable);
805
806    return TRUE;
807 }
808
809
810 static VOID
811 RtlpDestroyAtomHandleTable(PRTL_ATOM_TABLE AtomTable)
812 {
813    if (AtomTable->HandleTable)
814      {
815         RtlpDestroyHandleTable((PRTL_HANDLE_TABLE)AtomTable->HandleTable);
816         ExFreePool(AtomTable->HandleTable);
817         AtomTable->HandleTable = NULL;
818      }
819 }
820
821
822 static NTSTATUS
823 RtlpQueryAtomInformation(PRTL_ATOM_TABLE AtomTable,
824                          RTL_ATOM Atom,
825                          PATOM_BASIC_INFORMATION AtomInformation,
826                          ULONG AtomInformationLength,
827                          PULONG ReturnLength)
828 {
829    NTSTATUS Status;
830    ULONG UsageCount;
831    ULONG Flags;
832    ULONG NameLength;
833
834    NameLength = AtomInformationLength - sizeof(ATOM_BASIC_INFORMATION) + sizeof(WCHAR);
835    Status = RtlQueryAtomInAtomTable(AtomTable,
836                                     Atom,
837                                     &UsageCount,
838                                     &Flags,
839                                     AtomInformation->Name,
840                                     &NameLength);
841    if (!NT_SUCCESS(Status))
842      {
843         return Status;
844      }
845
846    DPRINT1("NameLength: %lu\n", NameLength);
847
848    if (ReturnLength != NULL)
849      {
850         *ReturnLength = NameLength + sizeof(ATOM_BASIC_INFORMATION);
851      }
852
853    if (NameLength + sizeof(ATOM_BASIC_INFORMATION) > AtomInformationLength)
854      {
855         return STATUS_BUFFER_TOO_SMALL;
856      }
857
858    AtomInformation->UsageCount = (USHORT)UsageCount;
859    AtomInformation->Flags = (USHORT)Flags;
860    AtomInformation->NameLength = (USHORT)NameLength;
861
862    return STATUS_SUCCESS;
863 }
864
865
866 static NTSTATUS
867 RtlpQueryAtomTableInformation(PRTL_ATOM_TABLE AtomTable,
868                               RTL_ATOM Atom,
869                               PATOM_TABLE_INFORMATION AtomInformation,
870                               ULONG AtomInformationLength,
871                               PULONG ReturnLength)
872 {
873    PLIST_ENTRY Current, Next;
874    PRTL_ATOM_ENTRY AtomEntry;
875    ULONG Length;
876    ULONG i, j;
877
878    Length = sizeof(ATOM_TABLE_INFORMATION);
879    if (AtomTable->NumberOfAtoms > 1)
880      {
881         Length += ((AtomTable->NumberOfAtoms - 1)* sizeof(RTL_ATOM));
882      }
883
884    DPRINT1("RequiredLength: %lu\n", Length);
885
886    if (ReturnLength != NULL)
887      {
888         *ReturnLength = Length;
889      }
890
891    if (Length > AtomInformationLength)
892      {
893         return STATUS_BUFFER_TOO_SMALL;
894      }
895
896    AtomInformation->NumberOfAtoms = AtomTable->NumberOfAtoms;
897
898    j = 0;
899    for (i = 0; i < AtomTable->TableSize; i++)
900      {
901         Current = AtomTable->Slot[i].Flink;
902         while (Current != &AtomTable->Slot[i])
903           {
904              Next = Current->Flink;
905              AtomEntry = (PRTL_ATOM_ENTRY)Current;
906
907              AtomInformation->Atoms[j] = AtomEntry->Index + 0xC000;
908              j++;
909
910              Current = Next;
911           }
912      }
913
914    return STATUS_SUCCESS;
915 }
916
917 /* EOF */