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