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