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