ReactOS  0.4.15-dev-3733-g974a0f0
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 CODE_SEG("INIT")
26 VOID
27 NTAPI
29 {
30  /* Initialize the list of handle tables and the lock */
33 }
34 
36 NTAPI
39 {
40  ULONG TableLevel;
41  ULONG_PTR TableBase;
42  PHANDLE_TABLE_ENTRY HandleArray, Entry;
43  PVOID *PointerArray;
44 
45  /* Clear the tag bits */
46  Handle.TagBits = 0;
47 
48  /* Check if the handle is in the allocated range */
49  if (Handle.Value >= HandleTable->NextHandleNeedingPool)
50  {
51  return NULL;
52  }
53 
54  /* Get the table code */
55  TableBase = HandleTable->TableCode;
56 
57  /* Extract the table level and actual table base */
58  TableLevel = (ULONG)(TableBase & 3);
59  TableBase &= ~3;
60 
61  PointerArray = (PVOID*)TableBase;
62  HandleArray = (PHANDLE_TABLE_ENTRY)TableBase;
63 
64  /* Check what level we're running at */
65  switch (TableLevel)
66  {
67  case 2:
68 
69  /* Get the mid level pointer array */
70  PointerArray = PointerArray[Handle.HighIndex];
71  ASSERT(PointerArray != NULL);
72 
73  /* Fall through */
74  case 1:
75 
76  /* Get the handle array */
77  HandleArray = PointerArray[Handle.MidIndex];
78  ASSERT(HandleArray != NULL);
79 
80  /* Fall through */
81  case 0:
82 
83  /* Get the entry using the low index */
84  Entry = &HandleArray[Handle.LowIndex];
85 
86  /* All done */
87  break;
88 
89  default:
90 
91  ASSERT(FALSE);
92  Entry = NULL;
93  }
94 
95  /* Return the handle entry */
96  return Entry;
97 }
98 
99 PVOID
100 NTAPI
102  IN SIZE_T Size)
103 {
104  PVOID Buffer;
106 
107  /* Do the allocation */
109  if (Buffer)
110  {
111  /* Clear the memory */
113 
114  /* Check if we have a process to charge quota */
115  if (Process)
116  {
117  /* Charge quota */
119  if (!NT_SUCCESS(Status))
120  {
122  return NULL;
123  }
124  }
125  }
126 
127  /* Return the allocated memory */
128  return Buffer;
129 }
130 
131 PVOID
132 NTAPI
134  IN SIZE_T Size)
135 {
136  PVOID Buffer;
138 
139  /* Do the allocation */
141  if (Buffer)
142  {
143  /* Check if we have a process to charge quota */
144  if (Process)
145  {
146  /* Charge quota */
148  if (!NT_SUCCESS(Status))
149  {
151  return NULL;
152  }
153  }
154  }
155 
156  /* Return the allocated memory */
157  return Buffer;
158 }
159 
160 VOID
161 NTAPI
163  IN PVOID Buffer,
164  IN SIZE_T Size)
165 {
166  /* Free the buffer */
168  if (Process)
169  {
170  /* Release quota */
172  }
173 }
174 
175 VOID
176 NTAPI
179 {
180  /* Check if we have an entry */
181  if (TableEntry[0].Object)
182  {
183  /* Free the entry */
185  TableEntry[0].Object,
187  sizeof(HANDLE_TABLE_ENTRY_INFO));
188  }
189 
190  /* Free the table */
192 }
193 
194 VOID
195 NTAPI
197 {
198  PEPROCESS Process = HandleTable->QuotaProcess;
199  ULONG i, j;
200  ULONG_PTR TableCode = HandleTable->TableCode;
201  ULONG_PTR TableBase = TableCode & ~3;
202  ULONG TableLevel = (ULONG)(TableCode & 3);
203  PHANDLE_TABLE_ENTRY Level1, *Level2, **Level3;
204  PAGED_CODE();
205 
206  /* Check which level we're at */
207  if (TableLevel == 0)
208  {
209  /* Select the first level table base and just free it */
210  Level1 = (PVOID)TableBase;
211  ExpFreeLowLevelTable(Process, Level1);
212  }
213  else if (TableLevel == 1)
214  {
215  /* Select the second level table base */
216  Level2 = (PVOID)TableBase;
217 
218  /* Loop each mid level entry */
219  for (i = 0; i < MID_LEVEL_ENTRIES; i++)
220  {
221  /* Leave if we've reached the last entry */
222  if (!Level2[i]) break;
223 
224  /* Free the second level table */
225  ExpFreeLowLevelTable(Process, Level2[i]);
226  }
227 
228  /* Free the second level table */
230  }
231  else
232  {
233  /* Select the third level table base */
234  Level3 = (PVOID)TableBase;
235 
236  /* Loop each high level entry */
237  for (i = 0; i < HIGH_LEVEL_ENTRIES; i++)
238  {
239  /* Leave if we've reached the last entry */
240  if (!Level3[i]) break;
241 
242  /* Loop each mid level entry */
243  for (j = 0; j < MID_LEVEL_ENTRIES; j++)
244  {
245  /* Leave if we've reached the last entry */
246  if (!Level3[i][j]) break;
247 
248  /* Free the second level table */
249  ExpFreeLowLevelTable(Process, Level3[i][j]);
250  }
251 
252  /* Free the third level table entry */
254  }
255 
256  /* Free the third level table */
258  Level3,
260  }
261 
262  /* Free the actual table and check if we need to release quota */
264  if (Process)
265  {
266  /* Release the quota it was taking up */
268  }
269 }
270 
271 VOID
272 NTAPI
275  IN PHANDLE_TABLE_ENTRY HandleTableEntry)
276 {
277  ULONG OldValue, *Free;
278  ULONG LockIndex;
279  PAGED_CODE();
280 
281  /* Sanity checks */
282  ASSERT(HandleTableEntry->Object == NULL);
283  ASSERT(HandleTableEntry == ExpLookupHandleTableEntry(HandleTable, Handle));
284 
285  /* Decrement the handle count */
286  InterlockedDecrement(&HandleTable->HandleCount);
287 
288  /* Mark the handle as free */
289  Handle.TagBits = 0;
290 
291  /* Check if we're FIFO */
292  if (!HandleTable->StrictFIFO)
293  {
294  /* Select a lock index */
295  LockIndex = Handle.Index % 4;
296 
297  /* Select which entry to use */
298  Free = (HandleTable->HandleTableLock[LockIndex].Locked) ?
299  &HandleTable->FirstFree : &HandleTable->LastFree;
300  }
301  else
302  {
303  /* No need to worry about locking, take the last entry */
304  Free = &HandleTable->LastFree;
305  }
306 
307  /* Start value change loop */
308  for (;;)
309  {
310  /* Get the current value and write */
311  OldValue = *Free;
312  HandleTableEntry->NextFreeTableEntry = OldValue;
313  if (InterlockedCompareExchange((PLONG)Free, Handle.AsULONG, OldValue) == OldValue)
314  {
315  /* Break out, we're done. Make sure the handle value makes sense */
316  ASSERT((OldValue & FREE_HANDLE_MASK) <
317  HandleTable->NextHandleNeedingPool);
318  break;
319  }
320  }
321 }
322 
324 NTAPI
326  IN BOOLEAN NewTable)
327 {
329  PHANDLE_TABLE_ENTRY HandleTableTable, HandleEntry;
330  ULONG i;
332  PAGED_CODE();
333 
334  /* Allocate the table */
336  sizeof(HANDLE_TABLE),
338  if (!HandleTable) return NULL;
339 
340  /* Check if we have a process */
341  if (Process)
342  {
343  /* Charge quota */
345  if (!NT_SUCCESS(Status))
346  {
348  return NULL;
349  }
350  }
351 
352  /* Clear the table */
354 
355  /* Now allocate the first level structures */
357  if (!HandleTableTable)
358  {
359  /* Failed, free the table */
361 
362  /* Return the quota it was taking up */
363  if (Process)
364  {
366  }
367 
368  return NULL;
369  }
370 
371  /* Write the pointer to our first level structures */
372  HandleTable->TableCode = (ULONG_PTR)HandleTableTable;
373 
374  /* Initialize the first entry */
375  HandleEntry = &HandleTableTable[0];
376  HandleEntry->NextFreeTableEntry = -2;
377  HandleEntry->Value = 0;
378 
379  /* Check if this is a new table */
380  if (NewTable)
381  {
382  /* Go past the root entry */
383  HandleEntry++;
384 
385  /* Loop every low level entry */
386  for (i = 1; i < (LOW_LEVEL_ENTRIES - 1); i++)
387  {
388  /* Set up the free data */
389  HandleEntry->Value = 0;
390  HandleEntry->NextFreeTableEntry = INDEX_TO_HANDLE_VALUE(i + 1);
391 
392  /* Move to the next entry */
393  HandleEntry++;
394  }
395 
396  /* Terminate the last entry */
397  HandleEntry->Value = 0;
398  HandleEntry->NextFreeTableEntry = 0;
399  HandleTable->FirstFree = INDEX_TO_HANDLE_VALUE(1);
400  }
401 
402  /* Set the next handle needing pool after our allocated page from above */
403  HandleTable->NextHandleNeedingPool = INDEX_TO_HANDLE_VALUE(LOW_LEVEL_ENTRIES);
404 
405  /* Setup the rest of the handle table data */
406  HandleTable->QuotaProcess = Process;
407  HandleTable->UniqueProcessId = PsGetCurrentProcess()->UniqueProcessId;
408  HandleTable->Flags = 0;
409 
410  /* Loop all the handle table locks */
411  for (i = 0; i < 4; i++)
412  {
413  /* Initialize the handle table lock */
414  ExInitializePushLock(&HandleTable->HandleTableLock[i]);
415  }
416 
417  /* Initialize the contention event lock and return the lock */
418  ExInitializePushLock(&HandleTable->HandleContentionEvent);
419  return HandleTable;
420 }
421 
423 NTAPI
425  IN BOOLEAN DoInit)
426 {
427  ULONG i, Base;
428  PHANDLE_TABLE_ENTRY Low, HandleEntry;
429 
430  /* Allocate the low level table */
432  PAGE_SIZE);
433  if (!Low) return NULL;
434 
435  /* Setup the initial entry */
436  HandleEntry = &Low[0];
437  HandleEntry->NextFreeTableEntry = -2;
438  HandleEntry->Value = 0;
439 
440  /* Check if we're initializing */
441  if (DoInit)
442  {
443  /* Go to the next entry and the base entry */
444  HandleEntry++;
445  Base = HandleTable->NextHandleNeedingPool + INDEX_TO_HANDLE_VALUE(2);
446 
447  /* Loop each entry */
448  for (i = Base;
450  i += INDEX_TO_HANDLE_VALUE(1))
451  {
452  /* Free this entry and move on to the next one */
453  HandleEntry->NextFreeTableEntry = i;
454  HandleEntry->Value = 0;
455  HandleEntry++;
456  }
457 
458  /* Terminate the last entry */
459  HandleEntry->NextFreeTableEntry = 0;
460  HandleEntry->Value = 0;
461  }
462 
463  /* Return the low level table */
464  return Low;
465 }
466 
468 NTAPI
470  IN BOOLEAN DoInit,
471  OUT PHANDLE_TABLE_ENTRY *LowTableEntry)
472 {
473  PHANDLE_TABLE_ENTRY *Mid, Low;
474 
475  /* Allocate the mid level table */
476  Mid = ExpAllocateTablePagedPool(HandleTable->QuotaProcess, PAGE_SIZE);
477  if (!Mid) return NULL;
478 
479  /* Allocate a new low level for it */
481  if (!Low)
482  {
483  /* We failed, free the mid table */
484  ExpFreeTablePagedPool(HandleTable->QuotaProcess, Mid, PAGE_SIZE);
485  return NULL;
486  }
487 
488  /* Link the tables and return the pointer */
489  Mid[0] = Low;
490  *LowTableEntry = Low;
491  return Mid;
492 }
493 
494 BOOLEAN
495 NTAPI
497  IN BOOLEAN DoInit)
498 {
499  ULONG i, j, Index;
500  PHANDLE_TABLE_ENTRY Low = NULL, *Mid, **High, *SecondLevel, **ThirdLevel;
501  ULONG NewFree, FirstFree;
502  PVOID Value;
503  ULONG_PTR TableCode = HandleTable->TableCode;
504  ULONG_PTR TableBase = TableCode & ~3;
505  ULONG TableLevel = (ULONG)(TableCode & 3);
506  PAGED_CODE();
507 
508  /* Check how many levels we already have */
509  if (TableLevel == 0)
510  {
511  /* Allocate a mid level, since we only have a low level */
512  Mid = ExpAllocateMidLevelTable(HandleTable, DoInit, &Low);
513  if (!Mid) return FALSE;
514 
515  /* Link up the tables */
516  Mid[1] = Mid[0];
517  Mid[0] = (PVOID)TableBase;
518 
519  /* Write the new level and attempt to change the table code */
520  TableBase = ((ULONG_PTR)Mid) | 1;
521  Value = InterlockedExchangePointer((PVOID*)&HandleTable->TableCode, (PVOID)TableBase);
522  }
523  else if (TableLevel == 1)
524  {
525  /* Setup the 2nd level table */
526  SecondLevel = (PVOID)TableBase;
527 
528  /* Get if the next index can fit in the table */
529  i = HandleTable->NextHandleNeedingPool /
531  if (i < MID_LEVEL_ENTRIES)
532  {
533  /* We need to allocate a new table */
535  if (!Low) return FALSE;
536 
537  /* Update the table */
538  Value = InterlockedExchangePointer((PVOID*)&SecondLevel[i], Low);
539  ASSERT(Value == NULL);
540  }
541  else
542  {
543  /* We need a new high level table */
546  if (!High) return FALSE;
547 
548  /* Allocate a new mid level table as well */
549  Mid = ExpAllocateMidLevelTable(HandleTable, DoInit, &Low);
550  if (!Mid)
551  {
552  /* We failed, free the high level table as well */
553  ExpFreeTablePagedPool(HandleTable->QuotaProcess,
554  High,
556  return FALSE;
557  }
558 
559  /* Link up the tables */
560  High[0] = (PVOID)TableBase;
561  High[1] = Mid;
562 
563  /* Write the new table and change the table code */
564  TableBase = ((ULONG_PTR)High) | 2;
566  (PVOID)TableBase);
567  }
568  }
569  else if (TableLevel == 2)
570  {
571  /* Setup the 3rd level table */
572  ThirdLevel = (PVOID)TableBase;
573 
574  /* Get the index and check if it can fit */
575  i = HandleTable->NextHandleNeedingPool / INDEX_TO_HANDLE_VALUE(MAX_MID_INDEX);
576  if (i >= HIGH_LEVEL_ENTRIES) return FALSE;
577 
578  /* Check if there's no mid-level table */
579  if (!ThirdLevel[i])
580  {
581  /* Allocate a new mid level table */
582  Mid = ExpAllocateMidLevelTable(HandleTable, DoInit, &Low);
583  if (!Mid) return FALSE;
584 
585  /* Update the table pointer */
586  Value = InterlockedExchangePointer((PVOID*)&ThirdLevel[i], Mid);
587  ASSERT(Value == NULL);
588  }
589  else
590  {
591  /* We have one, check at which index we should insert our entry */
592  Index = (HandleTable->NextHandleNeedingPool / INDEX_TO_HANDLE_VALUE(1)) -
593  i * MAX_MID_INDEX;
595 
596  /* Allocate a new low level */
598  if (!Low) return FALSE;
599 
600  /* Update the table pointer */
601  Value = InterlockedExchangePointer((PVOID*)&ThirdLevel[i][j], Low);
602  ASSERT(Value == NULL);
603  }
604  }
605  else
606  {
607  /* Something is really broken */
608  ASSERT(FALSE);
609  }
610 
611  /* Update the index of the next handle */
612  Index = InterlockedExchangeAdd((PLONG) &HandleTable->NextHandleNeedingPool,
614 
615  /* Check if need to initialize the table */
616  if (DoInit)
617  {
618  /* Create a new index number */
620 
621  /* Start free index change loop */
622  for (;;)
623  {
624  /* Setup the first free index */
625  FirstFree = HandleTable->FirstFree;
626  Low[LOW_LEVEL_ENTRIES - 1].NextFreeTableEntry = FirstFree;
627 
628  /* Change the index */
629  NewFree = InterlockedCompareExchange((PLONG) &HandleTable->FirstFree,
630  Index,
631  FirstFree);
632  if (NewFree == FirstFree) break;
633  }
634  }
635 
636  /* All done */
637  return TRUE;
638 }
639 
640 ULONG
641 NTAPI
643 {
644  ULONG LastFree, i;
645 
646  /* Clear the last free index */
647  LastFree = InterlockedExchange((PLONG) &HandleTable->LastFree, 0);
648 
649  /* Check if we had no index */
650  if (!LastFree) return LastFree;
651 
652  /* Acquire the locks we need */
653  for (i = 1; i < 4; i++)
654  {
655  /* Acquire this lock exclusively */
656  ExWaitOnPushLock(&HandleTable->HandleTableLock[i]);
657  }
658 
659  /* Check if we're not strict FIFO */
660  if (!HandleTable->StrictFIFO)
661  {
662  /* Update the first free index */
663  if (!InterlockedCompareExchange((PLONG) &HandleTable->FirstFree, LastFree, 0))
664  {
665  /* We're done, exit */
666  return LastFree;
667  }
668  }
669 
670  /* We are strict FIFO, we need to reverse the entries */
671  ASSERT(FALSE);
672  return LastFree;
673 }
674 
676 NTAPI
678  OUT PEXHANDLE NewHandle)
679 {
680  ULONG OldValue, NewValue, NewValue1;
682  EXHANDLE Handle, OldHandle;
683  BOOLEAN Result;
684  ULONG i;
685 
686  /* Start allocation loop */
687  for (;;)
688  {
689  /* Get the current link */
690  OldValue = HandleTable->FirstFree;
691  while (!OldValue)
692  {
693  /* No free entries remain, lock the handle table */
695  ExAcquirePushLockExclusive(&HandleTable->HandleTableLock[0]);
696 
697  /* Check the value again */
698  OldValue = HandleTable->FirstFree;
699  if (OldValue)
700  {
701  /* Another thread has already created a new level, bail out */
702  ExReleasePushLockExclusive(&HandleTable->HandleTableLock[0]);
704  break;
705  }
706 
707  /* Now move any free handles */
708  OldValue = ExpMoveFreeHandles(HandleTable);
709  if (OldValue)
710  {
711  /* Another thread has already moved them, bail out */
712  ExReleasePushLockExclusive(&HandleTable->HandleTableLock[0]);
714  break;
715  }
716 
717  /* We're the first one through, so do the actual allocation */
719 
720  /* Unlock the table and get the value now */
721  ExReleasePushLockExclusive(&HandleTable->HandleTableLock[0]);
723  OldValue = HandleTable->FirstFree;
724 
725  /* Check if allocation failed */
726  if (!Result)
727  {
728  /* Check if nobody else went through here */
729  if (!OldValue)
730  {
731  /* We're still the only thread around, so fail */
732  NewHandle->GenericHandleOverlay = NULL;
733  return NULL;
734  }
735  }
736  }
737 
738  /* We made it, write the current value */
739  Handle.Value = (OldValue & FREE_HANDLE_MASK);
740 
741  /* Lookup the entry for this handle */
743 
744  /* Get an available lock and acquire it */
745  OldHandle.Value = OldValue;
746  i = OldHandle.Index % 4;
748  ExAcquirePushLockShared(&HandleTable->HandleTableLock[i]);
749 
750  /* Check if the value changed after acquiring the lock */
751  if (OldValue != *(volatile ULONG*)&HandleTable->FirstFree)
752  {
753  /* It did, so try again */
754  ExReleasePushLockShared(&HandleTable->HandleTableLock[i]);
756  continue;
757  }
758 
759  /* Now get the next value and do the compare */
760  NewValue = *(volatile ULONG*)&Entry->NextFreeTableEntry;
761  NewValue1 = InterlockedCompareExchange((PLONG) &HandleTable->FirstFree,
762  NewValue,
763  OldValue);
764 
765  /* The change was done, so release the lock */
766  ExReleasePushLockShared(&HandleTable->HandleTableLock[i]);
768 
769  /* Check if the compare was successful */
770  if (NewValue1 == OldValue)
771  {
772  /* Make sure that the new handle is in range, and break out */
773  ASSERT((NewValue & FREE_HANDLE_MASK) <
774  HandleTable->NextHandleNeedingPool);
775  break;
776  }
777  else
778  {
779  /* The compare failed, make sure we expected it */
780  ASSERT((NewValue1 & FREE_HANDLE_MASK) !=
781  (OldValue & FREE_HANDLE_MASK));
782  }
783  }
784 
785  /* Increase the number of handles */
786  InterlockedIncrement(&HandleTable->HandleCount);
787 
788  /* Return the handle and the entry */
789  *NewHandle = Handle;
790  return Entry;
791 }
792 
794 NTAPI
796 {
798  PAGED_CODE();
799 
800  /* Allocate the handle table */
802  if (!HandleTable) return NULL;
803 
804  /* Acquire the handle table lock */
807 
808  /* Insert it into the list */
809  InsertTailList(&HandleTableListHead, &HandleTable->HandleTableList);
810 
811  /* Release the lock */
814 
815  /* Return the handle table */
816  return HandleTable;
817 }
818 
819 HANDLE
820 NTAPI
822  IN PHANDLE_TABLE_ENTRY HandleTableEntry)
823 {
825  PHANDLE_TABLE_ENTRY NewEntry;
826  PAGED_CODE();
827 
828  /* Start with a clean handle */
829  Handle.GenericHandleOverlay = NULL;
830 
831  /* Allocate a new entry */
833  if (NewEntry)
834  {
835  /* Enter a critical region */
837 
838  /* Write the entry */
839  *NewEntry = *HandleTableEntry;
840 
841  /* Unlock it and leave the critical region */
844  }
845 
846  /* Return the handle value */
847  return Handle.GenericHandleOverlay;
848 }
849 
850 VOID
851 NTAPI
853  IN PHANDLE_TABLE_ENTRY HandleTableEntry)
854 {
855  LONG_PTR OldValue;
856  EX_PUSH_LOCK_WAIT_BLOCK WaitBlock;
857 
858  /* Block on the pushlock */
859  ExBlockPushLock(&HandleTable->HandleContentionEvent, &WaitBlock);
860 
861  /* Get the current value and check if it's been unlocked */
862  OldValue = HandleTableEntry->Value;
863  if (!(OldValue) || (OldValue & EXHANDLE_TABLE_ENTRY_LOCK_BIT))
864  {
865  /* Unblock the pushlock and return */
866  ExfUnblockPushLock(&HandleTable->HandleContentionEvent, &WaitBlock);
867  }
868  else
869  {
870  /* Wait for it to be unblocked */
871  ExWaitForUnblockPushLock(&HandleTable->HandleContentionEvent,
872  &WaitBlock);
873  }
874 }
875 
876 BOOLEAN
877 NTAPI
879  IN PHANDLE_TABLE_ENTRY HandleTableEntry)
880 {
881  LONG_PTR NewValue, OldValue;
882 
883  /* Sanity check */
884  ASSERT((KeGetCurrentThread()->CombinedApcDisable != 0) ||
885  (KeGetCurrentIrql() == APC_LEVEL));
886 
887  /* Start lock loop */
888  for (;;)
889  {
890  /* Get the current value and check if it's locked */
891  OldValue = *(volatile LONG_PTR *)&HandleTableEntry->Object;
892  if (OldValue & EXHANDLE_TABLE_ENTRY_LOCK_BIT)
893  {
894  /* It's not locked, remove the lock bit to lock it */
895  NewValue = OldValue & ~EXHANDLE_TABLE_ENTRY_LOCK_BIT;
896  if (InterlockedCompareExchangePointer(&HandleTableEntry->Object,
897  (PVOID)NewValue,
898  (PVOID)OldValue) == (PVOID)OldValue)
899  {
900  /* We locked it, get out */
901  return TRUE;
902  }
903  }
904  else
905  {
906  /* We couldn't lock it, bail out if it's been freed */
907  if (!OldValue) return FALSE;
908  }
909 
910  /* It's locked, wait for it to be unlocked */
911  ExpBlockOnLockedHandleEntry(HandleTable, HandleTableEntry);
912  }
913 }
914 
915 VOID
916 NTAPI
918  IN PHANDLE_TABLE_ENTRY HandleTableEntry)
919 {
920  LONG_PTR OldValue;
921  PAGED_CODE();
922 
923  /* Sanity check */
924  ASSERT((KeGetCurrentThread()->CombinedApcDisable != 0) ||
925  (KeGetCurrentIrql() == APC_LEVEL));
926 
927  /* Set the lock bit and make sure it wasn't earlier */
928  OldValue = InterlockedOr((PLONG) &HandleTableEntry->Value,
930  ASSERT((OldValue & EXHANDLE_TABLE_ENTRY_LOCK_BIT) == 0);
931 
932  /* Unblock any waiters */
933  ExfUnblockPushLock(&HandleTable->HandleContentionEvent, NULL);
934 }
935 
936 VOID
937 NTAPI
939 {
940  PAGED_CODE();
941 
942  /* Acquire the table lock */
945 
946  /* Remove the table and reset the list */
947  RemoveEntryList(&HandleTable->HandleTableList);
948  InitializeListHead(&HandleTable->HandleTableList);
949 
950  /* Release the lock */
953 }
954 
955 VOID
956 NTAPI
958  IN PVOID DestroyHandleProcedure OPTIONAL)
959 {
960  PAGED_CODE();
961 
962  /* Remove the handle from the list */
964 
965  /* Check if we have a destroy callback */
966  if (DestroyHandleProcedure)
967  {
968  /* FIXME: */
969  ASSERT(FALSE);
970  }
971 
972  /* Free the handle table */
974 }
975 
976 BOOLEAN
977 NTAPI
979  IN HANDLE Handle,
980  IN PHANDLE_TABLE_ENTRY HandleTableEntry OPTIONAL)
981 {
982  EXHANDLE ExHandle;
983  PVOID Object;
984  PAGED_CODE();
985 
986  /* Setup the actual handle value */
987  ExHandle.GenericHandleOverlay = Handle;
988 
989  /* Enter a critical region and check if we have to lookup the handle */
991  if (!HandleTableEntry)
992  {
993  /* Lookup the entry */
994  HandleTableEntry = ExpLookupHandleTableEntry(HandleTable, ExHandle);
995 
996  /* Make sure that we found an entry, and that it's valid */
997  if (!(HandleTableEntry) ||
998  !(HandleTableEntry->Object) ||
999  (HandleTableEntry->NextFreeTableEntry == -2))
1000  {
1001  /* Invalid handle, fail */
1003  return FALSE;
1004  }
1005 
1006  /* Lock the entry */
1007  if (!ExpLockHandleTableEntry(HandleTable, HandleTableEntry))
1008  {
1009  /* Couldn't lock, fail */
1011  return FALSE;
1012  }
1013  }
1014  else
1015  {
1016  /* Make sure the handle is locked */
1017  ASSERT((HandleTableEntry->Value & EXHANDLE_TABLE_ENTRY_LOCK_BIT) == 0);
1018  }
1019 
1020  /* Clear the handle */
1021  Object = InterlockedExchangePointer((PVOID*)&HandleTableEntry->Object, NULL);
1022 
1023  /* Sanity checks */
1024  ASSERT(Object != NULL);
1026 
1027  /* Unblock the pushlock */
1028  ExfUnblockPushLock(&HandleTable->HandleContentionEvent, NULL);
1029 
1030  /* Free the actual entry */
1031  ExpFreeHandleTableEntry(HandleTable, ExHandle, HandleTableEntry);
1032 
1033  /* If we got here, return success */
1035  return TRUE;
1036 }
1037 
1039 NTAPI
1041  IN HANDLE Handle)
1042 {
1043  EXHANDLE ExHandle;
1044  PHANDLE_TABLE_ENTRY HandleTableEntry;
1045  PAGED_CODE();
1046 
1047  /* Set the handle value */
1048  ExHandle.GenericHandleOverlay = Handle;
1049 
1050  /* Fail if we got an invalid index */
1051  if (!(ExHandle.Index & (LOW_LEVEL_ENTRIES - 1))) return NULL;
1052 
1053  /* Do the lookup */
1054  HandleTableEntry = ExpLookupHandleTableEntry(HandleTable, ExHandle);
1055  if (!HandleTableEntry) return NULL;
1056 
1057  /* Lock it */
1058  if (!ExpLockHandleTableEntry(HandleTable, HandleTableEntry)) return NULL;
1059 
1060  /* Return the entry */
1061  return HandleTableEntry;
1062 }
1063 
1065 NTAPI
1068  IN PEX_DUPLICATE_HANDLE_CALLBACK DupHandleProcedure,
1069  IN ULONG_PTR Mask)
1070 {
1071  PHANDLE_TABLE NewTable;
1072  EXHANDLE Handle;
1073  PHANDLE_TABLE_ENTRY HandleTableEntry, NewEntry;
1074  BOOLEAN Failed = FALSE;
1075  PAGED_CODE();
1076 
1077  /* Allocate the duplicated copy */
1078  NewTable = ExpAllocateHandleTable(Process, FALSE);
1079  if (!NewTable) return NULL;
1080 
1081  /* Loop each entry */
1082  while (NewTable->NextHandleNeedingPool <
1083  HandleTable->NextHandleNeedingPool)
1084  {
1085  /* Insert it into the duplicated copy */
1086  if (!ExpAllocateHandleTableEntrySlow(NewTable, FALSE))
1087  {
1088  /* Insert failed, free the new copy and return */
1089  ExpFreeHandleTable(NewTable);
1090  return NULL;
1091  }
1092  }
1093 
1094  /* Setup the initial handle table data */
1095  NewTable->HandleCount = 0;
1096  NewTable->ExtraInfoPages = 0;
1097  NewTable->FirstFree = 0;
1098 
1099  /* Setup the first handle value */
1100  Handle.Value = INDEX_TO_HANDLE_VALUE(1);
1101 
1102  /* Enter a critical region and lookup the new entry */
1104  while ((NewEntry = ExpLookupHandleTableEntry(NewTable, Handle)))
1105  {
1106  /* Lookup the old entry */
1107  HandleTableEntry = ExpLookupHandleTableEntry(HandleTable, Handle);
1108 
1109  /* Loop each entry */
1110  do
1111  {
1112  /* Check if it doesn't match the audit mask */
1113  if (!(HandleTableEntry->Value & Mask))
1114  {
1115  /* Free it since we won't use it */
1116  Failed = TRUE;
1117  }
1118  else
1119  {
1120  /* Lock the entry */
1121  if (!ExpLockHandleTableEntry(HandleTable, HandleTableEntry))
1122  {
1123  /* Free it since we can't lock it, so we won't use it */
1124  Failed = TRUE;
1125  }
1126  else
1127  {
1128  /* Copy the handle value */
1129  *NewEntry = *HandleTableEntry;
1130 
1131  /* Call the duplicate callback */
1132  if (DupHandleProcedure(Process,
1133  HandleTable,
1134  HandleTableEntry,
1135  NewEntry))
1136  {
1137  /* Clear failure flag */
1138  Failed = FALSE;
1139 
1140  /* Lock the entry, increase the handle count */
1141  NewEntry->Value |= EXHANDLE_TABLE_ENTRY_LOCK_BIT;
1142  NewTable->HandleCount++;
1143  }
1144  else
1145  {
1146  /* Duplication callback refused, fail */
1147  Failed = TRUE;
1148  }
1149  }
1150  }
1151 
1152  /* Check if we failed earlier and need to free */
1153  if (Failed)
1154  {
1155  /* Free this entry */
1156  NewEntry->Object = NULL;
1157  NewEntry->NextFreeTableEntry = NewTable->FirstFree;
1158  NewTable->FirstFree = (ULONG)Handle.Value;
1159  }
1160 
1161  /* Increase the handle value and move to the next entry */
1162  Handle.Value += INDEX_TO_HANDLE_VALUE(1);
1163  NewEntry++;
1164  HandleTableEntry++;
1165  } while (Handle.Value % INDEX_TO_HANDLE_VALUE(LOW_LEVEL_ENTRIES));
1166 
1167  /* We're done, skip the last entry */
1169  }
1170 
1171  /* Acquire the table lock and insert this new table into the list */
1175 
1176  /* Leave the critical region we entered previously and return the table */
1178  return NewTable;
1179 }
1180 
1181 BOOLEAN
1182 NTAPI
1184  IN HANDLE Handle,
1185  IN PEX_CHANGE_HANDLE_CALLBACK ChangeRoutine,
1187 {
1188  EXHANDLE ExHandle;
1189  PHANDLE_TABLE_ENTRY HandleTableEntry;
1190  BOOLEAN Result = FALSE;
1191  PAGED_CODE();
1192 
1193  /* Set the handle value */
1194  ExHandle.GenericHandleOverlay = Handle;
1195 
1196  /* Find the entry for this handle */
1197  HandleTableEntry = ExpLookupHandleTableEntry(HandleTable, ExHandle);
1198 
1199  /* Make sure that we found an entry, and that it's valid */
1200  if (!(HandleTableEntry) ||
1201  !(HandleTableEntry->Object) ||
1202  (HandleTableEntry->NextFreeTableEntry == -2))
1203  {
1204  /* It isn't, fail */
1205  return FALSE;
1206  }
1207 
1208  /* Enter a critical region */
1210 
1211  /* Try locking the handle entry */
1212  if (ExpLockHandleTableEntry(HandleTable, HandleTableEntry))
1213  {
1214  /* Call the change routine and unlock the entry */
1215  Result = ChangeRoutine(HandleTableEntry, Context);
1216  ExUnlockHandleTableEntry(HandleTable, HandleTableEntry);
1217  }
1218 
1219  /* Leave the critical region and return the callback result */
1221  return Result;
1222 }
1223 
1224 VOID
1225 NTAPI
1227  IN PEX_SWEEP_HANDLE_CALLBACK EnumHandleProcedure,
1228  IN PVOID Context)
1229 {
1230  EXHANDLE Handle;
1231  PHANDLE_TABLE_ENTRY HandleTableEntry;
1232  PAGED_CODE();
1233 
1234  /* Set the initial value and loop the entries */
1235  Handle.Value = INDEX_TO_HANDLE_VALUE(1);
1236  while ((HandleTableEntry = ExpLookupHandleTableEntry(HandleTable, Handle)))
1237  {
1238  /* Loop each handle */
1239  do
1240  {
1241  /* Lock the entry */
1242  if (ExpLockHandleTableEntry(HandleTable, HandleTableEntry))
1243  {
1244  /* Notify the callback routine */
1245  EnumHandleProcedure(HandleTableEntry,
1246  Handle.GenericHandleOverlay,
1247  Context);
1248  }
1249 
1250  /* Go to the next handle and entry */
1251  Handle.Value += INDEX_TO_HANDLE_VALUE(1);
1252  HandleTableEntry++;
1253  } while (Handle.Value % INDEX_TO_HANDLE_VALUE(LOW_LEVEL_ENTRIES));
1254 
1255  /* Skip past the last entry */
1257  }
1258 }
1259 
1260 /*
1261  * @implemented
1262  */
1263 BOOLEAN
1264 NTAPI
1266  IN PEX_ENUM_HANDLE_CALLBACK EnumHandleProcedure,
1267  IN OUT PVOID Context,
1268  OUT PHANDLE EnumHandle OPTIONAL)
1269 {
1270  EXHANDLE Handle;
1271  PHANDLE_TABLE_ENTRY HandleTableEntry;
1272  BOOLEAN Result = FALSE;
1273  PAGED_CODE();
1274 
1275  /* Enter a critical region */
1277 
1278  /* Set the initial value and loop the entries */
1279  Handle.Value = 0;
1280  while ((HandleTableEntry = ExpLookupHandleTableEntry(HandleTable, Handle)))
1281  {
1282  /* Validate the entry */
1283  if ((HandleTableEntry->Object) &&
1284  (HandleTableEntry->NextFreeTableEntry != -2))
1285  {
1286  /* Lock the entry */
1287  if (ExpLockHandleTableEntry(HandleTable, HandleTableEntry))
1288  {
1289  /* Notify the callback routine */
1290  Result = EnumHandleProcedure(HandleTableEntry,
1291  Handle.GenericHandleOverlay,
1292  Context);
1293 
1294  /* Unlock it */
1295  ExUnlockHandleTableEntry(HandleTable, HandleTableEntry);
1296 
1297  /* Was this the one looked for? */
1298  if (Result)
1299  {
1300  /* If so, return it if requested */
1301  if (EnumHandle) *EnumHandle = Handle.GenericHandleOverlay;
1302  break;
1303  }
1304  }
1305  }
1306 
1307  /* Go to the next entry */
1308  Handle.Value += INDEX_TO_HANDLE_VALUE(1);
1309  }
1310 
1311  /* Leave the critical region and return callback result */
1313  return Result;
1314 }
1315 
1316 #if DBG && defined(KDBG)
1317 BOOLEAN ExpKdbgExtHandle(ULONG Argc, PCHAR Argv[])
1318 {
1319  USHORT i;
1320  char *endptr;
1321  HANDLE ProcessId;
1322  EXHANDLE ExHandle;
1325  WCHAR KeyPath[256];
1328  POBJECT_HEADER ObjectHeader;
1330  ULONG NeededLength = 0;
1331  ULONG NameLength;
1332  PCM_KEY_CONTROL_BLOCK Kcb, CurrentKcb;
1333  POBJECT_HEADER_NAME_INFO ObjectNameInfo;
1334 
1335  if (Argc > 1)
1336  {
1337  /* Get EPROCESS address or PID */
1338  i = 0;
1339  while (Argv[1][i])
1340  {
1341  if (!isdigit(Argv[1][i]))
1342  {
1343  i = 0;
1344  break;
1345  }
1346 
1347  ++i;
1348  }
1349 
1350  if (i == 0)
1351  {
1352  if (!KdbpGetHexNumber(Argv[1], (PVOID)&Process))
1353  {
1354  KdbpPrint("Invalid parameter: %s\n", Argv[1]);
1355  return TRUE;
1356  }
1357 
1358  /* In the end, we always want a PID */
1360  }
1361  else
1362  {
1363  ProcessId = (HANDLE)strtoul(Argv[1], &endptr, 10);
1364  if (*endptr != '\0')
1365  {
1366  KdbpPrint("Invalid parameter: %s\n", Argv[1]);
1367  return TRUE;
1368  }
1369  }
1370  }
1371  else
1372  {
1374  }
1375 
1378  Entry = Entry->Flink)
1379  {
1380  /* Only return matching PID
1381  * 0 matches everything
1382  */
1383  HandleTable = CONTAINING_RECORD(Entry, HANDLE_TABLE, HandleTableList);
1384  if (ProcessId != 0 && HandleTable->UniqueProcessId != ProcessId)
1385  {
1386  continue;
1387  }
1388 
1389  KdbpPrint("\n");
1390 
1391  KdbpPrint("Handle table at %p with %d entries in use\n", HandleTable, HandleTable->HandleCount);
1392 
1393  ExHandle.Value = 0;
1394  while ((TableEntry = ExpLookupHandleTableEntry(HandleTable, ExHandle)))
1395  {
1396  if ((TableEntry->Object) &&
1397  (TableEntry->NextFreeTableEntry != -2))
1398  {
1399  ObjectHeader = ObpGetHandleObject(TableEntry);
1400 
1401  KdbpPrint("%p: Object: %p GrantedAccess: %x Entry: %p\n", ExHandle.Value, &ObjectHeader->Body, TableEntry->GrantedAccess, TableEntry);
1402  KdbpPrint("Object: %p Type: (%x) %wZ\n", &ObjectHeader->Body, ObjectHeader->Type, &ObjectHeader->Type->Name);
1403  KdbpPrint("\tObjectHeader: %p\n", ObjectHeader);
1404  KdbpPrint("\t\tHandleCount: %u PointerCount: %u\n", ObjectHeader->HandleCount, ObjectHeader->PointerCount);
1405 
1406  /* Specific objects debug prints */
1407 
1408  /* For file, display path */
1409  if (ObjectHeader->Type == IoFileObjectType)
1410  {
1411  FileObject = (PFILE_OBJECT)&ObjectHeader->Body;
1412 
1413  KdbpPrint("\t\t\tName: %wZ\n", &FileObject->FileName);
1414  }
1415 
1416  /* For directory, and win32k objects, display object name */
1417  else if (ObjectHeader->Type == ObpDirectoryObjectType ||
1418  ObjectHeader->Type == ExWindowStationObjectType ||
1419  ObjectHeader->Type == ExDesktopObjectType ||
1420  ObjectHeader->Type == MmSectionObjectType)
1421  {
1422  ObjectNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
1423  if (ObjectNameInfo != NULL && ObjectNameInfo->Name.Buffer != NULL)
1424  {
1425  KdbpPrint("\t\t\tName: %wZ\n", &ObjectNameInfo->Name);
1426  }
1427  }
1428 
1429  /* For registry keys, display full path */
1430  else if (ObjectHeader->Type == CmpKeyObjectType)
1431  {
1432  Kcb = ((PCM_KEY_BODY)&ObjectHeader->Body)->KeyControlBlock;
1433  if (!Kcb->Delete)
1434  {
1435  CurrentKcb = Kcb;
1436 
1437  /* See: CmpQueryNameInformation() */
1438 
1439  while (CurrentKcb != NULL)
1440  {
1441  if (CurrentKcb->NameBlock->Compressed)
1442  NeededLength += CmpCompressedNameSize(CurrentKcb->NameBlock->Name, CurrentKcb->NameBlock->NameLength);
1443  else
1444  NeededLength += CurrentKcb->NameBlock->NameLength;
1445 
1446  NeededLength += sizeof(OBJ_NAME_PATH_SEPARATOR);
1447 
1448  CurrentKcb = CurrentKcb->ParentKcb;
1449  }
1450 
1451  if (NeededLength < sizeof(KeyPath))
1452  {
1453  CurrentKcb = Kcb;
1454 
1455  while (CurrentKcb != NULL)
1456  {
1457  if (CurrentKcb->NameBlock->Compressed)
1458  {
1459  NameLength = CmpCompressedNameSize(CurrentKcb->NameBlock->Name, CurrentKcb->NameBlock->NameLength);
1460  CmpCopyCompressedName(&KeyPath[(NeededLength - NameLength)/sizeof(WCHAR)],
1461  NameLength,
1462  CurrentKcb->NameBlock->Name,
1463  CurrentKcb->NameBlock->NameLength);
1464  }
1465  else
1466  {
1467  NameLength = CurrentKcb->NameBlock->NameLength;
1468  RtlCopyMemory(&KeyPath[(NeededLength - NameLength)/sizeof(WCHAR)],
1469  CurrentKcb->NameBlock->Name,
1470  NameLength);
1471  }
1472 
1473  NeededLength -= NameLength;
1474  NeededLength -= sizeof(OBJ_NAME_PATH_SEPARATOR);
1475  KeyPath[NeededLength/sizeof(WCHAR)] = OBJ_NAME_PATH_SEPARATOR;
1476 
1477  CurrentKcb = CurrentKcb->ParentKcb;
1478  }
1479  }
1480 
1481  KdbpPrint("\t\t\tName: %S\n", KeyPath);
1482  }
1483  }
1484  }
1485 
1486  ExHandle.Value += INDEX_TO_HANDLE_VALUE(1);
1487  }
1488  }
1489 
1490  return TRUE;
1491 }
1492 #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:325
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:37
IN PLARGE_INTEGER IN PLARGE_INTEGER PEPROCESS ProcessId
Definition: fatprocs.h:2709
UINT32 strtoul(const char *String, char **Terminator, UINT32 Base)
Definition: utclib.c:696
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:978
LONG_PTR HandleCount
Definition: obtypes.h:490
struct _Entry Entry
Definition: kefuncs.h:627
ULONG NextHandleNeedingPool
Definition: extypes.h:645
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34
struct _CM_KEY_CONTROL_BLOCK * ParentKcb
Definition: cm.h:282
#define TRUE
Definition: types.h:120
PHANDLE_TABLE_ENTRY NTAPI ExMapHandleToPointer(IN PHANDLE_TABLE HandleTable, IN HANDLE Handle)
Definition: handle.c:1040
VOID NTAPI ExDestroyHandleTable(IN PHANDLE_TABLE HandleTable, IN PVOID DestroyHandleProcedure OPTIONAL)
Definition: handle.c:957
LONG NTSTATUS
Definition: precomp.h:26
PHANDLE_TABLE_ENTRY NTAPI ExpAllocateLowLevelTable(IN PHANDLE_TABLE HandleTable, IN BOOLEAN DoInit)
Definition: handle.c:424
_In_opt_ ULONG Base
Definition: rtlfuncs.h:2386
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:852
#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:469
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:283
#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:917
BOOLEAN NTAPI KdbpGetHexNumber(IN PCHAR pszNum, OUT ULONG_PTR *pulValue)
Definition: kdb_cli.c:465
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:1183
_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:821
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:496
#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:101
#define ObpGetHandleObject(x)
Definition: ob.h:91
VOID NTAPI ExpFreeTablePagedPool(IN PEPROCESS Process OPTIONAL, IN PVOID Buffer, IN SIZE_T Size)
Definition: handle.c:162
_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:250
#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:241
#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:1066
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
PHANDLE_TABLE_ENTRY NTAPI ExpAllocateHandleTableEntry(IN PHANDLE_TABLE HandleTable, OUT PEXHANDLE NewHandle)
Definition: handle.c:677
#define ASSERT(a)
Definition: mode.c:44
VOID NTAPI ExpInitializeHandleTables(VOID)
Definition: handle.c:28
__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:938
_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:878
VOID KdbpPrint(IN PCHAR Format, IN ... OPTIONAL)
Prints the given string with printf-like formatting.
Definition: kdb_cli.c:2716
#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:795
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:1265
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:133
WCHAR Name[ANYSIZE_ARRAY]
Definition: cm.h:251
ULONG NTAPI ExpMoveFreeHandles(IN PHANDLE_TABLE HandleTable)
Definition: handle.c:642
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:177
#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:196
__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:1226
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:273
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[])