Reverted latest changes.
[reactos.git] / reactos / ntoskrnl / rtl / atom.c
1 /* $Id: atom.c,v 1.4 2002/09/08 10:23:41 chorns Exp $
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 */