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