Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

5211 lines
115 KiB

  1. /*++ BUILD Version: 0007 // Increment this if a change has global effects
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. ex.h
  5. Abstract:
  6. Public executive data structures and procedure prototypes.
  7. Author:
  8. Mark Lucovsky (markl) 23-Feb-1989
  9. Revision History:
  10. --*/
  11. #ifndef _EX_
  12. #define _EX_
  13. //
  14. // Define caller count hash table structures and function prototypes.
  15. //
  16. #define CALL_HASH_TABLE_SIZE 64
  17. typedef struct _CALL_HASH_ENTRY {
  18. LIST_ENTRY ListEntry;
  19. PVOID CallersAddress;
  20. PVOID CallersCaller;
  21. ULONG CallCount;
  22. } CALL_HASH_ENTRY, *PCALL_HASH_ENTRY;
  23. typedef struct _CALL_PERFORMANCE_DATA {
  24. KSPIN_LOCK SpinLock;
  25. LIST_ENTRY HashTable[CALL_HASH_TABLE_SIZE];
  26. } CALL_PERFORMANCE_DATA, *PCALL_PERFORMANCE_DATA;
  27. VOID
  28. ExInitializeCallData(
  29. IN PCALL_PERFORMANCE_DATA CallData
  30. );
  31. VOID
  32. ExRecordCallerInHashTable(
  33. IN PCALL_PERFORMANCE_DATA CallData,
  34. IN PVOID CallersAddress,
  35. IN PVOID CallersCaller
  36. );
  37. #define RECORD_CALL_DATA(Table) \
  38. { \
  39. PVOID CallersAddress; \
  40. PVOID CallersCaller; \
  41. RtlGetCallersAddress(&CallersAddress, &CallersCaller); \
  42. ExRecordCallerInHashTable((Table), CallersAddress, CallersCaller); \
  43. }
  44. //
  45. // Define executive event pair object structure.
  46. //
  47. typedef struct _EEVENT_PAIR {
  48. KEVENT_PAIR KernelEventPair;
  49. } EEVENT_PAIR, *PEEVENT_PAIR;
  50. //
  51. // empty struct def so we can forward reference ETHREAD
  52. //
  53. struct _ETHREAD;
  54. //
  55. // System Initialization procedure for EX subcomponent of NTOS (in exinit.c)
  56. //
  57. NTKERNELAPI
  58. BOOLEAN
  59. ExInitSystem(
  60. VOID
  61. );
  62. NTKERNELAPI
  63. VOID
  64. ExInitSystemPhase2(
  65. VOID
  66. );
  67. VOID
  68. ExInitPoolLookasidePointers (
  69. VOID
  70. );
  71. ULONG
  72. ExComputeTickCountMultiplier (
  73. IN ULONG TimeIncrement
  74. );
  75. // begin_ntddk begin_wdm begin_nthal begin_ntifs begin_ntndis begin_ntosp
  76. //
  77. // Pool Allocation routines (in pool.c)
  78. //
  79. typedef enum _POOL_TYPE {
  80. NonPagedPool,
  81. PagedPool,
  82. NonPagedPoolMustSucceed,
  83. DontUseThisType,
  84. NonPagedPoolCacheAligned,
  85. PagedPoolCacheAligned,
  86. NonPagedPoolCacheAlignedMustS,
  87. MaxPoolType
  88. // end_wdm
  89. ,
  90. //
  91. // Note these per session types are carefully chosen so that the appropriate
  92. // masking still applies as well as MaxPoolType above.
  93. //
  94. NonPagedPoolSession = 32,
  95. PagedPoolSession = NonPagedPoolSession + 1,
  96. NonPagedPoolMustSucceedSession = PagedPoolSession + 1,
  97. DontUseThisTypeSession = NonPagedPoolMustSucceedSession + 1,
  98. NonPagedPoolCacheAlignedSession = DontUseThisTypeSession + 1,
  99. PagedPoolCacheAlignedSession = NonPagedPoolCacheAlignedSession + 1,
  100. NonPagedPoolCacheAlignedMustSSession = PagedPoolCacheAlignedSession + 1,
  101. // begin_wdm
  102. } POOL_TYPE;
  103. #define POOL_COLD_ALLOCATION 256 // Note this cannot encode into the header.
  104. // end_ntddk end_wdm end_nthal end_ntifs end_ntndis begin_ntosp
  105. //
  106. // The following two definitions control the raising of exceptions on quota
  107. // and allocation failures.
  108. //
  109. #define POOL_QUOTA_FAIL_INSTEAD_OF_RAISE 8
  110. #define POOL_RAISE_IF_ALLOCATION_FAILURE 16 // ntifs
  111. // end_ntosp
  112. VOID
  113. InitializePool(
  114. IN POOL_TYPE PoolType,
  115. IN ULONG Threshold
  116. );
  117. //
  118. // These routines are private to the pool manager and the memory manager.
  119. //
  120. VOID
  121. ExInsertPoolTag (
  122. ULONG Tag,
  123. PVOID Va,
  124. SIZE_T NumberOfBytes,
  125. POOL_TYPE PoolType
  126. );
  127. VOID
  128. ExAllocatePoolSanityChecks(
  129. IN POOL_TYPE PoolType,
  130. IN SIZE_T NumberOfBytes
  131. );
  132. VOID
  133. ExFreePoolSanityChecks(
  134. IN PVOID P
  135. );
  136. // begin_ntddk begin_nthal begin_ntifs begin_wdm begin_ntosp
  137. NTKERNELAPI
  138. PVOID
  139. ExAllocatePool(
  140. IN POOL_TYPE PoolType,
  141. IN SIZE_T NumberOfBytes
  142. );
  143. NTKERNELAPI
  144. PVOID
  145. ExAllocatePoolWithQuota(
  146. IN POOL_TYPE PoolType,
  147. IN SIZE_T NumberOfBytes
  148. );
  149. NTKERNELAPI
  150. PVOID
  151. NTAPI
  152. ExAllocatePoolWithTag(
  153. IN POOL_TYPE PoolType,
  154. IN SIZE_T NumberOfBytes,
  155. IN ULONG Tag
  156. );
  157. //
  158. // _EX_POOL_PRIORITY_ provides a method for the system to handle requests
  159. // intelligently in low resource conditions.
  160. //
  161. // LowPoolPriority should be used when it is acceptable to the driver for the
  162. // mapping request to fail if the system is low on resources. An example of
  163. // this could be for a non-critical network connection where the driver can
  164. // handle the failure case when system resources are close to being depleted.
  165. //
  166. // NormalPoolPriority should be used when it is acceptable to the driver for the
  167. // mapping request to fail if the system is very low on resources. An example
  168. // of this could be for a non-critical local filesystem request.
  169. //
  170. // HighPoolPriority should be used when it is unacceptable to the driver for the
  171. // mapping request to fail unless the system is completely out of resources.
  172. // An example of this would be the paging file path in a driver.
  173. //
  174. // SpecialPool can be specified to bound the allocation at a page end (or
  175. // beginning). This should only be done on systems being debugged as the
  176. // memory cost is expensive.
  177. //
  178. // N.B. These values are very carefully chosen so that the pool allocation
  179. // code can quickly crack the priority request.
  180. //
  181. typedef enum _EX_POOL_PRIORITY {
  182. LowPoolPriority,
  183. LowPoolPrioritySpecialPoolOverrun = 8,
  184. LowPoolPrioritySpecialPoolUnderrun = 9,
  185. NormalPoolPriority = 16,
  186. NormalPoolPrioritySpecialPoolOverrun = 24,
  187. NormalPoolPrioritySpecialPoolUnderrun = 25,
  188. HighPoolPriority = 32,
  189. HighPoolPrioritySpecialPoolOverrun = 40,
  190. HighPoolPrioritySpecialPoolUnderrun = 41
  191. } EX_POOL_PRIORITY;
  192. NTKERNELAPI
  193. PVOID
  194. NTAPI
  195. ExAllocatePoolWithTagPriority(
  196. IN POOL_TYPE PoolType,
  197. IN SIZE_T NumberOfBytes,
  198. IN ULONG Tag,
  199. IN EX_POOL_PRIORITY Priority
  200. );
  201. #ifndef POOL_TAGGING
  202. #define ExAllocatePoolWithTag(a,b,c) ExAllocatePool(a,b)
  203. #endif //POOL_TAGGING
  204. NTKERNELAPI
  205. PVOID
  206. ExAllocatePoolWithQuotaTag(
  207. IN POOL_TYPE PoolType,
  208. IN SIZE_T NumberOfBytes,
  209. IN ULONG Tag
  210. );
  211. #ifndef POOL_TAGGING
  212. #define ExAllocatePoolWithQuotaTag(a,b,c) ExAllocatePoolWithQuota(a,b)
  213. #endif //POOL_TAGGING
  214. NTKERNELAPI
  215. VOID
  216. NTAPI
  217. ExFreePool(
  218. IN PVOID P
  219. );
  220. // end_wdm
  221. #if defined(POOL_TAGGING)
  222. #define ExFreePool(a) ExFreePoolWithTag(a,0)
  223. #endif
  224. //
  225. // If high order bit in Pool tag is set, then must use ExFreePoolWithTag to free
  226. //
  227. #define PROTECTED_POOL 0x80000000
  228. // begin_wdm
  229. NTKERNELAPI
  230. VOID
  231. ExFreePoolWithTag(
  232. IN PVOID P,
  233. IN ULONG Tag
  234. );
  235. // end_ntddk end_wdm end_nthal end_ntifs
  236. #ifndef POOL_TAGGING
  237. #define ExFreePoolWithTag(a,b) ExFreePool(a)
  238. #endif //POOL_TAGGING
  239. // end_ntosp
  240. NTKERNELAPI
  241. KIRQL
  242. ExLockPool(
  243. IN POOL_TYPE PoolType
  244. );
  245. NTKERNELAPI
  246. VOID
  247. ExUnlockPool(
  248. IN POOL_TYPE PoolType,
  249. IN KIRQL LockHandle
  250. );
  251. // begin_ntosp
  252. NTKERNELAPI // ntifs
  253. SIZE_T // ntifs
  254. ExQueryPoolBlockSize ( // ntifs
  255. IN PVOID PoolBlock, // ntifs
  256. OUT PBOOLEAN QuotaCharged // ntifs
  257. ); // ntifs
  258. // end_ntosp
  259. NTKERNELAPI
  260. VOID
  261. ExQueryPoolUsage(
  262. OUT PULONG PagedPoolPages,
  263. OUT PULONG NonPagedPoolPages,
  264. OUT PULONG PagedPoolAllocs,
  265. OUT PULONG PagedPoolFrees,
  266. OUT PULONG PagedPoolLookasideHits,
  267. OUT PULONG NonPagedPoolAllocs,
  268. OUT PULONG NonPagedPoolFrees,
  269. OUT PULONG NonPagedPoolLookasideHits
  270. );
  271. VOID
  272. ExReturnPoolQuota (
  273. IN PVOID P
  274. );
  275. #if DBG || (i386 && !FPO)
  276. NTKERNELAPI
  277. NTSTATUS
  278. ExSnapShotPool(
  279. IN POOL_TYPE PoolType,
  280. IN PSYSTEM_POOL_INFORMATION PoolInformation,
  281. IN ULONG Length,
  282. OUT PULONG ReturnLength OPTIONAL
  283. );
  284. #endif // DBG || (i386 && !FPO)
  285. // begin_ntifs begin_ntddk begin_wdm begin_nthal begin_ntosp
  286. //
  287. // Routines to support fast mutexes.
  288. //
  289. typedef struct _FAST_MUTEX {
  290. LONG Count;
  291. PKTHREAD Owner;
  292. ULONG Contention;
  293. KEVENT Event;
  294. ULONG OldIrql;
  295. } FAST_MUTEX, *PFAST_MUTEX;
  296. #define ExInitializeFastMutex(_FastMutex) \
  297. (_FastMutex)->Count = 1; \
  298. (_FastMutex)->Owner = NULL; \
  299. (_FastMutex)->Contention = 0; \
  300. KeInitializeEvent(&(_FastMutex)->Event, \
  301. SynchronizationEvent, \
  302. FALSE);
  303. NTKERNELAPI
  304. VOID
  305. FASTCALL
  306. ExAcquireFastMutexUnsafe (
  307. IN PFAST_MUTEX FastMutex
  308. );
  309. NTKERNELAPI
  310. VOID
  311. FASTCALL
  312. ExReleaseFastMutexUnsafe (
  313. IN PFAST_MUTEX FastMutex
  314. );
  315. #if defined(_ALPHA_) || defined(_IA64_) || defined(_AMD64_)
  316. NTKERNELAPI
  317. VOID
  318. FASTCALL
  319. ExAcquireFastMutex (
  320. IN PFAST_MUTEX FastMutex
  321. );
  322. NTKERNELAPI
  323. VOID
  324. FASTCALL
  325. ExReleaseFastMutex (
  326. IN PFAST_MUTEX FastMutex
  327. );
  328. NTKERNELAPI
  329. BOOLEAN
  330. FASTCALL
  331. ExTryToAcquireFastMutex (
  332. IN PFAST_MUTEX FastMutex
  333. );
  334. #elif defined(_X86_)
  335. NTHALAPI
  336. VOID
  337. FASTCALL
  338. ExAcquireFastMutex (
  339. IN PFAST_MUTEX FastMutex
  340. );
  341. NTHALAPI
  342. VOID
  343. FASTCALL
  344. ExReleaseFastMutex (
  345. IN PFAST_MUTEX FastMutex
  346. );
  347. NTHALAPI
  348. BOOLEAN
  349. FASTCALL
  350. ExTryToAcquireFastMutex (
  351. IN PFAST_MUTEX FastMutex
  352. );
  353. #else
  354. #error "Target architecture not defined"
  355. #endif
  356. // end_ntifs end_ntddk end_wdm end_nthal end_ntosp
  357. #define ExIsFastMutexOwned(_FastMutex) ((_FastMutex)->Count != 1)
  358. //
  359. // Interlocked support routine definitions.
  360. //
  361. // begin_ntddk begin_wdm begin_nthal begin_ntifs begin_ntndis begin_ntosp
  362. //
  363. NTKERNELAPI
  364. VOID
  365. FASTCALL
  366. ExInterlockedAddLargeStatistic (
  367. IN PLARGE_INTEGER Addend,
  368. IN ULONG Increment
  369. );
  370. // end_ntndis
  371. NTKERNELAPI
  372. LARGE_INTEGER
  373. ExInterlockedAddLargeInteger (
  374. IN PLARGE_INTEGER Addend,
  375. IN LARGE_INTEGER Increment,
  376. IN PKSPIN_LOCK Lock
  377. );
  378. // end_ntddk end_wdm end_nthal end_ntifs end_ntosp
  379. #if defined(NT_UP) && !defined(_NTHAL_) && !defined(_NTDDK_) && !defined(_NTIFS_)
  380. #undef ExInterlockedAddUlong
  381. #define ExInterlockedAddUlong(x, y, z) InterlockedExchangeAdd((PLONG)(x), (LONG)(y))
  382. #else
  383. // begin_wdm begin_ntddk begin_nthal begin_ntifs begin_ntosp
  384. NTKERNELAPI
  385. ULONG
  386. FASTCALL
  387. ExInterlockedAddUlong (
  388. IN PULONG Addend,
  389. IN ULONG Increment,
  390. IN PKSPIN_LOCK Lock
  391. );
  392. // end_wdm end_ntddk end_nthal end_ntifs end_ntosp
  393. #endif
  394. // begin_wdm begin_ntddk begin_nthal begin_ntifs begin_ntosp
  395. #if defined(_AMD64_) || defined(_AXP64_) || defined(_IA64_)
  396. #define ExInterlockedCompareExchange64(Destination, Exchange, Comperand, Lock) \
  397. InterlockedCompareExchange64(Destination, *(Exchange), *(Comperand))
  398. #elif defined(_ALPHA_)
  399. #define ExInterlockedCompareExchange64(Destination, Exchange, Comperand, Lock) \
  400. ExpInterlockedCompareExchange64(Destination, Exchange, Comperand)
  401. #else
  402. #define ExInterlockedCompareExchange64(Destination, Exchange, Comperand, Lock) \
  403. ExfInterlockedCompareExchange64(Destination, Exchange, Comperand)
  404. #endif
  405. NTKERNELAPI
  406. PLIST_ENTRY
  407. FASTCALL
  408. ExInterlockedInsertHeadList (
  409. IN PLIST_ENTRY ListHead,
  410. IN PLIST_ENTRY ListEntry,
  411. IN PKSPIN_LOCK Lock
  412. );
  413. NTKERNELAPI
  414. PLIST_ENTRY
  415. FASTCALL
  416. ExInterlockedInsertTailList (
  417. IN PLIST_ENTRY ListHead,
  418. IN PLIST_ENTRY ListEntry,
  419. IN PKSPIN_LOCK Lock
  420. );
  421. NTKERNELAPI
  422. PLIST_ENTRY
  423. FASTCALL
  424. ExInterlockedRemoveHeadList (
  425. IN PLIST_ENTRY ListHead,
  426. IN PKSPIN_LOCK Lock
  427. );
  428. NTKERNELAPI
  429. PSINGLE_LIST_ENTRY
  430. FASTCALL
  431. ExInterlockedPopEntryList (
  432. IN PSINGLE_LIST_ENTRY ListHead,
  433. IN PKSPIN_LOCK Lock
  434. );
  435. NTKERNELAPI
  436. PSINGLE_LIST_ENTRY
  437. FASTCALL
  438. ExInterlockedPushEntryList (
  439. IN PSINGLE_LIST_ENTRY ListHead,
  440. IN PSINGLE_LIST_ENTRY ListEntry,
  441. IN PKSPIN_LOCK Lock
  442. );
  443. // end_wdm end_ntddk end_nthal end_ntifs end_ntosp
  444. //
  445. // Define non-blocking interlocked queue functions.
  446. //
  447. // A non-blocking queue is a singly link list of queue entries with a
  448. // head pointer and a tail pointer. The head and tail pointers use
  449. // sequenced pointers as do next links in the entries themselves. The
  450. // queueing discipline is FIFO. New entries are inserted at the tail
  451. // of the list and current entries are removed from the front of the
  452. // list.
  453. //
  454. // Non-blocking queues require a descriptor for each entry in the queue.
  455. // A descriptor consists of a sequenced next pointer and a PVOID data
  456. // value. Descriptors for a queue must be preallocated and inserted in
  457. // an SLIST before calling the function to initialize a non-blocking
  458. // queue header. The SLIST should have as many entries as required for
  459. // the respective queue.
  460. //
  461. typedef struct _NBQUEUE_BLOCK {
  462. ULONG64 Next;
  463. ULONG64 Data;
  464. } NBQUEUE_BLOCK, *PNBQUEUE_BLOCK;
  465. PVOID
  466. ExInitializeNBQueueHead (
  467. IN PSLIST_HEADER SlistHead
  468. );
  469. BOOLEAN
  470. ExInsertTailNBQueue (
  471. IN PVOID Header,
  472. IN ULONG64 Value
  473. );
  474. BOOLEAN
  475. ExRemoveHeadNBQueue (
  476. IN PVOID Header,
  477. OUT PULONG64 Value
  478. );
  479. // begin_wdm begin_ntddk begin_nthal begin_ntifs begin_ntosp begin_ntndis
  480. //
  481. // Define interlocked sequenced listhead functions.
  482. //
  483. // A sequenced interlocked list is a singly linked list with a header that
  484. // contains the current depth and a sequence number. Each time an entry is
  485. // inserted or removed from the list the depth is updated and the sequence
  486. // number is incremented. This enables AMD64, IA64, and Pentium and later
  487. // machines to insert and remove from the list without the use of spinlocks.
  488. //
  489. #if !defined(_WINBASE_)
  490. /*++
  491. Routine Description:
  492. This function initializes a sequenced singly linked listhead.
  493. Arguments:
  494. SListHead - Supplies a pointer to a sequenced singly linked listhead.
  495. Return Value:
  496. None.
  497. --*/
  498. #if defined(_WIN64) && (defined(_NTDRIVER_) || defined(_NTDDK_) || defined(_NTIFS_) || defined(_NTHAL_) || defined(_NTOSP_))
  499. NTKERNELAPI
  500. VOID
  501. InitializeSListHead (
  502. IN PSLIST_HEADER SListHead
  503. );
  504. #else
  505. __inline
  506. VOID
  507. InitializeSListHead (
  508. IN PSLIST_HEADER SListHead
  509. )
  510. {
  511. #ifdef _WIN64
  512. //
  513. // Slist headers must be 16 byte aligned.
  514. //
  515. if ((ULONG_PTR) SListHead & 0x0f) {
  516. DbgPrint( "InitializeSListHead unaligned Slist header. Address = %p, Caller = %p\n", SListHead, _ReturnAddress());
  517. RtlRaiseStatus(STATUS_DATATYPE_MISALIGNMENT);
  518. }
  519. #endif
  520. SListHead->Alignment = 0;
  521. //
  522. // For IA-64 we save the region number of the elements of the list in a
  523. // separate field. This imposes the requirement that all elements stored
  524. // in the list are from the same region.
  525. #if defined(_IA64_)
  526. SListHead->Region = (ULONG_PTR)SListHead & VRN_MASK;
  527. #elif defined(_AMD64_)
  528. SListHead->Region = 0;
  529. #endif
  530. return;
  531. }
  532. #endif
  533. #endif // !defined(_WINBASE_)
  534. #define ExInitializeSListHead InitializeSListHead
  535. PSLIST_ENTRY
  536. FirstEntrySList (
  537. IN const SLIST_HEADER *SListHead
  538. );
  539. /*++
  540. Routine Description:
  541. This function queries the current number of entries contained in a
  542. sequenced single linked list.
  543. Arguments:
  544. SListHead - Supplies a pointer to the sequenced listhead which is
  545. be queried.
  546. Return Value:
  547. The current number of entries in the sequenced singly linked list is
  548. returned as the function value.
  549. --*/
  550. #if defined(_WIN64)
  551. #if (defined(_NTDRIVER_) || defined(_NTDDK_) || defined(_NTIFS_) || defined(_NTHAL_) || defined(_NTOSP_))
  552. NTKERNELAPI
  553. USHORT
  554. ExQueryDepthSList (
  555. IN PSLIST_HEADER SListHead
  556. );
  557. #else
  558. __inline
  559. USHORT
  560. ExQueryDepthSList (
  561. IN PSLIST_HEADER SListHead
  562. )
  563. {
  564. return (USHORT)(SListHead->Alignment & 0xffff);
  565. }
  566. #endif
  567. #else
  568. #define ExQueryDepthSList(_listhead_) (_listhead_)->Depth
  569. #endif
  570. #if defined(_WIN64)
  571. #define ExInterlockedPopEntrySList(Head, Lock) \
  572. ExpInterlockedPopEntrySList(Head)
  573. #define ExInterlockedPushEntrySList(Head, Entry, Lock) \
  574. ExpInterlockedPushEntrySList(Head, Entry)
  575. #define ExInterlockedFlushSList(Head) \
  576. ExpInterlockedFlushSList(Head)
  577. #if !defined(_WINBASE_)
  578. #define InterlockedPopEntrySList(Head) \
  579. ExpInterlockedPopEntrySList(Head)
  580. #define InterlockedPushEntrySList(Head, Entry) \
  581. ExpInterlockedPushEntrySList(Head, Entry)
  582. #define InterlockedFlushSList(Head) \
  583. ExpInterlockedFlushSList(Head)
  584. #define QueryDepthSList(Head) \
  585. ExQueryDepthSList(Head)
  586. #endif // !defined(_WINBASE_)
  587. NTKERNELAPI
  588. PSLIST_ENTRY
  589. ExpInterlockedPopEntrySList (
  590. IN PSLIST_HEADER ListHead
  591. );
  592. NTKERNELAPI
  593. PSLIST_ENTRY
  594. ExpInterlockedPushEntrySList (
  595. IN PSLIST_HEADER ListHead,
  596. IN PSLIST_ENTRY ListEntry
  597. );
  598. NTKERNELAPI
  599. PSLIST_ENTRY
  600. ExpInterlockedFlushSList (
  601. IN PSLIST_HEADER ListHead
  602. );
  603. #else
  604. #if defined(_WIN2K_COMPAT_SLIST_USAGE) && defined(_X86_)
  605. NTKERNELAPI
  606. PSLIST_ENTRY
  607. FASTCALL
  608. ExInterlockedPopEntrySList (
  609. IN PSLIST_HEADER ListHead,
  610. IN PKSPIN_LOCK Lock
  611. );
  612. NTKERNELAPI
  613. PSLIST_ENTRY
  614. FASTCALL
  615. ExInterlockedPushEntrySList (
  616. IN PSLIST_HEADER ListHead,
  617. IN PSLIST_ENTRY ListEntry,
  618. IN PKSPIN_LOCK Lock
  619. );
  620. #else
  621. #define ExInterlockedPopEntrySList(ListHead, Lock) \
  622. InterlockedPopEntrySList(ListHead)
  623. #define ExInterlockedPushEntrySList(ListHead, ListEntry, Lock) \
  624. InterlockedPushEntrySList(ListHead, ListEntry)
  625. #endif
  626. NTKERNELAPI
  627. PSLIST_ENTRY
  628. FASTCALL
  629. ExInterlockedFlushSList (
  630. IN PSLIST_HEADER ListHead
  631. );
  632. #if !defined(_WINBASE_)
  633. NTKERNELAPI
  634. PSLIST_ENTRY
  635. FASTCALL
  636. InterlockedPopEntrySList (
  637. IN PSLIST_HEADER ListHead
  638. );
  639. NTKERNELAPI
  640. PSLIST_ENTRY
  641. FASTCALL
  642. InterlockedPushEntrySList (
  643. IN PSLIST_HEADER ListHead,
  644. IN PSLIST_ENTRY ListEntry
  645. );
  646. #define InterlockedFlushSList(Head) \
  647. ExInterlockedFlushSList(Head)
  648. #define QueryDepthSList(Head) \
  649. ExQueryDepthSList(Head)
  650. #endif // !defined(_WINBASE_)
  651. #endif // defined(_WIN64)
  652. // end_ntddk end_wdm end_ntosp
  653. PSLIST_ENTRY
  654. FASTCALL
  655. InterlockedPushListSList (
  656. IN PSLIST_HEADER ListHead,
  657. IN PSLIST_ENTRY List,
  658. IN PSLIST_ENTRY ListEnd,
  659. IN ULONG Count
  660. );
  661. //
  662. // Define interlocked lookaside list structure and allocation functions.
  663. //
  664. VOID
  665. ExAdjustLookasideDepth (
  666. VOID
  667. );
  668. // begin_ntddk begin_wdm begin_ntosp
  669. typedef
  670. PVOID
  671. (*PALLOCATE_FUNCTION) (
  672. IN POOL_TYPE PoolType,
  673. IN SIZE_T NumberOfBytes,
  674. IN ULONG Tag
  675. );
  676. typedef
  677. VOID
  678. (*PFREE_FUNCTION) (
  679. IN PVOID Buffer
  680. );
  681. #if !defined(_WIN64) && (defined(_NTDDK_) || defined(_NTIFS_) || defined(_NDIS_))
  682. typedef struct _GENERAL_LOOKASIDE {
  683. #else
  684. typedef struct DECLSPEC_CACHEALIGN _GENERAL_LOOKASIDE {
  685. #endif
  686. SLIST_HEADER ListHead;
  687. USHORT Depth;
  688. USHORT MaximumDepth;
  689. ULONG TotalAllocates;
  690. union {
  691. ULONG AllocateMisses;
  692. ULONG AllocateHits;
  693. };
  694. ULONG TotalFrees;
  695. union {
  696. ULONG FreeMisses;
  697. ULONG FreeHits;
  698. };
  699. POOL_TYPE Type;
  700. ULONG Tag;
  701. ULONG Size;
  702. PALLOCATE_FUNCTION Allocate;
  703. PFREE_FUNCTION Free;
  704. LIST_ENTRY ListEntry;
  705. ULONG LastTotalAllocates;
  706. union {
  707. ULONG LastAllocateMisses;
  708. ULONG LastAllocateHits;
  709. };
  710. ULONG Future[2];
  711. } GENERAL_LOOKASIDE, *PGENERAL_LOOKASIDE;
  712. #if !defined(_WIN64) && (defined(_NTDDK_) || defined(_NTIFS_) || defined(_NDIS_))
  713. typedef struct _NPAGED_LOOKASIDE_LIST {
  714. #else
  715. typedef struct DECLSPEC_CACHEALIGN _NPAGED_LOOKASIDE_LIST {
  716. #endif
  717. GENERAL_LOOKASIDE L;
  718. #if !defined(_AMD64_) && !defined(_IA64_)
  719. KSPIN_LOCK Lock__ObsoleteButDoNotDelete;
  720. #endif
  721. } NPAGED_LOOKASIDE_LIST, *PNPAGED_LOOKASIDE_LIST;
  722. NTKERNELAPI
  723. VOID
  724. ExInitializeNPagedLookasideList (
  725. IN PNPAGED_LOOKASIDE_LIST Lookaside,
  726. IN PALLOCATE_FUNCTION Allocate,
  727. IN PFREE_FUNCTION Free,
  728. IN ULONG Flags,
  729. IN SIZE_T Size,
  730. IN ULONG Tag,
  731. IN USHORT Depth
  732. );
  733. NTKERNELAPI
  734. VOID
  735. ExDeleteNPagedLookasideList (
  736. IN PNPAGED_LOOKASIDE_LIST Lookaside
  737. );
  738. __inline
  739. PVOID
  740. ExAllocateFromNPagedLookasideList(
  741. IN PNPAGED_LOOKASIDE_LIST Lookaside
  742. )
  743. /*++
  744. Routine Description:
  745. This function removes (pops) the first entry from the specified
  746. nonpaged lookaside list.
  747. Arguments:
  748. Lookaside - Supplies a pointer to a nonpaged lookaside list structure.
  749. Return Value:
  750. If an entry is removed from the specified lookaside list, then the
  751. address of the entry is returned as the function value. Otherwise,
  752. NULL is returned.
  753. --*/
  754. {
  755. PVOID Entry;
  756. Lookaside->L.TotalAllocates += 1;
  757. #if defined(_WIN2K_COMPAT_SLIST_USAGE) && defined(_X86_)
  758. Entry = ExInterlockedPopEntrySList(&Lookaside->L.ListHead,
  759. &Lookaside->Lock__ObsoleteButDoNotDelete);
  760. #else
  761. Entry = InterlockedPopEntrySList(&Lookaside->L.ListHead);
  762. #endif
  763. if (Entry == NULL) {
  764. Lookaside->L.AllocateMisses += 1;
  765. Entry = (Lookaside->L.Allocate)(Lookaside->L.Type,
  766. Lookaside->L.Size,
  767. Lookaside->L.Tag);
  768. }
  769. return Entry;
  770. }
  771. __inline
  772. VOID
  773. ExFreeToNPagedLookasideList(
  774. IN PNPAGED_LOOKASIDE_LIST Lookaside,
  775. IN PVOID Entry
  776. )
  777. /*++
  778. Routine Description:
  779. This function inserts (pushes) the specified entry into the specified
  780. nonpaged lookaside list.
  781. Arguments:
  782. Lookaside - Supplies a pointer to a nonpaged lookaside list structure.
  783. Entry - Supples a pointer to the entry that is inserted in the
  784. lookaside list.
  785. Return Value:
  786. None.
  787. --*/
  788. {
  789. Lookaside->L.TotalFrees += 1;
  790. if (ExQueryDepthSList(&Lookaside->L.ListHead) >= Lookaside->L.Depth) {
  791. Lookaside->L.FreeMisses += 1;
  792. (Lookaside->L.Free)(Entry);
  793. } else {
  794. #if defined(_WIN2K_COMPAT_SLIST_USAGE) && defined(_X86_)
  795. ExInterlockedPushEntrySList(&Lookaside->L.ListHead,
  796. (PSLIST_ENTRY)Entry,
  797. &Lookaside->Lock__ObsoleteButDoNotDelete);
  798. #else
  799. InterlockedPushEntrySList(&Lookaside->L.ListHead,
  800. (PSLIST_ENTRY)Entry);
  801. #endif
  802. }
  803. return;
  804. }
  805. // end_ntndis
  806. #if !defined(_WIN64) && (defined(_NTDDK_) || defined(_NTIFS_) || defined(_NDIS_))
  807. typedef struct _PAGED_LOOKASIDE_LIST {
  808. #else
  809. typedef struct DECLSPEC_CACHEALIGN _PAGED_LOOKASIDE_LIST {
  810. #endif
  811. GENERAL_LOOKASIDE L;
  812. #if !defined(_AMD64_) && !defined(_IA64_)
  813. FAST_MUTEX Lock__ObsoleteButDoNotDelete;
  814. #endif
  815. } PAGED_LOOKASIDE_LIST, *PPAGED_LOOKASIDE_LIST;
  816. // end_ntddk end_wdm end_nthal end_ntifs end_ntosp
  817. //
  818. // N.B. Nonpaged lookaside list structures and pages lookaside list
  819. // structures MUST be the same size for the system itself. The
  820. // per-processor lookaside lists for small pool and I/O are
  821. // allocated with one allocation.
  822. //
  823. #if defined(_WIN64) || (!defined(_NTDDK_) && !defined(_NTIFS_) && !defined(_NDIS_))
  824. C_ASSERT(sizeof(NPAGED_LOOKASIDE_LIST) == sizeof(PAGED_LOOKASIDE_LIST));
  825. #endif
  826. // begin_ntddk begin_wdm begin_nthal begin_ntifs begin_ntosp
  827. NTKERNELAPI
  828. VOID
  829. ExInitializePagedLookasideList (
  830. IN PPAGED_LOOKASIDE_LIST Lookaside,
  831. IN PALLOCATE_FUNCTION Allocate,
  832. IN PFREE_FUNCTION Free,
  833. IN ULONG Flags,
  834. IN SIZE_T Size,
  835. IN ULONG Tag,
  836. IN USHORT Depth
  837. );
  838. NTKERNELAPI
  839. VOID
  840. ExDeletePagedLookasideList (
  841. IN PPAGED_LOOKASIDE_LIST Lookaside
  842. );
  843. #if defined(_WIN2K_COMPAT_SLIST_USAGE) && defined(_X86_)
  844. NTKERNELAPI
  845. PVOID
  846. ExAllocateFromPagedLookasideList(
  847. IN PPAGED_LOOKASIDE_LIST Lookaside
  848. );
  849. #else
  850. __inline
  851. PVOID
  852. ExAllocateFromPagedLookasideList(
  853. IN PPAGED_LOOKASIDE_LIST Lookaside
  854. )
  855. /*++
  856. Routine Description:
  857. This function removes (pops) the first entry from the specified
  858. paged lookaside list.
  859. Arguments:
  860. Lookaside - Supplies a pointer to a paged lookaside list structure.
  861. Return Value:
  862. If an entry is removed from the specified lookaside list, then the
  863. address of the entry is returned as the function value. Otherwise,
  864. NULL is returned.
  865. --*/
  866. {
  867. PVOID Entry;
  868. Lookaside->L.TotalAllocates += 1;
  869. Entry = InterlockedPopEntrySList(&Lookaside->L.ListHead);
  870. if (Entry == NULL) {
  871. Lookaside->L.AllocateMisses += 1;
  872. Entry = (Lookaside->L.Allocate)(Lookaside->L.Type,
  873. Lookaside->L.Size,
  874. Lookaside->L.Tag);
  875. }
  876. return Entry;
  877. }
  878. #endif
  879. #if defined(_WIN2K_COMPAT_SLIST_USAGE) && defined(_X86_)
  880. NTKERNELAPI
  881. VOID
  882. ExFreeToPagedLookasideList(
  883. IN PPAGED_LOOKASIDE_LIST Lookaside,
  884. IN PVOID Entry
  885. );
  886. #else
  887. __inline
  888. VOID
  889. ExFreeToPagedLookasideList(
  890. IN PPAGED_LOOKASIDE_LIST Lookaside,
  891. IN PVOID Entry
  892. )
  893. /*++
  894. Routine Description:
  895. This function inserts (pushes) the specified entry into the specified
  896. paged lookaside list.
  897. Arguments:
  898. Lookaside - Supplies a pointer to a nonpaged lookaside list structure.
  899. Entry - Supples a pointer to the entry that is inserted in the
  900. lookaside list.
  901. Return Value:
  902. None.
  903. --*/
  904. {
  905. Lookaside->L.TotalFrees += 1;
  906. if (ExQueryDepthSList(&Lookaside->L.ListHead) >= Lookaside->L.Depth) {
  907. Lookaside->L.FreeMisses += 1;
  908. (Lookaside->L.Free)(Entry);
  909. } else {
  910. InterlockedPushEntrySList(&Lookaside->L.ListHead,
  911. (PSLIST_ENTRY)Entry);
  912. }
  913. return;
  914. }
  915. #endif
  916. // end_ntddk end_nthal end_ntifs end_wdm end_ntosp
  917. VOID
  918. ExInitializeSystemLookasideList (
  919. IN PGENERAL_LOOKASIDE Lookaside,
  920. IN POOL_TYPE Type,
  921. IN ULONG Size,
  922. IN ULONG Tag,
  923. IN USHORT Depth,
  924. IN PLIST_ENTRY ListHead
  925. );
  926. //
  927. // Define per processor nonpage lookaside list structures.
  928. //
  929. typedef enum _PP_NPAGED_LOOKASIDE_NUMBER {
  930. LookasideSmallIrpList,
  931. LookasideLargeIrpList,
  932. LookasideMdlList,
  933. LookasideCreateInfoList,
  934. LookasideNameBufferList,
  935. LookasideTwilightList,
  936. LookasideCompletionList,
  937. LookasideMaximumList
  938. } PP_NPAGED_LOOKASIDE_NUMBER, *PPP_NPAGED_LOOKASIDE_NUMBER;
  939. #if !defined(_CROSS_PLATFORM_)
  940. FORCEINLINE
  941. PVOID
  942. ExAllocateFromPPLookasideList (
  943. IN PP_NPAGED_LOOKASIDE_NUMBER Number
  944. )
  945. /*++
  946. Routine Description:
  947. This function removes (pops) the first entry from the specified per
  948. processor lookaside list.
  949. N.B. It is possible to context switch during the allocation from a
  950. per processor nonpaged lookaside list, but this should happen
  951. infrequently and should not aversely effect the benefits of
  952. per processor lookaside lists.
  953. Arguments:
  954. Number - Supplies the per processor nonpaged lookaside list number.
  955. Return Value:
  956. If an entry is removed from the specified lookaside list, then the
  957. address of the entry is returned as the function value. Otherwise,
  958. NULL is returned.
  959. --*/
  960. {
  961. PVOID Entry;
  962. PGENERAL_LOOKASIDE Lookaside;
  963. PKPRCB Prcb;
  964. ASSERT((Number >= 0) && (Number < LookasideMaximumList));
  965. //
  966. // Attempt to allocate from the per processor lookaside list.
  967. //
  968. Prcb = KeGetCurrentPrcb();
  969. Lookaside = Prcb->PPLookasideList[Number].P;
  970. Lookaside->TotalAllocates += 1;
  971. Entry = InterlockedPopEntrySList(&Lookaside->ListHead);
  972. //
  973. // If the per processor allocation attempt failed, then attempt to
  974. // allocate from the system lookaside list.
  975. //
  976. if (Entry == NULL) {
  977. Lookaside->AllocateMisses += 1;
  978. Lookaside = Prcb->PPLookasideList[Number].L;
  979. Lookaside->TotalAllocates += 1;
  980. Entry = InterlockedPopEntrySList(&Lookaside->ListHead);
  981. if (Entry == NULL) {
  982. Lookaside->AllocateMisses += 1;
  983. Entry = (Lookaside->Allocate)(Lookaside->Type,
  984. Lookaside->Size,
  985. Lookaside->Tag);
  986. }
  987. }
  988. return Entry;
  989. }
  990. FORCEINLINE
  991. VOID
  992. ExFreeToPPLookasideList (
  993. IN PP_NPAGED_LOOKASIDE_NUMBER Number,
  994. IN PVOID Entry
  995. )
  996. /*++
  997. Routine Description:
  998. This function inserts (pushes) the specified entry into the specified
  999. per processor lookaside list.
  1000. N.B. It is possible to context switch during the free of a per
  1001. processor nonpaged lookaside list, but this should happen
  1002. infrequently and should not aversely effect the benefits of
  1003. per processor lookaside lists.
  1004. Arguments:
  1005. Number - Supplies the per processor nonpaged lookaside list number.
  1006. Entry - Supples a pointer to the entry that is inserted in the per
  1007. processor lookaside list.
  1008. Return Value:
  1009. None.
  1010. --*/
  1011. {
  1012. PGENERAL_LOOKASIDE Lookaside;
  1013. PKPRCB Prcb;
  1014. ASSERT((Number >= 0) && (Number < LookasideMaximumList));
  1015. //
  1016. // If the current depth is less than of equal to the maximum depth, then
  1017. // free the specified entry to the per processor lookaside list. Otherwise,
  1018. // free the entry to the system lookaside list;
  1019. //
  1020. //
  1021. Prcb = KeGetCurrentPrcb();
  1022. Lookaside = Prcb->PPLookasideList[Number].P;
  1023. Lookaside->TotalFrees += 1;
  1024. if (ExQueryDepthSList(&Lookaside->ListHead) >= Lookaside->Depth) {
  1025. Lookaside->FreeMisses += 1;
  1026. Lookaside = Prcb->PPLookasideList[Number].L;
  1027. Lookaside->TotalFrees += 1;
  1028. if (ExQueryDepthSList(&Lookaside->ListHead) >= Lookaside->Depth) {
  1029. Lookaside->FreeMisses += 1;
  1030. (Lookaside->Free)(Entry);
  1031. return;
  1032. }
  1033. }
  1034. InterlockedPushEntrySList(&Lookaside->ListHead,
  1035. (PSINGLE_LIST_ENTRY)Entry);
  1036. return;
  1037. }
  1038. #endif
  1039. #if i386 && !FPO
  1040. NTSTATUS
  1041. ExQuerySystemBackTraceInformation(
  1042. OUT PRTL_PROCESS_BACKTRACES BackTraceInformation,
  1043. IN ULONG BackTraceInformationLength,
  1044. OUT PULONG ReturnLength OPTIONAL
  1045. );
  1046. NTKERNELAPI
  1047. USHORT
  1048. ExGetPoolBackTraceIndex(
  1049. IN PVOID P
  1050. );
  1051. #endif // i386 && !FPO
  1052. NTKERNELAPI
  1053. NTSTATUS
  1054. ExLockUserBuffer(
  1055. IN PVOID Buffer,
  1056. IN ULONG Length,
  1057. OUT PVOID *LockedBuffer,
  1058. OUT PVOID *LockVariable
  1059. );
  1060. NTKERNELAPI
  1061. VOID
  1062. ExUnlockUserBuffer(
  1063. IN PVOID LockVariable
  1064. );
  1065. // begin_ntddk begin_wdm begin_ntifs begin_ntosp
  1066. NTKERNELAPI
  1067. VOID
  1068. NTAPI
  1069. ProbeForRead(
  1070. IN CONST VOID *Address,
  1071. IN SIZE_T Length,
  1072. IN ULONG Alignment
  1073. );
  1074. // end_ntddk end_wdm end_ntifs end_ntosp
  1075. #if !defined(_NTHAL_) && !defined(_NTDDK_) && !defined(_NTIFS_)
  1076. // begin_ntosp
  1077. // Probe function definitions
  1078. //
  1079. // Probe for read functions.
  1080. //
  1081. //++
  1082. //
  1083. // VOID
  1084. // ProbeForRead(
  1085. // IN PVOID Address,
  1086. // IN ULONG Length,
  1087. // IN ULONG Alignment
  1088. // )
  1089. //
  1090. //--
  1091. #define ProbeForRead(Address, Length, Alignment) \
  1092. ASSERT(((Alignment) == 1) || ((Alignment) == 2) || \
  1093. ((Alignment) == 4) || ((Alignment) == 8) || \
  1094. ((Alignment) == 16)); \
  1095. \
  1096. if ((Length) != 0) { \
  1097. if (((ULONG_PTR)(Address) & ((Alignment) - 1)) != 0) { \
  1098. ExRaiseDatatypeMisalignment(); \
  1099. \
  1100. } \
  1101. if ((((ULONG_PTR)(Address) + (Length)) < (ULONG_PTR)(Address)) || \
  1102. (((ULONG_PTR)(Address) + (Length)) > (ULONG_PTR)MM_USER_PROBE_ADDRESS)) { \
  1103. ExRaiseAccessViolation(); \
  1104. } \
  1105. }
  1106. //++
  1107. //
  1108. // VOID
  1109. // ProbeForReadSmallStructure(
  1110. // IN PVOID Address,
  1111. // IN ULONG Length,
  1112. // IN ULONG Alignment
  1113. // )
  1114. //
  1115. //--
  1116. #define ProbeForReadSmallStructure(Address,Size,Alignment) { \
  1117. ASSERT(((Alignment) == 1) || ((Alignment) == 2) || \
  1118. ((Alignment) == 4) || ((Alignment) == 8) || \
  1119. ((Alignment) == 16)); \
  1120. if (Size == 0 || Size > 0x10000) { \
  1121. ASSERT (0); \
  1122. ProbeForRead (Address,Size,Alignment); \
  1123. } else { \
  1124. if (((ULONG_PTR)(Address) & ((Alignment) - 1)) != 0) { \
  1125. ExRaiseDatatypeMisalignment(); \
  1126. } \
  1127. if ((ULONG_PTR)(Address) >= (ULONG_PTR)MM_USER_PROBE_ADDRESS) { \
  1128. *(volatile ULONG * const)MM_USER_PROBE_ADDRESS = 0; \
  1129. } \
  1130. } \
  1131. }
  1132. // end_ntosp
  1133. #endif
  1134. // begin_ntosp
  1135. //++
  1136. //
  1137. // BOOLEAN
  1138. // ProbeAndReadBoolean(
  1139. // IN PBOOLEAN Address
  1140. // )
  1141. //
  1142. //--
  1143. #define ProbeAndReadBoolean(Address) \
  1144. (((Address) >= (BOOLEAN * const)MM_USER_PROBE_ADDRESS) ? \
  1145. (*(volatile BOOLEAN * const)MM_USER_PROBE_ADDRESS) : (*(volatile BOOLEAN *)(Address)))
  1146. //++
  1147. //
  1148. // CHAR
  1149. // ProbeAndReadChar(
  1150. // IN PCHAR Address
  1151. // )
  1152. //
  1153. //--
  1154. #define ProbeAndReadChar(Address) \
  1155. (((Address) >= (CHAR * const)MM_USER_PROBE_ADDRESS) ? \
  1156. (*(volatile CHAR * const)MM_USER_PROBE_ADDRESS) : (*(volatile CHAR *)(Address)))
  1157. //++
  1158. //
  1159. // UCHAR
  1160. // ProbeAndReadUchar(
  1161. // IN PUCHAR Address
  1162. // )
  1163. //
  1164. //--
  1165. #define ProbeAndReadUchar(Address) \
  1166. (((Address) >= (UCHAR * const)MM_USER_PROBE_ADDRESS) ? \
  1167. (*(volatile UCHAR * const)MM_USER_PROBE_ADDRESS) : (*(volatile UCHAR *)(Address)))
  1168. //++
  1169. //
  1170. // SHORT
  1171. // ProbeAndReadShort(
  1172. // IN PSHORT Address
  1173. // )
  1174. //
  1175. //--
  1176. #define ProbeAndReadShort(Address) \
  1177. (((Address) >= (SHORT * const)MM_USER_PROBE_ADDRESS) ? \
  1178. (*(volatile SHORT * const)MM_USER_PROBE_ADDRESS) : (*(volatile SHORT *)(Address)))
  1179. //++
  1180. //
  1181. // USHORT
  1182. // ProbeAndReadUshort(
  1183. // IN PUSHORT Address
  1184. // )
  1185. //
  1186. //--
  1187. #define ProbeAndReadUshort(Address) \
  1188. (((Address) >= (USHORT * const)MM_USER_PROBE_ADDRESS) ? \
  1189. (*(volatile USHORT * const)MM_USER_PROBE_ADDRESS) : (*(volatile USHORT *)(Address)))
  1190. //++
  1191. //
  1192. // HANDLE
  1193. // ProbeAndReadHandle(
  1194. // IN PHANDLE Address
  1195. // )
  1196. //
  1197. //--
  1198. #define ProbeAndReadHandle(Address) \
  1199. (((Address) >= (HANDLE * const)MM_USER_PROBE_ADDRESS) ? \
  1200. (*(volatile HANDLE * const)MM_USER_PROBE_ADDRESS) : (*(volatile HANDLE *)(Address)))
  1201. //++
  1202. //
  1203. // PVOID
  1204. // ProbeAndReadPointer(
  1205. // IN PVOID *Address
  1206. // )
  1207. //
  1208. //--
  1209. #define ProbeAndReadPointer(Address) \
  1210. (((Address) >= (PVOID * const)MM_USER_PROBE_ADDRESS) ? \
  1211. (*(volatile PVOID * const)MM_USER_PROBE_ADDRESS) : (*(volatile PVOID *)(Address)))
  1212. //++
  1213. //
  1214. // LONG
  1215. // ProbeAndReadLong(
  1216. // IN PLONG Address
  1217. // )
  1218. //
  1219. //--
  1220. #define ProbeAndReadLong(Address) \
  1221. (((Address) >= (LONG * const)MM_USER_PROBE_ADDRESS) ? \
  1222. (*(volatile LONG * const)MM_USER_PROBE_ADDRESS) : (*(volatile LONG *)(Address)))
  1223. //++
  1224. //
  1225. // ULONG
  1226. // ProbeAndReadUlong(
  1227. // IN PULONG Address
  1228. // )
  1229. //
  1230. //--
  1231. #define ProbeAndReadUlong(Address) \
  1232. (((Address) >= (ULONG * const)MM_USER_PROBE_ADDRESS) ? \
  1233. (*(volatile ULONG * const)MM_USER_PROBE_ADDRESS) : (*(volatile ULONG *)(Address)))
  1234. //++
  1235. //
  1236. // ULONG_PTR
  1237. // ProbeAndReadUlong_ptr(
  1238. // IN PULONG_PTR Address
  1239. // )
  1240. //
  1241. //--
  1242. #define ProbeAndReadUlong_ptr(Address) \
  1243. (((Address) >= (ULONG_PTR * const)MM_USER_PROBE_ADDRESS) ? \
  1244. (*(volatile ULONG_PTR * const)MM_USER_PROBE_ADDRESS) : (*(volatile ULONG_PTR *)(Address)))
  1245. //++
  1246. //
  1247. // QUAD
  1248. // ProbeAndReadQuad(
  1249. // IN PQUAD Address
  1250. // )
  1251. //
  1252. //--
  1253. #define ProbeAndReadQuad(Address) \
  1254. (((Address) >= (QUAD * const)MM_USER_PROBE_ADDRESS) ? \
  1255. (*(volatile QUAD * const)MM_USER_PROBE_ADDRESS) : (*(volatile QUAD *)(Address)))
  1256. //++
  1257. //
  1258. // UQUAD
  1259. // ProbeAndReadUquad(
  1260. // IN PUQUAD Address
  1261. // )
  1262. //
  1263. //--
  1264. #define ProbeAndReadUquad(Address) \
  1265. (((Address) >= (UQUAD * const)MM_USER_PROBE_ADDRESS) ? \
  1266. (*(volatile UQUAD * const)MM_USER_PROBE_ADDRESS) : (*(volatile UQUAD *)(Address)))
  1267. //++
  1268. //
  1269. // LARGE_INTEGER
  1270. // ProbeAndReadLargeInteger(
  1271. // IN PLARGE_INTEGER Source
  1272. // )
  1273. //
  1274. //--
  1275. #define ProbeAndReadLargeInteger(Source) \
  1276. (((Source) >= (LARGE_INTEGER * const)MM_USER_PROBE_ADDRESS) ? \
  1277. (*(volatile LARGE_INTEGER * const)MM_USER_PROBE_ADDRESS) : (*(volatile LARGE_INTEGER *)(Source)))
  1278. //++
  1279. //
  1280. // ULARGE_INTEGER
  1281. // ProbeAndReadUlargeInteger(
  1282. // IN PULARGE_INTEGER Source
  1283. // )
  1284. //
  1285. //--
  1286. #define ProbeAndReadUlargeInteger(Source) \
  1287. (((Source) >= (ULARGE_INTEGER * const)MM_USER_PROBE_ADDRESS) ? \
  1288. (*(volatile ULARGE_INTEGER * const)MM_USER_PROBE_ADDRESS) : (*(volatile ULARGE_INTEGER *)(Source)))
  1289. //++
  1290. //
  1291. // UNICODE_STRING
  1292. // ProbeAndReadUnicodeString(
  1293. // IN PUNICODE_STRING Source
  1294. // )
  1295. //
  1296. //--
  1297. #define ProbeAndReadUnicodeString(Source) \
  1298. (((Source) >= (UNICODE_STRING * const)MM_USER_PROBE_ADDRESS) ? \
  1299. (*(volatile UNICODE_STRING * const)MM_USER_PROBE_ADDRESS) : (*(volatile UNICODE_STRING *)(Source)))
  1300. //++
  1301. //
  1302. // <STRUCTURE>
  1303. // ProbeAndReadStructure(
  1304. // IN P<STRUCTURE> Source
  1305. // <STRUCTURE>
  1306. // )
  1307. //
  1308. //--
  1309. #define ProbeAndReadStructure(Source,STRUCTURE) \
  1310. (((Source) >= (STRUCTURE * const)MM_USER_PROBE_ADDRESS) ? \
  1311. (*(STRUCTURE * const)MM_USER_PROBE_ADDRESS) : (*(STRUCTURE *)(Source)))
  1312. //
  1313. // Probe for write functions definitions.
  1314. //
  1315. //++
  1316. //
  1317. // VOID
  1318. // ProbeForWriteBoolean(
  1319. // IN PBOOLEAN Address
  1320. // )
  1321. //
  1322. //--
  1323. #define ProbeForWriteBoolean(Address) { \
  1324. if ((Address) >= (BOOLEAN * const)MM_USER_PROBE_ADDRESS) { \
  1325. *(volatile BOOLEAN * const)MM_USER_PROBE_ADDRESS = 0; \
  1326. } \
  1327. \
  1328. *(volatile BOOLEAN *)(Address) = *(volatile BOOLEAN *)(Address); \
  1329. }
  1330. //++
  1331. //
  1332. // VOID
  1333. // ProbeForWriteChar(
  1334. // IN PCHAR Address
  1335. // )
  1336. //
  1337. //--
  1338. #define ProbeForWriteChar(Address) { \
  1339. if ((Address) >= (CHAR * const)MM_USER_PROBE_ADDRESS) { \
  1340. *(volatile CHAR * const)MM_USER_PROBE_ADDRESS = 0; \
  1341. } \
  1342. \
  1343. *(volatile CHAR *)(Address) = *(volatile CHAR *)(Address); \
  1344. }
  1345. //++
  1346. //
  1347. // VOID
  1348. // ProbeForWriteUchar(
  1349. // IN PUCHAR Address
  1350. // )
  1351. //
  1352. //--
  1353. #define ProbeForWriteUchar(Address) { \
  1354. if ((Address) >= (UCHAR * const)MM_USER_PROBE_ADDRESS) { \
  1355. *(volatile UCHAR * const)MM_USER_PROBE_ADDRESS = 0; \
  1356. } \
  1357. \
  1358. *(volatile UCHAR *)(Address) = *(volatile UCHAR *)(Address); \
  1359. }
  1360. //++
  1361. //
  1362. // VOID
  1363. // ProbeForWriteIoStatus(
  1364. // IN PIO_STATUS_BLOCK Address
  1365. // )
  1366. //
  1367. //--
  1368. #define ProbeForWriteIoStatus(Address) { \
  1369. if ((Address) >= (IO_STATUS_BLOCK * const)MM_USER_PROBE_ADDRESS) { \
  1370. *(volatile ULONG * const)MM_USER_PROBE_ADDRESS = 0; \
  1371. } \
  1372. \
  1373. *(volatile IO_STATUS_BLOCK *)(Address) = *(volatile IO_STATUS_BLOCK *)(Address); \
  1374. }
  1375. #ifdef _WIN64
  1376. #define ProbeForWriteIoStatusEx(Address, Cookie) { \
  1377. if ((Address) >= (IO_STATUS_BLOCK * const)MM_USER_PROBE_ADDRESS) { \
  1378. *(volatile ULONG * const)MM_USER_PROBE_ADDRESS = 0; \
  1379. } \
  1380. if ((ULONG_PTR)(Cookie) & (ULONG)1) { \
  1381. *(volatile IO_STATUS_BLOCK32 *)(Address) = *(volatile IO_STATUS_BLOCK32 *)(Address);\
  1382. } else { \
  1383. *(volatile IO_STATUS_BLOCK *)(Address) = *(volatile IO_STATUS_BLOCK *)(Address); \
  1384. } \
  1385. }
  1386. #else
  1387. #define ProbeForWriteIoStatusEx(Address, Cookie) ProbeForWriteIoStatus(Address)
  1388. #endif
  1389. //++
  1390. //
  1391. // VOID
  1392. // ProbeForWriteShort(
  1393. // IN PSHORT Address
  1394. // )
  1395. //
  1396. //--
  1397. #define ProbeForWriteShort(Address) { \
  1398. if ((Address) >= (SHORT * const)MM_USER_PROBE_ADDRESS) { \
  1399. *(volatile SHORT * const)MM_USER_PROBE_ADDRESS = 0; \
  1400. } \
  1401. \
  1402. *(volatile SHORT *)(Address) = *(volatile SHORT *)(Address); \
  1403. }
  1404. //++
  1405. //
  1406. // VOID
  1407. // ProbeForWriteUshort(
  1408. // IN PUSHORT Address
  1409. // )
  1410. //
  1411. //--
  1412. #define ProbeForWriteUshort(Address) { \
  1413. if ((Address) >= (USHORT * const)MM_USER_PROBE_ADDRESS) { \
  1414. *(volatile USHORT * const)MM_USER_PROBE_ADDRESS = 0; \
  1415. } \
  1416. \
  1417. *(volatile USHORT *)(Address) = *(volatile USHORT *)(Address); \
  1418. }
  1419. //++
  1420. //
  1421. // VOID
  1422. // ProbeForWriteHandle(
  1423. // IN PHANDLE Address
  1424. // )
  1425. //
  1426. //--
  1427. #define ProbeForWriteHandle(Address) { \
  1428. if ((Address) >= (HANDLE * const)MM_USER_PROBE_ADDRESS) { \
  1429. *(volatile HANDLE * const)MM_USER_PROBE_ADDRESS = 0; \
  1430. } \
  1431. \
  1432. *(volatile HANDLE *)(Address) = *(volatile HANDLE *)(Address); \
  1433. }
  1434. //++
  1435. //
  1436. // VOID
  1437. // ProbeAndZeroHandle(
  1438. // IN PHANDLE Address
  1439. // )
  1440. //
  1441. //--
  1442. #define ProbeAndZeroHandle(Address) { \
  1443. if ((Address) >= (HANDLE * const)MM_USER_PROBE_ADDRESS) { \
  1444. *(volatile HANDLE * const)MM_USER_PROBE_ADDRESS = 0; \
  1445. } \
  1446. \
  1447. *(volatile HANDLE *)(Address) = 0; \
  1448. }
  1449. //++
  1450. //
  1451. // VOID
  1452. // ProbeForWritePointer(
  1453. // IN PVOID Address
  1454. // )
  1455. //
  1456. //--
  1457. #define ProbeForWritePointer(Address) { \
  1458. if ((PVOID *)(Address) >= (PVOID * const)MM_USER_PROBE_ADDRESS) { \
  1459. *(volatile PVOID * const)MM_USER_PROBE_ADDRESS = NULL; \
  1460. } \
  1461. \
  1462. *(volatile PVOID *)(Address) = *(volatile PVOID *)(Address); \
  1463. }
  1464. //++
  1465. //
  1466. // VOID
  1467. // ProbeAndNullPointer(
  1468. // IN PVOID *Address
  1469. // )
  1470. //
  1471. //--
  1472. #define ProbeAndNullPointer(Address) { \
  1473. if ((PVOID *)(Address) >= (PVOID * const)MM_USER_PROBE_ADDRESS) { \
  1474. *(volatile PVOID * const)MM_USER_PROBE_ADDRESS = NULL; \
  1475. } \
  1476. \
  1477. *(volatile PVOID *)(Address) = NULL; \
  1478. }
  1479. //++
  1480. //
  1481. // VOID
  1482. // ProbeForWriteLong(
  1483. // IN PLONG Address
  1484. // )
  1485. //
  1486. //--
  1487. #define ProbeForWriteLong(Address) { \
  1488. if ((Address) >= (LONG * const)MM_USER_PROBE_ADDRESS) { \
  1489. *(volatile LONG * const)MM_USER_PROBE_ADDRESS = 0; \
  1490. } \
  1491. \
  1492. *(volatile LONG *)(Address) = *(volatile LONG *)(Address); \
  1493. }
  1494. //++
  1495. //
  1496. // VOID
  1497. // ProbeForWriteUlong(
  1498. // IN PULONG Address
  1499. // )
  1500. //
  1501. //--
  1502. #define ProbeForWriteUlong(Address) { \
  1503. if ((Address) >= (ULONG * const)MM_USER_PROBE_ADDRESS) { \
  1504. *(volatile ULONG * const)MM_USER_PROBE_ADDRESS = 0; \
  1505. } \
  1506. \
  1507. *(volatile ULONG *)(Address) = *(volatile ULONG *)(Address); \
  1508. }
  1509. //++
  1510. //
  1511. // VOID
  1512. // ProbeForWriteUlong_ptr(
  1513. // IN PULONG_PTR Address
  1514. // )
  1515. //
  1516. //--
  1517. #define ProbeForWriteUlong_ptr(Address) { \
  1518. if ((Address) >= (ULONG_PTR * const)MM_USER_PROBE_ADDRESS) { \
  1519. *(volatile ULONG_PTR * const)MM_USER_PROBE_ADDRESS = 0; \
  1520. } \
  1521. \
  1522. *(volatile ULONG_PTR *)(Address) = *(volatile ULONG_PTR *)(Address); \
  1523. }
  1524. //++
  1525. //
  1526. // VOID
  1527. // ProbeForWriteQuad(
  1528. // IN PQUAD Address
  1529. // )
  1530. //
  1531. //--
  1532. #define ProbeForWriteQuad(Address) { \
  1533. if ((Address) >= (QUAD * const)MM_USER_PROBE_ADDRESS) { \
  1534. *(volatile LONG * const)MM_USER_PROBE_ADDRESS = 0; \
  1535. } \
  1536. \
  1537. *(volatile QUAD *)(Address) = *(volatile QUAD *)(Address); \
  1538. }
  1539. //++
  1540. //
  1541. // VOID
  1542. // ProbeForWriteUquad(
  1543. // IN PUQUAD Address
  1544. // )
  1545. //
  1546. //--
  1547. #define ProbeForWriteUquad(Address) { \
  1548. if ((Address) >= (QUAD * const)MM_USER_PROBE_ADDRESS) { \
  1549. *(volatile ULONG * const)MM_USER_PROBE_ADDRESS = 0; \
  1550. } \
  1551. \
  1552. *(volatile UQUAD *)(Address) = *(volatile UQUAD *)(Address); \
  1553. }
  1554. //
  1555. // Probe and write functions definitions.
  1556. //
  1557. //++
  1558. //
  1559. // VOID
  1560. // ProbeAndWriteBoolean(
  1561. // IN PBOOLEAN Address,
  1562. // IN BOOLEAN Value
  1563. // )
  1564. //
  1565. //--
  1566. #define ProbeAndWriteBoolean(Address, Value) { \
  1567. if ((Address) >= (BOOLEAN * const)MM_USER_PROBE_ADDRESS) { \
  1568. *(volatile BOOLEAN * const)MM_USER_PROBE_ADDRESS = 0; \
  1569. } \
  1570. \
  1571. *(Address) = (Value); \
  1572. }
  1573. //++
  1574. //
  1575. // VOID
  1576. // ProbeAndWriteChar(
  1577. // IN PCHAR Address,
  1578. // IN CHAR Value
  1579. // )
  1580. //
  1581. //--
  1582. #define ProbeAndWriteChar(Address, Value) { \
  1583. if ((Address) >= (CHAR * const)MM_USER_PROBE_ADDRESS) { \
  1584. *(volatile CHAR * const)MM_USER_PROBE_ADDRESS = 0; \
  1585. } \
  1586. \
  1587. *(Address) = (Value); \
  1588. }
  1589. //++
  1590. //
  1591. // VOID
  1592. // ProbeAndWriteUchar(
  1593. // IN PUCHAR Address,
  1594. // IN UCHAR Value
  1595. // )
  1596. //
  1597. //--
  1598. #define ProbeAndWriteUchar(Address, Value) { \
  1599. if ((Address) >= (UCHAR * const)MM_USER_PROBE_ADDRESS) { \
  1600. *(volatile UCHAR * const)MM_USER_PROBE_ADDRESS = 0; \
  1601. } \
  1602. \
  1603. *(Address) = (Value); \
  1604. }
  1605. //++
  1606. //
  1607. // VOID
  1608. // ProbeAndWriteShort(
  1609. // IN PSHORT Address,
  1610. // IN SHORT Value
  1611. // )
  1612. //
  1613. //--
  1614. #define ProbeAndWriteShort(Address, Value) { \
  1615. if ((Address) >= (SHORT * const)MM_USER_PROBE_ADDRESS) { \
  1616. *(volatile SHORT * const)MM_USER_PROBE_ADDRESS = 0; \
  1617. } \
  1618. \
  1619. *(Address) = (Value); \
  1620. }
  1621. //++
  1622. //
  1623. // VOID
  1624. // ProbeAndWriteUshort(
  1625. // IN PUSHORT Address,
  1626. // IN USHORT Value
  1627. // )
  1628. //
  1629. //--
  1630. #define ProbeAndWriteUshort(Address, Value) { \
  1631. if ((Address) >= (USHORT * const)MM_USER_PROBE_ADDRESS) { \
  1632. *(volatile USHORT * const)MM_USER_PROBE_ADDRESS = 0; \
  1633. } \
  1634. \
  1635. *(Address) = (Value); \
  1636. }
  1637. //++
  1638. //
  1639. // VOID
  1640. // ProbeAndWriteHandle(
  1641. // IN PHANDLE Address,
  1642. // IN HANDLE Value
  1643. // )
  1644. //
  1645. //--
  1646. #define ProbeAndWriteHandle(Address, Value) { \
  1647. if ((Address) >= (HANDLE * const)MM_USER_PROBE_ADDRESS) { \
  1648. *(volatile HANDLE * const)MM_USER_PROBE_ADDRESS = 0; \
  1649. } \
  1650. \
  1651. *(Address) = (Value); \
  1652. }
  1653. //++
  1654. //
  1655. // VOID
  1656. // ProbeAndWriteLong(
  1657. // IN PLONG Address,
  1658. // IN LONG Value
  1659. // )
  1660. //
  1661. //--
  1662. #define ProbeAndWriteLong(Address, Value) { \
  1663. if ((Address) >= (LONG * const)MM_USER_PROBE_ADDRESS) { \
  1664. *(volatile LONG * const)MM_USER_PROBE_ADDRESS = 0; \
  1665. } \
  1666. \
  1667. *(Address) = (Value); \
  1668. }
  1669. //++
  1670. //
  1671. // VOID
  1672. // ProbeAndWriteUlong(
  1673. // IN PULONG Address,
  1674. // IN ULONG Value
  1675. // )
  1676. //
  1677. //--
  1678. #define ProbeAndWriteUlong(Address, Value) { \
  1679. if ((Address) >= (ULONG * const)MM_USER_PROBE_ADDRESS) { \
  1680. *(volatile ULONG * const)MM_USER_PROBE_ADDRESS = 0; \
  1681. } \
  1682. \
  1683. *(Address) = (Value); \
  1684. }
  1685. //++
  1686. //
  1687. // VOID
  1688. // ProbeAndWriteQuad(
  1689. // IN PQUAD Address,
  1690. // IN QUAD Value
  1691. // )
  1692. //
  1693. //--
  1694. #define ProbeAndWriteQuad(Address, Value) { \
  1695. if ((Address) >= (QUAD * const)MM_USER_PROBE_ADDRESS) { \
  1696. *(volatile LONG * const)MM_USER_PROBE_ADDRESS = 0; \
  1697. } \
  1698. \
  1699. *(Address) = (Value); \
  1700. }
  1701. //++
  1702. //
  1703. // VOID
  1704. // ProbeAndWriteUquad(
  1705. // IN PUQUAD Address,
  1706. // IN UQUAD Value
  1707. // )
  1708. //
  1709. //--
  1710. #define ProbeAndWriteUquad(Address, Value) { \
  1711. if ((Address) >= (UQUAD * const)MM_USER_PROBE_ADDRESS) { \
  1712. *(volatile ULONG * const)MM_USER_PROBE_ADDRESS = 0; \
  1713. } \
  1714. \
  1715. *(Address) = (Value); \
  1716. }
  1717. //++
  1718. //
  1719. // VOID
  1720. // ProbeAndWriteSturcture(
  1721. // IN P<STRUCTURE> Address,
  1722. // IN <STRUCTURE> Value,
  1723. // <STRUCTURE>
  1724. // )
  1725. //
  1726. //--
  1727. #define ProbeAndWriteStructure(Address, Value,STRUCTURE) { \
  1728. if ((STRUCTURE * const)(Address) >= (STRUCTURE * const)MM_USER_PROBE_ADDRESS) { \
  1729. *(volatile ULONG * const)MM_USER_PROBE_ADDRESS = 0; \
  1730. } \
  1731. \
  1732. *(Address) = (Value); \
  1733. }
  1734. // begin_ntifs begin_ntddk begin_wdm begin_ntosp
  1735. //
  1736. // Common probe for write functions.
  1737. //
  1738. NTKERNELAPI
  1739. VOID
  1740. NTAPI
  1741. ProbeForWrite (
  1742. IN PVOID Address,
  1743. IN SIZE_T Length,
  1744. IN ULONG Alignment
  1745. );
  1746. // end_ntifs end_ntddk end_wdm end_ntosp
  1747. //
  1748. // Timer Rundown
  1749. //
  1750. NTKERNELAPI
  1751. VOID
  1752. ExTimerRundown (
  1753. VOID
  1754. );
  1755. // begin_ntddk begin_wdm begin_nthal begin_ntifs begin_ntosp
  1756. //
  1757. // Worker Thread
  1758. //
  1759. typedef enum _WORK_QUEUE_TYPE {
  1760. CriticalWorkQueue,
  1761. DelayedWorkQueue,
  1762. HyperCriticalWorkQueue,
  1763. MaximumWorkQueue
  1764. } WORK_QUEUE_TYPE;
  1765. typedef
  1766. VOID
  1767. (*PWORKER_THREAD_ROUTINE)(
  1768. IN PVOID Parameter
  1769. );
  1770. typedef struct _WORK_QUEUE_ITEM {
  1771. LIST_ENTRY List;
  1772. PWORKER_THREAD_ROUTINE WorkerRoutine;
  1773. PVOID Parameter;
  1774. } WORK_QUEUE_ITEM, *PWORK_QUEUE_ITEM;
  1775. #if PRAGMA_DEPRECATED_DDK
  1776. #pragma deprecated(ExInitializeWorkItem) // Use IoAllocateWorkItem
  1777. #endif
  1778. #define ExInitializeWorkItem(Item, Routine, Context) \
  1779. (Item)->WorkerRoutine = (Routine); \
  1780. (Item)->Parameter = (Context); \
  1781. (Item)->List.Flink = NULL;
  1782. DECLSPEC_DEPRECATED_DDK // Use IoQueueWorkItem
  1783. NTKERNELAPI
  1784. VOID
  1785. ExQueueWorkItem(
  1786. IN PWORK_QUEUE_ITEM WorkItem,
  1787. IN WORK_QUEUE_TYPE QueueType
  1788. );
  1789. // end_ntddk end_wdm end_nthal end_ntifs end_ntosp
  1790. VOID
  1791. ExSwapinWorkerThreads(
  1792. IN BOOLEAN AllowSwap
  1793. );
  1794. // begin_ntddk begin_wdm begin_nthal begin_ntifs begin_ntosp
  1795. NTKERNELAPI
  1796. BOOLEAN
  1797. ExIsProcessorFeaturePresent(
  1798. ULONG ProcessorFeature
  1799. );
  1800. // end_ntddk end_wdm end_nthal end_ntifs end_ntosp
  1801. //
  1802. // QueueDisabled indicates that the queue is being shut down, and new
  1803. // workers should not join the queue. WorkerCount indicates the total
  1804. // number of worker threads processing items in this queue. These two
  1805. // pieces of information need to do a RMW together, so it's simpler to
  1806. // smush them together than to use a lock.
  1807. //
  1808. typedef union {
  1809. struct {
  1810. #define EX_WORKER_QUEUE_DISABLED 0x80000000
  1811. ULONG QueueDisabled : 1;
  1812. //
  1813. // MakeThreadsAsNecessary indicates whether this work queue is eligible
  1814. // for dynamic creation of threads not just for deadlock detection,
  1815. // but to ensure that the CPUs are all kept busy clearing any work
  1816. // item backlog.
  1817. //
  1818. ULONG MakeThreadsAsNecessary : 1;
  1819. ULONG WaitMode : 1;
  1820. ULONG WorkerCount : 29;
  1821. };
  1822. LONG QueueWorkerInfo;
  1823. } EX_QUEUE_WORKER_INFO;
  1824. typedef struct _EX_WORK_QUEUE {
  1825. //
  1826. // Queue objects that that are used to hold work queue entries and
  1827. // synchronize worker thread activity.
  1828. //
  1829. KQUEUE WorkerQueue;
  1830. //
  1831. // Number of dynamic worker threads that have been created "on the fly"
  1832. // as part of worker thread deadlock prevention
  1833. //
  1834. ULONG DynamicThreadCount;
  1835. //
  1836. // Count of the number of work items processed.
  1837. //
  1838. ULONG WorkItemsProcessed;
  1839. //
  1840. // Used for deadlock detection, WorkItemsProcessedLastPass equals the value
  1841. // of WorkItemsProcessed the last time ExpDetectWorkerThreadDeadlock()
  1842. // ran.
  1843. //
  1844. ULONG WorkItemsProcessedLastPass;
  1845. //
  1846. // QueueDepthLastPass is also part of the worker queue state snapshot
  1847. // taken by ExpDetectWorkerThreadDeadlock().
  1848. //
  1849. ULONG QueueDepthLastPass;
  1850. EX_QUEUE_WORKER_INFO Info;
  1851. } EX_WORK_QUEUE, *PEX_WORK_QUEUE;
  1852. extern EX_WORK_QUEUE ExWorkerQueue[];
  1853. // begin_ntddk begin_nthal begin_ntifs begin_ntosp
  1854. //
  1855. // Zone Allocation
  1856. //
  1857. typedef struct _ZONE_SEGMENT_HEADER {
  1858. SINGLE_LIST_ENTRY SegmentList;
  1859. PVOID Reserved;
  1860. } ZONE_SEGMENT_HEADER, *PZONE_SEGMENT_HEADER;
  1861. typedef struct _ZONE_HEADER {
  1862. SINGLE_LIST_ENTRY FreeList;
  1863. SINGLE_LIST_ENTRY SegmentList;
  1864. ULONG BlockSize;
  1865. ULONG TotalSegmentSize;
  1866. } ZONE_HEADER, *PZONE_HEADER;
  1867. DECLSPEC_DEPRECATED_DDK
  1868. NTKERNELAPI
  1869. NTSTATUS
  1870. ExInitializeZone(
  1871. IN PZONE_HEADER Zone,
  1872. IN ULONG BlockSize,
  1873. IN PVOID InitialSegment,
  1874. IN ULONG InitialSegmentSize
  1875. );
  1876. DECLSPEC_DEPRECATED_DDK
  1877. NTKERNELAPI
  1878. NTSTATUS
  1879. ExExtendZone(
  1880. IN PZONE_HEADER Zone,
  1881. IN PVOID Segment,
  1882. IN ULONG SegmentSize
  1883. );
  1884. DECLSPEC_DEPRECATED_DDK
  1885. NTKERNELAPI
  1886. NTSTATUS
  1887. ExInterlockedExtendZone(
  1888. IN PZONE_HEADER Zone,
  1889. IN PVOID Segment,
  1890. IN ULONG SegmentSize,
  1891. IN PKSPIN_LOCK Lock
  1892. );
  1893. //++
  1894. //
  1895. // PVOID
  1896. // ExAllocateFromZone(
  1897. // IN PZONE_HEADER Zone
  1898. // )
  1899. //
  1900. // Routine Description:
  1901. //
  1902. // This routine removes an entry from the zone and returns a pointer to it.
  1903. //
  1904. // Arguments:
  1905. //
  1906. // Zone - Pointer to the zone header controlling the storage from which the
  1907. // entry is to be allocated.
  1908. //
  1909. // Return Value:
  1910. //
  1911. // The function value is a pointer to the storage allocated from the zone.
  1912. //
  1913. //--
  1914. #if PRAGMA_DEPRECATED_DDK
  1915. #pragma deprecated(ExAllocateFromZone)
  1916. #endif
  1917. #define ExAllocateFromZone(Zone) \
  1918. (PVOID)((Zone)->FreeList.Next); \
  1919. if ( (Zone)->FreeList.Next ) (Zone)->FreeList.Next = (Zone)->FreeList.Next->Next
  1920. //++
  1921. //
  1922. // PVOID
  1923. // ExFreeToZone(
  1924. // IN PZONE_HEADER Zone,
  1925. // IN PVOID Block
  1926. // )
  1927. //
  1928. // Routine Description:
  1929. //
  1930. // This routine places the specified block of storage back onto the free
  1931. // list in the specified zone.
  1932. //
  1933. // Arguments:
  1934. //
  1935. // Zone - Pointer to the zone header controlling the storage to which the
  1936. // entry is to be inserted.
  1937. //
  1938. // Block - Pointer to the block of storage to be freed back to the zone.
  1939. //
  1940. // Return Value:
  1941. //
  1942. // Pointer to previous block of storage that was at the head of the free
  1943. // list. NULL implies the zone went from no available free blocks to
  1944. // at least one free block.
  1945. //
  1946. //--
  1947. #if PRAGMA_DEPRECATED_DDK
  1948. #pragma deprecated(ExFreeToZone)
  1949. #endif
  1950. #define ExFreeToZone(Zone,Block) \
  1951. ( ((PSINGLE_LIST_ENTRY)(Block))->Next = (Zone)->FreeList.Next, \
  1952. (Zone)->FreeList.Next = ((PSINGLE_LIST_ENTRY)(Block)), \
  1953. ((PSINGLE_LIST_ENTRY)(Block))->Next \
  1954. )
  1955. //++
  1956. //
  1957. // BOOLEAN
  1958. // ExIsFullZone(
  1959. // IN PZONE_HEADER Zone
  1960. // )
  1961. //
  1962. // Routine Description:
  1963. //
  1964. // This routine determines if the specified zone is full or not. A zone
  1965. // is considered full if the free list is empty.
  1966. //
  1967. // Arguments:
  1968. //
  1969. // Zone - Pointer to the zone header to be tested.
  1970. //
  1971. // Return Value:
  1972. //
  1973. // TRUE if the zone is full and FALSE otherwise.
  1974. //
  1975. //--
  1976. #if PRAGMA_DEPRECATED_DDK
  1977. #pragma deprecated(ExIsFullZone)
  1978. #endif
  1979. #define ExIsFullZone(Zone) \
  1980. ( (Zone)->FreeList.Next == (PSINGLE_LIST_ENTRY)NULL )
  1981. //++
  1982. //
  1983. // PVOID
  1984. // ExInterlockedAllocateFromZone(
  1985. // IN PZONE_HEADER Zone,
  1986. // IN PKSPIN_LOCK Lock
  1987. // )
  1988. //
  1989. // Routine Description:
  1990. //
  1991. // This routine removes an entry from the zone and returns a pointer to it.
  1992. // The removal is performed with the specified lock owned for the sequence
  1993. // to make it MP-safe.
  1994. //
  1995. // Arguments:
  1996. //
  1997. // Zone - Pointer to the zone header controlling the storage from which the
  1998. // entry is to be allocated.
  1999. //
  2000. // Lock - Pointer to the spin lock which should be obtained before removing
  2001. // the entry from the allocation list. The lock is released before
  2002. // returning to the caller.
  2003. //
  2004. // Return Value:
  2005. //
  2006. // The function value is a pointer to the storage allocated from the zone.
  2007. //
  2008. //--
  2009. #if PRAGMA_DEPRECATED_DDK
  2010. #pragma deprecated(ExInterlockedAllocateFromZone)
  2011. #endif
  2012. #define ExInterlockedAllocateFromZone(Zone,Lock) \
  2013. (PVOID) ExInterlockedPopEntryList( &(Zone)->FreeList, Lock )
  2014. //++
  2015. //
  2016. // PVOID
  2017. // ExInterlockedFreeToZone(
  2018. // IN PZONE_HEADER Zone,
  2019. // IN PVOID Block,
  2020. // IN PKSPIN_LOCK Lock
  2021. // )
  2022. //
  2023. // Routine Description:
  2024. //
  2025. // This routine places the specified block of storage back onto the free
  2026. // list in the specified zone. The insertion is performed with the lock
  2027. // owned for the sequence to make it MP-safe.
  2028. //
  2029. // Arguments:
  2030. //
  2031. // Zone - Pointer to the zone header controlling the storage to which the
  2032. // entry is to be inserted.
  2033. //
  2034. // Block - Pointer to the block of storage to be freed back to the zone.
  2035. //
  2036. // Lock - Pointer to the spin lock which should be obtained before inserting
  2037. // the entry onto the free list. The lock is released before returning
  2038. // to the caller.
  2039. //
  2040. // Return Value:
  2041. //
  2042. // Pointer to previous block of storage that was at the head of the free
  2043. // list. NULL implies the zone went from no available free blocks to
  2044. // at least one free block.
  2045. //
  2046. //--
  2047. #if PRAGMA_DEPRECATED_DDK
  2048. #pragma deprecated(ExInterlockedFreeToZone)
  2049. #endif
  2050. #define ExInterlockedFreeToZone(Zone,Block,Lock) \
  2051. ExInterlockedPushEntryList( &(Zone)->FreeList, ((PSINGLE_LIST_ENTRY) (Block)), Lock )
  2052. //++
  2053. //
  2054. // BOOLEAN
  2055. // ExIsObjectInFirstZoneSegment(
  2056. // IN PZONE_HEADER Zone,
  2057. // IN PVOID Object
  2058. // )
  2059. //
  2060. // Routine Description:
  2061. //
  2062. // This routine determines if the specified pointer lives in the zone.
  2063. //
  2064. // Arguments:
  2065. //
  2066. // Zone - Pointer to the zone header controlling the storage to which the
  2067. // object may belong.
  2068. //
  2069. // Object - Pointer to the object in question.
  2070. //
  2071. // Return Value:
  2072. //
  2073. // TRUE if the Object came from the first segment of zone.
  2074. //
  2075. //--
  2076. #if PRAGMA_DEPRECATED_DDK
  2077. #pragma deprecated(ExIsObjectInFirstZoneSegment)
  2078. #endif
  2079. #define ExIsObjectInFirstZoneSegment(Zone,Object) ((BOOLEAN) \
  2080. (((PUCHAR)(Object) >= (PUCHAR)(Zone)->SegmentList.Next) && \
  2081. ((PUCHAR)(Object) < (PUCHAR)(Zone)->SegmentList.Next + \
  2082. (Zone)->TotalSegmentSize)) \
  2083. )
  2084. // end_ntddk end_nthal end_ntifs end_ntosp
  2085. // begin_ntifs begin_ntddk begin_wdm begin_ntosp
  2086. //
  2087. // Define executive resource data structures.
  2088. //
  2089. typedef ULONG_PTR ERESOURCE_THREAD;
  2090. typedef ERESOURCE_THREAD *PERESOURCE_THREAD;
  2091. typedef struct _OWNER_ENTRY {
  2092. ERESOURCE_THREAD OwnerThread;
  2093. union {
  2094. LONG OwnerCount;
  2095. ULONG TableSize;
  2096. };
  2097. } OWNER_ENTRY, *POWNER_ENTRY;
  2098. typedef struct _ERESOURCE {
  2099. LIST_ENTRY SystemResourcesList;
  2100. POWNER_ENTRY OwnerTable;
  2101. SHORT ActiveCount;
  2102. USHORT Flag;
  2103. PKSEMAPHORE SharedWaiters;
  2104. PKEVENT ExclusiveWaiters;
  2105. OWNER_ENTRY OwnerThreads[2];
  2106. ULONG ContentionCount;
  2107. USHORT NumberOfSharedWaiters;
  2108. USHORT NumberOfExclusiveWaiters;
  2109. union {
  2110. PVOID Address;
  2111. ULONG_PTR CreatorBackTraceIndex;
  2112. };
  2113. KSPIN_LOCK SpinLock;
  2114. } ERESOURCE, *PERESOURCE;
  2115. //
  2116. // Values for ERESOURCE.Flag
  2117. //
  2118. #define ResourceNeverExclusive 0x10
  2119. #define ResourceReleaseByOtherThread 0x20
  2120. #define ResourceOwnedExclusive 0x80
  2121. #define RESOURCE_HASH_TABLE_SIZE 64
  2122. typedef struct _RESOURCE_HASH_ENTRY {
  2123. LIST_ENTRY ListEntry;
  2124. PVOID Address;
  2125. ULONG ContentionCount;
  2126. ULONG Number;
  2127. } RESOURCE_HASH_ENTRY, *PRESOURCE_HASH_ENTRY;
  2128. typedef struct _RESOURCE_PERFORMANCE_DATA {
  2129. ULONG ActiveResourceCount;
  2130. ULONG TotalResourceCount;
  2131. ULONG ExclusiveAcquire;
  2132. ULONG SharedFirstLevel;
  2133. ULONG SharedSecondLevel;
  2134. ULONG StarveFirstLevel;
  2135. ULONG StarveSecondLevel;
  2136. ULONG WaitForExclusive;
  2137. ULONG OwnerTableExpands;
  2138. ULONG MaximumTableExpand;
  2139. LIST_ENTRY HashTable[RESOURCE_HASH_TABLE_SIZE];
  2140. } RESOURCE_PERFORMANCE_DATA, *PRESOURCE_PERFORMANCE_DATA;
  2141. //
  2142. // Define executive resource function prototypes.
  2143. //
  2144. NTKERNELAPI
  2145. NTSTATUS
  2146. ExInitializeResourceLite(
  2147. IN PERESOURCE Resource
  2148. );
  2149. NTKERNELAPI
  2150. NTSTATUS
  2151. ExReinitializeResourceLite(
  2152. IN PERESOURCE Resource
  2153. );
  2154. NTKERNELAPI
  2155. BOOLEAN
  2156. ExAcquireResourceSharedLite(
  2157. IN PERESOURCE Resource,
  2158. IN BOOLEAN Wait
  2159. );
  2160. NTKERNELAPI
  2161. BOOLEAN
  2162. ExAcquireResourceExclusiveLite(
  2163. IN PERESOURCE Resource,
  2164. IN BOOLEAN Wait
  2165. );
  2166. NTKERNELAPI
  2167. BOOLEAN
  2168. ExAcquireSharedStarveExclusive(
  2169. IN PERESOURCE Resource,
  2170. IN BOOLEAN Wait
  2171. );
  2172. NTKERNELAPI
  2173. BOOLEAN
  2174. ExAcquireSharedWaitForExclusive(
  2175. IN PERESOURCE Resource,
  2176. IN BOOLEAN Wait
  2177. );
  2178. NTKERNELAPI
  2179. BOOLEAN
  2180. ExTryToAcquireResourceExclusiveLite(
  2181. IN PERESOURCE Resource
  2182. );
  2183. //
  2184. // VOID
  2185. // ExReleaseResource(
  2186. // IN PERESOURCE Resource
  2187. // );
  2188. //
  2189. #if PRAGMA_DEPRECATED_DDK
  2190. #pragma deprecated(ExReleaseResource) // Use ExReleaseResourceLite
  2191. #endif
  2192. #define ExReleaseResource(R) (ExReleaseResourceLite(R))
  2193. NTKERNELAPI
  2194. VOID
  2195. FASTCALL
  2196. ExReleaseResourceLite(
  2197. IN PERESOURCE Resource
  2198. );
  2199. NTKERNELAPI
  2200. VOID
  2201. ExReleaseResourceForThreadLite(
  2202. IN PERESOURCE Resource,
  2203. IN ERESOURCE_THREAD ResourceThreadId
  2204. );
  2205. NTKERNELAPI
  2206. VOID
  2207. ExSetResourceOwnerPointer(
  2208. IN PERESOURCE Resource,
  2209. IN PVOID OwnerPointer
  2210. );
  2211. NTKERNELAPI
  2212. VOID
  2213. ExConvertExclusiveToSharedLite(
  2214. IN PERESOURCE Resource
  2215. );
  2216. NTKERNELAPI
  2217. NTSTATUS
  2218. ExDeleteResourceLite (
  2219. IN PERESOURCE Resource
  2220. );
  2221. NTKERNELAPI
  2222. ULONG
  2223. ExGetExclusiveWaiterCount (
  2224. IN PERESOURCE Resource
  2225. );
  2226. NTKERNELAPI
  2227. ULONG
  2228. ExGetSharedWaiterCount (
  2229. IN PERESOURCE Resource
  2230. );
  2231. // end_ntddk end_wdm end_ntosp
  2232. NTKERNELAPI
  2233. VOID
  2234. ExDisableResourceBoostLite (
  2235. IN PERESOURCE Resource
  2236. );
  2237. // begin_ntddk begin_wdm begin_ntosp
  2238. //
  2239. // ERESOURCE_THREAD
  2240. // ExGetCurrentResourceThread(
  2241. // );
  2242. //
  2243. #define ExGetCurrentResourceThread() ((ULONG_PTR)PsGetCurrentThread())
  2244. NTKERNELAPI
  2245. BOOLEAN
  2246. ExIsResourceAcquiredExclusiveLite (
  2247. IN PERESOURCE Resource
  2248. );
  2249. NTKERNELAPI
  2250. ULONG
  2251. ExIsResourceAcquiredSharedLite (
  2252. IN PERESOURCE Resource
  2253. );
  2254. //
  2255. // An acquired resource is always owned shared, as shared ownership is a subset
  2256. // of exclusive ownership.
  2257. //
  2258. #define ExIsResourceAcquiredLite ExIsResourceAcquiredSharedLite
  2259. // end_wdm
  2260. //
  2261. // ntddk.h stole the entrypoints we wanted so fix them up here.
  2262. //
  2263. #if PRAGMA_DEPRECATED_DDK
  2264. #pragma deprecated(ExInitializeResource) // use ExInitializeResourceLite
  2265. #pragma deprecated(ExAcquireResourceShared) // use ExAcquireResourceSharedLite
  2266. #pragma deprecated(ExAcquireResourceExclusive) // use ExAcquireResourceExclusiveLite
  2267. #pragma deprecated(ExReleaseResourceForThread) // use ExReleaseResourceForThreadLite
  2268. #pragma deprecated(ExConvertExclusiveToShared) // use ExConvertExclusiveToSharedLite
  2269. #pragma deprecated(ExDeleteResource) // use ExDeleteResourceLite
  2270. #pragma deprecated(ExIsResourceAcquiredExclusive) // use ExIsResourceAcquiredExclusiveLite
  2271. #pragma deprecated(ExIsResourceAcquiredShared) // use ExIsResourceAcquiredSharedLite
  2272. #pragma deprecated(ExIsResourceAcquired) // use ExIsResourceAcquiredSharedLite
  2273. #endif
  2274. #define ExInitializeResource ExInitializeResourceLite
  2275. #define ExAcquireResourceShared ExAcquireResourceSharedLite
  2276. #define ExAcquireResourceExclusive ExAcquireResourceExclusiveLite
  2277. #define ExReleaseResourceForThread ExReleaseResourceForThreadLite
  2278. #define ExConvertExclusiveToShared ExConvertExclusiveToSharedLite
  2279. #define ExDeleteResource ExDeleteResourceLite
  2280. #define ExIsResourceAcquiredExclusive ExIsResourceAcquiredExclusiveLite
  2281. #define ExIsResourceAcquiredShared ExIsResourceAcquiredSharedLite
  2282. #define ExIsResourceAcquired ExIsResourceAcquiredSharedLite
  2283. // end_ntddk end_ntosp
  2284. #define ExDisableResourceBoost ExDisableResourceBoostLite
  2285. // end_ntifs
  2286. NTKERNELAPI
  2287. NTSTATUS
  2288. ExQuerySystemLockInformation(
  2289. OUT struct _RTL_PROCESS_LOCKS *LockInformation,
  2290. IN ULONG LockInformationLength,
  2291. OUT PULONG ReturnLength OPTIONAL
  2292. );
  2293. // begin_ntosp
  2294. //
  2295. // Push lock definitions
  2296. //
  2297. typedef struct _EX_PUSH_LOCK {
  2298. #define EX_PUSH_LOCK_WAITING 0x1
  2299. #define EX_PUSH_LOCK_EXCLUSIVE 0x2
  2300. #define EX_PUSH_LOCK_SHARE_INC 0x4
  2301. union {
  2302. struct {
  2303. ULONG_PTR Waiting : 1;
  2304. ULONG_PTR Exclusive : 1;
  2305. ULONG_PTR Shared : sizeof (ULONG_PTR) * 8 - 2;
  2306. };
  2307. ULONG_PTR Value;
  2308. PVOID Ptr;
  2309. };
  2310. } EX_PUSH_LOCK, *PEX_PUSH_LOCK;
  2311. #if defined (NT_UP)
  2312. #define EX_CACHE_LINE_SIZE 16
  2313. #define EX_PUSH_LOCK_FANNED_COUNT 1
  2314. #else
  2315. #define EX_CACHE_LINE_SIZE 128
  2316. #define EX_PUSH_LOCK_FANNED_COUNT (PAGE_SIZE/EX_CACHE_LINE_SIZE)
  2317. #endif
  2318. //
  2319. // Define a fan out structure for n push locks each in its own cache line
  2320. //
  2321. typedef struct _EX_PUSH_LOCK_CACHE_AWARE {
  2322. PEX_PUSH_LOCK Locks[EX_PUSH_LOCK_FANNED_COUNT];
  2323. } EX_PUSH_LOCK_CACHE_AWARE, *PEX_PUSH_LOCK_CACHE_AWARE;
  2324. //
  2325. // Define structure thats a push lock padded to the size of a cache line
  2326. //
  2327. typedef struct _EX_PUSH_LOCK_CACHE_AWARE_PADDED {
  2328. EX_PUSH_LOCK Lock;
  2329. union {
  2330. UCHAR Pad[EX_CACHE_LINE_SIZE - sizeof (EX_PUSH_LOCK)];
  2331. BOOLEAN Single;
  2332. };
  2333. } EX_PUSH_LOCK_CACHE_AWARE_PADDED, *PEX_PUSH_LOCK_CACHE_AWARE_PADDED;
  2334. //
  2335. // Rundown protection structure
  2336. //
  2337. typedef struct _EX_RUNDOWN_REF {
  2338. #define EX_RUNDOWN_ACTIVE 0x1
  2339. #define EX_RUNDOWN_COUNT_SHIFT 0x1
  2340. #define EX_RUNDOWN_COUNT_INC (1<<EX_RUNDOWN_COUNT_SHIFT)
  2341. union {
  2342. ULONG_PTR Count;
  2343. PVOID Ptr;
  2344. };
  2345. } EX_RUNDOWN_REF, *PEX_RUNDOWN_REF;
  2346. //
  2347. // The Ex/Ob handle table interface package (in handle.c)
  2348. //
  2349. //
  2350. // The Ex/Ob handle table package uses a common handle definition. The actual
  2351. // type definition for a handle is a pvoid and is declared in sdk/inc. This
  2352. // package uses only the low 32 bits of the pvoid pointer.
  2353. //
  2354. // For simplicity we declare a new typedef called an exhandle
  2355. //
  2356. // The 2 bits of an EXHANDLE is available to the application and is
  2357. // ignored by the system. The next 24 bits store the handle table entry
  2358. // index and is used to refer to a particular entry in a handle table.
  2359. //
  2360. // Note that this format is immutable because there are outside programs with
  2361. // hardwired code that already assumes the format of a handle.
  2362. //
  2363. typedef struct _EXHANDLE {
  2364. union {
  2365. struct {
  2366. //
  2367. // Application available tag bits
  2368. //
  2369. ULONG TagBits : 2;
  2370. //
  2371. // The handle table entry index
  2372. //
  2373. ULONG Index : 30;
  2374. };
  2375. HANDLE GenericHandleOverlay;
  2376. #define HANDLE_VALUE_INC 4 // Amount to increment the Value to get to the next handle
  2377. ULONG_PTR Value;
  2378. };
  2379. } EXHANDLE, *PEXHANDLE;
  2380. // end_ntosp
  2381. typedef struct _HANDLE_TABLE_ENTRY_INFO {
  2382. //
  2383. // The following field contains the audit mask for the handle if one
  2384. // exists. The purpose of the audit mask is to record all of the accesses
  2385. // that may have been audited when the handle was opened in order to
  2386. // support "per operation" based auditing. It is computed by walking the
  2387. // SACL of the object being opened and keeping a record of all of the audit
  2388. // ACEs that apply to the open operation going on. Each set bit corresponds
  2389. // to an access that would be audited. As each operation takes place, its
  2390. // corresponding access bit is removed from this mask.
  2391. //
  2392. ACCESS_MASK AuditMask;
  2393. } HANDLE_TABLE_ENTRY_INFO, *PHANDLE_TABLE_ENTRY_INFO;
  2394. //
  2395. // A handle table stores multiple handle table entries, each entry is looked
  2396. // up by its exhandle. A handle table entry has really two fields.
  2397. //
  2398. // The first field contains a pointer object and is overloaded with the three
  2399. // low order bits used by ob to denote inherited, protected, and audited
  2400. // objects. The upper bit used as a handle table entry lock. Note, this
  2401. // means that all valid object pointers must be at least longword aligned and
  2402. // have their sign bit set (i.e., be negative).
  2403. //
  2404. // The next field contains the acces mask (sometimes in the form of a granted
  2405. // access index, and creator callback trace) if the entry is in use or a
  2406. // pointer in the free list if the entry is free.
  2407. //
  2408. // Two things to note:
  2409. //
  2410. // 1. An entry is free if the object pointer is null, this means that the
  2411. // following field contains the FreeTableEntryList.
  2412. //
  2413. // 2. An entry is unlocked if the object pointer is positive and locked if its
  2414. // negative. The handle package through callbacks and Map Handle to
  2415. // Pointer will lock the entry (thus making the pointer valid) outside
  2416. // routines can then read and reset the attributes field and the object
  2417. // provided they don't unlock the entry. When the callbacks return the
  2418. // entry will be unlocked and the callers or MapHandleToPointer will need
  2419. // to call UnlockHandleTableEntry explicitly.
  2420. //
  2421. typedef struct _HANDLE_TABLE_ENTRY {
  2422. //
  2423. // The pointer to the object overloaded with three ob attributes bits in
  2424. // the lower order and the high bit to denote locked or unlocked entries
  2425. //
  2426. union {
  2427. PVOID Object;
  2428. ULONG ObAttributes;
  2429. PHANDLE_TABLE_ENTRY_INFO InfoTable;
  2430. ULONG_PTR Value;
  2431. };
  2432. //
  2433. // This field either contains the granted access mask for the handle or an
  2434. // ob variation that also stores the same information. Or in the case of
  2435. // a free entry the field stores the index for the next free entry in the
  2436. // free list. This is like a FAT chain, and is used instead of pointers
  2437. // to make table duplication easier, because the entries can just be
  2438. // copied without needing to modify pointers.
  2439. //
  2440. union {
  2441. union {
  2442. ACCESS_MASK GrantedAccess;
  2443. struct {
  2444. USHORT GrantedAccessIndex;
  2445. USHORT CreatorBackTraceIndex;
  2446. };
  2447. };
  2448. LONG NextFreeTableEntry;
  2449. };
  2450. } HANDLE_TABLE_ENTRY, *PHANDLE_TABLE_ENTRY;
  2451. //
  2452. // Define a structure to track handle usage
  2453. //
  2454. #define HANDLE_TRACE_DB_MAX_STACKS 4096
  2455. #define HANDLE_TRACE_DB_STACK_SIZE 16
  2456. typedef struct _HANDLE_TRACE_DB_ENTRY {
  2457. CLIENT_ID ClientId;
  2458. HANDLE Handle;
  2459. #define HANDLE_TRACE_DB_OPEN 1
  2460. #define HANDLE_TRACE_DB_CLOSE 2
  2461. #define HANDLE_TRACE_DB_BADREF 3
  2462. ULONG Type;
  2463. PVOID StackTrace[HANDLE_TRACE_DB_STACK_SIZE];
  2464. } HANDLE_TRACE_DB_ENTRY, *PHANDLE_TRACE_DB_ENTRY;
  2465. typedef struct _HANDLE_TRACE_DEBUG_INFO {
  2466. //
  2467. // Current index for the stack trace DB
  2468. //
  2469. ULONG CurrentStackIndex;
  2470. //
  2471. // Save traces of those who open and close handles
  2472. //
  2473. HANDLE_TRACE_DB_ENTRY TraceDb[HANDLE_TRACE_DB_MAX_STACKS];
  2474. } HANDLE_TRACE_DEBUG_INFO, *PHANDLE_TRACE_DEBUG_INFO;
  2475. //
  2476. // One handle table exists per process. Unless otherwise specified, via a
  2477. // call to RemoveHandleTable, all handle tables are linked together in a
  2478. // global list. This list is used by the snapshot handle tables call.
  2479. //
  2480. typedef struct _HANDLE_TABLE {
  2481. //
  2482. // A pointer to the top level handle table tree node.
  2483. //
  2484. ULONG_PTR TableCode;
  2485. //
  2486. // The process who is being charged quota for this handle table and a
  2487. // unique process id to use in our callbacks
  2488. //
  2489. struct _EPROCESS *QuotaProcess;
  2490. HANDLE UniqueProcessId;
  2491. //
  2492. // These locks are used for table expansion and preventing the A-B-A problem
  2493. // on handle allocate.
  2494. //
  2495. #define HANDLE_TABLE_LOCKS 4
  2496. EX_PUSH_LOCK HandleTableLock[HANDLE_TABLE_LOCKS];
  2497. //
  2498. // The list of global handle tables. This field is protected by a global
  2499. // lock.
  2500. //
  2501. LIST_ENTRY HandleTableList;
  2502. //
  2503. // Define a field to block on if a handle is found locked.
  2504. //
  2505. EX_PUSH_LOCK HandleContentionEvent;
  2506. //
  2507. // Debug info. Only allocated if we are debuggign handles
  2508. //
  2509. PHANDLE_TRACE_DEBUG_INFO DebugInfo;
  2510. //
  2511. // The number of pages for additional info.
  2512. // This counter is used to improve the performance
  2513. // in ExGetHandleInfo
  2514. //
  2515. LONG ExtraInfoPages;
  2516. //
  2517. // This is a singly linked list of free table entries. We don't actually
  2518. // use pointers, but have each store the index of the next free entry
  2519. // in the list. The list is managed as a lifo list. We also keep track
  2520. // of the next index that we have to allocate pool to hold.
  2521. //
  2522. ULONG FirstFree;
  2523. //
  2524. // We free handles to this list when handle debugging is on or if we see
  2525. // that a thread has this handles bucket lock held. The allows us to delay reuse
  2526. // of handles to get a better chance of catching offenders
  2527. //
  2528. ULONG LastFree;
  2529. //
  2530. // This is the next handle index needing a pool allocation. Its also used as a bound
  2531. // for good handles.
  2532. //
  2533. ULONG NextHandleNeedingPool;
  2534. //
  2535. // The number of handle table entries in use.
  2536. //
  2537. LONG HandleCount;
  2538. //
  2539. // Define a flags field
  2540. //
  2541. union {
  2542. ULONG Flags;
  2543. //
  2544. // For optimization we reuse handle values quickly. This can be a problem for
  2545. // some usages of handles and makes debugging a little harder. If this
  2546. // bit is set then we always use FIFO handle allocation.
  2547. //
  2548. BOOLEAN StrictFIFO : 1;
  2549. };
  2550. } HANDLE_TABLE, *PHANDLE_TABLE;
  2551. //
  2552. // Routines for handle manipulation.
  2553. //
  2554. //
  2555. // Function for unlocking handle table entries
  2556. //
  2557. NTKERNELAPI
  2558. VOID
  2559. ExUnlockHandleTableEntry (
  2560. PHANDLE_TABLE HandleTable,
  2561. PHANDLE_TABLE_ENTRY HandleTableEntry
  2562. );
  2563. //
  2564. // A global initialization function called on at system start up
  2565. //
  2566. NTKERNELAPI
  2567. VOID
  2568. ExInitializeHandleTablePackage (
  2569. VOID
  2570. );
  2571. //
  2572. // Functions to create, remove, and destroy handle tables per process. The
  2573. // destroy function uses a callback.
  2574. //
  2575. NTKERNELAPI
  2576. PHANDLE_TABLE
  2577. ExCreateHandleTable (
  2578. IN struct _EPROCESS *Process OPTIONAL
  2579. );
  2580. VOID
  2581. ExSetHandleTableStrictFIFO (
  2582. IN PHANDLE_TABLE HandleTable
  2583. );
  2584. NTKERNELAPI
  2585. VOID
  2586. ExRemoveHandleTable (
  2587. IN PHANDLE_TABLE HandleTable
  2588. );
  2589. NTKERNELAPI
  2590. NTSTATUS
  2591. ExEnableHandleTracing (
  2592. IN PHANDLE_TABLE HandleTable
  2593. );
  2594. typedef VOID (*EX_DESTROY_HANDLE_ROUTINE)(
  2595. IN HANDLE Handle
  2596. );
  2597. NTKERNELAPI
  2598. VOID
  2599. ExDestroyHandleTable (
  2600. IN PHANDLE_TABLE HandleTable,
  2601. IN EX_DESTROY_HANDLE_ROUTINE DestroyHandleProcedure
  2602. );
  2603. //
  2604. // A function to enumerate through the handle table of a process using a
  2605. // callback.
  2606. //
  2607. typedef BOOLEAN (*EX_ENUMERATE_HANDLE_ROUTINE)(
  2608. IN PHANDLE_TABLE_ENTRY HandleTableEntry,
  2609. IN HANDLE Handle,
  2610. IN PVOID EnumParameter
  2611. );
  2612. NTKERNELAPI
  2613. BOOLEAN
  2614. ExEnumHandleTable (
  2615. IN PHANDLE_TABLE HandleTable,
  2616. IN EX_ENUMERATE_HANDLE_ROUTINE EnumHandleProcedure,
  2617. IN PVOID EnumParameter,
  2618. OUT PHANDLE Handle OPTIONAL
  2619. );
  2620. NTKERNELAPI
  2621. VOID
  2622. ExSweepHandleTable (
  2623. IN PHANDLE_TABLE HandleTable,
  2624. IN EX_ENUMERATE_HANDLE_ROUTINE EnumHandleProcedure,
  2625. IN PVOID EnumParameter
  2626. );
  2627. //
  2628. // A function to duplicate the handle table of a process using a callback
  2629. //
  2630. typedef BOOLEAN (*EX_DUPLICATE_HANDLE_ROUTINE)(
  2631. IN struct _EPROCESS *Process OPTIONAL,
  2632. IN PHANDLE_TABLE OldHandleTable,
  2633. IN PHANDLE_TABLE_ENTRY OldHandleTableEntry,
  2634. IN PHANDLE_TABLE_ENTRY HandleTableEntry
  2635. );
  2636. NTKERNELAPI
  2637. PHANDLE_TABLE
  2638. ExDupHandleTable (
  2639. IN struct _EPROCESS *Process OPTIONAL,
  2640. IN PHANDLE_TABLE OldHandleTable,
  2641. IN EX_DUPLICATE_HANDLE_ROUTINE DupHandleProcedure OPTIONAL
  2642. );
  2643. //
  2644. // A function that enumerates all the handles in all the handle tables
  2645. // throughout the system using a callback.
  2646. //
  2647. typedef NTSTATUS (*PEX_SNAPSHOT_HANDLE_ENTRY)(
  2648. IN OUT PSYSTEM_HANDLE_TABLE_ENTRY_INFO *HandleEntryInfo,
  2649. IN HANDLE UniqueProcessId,
  2650. IN PHANDLE_TABLE_ENTRY HandleEntry,
  2651. IN HANDLE Handle,
  2652. IN ULONG Length,
  2653. IN OUT PULONG RequiredLength
  2654. );
  2655. typedef NTSTATUS (*PEX_SNAPSHOT_HANDLE_ENTRY_EX)(
  2656. IN OUT PSYSTEM_HANDLE_TABLE_ENTRY_INFO_EX *HandleEntryInfo,
  2657. IN HANDLE UniqueProcessId,
  2658. IN PHANDLE_TABLE_ENTRY HandleEntry,
  2659. IN HANDLE Handle,
  2660. IN ULONG Length,
  2661. IN OUT PULONG RequiredLength
  2662. );
  2663. NTKERNELAPI
  2664. NTSTATUS
  2665. ExSnapShotHandleTables (
  2666. IN PEX_SNAPSHOT_HANDLE_ENTRY SnapShotHandleEntry,
  2667. IN OUT PSYSTEM_HANDLE_INFORMATION HandleInformation,
  2668. IN ULONG Length,
  2669. IN OUT PULONG RequiredLength
  2670. );
  2671. NTKERNELAPI
  2672. NTSTATUS
  2673. ExSnapShotHandleTablesEx (
  2674. IN PEX_SNAPSHOT_HANDLE_ENTRY_EX SnapShotHandleEntry,
  2675. IN OUT PSYSTEM_HANDLE_INFORMATION_EX HandleInformation,
  2676. IN ULONG Length,
  2677. IN OUT PULONG RequiredLength
  2678. );
  2679. //
  2680. // Functions to create, destroy, and modify handle table entries the modify
  2681. // function using a callback
  2682. //
  2683. NTKERNELAPI
  2684. HANDLE
  2685. ExCreateHandle (
  2686. IN PHANDLE_TABLE HandleTable,
  2687. IN PHANDLE_TABLE_ENTRY HandleTableEntry
  2688. );
  2689. NTKERNELAPI
  2690. BOOLEAN
  2691. ExDestroyHandle (
  2692. IN PHANDLE_TABLE HandleTable,
  2693. IN HANDLE Handle,
  2694. IN PHANDLE_TABLE_ENTRY HandleTableEntry OPTIONAL
  2695. );
  2696. typedef BOOLEAN (*PEX_CHANGE_HANDLE_ROUTINE) (
  2697. IN OUT PHANDLE_TABLE_ENTRY HandleTableEntry,
  2698. IN ULONG_PTR Parameter
  2699. );
  2700. NTKERNELAPI
  2701. BOOLEAN
  2702. ExChangeHandle (
  2703. IN PHANDLE_TABLE HandleTable,
  2704. IN HANDLE Handle,
  2705. IN PEX_CHANGE_HANDLE_ROUTINE ChangeRoutine,
  2706. IN ULONG_PTR Parameter
  2707. );
  2708. //
  2709. // A function that takes a handle value and returns a pointer to the
  2710. // associated handle table entry.
  2711. //
  2712. NTKERNELAPI
  2713. PHANDLE_TABLE_ENTRY
  2714. ExMapHandleToPointer (
  2715. IN PHANDLE_TABLE HandleTable,
  2716. IN HANDLE Handle
  2717. );
  2718. NTKERNELAPI
  2719. PHANDLE_TABLE_ENTRY
  2720. ExMapHandleToPointerEx (
  2721. IN PHANDLE_TABLE HandleTable,
  2722. IN HANDLE Handle,
  2723. IN KPROCESSOR_MODE PreviousMode
  2724. );
  2725. NTKERNELAPI
  2726. NTSTATUS
  2727. ExSetHandleInfo (
  2728. IN PHANDLE_TABLE HandleTable,
  2729. IN HANDLE Handle,
  2730. IN PHANDLE_TABLE_ENTRY_INFO EntryInfo,
  2731. IN BOOLEAN EntryLocked
  2732. );
  2733. NTKERNELAPI
  2734. PHANDLE_TABLE_ENTRY_INFO
  2735. ExpGetHandleInfo (
  2736. IN PHANDLE_TABLE HandleTable,
  2737. IN HANDLE Handle,
  2738. IN BOOLEAN EntryLocked
  2739. );
  2740. #define ExGetHandleInfo(HT,H,E) \
  2741. ((HT)->ExtraInfoPages ? ExpGetHandleInfo((HT),(H),(E)) : NULL)
  2742. //
  2743. // Macros for resetting the owner of the handle table, and current
  2744. // noop macro for setting fifo/lifo behaviour of the table
  2745. //
  2746. #define ExSetHandleTableOwner(ht,id) {(ht)->UniqueProcessId = (id);}
  2747. #define ExSetHandleTableOrder(ht,or) {NOTHING;}
  2748. //
  2749. // Locally Unique Identifier Services
  2750. //
  2751. NTKERNELAPI
  2752. BOOLEAN
  2753. ExLuidInitialization (
  2754. VOID
  2755. );
  2756. //
  2757. // VOID
  2758. // ExAllocateLocallyUniqueId (
  2759. // PLUID Luid
  2760. // )
  2761. //
  2762. //*++
  2763. //
  2764. // Routine Description:
  2765. //
  2766. // This function returns an LUID value that is unique since the system
  2767. // was last rebooted. It is unique only on the system it is generated on
  2768. // and not network wide.
  2769. //
  2770. // N.B. A LUID is a 64-bit value and for all practical purposes will
  2771. // never carry in the lifetime of a single boot of the system.
  2772. // At an increment rate of 1ns, the value would carry to zero in
  2773. // approximately 126 years.
  2774. //
  2775. // Arguments:
  2776. //
  2777. // Luid - Supplies a pointer to a variable that receives the allocated
  2778. // locally unique Id.
  2779. //
  2780. // Return Value:
  2781. //
  2782. // The allocated LUID value.
  2783. //
  2784. // --*/
  2785. extern LARGE_INTEGER ExpLuid;
  2786. extern const LARGE_INTEGER ExpLuidIncrement;
  2787. __inline
  2788. VOID
  2789. ExAllocateLocallyUniqueId (
  2790. IN OUT PLUID Luid
  2791. )
  2792. {
  2793. LARGE_INTEGER Initial;
  2794. #if defined (_IA64_)
  2795. Initial.QuadPart = InterlockedAdd64 (&ExpLuid.QuadPart, ExpLuidIncrement.QuadPart);
  2796. #else
  2797. LARGE_INTEGER Value;
  2798. while (1) {
  2799. Initial.QuadPart = ExpLuid.QuadPart;
  2800. Value.QuadPart = Initial.QuadPart + ExpLuidIncrement.QuadPart;
  2801. Value.QuadPart = InterlockedCompareExchange64(&ExpLuid.QuadPart,
  2802. Value.QuadPart,
  2803. Initial.QuadPart);
  2804. if (Initial.QuadPart != Value.QuadPart) {
  2805. continue;
  2806. }
  2807. break;
  2808. }
  2809. #endif
  2810. Luid->LowPart = Initial.LowPart;
  2811. Luid->HighPart = Initial.HighPart;
  2812. return;
  2813. }
  2814. // begin_ntddk begin_wdm begin_ntifs begin_ntosp
  2815. //
  2816. // Get previous mode
  2817. //
  2818. NTKERNELAPI
  2819. KPROCESSOR_MODE
  2820. ExGetPreviousMode(
  2821. VOID
  2822. );
  2823. // end_ntddk end_wdm end_ntifs end_ntosp
  2824. //
  2825. // Raise exception from kernel mode.
  2826. //
  2827. NTKERNELAPI
  2828. VOID
  2829. NTAPI
  2830. ExRaiseException (
  2831. PEXCEPTION_RECORD ExceptionRecord
  2832. );
  2833. // begin_ntddk begin_wdm begin_ntifs begin_ntosp
  2834. //
  2835. // Raise status from kernel mode.
  2836. //
  2837. NTKERNELAPI
  2838. VOID
  2839. NTAPI
  2840. ExRaiseStatus (
  2841. IN NTSTATUS Status
  2842. );
  2843. // end_wdm
  2844. NTKERNELAPI
  2845. VOID
  2846. ExRaiseDatatypeMisalignment (
  2847. VOID
  2848. );
  2849. NTKERNELAPI
  2850. VOID
  2851. ExRaiseAccessViolation (
  2852. VOID
  2853. );
  2854. // end_ntddk end_ntifs end_ntosp
  2855. FORCEINLINE
  2856. VOID
  2857. ProbeForWriteSmallStructure (
  2858. IN PVOID Address,
  2859. IN SIZE_T Size,
  2860. IN ULONG Alignment)
  2861. /*++
  2862. Routine Description:
  2863. Probes a structure whose size is know at compile time
  2864. Arguments:
  2865. Address - Address of structure
  2866. Size - Size of structure. This should be a compile time constant
  2867. Alignment - Alignment of structure. This should be a compile time constant
  2868. Return Value:
  2869. None
  2870. --*/
  2871. {
  2872. if ((ULONG_PTR)(Address) >= (ULONG_PTR)MM_USER_PROBE_ADDRESS) {
  2873. *(volatile UCHAR *) MM_USER_PROBE_ADDRESS = 0;
  2874. }
  2875. ASSERT(((Alignment) == 1) || ((Alignment) == 2) ||
  2876. ((Alignment) == 4) || ((Alignment) == 8) ||
  2877. ((Alignment) == 16));
  2878. //
  2879. // If the size of the structure is > 4k then call the standard routine.
  2880. // wow64 uses a page size of 4k even on ia64.
  2881. //
  2882. if (Size == 0 || Size >= 0x1000) {
  2883. ASSERT (0);
  2884. ProbeForWrite (Address, Size, Alignment);
  2885. } else {
  2886. if (((ULONG_PTR)(Address) & ((Alignment) - 1)) != 0) {
  2887. ExRaiseDatatypeMisalignment();
  2888. }
  2889. *(volatile UCHAR *)(Address) = *(volatile UCHAR *)(Address);
  2890. if (Size > Alignment) {
  2891. ((volatile UCHAR *)(Address))[(Size-1)&~(SIZE_T)(Alignment-1)] =
  2892. ((volatile UCHAR *)(Address))[(Size-1)&~(SIZE_T)(Alignment-1)];
  2893. }
  2894. }
  2895. }
  2896. extern BOOLEAN ExReadyForErrors;
  2897. // begin_ntosp
  2898. NTKERNELAPI
  2899. NTSTATUS
  2900. ExRaiseHardError(
  2901. IN NTSTATUS ErrorStatus,
  2902. IN ULONG NumberOfParameters,
  2903. IN ULONG UnicodeStringParameterMask,
  2904. IN PULONG_PTR Parameters,
  2905. IN ULONG ValidResponseOptions,
  2906. OUT PULONG Response
  2907. );
  2908. int
  2909. ExSystemExceptionFilter(
  2910. VOID
  2911. );
  2912. NTKERNELAPI
  2913. VOID
  2914. ExGetCurrentProcessorCpuUsage(
  2915. IN PULONG CpuUsage
  2916. );
  2917. NTKERNELAPI
  2918. VOID
  2919. ExGetCurrentProcessorCounts(
  2920. OUT PULONG IdleCount,
  2921. OUT PULONG KernelAndUser,
  2922. OUT PULONG Index
  2923. );
  2924. // end_ntosp
  2925. //
  2926. // The following are global counters used by the EX component to indicate
  2927. // the amount of EventPair transactions being performed in the system.
  2928. //
  2929. extern ULONG EvPrSetHigh;
  2930. extern ULONG EvPrSetLow;
  2931. //
  2932. // Debug event logging facility
  2933. //
  2934. #define EX_DEBUG_LOG_FORMAT_NONE (UCHAR)0
  2935. #define EX_DEBUG_LOG_FORMAT_ULONG (UCHAR)1
  2936. #define EX_DEBUG_LOG_FORMAT_PSZ (UCHAR)2
  2937. #define EX_DEBUG_LOG_FORMAT_PWSZ (UCHAR)3
  2938. #define EX_DEBUG_LOG_FORMAT_STRING (UCHAR)4
  2939. #define EX_DEBUG_LOG_FORMAT_USTRING (UCHAR)5
  2940. #define EX_DEBUG_LOG_FORMAT_OBJECT (UCHAR)6
  2941. #define EX_DEBUG_LOG_FORMAT_HANDLE (UCHAR)7
  2942. #define EX_DEBUG_LOG_NUMBER_OF_DATA_VALUES 4
  2943. #define EX_DEBUG_LOG_NUMBER_OF_BACK_TRACES 4
  2944. typedef struct _EX_DEBUG_LOG_TAG {
  2945. UCHAR Format[ EX_DEBUG_LOG_NUMBER_OF_DATA_VALUES ];
  2946. PCHAR Name;
  2947. } EX_DEBUG_LOG_TAG, *PEX_DEBUG_LOG_TAG;
  2948. typedef struct _EX_DEBUG_LOG_EVENT {
  2949. USHORT ThreadId;
  2950. USHORT ProcessId;
  2951. ULONG Time : 24;
  2952. ULONG Tag : 8;
  2953. ULONG BackTrace[ EX_DEBUG_LOG_NUMBER_OF_BACK_TRACES ];
  2954. ULONG Data[ EX_DEBUG_LOG_NUMBER_OF_DATA_VALUES ];
  2955. } EX_DEBUG_LOG_EVENT, *PEX_DEBUG_LOG_EVENT;
  2956. typedef struct _EX_DEBUG_LOG {
  2957. KSPIN_LOCK Lock;
  2958. ULONG NumberOfTags;
  2959. ULONG MaximumNumberOfTags;
  2960. PEX_DEBUG_LOG_TAG Tags;
  2961. ULONG CountOfEventsLogged;
  2962. PEX_DEBUG_LOG_EVENT First;
  2963. PEX_DEBUG_LOG_EVENT Last;
  2964. PEX_DEBUG_LOG_EVENT Next;
  2965. } EX_DEBUG_LOG, *PEX_DEBUG_LOG;
  2966. NTKERNELAPI
  2967. PEX_DEBUG_LOG
  2968. ExCreateDebugLog(
  2969. IN UCHAR MaximumNumberOfTags,
  2970. IN ULONG MaximumNumberOfEvents
  2971. );
  2972. NTKERNELAPI
  2973. UCHAR
  2974. ExCreateDebugLogTag(
  2975. IN PEX_DEBUG_LOG Log,
  2976. IN PCHAR Name,
  2977. IN UCHAR Format1,
  2978. IN UCHAR Format2,
  2979. IN UCHAR Format3,
  2980. IN UCHAR Format4
  2981. );
  2982. NTKERNELAPI
  2983. VOID
  2984. ExDebugLogEvent(
  2985. IN PEX_DEBUG_LOG Log,
  2986. IN UCHAR Tag,
  2987. IN ULONG Data1,
  2988. IN ULONG Data2,
  2989. IN ULONG Data3,
  2990. IN ULONG Data4
  2991. );
  2992. VOID
  2993. ExShutdownSystem(
  2994. IN ULONG Phase
  2995. );
  2996. BOOLEAN
  2997. ExAcquireTimeRefreshLock(
  2998. IN BOOLEAN Wait
  2999. );
  3000. VOID
  3001. ExReleaseTimeRefreshLock(
  3002. VOID
  3003. );
  3004. VOID
  3005. ExUpdateSystemTimeFromCmos (
  3006. IN BOOLEAN UpdateInterruptTime,
  3007. IN ULONG MaxSepInSeconds
  3008. );
  3009. VOID
  3010. ExGetNextWakeTime (
  3011. OUT PULONGLONG DueTime,
  3012. OUT PTIME_FIELDS TimeFields,
  3013. OUT PVOID *TimerObject
  3014. );
  3015. // begin_ntddk begin_wdm begin_ntifs begin_ntosp
  3016. //
  3017. // Set timer resolution.
  3018. //
  3019. NTKERNELAPI
  3020. ULONG
  3021. ExSetTimerResolution (
  3022. IN ULONG DesiredTime,
  3023. IN BOOLEAN SetResolution
  3024. );
  3025. //
  3026. // Subtract time zone bias from system time to get local time.
  3027. //
  3028. NTKERNELAPI
  3029. VOID
  3030. ExSystemTimeToLocalTime (
  3031. IN PLARGE_INTEGER SystemTime,
  3032. OUT PLARGE_INTEGER LocalTime
  3033. );
  3034. //
  3035. // Add time zone bias to local time to get system time.
  3036. //
  3037. NTKERNELAPI
  3038. VOID
  3039. ExLocalTimeToSystemTime (
  3040. IN PLARGE_INTEGER LocalTime,
  3041. OUT PLARGE_INTEGER SystemTime
  3042. );
  3043. // end_ntddk end_wdm end_ntifs end_ntosp
  3044. NTKERNELAPI
  3045. VOID
  3046. ExInitializeTimeRefresh(
  3047. VOID
  3048. );
  3049. // begin_ntddk begin_wdm begin_ntifs begin_nthal begin_ntminiport begin_ntosp
  3050. //
  3051. // Define the type for Callback function.
  3052. //
  3053. typedef struct _CALLBACK_OBJECT *PCALLBACK_OBJECT;
  3054. typedef VOID (*PCALLBACK_FUNCTION ) (
  3055. IN PVOID CallbackContext,
  3056. IN PVOID Argument1,
  3057. IN PVOID Argument2
  3058. );
  3059. NTKERNELAPI
  3060. NTSTATUS
  3061. ExCreateCallback (
  3062. OUT PCALLBACK_OBJECT *CallbackObject,
  3063. IN POBJECT_ATTRIBUTES ObjectAttributes,
  3064. IN BOOLEAN Create,
  3065. IN BOOLEAN AllowMultipleCallbacks
  3066. );
  3067. NTKERNELAPI
  3068. PVOID
  3069. ExRegisterCallback (
  3070. IN PCALLBACK_OBJECT CallbackObject,
  3071. IN PCALLBACK_FUNCTION CallbackFunction,
  3072. IN PVOID CallbackContext
  3073. );
  3074. NTKERNELAPI
  3075. VOID
  3076. ExUnregisterCallback (
  3077. IN PVOID CallbackRegistration
  3078. );
  3079. NTKERNELAPI
  3080. VOID
  3081. ExNotifyCallback (
  3082. IN PVOID CallbackObject,
  3083. IN PVOID Argument1,
  3084. IN PVOID Argument2
  3085. );
  3086. // end_ntddk end_wdm end_ntifs end_nthal end_ntminiport end_ntosp
  3087. //
  3088. // System lookaside list structure list.
  3089. //
  3090. extern LIST_ENTRY ExSystemLookasideListHead;
  3091. //
  3092. // The current bias from GMT to LocalTime
  3093. //
  3094. extern LARGE_INTEGER ExpTimeZoneBias;
  3095. extern LONG ExpLastTimeZoneBias;
  3096. extern LONG ExpAltTimeZoneBias;
  3097. extern ULONG ExpCurrentTimeZoneId;
  3098. extern ULONG ExpRealTimeIsUniversal;
  3099. extern ULONG ExCriticalWorkerThreads;
  3100. extern ULONG ExDelayedWorkerThreads;
  3101. extern ULONG ExpTickCountMultiplier;
  3102. //
  3103. // Used for cmos clock sanity
  3104. //
  3105. extern BOOLEAN ExCmosClockIsSane;
  3106. //
  3107. // The lock handle for PAGELK section, initialized in init\init.c
  3108. //
  3109. extern PVOID ExPageLockHandle;
  3110. //
  3111. // Global executive callbacks
  3112. //
  3113. extern PCALLBACK_OBJECT ExCbSetSystemTime;
  3114. extern PCALLBACK_OBJECT ExCbSetSystemState;
  3115. extern PCALLBACK_OBJECT ExCbPowerState;
  3116. // begin_ntosp
  3117. typedef
  3118. PVOID
  3119. (*PKWIN32_GLOBALATOMTABLE_CALLOUT) ( void );
  3120. extern PKWIN32_GLOBALATOMTABLE_CALLOUT ExGlobalAtomTableCallout;
  3121. // end_ntosp
  3122. // begin_ntddk begin_ntosp begin_ntifs
  3123. //
  3124. // UUID Generation
  3125. //
  3126. typedef GUID UUID;
  3127. NTKERNELAPI
  3128. NTSTATUS
  3129. ExUuidCreate(
  3130. OUT UUID *Uuid
  3131. );
  3132. // end_ntddk end_ntosp end_ntifs
  3133. // begin_ntddk begin_wdm begin_ntifs
  3134. //
  3135. // suite support
  3136. //
  3137. NTKERNELAPI
  3138. BOOLEAN
  3139. ExVerifySuite(
  3140. SUITE_TYPE SuiteType
  3141. );
  3142. // end_ntddk end_wdm end_ntifs
  3143. // begin_ntosp
  3144. NTKERNELAPI
  3145. VOID
  3146. FASTCALL
  3147. ExfInitializeRundownProtection (
  3148. IN PEX_RUNDOWN_REF RunRef
  3149. );
  3150. NTKERNELAPI
  3151. VOID
  3152. FORCEINLINE
  3153. FASTCALL
  3154. ExInitializeRundownProtection (
  3155. IN PEX_RUNDOWN_REF RunRef
  3156. )
  3157. /*++
  3158. Routine Description:
  3159. Initialize rundown protection structure
  3160. Arguments:
  3161. RunRef - Rundown block to be referenced
  3162. Return Value:
  3163. None
  3164. --*/
  3165. {
  3166. RunRef->Count = 0;
  3167. }
  3168. //
  3169. // Reset a rundown protection block
  3170. //
  3171. NTKERNELAPI
  3172. VOID
  3173. FASTCALL
  3174. ExReInitializeRundownProtection (
  3175. IN PEX_RUNDOWN_REF RunRef
  3176. );
  3177. //
  3178. // Acquire rundown protection
  3179. //
  3180. NTKERNELAPI
  3181. BOOLEAN
  3182. FASTCALL
  3183. ExAcquireRundownProtection (
  3184. IN PEX_RUNDOWN_REF RunRef
  3185. );
  3186. NTKERNELAPI
  3187. BOOLEAN
  3188. FASTCALL
  3189. ExAcquireRundownProtectionEx (
  3190. IN PEX_RUNDOWN_REF RunRef,
  3191. IN ULONG Count
  3192. );
  3193. //
  3194. // Release rundown protection
  3195. //
  3196. NTKERNELAPI
  3197. VOID
  3198. FASTCALL
  3199. ExReleaseRundownProtection (
  3200. IN PEX_RUNDOWN_REF RunRef
  3201. );
  3202. NTKERNELAPI
  3203. VOID
  3204. FASTCALL
  3205. ExReleaseRundownProtectionEx (
  3206. IN PEX_RUNDOWN_REF RunRef,
  3207. IN ULONG Count
  3208. );
  3209. //
  3210. // Mark rundown block as rundown having been completed.
  3211. //
  3212. NTKERNELAPI
  3213. VOID
  3214. FASTCALL
  3215. ExRundownCompleted (
  3216. IN PEX_RUNDOWN_REF RunRef
  3217. );
  3218. //
  3219. // Wait for all protected acquires to exit
  3220. //
  3221. NTKERNELAPI
  3222. VOID
  3223. FASTCALL
  3224. ExWaitForRundownProtectionRelease (
  3225. IN PEX_RUNDOWN_REF RunRef
  3226. );
  3227. // end_ntosp
  3228. //
  3229. // Fast reference routines. See ntos\ob\fastref.c for algorithm description.
  3230. //
  3231. #if defined (_WIN64)
  3232. #define MAX_FAST_REFS 15
  3233. #else
  3234. #define MAX_FAST_REFS 7
  3235. #endif
  3236. typedef struct _EX_FAST_REF {
  3237. union {
  3238. PVOID Object;
  3239. #if defined (_WIN64)
  3240. ULONG_PTR RefCnt : 4;
  3241. #else
  3242. ULONG_PTR RefCnt : 3;
  3243. #endif
  3244. ULONG_PTR Value;
  3245. };
  3246. } EX_FAST_REF, *PEX_FAST_REF;
  3247. NTKERNELAPI
  3248. LOGICAL
  3249. FORCEINLINE
  3250. ExFastRefCanBeReferenced (
  3251. IN EX_FAST_REF FastRef
  3252. )
  3253. /*++
  3254. Routine Description:
  3255. This routine allows the caller to determine if the fast reference
  3256. structure contains cached references.
  3257. Arguments:
  3258. FastRef - Fast reference block to be used
  3259. Return Value:
  3260. LOGICAL - TRUE: There were cached references in the object,
  3261. FALSE: No cached references are available.
  3262. --*/
  3263. {
  3264. return FastRef.RefCnt != 0;
  3265. }
  3266. NTKERNELAPI
  3267. LOGICAL
  3268. FORCEINLINE
  3269. ExFastRefCanBeDereferenced (
  3270. IN EX_FAST_REF FastRef
  3271. )
  3272. /*++
  3273. Routine Description:
  3274. This routine allows the caller to determine if the fast reference
  3275. structure contains room for cached references.
  3276. Arguments:
  3277. FastRef - Fast reference block to be used
  3278. Return Value:
  3279. LOGICAL - TRUE: There is space for cached references in the object,
  3280. FALSE: No space was available.
  3281. --*/
  3282. {
  3283. return FastRef.RefCnt != MAX_FAST_REFS;
  3284. }
  3285. NTKERNELAPI
  3286. LOGICAL
  3287. FORCEINLINE
  3288. ExFastRefIsLastReference (
  3289. IN EX_FAST_REF FastRef
  3290. )
  3291. /*++
  3292. Routine Description:
  3293. This routine allows the caller to determine if the fast reference
  3294. structure contains only 1 cached reference.
  3295. Arguments:
  3296. FastRef - Fast reference block to be used
  3297. Return Value:
  3298. LOGICAL - TRUE: There is only one cached reference in the object,
  3299. FALSE: The is more or less than one cached reference available.
  3300. --*/
  3301. {
  3302. return FastRef.RefCnt == 1;
  3303. }
  3304. NTKERNELAPI
  3305. PVOID
  3306. FORCEINLINE
  3307. ExFastRefGetObject (
  3308. IN EX_FAST_REF FastRef
  3309. )
  3310. /*++
  3311. Routine Description:
  3312. This routine allows the caller to obtain the object pointer from a fast
  3313. reference structure.
  3314. Arguments:
  3315. FastRef - Fast reference block to be used
  3316. Return Value:
  3317. PVOID - The contained object or NULL if there isn't one.
  3318. --*/
  3319. {
  3320. return (PVOID) (FastRef.Value & ~MAX_FAST_REFS);
  3321. }
  3322. NTKERNELAPI
  3323. BOOLEAN
  3324. FORCEINLINE
  3325. ExFastRefObjectNull (
  3326. IN EX_FAST_REF FastRef
  3327. )
  3328. /*++
  3329. Routine Description:
  3330. This routine allows the caller to test of the specified fastref value
  3331. has a null pointer
  3332. Arguments:
  3333. FastRef - Fast reference block to be used
  3334. Return Value:
  3335. BOOLEAN - TRUE if the object is NULL FALSE otherwise
  3336. --*/
  3337. {
  3338. return (BOOLEAN) (FastRef.Value == 0);
  3339. }
  3340. NTKERNELAPI
  3341. BOOLEAN
  3342. FORCEINLINE
  3343. ExFastRefEqualObjects (
  3344. IN EX_FAST_REF FastRef,
  3345. IN PVOID Object
  3346. )
  3347. /*++
  3348. Routine Description:
  3349. This routine allows the caller to test of the specified fastref contains
  3350. the specified object
  3351. Arguments:
  3352. FastRef - Fast reference block to be used
  3353. Return Value:
  3354. BOOLEAN - TRUE if the object matches FALSE otherwise
  3355. --*/
  3356. {
  3357. return (BOOLEAN)((FastRef.Value^(ULONG_PTR)Object) <= MAX_FAST_REFS);
  3358. }
  3359. NTKERNELAPI
  3360. ULONG
  3361. FORCEINLINE
  3362. ExFastRefGetUnusedReferences (
  3363. IN EX_FAST_REF FastRef
  3364. )
  3365. /*++
  3366. Routine Description:
  3367. This routine allows the caller to obtain the number of cached refrences
  3368. in the fast reference structure.
  3369. Arguments:
  3370. FastRef - Fast reference block to be used
  3371. Return Value:
  3372. ULONG - The number of cached references.
  3373. --*/
  3374. {
  3375. return (ULONG) FastRef.RefCnt;
  3376. }
  3377. NTKERNELAPI
  3378. VOID
  3379. FORCEINLINE
  3380. ExFastRefInitialize (
  3381. IN PEX_FAST_REF FastRef,
  3382. IN PVOID Object OPTIONAL
  3383. )
  3384. /*++
  3385. Routine Description:
  3386. This routine initializes fast reference structure.
  3387. Arguments:
  3388. FastRef - Fast reference block to be used
  3389. Object - Object pointer to be assigned to the fast reference
  3390. Return Value:
  3391. None.
  3392. --*/
  3393. {
  3394. ASSERT ((((ULONG_PTR)Object)&MAX_FAST_REFS) == 0);
  3395. if (Object == NULL) {
  3396. FastRef->Object = NULL;
  3397. } else {
  3398. FastRef->Value = (ULONG_PTR) Object | MAX_FAST_REFS;
  3399. }
  3400. }
  3401. NTKERNELAPI
  3402. VOID
  3403. FORCEINLINE
  3404. ExFastRefInitializeEx (
  3405. IN PEX_FAST_REF FastRef,
  3406. IN PVOID Object OPTIONAL,
  3407. IN ULONG AdditionalRefs
  3408. )
  3409. /*++
  3410. Routine Description:
  3411. This routine initializes fast reference structure with the specified additional references.
  3412. Arguments:
  3413. FastRef - Fast reference block to be used
  3414. Object - Object pointer to be assigned to the fast reference
  3415. AditionalRefs - Number of additional refs to add to the object
  3416. Return Value:
  3417. None
  3418. --*/
  3419. {
  3420. ASSERT (AdditionalRefs <= MAX_FAST_REFS);
  3421. ASSERT ((((ULONG_PTR)Object)&MAX_FAST_REFS) == 0);
  3422. if (Object == NULL) {
  3423. FastRef->Object = NULL;
  3424. } else {
  3425. FastRef->Value = (ULONG_PTR) Object + AdditionalRefs;
  3426. }
  3427. }
  3428. NTKERNELAPI
  3429. ULONG
  3430. FORCEINLINE
  3431. ExFastRefGetAdditionalReferenceCount (
  3432. VOID
  3433. )
  3434. {
  3435. return MAX_FAST_REFS;
  3436. }
  3437. NTKERNELAPI
  3438. EX_FAST_REF
  3439. FORCEINLINE
  3440. ExFastReference (
  3441. IN PEX_FAST_REF FastRef
  3442. )
  3443. /*++
  3444. Routine Description:
  3445. This routine attempts to obtain a fast (cached) reference from a fast
  3446. reference structure.
  3447. Arguments:
  3448. FastRef - Fast reference block to be used
  3449. Return Value:
  3450. EX_FAST_REF - The old or current contents of the fast reference structure.
  3451. --*/
  3452. {
  3453. EX_FAST_REF OldRef, NewRef;
  3454. while (1) {
  3455. //
  3456. // Fetch the old contents of the fast ref structure
  3457. //
  3458. OldRef = *FastRef;
  3459. //
  3460. // If the object pointer is null or if there are no cached references
  3461. // left then bail. In the second case this reference will need to be
  3462. // taken while holding the lock. Both cases are covered by the single
  3463. // test of the lower bits since a null pointer can never have cached
  3464. // refs.
  3465. //
  3466. if (OldRef.RefCnt != 0) {
  3467. //
  3468. // We know the bottom bits can't underflow into the pointer for a
  3469. // request that works so just decrement
  3470. //
  3471. NewRef.Value = OldRef.Value - 1;
  3472. NewRef.Object = InterlockedCompareExchangePointer (&FastRef->Object,
  3473. NewRef.Object,
  3474. OldRef.Object);
  3475. if (NewRef.Object != OldRef.Object) {
  3476. //
  3477. // The structured changed beneath us. Try the operation again
  3478. //
  3479. continue;
  3480. }
  3481. }
  3482. break;
  3483. }
  3484. return OldRef;
  3485. }
  3486. NTKERNELAPI
  3487. LOGICAL
  3488. FORCEINLINE
  3489. ExFastRefDereference (
  3490. IN PEX_FAST_REF FastRef,
  3491. IN PVOID Object
  3492. )
  3493. /*++
  3494. Routine Description:
  3495. This routine attempts to release a fast reference from a fast ref
  3496. structure. This routine could be called for a reference obtained
  3497. directly from the object but preumably the chances of the pointer
  3498. matching would be unlikely. The algorithm will work correctly in this
  3499. case.
  3500. Arguments:
  3501. FastRef - Fast reference block to be used
  3502. Object - The original object that the reference was taken on.
  3503. Return Value:
  3504. LOGICAL - TRUE: The fast dereference worked ok, FALSE: the
  3505. dereference didn't.
  3506. --*/
  3507. {
  3508. EX_FAST_REF OldRef, NewRef;
  3509. ASSERT ((((ULONG_PTR)Object)&MAX_FAST_REFS) == 0);
  3510. ASSERT (Object != NULL);
  3511. while (1) {
  3512. //
  3513. // Fetch the old contents of the fast ref structure
  3514. //
  3515. OldRef = *FastRef;
  3516. //
  3517. // If the reference cache is fully populated or the pointer has
  3518. // changed to another object then just return the old value. The
  3519. // caller can return the reference to the object instead.
  3520. //
  3521. if ((OldRef.Value^(ULONG_PTR)Object) >= MAX_FAST_REFS) {
  3522. return FALSE;
  3523. }
  3524. //
  3525. // We know the bottom bits can't overflow into the pointer so just
  3526. // increment
  3527. //
  3528. NewRef.Value = OldRef.Value + 1;
  3529. NewRef.Object = InterlockedCompareExchangePointer (&FastRef->Object,
  3530. NewRef.Object,
  3531. OldRef.Object);
  3532. if (NewRef.Object != OldRef.Object) {
  3533. //
  3534. // The structured changed beneath us. Try the operation again
  3535. //
  3536. continue;
  3537. }
  3538. break;
  3539. }
  3540. return TRUE;
  3541. }
  3542. NTKERNELAPI
  3543. LOGICAL
  3544. FORCEINLINE
  3545. ExFastRefAddAdditionalReferenceCounts (
  3546. IN PEX_FAST_REF FastRef,
  3547. IN PVOID Object,
  3548. IN ULONG RefsToAdd
  3549. )
  3550. /*++
  3551. Routine Description:
  3552. This routine attempts to update the cached references on structure to
  3553. allow future callers to run lock free. Callers must have already biased
  3554. the object by the RefsToAdd reference count. This operation can fail at
  3555. which point the caller should removed the extra references added and
  3556. continue.
  3557. Arguments:
  3558. FastRef - Fast reference block to be used
  3559. Object - The original object that has had its reference count biased.
  3560. RefsToAdd - The number of references to add to the cache
  3561. Return Value:
  3562. LOGICAL - TRUE: The references where cached ok, FALSE: The references
  3563. could not be cached.
  3564. --*/
  3565. {
  3566. EX_FAST_REF OldRef, NewRef;
  3567. ASSERT (RefsToAdd <= MAX_FAST_REFS);
  3568. ASSERT ((((ULONG_PTR)Object)&MAX_FAST_REFS) == 0);
  3569. while (1) {
  3570. //
  3571. // Fetch the old contents of the fast ref structure
  3572. //
  3573. OldRef = *FastRef;
  3574. //
  3575. // If the count would push us above maximum cached references or
  3576. // if the object pointer has changed the fail the request.
  3577. //
  3578. if (OldRef.RefCnt + RefsToAdd > MAX_FAST_REFS ||
  3579. (ULONG_PTR) Object != (OldRef.Value & ~MAX_FAST_REFS)) {
  3580. return FALSE;
  3581. }
  3582. //
  3583. // We know the bottom bits can't overflow into the pointer so just
  3584. // increment
  3585. //
  3586. NewRef.Value = OldRef.Value + RefsToAdd;
  3587. NewRef.Object = InterlockedCompareExchangePointer (&FastRef->Object,
  3588. NewRef.Object,
  3589. OldRef.Object);
  3590. if (NewRef.Object != OldRef.Object) {
  3591. //
  3592. // The structured changed beneath us. Use the return value from the
  3593. // exchange and try it all again.
  3594. //
  3595. continue;
  3596. }
  3597. break;
  3598. }
  3599. return TRUE;
  3600. }
  3601. NTKERNELAPI
  3602. EX_FAST_REF
  3603. FORCEINLINE
  3604. ExFastRefSwapObject (
  3605. IN PEX_FAST_REF FastRef,
  3606. IN PVOID Object
  3607. )
  3608. /*++
  3609. Routine Description:
  3610. This routine attempts to replace the current object with a new object.
  3611. This routine must be called while holding the lock that protects the
  3612. pointer field if concurrency with the slow ref path is possible.
  3613. Its also possible to obtain and drop the lock after this operation has
  3614. completed to force all the slow referencers from the slow reference path.
  3615. Arguments:
  3616. FastRef - Fast reference block to be used
  3617. Object - The new object that is to be placed in the structure. This
  3618. object must have already had its reference count biased by
  3619. the caller to account for the reference cache.
  3620. Return Value:
  3621. EX_FAST_REF - The old contents of the fast reference structure.
  3622. --*/
  3623. {
  3624. EX_FAST_REF OldRef;
  3625. EX_FAST_REF NewRef;
  3626. ASSERT ((((ULONG_PTR)Object)&MAX_FAST_REFS) == 0);
  3627. if (Object != NULL) {
  3628. NewRef.Value = (ULONG_PTR) Object | MAX_FAST_REFS;
  3629. } else {
  3630. NewRef.Value = 0;
  3631. }
  3632. OldRef.Object = InterlockedExchangePointer (&FastRef->Object, NewRef.Object);
  3633. return OldRef;
  3634. }
  3635. NTKERNELAPI
  3636. EX_FAST_REF
  3637. FORCEINLINE
  3638. ExFastRefCompareSwapObject (
  3639. IN PEX_FAST_REF FastRef,
  3640. IN PVOID Object,
  3641. IN PVOID OldObject
  3642. )
  3643. /*++
  3644. Routine Description:
  3645. This routine attempts to replace the current object with a new object if
  3646. the current object matches the old object.
  3647. This routine must be called while holding the lock that protects the
  3648. pointer field if concurrency with the slow ref path is possible.
  3649. Its also possible to obtain and drop the lock after this operation has
  3650. completed to force all the slow referencers from the slow reference path.
  3651. Arguments:
  3652. FastRef - Fast reference block to be used
  3653. Object - The new object that is to be placed in the structure. This
  3654. object must have already had its reference count biased by
  3655. the caller to account for the reference cache.
  3656. OldObject - The object that must match the current object for the
  3657. swap to occure.
  3658. Return Value:
  3659. EX_FAST_REF - The old contents of the fast reference structure.
  3660. --*/
  3661. {
  3662. EX_FAST_REF OldRef;
  3663. EX_FAST_REF NewRef;
  3664. ASSERT ((((ULONG_PTR)Object)&MAX_FAST_REFS) == 0);
  3665. while (1) {
  3666. //
  3667. // Fetch the old contents of the fast ref structure
  3668. //
  3669. OldRef = *FastRef;
  3670. //
  3671. // Compare the current object to the old to see if a swap is possible.
  3672. //
  3673. if (!ExFastRefEqualObjects (OldRef, OldObject)) {
  3674. return OldRef;
  3675. }
  3676. if (Object != NULL) {
  3677. NewRef.Value = (ULONG_PTR) Object | MAX_FAST_REFS;
  3678. } else {
  3679. NewRef.Value = (ULONG_PTR) Object;
  3680. }
  3681. NewRef.Object = InterlockedCompareExchangePointer (&FastRef->Object,
  3682. NewRef.Object,
  3683. OldRef.Object);
  3684. if (NewRef.Object != OldRef.Object) {
  3685. //
  3686. // The structured changed beneath us. Try it all again.
  3687. //
  3688. continue;
  3689. }
  3690. break;
  3691. }
  3692. return OldRef;
  3693. }
  3694. NTKERNELAPI
  3695. VOID
  3696. FORCEINLINE
  3697. ExInitializePushLock (
  3698. IN PEX_PUSH_LOCK PushLock
  3699. )
  3700. /*++
  3701. Routine Description:
  3702. Initialize a push lock structure
  3703. Arguments:
  3704. PushLock - Push lock to be initialized
  3705. Return Value:
  3706. None
  3707. --*/
  3708. {
  3709. PushLock->Value = 0;
  3710. }
  3711. NTKERNELAPI
  3712. VOID
  3713. FASTCALL
  3714. ExfAcquirePushLockExclusive (
  3715. IN PEX_PUSH_LOCK PushLock
  3716. );
  3717. NTKERNELAPI
  3718. VOID
  3719. FASTCALL
  3720. ExfAcquirePushLockShared (
  3721. IN PEX_PUSH_LOCK PushLock
  3722. );
  3723. NTKERNELAPI
  3724. VOID
  3725. FASTCALL
  3726. ExfReleasePushLock (
  3727. IN PEX_PUSH_LOCK PushLock
  3728. );
  3729. NTKERNELAPI
  3730. VOID
  3731. FORCEINLINE
  3732. ExAcquireReleasePushLockExclusive (
  3733. IN PEX_PUSH_LOCK PushLock
  3734. )
  3735. /*++
  3736. Routine Description:
  3737. Acquire a push lock exclusively and immediately release it
  3738. Arguments:
  3739. PushLock - Push lock to be acquired and released
  3740. Return Value:
  3741. None
  3742. --*/
  3743. {
  3744. KeMemoryBarrier ();
  3745. if ((volatile EX_PUSH_LOCK *)PushLock->Ptr != NULL) {
  3746. ExfAcquirePushLockExclusive (PushLock);
  3747. ExfReleasePushLock (PushLock);
  3748. }
  3749. }
  3750. NTKERNELAPI
  3751. BOOLEAN
  3752. FORCEINLINE
  3753. ExTryAcquireReleasePushLockExclusive (
  3754. IN PEX_PUSH_LOCK PushLock
  3755. )
  3756. /*++
  3757. Routine Description:
  3758. Try to acquire a push lock exclusively and immediately release it
  3759. Arguments:
  3760. PushLock - Push lock to be acquired and released
  3761. Return Value:
  3762. BOOLEAN - TRUE: The lock was acquired, FALSE: The lock was not acquired
  3763. --*/
  3764. {
  3765. KeMemoryBarrier ();
  3766. if ((volatile EX_PUSH_LOCK *)PushLock->Ptr == NULL) {
  3767. return TRUE;
  3768. } else {
  3769. return FALSE;
  3770. }
  3771. }
  3772. NTKERNELAPI
  3773. VOID
  3774. FORCEINLINE
  3775. ExAcquirePushLockExclusive (
  3776. IN PEX_PUSH_LOCK PushLock
  3777. )
  3778. /*++
  3779. Routine Description:
  3780. Acquire a push lock exclusively
  3781. Arguments:
  3782. PushLock - Push lock to be acquired
  3783. Return Value:
  3784. None
  3785. --*/
  3786. {
  3787. if (InterlockedCompareExchangePointer (&PushLock->Ptr,
  3788. (PVOID)EX_PUSH_LOCK_EXCLUSIVE,
  3789. NULL) != NULL) {
  3790. ExfAcquirePushLockExclusive (PushLock);
  3791. }
  3792. }
  3793. NTKERNELAPI
  3794. BOOLEAN
  3795. FORCEINLINE
  3796. ExTryAcquirePushLockExclusive (
  3797. IN PEX_PUSH_LOCK PushLock
  3798. )
  3799. /*++
  3800. Routine Description:
  3801. Try and acquire a push lock exclusively
  3802. Arguments:
  3803. PushLock - Push lock to be acquired
  3804. Return Value:
  3805. BOOLEAN - TRUE: Acquire was successfull, FALSE: Lock was already acquired
  3806. --*/
  3807. {
  3808. if (InterlockedCompareExchangePointer (&PushLock->Ptr,
  3809. (PVOID)EX_PUSH_LOCK_EXCLUSIVE,
  3810. NULL) == NULL) {
  3811. return TRUE;
  3812. } else {
  3813. return FALSE;
  3814. }
  3815. }
  3816. NTKERNELAPI
  3817. VOID
  3818. FORCEINLINE
  3819. ExAcquirePushLockShared (
  3820. IN PEX_PUSH_LOCK PushLock
  3821. )
  3822. /*++
  3823. Routine Description:
  3824. Acquire a push lock shared
  3825. Arguments:
  3826. PushLock - Push lock to be acquired
  3827. Return Value:
  3828. None
  3829. --*/
  3830. {
  3831. EX_PUSH_LOCK OldValue, NewValue;
  3832. OldValue = *PushLock;
  3833. OldValue.Value &= ~(EX_PUSH_LOCK_EXCLUSIVE | EX_PUSH_LOCK_WAITING);
  3834. NewValue.Value = OldValue.Value + EX_PUSH_LOCK_SHARE_INC;
  3835. if (InterlockedCompareExchangePointer (&PushLock->Ptr,
  3836. NewValue.Ptr,
  3837. OldValue.Ptr) != OldValue.Ptr) {
  3838. ExfAcquirePushLockShared (PushLock);
  3839. }
  3840. }
  3841. NTKERNELAPI
  3842. BOOLEAN
  3843. FORCEINLINE
  3844. ExTryConvertPushLockSharedToExclusive (
  3845. IN PEX_PUSH_LOCK PushLock
  3846. )
  3847. /*++
  3848. Routine Description:
  3849. Attempts to convert a shared acquire to exclusive. If other sharers or waiters are present
  3850. the function fails.
  3851. Arguments:
  3852. PushLock - Push lock to be acquired
  3853. Return Value:
  3854. BOOLEAN - TRUE: Conversion worked ok, FALSE: The conversion could not be achieved
  3855. --*/
  3856. {
  3857. if (InterlockedCompareExchangePointer (&PushLock->Ptr, (PVOID) EX_PUSH_LOCK_EXCLUSIVE,
  3858. (PVOID) EX_PUSH_LOCK_SHARE_INC) ==
  3859. (PVOID)EX_PUSH_LOCK_SHARE_INC) {
  3860. return TRUE;
  3861. } else {
  3862. return FALSE;
  3863. }
  3864. }
  3865. NTKERNELAPI
  3866. VOID
  3867. FORCEINLINE
  3868. ExReleasePushLock (
  3869. IN PEX_PUSH_LOCK PushLock
  3870. )
  3871. /*++
  3872. Routine Description:
  3873. Release a push lock that was acquired exclusively or shared
  3874. Arguments:
  3875. PushLock - Push lock to be released
  3876. Return Value:
  3877. None
  3878. --*/
  3879. {
  3880. EX_PUSH_LOCK OldValue, NewValue;
  3881. OldValue = *PushLock;
  3882. OldValue.Value &= ~EX_PUSH_LOCK_WAITING;
  3883. NewValue.Value = (OldValue.Value - EX_PUSH_LOCK_EXCLUSIVE) &
  3884. ~EX_PUSH_LOCK_EXCLUSIVE;
  3885. if (InterlockedCompareExchangePointer (&PushLock->Ptr,
  3886. NewValue.Ptr,
  3887. OldValue.Ptr) != OldValue.Ptr) {
  3888. ExfReleasePushLock (PushLock);
  3889. }
  3890. }
  3891. NTKERNELAPI
  3892. VOID
  3893. FORCEINLINE
  3894. ExReleasePushLockExclusive (
  3895. IN PEX_PUSH_LOCK PushLock
  3896. )
  3897. /*++
  3898. Routine Description:
  3899. Release a push lock that was acquired exclusively
  3900. Arguments:
  3901. PushLock - Push lock to be released
  3902. Return Value:
  3903. None
  3904. --*/
  3905. {
  3906. ASSERT (PushLock->Value & (EX_PUSH_LOCK_WAITING|EX_PUSH_LOCK_EXCLUSIVE));
  3907. if (InterlockedCompareExchangePointer (&PushLock->Ptr,
  3908. NULL,
  3909. (PVOID)EX_PUSH_LOCK_EXCLUSIVE) != (PVOID)EX_PUSH_LOCK_EXCLUSIVE) {
  3910. ExfReleasePushLock (PushLock);
  3911. }
  3912. }
  3913. NTKERNELAPI
  3914. VOID
  3915. FORCEINLINE
  3916. ExReleasePushLockShared (
  3917. IN PEX_PUSH_LOCK PushLock
  3918. )
  3919. /*++
  3920. Routine Description:
  3921. Release a push lock that was acquired shared
  3922. Arguments:
  3923. PushLock - Push lock to be released
  3924. Return Value:
  3925. None
  3926. --*/
  3927. {
  3928. EX_PUSH_LOCK OldValue, NewValue;
  3929. OldValue = *PushLock;
  3930. ASSERT (OldValue.Waiting || !OldValue.Exclusive);
  3931. OldValue.Value &= ~EX_PUSH_LOCK_WAITING;
  3932. NewValue.Value = OldValue.Value - EX_PUSH_LOCK_SHARE_INC;
  3933. if (InterlockedCompareExchangePointer (&PushLock->Ptr,
  3934. NewValue.Ptr,
  3935. OldValue.Ptr) != OldValue.Ptr) {
  3936. ExfReleasePushLock (PushLock);
  3937. }
  3938. }
  3939. //
  3940. // This is a block held on the local stack of the waiting threads.
  3941. //
  3942. typedef struct _EX_PUSH_LOCK_WAIT_BLOCK *PEX_PUSH_LOCK_WAIT_BLOCK;
  3943. typedef struct _EX_PUSH_LOCK_WAIT_BLOCK {
  3944. KEVENT WakeEvent;
  3945. PEX_PUSH_LOCK_WAIT_BLOCK Next;
  3946. ULONG ShareCount;
  3947. BOOLEAN Exclusive;
  3948. } EX_PUSH_LOCK_WAIT_BLOCK;
  3949. NTKERNELAPI
  3950. VOID
  3951. FASTCALL
  3952. ExBlockPushLock (
  3953. IN PEX_PUSH_LOCK PushLock,
  3954. IN PEX_PUSH_LOCK_WAIT_BLOCK WaitBlock
  3955. );
  3956. NTKERNELAPI
  3957. VOID
  3958. FASTCALL
  3959. ExfUnblockPushLock (
  3960. IN PEX_PUSH_LOCK PushLock,
  3961. IN PEX_PUSH_LOCK_WAIT_BLOCK WaitBlock OPTIONAL
  3962. );
  3963. NTKERNELAPI
  3964. VOID
  3965. FORCEINLINE
  3966. ExUnblockPushLock (
  3967. IN PEX_PUSH_LOCK PushLock,
  3968. IN PEX_PUSH_LOCK_WAIT_BLOCK WaitBlock OPTIONAL
  3969. )
  3970. {
  3971. if (WaitBlock != NULL || PushLock->Ptr != NULL) {
  3972. ExfUnblockPushLock (PushLock, WaitBlock);
  3973. }
  3974. }
  3975. NTKERNELAPI
  3976. VOID
  3977. FORCEINLINE
  3978. ExWaitForUnblockPushLock (
  3979. IN PEX_PUSH_LOCK PushLock,
  3980. IN PEX_PUSH_LOCK_WAIT_BLOCK WaitBlock OPTIONAL
  3981. )
  3982. {
  3983. UNREFERENCED_PARAMETER (PushLock);
  3984. KeWaitForSingleObject (&WaitBlock->WakeEvent,
  3985. Executive,
  3986. KernelMode,
  3987. FALSE,
  3988. NULL);
  3989. }
  3990. NTKERNELAPI
  3991. PEX_PUSH_LOCK_CACHE_AWARE
  3992. ExAllocateCacheAwarePushLock (
  3993. VOID
  3994. );
  3995. NTKERNELAPI
  3996. VOID
  3997. ExFreeCacheAwarePushLock (
  3998. PEX_PUSH_LOCK_CACHE_AWARE PushLock
  3999. );
  4000. NTKERNELAPI
  4001. VOID
  4002. ExAcquireCacheAwarePushLockExclusive (
  4003. IN PEX_PUSH_LOCK_CACHE_AWARE CacheAwarePushLock
  4004. );
  4005. NTKERNELAPI
  4006. VOID
  4007. ExReleaseCacheAwarePushLockExclusive (
  4008. IN PEX_PUSH_LOCK_CACHE_AWARE CacheAwarePushLock
  4009. );
  4010. NTKERNELAPI
  4011. PEX_PUSH_LOCK
  4012. FORCEINLINE
  4013. ExAcquireCacheAwarePushLockShared (
  4014. IN PEX_PUSH_LOCK_CACHE_AWARE CacheAwarePushLock
  4015. )
  4016. /*++
  4017. Routine Description:
  4018. Acquire a cache aware push lock shared.
  4019. Arguments:
  4020. PushLock - Cache aware push lock to be acquired
  4021. Return Value:
  4022. None
  4023. --*/
  4024. {
  4025. PEX_PUSH_LOCK PushLock;
  4026. //
  4027. // Take a single one of the slots in shared mode.
  4028. // Exclusive acquires must obtain all the slots exclusive.
  4029. //
  4030. PushLock = CacheAwarePushLock->Locks[KeGetCurrentProcessorNumber()%EX_PUSH_LOCK_FANNED_COUNT];
  4031. ExAcquirePushLockShared (PushLock);
  4032. return PushLock;
  4033. }
  4034. NTKERNELAPI
  4035. VOID
  4036. FORCEINLINE
  4037. ExReleaseCacheAwarePushLockShared (
  4038. IN PEX_PUSH_LOCK PushLock
  4039. )
  4040. /*++
  4041. Routine Description:
  4042. Acquire a cache aware push lock shared.
  4043. Arguments:
  4044. PushLock - Part of cache aware push lock returned by ExAcquireCacheAwarePushLockShared
  4045. Return Value:
  4046. None
  4047. --*/
  4048. {
  4049. ExReleasePushLockShared (PushLock);
  4050. return;
  4051. }
  4052. //
  4053. // Define low overhead callbacks for thread create etc
  4054. //
  4055. // begin_wdm begin_ntddk
  4056. //
  4057. // Define a block to hold the actual routine registration.
  4058. //
  4059. typedef NTSTATUS (*PEX_CALLBACK_FUNCTION ) (
  4060. IN PVOID CallbackContext,
  4061. IN PVOID Argument1,
  4062. IN PVOID Argument2
  4063. );
  4064. // end_wdm end_ntddk
  4065. typedef struct _EX_CALLBACK_ROUTINE_BLOCK {
  4066. EX_RUNDOWN_REF RundownProtect;
  4067. PEX_CALLBACK_FUNCTION Function;
  4068. PVOID Context;
  4069. } EX_CALLBACK_ROUTINE_BLOCK, *PEX_CALLBACK_ROUTINE_BLOCK;
  4070. //
  4071. // Define a structure the caller uses to hold the callbacks
  4072. //
  4073. typedef struct _EX_CALLBACK {
  4074. EX_FAST_REF RoutineBlock;
  4075. } EX_CALLBACK, *PEX_CALLBACK;
  4076. VOID
  4077. ExInitializeCallBack (
  4078. IN OUT PEX_CALLBACK CallBack
  4079. );
  4080. BOOLEAN
  4081. ExCompareExchangeCallBack (
  4082. IN OUT PEX_CALLBACK CallBack,
  4083. IN PEX_CALLBACK_ROUTINE_BLOCK NewBlock,
  4084. IN PEX_CALLBACK_ROUTINE_BLOCK OldBlock
  4085. );
  4086. NTSTATUS
  4087. ExCallCallBack (
  4088. IN OUT PEX_CALLBACK CallBack,
  4089. IN PVOID Argument1,
  4090. IN PVOID Argument2
  4091. );
  4092. PEX_CALLBACK_ROUTINE_BLOCK
  4093. ExAllocateCallBack (
  4094. IN PEX_CALLBACK_FUNCTION Function,
  4095. IN PVOID Context
  4096. );
  4097. VOID
  4098. ExFreeCallBack (
  4099. IN PEX_CALLBACK_ROUTINE_BLOCK CallBackBlock
  4100. );
  4101. PEX_CALLBACK_ROUTINE_BLOCK
  4102. ExReferenceCallBackBlock (
  4103. IN OUT PEX_CALLBACK CallBack
  4104. );
  4105. PEX_CALLBACK_FUNCTION
  4106. ExGetCallBackBlockRoutine (
  4107. IN PEX_CALLBACK_ROUTINE_BLOCK CallBackBlock
  4108. );
  4109. PVOID
  4110. ExGetCallBackBlockContext (
  4111. IN PEX_CALLBACK_ROUTINE_BLOCK CallBackBlock
  4112. );
  4113. VOID
  4114. ExDereferenceCallBackBlock (
  4115. IN OUT PEX_CALLBACK CallBack,
  4116. IN PEX_CALLBACK_ROUTINE_BLOCK CallBackBlock
  4117. );
  4118. VOID
  4119. ExWaitForCallBacks (
  4120. IN PEX_CALLBACK_ROUTINE_BLOCK CallBackBlock
  4121. );
  4122. #endif /* _EX_ */