1 #ifndef __NTOSKRNL_INCLUDE_INTERNAL_EXECUTIVE_H
2 #define __NTOSKRNL_INCLUDE_INTERNAL_EXECUTIVE_H
4 /* GLOBAL VARIABLES *********************************************************/
6 extern TIME_ZONE_INFORMATION ExpTimeZoneInfo
;
7 extern LARGE_INTEGER ExpTimeZoneBias
;
8 extern ULONG ExpTimeZoneId
;
9 extern ULONG ExpTickCountMultiplier
;
10 extern ULONG ExpLastTimeZoneBias
;
11 extern POBJECT_TYPE ExEventPairObjectType
;
12 extern POBJECT_TYPE _ExEventObjectType
, _ExSemaphoreObjectType
;
13 extern ULONG NtBuildNumber
;
14 extern ULONG NtMajorVersion
;
15 extern ULONG NtMinorVersion
;
16 extern FAST_MUTEX ExpEnvironmentLock
;
17 extern ERESOURCE ExpFirmwareTableResource
;
18 extern LIST_ENTRY ExpFirmwareTableProviderListHead
;
19 extern BOOLEAN ExpIsWinPEMode
;
20 ULONG ExpAnsiCodePageDataOffset
, ExpOemCodePageDataOffset
;
21 ULONG ExpUnicodeCaseTableDataOffset
;
22 PVOID ExpNlsSectionPointer
;
24 typedef struct _EXHANDLE
33 HANDLE GenericHandleOverlay
;
36 } EXHANDLE
, *PEXHANDLE
;
38 typedef struct _ETIMER
43 LIST_ENTRY ActiveTimerListEntry
;
46 BOOLEAN ApcAssociated
;
48 LIST_ENTRY WakeTimerListEntry
;
53 PCALLBACK_OBJECT
*CallbackObject
;
57 #define MAX_FAST_REFS 7
59 /* Note: we only use a spinlock on SMP. On UP, we cli/sti intead */
61 #define ExAcquireResourceLock(l, i) { \
65 #define ExReleaseResourceLock(l, i) _enable();
67 #define ExAcquireResourceLock(l, i) KeAcquireSpinLock(l, i);
68 #define ExReleaseResourceLock(l, i) KeReleaseSpinLock(l, i);
71 #define ExAcquireRundownProtection _ExAcquireRundownProtection
72 #define ExReleaseRundownProtection _ExReleaseRundownProtection
73 #define ExInitializeRundownProtection _ExInitializeRundownProtection
74 #define ExWaitForRundownProtectionRelease _ExWaitForRundownProtectionRelease
75 #define ExRundownCompleted _ExRundownCompleted
76 #define ExGetPreviousMode KeGetPreviousMode
80 // Various bits tagged on the handle or handle table
82 #define EXHANDLE_TABLE_ENTRY_LOCK_BIT 1
83 #define FREE_HANDLE_MASK -1
86 // Number of entries in each table level
88 #define LOW_LEVEL_ENTRIES (PAGE_SIZE / sizeof(HANDLE_TABLE_ENTRY))
89 #define MID_LEVEL_ENTRIES (PAGE_SIZE / sizeof(PHANDLE_TABLE_ENTRY))
90 #define HIGH_LEVEL_ENTRIES (65535 / (LOW_LEVEL_ENTRIES * MID_LEVEL_ENTRIES))
93 // Maximum index in each table level before we need another table
95 #define MAX_LOW_INDEX LOW_LEVEL_ENTRIES
96 #define MAX_MID_INDEX (MID_LEVEL_ENTRIES * LOW_LEVEL_ENTRIES)
97 #define MAX_HIGH_INDEX (MID_LEVEL_ENTRIES * MID_LEVEL_ENTRIES * LOW_LEVEL_ENTRIES)
102 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40102
105 // Broken GCC with Alignment Bug. We'll do alignment ourselves at higher cost.
107 #define DEFINE_WAIT_BLOCK(x) \
111 EX_PUSH_LOCK_WAIT_BLOCK UnalignedBlock; \
113 PEX_PUSH_LOCK_WAIT_BLOCK x = (PEX_PUSH_LOCK_WAIT_BLOCK) \
114 ((ULONG_PTR)&WaitBlockBuffer.UnalignedBlock &~ 0xF);
119 // This is only for compatibility; the compiler will optimize the extra
120 // local variable (the actual pointer) away, so we don't take any perf hit
123 #define DEFINE_WAIT_BLOCK(x) \
124 EX_PUSH_LOCK_WAIT_BLOCK WaitBlockBuffer; \
125 PEX_PUSH_LOCK_WAIT_BLOCK x = &WaitBlockBuffer;
129 /* INITIALIZATION FUNCTIONS *************************************************/
147 ExpInitializePushLocks(VOID
);
151 ExRefreshTimeZoneInformation(
152 IN PLARGE_INTEGER SystemBootTime
157 ExpInitializeWorkerThreads(VOID
);
161 ExpInitLookasideLists(VOID
);
165 ExInitializeSystemLookasideList(
166 IN PGENERAL_LOOKASIDE List
,
170 IN USHORT MaximumDepth
,
171 IN PLIST_ENTRY ListHead
176 ExpInitializeCallbacks(VOID
);
184 ExpInitializeExecutive(
186 IN PLOADER_PARAMETER_BLOCK LoaderBlock
191 ExpInitializeEventImplementation(VOID
);
195 ExpInitializeEventImplementation(VOID
);
199 ExpInitializeEventPairImplementation(VOID
);
203 ExpInitializeSemaphoreImplementation(VOID
);
207 ExpInitializeMutantImplementation(VOID
);
211 ExpInitializeTimerImplementation(VOID
);
215 ExpInitializeProfileImplementation(VOID
);
219 ExpResourceInitialization(VOID
);
223 ExInitPoolLookasidePointers(VOID
);
225 /* Callback Functions ********************************************************/
229 ExInitializeCallBack(
230 IN OUT PEX_CALLBACK Callback
233 PEX_CALLBACK_ROUTINE_BLOCK
236 IN PEX_CALLBACK_FUNCTION Function
,
243 IN PEX_CALLBACK_ROUTINE_BLOCK CallbackRoutineBlock
248 ExCompareExchangeCallBack (
249 IN OUT PEX_CALLBACK CallBack
,
250 IN PEX_CALLBACK_ROUTINE_BLOCK NewBlock
,
251 IN PEX_CALLBACK_ROUTINE_BLOCK OldBlock
254 PEX_CALLBACK_ROUTINE_BLOCK
256 ExReferenceCallBackBlock(
257 IN OUT PEX_CALLBACK CallBack
262 ExDereferenceCallBackBlock(
263 IN OUT PEX_CALLBACK CallBack
,
264 IN PEX_CALLBACK_ROUTINE_BLOCK CallbackRoutineBlock
267 PEX_CALLBACK_FUNCTION
269 ExGetCallBackBlockRoutine(
270 IN PEX_CALLBACK_ROUTINE_BLOCK CallbackRoutineBlock
275 ExGetCallBackBlockContext(
276 IN PEX_CALLBACK_ROUTINE_BLOCK CallbackRoutineBlock
282 IN PEX_CALLBACK_ROUTINE_BLOCK CallbackRoutineBlock
285 /* Rundown Functions ********************************************************/
289 ExfInitializeRundownProtection(
290 OUT PEX_RUNDOWN_REF RunRef
295 ExfReInitializeRundownProtection(
296 OUT PEX_RUNDOWN_REF RunRef
301 ExfAcquireRundownProtection(
302 IN OUT PEX_RUNDOWN_REF RunRef
307 ExfAcquireRundownProtectionEx(
308 IN OUT PEX_RUNDOWN_REF RunRef
,
314 ExfReleaseRundownProtection(
315 IN OUT PEX_RUNDOWN_REF RunRef
320 ExfReleaseRundownProtectionEx(
321 IN OUT PEX_RUNDOWN_REF RunRef
,
328 OUT PEX_RUNDOWN_REF RunRef
333 ExfWaitForRundownProtectionRelease(
334 IN OUT PEX_RUNDOWN_REF RunRef
337 /* HANDLE TABLE FUNCTIONS ***************************************************/
340 (NTAPI
*PEX_SWEEP_HANDLE_CALLBACK
)(
341 PHANDLE_TABLE_ENTRY HandleTableEntry
,
347 (NTAPI
*PEX_DUPLICATE_HANDLE_CALLBACK
)(
348 IN PEPROCESS Process
,
349 IN PHANDLE_TABLE HandleTable
,
350 IN PHANDLE_TABLE_ENTRY HandleTableEntry
,
351 IN PHANDLE_TABLE_ENTRY NewEntry
355 (NTAPI
*PEX_CHANGE_HANDLE_CALLBACK
)(
356 PHANDLE_TABLE_ENTRY HandleTableEntry
,
362 ExpInitializeHandleTables(
369 IN PEPROCESS Process OPTIONAL
374 ExUnlockHandleTableEntry(
375 IN PHANDLE_TABLE HandleTable
,
376 IN PHANDLE_TABLE_ENTRY HandleTableEntry
382 IN PHANDLE_TABLE HandleTable
,
383 IN PHANDLE_TABLE_ENTRY HandleTableEntry
388 ExDestroyHandleTable(
389 IN PHANDLE_TABLE HandleTable
,
390 IN PVOID DestroyHandleProcedure OPTIONAL
396 IN PHANDLE_TABLE HandleTable
,
398 IN PHANDLE_TABLE_ENTRY HandleTableEntry OPTIONAL
403 ExMapHandleToPointer(
404 IN PHANDLE_TABLE HandleTable
,
411 IN PEPROCESS Process
,
412 IN PHANDLE_TABLE HandleTable
,
413 IN PEX_DUPLICATE_HANDLE_CALLBACK DupHandleProcedure
,
420 IN PHANDLE_TABLE HandleTable
,
422 IN PEX_CHANGE_HANDLE_CALLBACK ChangeRoutine
,
429 IN PHANDLE_TABLE HandleTable
,
430 IN PEX_SWEEP_HANDLE_CALLBACK EnumHandleProcedure
,
434 /* PSEH EXCEPTION HANDLING **************************************************/
438 ExSystemExceptionFilter(VOID
);
440 static __inline
_SEH_FILTER(_SEH_ExSystemExceptionFilter
)
442 return ExSystemExceptionFilter();
445 /* CALLBACKS *****************************************************************/
449 ExDoCallBack(IN OUT PEX_CALLBACK Callback
,
454 PEX_CALLBACK_ROUTINE_BLOCK CallbackRoutineBlock
;
455 PEX_CALLBACK_FUNCTION Function
;
457 /* Reference the block */
458 CallbackRoutineBlock
= ExReferenceCallBackBlock(Callback
);
459 if (CallbackRoutineBlock
)
461 /* Get the function */
462 Function
= ExGetCallBackBlockRoutine(CallbackRoutineBlock
);
464 /* Do the callback */
465 Function(Context
, Argument1
, Argument2
);
467 /* Now dereference it */
468 ExDereferenceCallBackBlock(Callback
, CallbackRoutineBlock
);
472 /* RUNDOWN *******************************************************************/
475 #define ExpChangeRundown(x, y, z) InterlockedCompareExchange64((PLONGLONG)x, y, z)
476 #define ExpSetRundown(x, y) InterlockedExchange64((PLONGLONG)x, y)
478 #define ExpChangeRundown(x, y, z) InterlockedCompareExchange((PLONG)x, PtrToLong(y), PtrToLong(z))
479 #define ExpChangePushlock(x, y, z) LongToPtr(InterlockedCompareExchange((PLONG)x, PtrToLong(y), PtrToLong(z)))
480 #define ExpSetRundown(x, y) InterlockedExchange((PLONG)x, y)
484 * @name ExfAcquireRundownProtection
487 * The ExfAcquireRundownProtection routine acquires rundown protection for
488 * the specified descriptor.
491 * Pointer to a rundown reference descriptor.
493 * @return TRUE if access to the protected structure was granted, FALSE otherwise.
495 * @remarks This is the internal macro for system use only.In case the rundown
496 * was active, then the slow-path will be called through the exported
502 _ExAcquireRundownProtection(IN PEX_RUNDOWN_REF RunRef
)
504 ULONG_PTR Value
, NewValue
;
506 /* Get the current value and mask the active bit */
507 Value
= RunRef
->Count
&~ EX_RUNDOWN_ACTIVE
;
509 /* Add a reference */
510 NewValue
= Value
+ EX_RUNDOWN_COUNT_INC
;
512 /* Change the value */
513 NewValue
= ExpChangeRundown(RunRef
, NewValue
, Value
);
514 if (NewValue
!= Value
)
516 /* Rundown was active, use long path */
517 return ExfAcquireRundownProtection(RunRef
);
525 * @name ExReleaseRundownProtection
528 * The ExReleaseRundownProtection routine releases rundown protection for
529 * the specified descriptor.
532 * Pointer to a rundown reference descriptor.
534 * @return TRUE if access to the protected structure was granted, FALSE otherwise.
536 * @remarks This is the internal macro for system use only.In case the rundown
537 * was active, then the slow-path will be called through the exported
543 _ExReleaseRundownProtection(IN PEX_RUNDOWN_REF RunRef
)
545 ULONG_PTR Value
, NewValue
;
547 /* Get the current value and mask the active bit */
548 Value
= RunRef
->Count
&~ EX_RUNDOWN_ACTIVE
;
550 /* Remove a reference */
551 NewValue
= Value
- EX_RUNDOWN_COUNT_INC
;
553 /* Change the value */
554 NewValue
= ExpChangeRundown(RunRef
, NewValue
, Value
);
556 /* Check if the rundown was active */
557 if (NewValue
!= Value
)
559 /* Rundown was active, use long path */
560 ExfReleaseRundownProtection(RunRef
);
565 ASSERT((Value
>= EX_RUNDOWN_COUNT_INC
) || (KeNumberProcessors
> 1));
570 * @name ExInitializeRundownProtection
573 * The ExInitializeRundownProtection routine initializes a rundown
574 * protection descriptor.
577 * Pointer to a rundown reference descriptor.
581 * @remarks This is the internal macro for system use only.
586 _ExInitializeRundownProtection(IN PEX_RUNDOWN_REF RunRef
)
588 /* Set the count to zero */
593 * @name ExWaitForRundownProtectionRelease
596 * The ExWaitForRundownProtectionRelease routine waits until the specified
597 * rundown descriptor has been released.
600 * Pointer to a rundown reference descriptor.
604 * @remarks This is the internal macro for system use only. If a wait is actually
605 * necessary, then the slow path is taken through the exported function.
610 _ExWaitForRundownProtectionRelease(IN PEX_RUNDOWN_REF RunRef
)
614 /* Set the active bit */
615 Value
= ExpChangeRundown(RunRef
, EX_RUNDOWN_ACTIVE
, 0);
616 if ((Value
) && (Value
!= EX_RUNDOWN_ACTIVE
))
618 /* If the the rundown wasn't already active, then take the long path */
619 ExfWaitForRundownProtectionRelease(RunRef
);
624 * @name ExRundownCompleted
627 * The ExRundownCompleted routine completes the rundown of the specified
628 * descriptor by setting the active bit.
631 * Pointer to a rundown reference descriptor.
635 * @remarks This is the internal macro for system use only.
640 _ExRundownCompleted(IN PEX_RUNDOWN_REF RunRef
)
643 ASSERT((RunRef
->Count
& EX_RUNDOWN_ACTIVE
) != 0);
645 /* Mark the counter as active */
646 ExpSetRundown(&RunRef
->Count
, EX_RUNDOWN_ACTIVE
);
649 /* PUSHLOCKS *****************************************************************/
651 /* FIXME: VERIFY THESE! */
655 ExBlockPushLock(PEX_PUSH_LOCK PushLock
,
660 ExfUnblockPushLock(PEX_PUSH_LOCK PushLock
,
661 PVOID CurrentWaitBlock
);
665 ExWaitForUnblockPushLock(IN PEX_PUSH_LOCK PushLock
,
666 IN PEX_PUSH_LOCK_WAIT_BLOCK WaitBlock
);
669 * @name ExInitializePushLock
672 * The ExInitializePushLock macro initializes a PushLock.
675 * Pointer to the pushlock which is to be initialized.
684 ExInitializePushLock(IN PULONG_PTR PushLock
)
686 /* Set the value to 0 */
691 * @name ExAcquirePushLockExclusive
694 * The ExAcquirePushLockExclusive macro exclusively acquires a PushLock.
697 * Pointer to the pushlock which is to be acquired.
701 * @remarks The function attempts the quickest route to acquire the lock, which is
702 * to simply set the lock bit.
703 * However, if the pushlock is already shared, the slower path is taken.
705 * Callers of ExAcquirePushLockShared must be running at IRQL <= APC_LEVEL.
706 * This macro should usually be paired up with KeAcquireCriticalRegion.
711 ExAcquirePushLockExclusive(PEX_PUSH_LOCK PushLock
)
713 /* Try acquiring the lock */
714 if (InterlockedBitTestAndSet((PLONG
)PushLock
, EX_PUSH_LOCK_LOCK_V
))
716 /* Someone changed it, use the slow path */
717 DbgPrint("%s - Contention!\n", __FUNCTION__
);
718 ExfAcquirePushLockExclusive(PushLock
);
722 ASSERT(PushLock
->Locked
);
726 * @name ExAcquirePushLockShared
729 * The ExAcquirePushLockShared macro acquires a shared PushLock.
732 * Pointer to the pushlock which is to be acquired.
736 * @remarks The function attempts the quickest route to acquire the lock, which is
737 * to simply set the lock bit and set the share count to one.
738 * However, if the pushlock is already shared, the slower path is taken.
740 * Callers of ExAcquirePushLockShared must be running at IRQL <= APC_LEVEL.
741 * This macro should usually be paired up with KeAcquireCriticalRegion.
746 ExAcquirePushLockShared(PEX_PUSH_LOCK PushLock
)
748 EX_PUSH_LOCK NewValue
;
750 /* Try acquiring the lock */
751 NewValue
.Value
= EX_PUSH_LOCK_LOCK
| EX_PUSH_LOCK_SHARE_INC
;
752 if (ExpChangePushlock(PushLock
, NewValue
.Ptr
, 0))
754 /* Someone changed it, use the slow path */
755 DbgPrint("%s - Contention!\n", __FUNCTION__
);
756 ExfAcquirePushLockShared(PushLock
);
760 ASSERT(PushLock
->Locked
);
761 ASSERT(PushLock
->Waiting
|| PushLock
->Shared
> 0);
765 * @name ExConvertPushLockSharedToExclusive
768 * The ExConvertPushLockSharedToExclusive macro converts an exclusive
769 * pushlock to a shared pushlock.
772 * Pointer to the pushlock which is to be converted.
774 * @return FALSE if conversion failed, TRUE otherwise.
776 * @remarks The function attempts the quickest route to convert the lock, which is
777 * to simply set the lock bit and remove any other bits.
782 ExConvertPushLockSharedToExclusive(IN PEX_PUSH_LOCK PushLock
)
784 EX_PUSH_LOCK OldValue
;
786 /* Set the expected old value */
787 OldValue
.Value
= EX_PUSH_LOCK_LOCK
| EX_PUSH_LOCK_SHARE_INC
;
789 /* Try converting the lock */
790 if (ExpChangePushlock(PushLock
, EX_PUSH_LOCK_LOCK
, OldValue
.Value
) !=
793 /* Conversion failed */
798 ASSERT(PushLock
->Locked
);
803 * @name ExWaitOnPushLock
806 * The ExWaitOnPushLock macro acquires and instantly releases a pushlock.
809 * Pointer to a pushlock.
813 * @remarks The function attempts to get any exclusive waiters out of their slow
814 * path by forcing an instant acquire/release operation.
816 * Callers of ExWaitOnPushLock must be running at IRQL <= APC_LEVEL.
821 ExWaitOnPushLock(PEX_PUSH_LOCK PushLock
)
823 /* Check if we're locked */
824 if (PushLock
->Locked
)
826 /* Acquire the lock */
827 ExfAcquirePushLockExclusive(PushLock
);
828 ASSERT(PushLock
->Locked
);
831 ExfReleasePushLockExclusive(PushLock
);
836 * @name ExReleasePushLockShared
839 * The ExReleasePushLockShared macro releases a previously acquired PushLock.
842 * Pointer to a previously acquired pushlock.
846 * @remarks The function attempts the quickest route to release the lock, which is
847 * to simply decrease the share count and remove the lock bit.
848 * However, if the pushlock is being waited on then the long path is taken.
850 * Callers of ExReleasePushLockShared must be running at IRQL <= APC_LEVEL.
851 * This macro should usually be paired up with KeLeaveCriticalRegion.
856 ExReleasePushLockShared(PEX_PUSH_LOCK PushLock
)
858 EX_PUSH_LOCK OldValue
;
861 ASSERT(PushLock
->Locked
);
862 ASSERT(PushLock
->Waiting
|| PushLock
->Shared
> 0);
864 /* Try to clear the pushlock */
865 OldValue
.Value
= EX_PUSH_LOCK_LOCK
| EX_PUSH_LOCK_SHARE_INC
;
866 if (ExpChangePushlock(PushLock
, 0, OldValue
.Ptr
) != OldValue
.Ptr
)
868 /* There are still other people waiting on it */
869 DbgPrint("%s - Contention!\n", __FUNCTION__
);
870 ExfReleasePushLockShared(PushLock
);
875 * @name ExReleasePushLockExclusive
878 * The ExReleasePushLockExclusive macro releases a previously
879 * exclusively acquired PushLock.
882 * Pointer to a previously acquired pushlock.
886 * @remarks The function attempts the quickest route to release the lock, which is
887 * to simply clear the locked bit.
888 * However, if the pushlock is being waited on, the slow path is taken
889 * in an attempt to wake up the lock.
891 * Callers of ExReleasePushLockExclusive must be running at IRQL <= APC_LEVEL.
892 * This macro should usually be paired up with KeLeaveCriticalRegion.
897 ExReleasePushLockExclusive(PEX_PUSH_LOCK PushLock
)
899 EX_PUSH_LOCK OldValue
;
902 ASSERT(PushLock
->Locked
);
903 ASSERT(PushLock
->Waiting
|| PushLock
->Shared
== 0);
905 /* Unlock the pushlock */
906 OldValue
.Value
= InterlockedExchangeAddSizeT((PLONG
)PushLock
,
910 ASSERT(OldValue
.Locked
);
911 ASSERT(OldValue
.Waiting
|| OldValue
.Shared
== 0);
913 /* Check if anyone is waiting on it and it's not already waking*/
914 if ((OldValue
.Waiting
) && !(OldValue
.Waking
))
917 DbgPrint("%s - Contention!\n", __FUNCTION__
);
918 ExfTryToWakePushLock(PushLock
);
923 * @name ExReleasePushLock
926 * The ExReleasePushLock macro releases a previously acquired PushLock.
929 * Pointer to a previously acquired pushlock.
933 * @remarks The function attempts the quickest route to release the lock, which is
934 * to simply clear all the fields and decrease the share count if required.
935 * However, if the pushlock is being waited on then the long path is taken.
937 * Callers of ExReleasePushLock must be running at IRQL <= APC_LEVEL.
938 * This macro should usually be paired up with KeLeaveCriticalRegion.
943 ExReleasePushLock(PEX_PUSH_LOCK PushLock
)
945 EX_PUSH_LOCK OldValue
= *PushLock
;
946 EX_PUSH_LOCK NewValue
;
949 ASSERT(OldValue
.Locked
);
951 /* Check if the pushlock is shared */
952 if (OldValue
.Shared
> 1)
954 /* Decrease the share count */
955 NewValue
.Value
= OldValue
.Value
&~ EX_PUSH_LOCK_SHARE_INC
;
959 /* Clear the pushlock entirely */
963 /* Check if nobody is waiting on us and try clearing the lock here */
964 if ((OldValue
.Waiting
) ||
965 (ExpChangePushlock(PushLock
, NewValue
.Ptr
, OldValue
.Ptr
) !=
968 /* We have waiters, use the long path */
969 DbgPrint("%s - Contention!\n", __FUNCTION__
);
970 ExfReleasePushLock(PushLock
);
974 /* OTHER FUNCTIONS **********************************************************/
978 ExfpInterlockedExchange64(
979 LONGLONG
volatile * Destination
,
984 ExpSetTimeZoneInformation(PTIME_ZONE_INFORMATION TimeZoneInformation
);
988 ExpAllocateLocallyUniqueId(OUT LUID
*LocallyUniqueId
);
992 ExTimerRundown(VOID
);
994 #define InterlockedDecrementUL(Addend) \
995 (ULONG)InterlockedDecrement((PLONG)(Addend))
997 #define InterlockedIncrementUL(Addend) \
998 (ULONG)InterlockedIncrement((PLONG)(Addend))
1000 #define InterlockedExchangeUL(Target, Value) \
1001 (ULONG)InterlockedExchange((PLONG)(Target), (LONG)(Value))
1003 #define InterlockedExchangeAddUL(Addend, Value) \
1004 (ULONG)InterlockedExchangeAdd((PLONG)(Addend), (LONG)(Value))
1006 #define InterlockedCompareExchangeUL(Destination, Exchange, Comperand) \
1007 (ULONG)InterlockedCompareExchange((PLONG)(Destination), (LONG)(Exchange), (LONG)(Comperand))
1009 #define ExfInterlockedCompareExchange64UL(Destination, Exchange, Comperand) \
1010 (ULONGLONG)ExfInterlockedCompareExchange64((PLONGLONG)(Destination), (PLONGLONG)(Exchange), (PLONGLONG)(Comperand))
1012 #define ExfpInterlockedExchange64UL(Target, Value) \
1013 (ULONGLONG)ExfpInterlockedExchange64((PLONGLONG)(Target), (PLONGLONG)(Value))
1015 #endif /* __NTOSKRNL_INCLUDE_INTERNAL_EXECUTIVE_H */