[NTOSKRNL] Rename ExpCriticalWorkerThreads and ExpDelayedWorkerThreads (no p)
[reactos.git] / ntoskrnl / include / internal / ex.h
1 #pragma once
2
3 /* GLOBAL VARIABLES *********************************************************/
4
5 extern TIME_ZONE_INFORMATION ExpTimeZoneInfo;
6 extern LARGE_INTEGER ExpTimeZoneBias;
7 extern ULONG ExpTimeZoneId;
8 extern ULONG ExpTickCountMultiplier;
9 extern ULONG ExpLastTimeZoneBias;
10 extern POBJECT_TYPE ExEventPairObjectType;
11 extern POBJECT_TYPE _ExEventObjectType, _ExSemaphoreObjectType;
12 extern FAST_MUTEX ExpEnvironmentLock;
13 extern ERESOURCE ExpFirmwareTableResource;
14 extern LIST_ENTRY ExpFirmwareTableProviderListHead;
15 extern BOOLEAN ExpIsWinPEMode;
16 extern LIST_ENTRY ExpSystemResourcesList;
17 extern ULONG ExpAnsiCodePageDataOffset, ExpOemCodePageDataOffset;
18 extern ULONG ExpUnicodeCaseTableDataOffset;
19 extern PVOID ExpNlsSectionPointer;
20 extern ULONG NtGlobalFlag;
21 extern UNICODE_STRING NtSystemRoot;
22 extern ULONG ExpInitializationPhase;
23 extern ULONG ExpAltTimeZoneBias;
24 extern LIST_ENTRY ExSystemLookasideListHead;
25 extern PCALLBACK_OBJECT PowerStateCallback;
26 extern LIST_ENTRY ExPoolLookasideListHead;
27 extern LIST_ENTRY ExpNonPagedLookasideListHead;
28 extern LIST_ENTRY ExpPagedLookasideListHead;
29 extern KSPIN_LOCK ExpNonPagedLookasideListLock;
30 extern KSPIN_LOCK ExpPagedLookasideListLock;
31 extern ULONG ExCriticalWorkerThreads;
32 extern ULONG ExDelayedWorkerThreads;
33
34 /*
35 * NT/Cm Version Info variables
36 */
37 extern ULONG NtMajorVersion;
38 extern ULONG NtMinorVersion;
39 extern ULONG NtBuildNumber;
40 extern ULONG CmNtSpBuildNumber;
41 extern ULONG CmNtCSDVersion;
42 extern ULONG CmNtCSDReleaseType;
43 extern UNICODE_STRING CmVersionString;
44 extern UNICODE_STRING CmCSDVersionString;
45 extern CHAR NtBuildLab[];
46
47 // #ifdef _WINKD_
48 /*
49 * WinDBG Debugger Worker State Machine data (see dbgctrl.c)
50 */
51 typedef enum _WINKD_WORKER_STATE
52 {
53 WinKdWorkerReady = 0,
54 WinKdWorkerStart,
55 WinKdWorkerInitialized
56 } WINKD_WORKER_STATE;
57
58 extern WORK_QUEUE_ITEM ExpDebuggerWorkItem;
59 extern WINKD_WORKER_STATE ExpDebuggerWork;
60 extern PEPROCESS ExpDebuggerProcessAttach;
61 extern PEPROCESS ExpDebuggerProcessKill;
62 extern ULONG_PTR ExpDebuggerPageIn;
63 VOID NTAPI ExpDebuggerWorker(IN PVOID Context);
64 // #endif /* _WINKD_ */
65
66 #ifdef _WIN64
67 #define HANDLE_LOW_BITS (PAGE_SHIFT - 4)
68 #define HANDLE_HIGH_BITS (PAGE_SHIFT - 3)
69 #else
70 #define HANDLE_LOW_BITS (PAGE_SHIFT - 3)
71 #define HANDLE_HIGH_BITS (PAGE_SHIFT - 2)
72 #endif
73 #define HANDLE_TAG_BITS (2)
74 #define HANDLE_INDEX_BITS (HANDLE_LOW_BITS + 2*HANDLE_HIGH_BITS)
75 #define KERNEL_FLAG_BITS (sizeof(PVOID)*8 - HANDLE_INDEX_BITS - HANDLE_TAG_BITS)
76
77 typedef union _EXHANDLE
78 {
79 struct
80 {
81 ULONG_PTR TagBits: HANDLE_TAG_BITS;
82 ULONG_PTR Index: HANDLE_INDEX_BITS;
83 ULONG_PTR KernelFlag : KERNEL_FLAG_BITS;
84 };
85 struct
86 {
87 ULONG_PTR TagBits2: HANDLE_TAG_BITS;
88 ULONG_PTR LowIndex: HANDLE_LOW_BITS;
89 ULONG_PTR MidIndex: HANDLE_HIGH_BITS;
90 ULONG_PTR HighIndex: HANDLE_HIGH_BITS;
91 ULONG_PTR KernelFlag2: KERNEL_FLAG_BITS;
92 };
93 HANDLE GenericHandleOverlay;
94 ULONG_PTR Value;
95 ULONG AsULONG;
96 } EXHANDLE, *PEXHANDLE;
97
98 typedef struct _ETIMER
99 {
100 KTIMER KeTimer;
101 KAPC TimerApc;
102 KDPC TimerDpc;
103 LIST_ENTRY ActiveTimerListEntry;
104 KSPIN_LOCK Lock;
105 LONG Period;
106 BOOLEAN ApcAssociated;
107 BOOLEAN WakeTimer;
108 LIST_ENTRY WakeTimerListEntry;
109 } ETIMER, *PETIMER;
110
111 typedef struct
112 {
113 PCALLBACK_OBJECT *CallbackObject;
114 PWSTR Name;
115 } SYSTEM_CALLBACKS;
116
117 typedef struct _HARDERROR_USER_PARAMETERS
118 {
119 ULONG_PTR Parameters[MAXIMUM_HARDERROR_PARAMETERS];
120 UNICODE_STRING Strings[MAXIMUM_HARDERROR_PARAMETERS];
121 WCHAR Buffer[ANYSIZE_ARRAY];
122 } HARDERROR_USER_PARAMETERS, *PHARDERROR_USER_PARAMETERS;
123
124 #define MAX_FAST_REFS 7
125
126 #define ExAcquireRundownProtection _ExAcquireRundownProtection
127 #define ExReleaseRundownProtection _ExReleaseRundownProtection
128 #define ExInitializeRundownProtection _ExInitializeRundownProtection
129 #define ExWaitForRundownProtectionRelease _ExWaitForRundownProtectionRelease
130 #define ExRundownCompleted _ExRundownCompleted
131 #define ExGetPreviousMode KeGetPreviousMode
132
133
134 //
135 // Various bits tagged on the handle or handle table
136 //
137 #define EXHANDLE_TABLE_ENTRY_LOCK_BIT 1
138 #define FREE_HANDLE_MASK -1
139
140 //
141 // Number of entries in each table level
142 //
143 #define LOW_LEVEL_ENTRIES (PAGE_SIZE / sizeof(HANDLE_TABLE_ENTRY))
144 #define MID_LEVEL_ENTRIES (PAGE_SIZE / sizeof(PHANDLE_TABLE_ENTRY))
145 #define HIGH_LEVEL_ENTRIES (16777216 / (LOW_LEVEL_ENTRIES * MID_LEVEL_ENTRIES))
146
147 //
148 // Maximum index in each table level before we need another table
149 //
150 #define MAX_LOW_INDEX LOW_LEVEL_ENTRIES
151 #define MAX_MID_INDEX (MID_LEVEL_ENTRIES * LOW_LEVEL_ENTRIES)
152 #define MAX_HIGH_INDEX (MID_LEVEL_ENTRIES * MID_LEVEL_ENTRIES * LOW_LEVEL_ENTRIES)
153
154 #define ExpChangeRundown(x, y, z) (ULONG_PTR)InterlockedCompareExchangePointer(&x->Ptr, (PVOID)y, (PVOID)z)
155 #define ExpChangePushlock(x, y, z) InterlockedCompareExchangePointer((PVOID*)x, (PVOID)y, (PVOID)z)
156 #define ExpSetRundown(x, y) InterlockedExchangePointer(&x->Ptr, (PVOID)y)
157
158 NTSTATUS
159 NTAPI
160 ExGetPoolTagInfo(
161 IN PSYSTEM_POOLTAG_INFORMATION SystemInformation,
162 IN ULONG SystemInformationLength,
163 IN OUT PULONG ReturnLength OPTIONAL
164 );
165
166 /* INITIALIZATION FUNCTIONS *************************************************/
167
168 BOOLEAN
169 NTAPI
170 ExpWin32kInit(VOID);
171
172 VOID
173 NTAPI
174 ExInit2(VOID);
175
176 VOID
177 NTAPI
178 Phase1Initialization(
179 IN PVOID Context
180 );
181
182 VOID
183 NTAPI
184 ExpInitializePushLocks(VOID);
185
186 BOOLEAN
187 NTAPI
188 ExRefreshTimeZoneInformation(
189 IN PLARGE_INTEGER SystemBootTime
190 );
191
192 VOID
193 NTAPI
194 ExpInitializeWorkerThreads(VOID);
195
196 VOID
197 NTAPI
198 ExSwapinWorkerThreads(IN BOOLEAN AllowSwap);
199
200 VOID
201 NTAPI
202 ExpInitLookasideLists(VOID);
203
204 VOID
205 NTAPI
206 ExInitializeSystemLookasideList(
207 IN PGENERAL_LOOKASIDE List,
208 IN POOL_TYPE Type,
209 IN ULONG Size,
210 IN ULONG Tag,
211 IN USHORT MaximumDepth,
212 IN PLIST_ENTRY ListHead
213 );
214
215 BOOLEAN
216 NTAPI
217 ExpInitializeCallbacks(VOID);
218
219 VOID
220 NTAPI
221 ExpInitUuids(VOID);
222
223 VOID
224 NTAPI
225 ExpInitializeExecutive(
226 IN ULONG Cpu,
227 IN PLOADER_PARAMETER_BLOCK LoaderBlock
228 );
229
230 BOOLEAN
231 NTAPI
232 ExpInitializeEventImplementation(VOID);
233
234 BOOLEAN
235 NTAPI
236 ExpInitializeKeyedEventImplementation(VOID);
237
238 BOOLEAN
239 NTAPI
240 ExpInitializeEventPairImplementation(VOID);
241
242 BOOLEAN
243 NTAPI
244 ExpInitializeSemaphoreImplementation(VOID);
245
246 BOOLEAN
247 NTAPI
248 ExpInitializeMutantImplementation(VOID);
249
250 BOOLEAN
251 NTAPI
252 ExpInitializeTimerImplementation(VOID);
253
254 BOOLEAN
255 NTAPI
256 ExpInitializeProfileImplementation(VOID);
257
258 VOID
259 NTAPI
260 ExpResourceInitialization(VOID);
261
262 VOID
263 NTAPI
264 ExInitPoolLookasidePointers(VOID);
265
266 /* Callback Functions ********************************************************/
267
268 VOID
269 NTAPI
270 ExInitializeCallBack(
271 IN OUT PEX_CALLBACK Callback
272 );
273
274 PEX_CALLBACK_ROUTINE_BLOCK
275 NTAPI
276 ExAllocateCallBack(
277 IN PEX_CALLBACK_FUNCTION Function,
278 IN PVOID Context
279 );
280
281 VOID
282 NTAPI
283 ExFreeCallBack(
284 IN PEX_CALLBACK_ROUTINE_BLOCK CallbackRoutineBlock
285 );
286
287 BOOLEAN
288 NTAPI
289 ExCompareExchangeCallBack (
290 IN OUT PEX_CALLBACK CallBack,
291 IN PEX_CALLBACK_ROUTINE_BLOCK NewBlock,
292 IN PEX_CALLBACK_ROUTINE_BLOCK OldBlock
293 );
294
295 PEX_CALLBACK_ROUTINE_BLOCK
296 NTAPI
297 ExReferenceCallBackBlock(
298 IN OUT PEX_CALLBACK CallBack
299 );
300
301 VOID
302 NTAPI
303 ExDereferenceCallBackBlock(
304 IN OUT PEX_CALLBACK CallBack,
305 IN PEX_CALLBACK_ROUTINE_BLOCK CallbackRoutineBlock
306 );
307
308 PEX_CALLBACK_FUNCTION
309 NTAPI
310 ExGetCallBackBlockRoutine(
311 IN PEX_CALLBACK_ROUTINE_BLOCK CallbackRoutineBlock
312 );
313
314 PVOID
315 NTAPI
316 ExGetCallBackBlockContext(
317 IN PEX_CALLBACK_ROUTINE_BLOCK CallbackRoutineBlock
318 );
319
320 VOID
321 NTAPI
322 ExWaitForCallBacks(
323 IN PEX_CALLBACK_ROUTINE_BLOCK CallbackRoutineBlock
324 );
325
326 /* Rundown Functions ********************************************************/
327
328 VOID
329 FASTCALL
330 ExfInitializeRundownProtection(
331 OUT PEX_RUNDOWN_REF RunRef
332 );
333
334 VOID
335 FASTCALL
336 ExfReInitializeRundownProtection(
337 OUT PEX_RUNDOWN_REF RunRef
338 );
339
340 BOOLEAN
341 FASTCALL
342 ExfAcquireRundownProtection(
343 IN OUT PEX_RUNDOWN_REF RunRef
344 );
345
346 BOOLEAN
347 FASTCALL
348 ExfAcquireRundownProtectionEx(
349 IN OUT PEX_RUNDOWN_REF RunRef,
350 IN ULONG Count
351 );
352
353 VOID
354 FASTCALL
355 ExfReleaseRundownProtection(
356 IN OUT PEX_RUNDOWN_REF RunRef
357 );
358
359 VOID
360 FASTCALL
361 ExfReleaseRundownProtectionEx(
362 IN OUT PEX_RUNDOWN_REF RunRef,
363 IN ULONG Count
364 );
365
366 VOID
367 FASTCALL
368 ExfRundownCompleted(
369 OUT PEX_RUNDOWN_REF RunRef
370 );
371
372 VOID
373 FASTCALL
374 ExfWaitForRundownProtectionRelease(
375 IN OUT PEX_RUNDOWN_REF RunRef
376 );
377
378 /* HANDLE TABLE FUNCTIONS ***************************************************/
379
380 typedef BOOLEAN
381 (NTAPI *PEX_SWEEP_HANDLE_CALLBACK)(
382 PHANDLE_TABLE_ENTRY HandleTableEntry,
383 HANDLE Handle,
384 PVOID Context
385 );
386
387 typedef BOOLEAN
388 (NTAPI *PEX_DUPLICATE_HANDLE_CALLBACK)(
389 IN PEPROCESS Process,
390 IN PHANDLE_TABLE HandleTable,
391 IN PHANDLE_TABLE_ENTRY HandleTableEntry,
392 IN PHANDLE_TABLE_ENTRY NewEntry
393 );
394
395 typedef BOOLEAN
396 (NTAPI *PEX_CHANGE_HANDLE_CALLBACK)(
397 PHANDLE_TABLE_ENTRY HandleTableEntry,
398 ULONG_PTR Context
399 );
400
401 VOID
402 NTAPI
403 ExpInitializeHandleTables(
404 VOID
405 );
406
407 PHANDLE_TABLE
408 NTAPI
409 ExCreateHandleTable(
410 IN PEPROCESS Process OPTIONAL
411 );
412
413 VOID
414 NTAPI
415 ExUnlockHandleTableEntry(
416 IN PHANDLE_TABLE HandleTable,
417 IN PHANDLE_TABLE_ENTRY HandleTableEntry
418 );
419
420 HANDLE
421 NTAPI
422 ExCreateHandle(
423 IN PHANDLE_TABLE HandleTable,
424 IN PHANDLE_TABLE_ENTRY HandleTableEntry
425 );
426
427 VOID
428 NTAPI
429 ExDestroyHandleTable(
430 IN PHANDLE_TABLE HandleTable,
431 IN PVOID DestroyHandleProcedure OPTIONAL
432 );
433
434 BOOLEAN
435 NTAPI
436 ExDestroyHandle(
437 IN PHANDLE_TABLE HandleTable,
438 IN HANDLE Handle,
439 IN PHANDLE_TABLE_ENTRY HandleTableEntry OPTIONAL
440 );
441
442 PHANDLE_TABLE_ENTRY
443 NTAPI
444 ExMapHandleToPointer(
445 IN PHANDLE_TABLE HandleTable,
446 IN HANDLE Handle
447 );
448
449 PHANDLE_TABLE
450 NTAPI
451 ExDupHandleTable(
452 IN PEPROCESS Process,
453 IN PHANDLE_TABLE HandleTable,
454 IN PEX_DUPLICATE_HANDLE_CALLBACK DupHandleProcedure,
455 IN ULONG_PTR Mask
456 );
457
458 BOOLEAN
459 NTAPI
460 ExChangeHandle(
461 IN PHANDLE_TABLE HandleTable,
462 IN HANDLE Handle,
463 IN PEX_CHANGE_HANDLE_CALLBACK ChangeRoutine,
464 IN ULONG_PTR Context
465 );
466
467 VOID
468 NTAPI
469 ExSweepHandleTable(
470 IN PHANDLE_TABLE HandleTable,
471 IN PEX_SWEEP_HANDLE_CALLBACK EnumHandleProcedure,
472 IN PVOID Context
473 );
474
475 PHANDLE_TABLE_ENTRY
476 NTAPI
477 ExpLookupHandleTableEntry(
478 IN PHANDLE_TABLE HandleTable,
479 IN EXHANDLE Handle
480 );
481
482 BOOLEAN
483 NTAPI
484 ExpLockHandleTableEntry(
485 IN PHANDLE_TABLE HandleTable,
486 IN PHANDLE_TABLE_ENTRY HandleTableEntry
487 );
488
489 /* PSEH EXCEPTION HANDLING **************************************************/
490
491 LONG
492 NTAPI
493 ExSystemExceptionFilter(VOID);
494
495 /* CALLBACKS *****************************************************************/
496
497 FORCEINLINE
498 VOID
499 ExDoCallBack(IN OUT PEX_CALLBACK Callback,
500 IN PVOID Context,
501 IN PVOID Argument1,
502 IN PVOID Argument2)
503 {
504 PEX_CALLBACK_ROUTINE_BLOCK CallbackBlock;
505 PEX_CALLBACK_FUNCTION Function;
506
507 /* Reference the block */
508 CallbackBlock = ExReferenceCallBackBlock(Callback);
509 if (CallbackBlock)
510 {
511 /* Get the function */
512 Function = ExGetCallBackBlockRoutine(CallbackBlock);
513
514 /* Do the callback */
515 Function(Context, Argument1, Argument2);
516
517 /* Now dereference it */
518 ExDereferenceCallBackBlock(Callback, CallbackBlock);
519 }
520 }
521
522 /* FAST REFS ******************************************************************/
523
524 FORCEINLINE
525 PVOID
526 ExGetObjectFastReference(IN EX_FAST_REF FastRef)
527 {
528 /* Return the unbiased pointer */
529 return (PVOID)(FastRef.Value & ~MAX_FAST_REFS);
530 }
531
532 FORCEINLINE
533 ULONG
534 ExGetCountFastReference(IN EX_FAST_REF FastRef)
535 {
536 /* Return the reference count */
537 return (ULONG)FastRef.RefCnt;
538 }
539
540 FORCEINLINE
541 VOID
542 ExInitializeFastReference(OUT PEX_FAST_REF FastRef,
543 IN OPTIONAL PVOID Object)
544 {
545 /* Sanity check */
546 ASSERT((((ULONG_PTR)Object) & MAX_FAST_REFS) == 0);
547
548 /* Check if an object is being set */
549 if (!Object)
550 {
551 /* Clear the field */
552 FastRef->Object = NULL;
553 }
554 else
555 {
556 /* Otherwise, we assume the object was referenced and is ready */
557 FastRef->Value = (ULONG_PTR)Object | MAX_FAST_REFS;
558 }
559 }
560
561 FORCEINLINE
562 EX_FAST_REF
563 ExAcquireFastReference(IN OUT PEX_FAST_REF FastRef)
564 {
565 EX_FAST_REF OldValue, NewValue;
566
567 /* Start reference loop */
568 for (;;)
569 {
570 /* Get the current reference count */
571 OldValue = *FastRef;
572 if (OldValue.RefCnt)
573 {
574 /* Increase the reference count */
575 NewValue.Value = OldValue.Value - 1;
576 NewValue.Object = ExpChangePushlock(&FastRef->Object,
577 NewValue.Object,
578 OldValue.Object);
579 if (NewValue.Object != OldValue.Object) continue;
580 }
581
582 /* We are done */
583 break;
584 }
585
586 /* Return the old value */
587 return OldValue;
588 }
589
590 FORCEINLINE
591 BOOLEAN
592 ExInsertFastReference(IN OUT PEX_FAST_REF FastRef,
593 IN PVOID Object)
594 {
595 EX_FAST_REF OldValue, NewValue;
596
597 /* Sanity checks */
598 ASSERT(!(((ULONG_PTR)Object) & MAX_FAST_REFS));
599
600 /* Start update loop */
601 for (;;)
602 {
603 /* Get the current reference count */
604 OldValue = *FastRef;
605
606 /* Check if the current count is too high or if the pointer changed */
607 if (((OldValue.RefCnt + MAX_FAST_REFS) > MAX_FAST_REFS) ||
608 ((OldValue.Value &~ MAX_FAST_REFS) != (ULONG_PTR)Object))
609 {
610 /* Fail */
611 return FALSE;
612 }
613
614 /* Update the reference count */
615 NewValue.Value = OldValue.Value + MAX_FAST_REFS;
616 NewValue.Object = ExpChangePushlock(&FastRef->Object,
617 NewValue.Object,
618 OldValue.Object);
619 if (NewValue.Object != OldValue.Object) continue;
620
621 /* We are done */
622 break;
623 }
624
625 /* Return success */
626 return TRUE;
627 }
628
629 FORCEINLINE
630 BOOLEAN
631 ExReleaseFastReference(IN PEX_FAST_REF FastRef,
632 IN PVOID Object)
633 {
634 EX_FAST_REF OldValue, NewValue;
635
636 /* Sanity checks */
637 ASSERT(Object != NULL);
638 ASSERT(!(((ULONG_PTR)Object) & MAX_FAST_REFS));
639
640 /* Start reference loop */
641 for (;;)
642 {
643 /* Get the current reference count */
644 OldValue = *FastRef;
645
646 /* Check if we're full if if the pointer changed */
647 if ((OldValue.Value ^ (ULONG_PTR)Object) >= MAX_FAST_REFS) return FALSE;
648
649 /* Decrease the reference count */
650 NewValue.Value = OldValue.Value + 1;
651 NewValue.Object = ExpChangePushlock(&FastRef->Object,
652 NewValue.Object,
653 OldValue.Object);
654 if (NewValue.Object != OldValue.Object) continue;
655
656 /* We are done */
657 break;
658 }
659
660 /* Return success */
661 return TRUE;
662 }
663
664 FORCEINLINE
665 EX_FAST_REF
666 ExSwapFastReference(IN PEX_FAST_REF FastRef,
667 IN PVOID Object)
668 {
669 EX_FAST_REF NewValue, OldValue;
670
671 /* Sanity check */
672 ASSERT((((ULONG_PTR)Object) & MAX_FAST_REFS) == 0);
673
674 /* Check if an object is being set */
675 if (!Object)
676 {
677 /* Clear the field */
678 NewValue.Object = NULL;
679 }
680 else
681 {
682 /* Otherwise, we assume the object was referenced and is ready */
683 NewValue.Value = (ULONG_PTR)Object | MAX_FAST_REFS;
684 }
685
686 /* Update the object */
687 OldValue.Object = InterlockedExchangePointer(&FastRef->Object, NewValue.Object);
688 return OldValue;
689 }
690
691 FORCEINLINE
692 EX_FAST_REF
693 ExCompareSwapFastReference(IN PEX_FAST_REF FastRef,
694 IN PVOID Object,
695 IN PVOID OldObject)
696 {
697 EX_FAST_REF OldValue, NewValue;
698
699 /* Sanity check and start swap loop */
700 ASSERT(!(((ULONG_PTR)Object) & MAX_FAST_REFS));
701 for (;;)
702 {
703 /* Get the current value */
704 OldValue = *FastRef;
705
706 /* Make sure there's enough references to swap */
707 if (!((OldValue.Value ^ (ULONG_PTR)OldObject) <= MAX_FAST_REFS)) break;
708
709 /* Check if we have an object to swap */
710 if (Object)
711 {
712 /* Set up the value with maximum fast references */
713 NewValue.Value = (ULONG_PTR)Object | MAX_FAST_REFS;
714 }
715 else
716 {
717 /* Write the object address itself (which is empty) */
718 NewValue.Value = (ULONG_PTR)Object;
719 }
720
721 /* Do the actual compare exchange */
722 NewValue.Object = ExpChangePushlock(&FastRef->Object,
723 NewValue.Object,
724 OldValue.Object);
725 if (NewValue.Object != OldValue.Object) continue;
726
727 /* All done */
728 break;
729 }
730
731 /* Return the old value */
732 return OldValue;
733 }
734
735 /* RUNDOWN *******************************************************************/
736
737 /*++
738 * @name ExfAcquireRundownProtection
739 * INTERNAL MACRO
740 *
741 * The ExfAcquireRundownProtection routine acquires rundown protection for
742 * the specified descriptor.
743 *
744 * @param RunRef
745 * Pointer to a rundown reference descriptor.
746 *
747 * @return TRUE if access to the protected structure was granted, FALSE otherwise.
748 *
749 * @remarks This is the internal macro for system use only.In case the rundown
750 * was active, then the slow-path will be called through the exported
751 * function.
752 *
753 *--*/
754 FORCEINLINE
755 BOOLEAN
756 _ExAcquireRundownProtection(IN PEX_RUNDOWN_REF RunRef)
757 {
758 ULONG_PTR Value, NewValue;
759
760 /* Get the current value and mask the active bit */
761 Value = RunRef->Count &~ EX_RUNDOWN_ACTIVE;
762
763 /* Add a reference */
764 NewValue = Value + EX_RUNDOWN_COUNT_INC;
765
766 /* Change the value */
767 NewValue = ExpChangeRundown(RunRef, NewValue, Value);
768 if (NewValue != Value)
769 {
770 /* Rundown was active, use long path */
771 return ExfAcquireRundownProtection(RunRef);
772 }
773
774 /* Success */
775 return TRUE;
776 }
777
778 /*++
779 * @name ExReleaseRundownProtection
780 * INTERNAL MACRO
781 *
782 * The ExReleaseRundownProtection routine releases rundown protection for
783 * the specified descriptor.
784 *
785 * @param RunRef
786 * Pointer to a rundown reference descriptor.
787 *
788 * @return TRUE if access to the protected structure was granted, FALSE otherwise.
789 *
790 * @remarks This is the internal macro for system use only.In case the rundown
791 * was active, then the slow-path will be called through the exported
792 * function.
793 *
794 *--*/
795 FORCEINLINE
796 VOID
797 _ExReleaseRundownProtection(IN PEX_RUNDOWN_REF RunRef)
798 {
799 ULONG_PTR Value, NewValue;
800
801 /* Get the current value and mask the active bit */
802 Value = RunRef->Count &~ EX_RUNDOWN_ACTIVE;
803
804 /* Remove a reference */
805 NewValue = Value - EX_RUNDOWN_COUNT_INC;
806
807 /* Change the value */
808 NewValue = ExpChangeRundown(RunRef, NewValue, Value);
809
810 /* Check if the rundown was active */
811 if (NewValue != Value)
812 {
813 /* Rundown was active, use long path */
814 ExfReleaseRundownProtection(RunRef);
815 }
816 else
817 {
818 /* Sanity check */
819 ASSERT((Value >= EX_RUNDOWN_COUNT_INC) || (KeNumberProcessors > 1));
820 }
821 }
822
823 /*++
824 * @name ExInitializeRundownProtection
825 * INTERNAL MACRO
826 *
827 * The ExInitializeRundownProtection routine initializes a rundown
828 * protection descriptor.
829 *
830 * @param RunRef
831 * Pointer to a rundown reference descriptor.
832 *
833 * @return None.
834 *
835 * @remarks This is the internal macro for system use only.
836 *
837 *--*/
838 FORCEINLINE
839 VOID
840 _ExInitializeRundownProtection(IN PEX_RUNDOWN_REF RunRef)
841 {
842 /* Set the count to zero */
843 RunRef->Count = 0;
844 }
845
846 /*++
847 * @name ExWaitForRundownProtectionRelease
848 * INTERNAL MACRO
849 *
850 * The ExWaitForRundownProtectionRelease routine waits until the specified
851 * rundown descriptor has been released.
852 *
853 * @param RunRef
854 * Pointer to a rundown reference descriptor.
855 *
856 * @return None.
857 *
858 * @remarks This is the internal macro for system use only. If a wait is actually
859 * necessary, then the slow path is taken through the exported function.
860 *
861 *--*/
862 FORCEINLINE
863 VOID
864 _ExWaitForRundownProtectionRelease(IN PEX_RUNDOWN_REF RunRef)
865 {
866 ULONG_PTR Value;
867
868 /* Set the active bit */
869 Value = ExpChangeRundown(RunRef, EX_RUNDOWN_ACTIVE, 0);
870 if ((Value) && (Value != EX_RUNDOWN_ACTIVE))
871 {
872 /* If the the rundown wasn't already active, then take the long path */
873 ExfWaitForRundownProtectionRelease(RunRef);
874 }
875 }
876
877 /*++
878 * @name ExRundownCompleted
879 * INTERNAL MACRO
880 *
881 * The ExRundownCompleted routine completes the rundown of the specified
882 * descriptor by setting the active bit.
883 *
884 * @param RunRef
885 * Pointer to a rundown reference descriptor.
886 *
887 * @return None.
888 *
889 * @remarks This is the internal macro for system use only.
890 *
891 *--*/
892 FORCEINLINE
893 VOID
894 _ExRundownCompleted(IN PEX_RUNDOWN_REF RunRef)
895 {
896 /* Sanity check */
897 ASSERT((RunRef->Count & EX_RUNDOWN_ACTIVE) != 0);
898
899 /* Mark the counter as active */
900 ExpSetRundown(RunRef, EX_RUNDOWN_ACTIVE);
901 }
902
903 /* PUSHLOCKS *****************************************************************/
904
905 /* FIXME: VERIFY THESE! */
906
907 VOID
908 FASTCALL
909 ExBlockPushLock(
910 IN PEX_PUSH_LOCK PushLock,
911 IN PVOID WaitBlock
912 );
913
914 VOID
915 FASTCALL
916 ExfUnblockPushLock(
917 IN PEX_PUSH_LOCK PushLock,
918 IN PVOID CurrentWaitBlock
919 );
920
921 VOID
922 FASTCALL
923 ExWaitForUnblockPushLock(
924 IN PEX_PUSH_LOCK PushLock,
925 IN PVOID WaitBlock
926 );
927
928 /*++
929 * @name _ExInitializePushLock
930 * INTERNAL MACRO
931 *
932 * The _ExInitializePushLock macro initializes a PushLock.
933 *
934 * @params PushLock
935 * Pointer to the pushlock which is to be initialized.
936 *
937 * @return None.
938 *
939 * @remarks None.
940 *
941 *--*/
942 FORCEINLINE
943 VOID
944 _ExInitializePushLock(OUT PEX_PUSH_LOCK PushLock)
945 {
946 /* Set the value to 0 */
947 PushLock->Ptr = 0;
948 }
949 #define ExInitializePushLock _ExInitializePushLock
950
951 /*++
952 * @name ExAcquirePushLockExclusive
953 * INTERNAL MACRO
954 *
955 * The ExAcquirePushLockExclusive macro exclusively acquires a PushLock.
956 *
957 * @params PushLock
958 * Pointer to the pushlock which is to be acquired.
959 *
960 * @return None.
961 *
962 * @remarks The function attempts the quickest route to acquire the lock, which is
963 * to simply set the lock bit.
964 * However, if the pushlock is already shared, the slower path is taken.
965 *
966 * Callers of ExAcquirePushLockShared must be running at IRQL <= APC_LEVEL.
967 * This macro should usually be paired up with KeAcquireCriticalRegion.
968 *
969 *--*/
970 FORCEINLINE
971 VOID
972 ExAcquirePushLockExclusive(PEX_PUSH_LOCK PushLock)
973 {
974 /* Try acquiring the lock */
975 if (InterlockedBitTestAndSet((PLONG)PushLock, EX_PUSH_LOCK_LOCK_V))
976 {
977 /* Someone changed it, use the slow path */
978 ExfAcquirePushLockExclusive(PushLock);
979 }
980
981 /* Sanity check */
982 ASSERT(PushLock->Locked);
983 }
984
985 /*++
986 * @name ExTryToAcquirePushLockExclusive
987 * INTERNAL MACRO
988 *
989 * The ExAcquirePushLockExclusive macro exclusively acquires a PushLock.
990 *
991 * @params PushLock
992 * Pointer to the pushlock which is to be acquired.
993 *
994 * @return None.
995 *
996 * @remarks The function attempts the quickest route to acquire the lock, which is
997 * to simply set the lock bit.
998 * However, if the pushlock is already shared, the slower path is taken.
999 *
1000 * Callers of ExAcquirePushLockShared must be running at IRQL <= APC_LEVEL.
1001 * This macro should usually be paired up with KeAcquireCriticalRegion.
1002 *
1003 *--*/
1004 FORCEINLINE
1005 BOOLEAN
1006 ExTryToAcquirePushLockExclusive(PEX_PUSH_LOCK PushLock)
1007 {
1008 /* Try acquiring the lock */
1009 if (InterlockedBitTestAndSet((PLONG)PushLock, EX_PUSH_LOCK_LOCK_V))
1010 {
1011 /* Can't acquire */
1012 return FALSE;
1013 }
1014
1015 /* Got acquired */
1016 ASSERT (PushLock->Locked);
1017 return TRUE;
1018 }
1019
1020 /*++
1021 * @name ExAcquirePushLockShared
1022 * INTERNAL MACRO
1023 *
1024 * The ExAcquirePushLockShared macro acquires a shared PushLock.
1025 *
1026 * @params PushLock
1027 * Pointer to the pushlock which is to be acquired.
1028 *
1029 * @return None.
1030 *
1031 * @remarks The function attempts the quickest route to acquire the lock, which is
1032 * to simply set the lock bit and set the share count to one.
1033 * However, if the pushlock is already shared, the slower path is taken.
1034 *
1035 * Callers of ExAcquirePushLockShared must be running at IRQL <= APC_LEVEL.
1036 * This macro should usually be paired up with KeAcquireCriticalRegion.
1037 *
1038 *--*/
1039 FORCEINLINE
1040 VOID
1041 ExAcquirePushLockShared(PEX_PUSH_LOCK PushLock)
1042 {
1043 EX_PUSH_LOCK NewValue;
1044
1045 /* Try acquiring the lock */
1046 NewValue.Value = EX_PUSH_LOCK_LOCK | EX_PUSH_LOCK_SHARE_INC;
1047 if (ExpChangePushlock(PushLock, NewValue.Ptr, 0))
1048 {
1049 /* Someone changed it, use the slow path */
1050 ExfAcquirePushLockShared(PushLock);
1051 }
1052
1053 /* Sanity checks */
1054 ASSERT(PushLock->Locked);
1055 }
1056
1057 /*++
1058 * @name ExConvertPushLockSharedToExclusive
1059 * INTERNAL MACRO
1060 *
1061 * The ExConvertPushLockSharedToExclusive macro converts an exclusive
1062 * pushlock to a shared pushlock.
1063 *
1064 * @params PushLock
1065 * Pointer to the pushlock which is to be converted.
1066 *
1067 * @return FALSE if conversion failed, TRUE otherwise.
1068 *
1069 * @remarks The function attempts the quickest route to convert the lock, which is
1070 * to simply set the lock bit and remove any other bits.
1071 *
1072 *--*/
1073 FORCEINLINE
1074 BOOLEAN
1075 ExConvertPushLockSharedToExclusive(IN PEX_PUSH_LOCK PushLock)
1076 {
1077 EX_PUSH_LOCK OldValue;
1078
1079 /* Set the expected old value */
1080 OldValue.Value = EX_PUSH_LOCK_LOCK | EX_PUSH_LOCK_SHARE_INC;
1081
1082 /* Try converting the lock */
1083 if (ExpChangePushlock(PushLock, EX_PUSH_LOCK_LOCK, OldValue.Value) !=
1084 OldValue.Ptr)
1085 {
1086 /* Conversion failed */
1087 return FALSE;
1088 }
1089
1090 /* Sanity check */
1091 ASSERT(PushLock->Locked);
1092 return TRUE;
1093 }
1094
1095 /*++
1096 * @name ExWaitOnPushLock
1097 * INTERNAL MACRO
1098 *
1099 * The ExWaitOnPushLock macro acquires and instantly releases a pushlock.
1100 *
1101 * @params PushLock
1102 * Pointer to a pushlock.
1103 *
1104 * @return None.
1105 *
1106 * @remarks The function attempts to get any exclusive waiters out of their slow
1107 * path by forcing an instant acquire/release operation.
1108 *
1109 * Callers of ExWaitOnPushLock must be running at IRQL <= APC_LEVEL.
1110 *
1111 *--*/
1112 FORCEINLINE
1113 VOID
1114 ExWaitOnPushLock(PEX_PUSH_LOCK PushLock)
1115 {
1116 /* Check if we're locked */
1117 if (PushLock->Locked)
1118 {
1119 /* Acquire the lock */
1120 ExfAcquirePushLockExclusive(PushLock);
1121 ASSERT(PushLock->Locked);
1122
1123 /* Release it */
1124 ExfReleasePushLockExclusive(PushLock);
1125 }
1126 }
1127
1128 /*++
1129 * @name ExReleasePushLockShared
1130 * INTERNAL MACRO
1131 *
1132 * The ExReleasePushLockShared macro releases a previously acquired PushLock.
1133 *
1134 * @params PushLock
1135 * Pointer to a previously acquired pushlock.
1136 *
1137 * @return None.
1138 *
1139 * @remarks The function attempts the quickest route to release the lock, which is
1140 * to simply decrease the share count and remove the lock bit.
1141 * However, if the pushlock is being waited on then the long path is taken.
1142 *
1143 * Callers of ExReleasePushLockShared must be running at IRQL <= APC_LEVEL.
1144 * This macro should usually be paired up with KeLeaveCriticalRegion.
1145 *
1146 *--*/
1147 FORCEINLINE
1148 VOID
1149 ExReleasePushLockShared(PEX_PUSH_LOCK PushLock)
1150 {
1151 EX_PUSH_LOCK OldValue;
1152
1153 /* Sanity checks */
1154 ASSERT(PushLock->Locked);
1155
1156 /* Try to clear the pushlock */
1157 OldValue.Value = EX_PUSH_LOCK_LOCK | EX_PUSH_LOCK_SHARE_INC;
1158 if (ExpChangePushlock(PushLock, 0, OldValue.Ptr) != OldValue.Ptr)
1159 {
1160 /* There are still other people waiting on it */
1161 ExfReleasePushLockShared(PushLock);
1162 }
1163 }
1164
1165 /*++
1166 * @name ExReleasePushLockExclusive
1167 * INTERNAL MACRO
1168 *
1169 * The ExReleasePushLockExclusive macro releases a previously
1170 * exclusively acquired PushLock.
1171 *
1172 * @params PushLock
1173 * Pointer to a previously acquired pushlock.
1174 *
1175 * @return None.
1176 *
1177 * @remarks The function attempts the quickest route to release the lock, which is
1178 * to simply clear the locked bit.
1179 * However, if the pushlock is being waited on, the slow path is taken
1180 * in an attempt to wake up the lock.
1181 *
1182 * Callers of ExReleasePushLockExclusive must be running at IRQL <= APC_LEVEL.
1183 * This macro should usually be paired up with KeLeaveCriticalRegion.
1184 *
1185 *--*/
1186 FORCEINLINE
1187 VOID
1188 ExReleasePushLockExclusive(PEX_PUSH_LOCK PushLock)
1189 {
1190 EX_PUSH_LOCK OldValue;
1191
1192 /* Sanity checks */
1193 ASSERT(PushLock->Locked);
1194
1195 /* Unlock the pushlock */
1196 OldValue.Value = InterlockedExchangeAddSizeT((PSIZE_T)PushLock,
1197 -(SSIZE_T)EX_PUSH_LOCK_LOCK);
1198
1199 /* Sanity checks */
1200 ASSERT(OldValue.Locked);
1201 ASSERT(OldValue.Waiting || OldValue.Shared == 0);
1202
1203 /* Check if anyone is waiting on it and it's not already waking*/
1204 if ((OldValue.Waiting) && !(OldValue.Waking))
1205 {
1206 /* Wake it up */
1207 ExfTryToWakePushLock(PushLock);
1208 }
1209 }
1210
1211 /*++
1212 * @name ExReleasePushLock
1213 * INTERNAL MACRO
1214 *
1215 * The ExReleasePushLock macro releases a previously acquired PushLock.
1216 *
1217 * @params PushLock
1218 * Pointer to a previously acquired pushlock.
1219 *
1220 * @return None.
1221 *
1222 * @remarks The function attempts the quickest route to release the lock, which is
1223 * to simply clear all the fields and decrease the share count if required.
1224 * However, if the pushlock is being waited on then the long path is taken.
1225 *
1226 * Callers of ExReleasePushLock must be running at IRQL <= APC_LEVEL.
1227 * This macro should usually be paired up with KeLeaveCriticalRegion.
1228 *
1229 *--*/
1230 FORCEINLINE
1231 VOID
1232 ExReleasePushLock(PEX_PUSH_LOCK PushLock)
1233 {
1234 EX_PUSH_LOCK OldValue = *PushLock;
1235 EX_PUSH_LOCK NewValue;
1236
1237 /* Sanity checks */
1238 ASSERT(OldValue.Locked);
1239
1240 /* Check if the pushlock is shared */
1241 if (OldValue.Shared > 1)
1242 {
1243 /* Decrease the share count */
1244 NewValue.Value = OldValue.Value - EX_PUSH_LOCK_SHARE_INC;
1245 }
1246 else
1247 {
1248 /* Clear the pushlock entirely */
1249 NewValue.Value = 0;
1250 }
1251
1252 /* Check if nobody is waiting on us and try clearing the lock here */
1253 if ((OldValue.Waiting) ||
1254 (ExpChangePushlock(PushLock, NewValue.Ptr, OldValue.Ptr) !=
1255 OldValue.Ptr))
1256 {
1257 /* We have waiters, use the long path */
1258 ExfReleasePushLock(PushLock);
1259 }
1260 }
1261
1262 /* FAST MUTEX INLINES *********************************************************/
1263
1264 FORCEINLINE
1265 VOID
1266 _ExAcquireFastMutexUnsafe(IN PFAST_MUTEX FastMutex)
1267 {
1268 PKTHREAD Thread = KeGetCurrentThread();
1269
1270 /* Sanity check */
1271 ASSERT((KeGetCurrentIrql() == APC_LEVEL) ||
1272 (Thread->CombinedApcDisable != 0) ||
1273 (Thread->Teb == NULL) ||
1274 (Thread->Teb >= (PTEB)MM_SYSTEM_RANGE_START));
1275 ASSERT(FastMutex->Owner != Thread);
1276
1277 /* Decrease the count */
1278 if (InterlockedDecrement(&FastMutex->Count))
1279 {
1280 /* Someone is still holding it, use slow path */
1281 KiAcquireFastMutex(FastMutex);
1282 }
1283
1284 /* Set the owner */
1285 FastMutex->Owner = Thread;
1286 }
1287
1288 FORCEINLINE
1289 VOID
1290 _ExReleaseFastMutexUnsafe(IN OUT PFAST_MUTEX FastMutex)
1291 {
1292 ASSERT((KeGetCurrentIrql() == APC_LEVEL) ||
1293 (KeGetCurrentThread()->CombinedApcDisable != 0) ||
1294 (KeGetCurrentThread()->Teb == NULL) ||
1295 (KeGetCurrentThread()->Teb >= (PTEB)MM_SYSTEM_RANGE_START));
1296 ASSERT(FastMutex->Owner == KeGetCurrentThread());
1297
1298 /* Erase the owner */
1299 FastMutex->Owner = NULL;
1300
1301 /* Increase the count */
1302 if (InterlockedIncrement(&FastMutex->Count) <= 0)
1303 {
1304 /* Someone was waiting for it, signal the waiter */
1305 KeSetEventBoostPriority(&FastMutex->Event, NULL);
1306 }
1307 }
1308
1309 FORCEINLINE
1310 VOID
1311 _ExAcquireFastMutex(IN PFAST_MUTEX FastMutex)
1312 {
1313 KIRQL OldIrql;
1314 ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
1315
1316 /* Raise IRQL to APC */
1317 KeRaiseIrql(APC_LEVEL, &OldIrql);
1318
1319 /* Decrease the count */
1320 if (InterlockedDecrement(&FastMutex->Count))
1321 {
1322 /* Someone is still holding it, use slow path */
1323 KiAcquireFastMutex(FastMutex);
1324 }
1325
1326 /* Set the owner and IRQL */
1327 FastMutex->Owner = KeGetCurrentThread();
1328 FastMutex->OldIrql = OldIrql;
1329 }
1330
1331 FORCEINLINE
1332 VOID
1333 _ExReleaseFastMutex(IN OUT PFAST_MUTEX FastMutex)
1334 {
1335 KIRQL OldIrql;
1336 ASSERT(KeGetCurrentIrql() == APC_LEVEL);
1337
1338 /* Erase the owner */
1339 FastMutex->Owner = NULL;
1340 OldIrql = (KIRQL)FastMutex->OldIrql;
1341
1342 /* Increase the count */
1343 if (InterlockedIncrement(&FastMutex->Count) <= 0)
1344 {
1345 /* Someone was waiting for it, signal the waiter */
1346 KeSetEventBoostPriority(&FastMutex->Event, NULL);
1347 }
1348
1349 /* Lower IRQL back */
1350 KeLowerIrql(OldIrql);
1351 }
1352
1353 FORCEINLINE
1354 BOOLEAN
1355 _ExTryToAcquireFastMutex(IN OUT PFAST_MUTEX FastMutex)
1356 {
1357 KIRQL OldIrql;
1358 ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
1359
1360 /* Raise to APC_LEVEL */
1361 KeRaiseIrql(APC_LEVEL, &OldIrql);
1362
1363 /* Check if we can quickly acquire it */
1364 if (InterlockedCompareExchange(&FastMutex->Count, 0, 1) == 1)
1365 {
1366 /* We have, set us as owners */
1367 FastMutex->Owner = KeGetCurrentThread();
1368 FastMutex->OldIrql = OldIrql;
1369 return TRUE;
1370 }
1371 else
1372 {
1373 /* Acquire attempt failed */
1374 KeLowerIrql(OldIrql);
1375 YieldProcessor();
1376 return FALSE;
1377 }
1378 }
1379
1380 FORCEINLINE
1381 VOID
1382 _ExEnterCriticalRegionAndAcquireFastMutexUnsafe(IN OUT PFAST_MUTEX FastMutex)
1383 {
1384 /* Enter the Critical Region */
1385 KeEnterCriticalRegion();
1386
1387 /* Acquire the mutex unsafely */
1388 _ExAcquireFastMutexUnsafe(FastMutex);
1389 }
1390
1391 FORCEINLINE
1392 VOID
1393 _ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(IN OUT PFAST_MUTEX FastMutex)
1394 {
1395 /* Release the mutex unsafely */
1396 _ExReleaseFastMutexUnsafe(FastMutex);
1397
1398 /* Leave the critical region */
1399 KeLeaveCriticalRegion();
1400 }
1401
1402 /* OTHER FUNCTIONS **********************************************************/
1403
1404 BOOLEAN
1405 NTAPI
1406 ExTryToAcquireResourceExclusiveLite(
1407 IN PERESOURCE Resource
1408 );
1409
1410 NTSTATUS
1411 ExpSetTimeZoneInformation(
1412 IN PTIME_ZONE_INFORMATION TimeZoneInformation
1413 );
1414
1415 BOOLEAN
1416 NTAPI
1417 ExAcquireTimeRefreshLock(
1418 IN BOOLEAN Wait
1419 );
1420
1421 VOID
1422 NTAPI
1423 ExReleaseTimeRefreshLock(
1424 VOID
1425 );
1426
1427 VOID
1428 NTAPI
1429 ExUpdateSystemTimeFromCmos(
1430 IN BOOLEAN UpdateInterruptTime,
1431 IN ULONG MaxSepInSeconds
1432 );
1433
1434 VOID
1435 NTAPI
1436 ExAllocateLocallyUniqueId(
1437 OUT LUID *LocallyUniqueId
1438 );
1439
1440 VOID
1441 NTAPI
1442 ExTimerRundown(
1443 VOID
1444 );
1445
1446 VOID
1447 NTAPI
1448 HeadlessInit(
1449 IN PLOADER_PARAMETER_BLOCK LoaderBlock
1450 );
1451
1452 VOID
1453 NTAPI
1454 XIPInit(
1455 IN PLOADER_PARAMETER_BLOCK LoaderBlock
1456 );
1457
1458 #define InterlockedDecrementUL(Addend) \
1459 (ULONG)InterlockedDecrement((PLONG)(Addend))
1460
1461 #define InterlockedIncrementUL(Addend) \
1462 (ULONG)InterlockedIncrement((PLONG)(Addend))
1463
1464 #define InterlockedExchangeUL(Target, Value) \
1465 (ULONG)InterlockedExchange((PLONG)(Target), (LONG)(Value))
1466
1467 #define InterlockedExchangeAddUL(Addend, Value) \
1468 (ULONG)InterlockedExchangeAdd((PLONG)(Addend), (LONG)(Value))
1469
1470 #define InterlockedCompareExchangeUL(Destination, Exchange, Comperand) \
1471 (ULONG)InterlockedCompareExchange((PLONG)(Destination), (LONG)(Exchange), (LONG)(Comperand))
1472
1473 #define ExfInterlockedCompareExchange64UL(Destination, Exchange, Comperand) \
1474 (ULONGLONG)ExfInterlockedCompareExchange64((PLONGLONG)(Destination), (PLONGLONG)(Exchange), (PLONGLONG)(Comperand))