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