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