Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

handle.c File Reference

#include "exp.h"

Go to the source code of this file.

Defines

#define EXHANDLE_TABLE_ENTRY_LOCK_BIT   ((ULONG_PTR)1 << ((sizeof(ULONG_PTR) * 8) - 1))

Functions

PHANDLE_TABLE ExpAllocateHandleTable (IN PEPROCESS Process OPTIONAL)
VOID ExpFreeHandleTable (IN PHANDLE_TABLE HandleTable)
PHANDLE_TABLE_ENTRY ExpAllocateHandleTableEntry (IN PHANDLE_TABLE HandleTable, OUT PEXHANDLE Handle)
VOID ExpFreeHandleTableEntry (IN PHANDLE_TABLE HandleTable, IN EXHANDLE Handle, IN PHANDLE_TABLE_ENTRY HandleTableEntry)
PHANDLE_TABLE_ENTRY ExpLookupHandleTableEntry (IN PHANDLE_TABLE HandleTable, IN EXHANDLE Handle)
NTKERNELAPI VOID ExLockHandleTableShared (PHANDLE_TABLE HandleTable)
NTKERNELAPI VOID ExLockHandleTableExclusive (PHANDLE_TABLE HandleTable)
NTKERNELAPI VOID ExUnlockHandleTableShared (PHANDLE_TABLE HandleTable)
NTKERNELAPI VOID ExUnlockHandleTableExclusive (PHANDLE_TABLE HandleTable)
NTKERNELAPI BOOLEAN ExLockHandleTableEntry (PHANDLE_TABLE HandleTable, PHANDLE_TABLE_ENTRY HandleTableEntry)
NTKERNELAPI VOID ExUnlockHandleTableEntry (PHANDLE_TABLE HandleTable, PHANDLE_TABLE_ENTRY HandleTableEntry)
NTKERNELAPI VOID ExInitializeHandleTablePackage (VOID)
NTKERNELAPI PHANDLE_TABLE ExCreateHandleTable (IN struct _EPROCESS *Process OPTIONAL)
NTKERNELAPI VOID ExRemoveHandleTable (IN PHANDLE_TABLE HandleTable)
NTKERNELAPI VOID ExDestroyHandleTable (IN PHANDLE_TABLE HandleTable, IN EX_DESTROY_HANDLE_ROUTINE DestroyHandleProcedure OPTIONAL)
NTKERNELAPI BOOLEAN ExEnumHandleTable (IN PHANDLE_TABLE HandleTable, IN EX_ENUMERATE_HANDLE_ROUTINE EnumHandleProcedure, IN PVOID EnumParameter, OUT PHANDLE Handle OPTIONAL)
NTKERNELAPI PHANDLE_TABLE ExDupHandleTable (IN struct _EPROCESS *Process OPTIONAL, IN PHANDLE_TABLE OldHandleTable, IN EX_DUPLICATE_HANDLE_ROUTINE DupHandleProcedure OPTIONAL)
NTKERNELAPI NTSTATUS ExSnapShotHandleTables (IN PEX_SNAPSHOT_HANDLE_ENTRY SnapShotHandleEntry, IN OUT PSYSTEM_HANDLE_INFORMATION HandleInformation, IN ULONG Length, IN OUT PULONG RequiredLength)
NTKERNELAPI HANDLE ExCreateHandle (IN PHANDLE_TABLE HandleTable, IN PHANDLE_TABLE_ENTRY HandleTableEntry)
NTKERNELAPI BOOLEAN ExDestroyHandle (IN PHANDLE_TABLE HandleTable, IN HANDLE Handle, IN PHANDLE_TABLE_ENTRY HandleTableEntry OPTIONAL)
NTKERNELAPI BOOLEAN ExChangeHandle (IN PHANDLE_TABLE HandleTable, IN HANDLE Handle, IN PEX_CHANGE_HANDLE_ROUTINE ChangeRoutine, IN ULONG_PTR Parameter)
NTKERNELAPI PHANDLE_TABLE_ENTRY ExMapHandleToPointer (IN PHANDLE_TABLE HandleTable, IN HANDLE Handle)

Variables

ERESOURCE HandleTableListLock
LIST_ENTRY HandleTableListHead
LARGE_INTEGER Ex10Milliseconds = {(ULONG)(-10 * 1000 * 10), -1}


Define Documentation

#define EXHANDLE_TABLE_ENTRY_LOCK_BIT   ((ULONG_PTR)1 << ((sizeof(ULONG_PTR) * 8) - 1))
 

Definition at line 44 of file ex/handle.c.

Referenced by ExLockHandleTableEntry(), and ExUnlockHandleTableEntry().


Function Documentation

NTKERNELAPI BOOLEAN ExChangeHandle IN PHANDLE_TABLE  HandleTable,
IN HANDLE  Handle,
IN PEX_CHANGE_HANDLE_ROUTINE  ChangeRoutine,
IN ULONG_PTR  Parameter
 

Definition at line 1315 of file ex/handle.c.

References ExLockHandleTableEntry(), ExpLookupHandleTableEntry(), ExUnlockHandleTableEntry(), FALSE, _EXHANDLE::GenericHandleOverlay, Handle, KeEnterCriticalRegion, KeLeaveCriticalRegion, NULL, and PAGED_CODE.

Referenced by NtSetInformationObject(), PspCreateThread(), and PspExitThread().

