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