ReactOS  0.4.15-dev-4934-gfd1e799
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 
31 CODE_SEG("INIT")
32 VOID
33 NTAPI
35 {
36  /* Initialize the list of handle tables and the lock */
39 }
40 
42 NTAPI
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 
97  ASSERT(FALSE);
98  Entry = NULL;
99  }
100 
101  /* Return the handle entry */
102  return Entry;
103 }
104 
105 PVOID
106 NTAPI
108  IN SIZE_T Size)
109 {
110  PVOID Buffer;
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 
137 PVOID
138 NTAPI
140  IN SIZE_T Size)
141 {
142  PVOID Buffer;
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 
166 VOID
167 NTAPI
169  IN PVOID Buffer,
170  IN SIZE_T Size)
171 {
172  /* Free the buffer */
174  if (Process)
175  {
176  /* Release quota */
178  }
179 }
180 
181 VOID
182 NTAPI
185 {
186  /* Check if we have an entry */
187  if (TableEntry[0].Object)
188  {
189  /* Free the entry */
191  TableEntry[0].Object,
193  sizeof(HANDLE_TABLE_ENTRY_INFO));
194  }
195 
196  /* Free the table */
198 }
199 
200 VOID
201 NTAPI
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;
217  ExpFreeLowLevelTable(Process, Level1);
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 */
231  ExpFreeLowLevelTable(Process, Level2[i]);
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 
277 VOID
278 NTAPI
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 
330 NTAPI
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 
429 NTAPI
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;
456  i += INDEX_TO_HANDLE_VALUE(1))
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 
474 NTAPI
476  IN BOOLEAN DoInit,
477  OUT PHANDLE_TABLE_ENTRY *LowTableEntry)
478 {
479  PHANDLE_TABLE_ENTRY *Mid, Low;
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 
500 BOOLEAN
501 NTAPI
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 */
518  Mid = ExpAllocateMidLevelTable(HandleTable, DoInit, &Low);
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 */
555  Mid = ExpAllocateMidLevelTable(HandleTable, DoInit, &Low);
556  if (!Mid)
557  {
558  /* We failed, free the high level table as well */
559  ExpFreeTablePagedPool(HandleTable->QuotaProcess,
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 */
588  Mid = ExpAllocateMidLevelTable(HandleTable, DoInit, &Low);
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)) -
599  i * MAX_MID_INDEX;
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 
646 ULONG
647 NTAPI
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 
682 NTAPI
684  OUT PEXHANDLE NewHandle)
685 {
686  ULONG OldValue, NewValue, NewValue1;
688  EXHANDLE Handle, OldHandle;
689  BOOLEAN Result;
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 */
714  OldValue = ExpMoveFreeHandles(HandleTable);
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 
800 NTAPI
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 */
815  InsertTailList(&HandleTableListHead, &HandleTable->HandleTableList);
816 
817  /* Release the lock */
820 
821  /* Return the handle table */
822  return HandleTable;
823 }
824 
825 HANDLE
826 NTAPI
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 
856 VOID
857 NTAPI
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 
882 BOOLEAN
883 NTAPI
885  IN PHANDLE_TABLE_ENTRY HandleTableEntry)
886 {
887  LONG_PTR NewValue, OldValue;
888 
889  /* Sanity check */
890  ASSERT((KeGetCurrentThread()->CombinedApcDisable != 0) ||
891  (KeGetCurrentIrql() == APC_LEVEL));
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;
898  if (OldValue & EXHANDLE_TABLE_ENTRY_LOCK_BIT)
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 
921 VOID
922 NTAPI
924  IN PHANDLE_TABLE_ENTRY HandleTableEntry)
925 {
926  LONG_PTR OldValue;
927  PAGED_CODE();
928 
929  /* Sanity check */
930  ASSERT((KeGetCurrentThread()->CombinedApcDisable != 0) ||
931  (KeGetCurrentIrql() == APC_LEVEL));
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 
942 VOID
943 NTAPI
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 
961 VOID
962 NTAPI
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 
982 BOOLEAN
983 NTAPI
985  IN HANDLE Handle,
986  IN PHANDLE_TABLE_ENTRY HandleTableEntry OPTIONAL)
987 {
988  EXHANDLE ExHandle;
989  PVOID Object;
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 
1045 NTAPI
1047  IN HANDLE Handle)
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 
1071 NTAPI
1074  IN PEX_DUPLICATE_HANDLE_CALLBACK DupHandleProcedure,
1075  IN ULONG_PTR Mask)
1076 {
1077  PHANDLE_TABLE NewTable;
1078  EXHANDLE Handle;
1079  PHANDLE_TABLE_ENTRY HandleTableEntry, NewEntry;
1080  BOOLEAN Failed = FALSE;
1081  PAGED_CODE();
1082 
1083  /* Allocate the duplicated copy */
1084  NewTable = ExpAllocateHandleTable(Process, FALSE);
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,
1139  HandleTable,
1140  HandleTableEntry,
1141  NewEntry))
1142  {
1143  /* Clear failure flag */
1144  Failed = FALSE;
1145 
1146  /* Lock the entry, increase the handle count */
1147  NewEntry->Value |= EXHANDLE_TABLE_ENTRY_LOCK_BIT;
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++;
1171  } while (Handle.Value % INDEX_TO_HANDLE_VALUE(LOW_LEVEL_ENTRIES));
1172 
1173  /* We're done, skip the last entry */
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 
1187 BOOLEAN
1188 NTAPI
1190  IN HANDLE Handle,
1191  IN PEX_CHANGE_HANDLE_CALLBACK ChangeRoutine,
1193 {
1194  EXHANDLE ExHandle;
1195  PHANDLE_TABLE_ENTRY HandleTableEntry;
1196  BOOLEAN Result = FALSE;
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 
1230 VOID
1231 NTAPI
1233  IN PEX_SWEEP_HANDLE_CALLBACK EnumHandleProcedure,
1234  IN PVOID Context)
1235 {
1236  EXHANDLE Handle;
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++;
1259  } while (Handle.Value % INDEX_TO_HANDLE_VALUE(LOW_LEVEL_ENTRIES));
1260 
1261  /* Skip past the last entry */
1263  }
1264 }
1265 
1266 /*
1267  * @implemented
1268  */
1269 BOOLEAN
1270 NTAPI
1272  IN PEX_ENUM_HANDLE_CALLBACK EnumHandleProcedure,
1273  IN OUT PVOID Context,
1274  OUT PHANDLE EnumHandle OPTIONAL)
1275 {
1276  EXHANDLE Handle;
1277  PHANDLE_TABLE_ENTRY HandleTableEntry;
1278  BOOLEAN Result = FALSE;
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 BOOLEAN ExpKdbgExtHandle(ULONG Argc, PCHAR Argv[])
1324 {
1325  USHORT i;
1326  char *endptr;
1327  HANDLE ProcessId;
1328  EXHANDLE ExHandle;
1331  WCHAR KeyPath[256];
1334  POBJECT_HEADER ObjectHeader;
1336  ULONG NeededLength = 0;
1337  ULONG NameLength;
1338  PCM_KEY_CONTROL_BLOCK Kcb, CurrentKcb;
1339  POBJECT_HEADER_NAME_INFO ObjectNameInfo;
1340 
1341  if (Argc > 1)
1342  {
1343  /* Get EPROCESS address or PID */
1344  i = 0;
1345  while (Argv[1][i])
1346  {
1347  if (!isdigit(Argv[1][i]))
1348  {
1349  i = 0;
1350  break;
1351  }
1352 
1353  ++i;
1354  }
1355 
1356  if (i == 0)
1357  {
1358  if (!KdbpGetHexNumber(Argv[1], (PVOID)&Process))
1359  {
1360  KdbpPrint("Invalid parameter: %s\n", Argv[1]);
1361  return TRUE;
1362  }
1363 
1364  /* In the end, we always want a PID */
1366  }
1367  else
1368  {
1369  ProcessId = (HANDLE)strtoulptr(Argv[1], &endptr, 10);
1370  if (*endptr != '\0')
1371  {
1372  KdbpPrint("Invalid parameter: %s\n", Argv[1]);
1373  return TRUE;
1374  }
1375  }
1376  }
1377  else
1378  {
1380  }
1381 
1384  Entry = Entry->Flink)
1385  {
1386  /* Only return matching PID
1387  * 0 matches everything
1388  */
1389  HandleTable = CONTAINING_RECORD(Entry, HANDLE_TABLE, HandleTableList);
1390  if (ProcessId != 0 && HandleTable->UniqueProcessId != ProcessId)
1391  {
1392  continue;
1393  }
1394 
1395  KdbpPrint("\n");
1396 
1397  KdbpPrint("Handle table at %p with %d entries in use\n", HandleTable, HandleTable->HandleCount);
1398 
1399  ExHandle.Value = 0;
1400  while ((TableEntry = ExpLookupHandleTableEntry(HandleTable, ExHandle)))
1401  {
1402  if ((TableEntry->Object) &&
1403  (TableEntry->NextFreeTableEntry != -2))
1404  {
1405  ObjectHeader = ObpGetHandleObject(TableEntry);
1406 
1407  KdbpPrint("%p: Object: %p GrantedAccess: %x Entry: %p\n", ExHandle.Value, &ObjectHeader->Body, TableEntry->GrantedAccess, TableEntry);
1408  KdbpPrint("Object: %p Type: (%x) %wZ\n", &ObjectHeader->Body, ObjectHeader->Type, &ObjectHeader->Type->Name);
1409  KdbpPrint("\tObjectHeader: %p\n", ObjectHeader);
1410  KdbpPrint("\t\tHandleCount: %u PointerCount: %u\n", ObjectHeader->HandleCount, ObjectHeader->PointerCount);
1411 
1412  /* Specific objects debug prints */
1413 
1414  /* For file, display path */
1415  if (ObjectHeader->Type == IoFileObjectType)
1416  {
1417  FileObject = (PFILE_OBJECT)&ObjectHeader->Body;
1418 
1419  KdbpPrint("\t\t\tName: %wZ\n", &FileObject->FileName);
1420  }
1421 
1422  /* For directory, and win32k objects, display object name */
1423  else if (ObjectHeader->Type == ObpDirectoryObjectType ||
1424  ObjectHeader->Type == ExWindowStationObjectType ||
1425  ObjectHeader->Type == ExDesktopObjectType ||
1426  ObjectHeader->Type == MmSectionObjectType)
1427  {
1428  ObjectNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
1429  if (ObjectNameInfo != NULL && ObjectNameInfo->Name.Buffer != NULL)
1430  {
1431  KdbpPrint("\t\t\tName: %wZ\n", &ObjectNameInfo->Name);
1432  }
1433  }
1434 
1435  /* For registry keys, display full path */
1436  else if (ObjectHeader->Type == CmpKeyObjectType)
1437  {
1438  Kcb = ((PCM_KEY_BODY)&ObjectHeader->Body)->KeyControlBlock;
1439  if (!Kcb->Delete)
1440  {
1441  CurrentKcb = Kcb;
1442 
1443  /* See: CmpQueryNameInformation() */
1444 
1445  while (CurrentKcb != NULL)
1446  {
1447  if (CurrentKcb->NameBlock->Compressed)
1448  NeededLength += CmpCompressedNameSize(CurrentKcb->NameBlock->Name, CurrentKcb->NameBlock->NameLength);
1449  else
1450  NeededLength += CurrentKcb->NameBlock->NameLength;
1451 
1452  NeededLength += sizeof(OBJ_NAME_PATH_SEPARATOR);
1453 
1454  CurrentKcb = CurrentKcb->ParentKcb;
1455  }
1456 
1457  if (NeededLength < sizeof(KeyPath))
1458  {
1459  CurrentKcb = Kcb;
1460 
1461  while (CurrentKcb != NULL)
1462  {
1463  if (CurrentKcb->NameBlock->Compressed)
1464  {
1465  NameLength = CmpCompressedNameSize(CurrentKcb->NameBlock->Name, CurrentKcb->NameBlock->NameLength);
1466  CmpCopyCompressedName(&KeyPath[(NeededLength - NameLength)/sizeof(WCHAR)],
1467  NameLength,
1468  CurrentKcb->NameBlock->Name,
1469  CurrentKcb->NameBlock->NameLength);
1470  }
1471  else
1472  {
1473  NameLength = CurrentKcb->NameBlock->NameLength;
1474  RtlCopyMemory(&KeyPath[(NeededLength - NameLength)/sizeof(WCHAR)],
1475  CurrentKcb->NameBlock->Name,
1476  NameLength);
1477  }
1478 
1479  NeededLength -= NameLength;
1480  NeededLength -= sizeof(OBJ_NAME_PATH_SEPARATOR);
1481  KeyPath[NeededLength/sizeof(WCHAR)] = OBJ_NAME_PATH_SEPARATOR;
1482 
1483  CurrentKcb = CurrentKcb->ParentKcb;
1484  }
1485  }
1486 
1487  KdbpPrint("\t\t\tName: %S\n", KeyPath);
1488  }
1489  }
1490  }
1491 
1492  ExHandle.Value += INDEX_TO_HANDLE_VALUE(1);
1493  }
1494  }
1495 
1496  return TRUE;
1497 }
1498 #endif
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
signed char * PCHAR
Definition: retypes.h:7
PHANDLE_TABLE NTAPI ExpAllocateHandleTable(IN PEPROCESS Process OPTIONAL, IN BOOLEAN NewTable)
Definition: handle.c:331
EX_PUSH_LOCK_WAIT_BLOCK
Definition: extypes.h:501
FORCEINLINE VOID ExAcquirePushLockExclusive(PEX_PUSH_LOCK PushLock)
Definition: ex.h:1034
#define IN
Definition: typedefs.h:39
PHANDLE_TABLE_ENTRY NTAPI ExpLookupHandleTableEntry(IN PHANDLE_TABLE HandleTable, IN EXHANDLE Handle)
Definition: handle.c:43
IN PLARGE_INTEGER IN PLARGE_INTEGER PEPROCESS ProcessId
Definition: fatprocs.h:2709
Definition: extypes.h:590
VOID FASTCALL ExBlockPushLock(PEX_PUSH_LOCK PushLock, PVOID pWaitBlock)
Definition: pushlock.c:420
POBJECT_TYPE ExWindowStationObjectType
Definition: win32k.c:21
BOOLEAN NTAPI ExDestroyHandle(IN PHANDLE_TABLE HandleTable, IN HANDLE Handle, IN PHANDLE_TABLE_ENTRY HandleTableEntry OPTIONAL)
Definition: handle.c:984
LONG_PTR HandleCount
Definition: obtypes.h:490
struct _Entry Entry
Definition: kefuncs.h:629
ULONG NextHandleNeedingPool
Definition: extypes.h:645
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34
struct _CM_KEY_CONTROL_BLOCK * ParentKcb
Definition: cm.h:274
#define TRUE
Definition: types.h:120
PHANDLE_TABLE_ENTRY NTAPI ExMapHandleToPointer(IN PHANDLE_TABLE HandleTable, IN HANDLE Handle)
Definition: handle.c:1046
VOID NTAPI ExDestroyHandleTable(IN PHANDLE_TABLE HandleTable, IN PVOID DestroyHandleProcedure OPTIONAL)
Definition: handle.c:963
LONG NTSTATUS
Definition: precomp.h:26
PHANDLE_TABLE_ENTRY NTAPI ExpAllocateLowLevelTable(IN PHANDLE_TABLE HandleTable, IN BOOLEAN DoInit)
Definition: handle.c:430
_In_opt_ ULONG Base
Definition: rtlfuncs.h:2413
FORCEINLINE VOID ExWaitOnPushLock(PEX_PUSH_LOCK PushLock)
Definition: ex.h:1176
UNICODE_STRING Name
Definition: obtypes.h:433
VOID NTAPI ExpBlockOnLockedHandleEntry(IN PHANDLE_TABLE HandleTable, IN PHANDLE_TABLE_ENTRY HandleTableEntry)
Definition: handle.c:858
#define InterlockedCompareExchange
Definition: interlocked.h:104
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:361
LONG ExtraInfoPages
Definition: extypes.h:635
#define OBJECT_HEADER_TO_NAME_INFO(h)
Definition: obtypes.h:114
LIST_ENTRY HandleTableList
Definition: extypes.h:627
POBJECT_TYPE ExDesktopObjectType
Definition: win32k.c:22
PHANDLE_TABLE_ENTRY *NTAPI ExpAllocateMidLevelTable(IN PHANDLE_TABLE HandleTable, IN BOOLEAN DoInit, OUT PHANDLE_TABLE_ENTRY *LowTableEntry)
Definition: handle.c:475
Definition: strmini.h:380
static XMS_HANDLE HandleTable[XMS_MAX_HANDLES]
Definition: himem.c:83
VOID FASTCALL ExWaitForUnblockPushLock(IN PEX_PUSH_LOCK PushLock, IN PVOID WaitBlock)
Definition: pushlock.c:395
PCM_NAME_CONTROL_BLOCK NameBlock
Definition: cm.h:275
#define InsertTailList(ListHead, Entry)
if(dx==0 &&dy==0)
Definition: linetemp.h:174
VOID NTAPI ExUnlockHandleTableEntry(IN PHANDLE_TABLE HandleTable, IN PHANDLE_TABLE_ENTRY HandleTableEntry)
Definition: handle.c:923
BOOLEAN NTAPI KdbpGetHexNumber(IN PCHAR pszNum, OUT ULONG_PTR *pulValue)
Definition: kdb_cli.c:468
ULONG_PTR Index
Definition: ex.h:89
BOOLEAN(NTAPI * PEX_CHANGE_HANDLE_CALLBACK)(PHANDLE_TABLE_ENTRY HandleTableEntry, ULONG_PTR Context)
Definition: ex.h:447
BOOLEAN NTAPI ExChangeHandle(IN PHANDLE_TABLE HandleTable, IN HANDLE Handle, IN PEX_CHANGE_HANDLE_CALLBACK ChangeRoutine, IN ULONG_PTR Context)
Definition: handle.c:1189
_In_opt_ PALLOCATE_FUNCTION _In_opt_ PFREE_FUNCTION Free
Definition: exfuncs.h:814
uint32_t ULONG_PTR
Definition: typedefs.h:65
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
HANDLE NTAPI ExCreateHandle(IN PHANDLE_TABLE HandleTable, IN PHANDLE_TABLE_ENTRY HandleTableEntry)
Definition: handle.c:827
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:439
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define FALSE
Definition: types.h:117
BOOLEAN NTAPI ExpAllocateHandleTableEntrySlow(IN PHANDLE_TABLE HandleTable, IN BOOLEAN DoInit)
Definition: handle.c:502
#define OBJ_NAME_PATH_SEPARATOR
Definition: arcname_tests.c:25
VOID NTAPI CmpCopyCompressedName(OUT PWCHAR Destination, IN ULONG DestinationLength, IN PWCHAR Source, IN ULONG SourceLength)
Definition: cmname.c:56
#define InterlockedCompareExchangePointer
Definition: interlocked.h:129
#define PsGetCurrentProcess
Definition: psfuncs.h:17
#define SizeOfHandle(x)
Definition: handle.c:20
FORCEINLINE VOID ExReleasePushLockExclusive(PEX_PUSH_LOCK PushLock)
Definition: ex.h:1250
Definition: extypes.h:595
unsigned char BOOLEAN
PVOID NTAPI ExpAllocateTablePagedPool(IN PEPROCESS Process OPTIONAL, IN SIZE_T Size)
Definition: handle.c:107
#define ObpGetHandleObject(x)
Definition: ob.h:91
VOID NTAPI ExpFreeTablePagedPool(IN PEPROCESS Process OPTIONAL, IN PVOID Buffer, IN SIZE_T Size)
Definition: handle.c:168
_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:426
USHORT NameLength
Definition: cm.h:242
#define ExInitializePushLock
Definition: ex.h:1011
Definition: bufpool.h:45
void * PVOID
Definition: retypes.h:9
LONG HandleCount
Definition: extypes.h:644
BOOLEAN Compressed
Definition: cm.h:233
#define isdigit(c)
Definition: acclib.h:68
#define InterlockedExchangeAdd
Definition: interlocked.h:181
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:547
struct _HANDLE_TABLE_ENTRY * PHANDLE_TABLE_ENTRY
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
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:406
Definition: arc.h:79
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
Status
Definition: gdiplustypes.h:24
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
#define ObpDirectoryObjectType
Definition: ObTypes.c:123
#define InterlockedExchangePointer(Target, Value)
Definition: dshow.h:45
#define strtoulptr
Definition: handle.c:28
PHANDLE_TABLE_ENTRY NTAPI ExpAllocateHandleTableEntry(IN PHANDLE_TABLE HandleTable, OUT PEXHANDLE NewHandle)
Definition: handle.c:683
#define ASSERT(a)
Definition: mode.c:44
VOID NTAPI ExpInitializeHandleTables(VOID)
Definition: handle.c:34
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define FREE_HANDLE_MASK
Definition: ex.h:145
VOID NTAPI ExRemoveHandleTable(IN PHANDLE_TABLE HandleTable)
Definition: handle.c:944
_In_ WDFCOLLECTION _In_ ULONG Index
HANDLE GenericHandleOverlay
Definition: ex.h:100
BOOLEAN NTAPI ExpLockHandleTableEntry(IN PHANDLE_TABLE HandleTable, IN PHANDLE_TABLE_ENTRY HandleTableEntry)
Definition: handle.c:884
VOID KdbpPrint(IN PCHAR Format, IN ... OPTIONAL)
Prints the given string with printf-like formatting.
Definition: kdb_cli.c:2801
#define INDEX_TO_HANDLE_VALUE(x)
Definition: handle.c:21
PVOID HANDLE
Definition: typedefs.h:73
PHANDLE_TABLE NTAPI ExCreateHandleTable(IN PEPROCESS Process OPTIONAL)
Definition: handle.c:801
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
POBJECT_TYPE MmSectionObjectType
Definition: section.c:195
* PFILE_OBJECT
Definition: iotypes.h:1998
Definition: strmini.h:378
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define TAG_OBJECT_TABLE
Definition: tag.h:26
Definition: ex.h:84
#define InterlockedDecrement
Definition: armddk.h:52
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:454
#define KeEnterCriticalRegion()
Definition: ke_x.h:88
#define HIGH_LEVEL_ENTRIES
Definition: ex.h:152
#define InterlockedOr
Definition: interlocked.h:224
#define PAGE_SIZE
Definition: env_spec_w32.h:49
Definition: typedefs.h:119
#define MAX_MID_INDEX
Definition: ex.h:158
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
NTSTATUS NTAPI PsChargeProcessPagedPoolQuota(_In_ PEPROCESS Process, _In_ SIZE_T Amount)
Charges the paged pool quota of a given process.
Definition: quota.c:839
POBJECT_TYPE IoFileObjectType
Definition: iomgr.c:36
processorSet Mask
#define EXHANDLE_TABLE_ENTRY_LOCK_BIT
Definition: ex.h:144
#define InterlockedExchange
Definition: armddk.h:54
_Must_inspect_result_ _In_ WDFCOLLECTION _In_ WDFOBJECT Object
PVOID NTAPI ExpAllocateTablePagedPoolNoZero(IN PEPROCESS Process OPTIONAL, IN SIZE_T Size)
Definition: handle.c:139
WCHAR Name[ANYSIZE_ARRAY]
Definition: cm.h:243
ULONG NTAPI ExpMoveFreeHandles(IN PHANDLE_TABLE HandleTable)
Definition: handle.c:648
FORCEINLINE VOID ExAcquirePushLockShared(PEX_PUSH_LOCK PushLock)
Definition: ex.h:1103
ULONG_PTR SIZE_T
Definition: typedefs.h:80
VOID NTAPI ExpFreeLowLevelTable(IN PEPROCESS Process, IN PHANDLE_TABLE_ENTRY TableEntry)
Definition: handle.c:183
#define KeLeaveCriticalRegion()
Definition: ke_x.h:119
#define InterlockedIncrement
Definition: armddk.h:53
ULONG_PTR Value
Definition: extypes.h:602
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
#define LOW_LEVEL_ENTRIES
Definition: ex.h:150
unsigned short USHORT
Definition: pedump.c:61
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
VOID NTAPI ExpFreeHandleTable(IN PHANDLE_TABLE HandleTable)
Definition: handle.c:202
__int3264 LONG_PTR
Definition: mstsclib_h.h:276
LONG_PTR PointerCount
Definition: obtypes.h:487
HANDLE NTAPI PsGetCurrentProcessId(VOID)
Definition: process.c:1123
#define NULL
Definition: types.h:112
VOID NTAPI ExSweepHandleTable(IN PHANDLE_TABLE HandleTable, IN PEX_SWEEP_HANDLE_CALLBACK EnumHandleProcedure, IN PVOID Context)
Definition: handle.c:1232
VOID FASTCALL ExfUnblockPushLock(PEX_PUSH_LOCK PushLock, PVOID CurrentWaitBlock)
Definition: pushlock.c:1205
LONG NextFreeTableEntry
Definition: extypes.h:612
_Must_inspect_result_ typedef _In_ ULONG TableEntry
Definition: iotypes.h:4303
#define MID_LEVEL_ENTRIES
Definition: ex.h:151
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219
_In_ HANDLE Handle
Definition: extypes.h:390
#define OUT
Definition: typedefs.h:40
FORCEINLINE VOID ExReleasePushLockShared(PEX_PUSH_LOCK PushLock)
Definition: ex.h:1211
VOID NTAPI ExpFreeHandleTableEntry(IN PHANDLE_TABLE HandleTable, IN EXHANDLE Handle, IN PHANDLE_TABLE_ENTRY HandleTableEntry)
Definition: handle.c:279
EX_PUSH_LOCK HandleTableListLock
Definition: handle.c:19
unsigned int ULONG
Definition: retypes.h:1
#define CmpKeyObjectType
Definition: ObTypes.c:132
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define ULONG_PTR
Definition: config.h:101
PVOID Object
Definition: extypes.h:599
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
LIST_ENTRY HandleTableListHead
Definition: handle.c:18
ULONG_PTR Value
Definition: ex.h:101
HANDLE NTAPI PsGetProcessId(PEPROCESS Process)
Definition: process.c:1063
UNICODE_STRING Name
Definition: obtypes.h:383
#define KeGetCurrentThread
Definition: hal.h:55
POBJECT_TYPE Type
Definition: obtypes.h:493
struct _CM_KEY_BODY * PCM_KEY_BODY
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
signed int * PLONG
Definition: retypes.h:5
static CODE_SEG("PAGE")
Definition: isapnp.c:1482
#define APC_LEVEL
Definition: env_spec_w32.h:695
USHORT NTAPI CmpCompressedNameSize(IN PWCHAR Name, IN ULONG Length)
Definition: cmname.c:95
BOOLEAN(NTAPI * PEX_SWEEP_HANDLE_CALLBACK)(PHANDLE_TABLE_ENTRY HandleTableEntry, HANDLE Handle, PVOID Context)
Definition: ex.h:432
base of all file and directory entries
Definition: entries.h:82
#define PAGED_CODE()
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
BOOLEAN ExpKdbgExtHandle(ULONG Argc, PCHAR Argv[])