01324 : 01325 01326 This function provides the capability to change the contents of the 01327 handle entry corrsponding to the specified handle. 01328 01329 Arguments: 01330 01331 HandleTable - Supplies a pointer to a handle table. 01332 01333 Handle - Supplies the handle for the handle entry that is changed. 01334 01335 ChangeRoutine - Supplies a pointer to a function that is called to 01336 perform the change. 01337 01338 Parameter - Supplies an uninterpreted parameter that is passed to 01339 the change routine. 01340 01341 Return Value: 01342 01343 If the operation was successfully performed, then a value of TRUE 01344 is returned. Otherwise, a value of FALSE is returned. 01345 01346 --*/ 01347 01348 { 01349 EXHANDLE LocalHandle; 01350 01351 PHANDLE_TABLE_ENTRY HandleTableEntry; 01352 BOOLEAN ReturnValue; 01353 01354 PAGED_CODE(); 01355 01356 LocalHandle.GenericHandleOverlay = Handle; 01357 01358 // 01359 // Translate the input handle to a handle table entry and make 01360 // sure it is a valid handle. 01361 // 01362 01363 HandleTableEntry = ExpLookupHandleTableEntry( HandleTable, 01364 LocalHandle ); 01365 01366 if (HandleTableEntry == NULL) { 01367 01368 return FALSE; 01369 } 01370 01371 // 01372 // Try and lock the handle table entry, If this fails then that's 01373 // because someone freed the handle 01374 // 01375 01376 if (!ExLockHandleTableEntry( HandleTable, HandleTableEntry )) { 01377 01378 return FALSE; 01379 } 01380 01381 // 01382 // Make sure we can't get suspended and then invoke the callback 01383 // 01384 01385 KeEnterCriticalRegion(); 01386 01387 try { 01388 01389 ReturnValue = (*ChangeRoutine)( HandleTableEntry, Parameter ); 01390 01391 } finally { 01392 01393 ExUnlockHandleTableEntry( HandleTable, HandleTableEntry ); 01394 KeLeaveCriticalRegion(); 01395 } 01396 01397 return ReturnValue; 01398 }

NTKERNELAPI HANDLE ExCreateHandle IN PHANDLE_TABLE  HandleTable,
IN PHANDLE_TABLE_ENTRY  HandleTableEntry
 

Definition at line 1144 of file ex/handle.c.

References ExLockHandleTableExclusive(), ExpAllocateHandleTableEntry(), ExUnlockHandleTableEntry(), ExUnlockHandleTableExclusive(), Handle, KeEnterCriticalRegion, KeLeaveCriticalRegion, NULL, and PAGED_CODE.

Referenced by DoHandleTest(), NtDuplicateObject(), ObpCreateHandle(), ObpCreateUnnamedHandle(), PspCreateThread(), and RtlpCreateHandleForAtom().

01151 : 01152 01153 This function creates a handle entry in the specified handle table and 01154 returns a handle for the entry. 01155 01156 Arguments: 01157 01158 HandleTable - Supplies a pointer to a handle table 01159 01160 HandleEntry - Supplies a poiner to the handle entry for which a 01161 handle entry is created. 01162 01163 Return Value: 01164 01165 If the handle entry is successfully created, then value of the created 01166 handle is returned as the function value. Otherwise, a value of zero is 01167 returned. 01168 01169 --*/ 01170 01171 { 01172 EXHANDLE Handle; 01173 PHANDLE_TABLE_ENTRY NewHandleTableEntry; 01174 01175 PAGED_CODE(); 01176 01177 // 01178 // Set out output variable to zero (i.e., null) before going on 01179 // 01180 01181 // 01182 // Clears Handle.Index and Handle.TagBits 01183 // 01184 01185 Handle.GenericHandleOverlay = NULL; 01186 01187 // 01188 // Lock the handle table for exclusive access 01189 // 01190 01191 KeEnterCriticalRegion(); 01192 ExLockHandleTableExclusive( HandleTable ); 01193 01194 try { 01195 01196 // 01197 // Allocate a new handle table entry, and get the handle value 01198 // 01199 01200 NewHandleTableEntry = ExpAllocateHandleTableEntry( HandleTable, 01201 &Handle ); 01202 01203 // 01204 // If we really got a handle then copy over the template and unlock 01205 // the entry 01206 // 01207 01208 if (NewHandleTableEntry != NULL) { 01209 01210 *NewHandleTableEntry = *HandleTableEntry; 01211 01212 ExUnlockHandleTableEntry( HandleTable, NewHandleTableEntry ); 01213 } 01214 01215 } finally { 01216 01217 ExUnlockHandleTableExclusive( HandleTable ); 01218 KeLeaveCriticalRegion(); 01219 } 01220 01221 return Handle.GenericHandleOverlay; 01222 }

NTKERNELAPI PHANDLE_TABLE ExCreateHandleTable IN struct _EPROCESS *Process  OPTIONAL  ) 
 

Definition at line 457 of file ex/handle.c.

References ExpAllocateHandleTable(), and PAGED_CODE.

Referenced by DoHandleTest(), ObInitProcess(), ObInitSystem(), PspInitPhase0(), and RtlpInitializeHandleTableForAtomTable().

00463 : 00464 00465 This function allocate and initialize a new new handle table 00466 00467 Arguments: 00468 00469 Process - Supplies an optional pointer to the process against which quota 00470 will be charged. 00471 00472 Return Value: 00473 00474 If a handle table is successfully created, then the address of the 00475 handle table is returned as the function value. Otherwize, a value 00476 NULL is returned. 00477 00478 --*/ 00479 00480 { 00481 PHANDLE_TABLE HandleTable; 00482 00483 PAGED_CODE(); 00484 00485 // 00486 // Allocate and initialize a handle table descriptor 00487 // 00488 00489 HandleTable = ExpAllocateHandleTable( Process ); 00490 00491 // 00492 // And return to our caller 00493 // 00494 00495 return HandleTable; 00496 }

NTKERNELAPI BOOLEAN ExDestroyHandle IN PHANDLE_TABLE  HandleTable,
IN HANDLE  Handle,
IN PHANDLE_TABLE_ENTRY HandleTableEntry  OPTIONAL
 

Definition at line 1227 of file ex/handle.c.

References ExLockHandleTableEntry(), ExLockHandleTableExclusive(), ExpFreeHandleTableEntry(), ExpLookupHandleTableEntry(), ExUnlockHandleTableExclusive(), FALSE, _EXHANDLE::GenericHandleOverlay, Handle, KeEnterCriticalRegion, KeLeaveCriticalRegion, NULL, PAGED_CODE, and TRUE.

Referenced by DoHandleTest(), NtClose(), PspProcessDelete(), PspThreadDelete(), and RtlpFreeHandleForAtom().

01235 : 01236 01237 This function removes a handle from a handle table. 01238 01239 Arguments: 01240 01241 HandleTable - Supplies a pointer to a handle table 01242 01243 Handle - Supplies the handle value of the entry to remove. 01244 01245 HandleTableEntry - Optionally supplies a pointer to the handle 01246 table entry being destroyed. If supplied the entry is 01247 assume to be locked. 01248 01249 Return Value: 01250 01251 If the specified handle is successfully removed, then a value of 01252 TRUE is returned. Otherwise, a value of FALSE is returned. 01253 01254 --*/ 01255 01256 { 01257 EXHANDLE LocalHandle; 01258 01259 PAGED_CODE(); 01260 01261 LocalHandle.GenericHandleOverlay = Handle; 01262 01263 // 01264 // If the caller did not supply the optional handle table entry then 01265 // locate the entry via the supplied handle, make sure it is real, and 01266 // then lock the entry. 01267 // 01268 01269 if (HandleTableEntry == NULL) { 01270 01271 HandleTableEntry = ExpLookupHandleTableEntry( HandleTable, 01272 LocalHandle ); 01273 01274 if (HandleTableEntry == NULL) { 01275 01276 return FALSE; 01277 } 01278 01279 if (!ExLockHandleTableEntry( HandleTable, HandleTableEntry )) { 01280 01281 return FALSE; 01282 } 01283 } 01284 01285 // 01286 // At this point we have a locked handle table entry. Now mark it free 01287 // which does the implicit unlock. The system will not allocate it 01288 // again until we add it to the free list which we will do right after 01289 // we take out the lock 01290 // 01291 01292 HandleTableEntry->Object = NULL; 01293 01294 KeEnterCriticalRegion(); 01295 ExLockHandleTableExclusive( HandleTable ); 01296 01297 try { 01298 01299 ExpFreeHandleTableEntry( HandleTable, 01300 LocalHandle, 01301 HandleTableEntry ); 01302 01303 } finally { 01304 01305 ExUnlockHandleTableExclusive( HandleTable ); 01306 KeLeaveCriticalRegion(); 01307 } 01308 01309 return TRUE; 01310 }

NTKERNELAPI VOID ExDestroyHandleTable IN PHANDLE_TABLE  HandleTable,
IN EX_DESTROY_HANDLE_ROUTINE DestroyHandleProcedure  OPTIONAL
 

Definition at line 560 of file ex/handle.c.

References ExpFreeHandleTable(), ExpLookupHandleTableEntry(), ExRemoveHandleTable(), Handle, NULL, _HANDLE_TABLE_ENTRY::Object, and PAGED_CODE.

Referenced by DoHandleTest(), ObKillProcess(), and RtlpDestroyHandleTableForAtomTable().

00567 : 00568 00569 This function destroys the specified handle table. 00570 00571 Arguments: 00572 00573 HandleTable - Supplies a pointer to a handle table 00574 00575 DestroyHandleProcedure - Supplies a pointer to a function to call for each 00576 valid handle entry in the handle table. 00577 00578 Return Value: 00579 00580 None. 00581 00582 --*/ 00583 00584 { 00585 EXHANDLE Handle; 00586 PHANDLE_TABLE_ENTRY HandleTableEntry; 00587 00588 PAGED_CODE(); 00589 00590 // 00591 // Remove the handle table from the handle table list 00592 // 00593 00594 ExRemoveHandleTable( HandleTable ); 00595 00596 // 00597 // Iterate through the handle table and for each handle that is allocated 00598 // we'll invoke the call back. Note that this loop exits when we get a 00599 // null handle table entry. We know there will be no more possible 00600 // entries after the first null one is encountered because we allocate 00601 // memory of the handles in a dense fashion. But first test that we have 00602 // call back to use 00603 // 00604 00605 if (ARGUMENT_PRESENT(DestroyHandleProcedure)) { 00606 00607 for (Handle.GenericHandleOverlay = NULL; // does essentially the following "Handle.Index = 0, Handle.TagBits = 0;" 00608 (HandleTableEntry = ExpLookupHandleTableEntry( HandleTable, Handle )) != NULL; 00609 Handle.Index += 1) { 00610 00611 // 00612 // Only do the callback if the entry is not free 00613 // 00614 00615 if (HandleTableEntry->Object != NULL) { 00616 00617 (*DestroyHandleProcedure)( Handle.GenericHandleOverlay ); 00618 } 00619 } 00620 } 00621 00622 // 00623 // Now free up the handle table memory and return to our caller 00624 // 00625 00626 ExpFreeHandleTable( HandleTable ); 00627 00628 return; 00629 }

NTKERNELAPI PHANDLE_TABLE ExDupHandleTable IN struct _EPROCESS *Process  OPTIONAL,
IN PHANDLE_TABLE  OldHandleTable,
IN EX_DUPLICATE_HANDLE_ROUTINE DupHandleProcedure  OPTIONAL
 

Definition at line 765 of file ex/handle.c.

References ExLockHandleTableEntry(), ExLockHandleTableShared(), ExpAllocateHandleTable(), ExpAllocateHandleTableEntry(), ExpFreeHandleTable(), ExpFreeHandleTableEntry(), ExpLookupHandleTableEntry(), ExUnlockHandleTableEntry(), ExUnlockHandleTableShared(), _HANDLE_TABLE::FirstFreeTableEntry, Handle, _HANDLE_TABLE::HandleCount, KeEnterCriticalRegion, KeLeaveCriticalRegion, _HANDLE_TABLE_ENTRY::NextFreeTableEntry, _HANDLE_TABLE::NextIndexNeedingPool, NULL, _HANDLE_TABLE_ENTRY::Object, and PAGED_CODE.

Referenced by DoHandleTest(), and ObInitProcess().

00773 : 00774 00775 This function creates a duplicate copy of the specified handle table. 00776 00777 Arguments: 00778 00779 Process - Supplies an optional to the process to charge quota to. 00780 00781 OldHandleTable - Supplies a pointer to a handle table. 00782 00783 DupHandleProcedure - Supplies an optional pointer to a function to call 00784 for each valid handle in the duplicated handle table. 00785 00786 Return Value: 00787 00788 If the specified handle table is successfully duplicated, then the 00789 address of the new handle table is returned as the function value. 00790 Otherwize, a value NULL is returned. 00791 00792 --*/ 00793 00794 { 00795 PHANDLE_TABLE NewHandleTable; 00796 00797 PHANDLE_TABLE_ENTRY AdditionalFreeEntries; 00798 00799 EXHANDLE Handle; 00800 00801 PHANDLE_TABLE_ENTRY OldHandleTableEntry; 00802 PHANDLE_TABLE_ENTRY NewHandleTableEntry; 00803 00804 PAGED_CODE(); 00805 00806 // 00807 // First allocate a new handle table. If this fails then 00808 // return immediately to our caller 00809 // 00810 00811 NewHandleTable = ExpAllocateHandleTable( Process ); 00812 00813 if (NewHandleTable == NULL) { 00814 00815 return NULL; 00816 } 00817 00818 // 00819 // Now lock down the old handle table. We will release it 00820 // right after enumerating through the table 00821 // 00822 00823 KeEnterCriticalRegion(); 00824 ExLockHandleTableShared( OldHandleTable ); 00825 00826 AdditionalFreeEntries = NULL; 00827 00828 try { 00829 00830 // 00831 // Now we'll build up the new handle table. We do this by calling 00832 // allocating new handle table entries, and "fooling" the worker 00833 // routine to allocate keep on allocating until the next free 00834 // index needing pool are equal 00835 // 00836 00837 while (NewHandleTable->NextIndexNeedingPool < OldHandleTable->NextIndexNeedingPool) { 00838 00839 // 00840 // If we set the first free table entry to -1 then the worker 00841 // routine will allocate another buffer 00842 // 00843 00844 NewHandleTable->FirstFreeTableEntry = -1; 00845 00846 // 00847 // Call the worker routine to grow the new handle table. If 00848 // not successful then free the new table as far as we got, 00849 // set out output variable and exit out here 00850 // 00851 00852 if (ExpAllocateHandleTableEntry( NewHandleTable, &Handle ) == NULL) { 00853 00854 ExpFreeHandleTable( NewHandleTable ); 00855 00856 NewHandleTable = NULL; 00857 00858 leave; 00859 } 00860 } 00861 00862 // 00863 // Now modify the new handle table to think it has zero handles 00864 // and set its free list to start on the same index as the old 00865 // free list 00866 // 00867 00868 NewHandleTable->HandleCount = 0; 00869 NewHandleTable->FirstFreeTableEntry = OldHandleTable->FirstFreeTableEntry; 00870 00871 // 00872 // Now for every valid index value we'll copy over the old entry into 00873 // the new entry 00874 // 00875 00876 for (Handle.GenericHandleOverlay = NULL; // does essentially the following "Handle.Index = 0, Handle.TagBits = 0;" 00877 (OldHandleTableEntry = ExpLookupHandleTableEntry( OldHandleTable, Handle )) != NULL; 00878 Handle.Index += 1) { 00879 00880 // 00881 // The conditinal in the loop gives up the old handle table 00882 // entry, by definition there must exist a corresponding new 00883 // handle table entry, so now look it up 00884 // 00885 00886 NewHandleTableEntry = ExpLookupHandleTableEntry( NewHandleTable, 00887 Handle ); 00888 00889 // 00890 // If the old entry is free then simply copy over the entire 00891 // old entry to the new entry. The lock command will tell us 00892 // it entry is free. 00893 // 00894 00895 if (!ExLockHandleTableEntry( OldHandleTable, OldHandleTableEntry )) { 00896 00897 *NewHandleTableEntry = *OldHandleTableEntry; 00898 00899 } else { 00900 00901 // 00902 // Otherwise we have a non empty entry. So now copy it 00903 // over, and unlock the old entry. In both cases we bump 00904 // the handle count because either the entry is going into 00905 // the new table or we're going to remove it with Exp Free 00906 // Handle Table Entry which will decrement the handle count 00907 // 00908 00909 *NewHandleTableEntry = *OldHandleTableEntry; 00910 NewHandleTable->HandleCount += 1; 00911 00912 ExUnlockHandleTableEntry( OldHandleTable, OldHandleTableEntry ); 00913 00914 // 00915 // Invoke the callback and if it returns true then we 00916 // unlock the new entry 00917 // 00918 00919 if ((*DupHandleProcedure)( Process, NewHandleTableEntry )) { 00920 00921 ExUnlockHandleTableEntry( NewHandleTable, NewHandleTableEntry ); 00922 00923 } else { 00924 00925 // 00926 // Otherwise this entry is going to be freed in the 00927 // new handle table. So add it to the stack list of 00928 // additional freed entries 00929 // 00930 00931 NewHandleTableEntry->Object = AdditionalFreeEntries; 00932 NewHandleTableEntry->NextFreeTableEntry = Handle.Index; 00933 00934 AdditionalFreeEntries = NewHandleTableEntry; 00935 } 00936 } 00937 } 00938 00939 } finally { 00940 00941 ExUnlockHandleTableShared( OldHandleTable ); 00942 KeLeaveCriticalRegion(); 00943 } 00944 00945 // 00946 // At this point we are through with the old handle table, 00947 // and if present the new handle table is done with except 00948 // for adding back the newly freed entrires. The only time 00949 // the additionalFreeEntries variable will not be null is if 00950 // we successfully built the new table and the dup routine 00951 // came back false. 00952 // 00953 // While there are additional entries to add to the free list 00954 // pop the entry off the stack and add it to the table 00955 // 00956 00957 Handle.GenericHandleOverlay = NULL; 00958 while (AdditionalFreeEntries != NULL) { 00959 00960 PVOID Next; 00961 00962 Next = AdditionalFreeEntries->Object; 00963 Handle.Index = AdditionalFreeEntries->NextFreeTableEntry; 00964 00965 AdditionalFreeEntries->Object = NULL; 00966 00967 ExpFreeHandleTableEntry( NewHandleTable, 00968 Handle, 00969 AdditionalFreeEntries ); 00970 00971 AdditionalFreeEntries = Next; 00972 } 00973 00974 // 00975 // lastly return the new handle table to our caller 00976 // 00977 00978 return NewHandleTable; 00979 }

NTKERNELAPI BOOLEAN ExEnumHandleTable IN PHANDLE_TABLE  HandleTable,
IN EX_ENUMERATE_HANDLE_ROUTINE  EnumHandleProcedure,
IN PVOID  EnumParameter,
OUT PHANDLE Handle  OPTIONAL
 

Definition at line 634 of file ex/handle.c.

References ExLockHandleTableEntry(), ExLockHandleTableShared(), ExpLookupHandleTableEntry(), ExUnlockHandleTableEntry(), ExUnlockHandleTableShared(), FALSE, _EXHANDLE::GenericHandleOverlay, Handle, _EXHANDLE::Index, KeEnterCriticalRegion, KeLeaveCriticalRegion, NULL, _HANDLE_TABLE_ENTRY::Object, PAGED_CODE, and TRUE.

Referenced by DoHandleTest(), ObFindHandleForObject(), and ObInitProcess().

00643 : 00644 00645 This function enumerates all the valid handles in a handle table. 00646 For each valid handle in the handle table, the specified eumeration 00647 function is called. If the enumeration function returns TRUE, then 00648 the enumeration is stopped, the current handle is returned to the 00649 caller via the optional Handle parameter, and this function returns 00650 TRUE to indicated that the enumeration stopped at a specific handle. 00651 00652 Arguments: 00653 00654 HandleTable - Supplies a pointer to a handle table. 00655 00656 EnumHandleProcedure - Supplies a pointer to a fucntion to call for 00657 each valid handle in the enumerated handle table. 00658 00659 EnumParameter - Supplies an uninterpreted 32-bit value that is passed 00660 to the EnumHandleProcedure each time it is called. 00661 00662 Handle - Supplies an optional pointer a variable that receives the 00663 Handle value that the enumeration stopped at. Contents of the 00664 variable only valid if this function returns TRUE. 00665 00666 Return Value: 00667 00668 If the enumeration stopped at a specific handle, then a value of TRUE 00669 is returned. Otherwise, a value of FALSE is returned. 00670 00671 --*/ 00672 00673 { 00674 BOOLEAN ResultValue; 00675 EXHANDLE LocalHandle; 00676 PHANDLE_TABLE_ENTRY HandleTableEntry; 00677 00678 PAGED_CODE(); 00679 00680 // 00681 // First lock the handle table shared to stop anyone from creating or 00682 // destroying new handles. We need to do this because out iteration 00683 // function doesn't want the handles to be closed while we're doing 00684 // our work 00685 // 00686 00687 KeEnterCriticalRegion(); 00688 ExLockHandleTableShared( HandleTable ); 00689 00690 try { 00691 00692 // 00693 // Our initial return value is false until the enumeration callback 00694 // function tells us otherwise 00695 // 00696 00697 ResultValue = FALSE; 00698 00699 // 00700 // Iterate through the handle table and for each handle that is 00701 // allocated we'll invoke the call back. Note that this loop exits 00702 // when we get a null handle table entry. We know there will be no 00703 // more possible entries after the first null one is encountered 00704 // because we allocate memory of the handles in a dense fashion 00705 // 00706 00707 for (LocalHandle.GenericHandleOverlay = NULL; // does essentially the following "LocalHandle.Index = 0, LocalHandle.TagBits = 0;" 00708 (HandleTableEntry = ExpLookupHandleTableEntry( HandleTable, LocalHandle )) != NULL; 00709 LocalHandle.Index += 1) { 00710 00711 // 00712 // Only do the callback if the entry is not free 00713 // 00714 00715 if (HandleTableEntry->Object != NULL) { 00716 00717 // 00718 // Lock the handle table entry because we're about to give 00719 // it to the callback function, then release the entry 00720 // right after the call back. 00721 // 00722 00723 if (ExLockHandleTableEntry( HandleTable, HandleTableEntry )) { 00724 00725 try { 00726 00727 // 00728 // Invoke the callback, and if it returns true then set 00729 // the proper output values and break out of the loop. 00730 // 00731 00732 if ((*EnumHandleProcedure)( HandleTableEntry, 00733 LocalHandle.GenericHandleOverlay, 00734 EnumParameter )) { 00735 00736 if (ARGUMENT_PRESENT( Handle )) { 00737 00738 *Handle = LocalHandle.GenericHandleOverlay; 00739 } 00740 00741 ResultValue = TRUE; 00742 break; 00743 } 00744 00745 } finally { 00746 00747 ExUnlockHandleTableEntry( HandleTable, HandleTableEntry ); 00748 } 00749 } 00750 } 00751 } 00752 00753 } finally { 00754 00755 ExUnlockHandleTableShared( HandleTable ); 00756 KeLeaveCriticalRegion(); 00757 } 00758 00759 return ResultValue; 00760 }

NTKERNELAPI VOID ExInitializeHandleTablePackage VOID   ) 
 

Definition at line 422 of file ex/handle.c.

References ExInitializeResource, HandleTableListHead, and HandleTableListLock.

00428 : 00429 00430 This routine is called once at system initialization to setup the ex handle 00431 table package 00432 00433 Arguments: 00434 00435 None. 00436 00437 Return Value: 00438 00439 None. 00440 00441 --*/ 00442 00443 { 00444 // 00445 // Initialize the handle table synchronization resource and list head 00446 // 00447 00448 InitializeListHead( &HandleTableListHead ); 00449 ExInitializeResource( &HandleTableListLock ); 00450 00451 return; 00452 }

NTKERNELAPI BOOLEAN ExLockHandleTableEntry PHANDLE_TABLE  HandleTable,
PHANDLE_TABLE_ENTRY  HandleTableEntry
 

Definition at line 240 of file ex/handle.c.

References Ex10Milliseconds, Executive, EXHANDLE_TABLE_ENTRY_LOCK_BIT, FALSE, _HANDLE_TABLE::HandleContentionEvent, KernelMode, KeStallExecutionProcessor(), KeWaitForSingleObject(), _HANDLE_TABLE_ENTRY::Object, PAGED_CODE, and TRUE.

Referenced by ExChangeHandle(), ExDestroyHandle(), ExDupHandleTable(), ExEnumHandleTable(), ExMapHandleToPointer(), and ExSnapShotHandleTables().

00247 : 00248 00249 This routine locks the specified handle table entry. After the entry is 00250 locked the sign bit will be set. 00251 00252 Arguments: 00253 00254 HandleTable - Supplies the handle table containing the entry being locked. 00255 00256 HandleTableEntry - Supplies the handle table entry being locked. 00257 00258 Return Value: 00259 00260 TRUE if the entry is valid and locked, and FALSE if the entry is 00261 marked free. 00262 00263 --*/ 00264 00265 { 00266 LONG_PTR NewValue; 00267 LONG_PTR CurrentValue; 00268 ULONG LoopCount = 0; 00269 00270 PAGED_CODE(); 00271 00272 // 00273 // We'll keep on looping reading in the value, making sure it is not null, 00274 // and if it is not currently locked we'll try for the lock and return 00275 // true if we get it. Otherwise we'll pause a bit and then try again. 00276 // 00277 00278 while (TRUE) { 00279 00280 NewValue = 00281 CurrentValue = *((volatile LONG_PTR *)&HandleTableEntry->Object); 00282 00283 // 00284 // Make sure the handle table entry is not freed 00285 // 00286 00287 if (CurrentValue == 0) { 00288 00289 return FALSE; 00290 } 00291 00292 // 00293 // If the handle value is greater than zero then it is not currently 00294 // locked and we should try for the lock, but setting the lock bit and 00295 // doing an interlocked exchange. 00296 // 00297 00298 if (CurrentValue > 0) { 00299 00300 NewValue |= EXHANDLE_TABLE_ENTRY_LOCK_BIT; 00301 00302 if ((LONG_PTR)(InterlockedCompareExchangePointer( &HandleTableEntry->Object, 00303 (PVOID)NewValue, 00304 (PVOID)CurrentValue )) == CurrentValue) { 00305 00306 return TRUE; 00307 } 00308 } 00309 00310 // 00311 // Either someone already has the entry locked or the value changed 00312 // somehow, either way we'll wait a bit and try again. The first 00313 // time we'll wait by spinning for 10us and if that doesn't work 00314 // then we'll wait for the handle contention event to go off or 00315 // for 10ms, whichever comes first. 00316 // 00317 00318 if (LoopCount++ < 1) { 00319 00320 KeStallExecutionProcessor( 10 ); 00321 00322 } else { 00323 00324 KeWaitForSingleObject( &HandleTable->HandleContentionEvent, 00325 Executive, 00326 KernelMode, 00327 FALSE, 00328 &Ex10Milliseconds ); 00329 } 00330 } 00331 }

NTKERNELAPI VOID ExLockHandleTableExclusive PHANDLE_TABLE  HandleTable  ) 
 

Definition at line 146 of file ex/handle.c.

References ExAcquireResourceExclusive, _HANDLE_TABLE::HandleTableLock, PAGED_CODE, TRUE, and VOID().

Referenced by ExCreateHandle(), ExDestroyHandle(), and ExSnapShotHandleTables().

00152 : 00153 00154 This routine locks the specified handle table for exclusive access. Once 00155 locked the onwer can add or delete entries from the handle table. 00156 00157 Arguments: 00158 00159 HandleTable - Supplies the handle table being locked. 00160 00161 Return Value: 00162 00163 None. 00164 00165 --*/ 00166 00167 { 00168 PAGED_CODE(); 00169 00170 (VOID)ExAcquireResourceExclusive( &HandleTable->HandleTableLock, TRUE ); 00171 00172 return; 00173 }

NTKERNELAPI VOID ExLockHandleTableShared PHANDLE_TABLE  HandleTable  ) 
 

Definition at line 114 of file ex/handle.c.

References ExAcquireResourceShared, _HANDLE_TABLE::HandleTableLock, PAGED_CODE, TRUE, and VOID().

Referenced by ExDupHandleTable(), and ExEnumHandleTable().

00120 : 00121 00122 This routine locks the specified handle table for shared access. Once 00123 locked new entries cannot be added to deleted from the handle table. 00124 00125 Arguments: 00126 00127 HandleTable - Supplies the handle table being locked. 00128 00129 Return Value: 00130 00131 None. 00132 00133 --*/ 00134 00135 { 00136 PAGED_CODE(); 00137 00138 (VOID)ExAcquireResourceShared( &HandleTable->HandleTableLock, TRUE ); 00139 00140 return; 00141 }

NTKERNELAPI PHANDLE_TABLE_ENTRY ExMapHandleToPointer IN PHANDLE_TABLE  HandleTable,
IN HANDLE  Handle
 

Definition at line 1403 of file ex/handle.c.

References ExLockHandleTableEntry(), ExpLookupHandleTableEntry(), _EXHANDLE::GenericHandleOverlay, Handle, NULL, and PAGED_CODE.

Referenced by DoHandleTest(), NtClose(), NtWaitForMultipleObjects(), ObQueryObjectAuditingByHandle(), ObReferenceObjectByHandle(), PsLookupProcessByProcessId(), PsLookupProcessThreadByCid(), PsLookupThreadByThreadId(), and RtlpAtomMapAtomToHandleEntry().

01410 : 01411 01412 This function maps a handle to a pointer to a handle table entry. If the 01413 map operation is successful then the handle table entry is locked when 01414 we return. 01415 01416 Arguments: 01417 01418 HandleTable - Supplies a pointer to a handle table. 01419 01420 Handle - Supplies the handle to be mapped to a handle entry. 01421 01422 Return Value: 01423 01424 If the handle was successfully mapped to a pointer to a handle entry, 01425 then the address of the handle table entry is returned as the function 01426 value with the entry locked. Otherwise, a value of NULL is returned. 01427 01428 --*/ 01429 01430 { 01431 EXHANDLE LocalHandle; 01432 01433 PHANDLE_TABLE_ENTRY HandleTableEntry; 01434 01435 PAGED_CODE(); 01436 01437 LocalHandle.GenericHandleOverlay = Handle; 01438 01439 // 01440 // Translate the input handle to a handle table entry and make 01441 // sure it is a valid handle. 01442 // 01443 01444 HandleTableEntry = ExpLookupHandleTableEntry( HandleTable, 01445 LocalHandle ); 01446 01447 if (HandleTableEntry == NULL) { 01448 01449 return NULL; 01450 } 01451 01452 // 01453 // Try and lock the handle table entry, If this fails then that's 01454 // because someone freed the handle 01455 // 01456 01457 if (!ExLockHandleTableEntry( HandleTable, HandleTableEntry )) { 01458 01459 return NULL; 01460 } 01461 01462 // 01463 // Return the locked valid handle table entry 01464 // 01465 01466 return HandleTableEntry; 01467 }

PHANDLE_TABLE ExpAllocateHandleTable IN PEPROCESS Process  OPTIONAL  ) 
 

Definition at line 1475 of file ex/handle.c.

References ExAcquireResourceExclusive, ExAllocatePoolWithTag, EXCEPTION_EXECUTE_HANDLER, ExFreePool(), ExInitializeResource, ExReleaseResource, FALSE, _HANDLE_TABLE::FirstFreeTableEntry, HANDLE_TABLE, HANDLE_TABLE_ENTRY, _HANDLE_TABLE::HandleContentionEvent, _HANDLE_TABLE::HandleTableList, HandleTableListHead, HandleTableListLock, _HANDLE_TABLE::HandleTableLock, KeEnterCriticalRegion, KeInitializeEvent, KeLeaveCriticalRegion, _HANDLE_TABLE_ENTRY::NextFreeTableEntry, _HANDLE_TABLE::NextIndexNeedingPool, NonPagedPool, NULL, PAGED_CODE, PagedPool, POOL_RAISE_IF_ALLOCATION_FAILURE, PsChargePoolQuota(), PsGetCurrentProcess, PsReturnPoolQuota(), _HANDLE_TABLE::QuotaProcess, _HANDLE_TABLE::Table, TRUE, and _HANDLE_TABLE::UniqueProcessId.

Referenced by ExCreateHandleTable(), and ExDupHandleTable().

01481 : 01482 01483 This worker routine will allocate and initialize a new handle table 01484 structure. The new structure consists of the basic handle table 01485 struct plus the first allocation needed to store handles. This is 01486 really one page divided up into the top level node, the first mid 01487 level node, and one bottom level node. 01488 01489 Arguments: 01490 01491 Process - Optionally supplies the process to charge quota for the 01492 handle table 01493 01494 Return Value: 01495 01496 A pointer to the new handle table or NULL if unsuccessful at getting 01497 pool. 01498 01499 --*/ 01500 01501 { 01502 PHANDLE_TABLE HandleTable; 01503 BOOLEAN HandleTableQuotaCharged; 01504 01505 PVOID HandleTableTable; 01506 BOOLEAN HandleTableTableQuotaCharged; 01507 01508 ULONG i; 01509 01510 PAGED_CODE(); 01511 01512 HandleTable = NULL; 01513 HandleTableQuotaCharged = FALSE; 01514 01515 HandleTableTable = NULL; 01516 HandleTableTableQuotaCharged = FALSE; 01517 01518 // 01519 // If any alloation or quota failures happen we will catch it in the 01520 // following try-except clause and cleanup after outselves before 01521 // we return null 01522 // 01523 01524 try { 01525 01526 // 01527 // First allocate the handle table, make sure we got one, charge quota 01528 // for it and then zero it out 01529 // 01530 01531 HandleTable = (PHANDLE_TABLE)ExAllocatePoolWithTag( NonPagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE, 01532 sizeof(HANDLE_TABLE), 01533 'btbO' ); 01534 01535 if (ARGUMENT_PRESENT(Process)) { 01536 01537 PsChargePoolQuota( Process, 01538 NonPagedPool, 01539 sizeof(HANDLE_TABLE)); 01540 01541 HandleTableQuotaCharged = TRUE; 01542 } 01543 01544 RtlZeroMemory( HandleTable, sizeof(HANDLE_TABLE) ); 01545 01546 // 01547 // Now allocate space of the top level, one mid level and one bottom 01548 // level table structure. This will all fit on a page, maybe two. 01549 // 01550 01551 HandleTableTable = 01552 HandleTable->Table = ExAllocatePoolWithTag( PagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE, 01553 (2 * sizeof(ULONG_PTR) * 256) + (sizeof(HANDLE_TABLE_ENTRY) * 256), 01554 'btbO' ); 01555 01556 if (ARGUMENT_PRESENT(Process)) { 01557 01558 PsChargePoolQuota( Process, 01559 PagedPool, 01560 (2 * sizeof(ULONG_PTR) * 256) + (sizeof(HANDLE_TABLE_ENTRY) * 256) ); 01561 01562 HandleTableTableQuotaCharged = TRUE; 01563 01564 } 01565 01566 RtlZeroMemory( HandleTable->Table, 01567 (2 * sizeof(ULONG_PTR) * 256) + (sizeof(HANDLE_TABLE_ENTRY) * 256) ); 01568 01569 } except (EXCEPTION_EXECUTE_HANDLER) { 01570 01571 if (HandleTable != NULL) { 01572 01573 ExFreePool( HandleTable ); 01574 01575 if (HandleTableQuotaCharged) { 01576 01577 PsReturnPoolQuota( Process, 01578 NonPagedPool, 01579 sizeof(HANDLE_TABLE)); 01580 } 01581 } 01582 01583 if (HandleTableTable != NULL) { 01584 01585 ExFreePool( HandleTableTable ); 01586 01587 if (HandleTableTableQuotaCharged) { 01588 01589 PsReturnPoolQuota( Process, 01590 PagedPool, 01591 (2 * sizeof(ULONG_PTR) * 256) + (sizeof(HANDLE_TABLE_ENTRY) * 256) ); 01592 } 01593 } 01594 01595 return NULL; 01596 } 01597 01598 // 01599 // Now setup the pointers for the initial handle table tree 01600 // 01601 01602 HandleTable->Table[0] = (PVOID)(((PCHAR)(HandleTable->Table)) + 1 * (sizeof(ULONG_PTR) * 256)); 01603 HandleTable->Table[0][0] = (PVOID)(((PCHAR)(HandleTable->Table)) + 2 * (sizeof(ULONG_PTR) * 256)); 01604 01605 // 01606 // Now setup the free list. We do this by chaining together the free 01607 // entries such that each free entry give the next free index (i.e., 01608 // like a fat chain). The chain is terminated with a -1. Note that 01609 // we'll skip handle zero because our callers will get that value 01610 // confused with null. 01611 // 01612 01613 for (i = 0; i < 255; i += 1) { 01614 01615 (HandleTable->Table[0][0])[i].NextFreeTableEntry = i+1; 01616 } 01617 01618 (HandleTable->Table[0][0])[255].NextFreeTableEntry = -1; 01619 01620 HandleTable->FirstFreeTableEntry = 1; 01621 HandleTable->NextIndexNeedingPool = 256; 01622 01623 // 01624 // Setup the necessary process information 01625 // 01626 01627 HandleTable->QuotaProcess = Process; 01628 HandleTable->UniqueProcessId = PsGetCurrentProcess()->UniqueProcessId; 01629 01630 // 01631 // Initialize the lock handle table resource 01632 // 01633 01634 ExInitializeResource( &HandleTable->HandleTableLock ); 01635 01636 // 01637 // Initialize the notification event for handle table entry contention 01638 // 01639 01640 KeInitializeEvent( &HandleTable->HandleContentionEvent, NotificationEvent, FALSE ); 01641 01642 // 01643 // Insert the handle table in the handle table list. 01644 // 01645 01646 KeEnterCriticalRegion(); 01647 ExAcquireResourceExclusive( &HandleTableListLock, TRUE ); 01648 01649 InsertTailList( &HandleTableListHead, &HandleTable->HandleTableList ); 01650 01651 ExReleaseResource( &HandleTableListLock ); 01652 KeLeaveCriticalRegion(); 01653 01654 // 01655 // And return to our caller 01656 // 01657 01658 return HandleTable; 01659 }

PHANDLE_TABLE_ENTRY ExpAllocateHandleTableEntry IN PHANDLE_TABLE  HandleTable,
OUT PEXHANDLE  Handle
 

Definition at line 1825 of file ex/handle.c.

References ExAllocatePoolWithTag, EXCEPTION_EXECUTE_HANDLER, ExFreePool(), ExpLookupHandleTableEntry(), FALSE, Handle, HANDLE_TABLE_ENTRY, _HANDLE_TABLE_ENTRY::NextFreeTableEntry, NULL, PAGED_CODE, PagedPool, POOL_RAISE_IF_ALLOCATION_FAILURE, PsChargePoolQuota(), PsReturnPoolQuota(), and TRUE.

Referenced by ExCreateHandle(), and ExDupHandleTable().

01832 : 01833 01834 This worker routine allocates a new handle table entry for the specified 01835 handle table. 01836 01837 Note: The caller must have already locked the handle table 01838 01839 Arguments: 01840 01841 HandleTable - Supplies the handle table being used 01842 01843 Handle - Returns the handle of the new entry if the allocation is 01844 successful otherwise the value is null 01845 01846 Return Value: 01847 01848 Returns a pointer to the new handle table entry is the allocation is 01849 successful otherwise the return value is null. 01850 01851 --*/ 01852 01853 { 01854 ULONG i,j,k; 01855 01856 PUCHAR NewMidLevel; 01857 BOOLEAN MidTableQuotaCharged; 01858 01859 PUCHAR NewLowLevel; 01860 BOOLEAN LowTableQuotaCharged; 01861 01862 PHANDLE_TABLE_ENTRY HandleTableEntry; 01863 01864 PAGED_CODE(); 01865 01866 Handle->GenericHandleOverlay = NULL; 01867 01868 // 01869 // First see if the free stack is emtpy and if so then we need 01870 // to add some more entries to it 01871 // 01872 01873 if (HandleTable->FirstFreeTableEntry == -1) { 01874 01875 // 01876 // We need to allocate some more pool. We start by seeing 01877 // if the next index is too large to allocate. We only have 01878 // 24 bits of handle values to use 01879 // 01880 01881 if (HandleTable->NextIndexNeedingPool >= (1 << 24)) { 01882 01883 return NULL; 01884 } 01885 01886 // Now find the next index to allocate a buffer for 01887 // 01888 01889 i = (HandleTable->NextIndexNeedingPool >> 16) & 255; 01890 j = (HandleTable->NextIndexNeedingPool >> 8) & 255; 01891 01892 // 01893 // Within the following try body we'll be allocating and initializing 01894 // a low level buffer and possibly a new mid level buffer. The 01895 // might seem a little odd but is necessary to handle the situation 01896 // where our first buffer is allocated off a little bit (i.e., the 01897 // next buffer index starts are [0][1]). By the time we reach 01898 // [0][255] we add only one new buffer. Then start with even numbers 01899 // at [1][0] and work our way to completion 01900 // 01901 01902 NewMidLevel = NULL; 01903 MidTableQuotaCharged = FALSE; 01904 01905 NewLowLevel = NULL; 01906 LowTableQuotaCharged = FALSE; 01907 01908 try { 01909 01910 // 01911 // Check if we need to allocate a new mid level buffer, We do 01912 // these allocations four at a time 01913 // 01914 01915 if (HandleTable->Table[i] == NULL) { 01916 01917 NewMidLevel = ExAllocatePoolWithTag( PagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE, 01918 4 * sizeof(ULONG_PTR) * 256, 01919 'btbO' ); 01920 01921 RtlZeroMemory( NewMidLevel, 4 * sizeof(ULONG_PTR) * 256 ); 01922 01923 if (HandleTable->QuotaProcess != NULL) { 01924 01925 PsChargePoolQuota( HandleTable->QuotaProcess, 01926 PagedPool, 01927 (4 * sizeof(ULONG_PTR) * 256) ); 01928 01929 MidTableQuotaCharged = TRUE; 01930 } 01931 } 01932 01933 // 01934 // Now Allocate two new table entry buffers 01935 // 01936 01937 NewLowLevel = ExAllocatePoolWithTag( PagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE, 01938 2 * sizeof(HANDLE_TABLE_ENTRY) * 256, 01939 'btbO' ); 01940 01941 RtlZeroMemory( NewLowLevel, 2 * sizeof(HANDLE_TABLE_ENTRY) * 256 ); 01942 01943 if (HandleTable->QuotaProcess != NULL) { 01944 01945 PsChargePoolQuota( HandleTable->QuotaProcess, 01946 PagedPool, 01947 (2 * sizeof(HANDLE_TABLE_ENTRY) * 256) ); 01948 01949 LowTableQuotaCharged = TRUE; 01950 } 01951 01952 // 01953 // Now to guard against reordering of code we need to do 01954 // something to ensure that the last zero memory really has 01955 // happened before setting up the rest of our work. An 01956 // interlocked exchance will do the trick. 01957 // 01958 01959 InterlockedExchangePointer( (PVOID *) NewLowLevel, NULL ); 01960 01961 // 01962 // Now if we've allocated a new mid level buffer we need to 01963 // update the pointers from our handle table. The if's are 01964 // needed when we get near the end of the table 01965 // 01966 01967 if (NewMidLevel != NULL) { 01968 01969 if (i+0 < 256) { HandleTable->Table[i+0] = (PVOID)(NewMidLevel + 0 * sizeof(ULONG_PTR) * 256); } 01970 if (i+1 < 256) { HandleTable->Table[i+1] = (PVOID)(NewMidLevel + 1 * sizeof(ULONG_PTR) * 256); } 01971 if (i+2 < 256) { HandleTable->Table[i+2] = (PVOID)(NewMidLevel + 2 * sizeof(ULONG_PTR) * 256); } 01972 if (i+3 < 256) { HandleTable->Table[i+3] = (PVOID)(NewMidLevel + 3 * sizeof(ULONG_PTR) * 256); } 01973 } 01974 01975 // 01976 // Now fix up the low level buffers. We are actually guaranteed 01977 // that the first buffer will fit, because j starts out from a 01978 // byte. 01979 // 01980 01981 { HandleTable->Table[i][j+0] = (PVOID)(NewLowLevel + 0 * sizeof(HANDLE_TABLE_ENTRY) * 256); } 01982 if (j+1 < 256) { HandleTable->Table[i][j+1] = (PVOID)(NewLowLevel + 1 * sizeof(HANDLE_TABLE_ENTRY) * 256); } 01983 01984 // 01985 // Now add the new entries to the free list. To do this we 01986 // chain the new free entries together. We are guaranteed to 01987 // have at least one new buffer. The second buffer we need 01988 // to check for. 01989 // 01990 // Start by starting our stack top 01991 // 01992 01993 HandleTable->FirstFreeTableEntry = HandleTable->NextIndexNeedingPool; 01994 01995 // 01996 // Do the guaranteed first buffer 01997 // 01998 01999 for (k = 0; k < 256; k += 1) { 02000 02001 HandleTable->Table[i][j+0][k].NextFreeTableEntry = HandleTable->NextIndexNeedingPool + k + 1; 02002 } 02003 02004 // 02005 // Check if there is a second buffer 02006 // 02007 02008 if ((j+1 < 256) && (HandleTable->Table[i][j+1] != NULL)) { 02009 02010 // 02011 // Do the second buffer 02012 // 02013 02014 for (k = 0; k < 255; k += 1) { 02015 02016 HandleTable->Table[i][j+1][k].NextFreeTableEntry = HandleTable->NextIndexNeedingPool + k + 1 + 256; 02017 } 02018 02019 // 02020 // Fixup the last entry and update the next index needing 02021 // pool. 02022 // 02023 02024 HandleTable->Table[i][j+1][255].NextFreeTableEntry = -1; 02025 02026 HandleTable->NextIndexNeedingPool += 512; 02027 02028 } else { 02029 02030 // 02031 // Fixup the last entry and update the next index needing 02032 // pool. 02033 // 02034 02035 HandleTable->Table[i][j+0][255].NextFreeTableEntry = -1; 02036 02037 HandleTable->NextIndexNeedingPool += 256; 02038 } 02039 02040 } except (EXCEPTION_EXECUTE_HANDLER) { 02041 02042 // 02043 // We only execute this exception handler if the pool allocation 02044 // raises or if the quota request fails. In these cases we need 02045 // to cleanup after ourselves and return null to our caller 02046 // 02047 02048 if (NewMidLevel != NULL) { 02049 02050 ExFreePool( NewMidLevel ); 02051 02052 if (MidTableQuotaCharged) { 02053 02054 PsReturnPoolQuota( HandleTable->QuotaProcess, 02055 PagedPool, 02056 (4 * sizeof(ULONG_PTR) * 256) ); 02057 } 02058 } 02059 02060 if (NewLowLevel != NULL) { 02061 02062 ExFreePool( NewLowLevel ); 02063 02064 if (LowTableQuotaCharged) { 02065 02066 PsReturnPoolQuota( HandleTable->QuotaProcess, 02067 PagedPool, 02068 (2 * sizeof(HANDLE_TABLE_ENTRY) * 256) ); 02069 } 02070 } 02071 02072 Handle->Index = 0; 02073 02074 return NULL; 02075 } 02076 } 02077 02078 // 02079 // At this point the free stack has some elements in it. So we 02080 // only need to pop off the first entry. 02081 // 02082 // Get the top of the stack, both the index and table entry 02083 // 02084 02085 Handle->Index = HandleTable->FirstFreeTableEntry; 02086 02087 HandleTableEntry = ExpLookupHandleTableEntry( HandleTable, 02088 *Handle ); 02089 02090 // 02091 // Do the pop 02092 // 02093 02094 HandleTable->FirstFreeTableEntry = HandleTableEntry->NextFreeTableEntry; 02095 02096 // 02097 // Zero out the new table entry 02098 // 02099 02100 RtlZeroMemory( HandleTableEntry, sizeof(HANDLE_TABLE_ENTRY )); 02101 02102 // 02103 // Update our bookkeeping counters and return the entry to our 02104 // caller 02105 // 02106 02107 HandleTable->HandleCount += 1; 02108 02109 return HandleTableEntry; 02110 }

VOID ExpFreeHandleTable IN PHANDLE_TABLE  HandleTable  ) 
 

Definition at line 1667 of file ex/handle.c.

References ExDeleteResource, ExFreePool(), NonPagedPool, NULL, PAGED_CODE, PagedPool, and PsReturnPoolQuota().

Referenced by ExDestroyHandleTable(), and ExDupHandleTable().

01673 : 01674 01675 This worker routine tearsdown and frees the specified handle table. 01676 01677 Arguments: 01678 01679 HandleTable - Supplies the handle table being freed 01680 01681 Return Value: 01682 01683 None. 01684 01685 --*/ 01686 01687 { 01688 PEPROCESS Process; 01689 ULONG i,j; 01690 01691 PAGED_CODE(); 01692 01693 Process = HandleTable->QuotaProcess; 01694 01695 // 01696 // First free the lock for the local handle table 01697 // 01698 01699 ExDeleteResource( &HandleTable->HandleTableLock ); 01700 01701 // 01702 // We first return all of the additional exhandle table entry buffers 01703 // that we allocated. Note that each pool buffer we allocated is for 01704 // two subindex buffers in the table, and note also that we have to 01705 // start a little funny to compensate for the first that really contains 01706 // the top level and first mid level, and first entry buffer 01707 // 01708 // Take care of the special case where the [0][0] index is really 01709 // allocated up front, and we only need to examine [0][1] to see if 01710 // anything special needs to be deallocated, followed by [0][3], [0][5], 01711 // up to and including [0][255] 01712 // 01713 01714 for (j = 1; j < 256; j += 2) { 01715 01716 if (HandleTable->Table[0][j] == NULL) { 01717 01718 break; 01719 } 01720 01721 ExFreePool( HandleTable->Table[0][j] ); 01722 01723 if (Process != NULL) { 01724 01725 PsReturnPoolQuota( Process, 01726 PagedPool, 01727 2 * sizeof(HANDLE_TABLE_ENTRY) * 256 ); 01728 } 01729 } 01730 01731 // 01732 // Now that we've handle the special case we can do the rest of the table 01733 // starting with index [1][0], [1][2], ... [1][254], [2][0], [2][2] ... 01734 // up to and including [255][254] 01735 // 01736 01737 for (i = 1; i < 256; i += 1) { 01738 01739 if (HandleTable->Table[i] == NULL) { 01740 01741 break; 01742 } 01743 01744 for (j = 0; j < 256; j += 2) { 01745 01746 if (HandleTable->Table[i][j] == NULL) { 01747 01748 break; 01749 } 01750 01751 ExFreePool( HandleTable->Table[i][j] ); 01752 01753 if (Process != NULL) { 01754 01755 PsReturnPoolQuota( Process, 01756 PagedPool, 01757 2 * sizeof(HANDLE_TABLE_ENTRY) * 256 ); 01758 } 01759 } 01760 } 01761 01762 // 01763 // Now that we've deallocated the handle table entry buffer we can 01764 // deallocate the additional mid level buffers. Note that that these 01765 // start at index [0][1] and were allocated four a time from pool. 01766 // 01767 01768 for (i = 1; i < 256; i += 4) { 01769 01770 if (HandleTable->Table[i] == NULL) { 01771 01772 break; 01773 } 01774 01775 ExFreePool( HandleTable->Table[i] ); 01776 01777 if (Process != NULL) { 01778 01779 PsReturnPoolQuota( Process, 01780 PagedPool, 01781 4 * sizeof(ULONG_PTR) * 256 ); 01782 } 01783 } 01784 01785 // 01786 // Now deallocate the original handle table buffer used to store 01787 // the top level, first mid level, and first table entry buffer 01788 // 01789 01790 ExFreePool( HandleTable->Table ); 01791 01792 if (Process != NULL) { 01793 01794 PsReturnPoolQuota( Process, 01795 PagedPool, 01796 (2 * sizeof(ULONG_PTR) * 256) + (sizeof(HANDLE_TABLE_ENTRY) * 256) ); 01797 } 01798 01799 // 01800 // Finally deallocate the handle table itself 01801 // 01802 01803 ExFreePool( HandleTable ); 01804 01805 if (Process != NULL) { 01806 01807 PsReturnPoolQuota( Process, 01808 NonPagedPool, 01809 sizeof(HANDLE_TABLE) ); 01810 } 01811 01812 // 01813 // And return to our caller 01814 // 01815 01816 return; 01817 }

VOID ExpFreeHandleTableEntry IN PHANDLE_TABLE  HandleTable,
IN EXHANDLE  Handle,
IN PHANDLE_TABLE_ENTRY  HandleTableEntry
 

Definition at line 2127 of file ex/handle.c.

References Handle, and PAGED_CODE.

Referenced by ExDestroyHandle(), and ExDupHandleTable().

02136 : 02137 02138 This worker routine returns the specified handle table entry to the free 02139 list for the handle table. 02140 02141 Note: The caller must have already locked the handle table 02142 02143 Arguments: 02144 02145 HandleTable - Supplies the parent handle table being modified 02146 02147 Handle - Supplies the handle of the entry being freed 02148 02149 HandleTableEntry - Supplies the table entry being freed 02150 02151 Return Value: 02152 02153 None. 02154 02155 --*/ 02156 02157 { 02158 PAGED_CODE(); 02159 02160 // 02161 // A free is simply a push onto the free table entry stack, or in the 02162 // debug case we'll sometimes just float the entry to catch apps who 02163 // reuse a recycled handle value. 02164 // 02165 02166 #if DBG 02167 if (ExReuseHandles) { 02168 #endif //DBG 02169 02170 HandleTableEntry->NextFreeTableEntry = HandleTable->FirstFreeTableEntry; 02171 HandleTable->FirstFreeTableEntry = Handle.Index; 02172 02173 #if DBG 02174 } else { 02175 02176 HandleTableEntry->NextFreeTableEntry = 0; 02177 } 02178 #endif //DBG 02179 02180 // 02181 // And then update our handle count before returning to our caller 02182 // 02183 02184 HandleTable->HandleCount -= 1; 02185 02186 return; 02187 }

PHANDLE_TABLE_ENTRY ExpLookupHandleTableEntry IN PHANDLE_TABLE  HandleTable,
IN EXHANDLE  Handle
 

Definition at line 2195 of file ex/handle.c.

References Handle, NULL, and PAGED_CODE.

Referenced by ExChangeHandle(), ExDestroyHandle(), ExDestroyHandleTable(), ExDupHandleTable(), ExEnumHandleTable(), ExMapHandleToPointer(), ExpAllocateHandleTableEntry(), and ExSnapShotHandleTables().

02202 : 02203 02204 This routine looks up and returns the table entry for the 02205 specified handle value. 02206 02207 Arguments: 02208 02209 HandleTable - Supplies the handle table being queried 02210 02211 Handle - Supplies the handle value being queried 02212 02213 Return Value: 02214 02215 Returns a pointer to the corresponding table entry for the input 02216 handle. Or NULL if the handle value is invalid (i.e., too large 02217 for the tables current allocation. 02218 02219 --*/ 02220 02221 { 02222 ULONG i,j,k,l; 02223 02224 PAGED_CODE(); 02225 02226 // 02227 // Decode the handle index into its separate table indicies 02228 // 02229 02230 l = (Handle.Index >> 24) & 255; 02231 i = (Handle.Index >> 16) & 255; 02232 j = (Handle.Index >> 8) & 255; 02233 k = (Handle.Index) & 255; 02234 02235 // 02236 // The last bits should be 0 into a valid handle. If a function calls 02237 // ExpLookupHandleTableEntry for a kernel handle, it should decode the handle 02238 // before. 02239 // 02240 02241 if ( l != 0 ) { 02242 02243 // 02244 // Invalid handle. Return a NULL table entry. 02245 // 02246 02247 return NULL; 02248 } 02249 02250 // 02251 // Check that the top level table is present 02252 // 02253 02254 if (HandleTable->Table[i] == NULL) { 02255 02256 return NULL; 02257 } 02258 02259 // 02260 // Check that the mid level table is present 02261 // 02262 02263 if (HandleTable->Table[i][j] == NULL) { 02264 02265 return NULL; 02266 } 02267 02268 // 02269 // Return a pointer to the table entry 02270 // 02271 02272 return &(HandleTable->Table[i][j][k]); 02273 } }

NTKERNELAPI VOID ExRemoveHandleTable IN PHANDLE_TABLE  HandleTable  ) 
 

Definition at line 501 of file ex/handle.c.

References ExAcquireResourceExclusive, ExReleaseResource, HandleTableListLock, KeEnterCriticalRegion, KeLeaveCriticalRegion, PAGED_CODE, and TRUE.

Referenced by ExDestroyHandleTable(), PspInitPhase0(), and RtlpInitializeHandleTableForAtomTable().

00507 : 00508 00509 This function removes the specified exhandle table from the list of 00510 exhandle tables. Used by PS and ATOM packages to make sure their handle 00511 tables are not in the list enumerated by the ExSnapShotHandleTables 00512 routine and the !handle debugger extension. 00513 00514 Arguments: 00515 00516 HandleTable - Supplies a pointer to a handle table 00517 00518 Return Value: 00519 00520 None. 00521 00522 --*/ 00523 00524 { 00525 PAGED_CODE(); 00526 00527 // 00528 // First, acquire the global handle table lock 00529 // 00530 00531 KeEnterCriticalRegion(); 00532 ExAcquireResourceExclusive( &HandleTableListLock, TRUE ); 00533 00534 // 00535 // Remove the handle table from the handle table list. This routine is 00536 // written so that multiple calls to remove a handle table will not 00537 // corrupt the system. 00538 // 00539 00540 if (!IsListEmpty( &HandleTable->HandleTableList )) { 00541 00542 RemoveEntryList( &HandleTable->HandleTableList ); 00543 00544 InitializeListHead( &HandleTable->HandleTableList ); 00545 } 00546 00547 // 00548 // Now release the global lock and return to our caller 00549 // 00550 00551 ExReleaseResource( &HandleTableListLock ); 00552 KeLeaveCriticalRegion(); 00553 00554 return; 00555 }

NTKERNELAPI NTSTATUS ExSnapShotHandleTables IN PEX_SNAPSHOT_HANDLE_ENTRY  SnapShotHandleEntry,
IN OUT PSYSTEM_HANDLE_INFORMATION  HandleInformation,
IN ULONG  Length,
IN OUT PULONG  RequiredLength
 

Definition at line 984 of file ex/handle.c.

References ExAcquireResourceExclusive, ExLockHandleTableEntry(), ExLockHandleTableExclusive(), ExpLookupHandleTableEntry(), ExReleaseResource, ExUnlockHandleTableEntry(), ExUnlockHandleTableExclusive(), Handle, HandleTableListHead, HandleTableListLock, KeEnterCriticalRegion, KeLeaveCriticalRegion, NTSTATUS(), NULL, _HANDLE_TABLE_ENTRY::Object, PAGED_CODE, Status, TRUE, and _HANDLE_TABLE::UniqueProcessId.

Referenced by ObGetHandleInformation().

00993 : 00994 00995 This function visits and invokes the specified callback for every valid 00996 handle that it can find off of the handle table. 00997 00998 Arguments: 00999 01000 SnapShotHandleEntry - Supplies a pointer to a function to call for 01001 each valid handle we encounter. 01002 01003 HandleInformation - Supplies a handle information structure to 01004 be filled in for each handle table we encounter. This routine 01005 fills in the handle count, but relies on a callback to fill in 01006 entry info fields. 01007 01008 Length - Supplies a parameter for the callback. In reality this is 01009 the total size, in bytes, of the Handle Information buffer. 01010 01011 RequiredLength - Supplies a parameter for the callback. In reality 01012 this is a final size in bytes used to store the requested 01013 information. 01014 01015 Return Value: 01016 01017 The last return status of the callback 01018 01019 --*/ 01020 01021 { 01022 NTSTATUS Status; 01023 PSYSTEM_HANDLE_TABLE_ENTRY_INFO HandleEntryInfo; 01024 PLIST_ENTRY NextEntry; 01025 PHANDLE_TABLE HandleTable; 01026 EXHANDLE Handle; 01027 PHANDLE_TABLE_ENTRY HandleTableEntry; 01028 01029 PAGED_CODE(); 01030 01031 // 01032 // Lock the handle table list exclusive and traverse the list of handle 01033 // tables. 01034 // 01035 01036 Status = STATUS_SUCCESS; 01037 01038 KeEnterCriticalRegion(); 01039 ExAcquireResourceExclusive( &HandleTableListLock, TRUE ); 01040 01041 try { 01042 01043 // 01044 // Setup the output buffer pointer that the callback will maintain 01045 // 01046 01047 HandleEntryInfo = &HandleInformation->Handles[0]; 01048 01049 // 01050 // Zero out the handle count 01051 // 01052 01053 HandleInformation->NumberOfHandles = 0; 01054 01055 // 01056 // Iterate through all the handle tables in the system. 01057 // 01058 01059 for (NextEntry = HandleTableListHead.Flink; 01060 NextEntry != &HandleTableListHead; 01061 NextEntry = NextEntry->Flink) { 01062 01063 // 01064 // Get the address of the next handle table, lock the handle 01065 // table exclusive, and scan the list of handle entries. 01066 // 01067 01068 HandleTable = CONTAINING_RECORD( NextEntry, 01069 HANDLE_TABLE, 01070 HandleTableList ); 01071 01072 ExLockHandleTableExclusive( HandleTable ); 01073 01074 try { 01075 01076 // Iterate through the handle table and for each handle that 01077 // is allocated we'll invoke the call back. Note that this 01078 // loop exits when we get a null handle table entry. We know 01079 // there will be no more possible entries after the first null 01080 // one is encountered because we allocate memory of the 01081 // handles in a dense fashion 01082 // 01083 01084 for (Handle.Index = 0, Handle.TagBits = 0; 01085 (HandleTableEntry = ExpLookupHandleTableEntry( HandleTable, Handle )) != NULL; 01086 Handle.Index += 1) { 01087 01088 // 01089 // Only do the callback if the entry is not free 01090 // 01091 01092 if (HandleTableEntry->Object != NULL) { 01093 01094 // 01095 // Increment the handle count information in the 01096 // information buffer 01097 // 01098 01099 HandleInformation->NumberOfHandles += 1; 01100 01101 // 01102 // Lock the handle table entry because we're about to 01103 // give it to the callback function, then release the 01104 // entry right after the call back. 01105 // 01106 01107 if (ExLockHandleTableEntry( HandleTable, HandleTableEntry )) { 01108 01109 try { 01110 01111 Status = (*SnapShotHandleEntry)( &HandleEntryInfo, 01112 HandleTable->UniqueProcessId, 01113 HandleTableEntry, 01114 Handle.GenericHandleOverlay, 01115 Length, 01116 RequiredLength ); 01117 01118 } finally { 01119 01120 ExUnlockHandleTableEntry( HandleTable, HandleTableEntry ); 01121 } 01122 } 01123 } 01124 } 01125 01126 } finally { 01127 01128 ExUnlockHandleTableExclusive( HandleTable ); 01129 } 01130 } 01131 01132 } finally { 01133 01134 ExReleaseResource( &HandleTableListLock ); 01135 KeLeaveCriticalRegion(); 01136 } 01137 01138 return Status; 01139 }

NTKERNELAPI VOID ExUnlockHandleTableEntry PHANDLE_TABLE  HandleTable,
PHANDLE_TABLE_ENTRY  HandleTableEntry
 

Definition at line 336 of file ex/handle.c.

References EVENT_INCREMENT, EXHANDLE_TABLE_ENTRY_LOCK_BIT, FALSE, _HANDLE_TABLE::HandleContentionEvent, _KEVENT::Header, KeBugCheckEx(), KePulseEvent(), _HANDLE_TABLE_ENTRY::Object, PAGED_CODE, and _DISPATCHER_HEADER::WaitListHead.

Referenced by ExChangeHandle(), ExCreateHandle(), ExDupHandleTable(), ExEnumHandleTable(), ExSnapShotHandleTables(), NtClose(), NtWaitForMultipleObjects(), ObQueryObjectAuditingByHandle(), ObReferenceObjectByHandle(), PsLookupProcessByProcessId(), PsLookupProcessThreadByCid(), PsLookupThreadByThreadId(), and RtlpAtomMapAtomToHandleEntry().

00343 : 00344 00345 This routine unlocks the specified handle table entry. After the entry is 00346 unlocked the sign bit will be clear. 00347 00348 Arguments: 00349 00350 HandleTable - Supplies the handle table containing the entry being unlocked. 00351 00352 HandleTableEntry - Supplies the handle table entry being unlocked. 00353 00354 Return Value: 00355 00356 None. 00357 00358 --*/ 00359 00360 { 00361 LONG_PTR NewValue; 00362 LONG_PTR CurrentValue; 00363 00364 PAGED_CODE(); 00365 00366 // 00367 // This routine does not need to loop and attempt the unlock opeation more 00368 // than once because by defintion the caller has the entry already locked 00369 // and no one can be changing the value without the lock. 00370 // 00371 // So we'll read in the current value, check that the entry is really 00372 // locked, clear the lock bit and make sure the compare exchange worked. 00373 // 00374 00375 NewValue = CurrentValue = *((volatile LONG_PTR *)&HandleTableEntry->Object); 00376 00377 if (CurrentValue >= 0) { 00378 00379 KeBugCheckEx( BAD_EXHANDLE, __LINE__, (LONG_PTR)HandleTableEntry, NewValue, CurrentValue ); 00380 } 00381 00382 NewValue &= ~EXHANDLE_TABLE_ENTRY_LOCK_BIT; 00383 00384 if ((LONG_PTR)(InterlockedCompareExchangePointer( &HandleTableEntry->Object, 00385 (PVOID)NewValue, 00386 (PVOID)CurrentValue )) != CurrentValue) { 00387 00388 KeBugCheckEx( BAD_EXHANDLE, __LINE__, (LONG_PTR)HandleTableEntry, NewValue, CurrentValue ); 00389 } 00390 00391 // 00392 // Now that we've unlocked the event we'll see if there are any waiters 00393 // for handle table entries in this table. If there are any waiters 00394 // we'll wake them up and let them try for their lock again. 00395 // 00396 // Note that this will wake up all the waiters for all locks in a given 00397 // handle table. Each waiter also has a short time out so the worse 00398 // that can happen is that we might wake someone too early. It can also 00399 // be that no one is waiting for this exact lock, or the one waiting for 00400 // it has already gone off, but these are all benign. 00401 // 00402 // **** Note that we're testing for a non empty event header wait list 00403 // head. This is sort of behind the back and a better design 00404 // would get a macro from ke.h to do the test, but this will 00405 // suffice for now. This is actually an unsafe test in that it 00406 // might return the wrong answer, but even then we are willing to 00407 // live with it because any waiters will wake up in 10ms anyway and 00408 // any extra call to pulse the event without waiters is benign. 00409 // 00410 00411 if (!IsListEmpty( &HandleTable->HandleContentionEvent.Header.WaitListHead )) { 00412 00413 KePulseEvent( &HandleTable->HandleContentionEvent, EVENT_INCREMENT, FALSE ); 00414 } 00415 00416 return; 00417 }

NTKERNELAPI VOID ExUnlockHandleTableExclusive PHANDLE_TABLE  HandleTable  ) 
 

Definition at line 209 of file ex/handle.c.

References ExReleaseResource, _HANDLE_TABLE::HandleTableLock, PAGED_CODE, and VOID().

Referenced by ExCreateHandle(), ExDestroyHandle(), and ExSnapShotHandleTables().

00215 : 00216 00217 This routine unlocks the specified handle table from exclusive access. 00218 00219 Arguments: 00220 00221 HandleTable - Supplies the handle table being unlocked. 00222 00223 Return Value: 00224 00225 None. 00226 00227 --*/ 00228 00229 { 00230 PAGED_CODE(); 00231 00232 (VOID)ExReleaseResource( &HandleTable->HandleTableLock ); 00233 00234 return; 00235 }

NTKERNELAPI VOID ExUnlockHandleTableShared PHANDLE_TABLE  HandleTable  ) 
 

Definition at line 178 of file ex/handle.c.

References ExReleaseResource, _HANDLE_TABLE::HandleTableLock, PAGED_CODE, and VOID().

Referenced by ExDupHandleTable(), and ExEnumHandleTable().

00184 : 00185 00186 This routine unlocks the specified handle table from shared access. 00187 00188 Arguments: 00189 00190 HandleTable - Supplies the handle table being unlocked. 00191 00192 Return Value: 00193 00194 None. 00195 00196 --*/ 00197 00198 { 00199 PAGED_CODE(); 00200 00201 (VOID)ExReleaseResource( &HandleTable->HandleTableLock ); 00202 00203 return; 00204 }


Variable Documentation

LARGE_INTEGER Ex10Milliseconds = {(ULONG)(-10 * 1000 * 10), -1}
 

Definition at line 51 of file ex/handle.c.

Referenced by ExLockHandleTableEntry().

LIST_ENTRY HandleTableListHead
 

Definition at line 37 of file ex/handle.c.

Referenced by ExInitializeHandleTablePackage(), ExpAllocateHandleTable(), and ExSnapShotHandleTables().

ERESOURCE HandleTableListLock
 

Definition at line 36 of file ex/handle.c.

Referenced by ExInitializeHandleTablePackage(), ExpAllocateHandleTable(), ExRemoveHandleTable(), and ExSnapShotHandleTables().


Generated on Sat May 15 19:44:01 2004 for test by doxygen 1.3.7