ReactOS 0.4.15-dev-7924-g5949c20
handle.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/ex/handle.c
5 * PURPOSE: Generic Executive Handle Tables
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7 * Thomas Weidenmueller <w3seek@reactos.com>
8 */
9
10/* INCLUDES ******************************************************************/
11
12#include <ntoskrnl.h>
13#define NDEBUG
14#include <debug.h>
15
16/* GLOBALS *******************************************************************/
17
20#define SizeOfHandle(x) (sizeof(HANDLE) * (x))
21#define INDEX_TO_HANDLE_VALUE(x) ((x) << HANDLE_TAG_BITS)
22
23/* PRIVATE FUNCTIONS *********************************************************/
24
25#ifdef _WIN64
26#define strtoulptr strtoull
27#else
28#define strtoulptr strtoul
29#endif
30
31CODE_SEG("INIT")
32VOID
35{
36 /* Initialize the list of handle tables and the lock */
39}
40
45{
46 ULONG TableLevel;
47 ULONG_PTR TableBase;
48 PHANDLE_TABLE_ENTRY HandleArray, Entry;
49 PVOID *PointerArray;
50
51 /* Clear the tag bits */
52 Handle.TagBits = 0;
53
54 /* Check if the handle is in the allocated range */
55 if (Handle.Value >= HandleTable->NextHandleNeedingPool)
56 {
57 return NULL;
58 }
59
60 /* Get the table code */
61 TableBase = HandleTable->TableCode;
62
63 /* Extract the table level and actual table base */
64 TableLevel = (ULONG)(TableBase & 3);
65 TableBase &= ~3;
66
67 PointerArray = (PVOID*)TableBase;
68 HandleArray = (PHANDLE_TABLE_ENTRY)TableBase;
69
70 /* Check what level we're running at */
71 switch (TableLevel)
72 {
73 case 2:
74
75 /* Get the mid level pointer array */
76 PointerArray = PointerArray[Handle.HighIndex];
77 ASSERT(PointerArray != NULL);
78
79 /* Fall through */
80 case 1:
81
82 /* Get the handle array */
83 HandleArray = PointerArray[Handle.MidIndex];
84 ASSERT(HandleArray != NULL);
85
86 /* Fall through */
87 case 0:
88
89 /* Get the entry using the low index */
90 Entry = &HandleArray[Handle.LowIndex];
91
92 /* All done */
93 break;
94
95 default:
96
98 Entry = NULL;
99 }
100
101 /* Return the handle entry */
102 return Entry;
103}
104
105PVOID
106NTAPI
108 IN SIZE_T Size)
109{
112
113 /* Do the allocation */
115 if (Buffer)
116 {
117 /* Clear the memory */
119
120 /* Check if we have a process to charge quota */
121 if (Process)
122 {
123 /* Charge quota */
125 if (!NT_SUCCESS(Status))
126 {
128 return NULL;
129 }
130 }
131 }
132
133 /* Return the allocated memory */
134 return Buffer;
135}
136
137PVOID
138NTAPI
140 IN SIZE_T Size)
141{
144
145 /* Do the allocation */
147 if (Buffer)
148 {
149 /* Check if we have a process to charge quota */
150 if (Process)
151 {
152 /* Charge quota */
154 if (!NT_SUCCESS(Status))
155 {
157 return NULL;
158 }
159 }
160 }
161
162 /* Return the allocated memory */
163 return Buffer;
164}
165
166VOID
167NTAPI
170 IN SIZE_T Size)
171{
172 /* Free the buffer */
174 if (Process)
175 {
176 /* Release quota */
178 }
179}
180
181VOID
182NTAPI
185{
186 /* Check if we have an entry */
187 if (TableEntry[0].Object)
188 {
189 /* Free the entry */
194 }
195
196 /* Free the table */
198}
199
200VOID
201NTAPI
203{
204 PEPROCESS Process = HandleTable->QuotaProcess;
205 ULONG i, j;
206 ULONG_PTR TableCode = HandleTable->TableCode;
207 ULONG_PTR TableBase = TableCode & ~3;
208 ULONG TableLevel = (ULONG)(TableCode & 3);
209 PHANDLE_TABLE_ENTRY Level1, *Level2, **Level3;
210 PAGED_CODE();
211
212 /* Check which level we're at */
213 if (TableLevel == 0)
214 {
215 /* Select the first level table base and just free it */
216 Level1 = (PVOID)TableBase;
218 }
219 else if (TableLevel == 1)
220 {
221 /* Select the second level table base */
222 Level2 = (PVOID)TableBase;
223
224 /* Loop each mid level entry */
225 for (i = 0; i < MID_LEVEL_ENTRIES; i++)
226 {
227 /* Leave if we've reached the last entry */
228 if (!Level2[i]) break;
229
230 /* Free the second level table */
232 }
233
234 /* Free the second level table */
236 }
237 else
238 {
239 /* Select the third level table base */
240 Level3 = (PVOID)TableBase;
241
242 /* Loop each high level entry */
243 for (i = 0; i < HIGH_LEVEL_ENTRIES; i++)
244 {
245 /* Leave if we've reached the last entry */
246 if (!Level3[i]) break;
247
248 /* Loop each mid level entry */
249 for (j = 0; j < MID_LEVEL_ENTRIES; j++)
250 {
251 /* Leave if we've reached the last entry */
252 if (!Level3[i][j]) break;
253
254 /* Free the second level table */
255 ExpFreeLowLevelTable(Process, Level3[i][j]);
256 }
257
258 /* Free the third level table entry */
260 }
261
262 /* Free the third level table */
264 Level3,
266 }
267
268 /* Free the actual table and check if we need to release quota */
270 if (Process)
271 {
272 /* Release the quota it was taking up */
274 }
275}
276
277VOID
278NTAPI
281 IN PHANDLE_TABLE_ENTRY HandleTableEntry)
282{
283 ULONG OldValue, *Free;
284 ULONG LockIndex;
285 PAGED_CODE();
286
287 /* Sanity checks */
288 ASSERT(HandleTableEntry->Object == NULL);
289 ASSERT(HandleTableEntry == ExpLookupHandleTableEntry(HandleTable, Handle));
290
291 /* Decrement the handle count */
292 InterlockedDecrement(&HandleTable->HandleCount);
293
294 /* Mark the handle as free */
295 Handle.TagBits = 0;
296
297 /* Check if we're FIFO */
298 if (!HandleTable->StrictFIFO)
299 {
300 /* Select a lock index */
301 LockIndex = Handle.Index % 4;
302
303 /* Select which entry to use */
304 Free = (HandleTable->HandleTableLock[LockIndex].Locked) ?
305 &HandleTable->FirstFree : &HandleTable->LastFree;
306 }
307 else
308 {
309 /* No need to worry about locking, take the last entry */
310 Free = &HandleTable->LastFree;
311 }
312
313 /* Start value change loop */
314 for (;;)
315 {
316 /* Get the current value and write */
317 OldValue = *Free;
318 HandleTableEntry->NextFreeTableEntry = OldValue;
319 if (InterlockedCompareExchange((PLONG)Free, Handle.AsULONG, OldValue) == OldValue)
320 {
321 /* Break out, we're done. Make sure the handle value makes sense */
322 ASSERT((OldValue & FREE_HANDLE_MASK) <
323 HandleTable->NextHandleNeedingPool);
324 break;
325 }
326 }
327}
328
330NTAPI
332 IN BOOLEAN NewTable)
333{
335 PHANDLE_TABLE_ENTRY HandleTableTable, HandleEntry;
336 ULONG i;
338 PAGED_CODE();
339
340 /* Allocate the table */
342 sizeof(HANDLE_TABLE),
344 if (!HandleTable) return NULL;
345
346 /* Check if we have a process */
347 if (Process)
348 {
349 /* Charge quota */
351 if (!NT_SUCCESS(Status))
352 {
354 return NULL;
355 }
356 }
357
358 /* Clear the table */
360
361 /* Now allocate the first level structures */
363 if (!HandleTableTable)
364 {
365 /* Failed, free the table */
367
368 /* Return the quota it was taking up */
369 if (Process)
370 {
372 }
373
374 return NULL;
375 }
376
377 /* Write the pointer to our first level structures */
378 HandleTable->TableCode = (ULONG_PTR)HandleTableTable;
379
380 /* Initialize the first entry */
381 HandleEntry = &HandleTableTable[0];
382 HandleEntry->NextFreeTableEntry = -2;
383 HandleEntry->Value = 0;
384
385 /* Check if this is a new table */
386 if (NewTable)
387 {
388 /* Go past the root entry */
389 HandleEntry++;
390
391 /* Loop every low level entry */
392 for (i = 1; i < (LOW_LEVEL_ENTRIES - 1); i++)
393 {
394 /* Set up the free data */
395 HandleEntry->Value = 0;
396 HandleEntry->NextFreeTableEntry = INDEX_TO_HANDLE_VALUE(i + 1);
397
398 /* Move to the next entry */
399 HandleEntry++;
400 }
401
402 /* Terminate the last entry */
403 HandleEntry->Value = 0;
404 HandleEntry->NextFreeTableEntry = 0;
405 HandleTable->FirstFree = INDEX_TO_HANDLE_VALUE(1);
406 }
407
408 /* Set the next handle needing pool after our allocated page from above */
409 HandleTable->NextHandleNeedingPool = INDEX_TO_HANDLE_VALUE(LOW_LEVEL_ENTRIES);
410
411 /* Setup the rest of the handle table data */
412 HandleTable->QuotaProcess = Process;
413 HandleTable->UniqueProcessId = PsGetCurrentProcess()->UniqueProcessId;
414 HandleTable->Flags = 0;
415
416 /* Loop all the handle table locks */
417 for (i = 0; i < 4; i++)
418 {
419 /* Initialize the handle table lock */
420 ExInitializePushLock(&HandleTable->HandleTableLock[i]);
421 }
422
423 /* Initialize the contention event lock and return the lock */
424 ExInitializePushLock(&HandleTable->HandleContentionEvent);
425 return HandleTable;
426}
427
429NTAPI
431 IN BOOLEAN DoInit)
432{
433 ULONG i, Base;
434 PHANDLE_TABLE_ENTRY Low, HandleEntry;
435
436 /* Allocate the low level table */
438 PAGE_SIZE);
439 if (!Low) return NULL;
440
441 /* Setup the initial entry */
442 HandleEntry = &Low[0];
443 HandleEntry->NextFreeTableEntry = -2;
444 HandleEntry->Value = 0;
445
446 /* Check if we're initializing */
447 if (DoInit)
448 {
449 /* Go to the next entry and the base entry */
450 HandleEntry++;
451 Base = HandleTable->NextHandleNeedingPool + INDEX_TO_HANDLE_VALUE(2);
452
453 /* Loop each entry */
454 for (i = Base;
457 {
458 /* Free this entry and move on to the next one */
459 HandleEntry->NextFreeTableEntry = i;
460 HandleEntry->Value = 0;
461 HandleEntry++;
462 }
463
464 /* Terminate the last entry */
465 HandleEntry->NextFreeTableEntry = 0;
466 HandleEntry->Value = 0;
467 }
468
469 /* Return the low level table */
470 return Low;
471}
472
474NTAPI
476 IN BOOLEAN DoInit,
477 OUT PHANDLE_TABLE_ENTRY *LowTableEntry)
478{
480
481 /* Allocate the mid level table */
482 Mid = ExpAllocateTablePagedPool(HandleTable->QuotaProcess, PAGE_SIZE);
483 if (!Mid) return NULL;
484
485 /* Allocate a new low level for it */
487 if (!Low)
488 {
489 /* We failed, free the mid table */
490 ExpFreeTablePagedPool(HandleTable->QuotaProcess, Mid, PAGE_SIZE);
491 return NULL;
492 }
493
494 /* Link the tables and return the pointer */
495 Mid[0] = Low;
496 *LowTableEntry = Low;
497 return Mid;
498}
499
501NTAPI
503 IN BOOLEAN DoInit)
504{
505 ULONG i, j, Index;
506 PHANDLE_TABLE_ENTRY Low = NULL, *Mid, **High, *SecondLevel, **ThirdLevel;
507 ULONG NewFree, FirstFree;
508 PVOID Value;
509 ULONG_PTR TableCode = HandleTable->TableCode;
510 ULONG_PTR TableBase = TableCode & ~3;
511 ULONG TableLevel = (ULONG)(TableCode & 3);
512 PAGED_CODE();
513
514 /* Check how many levels we already have */
515 if (TableLevel == 0)
516 {
517 /* Allocate a mid level, since we only have a low level */
519 if (!Mid) return FALSE;
520
521 /* Link up the tables */
522 Mid[1] = Mid[0];
523 Mid[0] = (PVOID)TableBase;
524
525 /* Write the new level and attempt to change the table code */
526 TableBase = ((ULONG_PTR)Mid) | 1;
527 Value = InterlockedExchangePointer((PVOID*)&HandleTable->TableCode, (PVOID)TableBase);
528 }
529 else if (TableLevel == 1)
530 {
531 /* Setup the 2nd level table */
532 SecondLevel = (PVOID)TableBase;
533
534 /* Get if the next index can fit in the table */
535 i = HandleTable->NextHandleNeedingPool /
537 if (i < MID_LEVEL_ENTRIES)
538 {
539 /* We need to allocate a new table */
541 if (!Low) return FALSE;
542
543 /* Update the table */
544 Value = InterlockedExchangePointer((PVOID*)&SecondLevel[i], Low);
545 ASSERT(Value == NULL);
546 }
547 else
548 {
549 /* We need a new high level table */
552 if (!High) return FALSE;
553
554 /* Allocate a new mid level table as well */
556 if (!Mid)
557 {
558 /* We failed, free the high level table as well */
560 High,
562 return FALSE;
563 }
564
565 /* Link up the tables */
566 High[0] = (PVOID)TableBase;
567 High[1] = Mid;
568
569 /* Write the new table and change the table code */
570 TableBase = ((ULONG_PTR)High) | 2;
572 (PVOID)TableBase);
573 }
574 }
575 else if (TableLevel == 2)
576 {
577 /* Setup the 3rd level table */
578 ThirdLevel = (PVOID)TableBase;
579
580 /* Get the index and check if it can fit */
581 i = HandleTable->NextHandleNeedingPool / INDEX_TO_HANDLE_VALUE(MAX_MID_INDEX);
582 if (i >= HIGH_LEVEL_ENTRIES) return FALSE;
583
584 /* Check if there's no mid-level table */
585 if (!ThirdLevel[i])
586 {
587 /* Allocate a new mid level table */
589 if (!Mid) return FALSE;
590
591 /* Update the table pointer */
592 Value = InterlockedExchangePointer((PVOID*)&ThirdLevel[i], Mid);
593 ASSERT(Value == NULL);
594 }
595 else
596 {
597 /* We have one, check at which index we should insert our entry */
598 Index = (HandleTable->NextHandleNeedingPool / INDEX_TO_HANDLE_VALUE(1)) -
601
602 /* Allocate a new low level */
604 if (!Low) return FALSE;
605
606 /* Update the table pointer */
607 Value = InterlockedExchangePointer((PVOID*)&ThirdLevel[i][j], Low);
608 ASSERT(Value == NULL);
609 }
610 }
611 else
612 {
613 /* Something is really broken */
614 ASSERT(FALSE);
615 }
616
617 /* Update the index of the next handle */
618 Index = InterlockedExchangeAdd((PLONG) &HandleTable->NextHandleNeedingPool,
620
621 /* Check if need to initialize the table */
622 if (DoInit)
623 {
624 /* Create a new index number */
626
627 /* Start free index change loop */
628 for (;;)
629 {
630 /* Setup the first free index */
631 FirstFree = HandleTable->FirstFree;
632 Low[LOW_LEVEL_ENTRIES - 1].NextFreeTableEntry = FirstFree;
633
634 /* Change the index */
635 NewFree = InterlockedCompareExchange((PLONG) &HandleTable->FirstFree,
636 Index,
637 FirstFree);
638 if (NewFree == FirstFree) break;
639 }
640 }
641
642 /* All done */
643 return TRUE;
644}
645
646ULONG
647NTAPI
649{
650 ULONG LastFree, i;
651
652 /* Clear the last free index */
653 LastFree = InterlockedExchange((PLONG) &HandleTable->LastFree, 0);
654
655 /* Check if we had no index */
656 if (!LastFree) return LastFree;
657
658 /* Acquire the locks we need */
659 for (i = 1; i < 4; i++)
660 {
661 /* Acquire this lock exclusively */
662 ExWaitOnPushLock(&HandleTable->HandleTableLock[i]);
663 }
664
665 /* Check if we're not strict FIFO */
666 if (!HandleTable->StrictFIFO)
667 {
668 /* Update the first free index */
669 if (!InterlockedCompareExchange((PLONG) &HandleTable->FirstFree, LastFree, 0))
670 {
671 /* We're done, exit */
672 return LastFree;
673 }
674 }
675
676 /* We are strict FIFO, we need to reverse the entries */
677 ASSERT(FALSE);
678 return LastFree;
679}
680
682NTAPI
684 OUT PEXHANDLE NewHandle)
685{
686 ULONG OldValue, NewValue, NewValue1;
688 EXHANDLE Handle, OldHandle;
690 ULONG i;
691
692 /* Start allocation loop */
693 for (;;)
694 {
695 /* Get the current link */
696 OldValue = HandleTable->FirstFree;
697 while (!OldValue)
698 {
699 /* No free entries remain, lock the handle table */
701 ExAcquirePushLockExclusive(&HandleTable->HandleTableLock[0]);
702
703 /* Check the value again */
704 OldValue = HandleTable->FirstFree;
705 if (OldValue)
706 {
707 /* Another thread has already created a new level, bail out */
708 ExReleasePushLockExclusive(&HandleTable->HandleTableLock[0]);
710 break;
711 }
712
713 /* Now move any free handles */
715 if (OldValue)
716 {
717 /* Another thread has already moved them, bail out */
718 ExReleasePushLockExclusive(&HandleTable->HandleTableLock[0]);
720 break;
721 }
722
723 /* We're the first one through, so do the actual allocation */
725
726 /* Unlock the table and get the value now */
727 ExReleasePushLockExclusive(&HandleTable->HandleTableLock[0]);
729 OldValue = HandleTable->FirstFree;
730
731 /* Check if allocation failed */
732 if (!Result)
733 {
734 /* Check if nobody else went through here */
735 if (!OldValue)
736 {
737 /* We're still the only thread around, so fail */
738 NewHandle->GenericHandleOverlay = NULL;
739 return NULL;
740 }
741 }
742 }
743
744 /* We made it, write the current value */
745 Handle.Value = (OldValue & FREE_HANDLE_MASK);
746
747 /* Lookup the entry for this handle */
749
750 /* Get an available lock and acquire it */
751 OldHandle.Value = OldValue;
752 i = OldHandle.Index % 4;
754 ExAcquirePushLockShared(&HandleTable->HandleTableLock[i]);
755
756 /* Check if the value changed after acquiring the lock */
757 if (OldValue != *(volatile ULONG*)&HandleTable->FirstFree)
758 {
759 /* It did, so try again */
760 ExReleasePushLockShared(&HandleTable->HandleTableLock[i]);
762 continue;
763 }
764
765 /* Now get the next value and do the compare */
766 NewValue = *(volatile ULONG*)&Entry->NextFreeTableEntry;
767 NewValue1 = InterlockedCompareExchange((PLONG) &HandleTable->FirstFree,
768 NewValue,
769 OldValue);
770
771 /* The change was done, so release the lock */
772 ExReleasePushLockShared(&HandleTable->HandleTableLock[i]);
774
775 /* Check if the compare was successful */
776 if (NewValue1 == OldValue)
777 {
778 /* Make sure that the new handle is in range, and break out */
779 ASSERT((NewValue & FREE_HANDLE_MASK) <
780 HandleTable->NextHandleNeedingPool);
781 break;
782 }
783 else
784 {
785 /* The compare failed, make sure we expected it */
786 ASSERT((NewValue1 & FREE_HANDLE_MASK) !=
787 (OldValue & FREE_HANDLE_MASK));
788 }
789 }
790
791 /* Increase the number of handles */
792 InterlockedIncrement(&HandleTable->HandleCount);
793
794 /* Return the handle and the entry */
795 *NewHandle = Handle;
796 return Entry;
797}
798
800NTAPI
802{
804 PAGED_CODE();
805
806 /* Allocate the handle table */
808 if (!HandleTable) return NULL;
809
810 /* Acquire the handle table lock */
813
814 /* Insert it into the list */
816
817 /* Release the lock */
820
821 /* Return the handle table */
822 return HandleTable;
823}
824
825HANDLE
826NTAPI
828 IN PHANDLE_TABLE_ENTRY HandleTableEntry)
829{
831 PHANDLE_TABLE_ENTRY NewEntry;
832 PAGED_CODE();
833
834 /* Start with a clean handle */
835 Handle.GenericHandleOverlay = NULL;
836
837 /* Allocate a new entry */
839 if (NewEntry)
840 {
841 /* Enter a critical region */
843
844 /* Write the entry */
845 *NewEntry = *HandleTableEntry;
846
847 /* Unlock it and leave the critical region */
850 }
851
852 /* Return the handle value */
853 return Handle.GenericHandleOverlay;
854}
855
856VOID
857NTAPI
859 IN PHANDLE_TABLE_ENTRY HandleTableEntry)
860{
861 LONG_PTR OldValue;
862 EX_PUSH_LOCK_WAIT_BLOCK WaitBlock;
863
864 /* Block on the pushlock */
865 ExBlockPushLock(&HandleTable->HandleContentionEvent, &WaitBlock);
866
867 /* Get the current value and check if it's been unlocked */
868 OldValue = HandleTableEntry->Value;
869 if (!(OldValue) || (OldValue & EXHANDLE_TABLE_ENTRY_LOCK_BIT))
870 {
871 /* Unblock the pushlock and return */
872 ExfUnblockPushLock(&HandleTable->HandleContentionEvent, &WaitBlock);
873 }
874 else
875 {
876 /* Wait for it to be unblocked */
877 ExWaitForUnblockPushLock(&HandleTable->HandleContentionEvent,
878 &WaitBlock);
879 }
880}
881
883NTAPI
885 IN PHANDLE_TABLE_ENTRY HandleTableEntry)
886{
887 LONG_PTR NewValue, OldValue;
888
889 /* Sanity check */
890 ASSERT((KeGetCurrentThread()->CombinedApcDisable != 0) ||
892
893 /* Start lock loop */
894 for (;;)
895 {
896 /* Get the current value and check if it's locked */
897 OldValue = *(volatile LONG_PTR *)&HandleTableEntry->Object;
899 {
900 /* It's not locked, remove the lock bit to lock it */
901 NewValue = OldValue & ~EXHANDLE_TABLE_ENTRY_LOCK_BIT;
902 if (InterlockedCompareExchangePointer(&HandleTableEntry->Object,
903 (PVOID)NewValue,
904 (PVOID)OldValue) == (PVOID)OldValue)
905 {
906 /* We locked it, get out */
907 return TRUE;
908 }
909 }
910 else
911 {
912 /* We couldn't lock it, bail out if it's been freed */
913 if (!OldValue) return FALSE;
914 }
915
916 /* It's locked, wait for it to be unlocked */
917 ExpBlockOnLockedHandleEntry(HandleTable, HandleTableEntry);
918 }
919}
920
921VOID
922NTAPI
924 IN PHANDLE_TABLE_ENTRY HandleTableEntry)
925{
926 LONG_PTR OldValue;
927 PAGED_CODE();
928
929 /* Sanity check */
930 ASSERT((KeGetCurrentThread()->CombinedApcDisable != 0) ||
932
933 /* Set the lock bit and make sure it wasn't earlier */
934 OldValue = InterlockedOr((PLONG) &HandleTableEntry->Value,
936 ASSERT((OldValue & EXHANDLE_TABLE_ENTRY_LOCK_BIT) == 0);
937
938 /* Unblock any waiters */
939 ExfUnblockPushLock(&HandleTable->HandleContentionEvent, NULL);
940}
941
942VOID
943NTAPI
945{
946 PAGED_CODE();
947
948 /* Acquire the table lock */
951
952 /* Remove the table and reset the list */
953 RemoveEntryList(&HandleTable->HandleTableList);
954 InitializeListHead(&HandleTable->HandleTableList);
955
956 /* Release the lock */
959}
960
961VOID
962NTAPI
964 IN PVOID DestroyHandleProcedure OPTIONAL)
965{
966 PAGED_CODE();
967
968 /* Remove the handle from the list */
970
971 /* Check if we have a destroy callback */
972 if (DestroyHandleProcedure)
973 {
974 /* FIXME: */
975 ASSERT(FALSE);
976 }
977
978 /* Free the handle table */
980}
981
983NTAPI
986 IN PHANDLE_TABLE_ENTRY HandleTableEntry OPTIONAL)
987{
988 EXHANDLE ExHandle;
990 PAGED_CODE();
991
992 /* Setup the actual handle value */
993 ExHandle.GenericHandleOverlay = Handle;
994
995 /* Enter a critical region and check if we have to lookup the handle */
997 if (!HandleTableEntry)
998 {
999 /* Lookup the entry */
1000 HandleTableEntry = ExpLookupHandleTableEntry(HandleTable, ExHandle);
1001
1002 /* Make sure that we found an entry, and that it's valid */
1003 if (!(HandleTableEntry) ||
1004 !(HandleTableEntry->Object) ||
1005 (HandleTableEntry->NextFreeTableEntry == -2))
1006 {
1007 /* Invalid handle, fail */
1009 return FALSE;
1010 }
1011
1012 /* Lock the entry */
1013 if (!ExpLockHandleTableEntry(HandleTable, HandleTableEntry))
1014 {
1015 /* Couldn't lock, fail */
1017 return FALSE;
1018 }
1019 }
1020 else
1021 {
1022 /* Make sure the handle is locked */
1023 ASSERT((HandleTableEntry->Value & EXHANDLE_TABLE_ENTRY_LOCK_BIT) == 0);
1024 }
1025
1026 /* Clear the handle */
1027 Object = InterlockedExchangePointer((PVOID*)&HandleTableEntry->Object, NULL);
1028
1029 /* Sanity checks */
1030 ASSERT(Object != NULL);
1032
1033 /* Unblock the pushlock */
1034 ExfUnblockPushLock(&HandleTable->HandleContentionEvent, NULL);
1035
1036 /* Free the actual entry */
1037 ExpFreeHandleTableEntry(HandleTable, ExHandle, HandleTableEntry);
1038
1039 /* If we got here, return success */
1041 return TRUE;
1042}
1043
1045NTAPI
1048{
1049 EXHANDLE ExHandle;
1050 PHANDLE_TABLE_ENTRY HandleTableEntry;
1051 PAGED_CODE();
1052
1053 /* Set the handle value */
1054 ExHandle.GenericHandleOverlay = Handle;
1055
1056 /* Fail if we got an invalid index */
1057 if (!(ExHandle.Index & (LOW_LEVEL_ENTRIES - 1))) return NULL;
1058
1059 /* Do the lookup */
1060 HandleTableEntry = ExpLookupHandleTableEntry(HandleTable, ExHandle);
1061 if (!HandleTableEntry) return NULL;
1062
1063 /* Lock it */
1064 if (!ExpLockHandleTableEntry(HandleTable, HandleTableEntry)) return NULL;
1065
1066 /* Return the entry */
1067 return HandleTableEntry;
1068}
1069
1071NTAPI
1074 IN PEX_DUPLICATE_HANDLE_CALLBACK DupHandleProcedure,
1076{
1077 PHANDLE_TABLE NewTable;
1079 PHANDLE_TABLE_ENTRY HandleTableEntry, NewEntry;
1081 PAGED_CODE();
1082
1083 /* Allocate the duplicated copy */
1085 if (!NewTable) return NULL;
1086
1087 /* Loop each entry */
1088 while (NewTable->NextHandleNeedingPool <
1089 HandleTable->NextHandleNeedingPool)
1090 {
1091 /* Insert it into the duplicated copy */
1092 if (!ExpAllocateHandleTableEntrySlow(NewTable, FALSE))
1093 {
1094 /* Insert failed, free the new copy and return */
1095 ExpFreeHandleTable(NewTable);
1096 return NULL;
1097 }
1098 }
1099
1100 /* Setup the initial handle table data */
1101 NewTable->HandleCount = 0;
1102 NewTable->ExtraInfoPages = 0;
1103 NewTable->FirstFree = 0;
1104
1105 /* Setup the first handle value */
1106 Handle.Value = INDEX_TO_HANDLE_VALUE(1);
1107
1108 /* Enter a critical region and lookup the new entry */
1110 while ((NewEntry = ExpLookupHandleTableEntry(NewTable, Handle)))
1111 {
1112 /* Lookup the old entry */
1113 HandleTableEntry = ExpLookupHandleTableEntry(HandleTable, Handle);
1114
1115 /* Loop each entry */
1116 do
1117 {
1118 /* Check if it doesn't match the audit mask */
1119 if (!(HandleTableEntry->Value & Mask))
1120 {
1121 /* Free it since we won't use it */
1122 Failed = TRUE;
1123 }
1124 else
1125 {
1126 /* Lock the entry */
1127 if (!ExpLockHandleTableEntry(HandleTable, HandleTableEntry))
1128 {
1129 /* Free it since we can't lock it, so we won't use it */
1130 Failed = TRUE;
1131 }
1132 else
1133 {
1134 /* Copy the handle value */
1135 *NewEntry = *HandleTableEntry;
1136
1137 /* Call the duplicate callback */
1138 if (DupHandleProcedure(Process,
1140 HandleTableEntry,
1141 NewEntry))
1142 {
1143 /* Clear failure flag */
1144 Failed = FALSE;
1145
1146 /* Lock the entry, increase the handle count */
1148 NewTable->HandleCount++;
1149 }
1150 else
1151 {
1152 /* Duplication callback refused, fail */
1153 Failed = TRUE;
1154 }
1155 }
1156 }
1157
1158 /* Check if we failed earlier and need to free */
1159 if (Failed)
1160 {
1161 /* Free this entry */
1162 NewEntry->Object = NULL;
1163 NewEntry->NextFreeTableEntry = NewTable->FirstFree;
1164 NewTable->FirstFree = (ULONG)Handle.Value;
1165 }
1166
1167 /* Increase the handle value and move to the next entry */
1168 Handle.Value += INDEX_TO_HANDLE_VALUE(1);
1169 NewEntry++;
1170 HandleTableEntry++;
1172
1173 /* We're done, skip the last entry */
1174 Handle.Value += INDEX_TO_HANDLE_VALUE(1);
1175 }
1176
1177 /* Acquire the table lock and insert this new table into the list */
1181
1182 /* Leave the critical region we entered previously and return the table */
1184 return NewTable;
1185}
1186
1187BOOLEAN
1188NTAPI
1191 IN PEX_CHANGE_HANDLE_CALLBACK ChangeRoutine,
1193{
1194 EXHANDLE ExHandle;
1195 PHANDLE_TABLE_ENTRY HandleTableEntry;
1197 PAGED_CODE();
1198
1199 /* Set the handle value */
1200 ExHandle.GenericHandleOverlay = Handle;
1201
1202 /* Find the entry for this handle */
1203 HandleTableEntry = ExpLookupHandleTableEntry(HandleTable, ExHandle);
1204
1205 /* Make sure that we found an entry, and that it's valid */
1206 if (!(HandleTableEntry) ||
1207 !(HandleTableEntry->Object) ||
1208 (HandleTableEntry->NextFreeTableEntry == -2))
1209 {
1210 /* It isn't, fail */
1211 return FALSE;
1212 }
1213
1214 /* Enter a critical region */
1216
1217 /* Try locking the handle entry */
1218 if (ExpLockHandleTableEntry(HandleTable, HandleTableEntry))
1219 {
1220 /* Call the change routine and unlock the entry */
1221 Result = ChangeRoutine(HandleTableEntry, Context);
1222 ExUnlockHandleTableEntry(HandleTable, HandleTableEntry);
1223 }
1224
1225 /* Leave the critical region and return the callback result */
1227 return Result;
1228}
1229
1230VOID
1231NTAPI
1233 IN PEX_SWEEP_HANDLE_CALLBACK EnumHandleProcedure,
1235{
1237 PHANDLE_TABLE_ENTRY HandleTableEntry;
1238 PAGED_CODE();
1239
1240 /* Set the initial value and loop the entries */
1241 Handle.Value = INDEX_TO_HANDLE_VALUE(1);
1242 while ((HandleTableEntry = ExpLookupHandleTableEntry(HandleTable, Handle)))
1243 {
1244 /* Loop each handle */
1245 do
1246 {
1247 /* Lock the entry */
1248 if (ExpLockHandleTableEntry(HandleTable, HandleTableEntry))
1249 {
1250 /* Notify the callback routine */
1251 EnumHandleProcedure(HandleTableEntry,
1252 Handle.GenericHandleOverlay,
1253 Context);
1254 }
1255
1256 /* Go to the next handle and entry */
1257 Handle.Value += INDEX_TO_HANDLE_VALUE(1);
1258 HandleTableEntry++;
1260
1261 /* Skip past the last entry */
1262 Handle.Value += INDEX_TO_HANDLE_VALUE(1);
1263 }
1264}
1265
1266/*
1267 * @implemented
1268 */
1269BOOLEAN
1270NTAPI
1272 IN PEX_ENUM_HANDLE_CALLBACK EnumHandleProcedure,
1274 OUT PHANDLE EnumHandle OPTIONAL)
1275{
1277 PHANDLE_TABLE_ENTRY HandleTableEntry;
1279 PAGED_CODE();
1280
1281 /* Enter a critical region */
1283
1284 /* Set the initial value and loop the entries */
1285 Handle.Value = 0;
1286 while ((HandleTableEntry = ExpLookupHandleTableEntry(HandleTable, Handle)))
1287 {
1288 /* Validate the entry */
1289 if ((HandleTableEntry->Object) &&
1290 (HandleTableEntry->NextFreeTableEntry != -2))
1291 {
1292 /* Lock the entry */
1293 if (ExpLockHandleTableEntry(HandleTable, HandleTableEntry))
1294 {
1295 /* Notify the callback routine */
1296 Result = EnumHandleProcedure(HandleTableEntry,
1297 Handle.GenericHandleOverlay,
1298 Context);
1299
1300 /* Unlock it */
1301 ExUnlockHandleTableEntry(HandleTable, HandleTableEntry);
1302
1303 /* Was this the one looked for? */
1304 if (Result)
1305 {
1306 /* If so, return it if requested */
1307 if (EnumHandle) *EnumHandle = Handle.GenericHandleOverlay;
1308 break;
1309 }
1310 }
1311 }
1312
1313 /* Go to the next entry */
1314 Handle.Value += INDEX_TO_HANDLE_VALUE(1);
1315 }
1316
1317 /* Leave the critical region and return callback result */
1319 return Result;
1320}
1321
1322#if DBG && defined(KDBG)
1323
1324#include <kdbg/kdb.h>
1325
1326BOOLEAN ExpKdbgExtHandle(ULONG Argc, PCHAR Argv[])
1327{
1328 USHORT i;
1329 char *endptr;
1331 EXHANDLE ExHandle;
1334 WCHAR KeyPath[256];
1337 POBJECT_HEADER ObjectHeader;
1339 ULONG NeededLength = 0;
1340 ULONG NameLength;
1341 PCM_KEY_CONTROL_BLOCK Kcb, CurrentKcb;
1342 POBJECT_HEADER_NAME_INFO ObjectNameInfo;
1343
1344 if (Argc > 1)
1345 {
1346 /* Get EPROCESS address or PID */
1347 i = 0;
1348 while (Argv[1][i])
1349 {
1350 if (!isdigit(Argv[1][i]))
1351 {
1352 i = 0;
1353 break;
1354 }
1355
1356 ++i;
1357 }
1358
1359 if (i == 0)
1360 {
1361 if (!KdbpGetHexNumber(Argv[1], (PVOID)&Process))
1362 {
1363 KdbpPrint("Invalid parameter: %s\n", Argv[1]);
1364 return TRUE;
1365 }
1366
1367 /* In the end, we always want a PID */
1369 }
1370 else
1371 {
1372 ProcessId = (HANDLE)strtoulptr(Argv[1], &endptr, 10);
1373 if (*endptr != '\0')
1374 {
1375 KdbpPrint("Invalid parameter: %s\n", Argv[1]);
1376 return TRUE;
1377 }
1378 }
1379 }
1380 else
1381 {
1383 }
1384
1387 Entry = Entry->Flink)
1388 {
1389 /* Only return matching PID
1390 * 0 matches everything
1391 */
1392 HandleTable = CONTAINING_RECORD(Entry, HANDLE_TABLE, HandleTableList);
1393 if (ProcessId != 0 && HandleTable->UniqueProcessId != ProcessId)
1394 {
1395 continue;
1396 }
1397
1398 KdbpPrint("\n");
1399
1400 KdbpPrint("Handle table at %p with %d entries in use\n", HandleTable, HandleTable->HandleCount);
1401
1402 ExHandle.Value = 0;
1403 while ((TableEntry = ExpLookupHandleTableEntry(HandleTable, ExHandle)))
1404 {
1405 if ((TableEntry->Object) &&
1406 (TableEntry->NextFreeTableEntry != -2))
1407 {
1408 ObjectHeader = ObpGetHandleObject(TableEntry);
1409
1410 KdbpPrint("%p: Object: %p GrantedAccess: %x Entry: %p\n", ExHandle.Value, &ObjectHeader->Body, TableEntry->GrantedAccess, TableEntry);
1411 KdbpPrint("Object: %p Type: (%x) %wZ\n", &ObjectHeader->Body, ObjectHeader->Type, &ObjectHeader->Type->Name);
1412 KdbpPrint("\tObjectHeader: %p\n", ObjectHeader);
1413 KdbpPrint("\t\tHandleCount: %u PointerCount: %u\n", ObjectHeader->HandleCount, ObjectHeader->PointerCount);
1414
1415 /* Specific objects debug prints */
1416
1417 /* For file, display path */
1418 if (ObjectHeader->Type == IoFileObjectType)
1419 {
1420 FileObject = (PFILE_OBJECT)&ObjectHeader->Body;
1421
1422 KdbpPrint("\t\t\tName: %wZ\n", &FileObject->FileName);
1423 }
1424
1425 /* For directory, and win32k objects, display object name */
1426 else if (ObjectHeader->Type == ObpDirectoryObjectType ||
1427 ObjectHeader->Type == ExWindowStationObjectType ||
1428 ObjectHeader->Type == ExDesktopObjectType ||
1429 ObjectHeader->Type == MmSectionObjectType)
1430 {
1431 ObjectNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
1432 if (ObjectNameInfo != NULL && ObjectNameInfo->Name.Buffer != NULL)
1433 {
1434 KdbpPrint("\t\t\tName: %wZ\n", &ObjectNameInfo->Name);
1435 }
1436 }
1437
1438 /* For registry keys, display full path */
1439 else if (ObjectHeader->Type == CmpKeyObjectType)
1440 {
1441 Kcb = ((PCM_KEY_BODY)&ObjectHeader->Body)->KeyControlBlock;
1442 if (!Kcb->Delete)
1443 {
1444 CurrentKcb = Kcb;
1445
1446 /* See: CmpQueryNameInformation() */
1447
1448 while (CurrentKcb != NULL)
1449 {
1450 if (CurrentKcb->NameBlock->Compressed)
1451 NeededLength += CmpCompressedNameSize(CurrentKcb->NameBlock->Name, CurrentKcb->NameBlock->NameLength);
1452 else
1453 NeededLength += CurrentKcb->NameBlock->NameLength;
1454
1455 NeededLength += sizeof(OBJ_NAME_PATH_SEPARATOR);
1456
1457 CurrentKcb = CurrentKcb->ParentKcb;
1458 }
1459
1460 if (NeededLength < sizeof(KeyPath))
1461 {
1462 CurrentKcb = Kcb;
1463
1464 while (CurrentKcb != NULL)
1465 {
1466 if (CurrentKcb->NameBlock->Compressed)
1467 {
1468 NameLength = CmpCompressedNameSize(CurrentKcb->NameBlock->Name, CurrentKcb->NameBlock->NameLength);
1469 CmpCopyCompressedName(&KeyPath[(NeededLength - NameLength)/sizeof(WCHAR)],
1470 NameLength,
1471 CurrentKcb->NameBlock->Name,
1472 CurrentKcb->NameBlock->NameLength);
1473 }
1474 else
1475 {
1476 NameLength = CurrentKcb->NameBlock->NameLength;
1477 RtlCopyMemory(&KeyPath[(NeededLength - NameLength)/sizeof(WCHAR)],
1478 CurrentKcb->NameBlock->Name,
1479 NameLength);
1480 }
1481
1482 NeededLength -= NameLength;
1483 NeededLength -= sizeof(OBJ_NAME_PATH_SEPARATOR);
1484 KeyPath[NeededLength/sizeof(WCHAR)] = OBJ_NAME_PATH_SEPARATOR;
1485
1486 CurrentKcb = CurrentKcb->ParentKcb;
1487 }
1488 }
1489
1490 KdbpPrint("\t\t\tName: %S\n", KeyPath);
1491 }
1492 }
1493 }
1494
1495 ExHandle.Value += INDEX_TO_HANDLE_VALUE(1);
1496 }
1497 }
1498
1499 return TRUE;
1500}
1501
1502#endif // DBG && defined(KDBG)
#define PAGED_CODE()
#define CODE_SEG(...)
#define ObpDirectoryObjectType
Definition: ObTypes.c:118
#define CmpKeyObjectType
Definition: ObTypes.c:127
unsigned char BOOLEAN
#define isdigit(c)
Definition: acclib.h:68
#define OBJ_NAME_PATH_SEPARATOR
Definition: arcname_tests.c:25
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedExchange
Definition: armddk.h:54
#define InterlockedDecrement
Definition: armddk.h:52
LONG NTSTATUS
Definition: precomp.h:26
Definition: bufpool.h:45
struct _CM_KEY_BODY * PCM_KEY_BODY
VOID NTAPI CmpCopyCompressedName(OUT PWCHAR Destination, IN ULONG DestinationLength, IN PWCHAR Source, IN ULONG SourceLength)
Definition: cmname.c:56
USHORT NTAPI CmpCompressedNameSize(IN PWCHAR Name, IN ULONG Length)
Definition: cmname.c:95
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define ULONG_PTR
Definition: config.h:101
#define InterlockedExchangePointer(Target, Value)
Definition: dshow.h:45
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InsertTailList(ListHead, Entry)
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define APC_LEVEL
Definition: env_spec_w32.h:695
#define PAGE_SIZE
Definition: env_spec_w32.h:49
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define PagedPool
Definition: env_spec_w32.h:308
#define ExInitializePushLock
Definition: ex.h:1013
#define FREE_HANDLE_MASK
Definition: ex.h:147
BOOLEAN(NTAPI * PEX_SWEEP_HANDLE_CALLBACK)(PHANDLE_TABLE_ENTRY HandleTableEntry, HANDLE Handle, PVOID Context)
Definition: ex.h:434
BOOLEAN(NTAPI * PEX_CHANGE_HANDLE_CALLBACK)(PHANDLE_TABLE_ENTRY HandleTableEntry, ULONG_PTR Context)
Definition: ex.h:449
#define EXHANDLE_TABLE_ENTRY_LOCK_BIT
Definition: ex.h:146
FORCEINLINE VOID ExAcquirePushLockExclusive(PEX_PUSH_LOCK PushLock)
Definition: ex.h:1036
#define MID_LEVEL_ENTRIES
Definition: ex.h:153
#define HIGH_LEVEL_ENTRIES
Definition: ex.h:154
FORCEINLINE VOID ExAcquirePushLockShared(PEX_PUSH_LOCK PushLock)
Definition: ex.h:1105
#define MAX_MID_INDEX
Definition: ex.h:160
FORCEINLINE VOID ExReleasePushLockShared(PEX_PUSH_LOCK PushLock)
Definition: ex.h:1213
#define LOW_LEVEL_ENTRIES
Definition: ex.h:152
FORCEINLINE VOID ExReleasePushLockExclusive(PEX_PUSH_LOCK PushLock)
Definition: ex.h:1252
BOOLEAN(NTAPI * PEX_DUPLICATE_HANDLE_CALLBACK)(IN PEPROCESS Process, IN PHANDLE_TABLE HandleTable, IN PHANDLE_TABLE_ENTRY HandleTableEntry, IN PHANDLE_TABLE_ENTRY NewEntry)
Definition: ex.h:441
FORCEINLINE VOID ExWaitOnPushLock(PEX_PUSH_LOCK PushLock)
Definition: ex.h:1178
IN PLARGE_INTEGER IN PLARGE_INTEGER PEPROCESS ProcessId
Definition: fatprocs.h:2711
unsigned int Mask
Definition: fpcontrol.c:82
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:223
ULONG Handle
Definition: gdb_input.c:15
Status
Definition: gdiplustypes.h:25
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
#define KeGetCurrentThread
Definition: hal.h:55
static XMS_HANDLE HandleTable[XMS_MAX_HANDLES]
Definition: himem.c:83
#define InterlockedExchangeAdd
Definition: interlocked.h:181
#define InterlockedOr
Definition: interlocked.h:224
#define InterlockedCompareExchangePointer
Definition: interlocked.h:129
#define InterlockedCompareExchange
Definition: interlocked.h:104
POBJECT_TYPE IoFileObjectType
Definition: iomgr.c:36
VOID KdbpPrint(_In_ PSTR Format, _In_ ...)
Prints the given string with printf-like formatting.
Definition: kdb_cli.c:3082
BOOLEAN NTAPI KdbpGetHexNumber(IN PCHAR pszNum, OUT ULONG_PTR *pulValue)
Definition: kdb_cli.c:449
BOOLEAN ExpKdbgExtHandle(ULONG Argc, PCHAR Argv[])
#define KeLeaveCriticalRegion()
Definition: ke_x.h:119
#define KeEnterCriticalRegion()
Definition: ke_x.h:88
if(dx< 0)
Definition: linetemp.h:194
#define ASSERT(a)
Definition: mode.c:44
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
__int3264 LONG_PTR
Definition: mstsclib_h.h:276
BOOLEAN(NTAPI * PEX_ENUM_HANDLE_CALLBACK)(_In_ struct _HANDLE_TABLE_ENTRY *HandleTableEntry, _In_ HANDLE Handle, _In_ PVOID Context)
Definition: extypes.h:388
struct _HANDLE_TABLE_ENTRY * PHANDLE_TABLE_ENTRY
EX_PUSH_LOCK_WAIT_BLOCK
Definition: extypes.h:501
#define OBJECT_HEADER_TO_NAME_INFO(h)
Definition: obtypes.h:114
_In_opt_ ULONG Base
Definition: rtlfuncs.h:2439
VOID NTAPI ExpFreeLowLevelTable(IN PEPROCESS Process, IN PHANDLE_TABLE_ENTRY TableEntry)
Definition: handle.c:183
PVOID NTAPI ExpAllocateTablePagedPoolNoZero(IN PEPROCESS Process OPTIONAL, IN SIZE_T Size)
Definition: handle.c:139
PHANDLE_TABLE NTAPI ExpAllocateHandleTable(IN PEPROCESS Process OPTIONAL, IN BOOLEAN NewTable)
Definition: handle.c:331
ULONG NTAPI ExpMoveFreeHandles(IN PHANDLE_TABLE HandleTable)
Definition: handle.c:648
VOID NTAPI ExSweepHandleTable(IN PHANDLE_TABLE HandleTable, IN PEX_SWEEP_HANDLE_CALLBACK EnumHandleProcedure, IN PVOID Context)
Definition: handle.c:1232
#define strtoulptr
Definition: handle.c:28
BOOLEAN NTAPI ExChangeHandle(IN PHANDLE_TABLE HandleTable, IN HANDLE Handle, IN PEX_CHANGE_HANDLE_CALLBACK ChangeRoutine, IN ULONG_PTR Context)
Definition: handle.c:1189
BOOLEAN NTAPI ExEnumHandleTable(IN PHANDLE_TABLE HandleTable, IN PEX_ENUM_HANDLE_CALLBACK EnumHandleProcedure, IN OUT PVOID Context, OUT PHANDLE EnumHandle OPTIONAL)
Definition: handle.c:1271
PVOID NTAPI ExpAllocateTablePagedPool(IN PEPROCESS Process OPTIONAL, IN SIZE_T Size)
Definition: handle.c:107
VOID NTAPI ExpInitializeHandleTables(VOID)
Definition: handle.c:34
PHANDLE_TABLE_ENTRY NTAPI ExpLookupHandleTableEntry(IN PHANDLE_TABLE HandleTable, IN EXHANDLE Handle)
Definition: handle.c:43
HANDLE NTAPI ExCreateHandle(IN PHANDLE_TABLE HandleTable, IN PHANDLE_TABLE_ENTRY HandleTableEntry)
Definition: handle.c:827
PHANDLE_TABLE_ENTRY NTAPI ExpAllocateHandleTableEntry(IN PHANDLE_TABLE HandleTable, OUT PEXHANDLE NewHandle)
Definition: handle.c:683
VOID NTAPI ExRemoveHandleTable(IN PHANDLE_TABLE HandleTable)
Definition: handle.c:944
VOID NTAPI ExpFreeTablePagedPool(IN PEPROCESS Process OPTIONAL, IN PVOID Buffer, IN SIZE_T Size)
Definition: handle.c:168
VOID NTAPI ExpFreeHandleTableEntry(IN PHANDLE_TABLE HandleTable, IN EXHANDLE Handle, IN PHANDLE_TABLE_ENTRY HandleTableEntry)
Definition: handle.c:279
PHANDLE_TABLE NTAPI ExCreateHandleTable(IN PEPROCESS Process OPTIONAL)
Definition: handle.c:801
PHANDLE_TABLE_ENTRY NTAPI ExpAllocateLowLevelTable(IN PHANDLE_TABLE HandleTable, IN BOOLEAN DoInit)
Definition: handle.c:430
EX_PUSH_LOCK HandleTableListLock
Definition: handle.c:19
LIST_ENTRY HandleTableListHead
Definition: handle.c:18
BOOLEAN NTAPI ExpAllocateHandleTableEntrySlow(IN PHANDLE_TABLE HandleTable, IN BOOLEAN DoInit)
Definition: handle.c:502
BOOLEAN NTAPI ExDestroyHandle(IN PHANDLE_TABLE HandleTable, IN HANDLE Handle, IN PHANDLE_TABLE_ENTRY HandleTableEntry OPTIONAL)
Definition: handle.c:984
BOOLEAN NTAPI ExpLockHandleTableEntry(IN PHANDLE_TABLE HandleTable, IN PHANDLE_TABLE_ENTRY HandleTableEntry)
Definition: handle.c:884
#define INDEX_TO_HANDLE_VALUE(x)
Definition: handle.c:21
VOID NTAPI ExDestroyHandleTable(IN PHANDLE_TABLE HandleTable, IN PVOID DestroyHandleProcedure OPTIONAL)
Definition: handle.c:963
PHANDLE_TABLE_ENTRY NTAPI ExMapHandleToPointer(IN PHANDLE_TABLE HandleTable, IN HANDLE Handle)
Definition: handle.c:1046
#define SizeOfHandle(x)
Definition: handle.c:20
VOID NTAPI ExUnlockHandleTableEntry(IN PHANDLE_TABLE HandleTable, IN PHANDLE_TABLE_ENTRY HandleTableEntry)
Definition: handle.c:923
VOID NTAPI ExpBlockOnLockedHandleEntry(IN PHANDLE_TABLE HandleTable, IN PHANDLE_TABLE_ENTRY HandleTableEntry)
Definition: handle.c:858
VOID NTAPI ExpFreeHandleTable(IN PHANDLE_TABLE HandleTable)
Definition: handle.c:202
PHANDLE_TABLE_ENTRY *NTAPI ExpAllocateMidLevelTable(IN PHANDLE_TABLE HandleTable, IN BOOLEAN DoInit, OUT PHANDLE_TABLE_ENTRY *LowTableEntry)
Definition: handle.c:475
PHANDLE_TABLE NTAPI ExDupHandleTable(IN PEPROCESS Process, IN PHANDLE_TABLE HandleTable, IN PEX_DUPLICATE_HANDLE_CALLBACK DupHandleProcedure, IN ULONG_PTR Mask)
Definition: handle.c:1072
HANDLE NTAPI PsGetCurrentProcessId(VOID)
Definition: process.c:1123
HANDLE NTAPI PsGetProcessId(PEPROCESS Process)
Definition: process.c:1063
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:455
#define ObpGetHandleObject(x)
Definition: ob.h:91
unsigned short USHORT
Definition: pedump.c:61
VOID FASTCALL ExWaitForUnblockPushLock(IN PEX_PUSH_LOCK PushLock, IN PVOID WaitBlock)
Definition: pushlock.c:395
VOID FASTCALL ExfUnblockPushLock(PEX_PUSH_LOCK PushLock, PVOID CurrentWaitBlock)
Definition: pushlock.c:1205
VOID FASTCALL ExBlockPushLock(PEX_PUSH_LOCK PushLock, PVOID pWaitBlock)
Definition: pushlock.c:420
VOID NTAPI PsReturnProcessPagedPoolQuota(_In_ PEPROCESS Process, _In_ SIZE_T Amount)
Returns the paged pool quota that the process was taking up.
Definition: quota.c:965
NTSTATUS NTAPI PsChargeProcessPagedPoolQuota(_In_ PEPROCESS Process, _In_ SIZE_T Amount)
Charges the paged pool quota of a given process.
Definition: quota.c:839
@ Failed
Definition: arc.h:79
POBJECT_TYPE MmSectionObjectType
Definition: section.c:194
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
@ High
Definition: strmini.h:378
@ Low
Definition: strmini.h:380
base of all file and directory entries
Definition: entries.h:83
PCM_NAME_CONTROL_BLOCK NameBlock
Definition: cm.h:290
struct _CM_KEY_CONTROL_BLOCK * ParentKcb
Definition: cm.h:289
BOOLEAN Compressed
Definition: cm.h:248
USHORT NameLength
Definition: cm.h:257
WCHAR Name[ANYSIZE_ARRAY]
Definition: cm.h:258
Definition: extypes.h:591
Definition: extypes.h:596
PVOID Object
Definition: extypes.h:599
ULONG_PTR Value
Definition: extypes.h:602
LONG NextFreeTableEntry
Definition: extypes.h:612
LONG HandleCount
Definition: extypes.h:644
LONG ExtraInfoPages
Definition: extypes.h:635
ULONG NextHandleNeedingPool
Definition: extypes.h:645
LIST_ENTRY HandleTableList
Definition: extypes.h:627
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
UNICODE_STRING Name
Definition: obtypes.h:433
LONG_PTR HandleCount
Definition: obtypes.h:490
LONG_PTR PointerCount
Definition: obtypes.h:487
POBJECT_TYPE Type
Definition: obtypes.h:493
UNICODE_STRING Name
Definition: obtypes.h:383
#define TAG_OBJECT_TABLE
Definition: tag.h:26
#define NTAPI
Definition: typedefs.h:36
void * PVOID
Definition: typedefs.h:50
PVOID HANDLE
Definition: typedefs.h:73
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define IN
Definition: typedefs.h:39
int32_t * PLONG
Definition: typedefs.h:58
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
char * PCHAR
Definition: typedefs.h:51
Definition: ex.h:87
ULONG_PTR Index
Definition: ex.h:91
HANDLE GenericHandleOverlay
Definition: ex.h:102
ULONG_PTR Value
Definition: ex.h:103
_Must_inspect_result_ _In_ WDFCOLLECTION _In_ WDFOBJECT Object
_In_ WDFCOLLECTION _In_ ULONG Index
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:550
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4533
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:413
POBJECT_TYPE ExDesktopObjectType
Definition: win32k.c:22
POBJECT_TYPE ExWindowStationObjectType
Definition: win32k.c:21
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:409
_In_opt_ PALLOCATE_FUNCTION _In_opt_ PFREE_FUNCTION Free
Definition: exfuncs.h:815
_Must_inspect_result_ typedef _In_ ULONG TableEntry
Definition: iotypes.h:4303
* PFILE_OBJECT
Definition: iotypes.h:1998
#define PsGetCurrentProcess
Definition: psfuncs.h:17
__wchar_t WCHAR
Definition: xmlstorage.h:180