1 /* 2 * PROJECT: ReactOS Kernel 3 * LICENSE: GPL - See COPYING in the top level directory 4 * FILE: ntoskrnl/ex/handle.c 5 * PURPOSE: Generic Executive Handle Tables 6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) 7 * Thomas Weidenmueller <w3seek@reactos.com> 8 */ 9 10 /* INCLUDES ******************************************************************/ 11 12 #include <ntoskrnl.h> 13 #define NDEBUG 14 #include <debug.h> 15 16 /* GLOBALS *******************************************************************/ 17 18 LIST_ENTRY HandleTableListHead; 19 EX_PUSH_LOCK HandleTableListLock; 20 #define SizeOfHandle(x) (sizeof(HANDLE) * (x)) 21 #define INDEX_TO_HANDLE_VALUE(x) ((x) << HANDLE_TAG_BITS) 22 23 /* PRIVATE FUNCTIONS *********************************************************/ 24 25 INIT_FUNCTION 26 VOID 27 NTAPI 28 ExpInitializeHandleTables(VOID) 29 { 30 /* Initialize the list of handle tables and the lock */ 31 InitializeListHead(&HandleTableListHead); 32 ExInitializePushLock(&HandleTableListLock); 33 } 34 35 PHANDLE_TABLE_ENTRY 36 NTAPI 37 ExpLookupHandleTableEntry(IN PHANDLE_TABLE HandleTable, 38 IN EXHANDLE Handle) 39 { 40 ULONG TableLevel; 41 ULONG_PTR TableBase; 42 PHANDLE_TABLE_ENTRY HandleArray, Entry; 43 PVOID *PointerArray; 44 45 /* Clear the tag bits */ 46 Handle.TagBits = 0; 47 48 /* Check if the handle is in the allocated range */ 49 if (Handle.Value >= HandleTable->NextHandleNeedingPool) 50 { 51 return NULL; 52 } 53 54 /* Get the table code */ 55 TableBase = HandleTable->TableCode; 56 57 /* Extract the table level and actual table base */ 58 TableLevel = (ULONG)(TableBase & 3); 59 TableBase &= ~3; 60 61 PointerArray = (PVOID*)TableBase; 62 HandleArray = (PHANDLE_TABLE_ENTRY)TableBase; 63 64 /* Check what level we're running at */ 65 switch (TableLevel) 66 { 67 case 2: 68 69 /* Get the mid level pointer array */ 70 PointerArray = PointerArray[Handle.HighIndex]; 71 ASSERT(PointerArray != NULL); 72 73 /* Fall through */ 74 case 1: 75 76 /* Get the handle array */ 77 HandleArray = PointerArray[Handle.MidIndex]; 78 ASSERT(HandleArray != NULL); 79 80 /* Fall through */ 81 case 0: 82 83 /* Get the entry using the low index */ 84 Entry = &HandleArray[Handle.LowIndex]; 85 86 /* All done */ 87 break; 88 89 default: 90 91 ASSERT(FALSE); 92 Entry = NULL; 93 } 94 95 /* Return the handle entry */ 96 return Entry; 97 } 98 99 PVOID 100 NTAPI 101 ExpAllocateTablePagedPool(IN PEPROCESS Process OPTIONAL, 102 IN SIZE_T Size) 103 { 104 PVOID Buffer; 105 106 /* Do the allocation */ 107 Buffer = ExAllocatePoolWithTag(PagedPool, Size, TAG_OBJECT_TABLE); 108 if (Buffer) 109 { 110 /* Clear the memory */ 111 RtlZeroMemory(Buffer, Size); 112 113 /* Check if we have a process to charge quota */ 114 if (Process) 115 { 116 /* FIXME: Charge quota */ 117 } 118 } 119 120 /* Return the allocated memory */ 121 return Buffer; 122 } 123 124 PVOID 125 NTAPI 126 ExpAllocateTablePagedPoolNoZero(IN PEPROCESS Process OPTIONAL, 127 IN SIZE_T Size) 128 { 129 PVOID Buffer; 130 131 /* Do the allocation */ 132 Buffer = ExAllocatePoolWithTag(PagedPool, Size, TAG_OBJECT_TABLE); 133 if (Buffer) 134 { 135 /* Check if we have a process to charge quota */ 136 if (Process) 137 { 138 /* FIXME: Charge quota */ 139 } 140 } 141 142 /* Return the allocated memory */ 143 return Buffer; 144 } 145 146 VOID 147 NTAPI 148 ExpFreeTablePagedPool(IN PEPROCESS Process OPTIONAL, 149 IN PVOID Buffer, 150 IN SIZE_T Size) 151 { 152 /* Free the buffer */ 153 ExFreePoolWithTag(Buffer, TAG_OBJECT_TABLE); 154 if (Process) 155 { 156 /* FIXME: Release quota */ 157 } 158 } 159 160 VOID 161 NTAPI 162 ExpFreeLowLevelTable(IN PEPROCESS Process, 163 IN PHANDLE_TABLE_ENTRY TableEntry) 164 { 165 /* Check if we have an entry */ 166 if (TableEntry[0].Object) 167 { 168 /* Free the entry */ 169 ExpFreeTablePagedPool(Process, 170 TableEntry[0].Object, 171 LOW_LEVEL_ENTRIES * 172 sizeof(HANDLE_TABLE_ENTRY_INFO)); 173 } 174 175 /* Free the table */ 176 ExpFreeTablePagedPool(Process, TableEntry, PAGE_SIZE); 177 } 178 179 VOID 180 NTAPI 181 ExpFreeHandleTable(IN PHANDLE_TABLE HandleTable) 182 { 183 PEPROCESS Process = HandleTable->QuotaProcess; 184 ULONG i, j; 185 ULONG_PTR TableCode = HandleTable->TableCode; 186 ULONG_PTR TableBase = TableCode & ~3; 187 ULONG TableLevel = (ULONG)(TableCode & 3); 188 PHANDLE_TABLE_ENTRY Level1, *Level2, **Level3; 189 PAGED_CODE(); 190 191 /* Check which level we're at */ 192 if (TableLevel == 0) 193 { 194 /* Select the first level table base and just free it */ 195 Level1 = (PVOID)TableBase; 196 ExpFreeLowLevelTable(Process, Level1); 197 } 198 else if (TableLevel == 1) 199 { 200 /* Select the second level table base */ 201 Level2 = (PVOID)TableBase; 202 203 /* Loop each mid level entry */ 204 for (i = 0; i < MID_LEVEL_ENTRIES; i++) 205 { 206 /* Leave if we've reached the last entry */ 207 if (!Level2[i]) break; 208 209 /* Free the second level table */ 210 ExpFreeLowLevelTable(Process, Level2[i]); 211 } 212 213 /* Free the second level table */ 214 ExpFreeTablePagedPool(Process, Level2, PAGE_SIZE); 215 } 216 else 217 { 218 /* Select the third level table base */ 219 Level3 = (PVOID)TableBase; 220 221 /* Loop each high level entry */ 222 for (i = 0; i < HIGH_LEVEL_ENTRIES; i++) 223 { 224 /* Leave if we've reached the last entry */ 225 if (!Level3[i]) break; 226 227 /* Loop each mid level entry */ 228 for (j = 0; j < MID_LEVEL_ENTRIES; j++) 229 { 230 /* Leave if we've reached the last entry */ 231 if (!Level3[i][j]) break; 232 233 /* Free the second level table */ 234 ExpFreeLowLevelTable(Process, Level3[i][j]); 235 } 236 237 /* Free the third level table entry */ 238 ExpFreeTablePagedPool(Process, Level3[i], PAGE_SIZE); 239 } 240 241 /* Free the third level table */ 242 ExpFreeTablePagedPool(Process, 243 Level3, 244 SizeOfHandle(HIGH_LEVEL_ENTRIES)); 245 } 246 247 /* Free the actual table and check if we need to release quota */ 248 ExFreePoolWithTag(HandleTable, TAG_OBJECT_TABLE); 249 if (Process) 250 { 251 /* FIXME: TODO */ 252 } 253 } 254 255 VOID 256 NTAPI 257 ExpFreeHandleTableEntry(IN PHANDLE_TABLE HandleTable, 258 IN EXHANDLE Handle, 259 IN PHANDLE_TABLE_ENTRY HandleTableEntry) 260 { 261 ULONG OldValue, *Free; 262 ULONG LockIndex; 263 PAGED_CODE(); 264 265 /* Sanity checks */ 266 ASSERT(HandleTableEntry->Object == NULL); 267 ASSERT(HandleTableEntry == ExpLookupHandleTableEntry(HandleTable, Handle)); 268 269 /* Decrement the handle count */ 270 InterlockedDecrement(&HandleTable->HandleCount); 271 272 /* Mark the handle as free */ 273 Handle.TagBits = 0; 274 275 /* Check if we're FIFO */ 276 if (!HandleTable->StrictFIFO) 277 { 278 /* Select a lock index */ 279 LockIndex = Handle.Index % 4; 280 281 /* Select which entry to use */ 282 Free = (HandleTable->HandleTableLock[LockIndex].Locked) ? 283 &HandleTable->FirstFree : &HandleTable->LastFree; 284 } 285 else 286 { 287 /* No need to worry about locking, take the last entry */ 288 Free = &HandleTable->LastFree; 289 } 290 291 /* Start value change loop */ 292 for (;;) 293 { 294 /* Get the current value and write */ 295 OldValue = *Free; 296 HandleTableEntry->NextFreeTableEntry = OldValue; 297 if (InterlockedCompareExchange((PLONG)Free, Handle.AsULONG, OldValue) == OldValue) 298 { 299 /* Break out, we're done. Make sure the handle value makes sense */ 300 ASSERT((OldValue & FREE_HANDLE_MASK) < 301 HandleTable->NextHandleNeedingPool); 302 break; 303 } 304 } 305 } 306 307 PHANDLE_TABLE 308 NTAPI 309 ExpAllocateHandleTable(IN PEPROCESS Process OPTIONAL, 310 IN BOOLEAN NewTable) 311 { 312 PHANDLE_TABLE HandleTable; 313 PHANDLE_TABLE_ENTRY HandleTableTable, HandleEntry; 314 ULONG i; 315 PAGED_CODE(); 316 317 /* Allocate the table */ 318 HandleTable = ExAllocatePoolWithTag(PagedPool, 319 sizeof(HANDLE_TABLE), 320 TAG_OBJECT_TABLE); 321 if (!HandleTable) return NULL; 322 323 /* Check if we have a process */ 324 if (Process) 325 { 326 /* FIXME: Charge quota */ 327 } 328 329 /* Clear the table */ 330 RtlZeroMemory(HandleTable, sizeof(HANDLE_TABLE)); 331 332 /* Now allocate the first level structures */ 333 HandleTableTable = ExpAllocateTablePagedPoolNoZero(Process, PAGE_SIZE); 334 if (!HandleTableTable) 335 { 336 /* Failed, free the table */ 337 ExFreePoolWithTag(HandleTable, TAG_OBJECT_TABLE); 338 return NULL; 339 } 340 341 /* Write the pointer to our first level structures */ 342 HandleTable->TableCode = (ULONG_PTR)HandleTableTable; 343 344 /* Initialize the first entry */ 345 HandleEntry = &HandleTableTable[0]; 346 HandleEntry->NextFreeTableEntry = -2; 347 HandleEntry->Value = 0; 348 349 /* Check if this is a new table */ 350 if (NewTable) 351 { 352 /* Go past the root entry */ 353 HandleEntry++; 354 355 /* Loop every low level entry */ 356 for (i = 1; i < (LOW_LEVEL_ENTRIES - 1); i++) 357 { 358 /* Set up the free data */ 359 HandleEntry->Value = 0; 360 HandleEntry->NextFreeTableEntry = INDEX_TO_HANDLE_VALUE(i + 1); 361 362 /* Move to the next entry */ 363 HandleEntry++; 364 } 365 366 /* Terminate the last entry */ 367 HandleEntry->Value = 0; 368 HandleEntry->NextFreeTableEntry = 0; 369 HandleTable->FirstFree = INDEX_TO_HANDLE_VALUE(1); 370 } 371 372 /* Set the next handle needing pool after our allocated page from above */ 373 HandleTable->NextHandleNeedingPool = INDEX_TO_HANDLE_VALUE(LOW_LEVEL_ENTRIES); 374 375 /* Setup the rest of the handle table data */ 376 HandleTable->QuotaProcess = Process; 377 HandleTable->UniqueProcessId = PsGetCurrentProcess()->UniqueProcessId; 378 HandleTable->Flags = 0; 379 380 /* Loop all the handle table locks */ 381 for (i = 0; i < 4; i++) 382 { 383 /* Initialize the handle table lock */ 384 ExInitializePushLock(&HandleTable->HandleTableLock[i]); 385 } 386 387 /* Initialize the contention event lock and return the lock */ 388 ExInitializePushLock(&HandleTable->HandleContentionEvent); 389 return HandleTable; 390 } 391 392 PHANDLE_TABLE_ENTRY 393 NTAPI 394 ExpAllocateLowLevelTable(IN PHANDLE_TABLE HandleTable, 395 IN BOOLEAN DoInit) 396 { 397 ULONG i, Base; 398 PHANDLE_TABLE_ENTRY Low, HandleEntry; 399 400 /* Allocate the low level table */ 401 Low = ExpAllocateTablePagedPoolNoZero(HandleTable->QuotaProcess, 402 PAGE_SIZE); 403 if (!Low) return NULL; 404 405 /* Setup the initial entry */ 406 HandleEntry = &Low[0]; 407 HandleEntry->NextFreeTableEntry = -2; 408 HandleEntry->Value = 0; 409 410 /* Check if we're initializing */ 411 if (DoInit) 412 { 413 /* Go to the next entry and the base entry */ 414 HandleEntry++; 415 Base = HandleTable->NextHandleNeedingPool + INDEX_TO_HANDLE_VALUE(2); 416 417 /* Loop each entry */ 418 for (i = Base; 419 i < Base + INDEX_TO_HANDLE_VALUE(LOW_LEVEL_ENTRIES - 2); 420 i += INDEX_TO_HANDLE_VALUE(1)) 421 { 422 /* Free this entry and move on to the next one */ 423 HandleEntry->NextFreeTableEntry = i; 424 HandleEntry->Value = 0; 425 HandleEntry++; 426 } 427 428 /* Terminate the last entry */ 429 HandleEntry->NextFreeTableEntry = 0; 430 HandleEntry->Value = 0; 431 } 432 433 /* Return the low level table */ 434 return Low; 435 } 436 437 PHANDLE_TABLE_ENTRY* 438 NTAPI 439 ExpAllocateMidLevelTable(IN PHANDLE_TABLE HandleTable, 440 IN BOOLEAN DoInit, 441 OUT PHANDLE_TABLE_ENTRY *LowTableEntry) 442 { 443 PHANDLE_TABLE_ENTRY *Mid, Low; 444 445 /* Allocate the mid level table */ 446 Mid = ExpAllocateTablePagedPool(HandleTable->QuotaProcess, PAGE_SIZE); 447 if (!Mid) return NULL; 448 449 /* Allocate a new low level for it */ 450 Low = ExpAllocateLowLevelTable(HandleTable, DoInit); 451 if (!Low) 452 { 453 /* We failed, free the mid table */ 454 ExpFreeTablePagedPool(HandleTable->QuotaProcess, Mid, PAGE_SIZE); 455 return NULL; 456 } 457 458 /* Link the tables and return the pointer */ 459 Mid[0] = Low; 460 *LowTableEntry = Low; 461 return Mid; 462 } 463 464 BOOLEAN 465 NTAPI 466 ExpAllocateHandleTableEntrySlow(IN PHANDLE_TABLE HandleTable, 467 IN BOOLEAN DoInit) 468 { 469 ULONG i, j, Index; 470 PHANDLE_TABLE_ENTRY Low = NULL, *Mid, **High, *SecondLevel, **ThirdLevel; 471 ULONG NewFree, FirstFree; 472 PVOID Value; 473 ULONG_PTR TableCode = HandleTable->TableCode; 474 ULONG_PTR TableBase = TableCode & ~3; 475 ULONG TableLevel = (ULONG)(TableCode & 3); 476 PAGED_CODE(); 477 478 /* Check how many levels we already have */ 479 if (TableLevel == 0) 480 { 481 /* Allocate a mid level, since we only have a low level */ 482 Mid = ExpAllocateMidLevelTable(HandleTable, DoInit, &Low); 483 if (!Mid) return FALSE; 484 485 /* Link up the tables */ 486 Mid[1] = Mid[0]; 487 Mid[0] = (PVOID)TableBase; 488 489 /* Write the new level and attempt to change the table code */ 490 TableBase = ((ULONG_PTR)Mid) | 1; 491 Value = InterlockedExchangePointer((PVOID*)&HandleTable->TableCode, (PVOID)TableBase); 492 } 493 else if (TableLevel == 1) 494 { 495 /* Setup the 2nd level table */ 496 SecondLevel = (PVOID)TableBase; 497 498 /* Get if the next index can fit in the table */ 499 i = HandleTable->NextHandleNeedingPool / 500 INDEX_TO_HANDLE_VALUE(LOW_LEVEL_ENTRIES); 501 if (i < MID_LEVEL_ENTRIES) 502 { 503 /* We need to allocate a new table */ 504 Low = ExpAllocateLowLevelTable(HandleTable, DoInit); 505 if (!Low) return FALSE; 506 507 /* Update the table */ 508 Value = InterlockedExchangePointer((PVOID*)&SecondLevel[i], Low); 509 ASSERT(Value == NULL); 510 } 511 else 512 { 513 /* We need a new high level table */ 514 High = ExpAllocateTablePagedPool(HandleTable->QuotaProcess, 515 SizeOfHandle(HIGH_LEVEL_ENTRIES)); 516 if (!High) return FALSE; 517 518 /* Allocate a new mid level table as well */ 519 Mid = ExpAllocateMidLevelTable(HandleTable, DoInit, &Low); 520 if (!Mid) 521 { 522 /* We failed, free the high level table as well */ 523 ExpFreeTablePagedPool(HandleTable->QuotaProcess, 524 High, 525 SizeOfHandle(HIGH_LEVEL_ENTRIES)); 526 return FALSE; 527 } 528 529 /* Link up the tables */ 530 High[0] = (PVOID)TableBase; 531 High[1] = Mid; 532 533 /* Write the new table and change the table code */ 534 TableBase = ((ULONG_PTR)High) | 2; 535 Value = InterlockedExchangePointer((PVOID*)&HandleTable->TableCode, 536 (PVOID)TableBase); 537 } 538 } 539 else if (TableLevel == 2) 540 { 541 /* Setup the 3rd level table */ 542 ThirdLevel = (PVOID)TableBase; 543 544 /* Get the index and check if it can fit */ 545 i = HandleTable->NextHandleNeedingPool / INDEX_TO_HANDLE_VALUE(MAX_MID_INDEX); 546 if (i >= HIGH_LEVEL_ENTRIES) return FALSE; 547 548 /* Check if there's no mid-level table */ 549 if (!ThirdLevel[i]) 550 { 551 /* Allocate a new mid level table */ 552 Mid = ExpAllocateMidLevelTable(HandleTable, DoInit, &Low); 553 if (!Mid) return FALSE; 554 555 /* Update the table pointer */ 556 Value = InterlockedExchangePointer((PVOID*)&ThirdLevel[i], Mid); 557 ASSERT(Value == NULL); 558 } 559 else 560 { 561 /* We have one, check at which index we should insert our entry */ 562 Index = (HandleTable->NextHandleNeedingPool / INDEX_TO_HANDLE_VALUE(1)) - 563 i * MAX_MID_INDEX; 564 j = Index / LOW_LEVEL_ENTRIES; 565 566 /* Allocate a new low level */ 567 Low = ExpAllocateLowLevelTable(HandleTable, DoInit); 568 if (!Low) return FALSE; 569 570 /* Update the table pointer */ 571 Value = InterlockedExchangePointer((PVOID*)&ThirdLevel[i][j], Low); 572 ASSERT(Value == NULL); 573 } 574 } 575 else 576 { 577 /* Something is really broken */ 578 ASSERT(FALSE); 579 } 580 581 /* Update the index of the next handle */ 582 Index = InterlockedExchangeAdd((PLONG) &HandleTable->NextHandleNeedingPool, 583 INDEX_TO_HANDLE_VALUE(LOW_LEVEL_ENTRIES)); 584 585 /* Check if need to initialize the table */ 586 if (DoInit) 587 { 588 /* Create a new index number */ 589 Index += INDEX_TO_HANDLE_VALUE(1); 590 591 /* Start free index change loop */ 592 for (;;) 593 { 594 /* Setup the first free index */ 595 FirstFree = HandleTable->FirstFree; 596 Low[LOW_LEVEL_ENTRIES - 1].NextFreeTableEntry = FirstFree; 597 598 /* Change the index */ 599 NewFree = InterlockedCompareExchange((PLONG) &HandleTable->FirstFree, 600 Index, 601 FirstFree); 602 if (NewFree == FirstFree) break; 603 } 604 } 605 606 /* All done */ 607 return TRUE; 608 } 609 610 ULONG 611 NTAPI 612 ExpMoveFreeHandles(IN PHANDLE_TABLE HandleTable) 613 { 614 ULONG LastFree, i; 615 616 /* Clear the last free index */ 617 LastFree = InterlockedExchange((PLONG) &HandleTable->LastFree, 0); 618 619 /* Check if we had no index */ 620 if (!LastFree) return LastFree; 621 622 /* Acquire the locks we need */ 623 for (i = 1; i < 4; i++) 624 { 625 /* Acquire this lock exclusively */ 626 ExWaitOnPushLock(&HandleTable->HandleTableLock[i]); 627 } 628 629 /* Check if we're not strict FIFO */ 630 if (!HandleTable->StrictFIFO) 631 { 632 /* Update the first free index */ 633 if (!InterlockedCompareExchange((PLONG) &HandleTable->FirstFree, LastFree, 0)) 634 { 635 /* We're done, exit */ 636 return LastFree; 637 } 638 } 639 640 /* We are strict FIFO, we need to reverse the entries */ 641 ASSERT(FALSE); 642 return LastFree; 643 } 644 645 PHANDLE_TABLE_ENTRY 646 NTAPI 647 ExpAllocateHandleTableEntry(IN PHANDLE_TABLE HandleTable, 648 OUT PEXHANDLE NewHandle) 649 { 650 ULONG OldValue, NewValue, NewValue1; 651 PHANDLE_TABLE_ENTRY Entry; 652 EXHANDLE Handle, OldHandle; 653 BOOLEAN Result; 654 ULONG i; 655 656 /* Start allocation loop */ 657 for (;;) 658 { 659 /* Get the current link */ 660 OldValue = HandleTable->FirstFree; 661 while (!OldValue) 662 { 663 /* No free entries remain, lock the handle table */ 664 KeEnterCriticalRegion(); 665 ExAcquirePushLockExclusive(&HandleTable->HandleTableLock[0]); 666 667 /* Check the value again */ 668 OldValue = HandleTable->FirstFree; 669 if (OldValue) 670 { 671 /* Another thread has already created a new level, bail out */ 672 ExReleasePushLockExclusive(&HandleTable->HandleTableLock[0]); 673 KeLeaveCriticalRegion(); 674 break; 675 } 676 677 /* Now move any free handles */ 678 OldValue = ExpMoveFreeHandles(HandleTable); 679 if (OldValue) 680 { 681 /* Another thread has already moved them, bail out */ 682 ExReleasePushLockExclusive(&HandleTable->HandleTableLock[0]); 683 KeLeaveCriticalRegion(); 684 break; 685 } 686 687 /* We're the first one through, so do the actual allocation */ 688 Result = ExpAllocateHandleTableEntrySlow(HandleTable, TRUE); 689 690 /* Unlock the table and get the value now */ 691 ExReleasePushLockExclusive(&HandleTable->HandleTableLock[0]); 692 KeLeaveCriticalRegion(); 693 OldValue = HandleTable->FirstFree; 694 695 /* Check if allocation failed */ 696 if (!Result) 697 { 698 /* Check if nobody else went through here */ 699 if (!OldValue) 700 { 701 /* We're still the only thread around, so fail */ 702 NewHandle->GenericHandleOverlay = NULL; 703 return NULL; 704 } 705 } 706 } 707 708 /* We made it, write the current value */ 709 Handle.Value = (OldValue & FREE_HANDLE_MASK); 710 711 /* Lookup the entry for this handle */ 712 Entry = ExpLookupHandleTableEntry(HandleTable, Handle); 713 714 /* Get an available lock and acquire it */ 715 OldHandle.Value = OldValue; 716 i = OldHandle.Index % 4; 717 KeEnterCriticalRegion(); 718 ExAcquirePushLockShared(&HandleTable->HandleTableLock[i]); 719 720 /* Check if the value changed after acquiring the lock */ 721 if (OldValue != *(volatile ULONG*)&HandleTable->FirstFree) 722 { 723 /* It did, so try again */ 724 ExReleasePushLockShared(&HandleTable->HandleTableLock[i]); 725 KeLeaveCriticalRegion(); 726 continue; 727 } 728 729 /* Now get the next value and do the compare */ 730 NewValue = *(volatile ULONG*)&Entry->NextFreeTableEntry; 731 NewValue1 = InterlockedCompareExchange((PLONG) &HandleTable->FirstFree, 732 NewValue, 733 OldValue); 734 735 /* The change was done, so release the lock */ 736 ExReleasePushLockShared(&HandleTable->HandleTableLock[i]); 737 KeLeaveCriticalRegion(); 738 739 /* Check if the compare was successful */ 740 if (NewValue1 == OldValue) 741 { 742 /* Make sure that the new handle is in range, and break out */ 743 ASSERT((NewValue & FREE_HANDLE_MASK) < 744 HandleTable->NextHandleNeedingPool); 745 break; 746 } 747 else 748 { 749 /* The compare failed, make sure we expected it */ 750 ASSERT((NewValue1 & FREE_HANDLE_MASK) != 751 (OldValue & FREE_HANDLE_MASK)); 752 } 753 } 754 755 /* Increase the number of handles */ 756 InterlockedIncrement(&HandleTable->HandleCount); 757 758 /* Return the handle and the entry */ 759 *NewHandle = Handle; 760 return Entry; 761 } 762 763 PHANDLE_TABLE 764 NTAPI 765 ExCreateHandleTable(IN PEPROCESS Process OPTIONAL) 766 { 767 PHANDLE_TABLE HandleTable; 768 PAGED_CODE(); 769 770 /* Allocate the handle table */ 771 HandleTable = ExpAllocateHandleTable(Process, TRUE); 772 if (!HandleTable) return NULL; 773 774 /* Acquire the handle table lock */ 775 KeEnterCriticalRegion(); 776 ExAcquirePushLockExclusive(&HandleTableListLock); 777 778 /* Insert it into the list */ 779 InsertTailList(&HandleTableListHead, &HandleTable->HandleTableList); 780 781 /* Release the lock */ 782 ExReleasePushLockExclusive(&HandleTableListLock); 783 KeLeaveCriticalRegion(); 784 785 /* Return the handle table */ 786 return HandleTable; 787 } 788 789 HANDLE 790 NTAPI 791 ExCreateHandle(IN PHANDLE_TABLE HandleTable, 792 IN PHANDLE_TABLE_ENTRY HandleTableEntry) 793 { 794 EXHANDLE Handle; 795 PHANDLE_TABLE_ENTRY NewEntry; 796 PAGED_CODE(); 797 798 /* Start with a clean handle */ 799 Handle.GenericHandleOverlay = NULL; 800 801 /* Allocate a new entry */ 802 NewEntry = ExpAllocateHandleTableEntry(HandleTable, &Handle); 803 if (NewEntry) 804 { 805 /* Enter a critical region */ 806 KeEnterCriticalRegion(); 807 808 /* Write the entry */ 809 *NewEntry = *HandleTableEntry; 810 811 /* Unlock it and leave the critical region */ 812 ExUnlockHandleTableEntry(HandleTable, NewEntry); 813 KeLeaveCriticalRegion(); 814 } 815 816 /* Return the handle value */ 817 return Handle.GenericHandleOverlay; 818 } 819 820 VOID 821 NTAPI 822 ExpBlockOnLockedHandleEntry(IN PHANDLE_TABLE HandleTable, 823 IN PHANDLE_TABLE_ENTRY HandleTableEntry) 824 { 825 LONG_PTR OldValue; 826 EX_PUSH_LOCK_WAIT_BLOCK WaitBlock; 827 828 /* Block on the pushlock */ 829 ExBlockPushLock(&HandleTable->HandleContentionEvent, &WaitBlock); 830 831 /* Get the current value and check if it's been unlocked */ 832 OldValue = HandleTableEntry->Value; 833 if (!(OldValue) || (OldValue & EXHANDLE_TABLE_ENTRY_LOCK_BIT)) 834 { 835 /* Unblock the pushlock and return */ 836 ExfUnblockPushLock(&HandleTable->HandleContentionEvent, &WaitBlock); 837 } 838 else 839 { 840 /* Wait for it to be unblocked */ 841 ExWaitForUnblockPushLock(&HandleTable->HandleContentionEvent, 842 &WaitBlock); 843 } 844 } 845 846 BOOLEAN 847 NTAPI 848 ExpLockHandleTableEntry(IN PHANDLE_TABLE HandleTable, 849 IN PHANDLE_TABLE_ENTRY HandleTableEntry) 850 { 851 LONG_PTR NewValue, OldValue; 852 853 /* Sanity check */ 854 ASSERT((KeGetCurrentThread()->CombinedApcDisable != 0) || 855 (KeGetCurrentIrql() == APC_LEVEL)); 856 857 /* Start lock loop */ 858 for (;;) 859 { 860 /* Get the current value and check if it's locked */ 861 OldValue = *(volatile LONG_PTR *)&HandleTableEntry->Object; 862 if (OldValue & EXHANDLE_TABLE_ENTRY_LOCK_BIT) 863 { 864 /* It's not locked, remove the lock bit to lock it */ 865 NewValue = OldValue & ~EXHANDLE_TABLE_ENTRY_LOCK_BIT; 866 if (InterlockedCompareExchangePointer(&HandleTableEntry->Object, 867 (PVOID)NewValue, 868 (PVOID)OldValue) == (PVOID)OldValue) 869 { 870 /* We locked it, get out */ 871 return TRUE; 872 } 873 } 874 else 875 { 876 /* We couldn't lock it, bail out if it's been freed */ 877 if (!OldValue) return FALSE; 878 } 879 880 /* It's locked, wait for it to be unlocked */ 881 ExpBlockOnLockedHandleEntry(HandleTable, HandleTableEntry); 882 } 883 } 884 885 VOID 886 NTAPI 887 ExUnlockHandleTableEntry(IN PHANDLE_TABLE HandleTable, 888 IN PHANDLE_TABLE_ENTRY HandleTableEntry) 889 { 890 LONG_PTR OldValue; 891 PAGED_CODE(); 892 893 /* Sanity check */ 894 ASSERT((KeGetCurrentThread()->CombinedApcDisable != 0) || 895 (KeGetCurrentIrql() == APC_LEVEL)); 896 897 /* Set the lock bit and make sure it wasn't earlier */ 898 OldValue = InterlockedOr((PLONG) &HandleTableEntry->Value, 899 EXHANDLE_TABLE_ENTRY_LOCK_BIT); 900 ASSERT((OldValue & EXHANDLE_TABLE_ENTRY_LOCK_BIT) == 0); 901 902 /* Unblock any waiters */ 903 ExfUnblockPushLock(&HandleTable->HandleContentionEvent, NULL); 904 } 905 906 VOID 907 NTAPI 908 ExRemoveHandleTable(IN PHANDLE_TABLE HandleTable) 909 { 910 PAGED_CODE(); 911 912 /* Acquire the table lock */ 913 KeEnterCriticalRegion(); 914 ExAcquirePushLockExclusive(&HandleTableListLock); 915 916 /* Remove the table and reset the list */ 917 RemoveEntryList(&HandleTable->HandleTableList); 918 InitializeListHead(&HandleTable->HandleTableList); 919 920 /* Release the lock */ 921 ExReleasePushLockExclusive(&HandleTableListLock); 922 KeLeaveCriticalRegion(); 923 } 924 925 VOID 926 NTAPI 927 ExDestroyHandleTable(IN PHANDLE_TABLE HandleTable, 928 IN PVOID DestroyHandleProcedure OPTIONAL) 929 { 930 PAGED_CODE(); 931 932 /* Remove the handle from the list */ 933 ExRemoveHandleTable(HandleTable); 934 935 /* Check if we have a destroy callback */ 936 if (DestroyHandleProcedure) 937 { 938 /* FIXME: */ 939 ASSERT(FALSE); 940 } 941 942 /* Free the handle table */ 943 ExpFreeHandleTable(HandleTable); 944 } 945 946 BOOLEAN 947 NTAPI 948 ExDestroyHandle(IN PHANDLE_TABLE HandleTable, 949 IN HANDLE Handle, 950 IN PHANDLE_TABLE_ENTRY HandleTableEntry OPTIONAL) 951 { 952 EXHANDLE ExHandle; 953 PVOID Object; 954 PAGED_CODE(); 955 956 /* Setup the actual handle value */ 957 ExHandle.GenericHandleOverlay = Handle; 958 959 /* Enter a critical region and check if we have to lookup the handle */ 960 KeEnterCriticalRegion(); 961 if (!HandleTableEntry) 962 { 963 /* Lookup the entry */ 964 HandleTableEntry = ExpLookupHandleTableEntry(HandleTable, ExHandle); 965 966 /* Make sure that we found an entry, and that it's valid */ 967 if (!(HandleTableEntry) || 968 !(HandleTableEntry->Object) || 969 (HandleTableEntry->NextFreeTableEntry == -2)) 970 { 971 /* Invalid handle, fail */ 972 KeLeaveCriticalRegion(); 973 return FALSE; 974 } 975 976 /* Lock the entry */ 977 if (!ExpLockHandleTableEntry(HandleTable, HandleTableEntry)) 978 { 979 /* Couldn't lock, fail */ 980 KeLeaveCriticalRegion(); 981 return FALSE; 982 } 983 } 984 else 985 { 986 /* Make sure the handle is locked */ 987 ASSERT((HandleTableEntry->Value & EXHANDLE_TABLE_ENTRY_LOCK_BIT) == 0); 988 } 989 990 /* Clear the handle */ 991 Object = InterlockedExchangePointer((PVOID*)&HandleTableEntry->Object, NULL); 992 993 /* Sanity checks */ 994 ASSERT(Object != NULL); 995 ASSERT((((ULONG_PTR)Object) & EXHANDLE_TABLE_ENTRY_LOCK_BIT) == 0); 996 997 /* Unblock the pushlock */ 998 ExfUnblockPushLock(&HandleTable->HandleContentionEvent, NULL); 999 1000 /* Free the actual entry */ 1001 ExpFreeHandleTableEntry(HandleTable, ExHandle, HandleTableEntry); 1002 1003 /* If we got here, return success */ 1004 KeLeaveCriticalRegion(); 1005 return TRUE; 1006 } 1007 1008 PHANDLE_TABLE_ENTRY 1009 NTAPI 1010 ExMapHandleToPointer(IN PHANDLE_TABLE HandleTable, 1011 IN HANDLE Handle) 1012 { 1013 EXHANDLE ExHandle; 1014 PHANDLE_TABLE_ENTRY HandleTableEntry; 1015 PAGED_CODE(); 1016 1017 /* Set the handle value */ 1018 ExHandle.GenericHandleOverlay = Handle; 1019 1020 /* Fail if we got an invalid index */ 1021 if (!(ExHandle.Index & (LOW_LEVEL_ENTRIES - 1))) return NULL; 1022 1023 /* Do the lookup */ 1024 HandleTableEntry = ExpLookupHandleTableEntry(HandleTable, ExHandle); 1025 if (!HandleTableEntry) return NULL; 1026 1027 /* Lock it */ 1028 if (!ExpLockHandleTableEntry(HandleTable, HandleTableEntry)) return NULL; 1029 1030 /* Return the entry */ 1031 return HandleTableEntry; 1032 } 1033 1034 PHANDLE_TABLE 1035 NTAPI 1036 ExDupHandleTable(IN PEPROCESS Process, 1037 IN PHANDLE_TABLE HandleTable, 1038 IN PEX_DUPLICATE_HANDLE_CALLBACK DupHandleProcedure, 1039 IN ULONG_PTR Mask) 1040 { 1041 PHANDLE_TABLE NewTable; 1042 EXHANDLE Handle; 1043 PHANDLE_TABLE_ENTRY HandleTableEntry, NewEntry; 1044 BOOLEAN Failed = FALSE; 1045 PAGED_CODE(); 1046 1047 /* Allocate the duplicated copy */ 1048 NewTable = ExpAllocateHandleTable(Process, FALSE); 1049 if (!NewTable) return NULL; 1050 1051 /* Loop each entry */ 1052 while (NewTable->NextHandleNeedingPool < 1053 HandleTable->NextHandleNeedingPool) 1054 { 1055 /* Insert it into the duplicated copy */ 1056 if (!ExpAllocateHandleTableEntrySlow(NewTable, FALSE)) 1057 { 1058 /* Insert failed, free the new copy and return */ 1059 ExpFreeHandleTable(NewTable); 1060 return NULL; 1061 } 1062 } 1063 1064 /* Setup the initial handle table data */ 1065 NewTable->HandleCount = 0; 1066 NewTable->ExtraInfoPages = 0; 1067 NewTable->FirstFree = 0; 1068 1069 /* Setup the first handle value */ 1070 Handle.Value = INDEX_TO_HANDLE_VALUE(1); 1071 1072 /* Enter a critical region and lookup the new entry */ 1073 KeEnterCriticalRegion(); 1074 while ((NewEntry = ExpLookupHandleTableEntry(NewTable, Handle))) 1075 { 1076 /* Lookup the old entry */ 1077 HandleTableEntry = ExpLookupHandleTableEntry(HandleTable, Handle); 1078 1079 /* Loop each entry */ 1080 do 1081 { 1082 /* Check if it doesn't match the audit mask */ 1083 if (!(HandleTableEntry->Value & Mask)) 1084 { 1085 /* Free it since we won't use it */ 1086 Failed = TRUE; 1087 } 1088 else 1089 { 1090 /* Lock the entry */ 1091 if (!ExpLockHandleTableEntry(HandleTable, HandleTableEntry)) 1092 { 1093 /* Free it since we can't lock it, so we won't use it */ 1094 Failed = TRUE; 1095 } 1096 else 1097 { 1098 /* Copy the handle value */ 1099 *NewEntry = *HandleTableEntry; 1100 1101 /* Call the duplicate callback */ 1102 if (DupHandleProcedure(Process, 1103 HandleTable, 1104 HandleTableEntry, 1105 NewEntry)) 1106 { 1107 /* Clear failure flag */ 1108 Failed = FALSE; 1109 1110 /* Lock the entry, increase the handle count */ 1111 NewEntry->Value |= EXHANDLE_TABLE_ENTRY_LOCK_BIT; 1112 NewTable->HandleCount++; 1113 } 1114 else 1115 { 1116 /* Duplication callback refused, fail */ 1117 Failed = TRUE; 1118 } 1119 } 1120 } 1121 1122 /* Check if we failed earlier and need to free */ 1123 if (Failed) 1124 { 1125 /* Free this entry */ 1126 NewEntry->Object = NULL; 1127 NewEntry->NextFreeTableEntry = NewTable->FirstFree; 1128 NewTable->FirstFree = (ULONG)Handle.Value; 1129 } 1130 1131 /* Increase the handle value and move to the next entry */ 1132 Handle.Value += INDEX_TO_HANDLE_VALUE(1); 1133 NewEntry++; 1134 HandleTableEntry++; 1135 } while (Handle.Value % INDEX_TO_HANDLE_VALUE(LOW_LEVEL_ENTRIES)); 1136 1137 /* We're done, skip the last entry */ 1138 Handle.Value += INDEX_TO_HANDLE_VALUE(1); 1139 } 1140 1141 /* Acquire the table lock and insert this new table into the list */ 1142 ExAcquirePushLockExclusive(&HandleTableListLock); 1143 InsertTailList(&HandleTableListHead, &NewTable->HandleTableList); 1144 ExReleasePushLockExclusive(&HandleTableListLock); 1145 1146 /* Leave the critical region we entered previously and return the table */ 1147 KeLeaveCriticalRegion(); 1148 return NewTable; 1149 } 1150 1151 BOOLEAN 1152 NTAPI 1153 ExChangeHandle(IN PHANDLE_TABLE HandleTable, 1154 IN HANDLE Handle, 1155 IN PEX_CHANGE_HANDLE_CALLBACK ChangeRoutine, 1156 IN ULONG_PTR Context) 1157 { 1158 EXHANDLE ExHandle; 1159 PHANDLE_TABLE_ENTRY HandleTableEntry; 1160 BOOLEAN Result = FALSE; 1161 PAGED_CODE(); 1162 1163 /* Set the handle value */ 1164 ExHandle.GenericHandleOverlay = Handle; 1165 1166 /* Find the entry for this handle */ 1167 HandleTableEntry = ExpLookupHandleTableEntry(HandleTable, ExHandle); 1168 1169 /* Make sure that we found an entry, and that it's valid */ 1170 if (!(HandleTableEntry) || 1171 !(HandleTableEntry->Object) || 1172 (HandleTableEntry->NextFreeTableEntry == -2)) 1173 { 1174 /* It isn't, fail */ 1175 return FALSE; 1176 } 1177 1178 /* Enter a critical region */ 1179 KeEnterCriticalRegion(); 1180 1181 /* Try locking the handle entry */ 1182 if (ExpLockHandleTableEntry(HandleTable, HandleTableEntry)) 1183 { 1184 /* Call the change routine and unlock the entry */ 1185 Result = ChangeRoutine(HandleTableEntry, Context); 1186 ExUnlockHandleTableEntry(HandleTable, HandleTableEntry); 1187 } 1188 1189 /* Leave the critical region and return the callback result */ 1190 KeLeaveCriticalRegion(); 1191 return Result; 1192 } 1193 1194 VOID 1195 NTAPI 1196 ExSweepHandleTable(IN PHANDLE_TABLE HandleTable, 1197 IN PEX_SWEEP_HANDLE_CALLBACK EnumHandleProcedure, 1198 IN PVOID Context) 1199 { 1200 EXHANDLE Handle; 1201 PHANDLE_TABLE_ENTRY HandleTableEntry; 1202 PAGED_CODE(); 1203 1204 /* Set the initial value and loop the entries */ 1205 Handle.Value = INDEX_TO_HANDLE_VALUE(1); 1206 while ((HandleTableEntry = ExpLookupHandleTableEntry(HandleTable, Handle))) 1207 { 1208 /* Loop each handle */ 1209 do 1210 { 1211 /* Lock the entry */ 1212 if (ExpLockHandleTableEntry(HandleTable, HandleTableEntry)) 1213 { 1214 /* Notify the callback routine */ 1215 EnumHandleProcedure(HandleTableEntry, 1216 Handle.GenericHandleOverlay, 1217 Context); 1218 } 1219 1220 /* Go to the next handle and entry */ 1221 Handle.Value += INDEX_TO_HANDLE_VALUE(1); 1222 HandleTableEntry++; 1223 } while (Handle.Value % INDEX_TO_HANDLE_VALUE(LOW_LEVEL_ENTRIES)); 1224 1225 /* Skip past the last entry */ 1226 Handle.Value += INDEX_TO_HANDLE_VALUE(1); 1227 } 1228 } 1229 1230 /* 1231 * @implemented 1232 */ 1233 BOOLEAN 1234 NTAPI 1235 ExEnumHandleTable(IN PHANDLE_TABLE HandleTable, 1236 IN PEX_ENUM_HANDLE_CALLBACK EnumHandleProcedure, 1237 IN OUT PVOID Context, 1238 OUT PHANDLE EnumHandle OPTIONAL) 1239 { 1240 EXHANDLE Handle; 1241 PHANDLE_TABLE_ENTRY HandleTableEntry; 1242 BOOLEAN Result = FALSE; 1243 PAGED_CODE(); 1244 1245 /* Enter a critical region */ 1246 KeEnterCriticalRegion(); 1247 1248 /* Set the initial value and loop the entries */ 1249 Handle.Value = 0; 1250 while ((HandleTableEntry = ExpLookupHandleTableEntry(HandleTable, Handle))) 1251 { 1252 /* Validate the entry */ 1253 if ((HandleTableEntry->Object) && 1254 (HandleTableEntry->NextFreeTableEntry != -2)) 1255 { 1256 /* Lock the entry */ 1257 if (ExpLockHandleTableEntry(HandleTable, HandleTableEntry)) 1258 { 1259 /* Notify the callback routine */ 1260 Result = EnumHandleProcedure(HandleTableEntry, 1261 Handle.GenericHandleOverlay, 1262 Context); 1263 1264 /* Unlock it */ 1265 ExUnlockHandleTableEntry(HandleTable, HandleTableEntry); 1266 1267 /* Was this the one looked for? */ 1268 if (Result) 1269 { 1270 /* If so, return it if requested */ 1271 if (EnumHandle) *EnumHandle = Handle.GenericHandleOverlay; 1272 break; 1273 } 1274 } 1275 } 1276 1277 /* Go to the next entry */ 1278 Handle.Value += INDEX_TO_HANDLE_VALUE(1); 1279 } 1280 1281 /* Leave the critical region and return callback result */ 1282 KeLeaveCriticalRegion(); 1283 return Result; 1284 } 1285 1286 #if DBG && defined(KDBG) 1287 BOOLEAN ExpKdbgExtHandle(ULONG Argc, PCHAR Argv[]) 1288 { 1289 USHORT i; 1290 char *endptr; 1291 HANDLE ProcessId; 1292 EXHANDLE ExHandle; 1293 PLIST_ENTRY Entry; 1294 PEPROCESS Process; 1295 WCHAR KeyPath[MAX_PATH]; 1296 PFILE_OBJECT FileObject; 1297 PHANDLE_TABLE HandleTable; 1298 POBJECT_HEADER ObjectHeader; 1299 PHANDLE_TABLE_ENTRY TableEntry; 1300 ULONG NeededLength, NameLength; 1301 PCM_KEY_CONTROL_BLOCK Kcb, CurrentKcb; 1302 POBJECT_HEADER_NAME_INFO ObjectNameInfo; 1303 1304 if (Argc > 1) 1305 { 1306 /* Get EPROCESS address or PID */ 1307 i = 0; 1308 while (Argv[1][i]) 1309 { 1310 if (!isdigit(Argv[1][i])) 1311 { 1312 i = 0; 1313 break; 1314 } 1315 1316 ++i; 1317 } 1318 1319 if (i == 0) 1320 { 1321 if (!KdbpGetHexNumber(Argv[1], (PVOID)&Process)) 1322 { 1323 KdbpPrint("Invalid parameter: %s\n", Argv[1]); 1324 return TRUE; 1325 } 1326 1327 /* In the end, we always want a PID */ 1328 ProcessId = PsGetProcessId(Process); 1329 } 1330 else 1331 { 1332 ProcessId = (HANDLE)strtoul(Argv[1], &endptr, 10); 1333 if (*endptr != '\0') 1334 { 1335 KdbpPrint("Invalid parameter: %s\n", Argv[1]); 1336 return TRUE; 1337 } 1338 } 1339 } 1340 else 1341 { 1342 ProcessId = PsGetCurrentProcessId(); 1343 } 1344 1345 for (Entry = HandleTableListHead.Flink; 1346 Entry != &HandleTableListHead; 1347 Entry = Entry->Flink) 1348 { 1349 /* Only return matching PID 1350 * 0 matches everything 1351 */ 1352 HandleTable = CONTAINING_RECORD(Entry, HANDLE_TABLE, HandleTableList); 1353 if (ProcessId != 0 && HandleTable->UniqueProcessId != ProcessId) 1354 { 1355 continue; 1356 } 1357 1358 KdbpPrint("\n"); 1359 1360 KdbpPrint("Handle table at %p with %d entries in use\n", HandleTable, HandleTable->HandleCount); 1361 1362 ExHandle.Value = 0; 1363 while ((TableEntry = ExpLookupHandleTableEntry(HandleTable, ExHandle))) 1364 { 1365 if ((TableEntry->Object) && 1366 (TableEntry->NextFreeTableEntry != -2)) 1367 { 1368 ObjectHeader = ObpGetHandleObject(TableEntry); 1369 1370 KdbpPrint("%p: Object: %p GrantedAccess: %x Entry: %p\n", ExHandle.Value, &ObjectHeader->Body, TableEntry->GrantedAccess, TableEntry); 1371 KdbpPrint("Object: %p Type: (%x) %wZ\n", &ObjectHeader->Body, ObjectHeader->Type, &ObjectHeader->Type->Name); 1372 KdbpPrint("\tObjectHeader: %p\n", ObjectHeader); 1373 KdbpPrint("\t\tHandleCount: %u PointerCount: %u\n", ObjectHeader->HandleCount, ObjectHeader->PointerCount); 1374 1375 /* Specific objects debug prints */ 1376 1377 /* For file, display path */ 1378 if (ObjectHeader->Type == IoFileObjectType) 1379 { 1380 FileObject = (PFILE_OBJECT)&ObjectHeader->Body; 1381 1382 KdbpPrint("\t\t\tName: %wZ\n", &FileObject->FileName); 1383 } 1384 1385 /* For directory, and win32k objects, display object name */ 1386 else if (ObjectHeader->Type == ObpDirectoryObjectType || 1387 ObjectHeader->Type == ExWindowStationObjectType || 1388 ObjectHeader->Type == ExDesktopObjectType || 1389 ObjectHeader->Type == MmSectionObjectType) 1390 { 1391 ObjectNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader); 1392 if (ObjectNameInfo != NULL && ObjectNameInfo->Name.Buffer != NULL) 1393 { 1394 KdbpPrint("\t\t\tName: %wZ\n", &ObjectNameInfo->Name); 1395 } 1396 } 1397 1398 /* For registry keys, display full path */ 1399 else if (ObjectHeader->Type == CmpKeyObjectType) 1400 { 1401 Kcb = ((PCM_KEY_BODY)&ObjectHeader->Body)->KeyControlBlock; 1402 if (!Kcb->Delete) 1403 { 1404 CurrentKcb = Kcb; 1405 1406 /* See: CmpQueryNameInformation() */ 1407 1408 while (CurrentKcb != NULL) 1409 { 1410 if (CurrentKcb->NameBlock->Compressed) 1411 NeededLength += CmpCompressedNameSize(CurrentKcb->NameBlock->Name, CurrentKcb->NameBlock->NameLength); 1412 else 1413 NeededLength += CurrentKcb->NameBlock->NameLength; 1414 1415 NeededLength += sizeof(OBJ_NAME_PATH_SEPARATOR); 1416 1417 CurrentKcb = CurrentKcb->ParentKcb; 1418 } 1419 1420 if (NeededLength < MAX_PATH * sizeof(WCHAR)) 1421 { 1422 CurrentKcb = Kcb; 1423 1424 while (CurrentKcb != NULL) 1425 { 1426 if (CurrentKcb->NameBlock->Compressed) 1427 { 1428 NameLength = CmpCompressedNameSize(CurrentKcb->NameBlock->Name, CurrentKcb->NameBlock->NameLength); 1429 CmpCopyCompressedName(&KeyPath[(NeededLength - NameLength)/sizeof(WCHAR)], 1430 NameLength, 1431 CurrentKcb->NameBlock->Name, 1432 CurrentKcb->NameBlock->NameLength); 1433 } 1434 else 1435 { 1436 NameLength = CurrentKcb->NameBlock->NameLength; 1437 RtlCopyMemory(&KeyPath[(NeededLength - NameLength)/sizeof(WCHAR)], 1438 CurrentKcb->NameBlock->Name, 1439 NameLength); 1440 } 1441 1442 NeededLength -= NameLength; 1443 NeededLength -= sizeof(OBJ_NAME_PATH_SEPARATOR); 1444 KeyPath[NeededLength/sizeof(WCHAR)] = OBJ_NAME_PATH_SEPARATOR; 1445 1446 CurrentKcb = CurrentKcb->ParentKcb; 1447 } 1448 } 1449 1450 KdbpPrint("\t\t\tName: %S\n", KeyPath); 1451 } 1452 } 1453 } 1454 1455 ExHandle.Value += INDEX_TO_HANDLE_VALUE(1); 1456 } 1457 } 1458 1459 return TRUE; 1460 } 1461 #endif 1462