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