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