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