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

ex.h

Go to the documentation of this file.
00001 /*++ BUILD Version: 0007 // Increment this if a change has global effects 00002 00003 Copyright (c) 1989 Microsoft Corporation 00004 00005 Module Name: 00006 00007 ex.h 00008 00009 Abstract: 00010 00011 Public executive data structures and procedure prototypes. 00012 00013 Author: 00014 00015 Mark Lucovsky (markl) 23-Feb-1989 00016 00017 Revision History: 00018 00019 --*/ 00020 00021 #ifndef _EX_ 00022 #define _EX_ 00023 00024 // 00025 // Define caller count hash table structures and function prototypes. 00026 // 00027 00028 #define CALL_HASH_TABLE_SIZE 64 00029 00030 typedef struct _CALL_HASH_ENTRY { 00031 LIST_ENTRY ListEntry; 00032 PVOID CallersAddress; 00033 PVOID CallersCaller; 00034 ULONG CallCount; 00035 } CALL_HASH_ENTRY, *PCALL_HASH_ENTRY; 00036 00037 typedef struct _CALL_PERFORMANCE_DATA { 00038 KSPIN_LOCK SpinLock; 00039 LIST_ENTRY HashTable[CALL_HASH_TABLE_SIZE]; 00040 } CALL_PERFORMANCE_DATA, *PCALL_PERFORMANCE_DATA; 00041 00042 VOID 00043 ExInitializeCallData( 00044 IN PCALL_PERFORMANCE_DATA CallData 00045 ); 00046 00047 VOID 00048 ExRecordCallerInHashTable( 00049 IN PCALL_PERFORMANCE_DATA CallData, 00050 IN PVOID CallersAddress, 00051 IN PVOID CallersCaller 00052 ); 00053 00054 #define RECORD_CALL_DATA(Table) \ 00055 { \ 00056 PVOID CallersAddress; \ 00057 PVOID CallersCaller; \ 00058 RtlGetCallersAddress(&CallersAddress, &CallersCaller); \ 00059 ExRecordCallerInHashTable((Table), CallersAddress, CallersCaller); \ 00060 } 00061 00062 // 00063 // Define executive event pair object structure. 00064 // 00065 00066 typedef struct _EEVENT_PAIR { 00067 KEVENT_PAIR KernelEventPair; 00068 } EEVENT_PAIR, *PEEVENT_PAIR; 00069 00070 // 00071 // empty struct def so we can forward reference ETHREAD 00072 // 00073 00074 struct _ETHREAD; 00075 00076 // 00077 // System Initialization procedure for EX subcomponent of NTOS (in exinit.c) 00078 // 00079 00080 NTKERNELAPI 00081 BOOLEAN 00082 ExInitSystem( 00083 VOID 00084 ); 00085 00086 NTKERNELAPI 00087 VOID 00088 ExInitSystemPhase2( 00089 VOID 00090 ); 00091 00092 VOID 00093 ExInitPoolLookasidePointers ( 00094 VOID 00095 ); 00096 00097 ULONG 00098 ExComputeTickCountMultiplier ( 00099 IN ULONG TimeIncrement 00100 ); 00101 00102 // begin_ntddk begin_wdm begin_nthal begin_ntifs begin_ntndis 00103 // 00104 // Pool Allocation routines (in pool.c) 00105 // 00106 00107 typedef enum _POOL_TYPE { 00108 NonPagedPool, 00109 PagedPool, 00110 NonPagedPoolMustSucceed, 00111 DontUseThisType, 00112 NonPagedPoolCacheAligned, 00113 PagedPoolCacheAligned, 00114 NonPagedPoolCacheAlignedMustS, 00115 MaxPoolType 00116 00117 // end_wdm 00118 , 00119 // 00120 // Note these per session types are carefully chosen so that the appropriate 00121 // masking still applies as well as MaxPoolType above. 00122 // 00123 00124 NonPagedPoolSession = 32, 00125 PagedPoolSession = NonPagedPoolSession + 1, 00126 NonPagedPoolMustSucceedSession = PagedPoolSession + 1, 00127 DontUseThisTypeSession = NonPagedPoolMustSucceedSession + 1, 00128 NonPagedPoolCacheAlignedSession = DontUseThisTypeSession + 1, 00129 PagedPoolCacheAlignedSession = NonPagedPoolCacheAlignedSession + 1, 00130 NonPagedPoolCacheAlignedMustSSession = PagedPoolCacheAlignedSession + 1, 00131 00132 // begin_wdm 00133 00134 } POOL_TYPE; 00135 00136 // end_ntddk end_wdm end_nthal end_ntifs end_ntndis 00137 00138 // 00139 // The following two definitions control the raising of exceptions on quota 00140 // and allocation failures. 00141 // 00142 00143 #define POOL_QUOTA_FAIL_INSTEAD_OF_RAISE 8 00144 #define POOL_RAISE_IF_ALLOCATION_FAILURE 16 // ntifs 00145 00146 VOID 00147 InitializePool( 00148 IN POOL_TYPE PoolType, 00149 IN ULONG Threshold 00150 ); 00151 00152 // 00153 // These routines are private to the pool manager and the memory manager. 00154 // 00155 00156 VOID 00157 ExInsertPoolTag ( 00158 ULONG Tag, 00159 PVOID Va, 00160 SIZE_T NumberOfBytes, 00161 POOL_TYPE PoolType 00162 ); 00163 00164 VOID 00165 ExAllocatePoolSanityChecks( 00166 IN POOL_TYPE PoolType, 00167 IN SIZE_T NumberOfBytes 00168 ); 00169 00170 VOID 00171 ExFreePoolSanityChecks( 00172 IN PVOID P 00173 ); 00174 00175 // begin_ntddk begin_nthal begin_ntifs begin_wdm 00176 00177 NTKERNELAPI 00178 PVOID 00179 ExAllocatePool( 00180 IN POOL_TYPE PoolType, 00181 IN SIZE_T NumberOfBytes 00182 ); 00183 00184 NTKERNELAPI 00185 PVOID 00186 ExAllocatePoolWithQuota( 00187 IN POOL_TYPE PoolType, 00188 IN SIZE_T NumberOfBytes 00189 ); 00190 00191 NTKERNELAPI 00192 PVOID 00193 NTAPI 00194 ExAllocatePoolWithTag( 00195 IN POOL_TYPE PoolType, 00196 IN SIZE_T NumberOfBytes, 00197 IN ULONG Tag 00198 ); 00199 00200 // end_wdm 00201 00202 // 00203 // _EX_POOL_PRIORITY_ provides a method for the system to handle requests 00204 // intelligently in low resource conditions. 00205 // 00206 // LowPoolPriority should be used when it is acceptable to the driver for the 00207 // mapping request to fail if the system is low on resources. An example of 00208 // this could be for a non-critical network connection where the driver can 00209 // handle the failure case when system resources are close to being depleted. 00210 // 00211 // NormalPoolPriority should be used when it is acceptable to the driver for the 00212 // mapping request to fail if the system is very low on resources. An example 00213 // of this could be for a non-critical local filesystem request. 00214 // 00215 // HighPoolPriority should be used when it is unacceptable to the driver for the 00216 // mapping request to fail unless the system is completely out of resources. 00217 // An example of this would be the paging file path in a driver. 00218 // 00219 // SpecialPool can be specified to bound the allocation at a page end (or 00220 // beginning). This should only be done on systems being debugged as the 00221 // memory cost is expensive. 00222 // 00223 // N.B. These values are very carefully chosen so that the pool allocation 00224 // code can quickly crack the priority request. 00225 // 00226 00227 typedef enum _EX_POOL_PRIORITY { 00228 LowPoolPriority, 00229 LowPoolPrioritySpecialPoolOverrun = 8, 00230 LowPoolPrioritySpecialPoolUnderrun = 9, 00231 NormalPoolPriority = 16, 00232 NormalPoolPrioritySpecialPoolOverrun = 24, 00233 NormalPoolPrioritySpecialPoolUnderrun = 25, 00234 HighPoolPriority = 32, 00235 HighPoolPrioritySpecialPoolOverrun = 40, 00236 HighPoolPrioritySpecialPoolUnderrun = 41 00237 00238 } EX_POOL_PRIORITY; 00239 00240 NTKERNELAPI 00241 PVOID 00242 NTAPI 00243 ExAllocatePoolWithTagPriority( 00244 IN POOL_TYPE PoolType, 00245 IN SIZE_T NumberOfBytes, 00246 IN ULONG Tag, 00247 IN EX_POOL_PRIORITY Priority 00248 ); 00249 00250 // begin_wdm 00251 00252 #ifndef POOL_TAGGING 00253 #define ExAllocatePoolWithTag(a,b,c) ExAllocatePool(a,b) 00254 #endif //POOL_TAGGING 00255 00256 NTKERNELAPI 00257 PVOID 00258 ExAllocatePoolWithQuotaTag( 00259 IN POOL_TYPE PoolType, 00260 IN SIZE_T NumberOfBytes, 00261 IN ULONG Tag 00262 ); 00263 00264 #ifndef POOL_TAGGING 00265 #define ExAllocatePoolWithQuotaTag(a,b,c) ExAllocatePoolWithQuota(a,b) 00266 #endif //POOL_TAGGING 00267 00268 NTKERNELAPI 00269 VOID 00270 NTAPI 00271 ExFreePool( 00272 IN PVOID P 00273 ); 00274 00275 // end_ntddk end_wdm end_nthal end_ntifs 00276 00277 // 00278 // If high order bit in Pool tag is set, then must use ExFreePoolWithTag to free 00279 // 00280 00281 #define PROTECTED_POOL 0x80000000 00282 00283 NTKERNELAPI 00284 VOID 00285 ExFreePoolWithTag( 00286 IN PVOID P, 00287 IN ULONG Tag 00288 ); 00289 00290 #ifndef POOL_TAGGING 00291 #define ExFreePoolWithTag(a,b) ExFreePool(a) 00292 #endif //POOL_TAGGING 00293 00294 00295 NTKERNELAPI 00296 KIRQL 00297 ExLockPool( 00298 IN POOL_TYPE PoolType 00299 ); 00300 00301 NTKERNELAPI 00302 VOID 00303 ExUnlockPool( 00304 IN POOL_TYPE PoolType, 00305 IN KIRQL LockHandle 00306 ); 00307 00308 NTKERNELAPI // ntifs 00309 ULONG // ntifs 00310 ExQueryPoolBlockSize ( // ntifs 00311 IN PVOID PoolBlock, // ntifs 00312 OUT PBOOLEAN QuotaCharged // ntifs 00313 ); // ntifs 00314 00315 NTKERNELAPI 00316 VOID 00317 ExQueryPoolUsage( 00318 OUT PULONG PagedPoolPages, 00319 OUT PULONG NonPagedPoolPages, 00320 OUT PULONG PagedPoolAllocs, 00321 OUT PULONG PagedPoolFrees, 00322 OUT PULONG PagedPoolLookasideHits, 00323 OUT PULONG NonPagedPoolAllocs, 00324 OUT PULONG NonPagedPoolFrees, 00325 OUT PULONG NonPagedPoolLookasideHits 00326 ); 00327 00328 VOID 00329 ExReturnPoolQuota ( 00330 IN PVOID P 00331 ); 00332 00333 #if DBG || (i386 && !FPO) 00334 NTKERNELAPI 00335 NTSTATUS 00336 ExSnapShotPool( 00337 IN POOL_TYPE PoolType, 00338 IN PSYSTEM_POOL_INFORMATION PoolInformation, 00339 IN ULONG Length, 00340 OUT PULONG ReturnLength OPTIONAL 00341 ); 00342 #endif // DBG || (i386 && !FPO) 00343 00344 00345 // begin_ntifs begin_ntddk begin_wdm begin_nthal 00346 // 00347 // Routines to support fast mutexes. 00348 // 00349 00350 typedef struct _FAST_MUTEX { 00351 LONG Count; 00352 PKTHREAD Owner; 00353 ULONG Contention; 00354 KEVENT Event; 00355 ULONG OldIrql; 00356 } FAST_MUTEX, *PFAST_MUTEX; 00357 00358 #if DBG 00359 #define ExInitializeFastMutex(_FastMutex) \ 00360 (_FastMutex)->Count = 1; \ 00361 (_FastMutex)->Owner = NULL; \ 00362 (_FastMutex)->Contention = 0; \ 00363 KeInitializeEvent(&(_FastMutex)->Event, \ 00364 SynchronizationEvent, \ 00365 FALSE); 00366 #else 00367 #define ExInitializeFastMutex(_FastMutex) \ 00368 (_FastMutex)->Count = 1; \ 00369 (_FastMutex)->Contention = 0; \ 00370 KeInitializeEvent(&(_FastMutex)->Event, \ 00371 SynchronizationEvent, \ 00372 FALSE); 00373 #endif // DBG 00374 00375 NTKERNELAPI 00376 VOID 00377 FASTCALL 00378 ExAcquireFastMutexUnsafe ( 00379 IN PFAST_MUTEX FastMutex 00380 ); 00381 00382 NTKERNELAPI 00383 VOID 00384 FASTCALL 00385 ExReleaseFastMutexUnsafe ( 00386 IN PFAST_MUTEX FastMutex 00387 ); 00388 00389 #if defined(_ALPHA_) || defined(_IA64_) 00390 00391 NTKERNELAPI 00392 VOID 00393 FASTCALL 00394 ExAcquireFastMutex ( 00395 IN PFAST_MUTEX FastMutex 00396 ); 00397 00398 NTKERNELAPI 00399 VOID 00400 FASTCALL 00401 ExReleaseFastMutex ( 00402 IN PFAST_MUTEX FastMutex 00403 ); 00404 00405 // end_wdm 00406 00407 NTKERNELAPI 00408 BOOLEAN 00409 FASTCALL 00410 ExTryToAcquireFastMutex ( 00411 IN PFAST_MUTEX FastMutex 00412 ); 00413 00414 // begin_wdm 00415 00416 #elif defined(_X86_) 00417 00418 NTHALAPI 00419 VOID 00420 FASTCALL 00421 ExAcquireFastMutex ( 00422 IN PFAST_MUTEX FastMutex 00423 ); 00424 00425 NTHALAPI 00426 VOID 00427 FASTCALL 00428 ExReleaseFastMutex ( 00429 IN PFAST_MUTEX FastMutex 00430 ); 00431 00432 // end_wdm 00433 00434 NTHALAPI 00435 BOOLEAN 00436 FASTCALL 00437 ExTryToAcquireFastMutex ( 00438 IN PFAST_MUTEX FastMutex 00439 ); 00440 00441 // begin_wdm 00442 00443 #else 00444 00445 #error "Target architecture not defined" 00446 00447 #endif 00448 00449 // end_ntifs end_ntddk end_wdm end_nthal 00450 00451 // 00452 // Interlocked support routine definitions. 00453 // 00454 // begin_ntddk begin_wdm begin_nthal begin_ntifs begin_ntndis 00455 // 00456 00457 NTKERNELAPI 00458 VOID 00459 FASTCALL 00460 ExInterlockedAddLargeStatistic ( 00461 IN PLARGE_INTEGER Addend, 00462 IN ULONG Increment 00463 ); 00464 00465 // end_ntndis 00466 00467 NTKERNELAPI 00468 LARGE_INTEGER 00469 ExInterlockedAddLargeInteger ( 00470 IN PLARGE_INTEGER Addend, 00471 IN LARGE_INTEGER Increment, 00472 IN PKSPIN_LOCK Lock 00473 ); 00474 00475 // end_wdm end_ntifs end_ntddk end_nthal 00476 00477 #if defined(NT_UP) && !defined(_NTHAL_) && !defined(_NTDDK_) && !defined(_NTIFS_) 00478 00479 #undef ExInterlockedAddUlong 00480 #define ExInterlockedAddUlong(x, y, z) InterlockedExchangeAdd((PLONG)(x), (LONG)(y)) 00481 00482 #else 00483 00484 // begin_wdm begin_ntddk begin_nthal begin_ntifs 00485 00486 NTKERNELAPI 00487 ULONG 00488 FASTCALL 00489 ExInterlockedAddUlong ( 00490 IN PULONG Addend, 00491 IN ULONG Increment, 00492 IN PKSPIN_LOCK Lock 00493 ); 00494 00495 // end_wdm end_ntifs end_ntddk end_nthal 00496 00497 #endif 00498 00499 // begin_wdm begin_ntddk begin_nthal begin_ntifs 00500 00501 #if defined(_AXP64_) 00502 00503 #define ExInterlockedCompareExchange64(Destination, Exchange, Comperand, Lock) \ 00504 InterlockedCompareExchange64(Destination, *(Exchange), *(Comperand)) 00505 00506 #elif defined(_ALPHA_) 00507 00508 #define ExInterlockedCompareExchange64(Destination, Exchange, Comperand, Lock) \ 00509 ExpInterlockedCompareExchange64(Destination, Exchange, Comperand) 00510 00511 #elif defined(_IA64_) 00512 00513 #define ExInterlockedCompareExchange64(Destination, Exchange, Comperand, Lock) \ 00514 InterlockedCompareExchange64(Destination, *(Exchange), *(Comperand)) 00515 00516 #else 00517 00518 NTKERNELAPI 00519 LONGLONG 00520 FASTCALL 00521 ExInterlockedCompareExchange64 ( 00522 IN PLONGLONG Destination, 00523 IN PLONGLONG Exchange, 00524 IN PLONGLONG Comperand, 00525 IN PKSPIN_LOCK Lock 00526 ); 00527 00528 #endif 00529 00530 NTKERNELAPI 00531 PLIST_ENTRY 00532 FASTCALL 00533 ExInterlockedInsertHeadList ( 00534 IN PLIST_ENTRY ListHead, 00535 IN PLIST_ENTRY ListEntry, 00536 IN PKSPIN_LOCK Lock 00537 ); 00538 00539 NTKERNELAPI 00540 PLIST_ENTRY 00541 FASTCALL 00542 ExInterlockedInsertTailList ( 00543 IN PLIST_ENTRY ListHead, 00544 IN PLIST_ENTRY ListEntry, 00545 IN PKSPIN_LOCK Lock 00546 ); 00547 00548 NTKERNELAPI 00549 PLIST_ENTRY 00550 FASTCALL 00551 ExInterlockedRemoveHeadList ( 00552 IN PLIST_ENTRY ListHead, 00553 IN PKSPIN_LOCK Lock 00554 ); 00555 00556 NTKERNELAPI 00557 PSINGLE_LIST_ENTRY 00558 FASTCALL 00559 ExInterlockedPopEntryList ( 00560 IN PSINGLE_LIST_ENTRY ListHead, 00561 IN PKSPIN_LOCK Lock 00562 ); 00563 00564 NTKERNELAPI 00565 PSINGLE_LIST_ENTRY 00566 FASTCALL 00567 ExInterlockedPushEntryList ( 00568 IN PSINGLE_LIST_ENTRY ListHead, 00569 IN PSINGLE_LIST_ENTRY ListEntry, 00570 IN PKSPIN_LOCK Lock 00571 ); 00572 00573 // begin_ntndis 00574 00575 // 00576 // Define interlocked sequenced listhead functions. 00577 // 00578 // A sequenced interlocked list is a singly linked list with a header that 00579 // contains the current depth and a sequence number. Each time an entry is 00580 // inserted or removed from the list the depth is updated and the sequence 00581 // number is incremented. This enables MIPS, Alpha, and Pentium and later 00582 // machines to insert and remove from the list without the use of spinlocks. 00583 // The PowerPc, however, must use a spinlock to synchronize access to the 00584 // list. 00585 // 00586 // N.B. A spinlock must be specified with SLIST operations. However, it may 00587 // not actually be used. 00588 // 00589 00590 /*++ 00591 00592 VOID 00593 ExInitializeSListHead ( 00594 IN PSLIST_HEADER SListHead 00595 ) 00596 00597 Routine Description: 00598 00599 This function initializes a sequenced singly linked listhead. 00600 00601 Arguments: 00602 00603 SListHead - Supplies a pointer to a sequenced singly linked listhead. 00604 00605 Return Value: 00606 00607 None. 00608 00609 --*/ 00610 00611 #define ExInitializeSListHead(_listhead_) (_listhead_)->Alignment = 0 00612 00613 /*++ 00614 00615 USHORT 00616 ExQueryDepthSList ( 00617 IN PSLIST_HEADERT SListHead 00618 ) 00619 00620 Routine Description: 00621 00622 This function queries the current number of entries contained in a 00623 sequenced single linked list. 00624 00625 Arguments: 00626 00627 SListHead - Supplies a pointer to the sequenced listhead which is 00628 be queried. 00629 00630 Return Value: 00631 00632 The current number of entries in the sequenced singly linked list is 00633 returned as the function value. 00634 00635 --*/ 00636 00637 #define ExQueryDepthSList(_listhead_) (USHORT)(_listhead_)->Depth 00638 00639 #if defined(_MIPS_) || defined(_ALPHA_) || defined(_IA64_) 00640 00641 #define ExInterlockedPopEntrySList(Head, Lock) \ 00642 ExpInterlockedPopEntrySList(Head) 00643 00644 #define ExInterlockedPushEntrySList(Head, Entry, Lock) \ 00645 ExpInterlockedPushEntrySList(Head, Entry) 00646 00647 #define ExInterlockedFlushSList(Head) \ 00648 ExpInterlockedFlushSList(Head) 00649 00650 NTKERNELAPI 00651 PSINGLE_LIST_ENTRY 00652 ExpInterlockedPopEntrySList ( 00653 IN PSLIST_HEADER ListHead 00654 ); 00655 00656 NTKERNELAPI 00657 PSINGLE_LIST_ENTRY 00658 ExpInterlockedPushEntrySList ( 00659 IN PSLIST_HEADER ListHead, 00660 IN PSINGLE_LIST_ENTRY ListEntry 00661 ); 00662 00663 NTKERNELAPI 00664 PSINGLE_LIST_ENTRY 00665 ExpInterlockedFlushSList ( 00666 IN PSLIST_HEADER ListHead 00667 ); 00668 00669 #else 00670 00671 NTKERNELAPI 00672 PSINGLE_LIST_ENTRY 00673 FASTCALL 00674 ExInterlockedPopEntrySList ( 00675 IN PSLIST_HEADER ListHead, 00676 IN PKSPIN_LOCK Lock 00677 ); 00678 00679 NTKERNELAPI 00680 PSINGLE_LIST_ENTRY 00681 FASTCALL 00682 ExInterlockedPushEntrySList ( 00683 IN PSLIST_HEADER ListHead, 00684 IN PSINGLE_LIST_ENTRY ListEntry, 00685 IN PKSPIN_LOCK Lock 00686 ); 00687 00688 NTKERNELAPI 00689 PSINGLE_LIST_ENTRY 00690 FASTCALL 00691 ExInterlockedFlushSList ( 00692 IN PSLIST_HEADER ListHead 00693 ); 00694 00695 #endif 00696 00697 // end_ntddk end_wdm 00698 // 00699 // Define interlocked lookaside list structure and allocation functions. 00700 // 00701 00702 VOID 00703 ExAdjustLookasideDepth ( 00704 VOID 00705 ); 00706 00707 // begin_ntddk begin_wdm 00708 00709 typedef 00710 PVOID 00711 (*PALLOCATE_FUNCTION) ( 00712 IN POOL_TYPE PoolType, 00713 IN SIZE_T NumberOfBytes, 00714 IN ULONG Tag 00715 ); 00716 00717 typedef 00718 VOID 00719 (*PFREE_FUNCTION) ( 00720 IN PVOID Buffer 00721 ); 00722 00723 typedef struct _GENERAL_LOOKASIDE { 00724 SLIST_HEADER ListHead; 00725 USHORT Depth; 00726 USHORT MaximumDepth; 00727 ULONG TotalAllocates; 00728 union { 00729 ULONG AllocateMisses; 00730 ULONG AllocateHits; 00731 }; 00732 00733 ULONG TotalFrees; 00734 union { 00735 ULONG FreeMisses; 00736 ULONG FreeHits; 00737 }; 00738 00739 POOL_TYPE Type; 00740 ULONG Tag; 00741 ULONG Size; 00742 PALLOCATE_FUNCTION Allocate; 00743 PFREE_FUNCTION Free; 00744 LIST_ENTRY ListEntry; 00745 ULONG LastTotalAllocates; 00746 union { 00747 ULONG LastAllocateMisses; 00748 ULONG LastAllocateHits; 00749 }; 00750 00751 ULONG Future[2]; 00752 } GENERAL_LOOKASIDE, *PGENERAL_LOOKASIDE; 00753 00754 typedef struct _NPAGED_LOOKASIDE_LIST { 00755 GENERAL_LOOKASIDE L; 00756 KSPIN_LOCK Lock; 00757 } NPAGED_LOOKASIDE_LIST, *PNPAGED_LOOKASIDE_LIST; 00758 00759 00760 NTKERNELAPI 00761 VOID 00762 ExInitializeNPagedLookasideList ( 00763 IN PNPAGED_LOOKASIDE_LIST Lookaside, 00764 IN PALLOCATE_FUNCTION Allocate, 00765 IN PFREE_FUNCTION Free, 00766 IN ULONG Flags, 00767 IN SIZE_T Size, 00768 IN ULONG Tag, 00769 IN USHORT Depth 00770 ); 00771 00772 NTKERNELAPI 00773 VOID 00774 ExDeleteNPagedLookasideList ( 00775 IN PNPAGED_LOOKASIDE_LIST Lookaside 00776 ); 00777 00778 __inline 00779 PVOID 00780 ExAllocateFromNPagedLookasideList( 00781 IN PNPAGED_LOOKASIDE_LIST Lookaside 00782 ) 00783 00784 /*++ 00785 00786 Routine Description: 00787 00788 This function removes (pops) the first entry from the specified 00789 nonpaged lookaside list. 00790 00791 Arguments: 00792 00793 Lookaside - Supplies a pointer to a nonpaged lookaside list structure. 00794 00795 Return Value: 00796 00797 If an entry is removed from the specified lookaside list, then the 00798 address of the entry is returned as the function value. Otherwise, 00799 NULL is returned. 00800 00801 --*/ 00802 00803 { 00804 00805 PVOID Entry; 00806 00807 Lookaside->L.TotalAllocates += 1; 00808 Entry = ExInterlockedPopEntrySList(&Lookaside->L.ListHead, &Lookaside->Lock); 00809 if (Entry == NULL) { 00810 Lookaside->L.AllocateMisses += 1; 00811 Entry = (Lookaside->L.Allocate)(Lookaside->L.Type, 00812 Lookaside->L.Size, 00813 Lookaside->L.Tag); 00814 } 00815 00816 return Entry; 00817 } 00818 00819 __inline 00820 VOID 00821 ExFreeToNPagedLookasideList( 00822 IN PNPAGED_LOOKASIDE_LIST Lookaside, 00823 IN PVOID Entry 00824 ) 00825 00826 /*++ 00827 00828 Routine Description: 00829 00830 This function inserts (pushes) the specified entry into the specified 00831 nonpaged lookaside list. 00832 00833 Arguments: 00834 00835 Lookaside - Supplies a pointer to a nonpaged lookaside list structure. 00836 00837 Entry - Supples a pointer to the entry that is inserted in the 00838 lookaside list. 00839 00840 Return Value: 00841 00842 None. 00843 00844 --*/ 00845 00846 { 00847 00848 Lookaside->L.TotalFrees += 1; 00849 if (ExQueryDepthSList(&Lookaside->L.ListHead) >= Lookaside->L.Depth) { 00850 Lookaside->L.FreeMisses += 1; 00851 (Lookaside->L.Free)(Entry); 00852 00853 } else { 00854 ExInterlockedPushEntrySList(&Lookaside->L.ListHead, 00855 (PSINGLE_LIST_ENTRY)Entry, 00856 &Lookaside->Lock); 00857 } 00858 00859 return; 00860 } 00861 00862 // end_ntndis 00863 00864 typedef struct _PAGED_LOOKASIDE_LIST { 00865 GENERAL_LOOKASIDE L; 00866 FAST_MUTEX Lock; 00867 } PAGED_LOOKASIDE_LIST, *PPAGED_LOOKASIDE_LIST; 00868 00869 NTKERNELAPI 00870 VOID 00871 ExInitializePagedLookasideList ( 00872 IN PPAGED_LOOKASIDE_LIST Lookaside, 00873 IN PALLOCATE_FUNCTION Allocate, 00874 IN PFREE_FUNCTION Free, 00875 IN ULONG Flags, 00876 IN SIZE_T Size, 00877 IN ULONG Tag, 00878 IN USHORT Depth 00879 ); 00880 00881 NTKERNELAPI 00882 VOID 00883 ExDeletePagedLookasideList ( 00884 IN PPAGED_LOOKASIDE_LIST Lookaside 00885 ); 00886 00887 #if defined(_X86_) 00888 00889 NTKERNELAPI 00890 PVOID 00891 ExAllocateFromPagedLookasideList( 00892 IN PPAGED_LOOKASIDE_LIST Lookaside 00893 ); 00894 00895 NTKERNELAPI 00896 VOID 00897 ExFreeToPagedLookasideList( 00898 IN PPAGED_LOOKASIDE_LIST Lookaside, 00899 IN PVOID Entry 00900 ); 00901 00902 #else 00903 00904 __inline 00905 PVOID 00906 ExAllocateFromPagedLookasideList( 00907 IN PPAGED_LOOKASIDE_LIST Lookaside 00908 ) 00909 00910 /*++ 00911 00912 Routine Description: 00913 00914 This function removes (pops) the first entry from the specified 00915 paged lookaside list. 00916 00917 Arguments: 00918 00919 Lookaside - Supplies a pointer to a paged lookaside list structure. 00920 00921 Return Value: 00922 00923 If an entry is removed from the specified lookaside list, then the 00924 address of the entry is returned as the function value. Otherwise, 00925 NULL is returned. 00926 00927 --*/ 00928 00929 { 00930 00931 PVOID Entry; 00932 00933 Lookaside->L.TotalAllocates += 1; 00934 Entry = ExInterlockedPopEntrySList(&Lookaside->L.ListHead, NULL); 00935 if (Entry == NULL) { 00936 Lookaside->L.AllocateMisses += 1; 00937 Entry = (Lookaside->L.Allocate)(Lookaside->L.Type, 00938 Lookaside->L.Size, 00939 Lookaside->L.Tag); 00940 } 00941 00942 return Entry; 00943 } 00944 00945 __inline 00946 VOID 00947 ExFreeToPagedLookasideList( 00948 IN PPAGED_LOOKASIDE_LIST Lookaside, 00949 IN PVOID Entry 00950 ) 00951 00952 /*++ 00953 00954 Routine Description: 00955 00956 This function inserts (pushes) the specified entry into the specified 00957 paged lookaside list. 00958 00959 Arguments: 00960 00961 Lookaside - Supplies a pointer to a nonpaged lookaside list structure. 00962 00963 Entry - Supples a pointer to the entry that is inserted in the 00964 lookaside list. 00965 00966 Return Value: 00967 00968 None. 00969 00970 --*/ 00971 00972 { 00973 00974 Lookaside->L.TotalFrees += 1; 00975 if (ExQueryDepthSList(&Lookaside->L.ListHead) >= Lookaside->L.Depth) { 00976 Lookaside->L.FreeMisses += 1; 00977 (Lookaside->L.Free)(Entry); 00978 00979 } else { 00980 ExInterlockedPushEntrySList(&Lookaside->L.ListHead, 00981 (PSINGLE_LIST_ENTRY)Entry, 00982 NULL); 00983 } 00984 00985 return; 00986 } 00987 00988 #endif 00989 00990 // end_ntddk end_nthal end_ntifs end_wdm 00991 00992 // 00993 // Define per processor nonpage lookaside list structures. 00994 // 00995 00996 typedef enum _PP_NPAGED_LOOKASIDE_NUMBER { 00997 LookasideSmallIrpList, 00998 LookasideLargeIrpList, 00999 LookasideMdlList, 01000 LookasideCreateInfoList, 01001 LookasideNameBufferList, 01002 LookasideTwilightList, 01003 LookasideCompletionList, 01004 LookasideMaximumList 01005 } PP_NPAGED_LOOKASIDE_NUMBER, *PPP_NPAGED_LOOKASIDE_NUMBER; 01006 01007 #if !defined(_CROSS_PLATFORM_) 01008 01009 __inline 01010 PVOID 01011 ExAllocateFromPPNPagedLookasideList( 01012 IN PP_NPAGED_LOOKASIDE_NUMBER Number 01013 ) 01014 01015 /*++ 01016 01017 Routine Description: 01018 01019 This function removes (pops) the first entry from the specified 01020 nonpaged per processor lookaside list. 01021 01022 Arguments: 01023 01024 Number - Supplies the per processor nonpaged lookaside list number. 01025 01026 Return Value: 01027 01028 If an entry is removed from the specified lookaside list, then the 01029 address of the entry is returned as the function value. Otherwise, 01030 NULL is returned. 01031 01032 --*/ 01033 01034 { 01035 01036 PVOID Entry; 01037 PNPAGED_LOOKASIDE_LIST Lookaside; 01038 PKPRCB Prcb; 01039 01040 // 01041 // Get address of current processor block. 01042 // 01043 // N.B. It is possible to context switch during the allocation from a 01044 // per processor nonpaged lookaside list, but this should happen 01045 // infrequently and should not aversely effect the benefits of 01046 // per processor lookaside lists. 01047 // 01048 01049 ASSERT((Number >= 0) && (Number < LookasideMaximumList)); 01050 01051 Prcb = KeGetCurrentPrcb(); 01052 01053 // 01054 // Attempt to allocate from the per processor lookaside list. 01055 // 01056 01057 Lookaside = Prcb->PPLookasideList[Number].P; 01058 Lookaside->L.TotalAllocates += 1; 01059 Entry = ExInterlockedPopEntrySList(&Lookaside->L.ListHead, &Lookaside->Lock); 01060 01061 // 01062 // If the per processor allocation attempt failed, then attempt to 01063 // allocate from the system lookaside list. 01064 // 01065 01066 if (Entry == NULL) { 01067 Lookaside->L.AllocateMisses += 1; 01068 Lookaside = Prcb->PPLookasideList[Number].L; 01069 Entry = ExAllocateFromNPagedLookasideList(Lookaside); 01070 } 01071 01072 return Entry; 01073 } 01074 01075 __inline 01076 VOID 01077 ExFreeToPPNPagedLookasideList( 01078 IN PP_NPAGED_LOOKASIDE_NUMBER Number, 01079 IN PVOID Entry 01080 ) 01081 01082 /*++ 01083 01084 Routine Description: 01085 01086 This function inserts (pushes) the specified entry into the specified 01087 nonpaged per processor lookaside list. 01088 01089 Arguments: 01090 01091 Number - Supplies the per processor nonpaged lookaside list number. 01092 01093 Entry - Supples a pointer to the entry that is inserted in the nonpaged 01094 per processor lookaside list. 01095 01096 Return Value: 01097 01098 None. 01099 01100 --*/ 01101 01102 { 01103 01104 PNPAGED_LOOKASIDE_LIST Lookaside; 01105 PKPRCB Prcb; 01106 01107 // 01108 // Get address of current processor block. 01109 // 01110 // N.B. It is possible to context switch during the free to a per 01111 // processor nonpaged lookaside list, but this should happen 01112 // infrequently and should not aversely effect the benefits of 01113 // per processor lookaside lists. 01114 // 01115 01116 ASSERT((Number >= 0) && (Number < LookasideMaximumList)); 01117 01118 Prcb = KeGetCurrentPrcb(); 01119 01120 // 01121 // If the current depth is less than of equal to the maximum depth, then 01122 // free the specified entry to the per processor lookaside list. Otherwise, 01123 // free the entry to the system lookaside list; 01124 // 01125 // 01126 01127 Lookaside = Prcb->PPLookasideList[Number].P; 01128 Lookaside->L.TotalFrees += 1; 01129 if (ExQueryDepthSList(&Lookaside->L.ListHead) >= Lookaside->L.Depth) { 01130 Lookaside->L.FreeMisses += 1; 01131 Lookaside = Prcb->PPLookasideList[Number].L; 01132 ExFreeToNPagedLookasideList(Lookaside, Entry); 01133 01134 } else { 01135 ExInterlockedPushEntrySList(&Lookaside->L.ListHead, 01136 (PSINGLE_LIST_ENTRY)Entry, 01137 &Lookaside->Lock); 01138 } 01139 01140 return; 01141 } 01142 01143 #endif 01144 01145 #if i386 && !FPO 01146 01147 NTSTATUS 01148 ExQuerySystemBackTraceInformation( 01149 OUT PRTL_PROCESS_BACKTRACES BackTraceInformation, 01150 IN ULONG BackTraceInformationLength, 01151 OUT PULONG ReturnLength OPTIONAL 01152 ); 01153 01154 NTKERNELAPI 01155 USHORT 01156 ExGetPoolBackTraceIndex( 01157 IN PVOID P 01158 ); 01159 01160 #endif // i386 && !FPO 01161 01162 NTKERNELAPI 01163 PVOID 01164 ExLockUserBuffer( 01165 IN PVOID Buffer, 01166 IN ULONG Length, 01167 OUT PVOID *LockVariable 01168 ); 01169 01170 NTKERNELAPI 01171 VOID 01172 ExUnlockUserBuffer( 01173 IN PVOID LockVariable 01174 ); 01175 01176 01177 01178 // begin_ntddk begin_wdm begin_ntifs 01179 01180 NTKERNELAPI 01181 VOID 01182 NTAPI 01183 ProbeForRead( 01184 IN CONST VOID *Address, 01185 IN ULONG Length, 01186 IN ULONG Alignment 01187 ); 01188 01189 // end_ntddk end_wdm end_ntifs 01190 01191 #if !defined(_NTHAL_) && !defined(_NTDDK_) && !defined(_NTIFS_) 01192 01193 // 01194 // Probe function definitions 01195 // 01196 // Probe for read functions. 01197 // 01198 //++ 01199 // 01200 // VOID 01201 // ProbeForRead( 01202 // IN PVOID Address, 01203 // IN ULONG Length, 01204 // IN ULONG Alignment 01205 // ) 01206 // 01207 //-- 01208 01209 #define ProbeForRead(Address, Length, Alignment) \ 01210 ASSERT(((Alignment) == 1) || ((Alignment) == 2) || \ 01211 ((Alignment) == 4) || ((Alignment) == 8) || \ 01212 ((Alignment) == 16)); \ 01213 \ 01214 if ((Length) != 0) { \ 01215 if (((ULONG_PTR)(Address) & ((Alignment) - 1)) != 0) { \ 01216 ExRaiseDatatypeMisalignment(); \ 01217 \ 01218 } else if ((((ULONG_PTR)(Address) + (Length)) < (ULONG_PTR)(Address)) || \ 01219 (((ULONG_PTR)(Address) + (Length)) > (ULONG_PTR)MM_USER_PROBE_ADDRESS)) { \ 01220 ExRaiseAccessViolation(); \ 01221 } \ 01222 } 01223 01224 #endif 01225 01226 //++ 01227 // 01228 // BOOLEAN 01229 // ProbeAndReadBoolean( 01230 // IN PBOOLEAN Address 01231 // ) 01232 // 01233 //-- 01234 01235 #define ProbeAndReadBoolean(Address) \ 01236 (((Address) >= (BOOLEAN * const)MM_USER_PROBE_ADDRESS) ? \ 01237 (*(volatile BOOLEAN * const)MM_USER_PROBE_ADDRESS) : (*(volatile BOOLEAN *)(Address))) 01238 01239 //++ 01240 // 01241 // CHAR 01242 // ProbeAndReadChar( 01243 // IN PCHAR Address 01244 // ) 01245 // 01246 //-- 01247 01248 #define ProbeAndReadChar(Address) \ 01249 (((Address) >= (CHAR * const)MM_USER_PROBE_ADDRESS) ? \ 01250 (*(volatile CHAR * const)MM_USER_PROBE_ADDRESS) : (*(volatile CHAR *)(Address))) 01251 01252 //++ 01253 // 01254 // UCHAR 01255 // ProbeAndReadUchar( 01256 // IN PUCHAR Address 01257 // ) 01258 // 01259 //-- 01260 01261 #define ProbeAndReadUchar(Address) \ 01262 (((Address) >= (UCHAR * const)MM_USER_PROBE_ADDRESS) ? \ 01263 (*(volatile UCHAR * const)MM_USER_PROBE_ADDRESS) : (*(volatile UCHAR *)(Address))) 01264 01265 //++ 01266 // 01267 // SHORT 01268 // ProbeAndReadShort( 01269 // IN PSHORT Address 01270 // ) 01271 // 01272 //-- 01273 01274 #define ProbeAndReadShort(Address) \ 01275 (((Address) >= (SHORT * const)MM_USER_PROBE_ADDRESS) ? \ 01276 (*(volatile SHORT * const)MM_USER_PROBE_ADDRESS) : (*(volatile SHORT *)(Address))) 01277 01278 //++ 01279 // 01280 // USHORT 01281 // ProbeAndReadUshort( 01282 // IN PUSHORT Address 01283 // ) 01284 // 01285 //-- 01286 01287 #define ProbeAndReadUshort(Address) \ 01288 (((Address) >= (USHORT * const)MM_USER_PROBE_ADDRESS) ? \ 01289 (*(volatile USHORT * const)MM_USER_PROBE_ADDRESS) : (*(volatile USHORT *)(Address))) 01290 01291 //++ 01292 // 01293 // HANDLE 01294 // ProbeAndReadHandle( 01295 // IN PHANDLE Address 01296 // ) 01297 // 01298 //-- 01299 01300 #define ProbeAndReadHandle(Address) \ 01301 (((Address) >= (HANDLE * const)MM_USER_PROBE_ADDRESS) ? \ 01302 (*(volatile HANDLE * const)MM_USER_PROBE_ADDRESS) : (*(volatile HANDLE *)(Address))) 01303 01304 //++ 01305 // 01306 // PVOID 01307 // ProbeAndReadPointer( 01308 // IN PVOID *Address 01309 // ) 01310 // 01311 //-- 01312 01313 #define ProbeAndReadPointer(Address) \ 01314 (((Address) >= (PVOID * const)MM_USER_PROBE_ADDRESS) ? \ 01315 (*(volatile PVOID * const)MM_USER_PROBE_ADDRESS) : (*(volatile PVOID *)(Address))) 01316 01317 //++ 01318 // 01319 // LONG 01320 // ProbeAndReadLong( 01321 // IN PLONG Address 01322 // ) 01323 // 01324 //-- 01325 01326 #define ProbeAndReadLong(Address) \ 01327 (((Address) >= (LONG * const)MM_USER_PROBE_ADDRESS) ? \ 01328 (*(volatile LONG * const)MM_USER_PROBE_ADDRESS) : (*(volatile LONG *)(Address))) 01329 01330 //++ 01331 // 01332 // ULONG 01333 // ProbeAndReadUlong( 01334 // IN PULONG Address 01335 // ) 01336 // 01337 //-- 01338 01339 #define ProbeAndReadUlong(Address) \ 01340 (((Address) >= (ULONG * const)MM_USER_PROBE_ADDRESS) ? \ 01341 (*(volatile ULONG * const)MM_USER_PROBE_ADDRESS) : (*(volatile ULONG *)(Address))) 01342 01343 //++ 01344 // 01345 // ULONG_PTR 01346 // ProbeAndReadUlong_ptr( 01347 // IN PULONG_PTR Address 01348 // ) 01349 // 01350 //-- 01351 01352 #define ProbeAndReadUlong_ptr(Address) \ 01353 (((Address) >= (ULONG_PTR * const)MM_USER_PROBE_ADDRESS) ? \ 01354 (*(volatile ULONG_PTR * const)MM_USER_PROBE_ADDRESS) : (*(volatile ULONG_PTR *)(Address))) 01355 01356 //++ 01357 // 01358 // QUAD 01359 // ProbeAndReadQuad( 01360 // IN PQUAD Address 01361 // ) 01362 // 01363 //-- 01364 01365 #define ProbeAndReadQuad(Address) \ 01366 (((Address) >= (QUAD * const)MM_USER_PROBE_ADDRESS) ? \ 01367 (*(volatile QUAD * const)MM_USER_PROBE_ADDRESS) : (*(volatile QUAD *)(Address))) 01368 01369 //++ 01370 // 01371 // UQUAD 01372 // ProbeAndReadUquad( 01373 // IN PUQUAD Address 01374 // ) 01375 // 01376 //-- 01377 01378 #define ProbeAndReadUquad(Address) \ 01379 (((Address) >= (UQUAD * const)MM_USER_PROBE_ADDRESS) ? \ 01380 (*(volatile UQUAD * const)MM_USER_PROBE_ADDRESS) : (*(volatile UQUAD *)(Address))) 01381 01382 //++ 01383 // 01384 // LARGE_INTEGER 01385 // ProbeAndReadLargeInteger( 01386 // IN PLARGE_INTEGER Source 01387 // ) 01388 // 01389 //-- 01390 01391 #define ProbeAndReadLargeInteger(Source) \ 01392 (((Source) >= (LARGE_INTEGER * const)MM_USER_PROBE_ADDRESS) ? \ 01393 (*(volatile LARGE_INTEGER * const)MM_USER_PROBE_ADDRESS) : (*(volatile LARGE_INTEGER *)(Source))) 01394 01395 //++ 01396 // 01397 // ULARGE_INTEGER 01398 // ProbeAndReadUlargeInteger( 01399 // IN PULARGE_INTEGER Source 01400 // ) 01401 // 01402 //-- 01403 01404 #define ProbeAndReadUlargeInteger(Source) \ 01405 (((Source) >= (ULARGE_INTEGER * const)MM_USER_PROBE_ADDRESS) ? \ 01406 (*(volatile ULARGE_INTEGER * const)MM_USER_PROBE_ADDRESS) : (*(volatile ULARGE_INTEGER *)(Source))) 01407 01408 //++ 01409 // 01410 // UNICODE_STRING 01411 // ProbeAndReadUnicodeString( 01412 // IN PUNICODE_STRING Source 01413 // ) 01414 // 01415 //-- 01416 01417 #define ProbeAndReadUnicodeString(Source) \ 01418 (((Source) >= (UNICODE_STRING * const)MM_USER_PROBE_ADDRESS) ? \ 01419 (*(volatile UNICODE_STRING * const)MM_USER_PROBE_ADDRESS) : (*(volatile UNICODE_STRING *)(Source))) 01420 01421 //++ 01422 // 01423 // <STRUCTURE> 01424 // ProbeAndReadStructure( 01425 // IN P<STRUCTURE> Source 01426 // <STRUCTURE> 01427 // ) 01428 // 01429 //-- 01430 01431 #define ProbeAndReadStructure(Source,STRUCTURE) \ 01432 (((Source) >= (STRUCTURE * const)MM_USER_PROBE_ADDRESS) ? \ 01433 (*(STRUCTURE * const)MM_USER_PROBE_ADDRESS) : (*(STRUCTURE *)(Source))) 01434 01435 // 01436 // Probe for write functions definitions. 01437 // 01438 //++ 01439 // 01440 // VOID 01441 // ProbeForWriteBoolean( 01442 // IN PBOOLEAN Address 01443 // ) 01444 // 01445 //-- 01446 01447 #define ProbeForWriteBoolean(Address) { \ 01448 if ((Address) >= (BOOLEAN * const)MM_USER_PROBE_ADDRESS) { \ 01449 *(volatile BOOLEAN * const)MM_USER_PROBE_ADDRESS = 0; \ 01450 } \ 01451 \ 01452 *(volatile BOOLEAN *)(Address) = *(volatile BOOLEAN *)(Address); \ 01453 } 01454 01455 //++ 01456 // 01457 // VOID 01458 // ProbeForWriteChar( 01459 // IN PCHAR Address 01460 // ) 01461 // 01462 //-- 01463 01464 #define ProbeForWriteChar(Address) { \ 01465 if ((Address) >= (CHAR * const)MM_USER_PROBE_ADDRESS) { \ 01466 *(volatile CHAR * const)MM_USER_PROBE_ADDRESS = 0; \ 01467 } \ 01468 \ 01469 *(volatile CHAR *)(Address) = *(volatile CHAR *)(Address); \ 01470 } 01471 01472 //++ 01473 // 01474 // VOID 01475 // ProbeForWriteUchar( 01476 // IN PUCHAR Address 01477 // ) 01478 // 01479 //-- 01480 01481 #define ProbeForWriteUchar(Address) { \ 01482 if ((Address) >= (UCHAR * const)MM_USER_PROBE_ADDRESS) { \ 01483 *(volatile UCHAR * const)MM_USER_PROBE_ADDRESS = 0; \ 01484 } \ 01485 \ 01486 *(volatile UCHAR *)(Address) = *(volatile UCHAR *)(Address); \ 01487 } 01488 01489 //++ 01490 // 01491 // VOID 01492 // ProbeForWriteIoStatus( 01493 // IN PIO_STATUS_BLOCK Address 01494 // ) 01495 // 01496 //-- 01497 01498 #define ProbeForWriteIoStatus(Address) { \ 01499 if ((Address) >= (IO_STATUS_BLOCK * const)MM_USER_PROBE_ADDRESS) { \ 01500 *(volatile ULONG * const)MM_USER_PROBE_ADDRESS = 0; \ 01501 } \ 01502 \ 01503 *(volatile IO_STATUS_BLOCK *)(Address) = *(volatile IO_STATUS_BLOCK *)(Address); \ 01504 } 01505 01506 #ifdef _WIN64 01507 #define ProbeForWriteIoStatusEx(Address, Cookie) { \ 01508 if ((Address) >= (IO_STATUS_BLOCK * const)MM_USER_PROBE_ADDRESS) { \ 01509 *(volatile ULONG * const)MM_USER_PROBE_ADDRESS = 0; \ 01510 } \ 01511 if ((ULONG_PTR)(Cookie) & (ULONG)1) { \ 01512 *(volatile IO_STATUS_BLOCK32 *)(Address) = *(volatile IO_STATUS_BLOCK32 *)(Address);\ 01513 } else { \ 01514 *(volatile IO_STATUS_BLOCK *)(Address) = *(volatile IO_STATUS_BLOCK *)(Address); \ 01515 } \ 01516 } 01517 #else 01518 #define ProbeForWriteIoStatusEx(Address, Cookie) ProbeForWriteIoStatus(Address) 01519 #endif 01520 01521 //++ 01522 // 01523 // VOID 01524 // ProbeForWriteShort( 01525 // IN PSHORT Address 01526 // ) 01527 // 01528 //-- 01529 01530 #define ProbeForWriteShort(Address) { \ 01531 if ((Address) >= (SHORT * const)MM_USER_PROBE_ADDRESS) { \ 01532 *(volatile SHORT * const)MM_USER_PROBE_ADDRESS = 0; \ 01533 } \ 01534 \ 01535 *(volatile SHORT *)(Address) = *(volatile SHORT *)(Address); \ 01536 } 01537 01538 //++ 01539 // 01540 // VOID 01541 // ProbeForWriteUshort( 01542 // IN PUSHORT Address 01543 // ) 01544 // 01545 //-- 01546 01547 #define ProbeForWriteUshort(Address) { \ 01548 if ((Address) >= (USHORT * const)MM_USER_PROBE_ADDRESS) { \ 01549 *(volatile USHORT * const)MM_USER_PROBE_ADDRESS = 0; \ 01550 } \ 01551 \ 01552 *(volatile USHORT *)(Address) = *(volatile USHORT *)(Address); \ 01553 } 01554 01555 //++ 01556 // 01557 // VOID 01558 // ProbeForWriteHandle( 01559 // IN PHANDLE Address 01560 // ) 01561 // 01562 //-- 01563 01564 #define ProbeForWriteHandle(Address) { \ 01565 if ((Address) >= (HANDLE * const)MM_USER_PROBE_ADDRESS) { \ 01566 *(volatile HANDLE * const)MM_USER_PROBE_ADDRESS = 0; \ 01567 } \ 01568 \ 01569 *(volatile HANDLE *)(Address) = *(volatile HANDLE *)(Address); \ 01570 } 01571 01572 //++ 01573 // 01574 // VOID 01575 // ProbeAndZeroHandle( 01576 // IN PHANDLE Address 01577 // ) 01578 // 01579 //-- 01580 01581 #define ProbeAndZeroHandle(Address) { \ 01582 if ((Address) >= (HANDLE * const)MM_USER_PROBE_ADDRESS) { \ 01583 *(volatile HANDLE * const)MM_USER_PROBE_ADDRESS = 0; \ 01584 } \ 01585 \ 01586 *(volatile HANDLE *)(Address) = 0; \ 01587 } 01588 01589 //++ 01590 // 01591 // VOID 01592 // ProbeForWritePointer( 01593 // IN PVOID Address 01594 // ) 01595 // 01596 //-- 01597 01598 #define ProbeForWritePointer(Address) { \ 01599 if ((PVOID *)(Address) >= (PVOID * const)MM_USER_PROBE_ADDRESS) { \ 01600 *(volatile PVOID * const)MM_USER_PROBE_ADDRESS = NULL; \ 01601 } \ 01602 \ 01603 *(volatile PVOID *)(Address) = *(volatile PVOID *)(Address); \ 01604 } 01605 01606 //++ 01607 // 01608 // VOID 01609 // ProbeAndNullPointer( 01610 // IN PVOID *Address 01611 // ) 01612 // 01613 //-- 01614 01615 #define ProbeAndNullPointer(Address) { \ 01616 if ((PVOID *)(Address) >= (PVOID * const)MM_USER_PROBE_ADDRESS) { \ 01617 *(volatile PVOID * const)MM_USER_PROBE_ADDRESS = NULL; \ 01618 } \ 01619 \ 01620 *(volatile PVOID *)(Address) = NULL; \ 01621 } 01622 01623 //++ 01624 // 01625 // VOID 01626 // ProbeForWriteLong( 01627 // IN PLONG Address 01628 // ) 01629 // 01630 //-- 01631 01632 #define ProbeForWriteLong(Address) { \ 01633 if ((Address) >= (LONG * const)MM_USER_PROBE_ADDRESS) { \ 01634 *(volatile LONG * const)MM_USER_PROBE_ADDRESS = 0; \ 01635 } \ 01636 \ 01637 *(volatile LONG *)(Address) = *(volatile LONG *)(Address); \ 01638 } 01639 01640 //++ 01641 // 01642 // VOID 01643 // ProbeForWriteUlong( 01644 // IN PULONG Address 01645 // ) 01646 // 01647 //-- 01648 01649 #define ProbeForWriteUlong(Address) { \ 01650 if ((Address) >= (ULONG * const)MM_USER_PROBE_ADDRESS) { \ 01651 *(volatile ULONG * const)MM_USER_PROBE_ADDRESS = 0; \ 01652 } \ 01653 \ 01654 *(volatile ULONG *)(Address) = *(volatile ULONG *)(Address); \ 01655 } 01656 01657 //++ 01658 // 01659 // VOID 01660 // ProbeForWriteUlong_ptr( 01661 // IN PULONG_PTR Address 01662 // ) 01663 // 01664 //-- 01665 01666 #define ProbeForWriteUlong_ptr(Address) { \ 01667 if ((Address) >= (ULONG_PTR * const)MM_USER_PROBE_ADDRESS) { \ 01668 *(volatile ULONG_PTR * const)MM_USER_PROBE_ADDRESS = 0; \ 01669 } \ 01670 \ 01671 *(volatile ULONG_PTR *)(Address) = *(volatile ULONG_PTR *)(Address); \ 01672 } 01673 01674 //++ 01675 // 01676 // VOID 01677 // ProbeForWriteQuad( 01678 // IN PQUAD Address 01679 // ) 01680 // 01681 //-- 01682 01683 #define ProbeForWriteQuad(Address) { \ 01684 if ((Address) >= (QUAD * const)MM_USER_PROBE_ADDRESS) { \ 01685 *(volatile LONG * const)MM_USER_PROBE_ADDRESS = 0; \ 01686 } \ 01687 \ 01688 *(volatile QUAD *)(Address) = *(volatile QUAD *)(Address); \ 01689 } 01690 01691 //++ 01692 // 01693 // VOID 01694 // ProbeForWriteUquad( 01695 // IN PUQUAD Address 01696 // ) 01697 // 01698 //-- 01699 01700 #define ProbeForWriteUquad(Address) { \ 01701 if ((Address) >= (QUAD * const)MM_USER_PROBE_ADDRESS) { \ 01702 *(volatile ULONG * const)MM_USER_PROBE_ADDRESS = 0; \ 01703 } \ 01704 \ 01705 *(volatile UQUAD *)(Address) = *(volatile UQUAD *)(Address); \ 01706 } 01707 01708 // 01709 // Probe and write functions definitions. 01710 // 01711 //++ 01712 // 01713 // VOID 01714 // ProbeAndWriteBoolean( 01715 // IN PBOOLEAN Address, 01716 // IN BOOLEAN Value 01717 // ) 01718 // 01719 //-- 01720 01721 #define ProbeAndWriteBoolean(Address, Value) { \ 01722 if ((Address) >= (BOOLEAN * const)MM_USER_PROBE_ADDRESS) { \ 01723 *(volatile BOOLEAN * const)MM_USER_PROBE_ADDRESS = 0; \ 01724 } \ 01725 \ 01726 *(Address) = (Value); \ 01727 } 01728 01729 //++ 01730 // 01731 // VOID 01732 // ProbeAndWriteChar( 01733 // IN PCHAR Address, 01734 // IN CHAR Value 01735 // ) 01736 // 01737 //-- 01738 01739 #define ProbeAndWriteChar(Address, Value) { \ 01740 if ((Address) >= (CHAR * const)MM_USER_PROBE_ADDRESS) { \ 01741 *(volatile CHAR * const)MM_USER_PROBE_ADDRESS = 0; \ 01742 } \ 01743 \ 01744 *(Address) = (Value); \ 01745 } 01746 01747 //++ 01748 // 01749 // VOID 01750 // ProbeAndWriteUchar( 01751 // IN PUCHAR Address, 01752 // IN UCHAR Value 01753 // ) 01754 // 01755 //-- 01756 01757 #define ProbeAndWriteUchar(Address, Value) { \ 01758 if ((Address) >= (UCHAR * const)MM_USER_PROBE_ADDRESS) { \ 01759 *(volatile UCHAR * const)MM_USER_PROBE_ADDRESS = 0; \ 01760 } \ 01761 \ 01762 *(Address) = (Value); \ 01763 } 01764 01765 //++ 01766 // 01767 // VOID 01768 // ProbeAndWriteShort( 01769 // IN PSHORT Address, 01770 // IN SHORT Value 01771 // ) 01772 // 01773 //-- 01774 01775 #define ProbeAndWriteShort(Address, Value) { \ 01776 if ((Address) >= (SHORT * const)MM_USER_PROBE_ADDRESS) { \ 01777 *(volatile SHORT * const)MM_USER_PROBE_ADDRESS = 0; \ 01778 } \ 01779 \ 01780 *(Address) = (Value); \ 01781 } 01782 01783 //++ 01784 // 01785 // VOID 01786 // ProbeAndWriteUshort( 01787 // IN PUSHORT Address, 01788 // IN USHORT Value 01789 // ) 01790 // 01791 //-- 01792 01793 #define ProbeAndWriteUshort(Address, Value) { \ 01794 if ((Address) >= (USHORT * const)MM_USER_PROBE_ADDRESS) { \ 01795 *(volatile USHORT * const)MM_USER_PROBE_ADDRESS = 0; \ 01796 } \ 01797 \ 01798 *(Address) = (Value); \ 01799 } 01800 01801 //++ 01802 // 01803 // VOID 01804 // ProbeAndWriteHandle( 01805 // IN PHANDLE Address, 01806 // IN HANDLE Value 01807 // ) 01808 // 01809 //-- 01810 01811 #define ProbeAndWriteHandle(Address, Value) { \ 01812 if ((Address) >= (HANDLE * const)MM_USER_PROBE_ADDRESS) { \ 01813 *(volatile HANDLE * const)MM_USER_PROBE_ADDRESS = 0; \ 01814 } \ 01815 \ 01816 *(Address) = (Value); \ 01817 } 01818 01819 //++ 01820 // 01821 // VOID 01822 // ProbeAndWriteLong( 01823 // IN PLONG Address, 01824 // IN LONG Value 01825 // ) 01826 // 01827 //-- 01828 01829 #define ProbeAndWriteLong(Address, Value) { \ 01830 if ((Address) >= (LONG * const)MM_USER_PROBE_ADDRESS) { \ 01831 *(volatile LONG * const)MM_USER_PROBE_ADDRESS = 0; \ 01832 } \ 01833 \ 01834 *(Address) = (Value); \ 01835 } 01836 01837 //++ 01838 // 01839 // VOID 01840 // ProbeAndWriteUlong( 01841 // IN PULONG Address, 01842 // IN ULONG Value 01843 // ) 01844 // 01845 //-- 01846 01847 #define ProbeAndWriteUlong(Address, Value) { \ 01848 if ((Address) >= (ULONG * const)MM_USER_PROBE_ADDRESS) { \ 01849 *(volatile ULONG * const)MM_USER_PROBE_ADDRESS = 0; \ 01850 } \ 01851 \ 01852 *(Address) = (Value); \ 01853 } 01854 01855 //++ 01856 // 01857 // VOID 01858 // ProbeAndWriteQuad( 01859 // IN PQUAD Address, 01860 // IN QUAD Value 01861 // ) 01862 // 01863 //-- 01864 01865 #define ProbeAndWriteQuad(Address, Value) { \ 01866 if ((Address) >= (QUAD * const)MM_USER_PROBE_ADDRESS) { \ 01867 *(volatile LONG * const)MM_USER_PROBE_ADDRESS = 0; \ 01868 } \ 01869 \ 01870 *(Address) = (Value); \ 01871 } 01872 01873 //++ 01874 // 01875 // VOID 01876 // ProbeAndWriteUquad( 01877 // IN PUQUAD Address, 01878 // IN UQUAD Value 01879 // ) 01880 // 01881 //-- 01882 01883 #define ProbeAndWriteUquad(Address, Value) { \ 01884 if ((Address) >= (UQUAD * const)MM_USER_PROBE_ADDRESS) { \ 01885 *(volatile ULONG * const)MM_USER_PROBE_ADDRESS = 0; \ 01886 } \ 01887 \ 01888 *(Address) = (Value); \ 01889 } 01890 01891 //++ 01892 // 01893 // VOID 01894 // ProbeAndWriteSturcture( 01895 // IN P<STRUCTURE> Address, 01896 // IN <STRUCTURE> Value, 01897 // <STRUCTURE> 01898 // ) 01899 // 01900 //-- 01901 01902 #define ProbeAndWriteStructure(Address, Value,STRUCTURE) { \ 01903 if ((STRUCTURE * const)(Address) >= (STRUCTURE * const)MM_USER_PROBE_ADDRESS) { \ 01904 *(volatile ULONG * const)MM_USER_PROBE_ADDRESS = 0; \ 01905 } \ 01906 \ 01907 *(Address) = (Value); \ 01908 } 01909 01910 // begin_ntifs begin_ntddk begin_wdm 01911 // 01912 // Common probe for write functions. 01913 // 01914 01915 NTKERNELAPI 01916 VOID 01917 NTAPI 01918 ProbeForWrite ( 01919 IN PVOID Address, 01920 IN ULONG Length, 01921 IN ULONG Alignment 01922 ); 01923 01924 // end_ntifs end_ntddk end_wdm 01925 01926 // 01927 // Timer Rundown 01928 // 01929 01930 NTKERNELAPI 01931 VOID 01932 ExTimerRundown ( 01933 VOID 01934 ); 01935 01936 // begin_ntddk begin_wdm begin_nthal begin_ntifs 01937 // 01938 // Worker Thread 01939 // 01940 01941 typedef enum _WORK_QUEUE_TYPE { 01942 CriticalWorkQueue, 01943 DelayedWorkQueue, 01944 HyperCriticalWorkQueue, 01945 MaximumWorkQueue 01946 } WORK_QUEUE_TYPE; 01947 01948 typedef 01949 VOID 01950 (*PWORKER_THREAD_ROUTINE)( 01951 IN PVOID Parameter 01952 ); 01953 01954 typedef struct _WORK_QUEUE_ITEM { 01955 LIST_ENTRY List; 01956 PWORKER_THREAD_ROUTINE WorkerRoutine; 01957 PVOID Parameter; 01958 } WORK_QUEUE_ITEM, *PWORK_QUEUE_ITEM; 01959 01960 01961 #define ExInitializeWorkItem(Item, Routine, Context) \ 01962 (Item)->WorkerRoutine = (Routine); \ 01963 (Item)->Parameter = (Context); \ 01964 (Item)->List.Flink = NULL; 01965 01966 NTKERNELAPI 01967 VOID 01968 ExQueueWorkItem( 01969 IN PWORK_QUEUE_ITEM WorkItem, 01970 IN WORK_QUEUE_TYPE QueueType 01971 ); 01972 01973 // end_wdm 01974 01975 NTKERNELAPI 01976 BOOLEAN 01977 ExIsProcessorFeaturePresent( 01978 ULONG ProcessorFeature 01979 ); 01980 01981 // end_ntddk end_nthal end_ntifs 01982 01983 typedef struct _EX_WORK_QUEUE { 01984 01985 // 01986 // Queue objects that that are used to hold work queue entries and 01987 // synchronize worker thread activity. 01988 // 01989 01990 KQUEUE WorkerQueue; 01991 01992 // 01993 // Number of dynamic worker threads that have been created "on the fly" 01994 // as part of worker thread deadlock prevention 01995 // 01996 01997 ULONG DynamicThreadCount; 01998 01999 // 02000 // Count of the number of work items processed. 02001 // 02002 02003 ULONG WorkItemsProcessed; 02004 02005 // 02006 // Used for deadlock detection, WorkItemsProcessedLastPass equals the value 02007 // of WorkItemsProcessed the last time ExpDetectWorkerThreadDeadlock() 02008 // ran. 02009 // 02010 02011 ULONG WorkItemsProcessedLastPass; 02012 02013 // 02014 // QueueDepthLastPass is also part of the worker queue state snapshot 02015 // taken by ExpDetectWorkerThreadDeadlock(). 02016 // 02017 02018 ULONG QueueDepthLastPass; 02019 02020 // 02021 // MakeThreadsAsNecessary indicates whether this work queue is elligible 02022 // for dynamic creation of threads not just for deadlock detection, 02023 // but to ensure that the CPUs are all kept busy clearing any work 02024 // item backlog. 02025 // 02026 02027 BOOLEAN MakeThreadsAsNecessary; 02028 02029 } EX_WORK_QUEUE, *PEX_WORK_QUEUE; 02030 02031 extern EX_WORK_QUEUE ExWorkerQueue[]; 02032 02033 02034 // begin_ntddk begin_nthal begin_ntifs 02035 // 02036 // Zone Allocation 02037 // 02038 02039 typedef struct _ZONE_SEGMENT_HEADER { 02040 SINGLE_LIST_ENTRY SegmentList; 02041 PVOID Reserved; 02042 } ZONE_SEGMENT_HEADER, *PZONE_SEGMENT_HEADER; 02043 02044 typedef struct _ZONE_HEADER { 02045 SINGLE_LIST_ENTRY FreeList; 02046 SINGLE_LIST_ENTRY SegmentList; 02047 ULONG BlockSize; 02048 ULONG TotalSegmentSize; 02049 } ZONE_HEADER, *PZONE_HEADER; 02050 02051 02052 NTKERNELAPI 02053 NTSTATUS 02054 ExInitializeZone( 02055 IN PZONE_HEADER Zone, 02056 IN ULONG BlockSize, 02057 IN PVOID InitialSegment, 02058 IN ULONG InitialSegmentSize 02059 ); 02060 02061 NTKERNELAPI 02062 NTSTATUS 02063 ExExtendZone( 02064 IN PZONE_HEADER Zone, 02065 IN PVOID Segment, 02066 IN ULONG SegmentSize 02067 ); 02068 02069 NTKERNELAPI 02070 NTSTATUS 02071 ExInterlockedExtendZone( 02072 IN PZONE_HEADER Zone, 02073 IN PVOID Segment, 02074 IN ULONG SegmentSize, 02075 IN PKSPIN_LOCK Lock 02076 ); 02077 02078 //++ 02079 // 02080 // PVOID 02081 // ExAllocateFromZone( 02082 // IN PZONE_HEADER Zone 02083 // ) 02084 // 02085 // Routine Description: 02086 // 02087 // This routine removes an entry from the zone and returns a pointer to it. 02088 // 02089 // Arguments: 02090 // 02091 // Zone - Pointer to the zone header controlling the storage from which the 02092 // entry is to be allocated. 02093 // 02094 // Return Value: 02095 // 02096 // The function value is a pointer to the storage allocated from the zone. 02097 // 02098 //-- 02099 02100 #define ExAllocateFromZone(Zone) \ 02101 (PVOID)((Zone)->FreeList.Next); \ 02102 if ( (Zone)->FreeList.Next ) (Zone)->FreeList.Next = (Zone)->FreeList.Next->Next 02103 02104 02105 //++ 02106 // 02107 // PVOID 02108 // ExFreeToZone( 02109 // IN PZONE_HEADER Zone, 02110 // IN PVOID Block 02111 // ) 02112 // 02113 // Routine Description: 02114 // 02115 // This routine places the specified block of storage back onto the free 02116 // list in the specified zone. 02117 // 02118 // Arguments: 02119 // 02120 // Zone - Pointer to the zone header controlling the storage to which the 02121 // entry is to be inserted. 02122 // 02123 // Block - Pointer to the block of storage to be freed back to the zone. 02124 // 02125 // Return Value: 02126 // 02127 // Pointer to previous block of storage that was at the head of the free 02128 // list. NULL implies the zone went from no available free blocks to 02129 // at least one free block. 02130 // 02131 //-- 02132 02133 #define ExFreeToZone(Zone,Block) \ 02134 ( ((PSINGLE_LIST_ENTRY)(Block))->Next = (Zone)->FreeList.Next, \ 02135 (Zone)->FreeList.Next = ((PSINGLE_LIST_ENTRY)(Block)), \ 02136 ((PSINGLE_LIST_ENTRY)(Block))->Next \ 02137 ) 02138 02139 //++ 02140 // 02141 // BOOLEAN 02142 // ExIsFullZone( 02143 // IN PZONE_HEADER Zone 02144 // ) 02145 // 02146 // Routine Description: 02147 // 02148 // This routine determines if the specified zone is full or not. A zone 02149 // is considered full if the free list is empty. 02150 // 02151 // Arguments: 02152 // 02153 // Zone - Pointer to the zone header to be tested. 02154 // 02155 // Return Value: 02156 // 02157 // TRUE if the zone is full and FALSE otherwise. 02158 // 02159 //-- 02160 02161 #define ExIsFullZone(Zone) \ 02162 ( (Zone)->FreeList.Next == (PSINGLE_LIST_ENTRY)NULL ) 02163 02164 //++ 02165 // 02166 // PVOID 02167 // ExInterlockedAllocateFromZone( 02168 // IN PZONE_HEADER Zone, 02169 // IN PKSPIN_LOCK Lock 02170 // ) 02171 // 02172 // Routine Description: 02173 // 02174 // This routine removes an entry from the zone and returns a pointer to it. 02175 // The removal is performed with the specified lock owned for the sequence 02176 // to make it MP-safe. 02177 // 02178 // Arguments: 02179 // 02180 // Zone - Pointer to the zone header controlling the storage from which the 02181 // entry is to be allocated. 02182 // 02183 // Lock - Pointer to the spin lock which should be obtained before removing 02184 // the entry from the allocation list. The lock is released before 02185 // returning to the caller. 02186 // 02187 // Return Value: 02188 // 02189 // The function value is a pointer to the storage allocated from the zone. 02190 // 02191 //-- 02192 02193 #define ExInterlockedAllocateFromZone(Zone,Lock) \ 02194 (PVOID) ExInterlockedPopEntryList( &(Zone)->FreeList, Lock ) 02195 02196 //++ 02197 // 02198 // PVOID 02199 // ExInterlockedFreeToZone( 02200 // IN PZONE_HEADER Zone, 02201 // IN PVOID Block, 02202 // IN PKSPIN_LOCK Lock 02203 // ) 02204 // 02205 // Routine Description: 02206 // 02207 // This routine places the specified block of storage back onto the free 02208 // list in the specified zone. The insertion is performed with the lock 02209 // owned for the sequence to make it MP-safe. 02210 // 02211 // Arguments: 02212 // 02213 // Zone - Pointer to the zone header controlling the storage to which the 02214 // entry is to be inserted. 02215 // 02216 // Block - Pointer to the block of storage to be freed back to the zone. 02217 // 02218 // Lock - Pointer to the spin lock which should be obtained before inserting 02219 // the entry onto the free list. The lock is released before returning 02220 // to the caller. 02221 // 02222 // Return Value: 02223 // 02224 // Pointer to previous block of storage that was at the head of the free 02225 // list. NULL implies the zone went from no available free blocks to 02226 // at least one free block. 02227 // 02228 //-- 02229 02230 #define ExInterlockedFreeToZone(Zone,Block,Lock) \ 02231 ExInterlockedPushEntryList( &(Zone)->FreeList, ((PSINGLE_LIST_ENTRY) (Block)), Lock ) 02232 02233 02234 //++ 02235 // 02236 // BOOLEAN 02237 // ExIsObjectInFirstZoneSegment( 02238 // IN PZONE_HEADER Zone, 02239 // IN PVOID Object 02240 // ) 02241 // 02242 // Routine Description: 02243 // 02244 // This routine determines if the specified pointer lives in the zone. 02245 // 02246 // Arguments: 02247 // 02248 // Zone - Pointer to the zone header controlling the storage to which the 02249 // object may belong. 02250 // 02251 // Object - Pointer to the object in question. 02252 // 02253 // Return Value: 02254 // 02255 // TRUE if the Object came from the first segment of zone. 02256 // 02257 //-- 02258 02259 #define ExIsObjectInFirstZoneSegment(Zone,Object) ((BOOLEAN) \ 02260 (((PUCHAR)(Object) >= (PUCHAR)(Zone)->SegmentList.Next) && \ 02261 ((PUCHAR)(Object) < (PUCHAR)(Zone)->SegmentList.Next + \ 02262 (Zone)->TotalSegmentSize)) \ 02263 ) 02264 02265 // end_ntddk end_nthal end_ntifs 02266 02267 02268 02269 // begin_ntifs begin_ntddk 02270 // 02271 // Define executive resource data structures. 02272 // 02273 02274 typedef ULONG_PTR ERESOURCE_THREAD; 02275 typedef ERESOURCE_THREAD *PERESOURCE_THREAD; 02276 02277 typedef struct _OWNER_ENTRY { 02278 ERESOURCE_THREAD OwnerThread; 02279 union { 02280 LONG OwnerCount; 02281 ULONG TableSize; 02282 }; 02283 02284 } OWNER_ENTRY, *POWNER_ENTRY; 02285 02286 typedef struct _ERESOURCE { 02287 LIST_ENTRY SystemResourcesList; 02288 POWNER_ENTRY OwnerTable; 02289 SHORT ActiveCount; 02290 USHORT Flag; 02291 PKSEMAPHORE SharedWaiters; 02292 PKEVENT ExclusiveWaiters; 02293 OWNER_ENTRY OwnerThreads[2]; 02294 ULONG ContentionCount; 02295 USHORT NumberOfSharedWaiters; 02296 USHORT NumberOfExclusiveWaiters; 02297 union { 02298 PVOID Address; 02299 ULONG_PTR CreatorBackTraceIndex; 02300 }; 02301 02302 KSPIN_LOCK SpinLock; 02303 } ERESOURCE, *PERESOURCE; 02304 02305 // 02306 // Values for ERESOURCE.Flag 02307 // 02308 02309 #define ResourceNeverExclusive 0x10 02310 #define ResourceReleaseByOtherThread 0x20 02311 #define ResourceOwnedExclusive 0x80 02312 02313 #define RESOURCE_HASH_TABLE_SIZE 64 02314 02315 typedef struct _RESOURCE_HASH_ENTRY { 02316 LIST_ENTRY ListEntry; 02317 PVOID Address; 02318 ULONG ContentionCount; 02319 ULONG Number; 02320 } RESOURCE_HASH_ENTRY, *PRESOURCE_HASH_ENTRY; 02321 02322 typedef struct _RESOURCE_PERFORMANCE_DATA { 02323 ULONG ActiveResourceCount; 02324 ULONG TotalResourceCount; 02325 ULONG ExclusiveAcquire; 02326 ULONG SharedFirstLevel; 02327 ULONG SharedSecondLevel; 02328 ULONG StarveFirstLevel; 02329 ULONG StarveSecondLevel; 02330 ULONG WaitForExclusive; 02331 ULONG OwnerTableExpands; 02332 ULONG MaximumTableExpand; 02333 LIST_ENTRY HashTable[RESOURCE_HASH_TABLE_SIZE]; 02334 } RESOURCE_PERFORMANCE_DATA, *PRESOURCE_PERFORMANCE_DATA; 02335 02336 // 02337 // Define executive resource function prototypes. 02338 // 02339 02340 NTKERNELAPI 02341 NTSTATUS 02342 ExInitializeResourceLite( 02343 IN PERESOURCE Resource 02344 ); 02345 02346 NTKERNELAPI 02347 NTSTATUS 02348 ExReinitializeResourceLite( 02349 IN PERESOURCE Resource 02350 ); 02351 02352 NTKERNELAPI 02353 BOOLEAN 02354 ExAcquireResourceSharedLite( 02355 IN PERESOURCE Resource, 02356 IN BOOLEAN Wait 02357 ); 02358 02359 NTKERNELAPI 02360 BOOLEAN 02361 ExAcquireResourceExclusiveLite( 02362 IN PERESOURCE Resource, 02363 IN BOOLEAN Wait 02364 ); 02365 02366 NTKERNELAPI 02367 BOOLEAN 02368 ExAcquireSharedStarveExclusive( 02369 IN PERESOURCE Resource, 02370 IN BOOLEAN Wait 02371 ); 02372 02373 NTKERNELAPI 02374 BOOLEAN 02375 ExAcquireSharedWaitForExclusive( 02376 IN PERESOURCE Resource, 02377 IN BOOLEAN Wait 02378 ); 02379 02380 NTKERNELAPI 02381 BOOLEAN 02382 ExTryToAcquireResourceExclusiveLite( 02383 IN PERESOURCE Resource 02384 ); 02385 02386 // 02387 // VOID 02388 // ExReleaseResource( 02389 // IN PERESOURCE Resource 02390 // ); 02391 // 02392 02393 #define ExReleaseResource(R) (ExReleaseResourceLite(R)) 02394 02395 NTKERNELAPI 02396 VOID 02397 FASTCALL 02398 ExReleaseResourceLite( 02399 IN PERESOURCE Resource 02400 ); 02401 02402 NTKERNELAPI 02403 VOID 02404 ExReleaseResourceForThreadLite( 02405 IN PERESOURCE Resource, 02406 IN ERESOURCE_THREAD ResourceThreadId 02407 ); 02408 02409 NTKERNELAPI 02410 VOID 02411 ExSetResourceOwnerPointer( 02412 IN PERESOURCE Resource, 02413 IN PVOID OwnerPointer 02414 ); 02415 02416 NTKERNELAPI 02417 VOID 02418 ExConvertExclusiveToSharedLite( 02419 IN PERESOURCE Resource 02420 ); 02421 02422 NTKERNELAPI 02423 NTSTATUS 02424 ExDeleteResourceLite ( 02425 IN PERESOURCE Resource 02426 ); 02427 02428 NTKERNELAPI 02429 ULONG 02430 ExGetExclusiveWaiterCount ( 02431 IN PERESOURCE Resource 02432 ); 02433 02434 NTKERNELAPI 02435 ULONG 02436 ExGetSharedWaiterCount ( 02437 IN PERESOURCE Resource 02438 ); 02439 02440 // end_ntddk 02441 02442 NTKERNELAPI 02443 VOID 02444 ExDisableResourceBoostLite ( 02445 IN PERESOURCE Resource 02446 ); 02447 02448 // begin_ntddk 02449 // 02450 // ERESOURCE_THREAD 02451 // ExGetCurrentResourceThread( 02452 // ); 02453 // 02454 02455 #define ExGetCurrentResourceThread() ((ULONG_PTR)PsGetCurrentThread()) 02456 02457 NTKERNELAPI 02458 BOOLEAN 02459 ExIsResourceAcquiredExclusiveLite ( 02460 IN PERESOURCE Resource 02461 ); 02462 02463 NTKERNELAPI 02464 ULONG 02465 ExIsResourceAcquiredSharedLite ( 02466 IN PERESOURCE Resource 02467 ); 02468 02469 // 02470 // ntddk.h stole the entrypoints we wanted so fix them up here. 02471 // 02472 02473 #define ExInitializeResource ExInitializeResourceLite 02474 #define ExAcquireResourceShared ExAcquireResourceSharedLite 02475 #define ExAcquireResourceExclusive ExAcquireResourceExclusiveLite 02476 #define ExReleaseResourceForThread ExReleaseResourceForThreadLite 02477 #define ExConvertExclusiveToShared ExConvertExclusiveToSharedLite 02478 #define ExDeleteResource ExDeleteResourceLite 02479 #define ExIsResourceAcquiredExclusive ExIsResourceAcquiredExclusiveLite 02480 #define ExIsResourceAcquiredShared ExIsResourceAcquiredSharedLite 02481 // end_ntddk 02482 #define ExDisableResourceBoost ExDisableResourceBoostLite 02483 // end_ntifs 02484 02485 #if DEVL 02486 NTKERNELAPI 02487 NTSTATUS 02488 ExQuerySystemLockInformation( 02489 OUT struct _RTL_PROCESS_LOCKS *LockInformation, 02490 IN ULONG LockInformationLength, 02491 OUT PULONG ReturnLength OPTIONAL 02492 ); 02493 #endif // DEVL 02494 02495 // 02496 // Shared resource function definitions (in resource.c). 02497 // 02498 // This definition here matches the ntddk one defined above. It allows 02499 // the resource package to deal with these antiquated objects. 02500 // 02501 02502 typedef struct _NTDDK_ERESOURCE { 02503 02504 // 02505 // First 8 bytes are used to align the next part of the structure 02506 // onto 16 bytes. (typical case) 02507 // 02508 02509 LIST_ENTRY SystemResourcesList; 02510 02511 // 02512 // Next 128 bits of this structure are field which we know 02513 // we will hit to obtain this resource either shared or exclusive 02514 // 02515 02516 PERESOURCE_THREAD OwnerThreads; 02517 PUCHAR OwnerCounts; 02518 02519 USHORT TableSize; 02520 USHORT ActiveCount; 02521 02522 USHORT Flag; 02523 USHORT TableRover; // (0 - 128 bits) 02524 02525 // 02526 // Next 128 bits contain the initial counters and at least the 02527 // first initial thread (which is also highly updated) 02528 // 02529 02530 UCHAR InitialOwnerCounts[4]; 02531 ERESOURCE_THREAD InitialOwnerThreads[4]; 02532 02533 ULONG Spare1; 02534 02535 // 02536 // The rest is what ever was left. The spinlock is in with 02537 // a part of the structure we normally don't touch in the 02538 // hot paths (read or write) 02539 // 02540 02541 ULONG ContentionCount; 02542 02543 USHORT NumberOfExclusiveWaiters; 02544 USHORT NumberOfSharedWaiters; 02545 02546 KSEMAPHORE SharedWaiters; 02547 KEVENT ExclusiveWaiters; 02548 02549 KSPIN_LOCK SpinLock; 02550 02551 USHORT CreatorBackTraceIndex; 02552 USHORT Spare2; 02553 02554 } NTDDK_ERESOURCE; 02555 typedef NTDDK_ERESOURCE *PNTDDK_ERESOURCE; 02556 02557 // 02558 // These are routines that were unfortunately exported to ntddk.h 02559 // 02560 // They live in ntos\ex\ddkresrc.c 02561 // 02562 02563 // 02564 // NTKERNELAPI 02565 // NTSTATUS 02566 // ExInitializeResource( 02567 // IN PNTDDK_ERESOURCE Resource 02568 // ); 02569 // 02570 // NTKERNELAPI 02571 // BOOLEAN 02572 // ExAcquireResourceExclusive( 02573 // IN PNTDDK_ERESOURCE Resource, 02574 // IN BOOLEAN Wait 02575 // ); 02576 // 02577 // NTKERNELAPI 02578 // VOID 02579 // ExReleaseResourceForThread( 02580 // IN PNTDDK_ERESOURCE Resource, 02581 // IN ERESOURCE_THREAD ResourceThreadId 02582 // ); 02583 // 02584 // NTKERNELAPI 02585 // NTSTATUS 02586 // ExDeleteResource ( 02587 // IN PNTDDK_ERESOURCE Resource 02588 // ); 02589 // 02590 02591 02592 // 02593 // The Ex/Ob handle table interface package (in handle.c) 02594 // 02595 02596 // 02597 // The Ex/Ob handle table package uses a common handle definition. The actual 02598 // type definition for a handle is a pvoid and is declared in sdk/inc. This 02599 // package uses only the low 32 bits of the pvoid pointer. 02600 // 02601 // For simplicity we declare a new typedef called an exhandle 02602 // 02603 // The 2 bits of an EXHANDLE is available to the application and is 02604 // ignored by the system. The next 24 bits store the handle table entry 02605 // index and is used to refer to a particular entry in a handle table. 02606 // 02607 // Note that this format is immutable because there are outside programs with 02608 // hardwired code that already assumes the format of a handle. 02609 // 02610 02611 typedef struct _EXHANDLE { 02612 02613 union { 02614 02615 struct { 02616 02617 // 02618 // Application available tag bits 02619 // 02620 02621 ULONG TagBits : 2; 02622 02623 // 02624 // The handle table entry index 02625 // 02626 02627 ULONG Index : 30; 02628 }; 02629 02630 HANDLE GenericHandleOverlay; 02631 }; 02632 02633 } EXHANDLE, *PEXHANDLE; 02634 02635 // 02636 // A handle table stores multiple handle table entries, each entry is looked 02637 // up by its exhandle. A handle table entry has really two fields. 02638 // 02639 // The first field contains a pointer object and is overloaded with the three 02640 // low order bits used by ob to denote inherited, protected, and audited 02641 // objects. The upper bit used as a handle table entry lock. Note, this 02642 // means that all valid object pointers must be at least longword aligned and 02643 // have their sign bit set (i.e., be negative). 02644 // 02645 // The next field contains the acces mask (sometimes in the form of a granted 02646 // access index, and creator callback trace) if the entry is in use or a 02647 // pointer in the free list if the entry is free. 02648 // 02649 // Two things to note: 02650 // 02651 // 1. An entry is free if the object pointer is null, this means that the 02652 // following field contains the FreeTableEntryList. 02653 // 02654 // 2. An entry is unlocked if the object pointer is positive and locked if its 02655 // negative. The handle package through callbacks and Map Handle to 02656 // Pointer will lock the entry (thus making the pointer valid) outside 02657 // routines can then read and reset the attributes field and the object 02658 // provided they don't unlock the entry. When the callbacks return the 02659 // entry will be unlocked and the callers or MapHandleToPointer will need 02660 // to call UnlockHandleTableEntry explicitly. 02661 // 02662 02663 typedef struct _HANDLE_TABLE_ENTRY { 02664 02665 // 02666 // The pointer to the object overloaded with three ob attributes bits in 02667 // the lower order and the high bit to denote locked or unlocked entries 02668 // 02669 02670 union { 02671 02672 PVOID Object; 02673 02674 ULONG ObAttributes; 02675 }; 02676 02677 // 02678 // This field either contains the granted access mask for the handle or an 02679 // ob variation that also stores the same information. Or in the case of 02680 // a free entry the field stores the index for the next free entry in the 02681 // free list. This is like a FAT chain, and is used instead of pointers 02682 // to make table duplication easier, because the entries can just be 02683 // copied without needing to modify pointers. 02684 // 02685 02686 union { 02687 02688 union { 02689 02690 ACCESS_MASK GrantedAccess; 02691 02692 struct { 02693 02694 USHORT GrantedAccessIndex; 02695 USHORT CreatorBackTraceIndex; 02696 }; 02697 }; 02698 02699 LONG NextFreeTableEntry; 02700 }; 02701 02702 } HANDLE_TABLE_ENTRY, *PHANDLE_TABLE_ENTRY; 02703 02704 // 02705 // One handle table exists per process. Unless otherwise specified, via a 02706 // call to RemoveHandleTable, all handle tables are linked together in a 02707 // global list. This list is used by the snapshot handle tables call. 02708 // 02709 02710 typedef struct _HANDLE_TABLE { 02711 02712 // 02713 // A set of flags used to denote the state or attributes of this 02714 // particular handle table 02715 // 02716 02717 ULONG Flags; 02718 02719 // 02720 // The number of handle table entries in use. 02721 // 02722 02723 LONG HandleCount; 02724 02725 // 02726 // A pointer to the top level handle table tree node. 02727 // 02728 02729 PHANDLE_TABLE_ENTRY **Table; 02730 02731 // 02732 // The process who is being charged quota for this handle table and a 02733 // unique process id to use in our callbacks 02734 // 02735 02736 struct _EPROCESS *QuotaProcess; 02737 HANDLE UniqueProcessId; 02738 02739 // 02740 // This is a singly linked list of free table entries. We don't actually 02741 // use pointers, but have each store the index of the next free entry 02742 // in the list. The list is managed as a lifo list. We also keep track 02743 // of the next index that we have to allocate pool to hold. 02744 // 02745 02746 LONG FirstFreeTableEntry; 02747 LONG NextIndexNeedingPool; 02748 02749 // 02750 // This is the lock used to protect the fields in the record, and the 02751 // handle table tree in general. Individual handle table entries that are 02752 // not free have their own lock 02753 // 02754 02755 ERESOURCE HandleTableLock; 02756 02757 // 02758 // The list of global handle tables. This field is protected by a global 02759 // lock. 02760 // 02761 02762 LIST_ENTRY HandleTableList; 02763 02764 // 02765 // The following field is used to loosely synchronize thread contention 02766 // on a handle. If a thread wants to wait for a handle to be unlocked 02767 // it will wait on this event with a short timeout. Any handle unlock 02768 // operation will pulse this event if there are threads waiting on it 02769 // 02770 02771 KEVENT HandleContentionEvent; 02772 02773 } HANDLE_TABLE, *PHANDLE_TABLE; 02774 02775 // 02776 // Routines for handle manipulation. 02777 // 02778 02779 // 02780 // Functions for locking and unlocking the handle table, and for locking and 02781 // locking handle table entries 02782 // 02783 02784 NTKERNELAPI 02785 VOID 02786 ExLockHandleTableShared ( 02787 PHANDLE_TABLE HandleTable 02788 ); 02789 02790 NTKERNELAPI 02791 VOID 02792 ExLockHandleTableExclusive ( 02793 PHANDLE_TABLE HandleTable 02794 ); 02795 02796 NTKERNELAPI 02797 VOID 02798 ExUnlockHandleTableShared ( 02799 PHANDLE_TABLE HandleTable 02800 ); 02801 02802 NTKERNELAPI 02803 VOID 02804 ExUnlockHandleTableExclusive ( 02805 PHANDLE_TABLE HandleTable 02806 ); 02807 02808 NTKERNELAPI 02809 BOOLEAN 02810 ExLockHandleTableEntry ( 02811 PHANDLE_TABLE HandleTable, 02812 PHANDLE_TABLE_ENTRY HandleTableEntry 02813 ); 02814 02815 NTKERNELAPI 02816 VOID 02817 ExUnlockHandleTableEntry ( 02818 PHANDLE_TABLE HandleTable, 02819 PHANDLE_TABLE_ENTRY HandleTableEntry 02820 ); 02821 02822 // 02823 // A global initialization function called on at system start up 02824 // 02825 02826 NTKERNELAPI 02827 VOID 02828 ExInitializeHandleTablePackage ( 02829 VOID 02830 ); 02831 02832 // 02833 // Functions to create, remove, and destroy handle tables per process. The 02834 // destroy function uses a callback. 02835 // 02836 02837 NTKERNELAPI 02838 PHANDLE_TABLE 02839 ExCreateHandleTable ( 02840 IN struct _EPROCESS *Process OPTIONAL 02841 ); 02842 02843 NTKERNELAPI 02844 VOID 02845 ExRemoveHandleTable ( 02846 IN PHANDLE_TABLE HandleTable 02847 ); 02848 02849 typedef VOID (*EX_DESTROY_HANDLE_ROUTINE)( 02850 IN HANDLE Handle 02851 ); 02852 02853 NTKERNELAPI 02854 VOID 02855 ExDestroyHandleTable ( 02856 IN PHANDLE_TABLE HandleTable, 02857 IN EX_DESTROY_HANDLE_ROUTINE DestroyHandleProcedure 02858 ); 02859 02860 // 02861 // A function to enumerate through the handle table of a process using a 02862 // callback. 02863 // 02864 02865 typedef BOOLEAN (*EX_ENUMERATE_HANDLE_ROUTINE)( 02866 IN PHANDLE_TABLE_ENTRY HandleTableEntry, 02867 IN HANDLE Handle, 02868 IN PVOID EnumParameter 02869 ); 02870 02871 NTKERNELAPI 02872 BOOLEAN 02873 ExEnumHandleTable ( 02874 IN PHANDLE_TABLE HandleTable, 02875 IN EX_ENUMERATE_HANDLE_ROUTINE EnumHandleProcedure, 02876 IN PVOID EnumParameter, 02877 OUT PHANDLE Handle OPTIONAL 02878 ); 02879 02880 // 02881 // A function to duplicate the handle table of a process using a callback 02882 // 02883 02884 typedef BOOLEAN (*EX_DUPLICATE_HANDLE_ROUTINE)( 02885 IN struct _EPROCESS *Process OPTIONAL, 02886 IN PHANDLE_TABLE_ENTRY HandleTableEntry 02887 ); 02888 02889 NTKERNELAPI 02890 PHANDLE_TABLE 02891 ExDupHandleTable ( 02892 IN struct _EPROCESS *Process OPTIONAL, 02893 IN PHANDLE_TABLE OldHandleTable, 02894 IN EX_DUPLICATE_HANDLE_ROUTINE DupHandleProcedure OPTIONAL 02895 ); 02896 02897 // 02898 // A function that enumerates all the handles in all the handle tables 02899 // throughout the system using a callback. 02900 // 02901 02902 typedef NTSTATUS (*PEX_SNAPSHOT_HANDLE_ENTRY)( 02903 IN OUT PSYSTEM_HANDLE_TABLE_ENTRY_INFO *HandleEntryInfo, 02904 IN HANDLE UniqueProcessId, 02905 IN PHANDLE_TABLE_ENTRY HandleEntry, 02906 IN HANDLE Handle, 02907 IN ULONG Length, 02908 IN OUT PULONG RequiredLength 02909 ); 02910 02911 NTKERNELAPI 02912 NTSTATUS 02913 ExSnapShotHandleTables ( 02914 IN PEX_SNAPSHOT_HANDLE_ENTRY SnapShotHandleEntry, 02915 IN OUT PSYSTEM_HANDLE_INFORMATION HandleInformation, 02916 IN ULONG Length, 02917 IN OUT PULONG RequiredLength 02918 ); 02919 02920 // 02921 // Functions to create, destroy, and modify handle table entries the modify 02922 // function using a callback 02923 // 02924 02925 NTKERNELAPI 02926 HANDLE 02927 ExCreateHandle ( 02928 IN PHANDLE_TABLE HandleTable, 02929 IN PHANDLE_TABLE_ENTRY HandleTableEntry 02930 ); 02931 02932 02933 NTKERNELAPI 02934 BOOLEAN 02935 ExDestroyHandle ( 02936 IN PHANDLE_TABLE HandleTable, 02937 IN HANDLE Handle, 02938 IN PHANDLE_TABLE_ENTRY HandleTableEntry OPTIONAL 02939 ); 02940 02941 02942 typedef BOOLEAN (*PEX_CHANGE_HANDLE_ROUTINE) ( 02943 IN OUT PHANDLE_TABLE_ENTRY HandleTableEntry, 02944 IN ULONG_PTR Parameter 02945 ); 02946 02947 NTKERNELAPI 02948 BOOLEAN 02949 ExChangeHandle ( 02950 IN PHANDLE_TABLE HandleTable, 02951 IN HANDLE Handle, 02952 IN PEX_CHANGE_HANDLE_ROUTINE ChangeRoutine, 02953 IN ULONG_PTR Parameter 02954 ); 02955 02956 // 02957 // A function that takes a handle value and returns a pointer to the 02958 // associated handle table entry. 02959 // 02960 02961 NTKERNELAPI 02962 PHANDLE_TABLE_ENTRY 02963 ExMapHandleToPointer ( 02964 IN PHANDLE_TABLE HandleTable, 02965 IN HANDLE Handle 02966 ); 02967 02968 // 02969 // Macros for resetting the owner of the handle table, and current 02970 // noop macro for setting fifo/lifo behaviour of the table 02971 // 02972 02973 #define ExSetHandleTableOwner(ht,id) {(ht)->UniqueProcessId = (id);} 02974 02975 #define ExSetHandleTableOrder(ht,or) {NOTHING;} 02976 02977 02978 // 02979 // Locally Unique Identifier Services 02980 // 02981 02982 NTKERNELAPI 02983 BOOLEAN 02984 ExLuidInitialization ( 02985 VOID 02986 ); 02987 02988 // 02989 // VOID 02990 // ExAllocateLocallyUniqueId ( 02991 // PLUID Luid 02992 // ) 02993 // 02994 //*++ 02995 // 02996 // Routine Description: 02997 // 02998 // This function returns an LUID value that is unique since the system 02999 // was last rebooted. It is unique only on the system it is generated on 03000 // and not network wide. 03001 // 03002 // N.B. A LUID is a 64-bit value and for all practical purposes will 03003 // never carry in the lifetime of a single boot of the system. 03004 // At an increment rate of 1ns, the value would carry to zero in 03005 // approximately 126 years. 03006 // 03007 // Arguments: 03008 // 03009 // Luid - Supplies a pointer to a variable that receives the allocated 03010 // locally unique Id. 03011 // 03012 // Return Value: 03013 // 03014 // The allocated LUID value. 03015 // 03016 // --*/ 03017 03018 03019 extern LARGE_INTEGER ExpLuid; 03020 extern LARGE_INTEGER ExpLuidIncrement; 03021 extern KSPIN_LOCK ExpLuidLock; 03022 03023 03024 #define ExAllocateLocallyUniqueId(Luid) \ 03025 { \ 03026 LARGE_INTEGER _TempLi; \ 03027 \ 03028 _TempLi = ExInterlockedExchangeAddLargeInteger(&ExpLuid, \ 03029 ExpLuidIncrement, \ 03030 &ExpLuidLock); \ 03031 (Luid)->LowPart = _TempLi.LowPart; \ 03032 (Luid)->HighPart = _TempLi.HighPart; \ 03033 } 03034 03035 03036 // begin_ntddk begin_wdm begin_ntifs 03037 // 03038 // Get previous mode 03039 // 03040 03041 NTKERNELAPI 03042 KPROCESSOR_MODE 03043 ExGetPreviousMode( 03044 VOID 03045 ); 03046 // end_ntddk end_wdm end_ntifs 03047 03048 // 03049 // Raise exception from kernel mode. 03050 // 03051 03052 NTKERNELAPI 03053 VOID 03054 NTAPI 03055 ExRaiseException ( 03056 PEXCEPTION_RECORD ExceptionRecord 03057 ); 03058 03059 // begin_ntddk begin_wdm begin_ntifs 03060 // 03061 // Raise status from kernel mode. 03062 // 03063 03064 NTKERNELAPI 03065 VOID 03066 NTAPI 03067 ExRaiseStatus ( 03068 IN NTSTATUS Status 03069 ); 03070 03071 // end_wdm 03072 03073 NTKERNELAPI 03074 VOID 03075 ExRaiseDatatypeMisalignment ( 03076 VOID 03077 ); 03078 03079 NTKERNELAPI 03080 VOID 03081 ExRaiseAccessViolation ( 03082 VOID 03083 ); 03084 03085 // end_ntddk end_ntifs 03086 03087 extern BOOLEAN ExReadyForErrors; 03088 03089 NTKERNELAPI 03090 NTSTATUS 03091 ExRaiseHardError( 03092 IN NTSTATUS ErrorStatus, 03093 IN ULONG NumberOfParameters, 03094 IN ULONG UnicodeStringParameterMask, 03095 IN PULONG_PTR Parameters, 03096 IN ULONG ValidResponseOptions, 03097 OUT PULONG Response 03098 ); 03099 03100 int 03101 ExSystemExceptionFilter( 03102 VOID 03103 ); 03104 03105 // 03106 // The following are global counters used by the EX component to indicate 03107 // the amount of EventPair transactions being performed in the system. 03108 // 03109 03110 extern ULONG EvPrSetHigh; 03111 extern ULONG EvPrSetLow; 03112 03113 03114 // 03115 // Debug event logging facility 03116 // 03117 03118 #define EX_DEBUG_LOG_FORMAT_NONE (UCHAR)0 03119 #define EX_DEBUG_LOG_FORMAT_ULONG (UCHAR)1 03120 #define EX_DEBUG_LOG_FORMAT_PSZ (UCHAR)2 03121 #define EX_DEBUG_LOG_FORMAT_PWSZ (UCHAR)3 03122 #define EX_DEBUG_LOG_FORMAT_STRING (UCHAR)4 03123 #define EX_DEBUG_LOG_FORMAT_USTRING (UCHAR)5 03124 #define EX_DEBUG_LOG_FORMAT_OBJECT (UCHAR)6 03125 #define EX_DEBUG_LOG_FORMAT_HANDLE (UCHAR)7 03126 03127 #define EX_DEBUG_LOG_NUMBER_OF_DATA_VALUES 4 03128 #define EX_DEBUG_LOG_NUMBER_OF_BACK_TRACES 4 03129 03130 typedef struct _EX_DEBUG_LOG_TAG { 03131 UCHAR Format[ EX_DEBUG_LOG_NUMBER_OF_DATA_VALUES ]; 03132 PCHAR Name; 03133 } EX_DEBUG_LOG_TAG, *PEX_DEBUG_LOG_TAG; 03134 03135 typedef struct _EX_DEBUG_LOG_EVENT { 03136 USHORT ThreadId; 03137 USHORT ProcessId; 03138 ULONG Time : 24; 03139 ULONG Tag : 8; 03140 ULONG BackTrace[ EX_DEBUG_LOG_NUMBER_OF_BACK_TRACES ]; 03141 ULONG Data[ EX_DEBUG_LOG_NUMBER_OF_DATA_VALUES ]; 03142 } EX_DEBUG_LOG_EVENT, *PEX_DEBUG_LOG_EVENT; 03143 03144 typedef struct _EX_DEBUG_LOG { 03145 KSPIN_LOCK Lock; 03146 ULONG NumberOfTags; 03147 ULONG MaximumNumberOfTags; 03148 PEX_DEBUG_LOG_TAG Tags; 03149 ULONG CountOfEventsLogged; 03150 PEX_DEBUG_LOG_EVENT First; 03151 PEX_DEBUG_LOG_EVENT Last; 03152 PEX_DEBUG_LOG_EVENT Next; 03153 } EX_DEBUG_LOG, *PEX_DEBUG_LOG; 03154 03155 03156 NTKERNELAPI 03157 PEX_DEBUG_LOG 03158 ExCreateDebugLog( 03159 IN UCHAR MaximumNumberOfTags, 03160 IN ULONG MaximumNumberOfEvents 03161 ); 03162 03163 NTKERNELAPI 03164 UCHAR 03165 ExCreateDebugLogTag( 03166 IN PEX_DEBUG_LOG Log, 03167 IN PCHAR Name, 03168 IN UCHAR Format1, 03169 IN UCHAR Format2, 03170 IN UCHAR Format3, 03171 IN UCHAR Format4 03172 ); 03173 03174 NTKERNELAPI 03175 VOID 03176 ExDebugLogEvent( 03177 IN PEX_DEBUG_LOG Log, 03178 IN UCHAR Tag, 03179 IN ULONG Data1, 03180 IN ULONG Data2, 03181 IN ULONG Data3, 03182 IN ULONG Data4 03183 ); 03184 03185 VOID 03186 ExShutdownSystem( 03187 VOID 03188 ); 03189 03190 VOID 03191 ExAcquireTimeRefreshLock( 03192 VOID 03193 ); 03194 03195 VOID 03196 ExReleaseTimeRefreshLock( 03197 VOID 03198 ); 03199 03200 VOID 03201 ExUpdateSystemTimeFromCmos ( 03202 IN BOOLEAN UpdateInterruptTime, 03203 IN ULONG MaxSepInSeconds 03204 ); 03205 03206 VOID 03207 ExGetNextWakeTime ( 03208 OUT PULONGLONG DueTime, 03209 OUT PTIME_FIELDS TimeFields, 03210 OUT PVOID *TimerObject 03211 ); 03212 03213 // begin_ntddk begin_wdm begin_ntifs 03214 // 03215 // Set timer resolution. 03216 // 03217 03218 NTKERNELAPI 03219 ULONG 03220 ExSetTimerResolution ( 03221 IN ULONG DesiredTime, 03222 IN BOOLEAN SetResolution 03223 ); 03224 03225 // end_wdm 03226 // 03227 // Subtract time zone bias from system time to get local time. 03228 // 03229 03230 NTKERNELAPI 03231 VOID 03232 ExSystemTimeToLocalTime ( 03233 IN PLARGE_INTEGER SystemTime, 03234 OUT PLARGE_INTEGER LocalTime 03235 ); 03236 03237 // 03238 // Add time zone bias to local time to get system time. 03239 // 03240 03241 NTKERNELAPI 03242 VOID 03243 ExLocalTimeToSystemTime ( 03244 IN PLARGE_INTEGER LocalTime, 03245 OUT PLARGE_INTEGER SystemTime 03246 ); 03247 03248 // end_ntddk end_ntifs 03249 03250 NTKERNELAPI 03251 VOID 03252 ExInitializeTimeRefresh( 03253 VOID 03254 ); 03255 03256 // begin_ntddk begin_wdm begin_ntifs begin_nthal begin_ntminiport 03257 03258 // 03259 // Define the type for Callback function. 03260 // 03261 03262 typedef struct _CALLBACK_OBJECT *PCALLBACK_OBJECT; 03263 03264 typedef VOID (*PCALLBACK_FUNCTION ) ( 03265 IN PVOID CallbackContext, 03266 IN PVOID Argument1, 03267 IN PVOID Argument2 03268 ); 03269 03270 03271 NTKERNELAPI 03272 NTSTATUS 03273 ExCreateCallback ( 03274 OUT PCALLBACK_OBJECT *CallbackObject, 03275 IN POBJECT_ATTRIBUTES ObjectAttributes, 03276 IN BOOLEAN Create, 03277 IN BOOLEAN AllowMultipleCallbacks 03278 ); 03279 03280 NTKERNELAPI 03281 PVOID 03282 ExRegisterCallback ( 03283 IN PCALLBACK_OBJECT CallbackObject, 03284 IN PCALLBACK_FUNCTION CallbackFunction, 03285 IN PVOID CallbackContext 03286 ); 03287 03288 NTKERNELAPI 03289 VOID 03290 ExUnregisterCallback ( 03291 IN PVOID CallbackRegistration 03292 ); 03293 03294 NTKERNELAPI 03295 VOID 03296 ExNotifyCallback ( 03297 IN PVOID CallbackObject, 03298 IN PVOID Argument1, 03299 IN PVOID Argument2 03300 ); 03301 03302 // end_ntddk end_wdm end_ntifs end_nthal end_ntminiport 03303 03304 // 03305 // The current bias from GMT to LocalTime 03306 // 03307 03308 extern LARGE_INTEGER ExpTimeZoneBias; 03309 extern LONG ExpLastTimeZoneBias; 03310 extern LONG ExpAltTimeZoneBias; 03311 extern ULONG ExpCurrentTimeZoneId; 03312 extern ULONG ExpRealTimeIsUniversal; 03313 extern ULONG ExCriticalWorkerThreads; 03314 extern ULONG ExDelayedWorkerThreads; 03315 extern ULONG ExpTickCountMultiplier; 03316 03317 // 03318 // The lock handle for PAGELK section, initialized in init\init.c 03319 // 03320 03321 extern PVOID ExPageLockHandle; 03322 03323 // 03324 // Global executive callbacks 03325 // 03326 03327 extern PCALLBACK_OBJECT ExCbSetSystemTime; 03328 extern PCALLBACK_OBJECT ExCbSetSystemState; 03329 extern PCALLBACK_OBJECT ExCbPowerState; 03330 03331 03332 typedef 03333 PVOID 03334 (*PKWIN32_GLOBALATOMTABLE_CALLOUT) ( void ); 03335 03336 extern PKWIN32_GLOBALATOMTABLE_CALLOUT ExGlobalAtomTableCallout; 03337 03338 // begin_ntddk 03339 03340 // 03341 // UUID Generation 03342 // 03343 03344 typedef GUID UUID; 03345 03346 NTKERNELAPI 03347 NTSTATUS 03348 ExUuidCreate( 03349 OUT UUID *Uuid 03350 ); 03351 03352 // end_ntddk 03353 03354 // 03355 // suite support 03356 // 03357 03358 03359 NTKERNELAPI 03360 BOOLEAN 03361 ExVerifySuite( 03362 SUITE_TYPE SuiteType 03363 ); 03364 03365 NTKERNELAPI 03366 ULONG 03367 FASTCALL 03368 ExInterlockedSetBits ( 03369 IN OUT PULONG Flags, 03370 IN ULONG Flag 03371 ); 03372 03373 NTKERNELAPI 03374 ULONG 03375 FASTCALL 03376 ExInterlockedClearBits ( 03377 IN OUT PULONG Flags, 03378 IN ULONG Flag 03379 ); 03380 03381 NTKERNELAPI 03382 ULONG 03383 FASTCALL 03384 ExInterlockedSetClearBits ( 03385 IN OUT PULONG Flags, 03386 IN ULONG sFlag, 03387 IN ULONG cFlag 03388 ); 03389 #endif /* _EX_ */

Generated on Sat May 15 19:39:57 2004 for test by doxygen 1.3.7