1 /* 2 * PROJECT: ReactOS Kernel 3 * LICENSE: GPL - See COPYING in the top level directory 4 * FILE: ntoskrnl/ob/obhandle.c 5 * PURPOSE: Manages all functions related to the Object Manager handle 6 * implementation, including creating and destroying handles 7 * and/or handle tables, duplicating objects, and setting the 8 * permanent or temporary flags. 9 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) 10 * Eric Kohl 11 * Thomas Weidenmueller (w3seek@reactos.org) 12 */ 13 14 /* INCLUDES ******************************************************************/ 15 16 #include <ntoskrnl.h> 17 #define NDEBUG 18 #include <debug.h> 19 20 PHANDLE_TABLE ObpKernelHandleTable = NULL; 21 22 #define TAG_OB_HANDLE 'dHbO' 23 24 /* PRIVATE FUNCTIONS *********************************************************/ 25 26 PHANDLE_TABLE 27 NTAPI 28 ObReferenceProcessHandleTable(IN PEPROCESS Process) 29 { 30 PHANDLE_TABLE HandleTable = NULL; 31 32 /* Lock the process */ 33 if (ExAcquireRundownProtection(&Process->RundownProtect)) 34 { 35 /* Get the handle table */ 36 HandleTable = Process->ObjectTable; 37 if (!HandleTable) 38 { 39 /* No table, release the lock */ 40 ExReleaseRundownProtection(&Process->RundownProtect); 41 } 42 } 43 44 /* Return the handle table */ 45 return HandleTable; 46 } 47 48 VOID 49 NTAPI 50 ObDereferenceProcessHandleTable(IN PEPROCESS Process) 51 { 52 /* Release the process lock */ 53 ExReleaseRundownProtection(&Process->RundownProtect); 54 } 55 56 ULONG 57 NTAPI 58 ObGetProcessHandleCount(IN PEPROCESS Process) 59 { 60 ULONG HandleCount; 61 PHANDLE_TABLE HandleTable; 62 63 ASSERT(Process); 64 65 /* Ensure the handle table doesn't go away while we use it */ 66 HandleTable = ObReferenceProcessHandleTable(Process); 67 68 if (HandleTable != NULL) 69 { 70 /* Count the number of handles the process has */ 71 HandleCount = HandleTable->HandleCount; 72 73 /* Let the handle table go */ 74 ObDereferenceProcessHandleTable(Process); 75 } 76 else 77 { 78 /* No handle table, no handles */ 79 HandleCount = 0; 80 } 81 82 return HandleCount; 83 } 84 85 NTSTATUS 86 NTAPI 87 ObpReferenceProcessObjectByHandle(IN HANDLE Handle, 88 IN PEPROCESS Process, 89 IN PHANDLE_TABLE HandleTable, 90 IN KPROCESSOR_MODE AccessMode, 91 OUT PVOID *Object, 92 OUT POBJECT_HANDLE_INFORMATION HandleInformation, 93 OUT PACCESS_MASK AuditMask) 94 { 95 PHANDLE_TABLE_ENTRY HandleEntry; 96 POBJECT_HEADER ObjectHeader; 97 ACCESS_MASK GrantedAccess; 98 ULONG Attributes; 99 PETHREAD Thread = PsGetCurrentThread(); 100 NTSTATUS Status; 101 102 /* Assume failure */ 103 *Object = NULL; 104 105 /* Check if this is a special handle */ 106 if (HandleToLong(Handle) < 0) 107 { 108 /* Check if the caller wants the current process */ 109 if (Handle == NtCurrentProcess()) 110 { 111 /* Return handle info */ 112 HandleInformation->HandleAttributes = 0; 113 HandleInformation->GrantedAccess = Process->GrantedAccess; 114 115 /* No audit mask */ 116 *AuditMask = 0; 117 118 /* Reference ourselves */ 119 ObjectHeader = OBJECT_TO_OBJECT_HEADER(Process); 120 InterlockedIncrementSizeT(&ObjectHeader->PointerCount); 121 122 /* Return the pointer */ 123 *Object = Process; 124 ASSERT(*Object != NULL); 125 return STATUS_SUCCESS; 126 } 127 128 /* Check if the caller wants the current thread */ 129 if (Handle == NtCurrentThread()) 130 { 131 /* Return handle information */ 132 HandleInformation->HandleAttributes = 0; 133 HandleInformation->GrantedAccess = Thread->GrantedAccess; 134 135 /* Reference ourselves */ 136 ObjectHeader = OBJECT_TO_OBJECT_HEADER(Thread); 137 InterlockedIncrementSizeT(&ObjectHeader->PointerCount); 138 139 /* No audit mask */ 140 *AuditMask = 0; 141 142 /* Return the pointer */ 143 *Object = Thread; 144 ASSERT(*Object != NULL); 145 return STATUS_SUCCESS; 146 } 147 148 /* This is a kernel handle... do we have access? */ 149 if (AccessMode == KernelMode) 150 { 151 /* Use the kernel handle table and get the actual handle value */ 152 Handle = ObKernelHandleToHandle(Handle); 153 HandleTable = ObpKernelHandleTable; 154 } 155 else 156 { 157 /* This is an illegal attempt to access a kernel handle */ 158 return STATUS_INVALID_HANDLE; 159 } 160 } 161 162 /* Enter a critical region while we touch the handle table */ 163 ASSERT(HandleTable != NULL); 164 KeEnterCriticalRegion(); 165 166 /* Get the handle entry */ 167 HandleEntry = ExMapHandleToPointer(HandleTable, Handle); 168 if (HandleEntry) 169 { 170 /* Get the object header and validate the type*/ 171 ObjectHeader = ObpGetHandleObject(HandleEntry); 172 173 /* Get the granted access and validate it */ 174 GrantedAccess = HandleEntry->GrantedAccess; 175 176 /* Mask out the internal attributes */ 177 Attributes = HandleEntry->ObAttributes & OBJ_HANDLE_ATTRIBUTES; 178 179 /* Fill out the information */ 180 HandleInformation->HandleAttributes = Attributes; 181 HandleInformation->GrantedAccess = GrantedAccess; 182 183 /* No audit mask (FIXME!) */ 184 *AuditMask = 0; 185 186 /* Return the pointer */ 187 *Object = &ObjectHeader->Body; 188 189 /* Add a reference */ 190 InterlockedIncrementSizeT(&ObjectHeader->PointerCount); 191 192 /* Unlock the handle */ 193 ExUnlockHandleTableEntry(HandleTable, HandleEntry); 194 KeLeaveCriticalRegion(); 195 196 /* Return success */ 197 ASSERT(*Object != NULL); 198 return STATUS_SUCCESS; 199 } 200 else 201 { 202 /* Invalid handle */ 203 Status = STATUS_INVALID_HANDLE; 204 } 205 206 /* Return failure status */ 207 KeLeaveCriticalRegion(); 208 return Status; 209 } 210 211 BOOLEAN 212 NTAPI 213 ObpEnumFindHandleProcedure(IN PHANDLE_TABLE_ENTRY HandleEntry, 214 IN HANDLE Handle, 215 IN PVOID Context) 216 { 217 POBJECT_HEADER ObjectHeader; 218 ACCESS_MASK GrantedAccess; 219 ULONG HandleAttributes; 220 POBP_FIND_HANDLE_DATA FindData = Context; 221 222 /* Get the object header */ 223 ObjectHeader = ObpGetHandleObject(HandleEntry); 224 225 /* Make sure it's valid and matching */ 226 if ((FindData->ObjectHeader) && (FindData->ObjectHeader != ObjectHeader)) 227 { 228 /* No match, fail */ 229 return FALSE; 230 } 231 232 /* Now attempt to match the object type */ 233 if ((FindData->ObjectType) && (FindData->ObjectType != ObjectHeader->Type)) 234 { 235 /* No match, fail */ 236 return FALSE; 237 } 238 239 /* Check if we have extra information */ 240 if (FindData->HandleInformation) 241 { 242 /* Get the granted access and attributes */ 243 GrantedAccess = HandleEntry->GrantedAccess; 244 HandleAttributes = HandleEntry->ObAttributes & OBJ_HANDLE_ATTRIBUTES; 245 246 /* Attempt to match them */ 247 if ((FindData->HandleInformation->HandleAttributes != HandleAttributes) || 248 (FindData->HandleInformation->GrantedAccess != GrantedAccess)) 249 { 250 /* No match, fail */ 251 return FALSE; 252 } 253 } 254 255 /* We have a match */ 256 return TRUE; 257 } 258 259 POBJECT_HANDLE_COUNT_ENTRY 260 NTAPI 261 ObpInsertHandleCount(IN POBJECT_HEADER ObjectHeader) 262 { 263 POBJECT_HEADER_HANDLE_INFO HandleInfo; 264 POBJECT_HANDLE_COUNT_ENTRY FreeEntry; 265 POBJECT_HANDLE_COUNT_DATABASE HandleDatabase, OldHandleDatabase; 266 ULONG i; 267 ULONG Size, OldSize; 268 OBJECT_HANDLE_COUNT_DATABASE SingleDatabase; 269 PAGED_CODE(); 270 271 /* Get the handle info */ 272 HandleInfo = OBJECT_HEADER_TO_HANDLE_INFO(ObjectHeader); 273 if (!HandleInfo) return NULL; 274 275 /* Check if we only have one entry */ 276 if (ObjectHeader->Flags & OB_FLAG_SINGLE_PROCESS) 277 { 278 /* Fill out the single entry */ 279 SingleDatabase.CountEntries = 1; 280 SingleDatabase.HandleCountEntries[0] = HandleInfo->SingleEntry; 281 282 /* Use this as the old size */ 283 OldHandleDatabase = &SingleDatabase; 284 OldSize = sizeof(SingleDatabase); 285 286 /* Now we'll have two entries, and an entire DB */ 287 i = 2; 288 Size = sizeof(OBJECT_HANDLE_COUNT_DATABASE) + 289 ((i - 1) * sizeof(OBJECT_HANDLE_COUNT_ENTRY)); 290 } 291 else 292 { 293 /* We already have a DB, get the information from it */ 294 OldHandleDatabase = HandleInfo->HandleCountDatabase; 295 i = OldHandleDatabase->CountEntries; 296 OldSize = sizeof(OBJECT_HANDLE_COUNT_DATABASE) + 297 ((i - 1) * sizeof(OBJECT_HANDLE_COUNT_ENTRY)); 298 299 /* Add 4 more entries */ 300 i += 4; 301 Size = OldSize + (4 * sizeof(OBJECT_HANDLE_COUNT_ENTRY)); 302 } 303 304 /* Allocate the DB */ 305 HandleDatabase = ExAllocatePoolWithTag(PagedPool, Size, TAG_OB_HANDLE); 306 if (!HandleDatabase) return NULL; 307 308 /* Copy the old database */ 309 RtlCopyMemory(HandleDatabase, OldHandleDatabase, OldSize); 310 311 /* Check if we he had a single entry before */ 312 if (ObjectHeader->Flags & OB_FLAG_SINGLE_PROCESS) 313 { 314 /* Now we have more */ 315 ObjectHeader->Flags &= ~OB_FLAG_SINGLE_PROCESS; 316 } 317 else 318 { 319 /* Otherwise we had a DB, free it */ 320 ExFreePoolWithTag(OldHandleDatabase, TAG_OB_HANDLE); 321 } 322 323 /* Find the end of the copy and zero out the new data */ 324 FreeEntry = (PVOID)((ULONG_PTR)HandleDatabase + OldSize); 325 RtlZeroMemory(FreeEntry, Size - OldSize); 326 327 /* Set the new information and return the free entry */ 328 HandleDatabase->CountEntries = i; 329 HandleInfo->HandleCountDatabase = HandleDatabase; 330 return FreeEntry; 331 } 332 333 NTSTATUS 334 NTAPI 335 ObpIncrementHandleDataBase(IN POBJECT_HEADER ObjectHeader, 336 IN PEPROCESS Process, 337 IN OUT PULONG NewProcessHandleCount) 338 { 339 POBJECT_HEADER_HANDLE_INFO HandleInfo; 340 POBJECT_HANDLE_COUNT_ENTRY HandleEntry, FreeEntry = NULL; 341 POBJECT_HANDLE_COUNT_DATABASE HandleDatabase; 342 ULONG i; 343 PAGED_CODE(); 344 345 /* Get the handle info and check if we only have one entry */ 346 HandleInfo = OBJECT_HEADER_TO_HANDLE_INFO(ObjectHeader); 347 if (ObjectHeader->Flags & OB_FLAG_SINGLE_PROCESS) 348 { 349 /* Check if the entry is free */ 350 if (!HandleInfo->SingleEntry.HandleCount) 351 { 352 /* Add ours */ 353 HandleInfo->SingleEntry.HandleCount = 1; 354 HandleInfo->SingleEntry.Process = Process; 355 356 /* Return success and 1 handle */ 357 *NewProcessHandleCount = 1; 358 return STATUS_SUCCESS; 359 } 360 else if (HandleInfo->SingleEntry.Process == Process) 361 { 362 /* Busy entry, but same process */ 363 *NewProcessHandleCount = ++HandleInfo->SingleEntry.HandleCount; 364 return STATUS_SUCCESS; 365 } 366 else 367 { 368 /* Insert a new entry */ 369 FreeEntry = ObpInsertHandleCount(ObjectHeader); 370 if (!FreeEntry) return STATUS_INSUFFICIENT_RESOURCES; 371 ASSERT(!FreeEntry->Process); 372 ASSERT(!FreeEntry->HandleCount); 373 374 /* Fill it out */ 375 FreeEntry->Process = Process; 376 FreeEntry->HandleCount = 1; 377 378 /* Return success and 1 handle */ 379 *NewProcessHandleCount = 1; 380 return STATUS_SUCCESS; 381 } 382 } 383 384 /* We have a database instead */ 385 HandleDatabase = HandleInfo->HandleCountDatabase; 386 if (HandleDatabase) 387 { 388 /* Get the entries and loop them */ 389 i = HandleDatabase->CountEntries; 390 HandleEntry = &HandleDatabase->HandleCountEntries[0]; 391 while (i) 392 { 393 /* Check if this is a match */ 394 if (HandleEntry->Process == Process) 395 { 396 /* Found it, get the process handle count */ 397 *NewProcessHandleCount = ++HandleEntry->HandleCount; 398 return STATUS_SUCCESS; 399 } 400 else if (!HandleEntry->HandleCount) 401 { 402 /* Found a free entry */ 403 FreeEntry = HandleEntry; 404 } 405 406 /* Keep looping */ 407 HandleEntry++; 408 i--; 409 } 410 411 /* Check if we couldn't find a free entry */ 412 if (!FreeEntry) 413 { 414 /* Allocate one */ 415 FreeEntry = ObpInsertHandleCount(ObjectHeader); 416 if (!FreeEntry) return STATUS_INSUFFICIENT_RESOURCES; 417 ASSERT(!FreeEntry->Process); 418 ASSERT(!FreeEntry->HandleCount); 419 } 420 421 /* Fill out the entry */ 422 FreeEntry->Process = Process; 423 FreeEntry->HandleCount = 1; 424 *NewProcessHandleCount = 1; 425 } 426 427 /* Return success if we got here */ 428 return STATUS_SUCCESS; 429 } 430 431 NTSTATUS 432 NTAPI 433 ObpChargeQuotaForObject(IN POBJECT_HEADER ObjectHeader, 434 IN POBJECT_TYPE ObjectType, 435 OUT PBOOLEAN NewObject) 436 { 437 POBJECT_HEADER_QUOTA_INFO ObjectQuota; 438 ULONG PagedPoolCharge, NonPagedPoolCharge; 439 440 /* Get quota information */ 441 ObjectQuota = OBJECT_HEADER_TO_QUOTA_INFO(ObjectHeader); 442 *NewObject = FALSE; 443 444 /* Check if this is a new object */ 445 if (ObjectHeader->Flags & OB_FLAG_CREATE_INFO) 446 { 447 /* Remove the flag */ 448 ObjectHeader->Flags &= ~ OB_FLAG_CREATE_INFO; 449 if (ObjectQuota) 450 { 451 /* We have a quota, get the charges */ 452 PagedPoolCharge = ObjectQuota->PagedPoolCharge; 453 NonPagedPoolCharge = ObjectQuota->NonPagedPoolCharge; 454 } 455 else 456 { 457 /* Get it from the object type */ 458 PagedPoolCharge = ObjectType->TypeInfo.DefaultPagedPoolCharge; 459 NonPagedPoolCharge = ObjectType->TypeInfo.DefaultNonPagedPoolCharge; 460 } 461 462 /* Charge the quota */ 463 ObjectHeader->QuotaBlockCharged = (PVOID)1; 464 DPRINT("FIXME: Should charge: %lx %lx\n", PagedPoolCharge, NonPagedPoolCharge); 465 #if 0 466 PsChargeSharedPoolQuota(PsGetCurrentProcess(), 467 PagedPoolCharge, 468 NonPagedPoolCharge); 469 #endif 470 471 /* Check if we don't have a quota block */ 472 if (!ObjectHeader->QuotaBlockCharged) return STATUS_QUOTA_EXCEEDED; 473 474 /* Now set the flag */ 475 *NewObject = TRUE; 476 } 477 478 /* Return success */ 479 return STATUS_SUCCESS; 480 } 481 482 NTSTATUS 483 NTAPI 484 ObpValidateAccessMask(IN PACCESS_STATE AccessState) 485 { 486 PISECURITY_DESCRIPTOR SecurityDescriptor; 487 488 /* We're only interested if the object for this access state has an SD */ 489 SecurityDescriptor = AccessState->SecurityDescriptor; 490 if (SecurityDescriptor) 491 { 492 /* Check if the SD has a system ACL but hasn't been granted access to get/set it */ 493 if ((SecurityDescriptor->Control & SE_SACL_PRESENT) && 494 !(AccessState->PreviouslyGrantedAccess & ACCESS_SYSTEM_SECURITY)) 495 { 496 /* We're gonna need access */ 497 AccessState->RemainingDesiredAccess |= ACCESS_SYSTEM_SECURITY; 498 } 499 } 500 501 /* This can't fail */ 502 return STATUS_SUCCESS; 503 } 504 505 /*++ 506 * @name ObpDecrementHandleCount 507 * 508 * The ObpDecrementHandleCount routine <FILLMEIN> 509 * 510 * @param ObjectBody 511 * <FILLMEIN>. 512 * 513 * @param Process 514 * <FILLMEIN>. 515 * 516 * @param GrantedAccess 517 * <FILLMEIN>. 518 * 519 * @return None. 520 * 521 * @remarks None. 522 * 523 *--*/ 524 VOID 525 NTAPI 526 ObpDecrementHandleCount(IN PVOID ObjectBody, 527 IN PEPROCESS Process, 528 IN ACCESS_MASK GrantedAccess, 529 IN POBJECT_TYPE ObjectType) 530 { 531 POBJECT_HEADER ObjectHeader; 532 LONG SystemHandleCount, ProcessHandleCount; 533 LONG NewCount; 534 KIRQL CalloutIrql; 535 POBJECT_HEADER_HANDLE_INFO HandleInfo; 536 POBJECT_HANDLE_COUNT_ENTRY HandleEntry; 537 POBJECT_HANDLE_COUNT_DATABASE HandleDatabase; 538 ULONG i; 539 PAGED_CODE(); 540 541 /* Get the object type and header */ 542 ObjectHeader = OBJECT_TO_OBJECT_HEADER(ObjectBody); 543 OBTRACE(OB_HANDLE_DEBUG, 544 "%s - Decrementing count for: %p. HC PC %lx %lx\n", 545 __FUNCTION__, 546 ObjectBody, 547 ObjectHeader->HandleCount, 548 ObjectHeader->PointerCount); 549 550 /* Lock the object */ 551 ObpAcquireObjectLock(ObjectHeader); 552 553 /* Set default counts */ 554 SystemHandleCount = ObjectHeader->HandleCount; 555 ProcessHandleCount = 0; 556 557 /* Decrement the handle count */ 558 NewCount = InterlockedDecrementSizeT(&ObjectHeader->HandleCount); 559 560 /* Check if we're out of handles and this was an exclusive object */ 561 if (!(NewCount) && (ObjectHeader->Flags & OB_FLAG_EXCLUSIVE)) 562 { 563 /* Clear the exclusive flag */ 564 OBJECT_HEADER_TO_QUOTA_INFO(ObjectHeader)->ExclusiveProcess = NULL; 565 } 566 567 /* Is the object type keeping track of handles? */ 568 if (ObjectType->TypeInfo.MaintainHandleCount) 569 { 570 /* Get handle information */ 571 HandleInfo = OBJECT_HEADER_TO_HANDLE_INFO(ObjectHeader); 572 573 /* Check if there's only a single entry */ 574 if (ObjectHeader->Flags & OB_FLAG_SINGLE_PROCESS) 575 { 576 /* It should be us */ 577 ASSERT(HandleInfo->SingleEntry.Process == Process); 578 ASSERT(HandleInfo->SingleEntry.HandleCount > 0); 579 580 /* Get the handle counts */ 581 ProcessHandleCount = HandleInfo->SingleEntry.HandleCount--; 582 HandleEntry = &HandleInfo->SingleEntry; 583 } 584 else 585 { 586 /* Otherwise, get the database */ 587 HandleDatabase = HandleInfo->HandleCountDatabase; 588 if (HandleDatabase) 589 { 590 /* Get the entries and loop them */ 591 i = HandleDatabase->CountEntries; 592 HandleEntry = &HandleDatabase->HandleCountEntries[0]; 593 while (i) 594 { 595 /* Check if this is a match */ 596 if ((HandleEntry->HandleCount) && 597 (HandleEntry->Process == Process)) 598 { 599 /* Found it, get the process handle count */ 600 ProcessHandleCount = HandleEntry->HandleCount--; 601 break; 602 } 603 604 /* Keep looping */ 605 HandleEntry++; 606 i--; 607 } 608 } 609 else 610 { 611 /* No database, so no entry */ 612 HandleEntry = NULL; 613 } 614 } 615 616 /* Check if this is the last handle */ 617 if (ProcessHandleCount == 1) 618 { 619 /* Then clear the entry */ 620 HandleEntry->Process = NULL; 621 HandleEntry->HandleCount = 0; 622 } 623 } 624 625 /* Release the lock */ 626 ObpReleaseObjectLock(ObjectHeader); 627 628 /* Check if we have a close procedure */ 629 if (ObjectType->TypeInfo.CloseProcedure) 630 { 631 /* Call it */ 632 ObpCalloutStart(&CalloutIrql); 633 ObjectType->TypeInfo.CloseProcedure(Process, 634 ObjectBody, 635 GrantedAccess, 636 ProcessHandleCount, 637 SystemHandleCount); 638 ObpCalloutEnd(CalloutIrql, "Close", ObjectType, ObjectBody); 639 } 640 641 /* Check if we should delete the object */ 642 ObpDeleteNameCheck(ObjectBody); 643 644 /* Decrease the total number of handles for this type */ 645 InterlockedDecrement((PLONG)&ObjectType->TotalNumberOfHandles); 646 OBTRACE(OB_HANDLE_DEBUG, 647 "%s - Decremented count for: %p. HC PC %lx %lx\n", 648 __FUNCTION__, 649 ObjectBody, 650 ObjectHeader->HandleCount, 651 ObjectHeader->PointerCount); 652 } 653 654 /*++ 655 * @name ObpCloseHandleTableEntry 656 * 657 * The ObpCloseHandleTableEntry routine <FILLMEIN> 658 * 659 * @param HandleTable 660 * <FILLMEIN>. 661 * 662 * @param HandleEntry 663 * <FILLMEIN>. 664 * 665 * @param Handle 666 * <FILLMEIN>. 667 * 668 * @param AccessMode 669 * <FILLMEIN>. 670 * 671 * @param IgnoreHandleProtection 672 * <FILLMEIN>. 673 * 674 * @return <FILLMEIN>. 675 * 676 * @remarks None. 677 * 678 *--*/ 679 NTSTATUS 680 NTAPI 681 ObpCloseHandleTableEntry(IN PHANDLE_TABLE HandleTable, 682 IN PHANDLE_TABLE_ENTRY HandleEntry, 683 IN HANDLE Handle, 684 IN KPROCESSOR_MODE AccessMode, 685 IN BOOLEAN IgnoreHandleProtection) 686 { 687 PVOID Body; 688 POBJECT_TYPE ObjectType; 689 POBJECT_HEADER ObjectHeader; 690 ACCESS_MASK GrantedAccess; 691 KIRQL CalloutIrql; 692 PAGED_CODE(); 693 694 /* Get the object data */ 695 ObjectHeader = ObpGetHandleObject(HandleEntry); 696 ObjectType = ObjectHeader->Type; 697 Body = &ObjectHeader->Body; 698 GrantedAccess = HandleEntry->GrantedAccess; 699 OBTRACE(OB_HANDLE_DEBUG, 700 "%s - Closing handle: %p for %p. HC PC %lx %lx\n", 701 __FUNCTION__, 702 Handle, 703 Body, 704 ObjectHeader->HandleCount, 705 ObjectHeader->PointerCount); 706 707 /* Check if the object has an Okay To Close procedure */ 708 if (ObjectType->TypeInfo.OkayToCloseProcedure) 709 { 710 /* Call it and check if it's not letting us close it */ 711 ObpCalloutStart(&CalloutIrql); 712 if (!ObjectType->TypeInfo.OkayToCloseProcedure(PsGetCurrentProcess(), 713 Body, 714 Handle, 715 AccessMode)) 716 { 717 /* Fail */ 718 ObpCalloutEnd(CalloutIrql, "NtClose", ObjectType, Body); 719 ExUnlockHandleTableEntry(HandleTable, HandleEntry); 720 return STATUS_HANDLE_NOT_CLOSABLE; 721 } 722 723 /* Success, validate callout retrn */ 724 ObpCalloutEnd(CalloutIrql, "NtClose", ObjectType, Body); 725 } 726 727 /* The callback allowed us to close it, but does the handle itself? */ 728 if ((HandleEntry->GrantedAccess & ObpAccessProtectCloseBit) && 729 !(IgnoreHandleProtection)) 730 { 731 /* It doesn't, are we from user mode? */ 732 if (AccessMode != KernelMode) 733 { 734 /* We are! Unlock the entry */ 735 ExUnlockHandleTableEntry(HandleTable, HandleEntry); 736 737 /* Make sure we have a debug port */ 738 if (PsGetCurrentProcess()->DebugPort) 739 { 740 /* Raise an exception */ 741 return KeRaiseUserException(STATUS_HANDLE_NOT_CLOSABLE); 742 } 743 else 744 { 745 /* Return the error instead */ 746 return STATUS_HANDLE_NOT_CLOSABLE; 747 } 748 } 749 else 750 { 751 /* Otherwise, bugcheck the OS */ 752 KeBugCheckEx(INVALID_KERNEL_HANDLE, (ULONG_PTR)Handle, 0, 0, 0); 753 } 754 } 755 756 /* Destroy and unlock the handle entry */ 757 ExDestroyHandle(HandleTable, Handle, HandleEntry); 758 759 /* Now decrement the handle count */ 760 ObpDecrementHandleCount(Body, 761 PsGetCurrentProcess(), 762 GrantedAccess, 763 ObjectType); 764 765 /* Dereference the object as well */ 766 ObDereferenceObject(Body); 767 768 /* Return to caller */ 769 OBTRACE(OB_HANDLE_DEBUG, 770 "%s - Closed handle: %p for %p.\n", 771 __FUNCTION__, 772 Handle, 773 Body); 774 return STATUS_SUCCESS; 775 } 776 777 /*++ 778 * @name ObpIncrementHandleCount 779 * 780 * The ObpIncrementHandleCount routine <FILLMEIN> 781 * 782 * @param Object 783 * <FILLMEIN>. 784 * 785 * @param AccessState 786 * <FILLMEIN>. 787 * 788 * @param AccessMode 789 * <FILLMEIN>. 790 * 791 * @param HandleAttributes 792 * <FILLMEIN>. 793 * 794 * @param Process 795 * <FILLMEIN>. 796 * 797 * @param OpenReason 798 * <FILLMEIN>. 799 * 800 * @return <FILLMEIN>. 801 * 802 * @remarks None. 803 * 804 *--*/ 805 NTSTATUS 806 NTAPI 807 ObpIncrementHandleCount(IN PVOID Object, 808 IN PACCESS_STATE AccessState OPTIONAL, 809 IN KPROCESSOR_MODE AccessMode, 810 IN ULONG HandleAttributes, 811 IN PEPROCESS Process, 812 IN OB_OPEN_REASON OpenReason) 813 { 814 POBJECT_HEADER ObjectHeader; 815 POBJECT_TYPE ObjectType; 816 ULONG ProcessHandleCount; 817 NTSTATUS Status; 818 PEPROCESS ExclusiveProcess; 819 BOOLEAN Exclusive = FALSE, NewObject; 820 POBJECT_HEADER_CREATOR_INFO CreatorInfo; 821 KIRQL CalloutIrql; 822 KPROCESSOR_MODE ProbeMode; 823 ULONG Total; 824 POBJECT_HEADER_NAME_INFO NameInfo; 825 PAGED_CODE(); 826 827 /* Get the object header and type */ 828 ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object); 829 ObjectType = ObjectHeader->Type; 830 OBTRACE(OB_HANDLE_DEBUG, 831 "%s - Incrementing count for: %p. Reason: %lx. HC PC %lx %lx\n", 832 __FUNCTION__, 833 Object, 834 OpenReason, 835 ObjectHeader->HandleCount, 836 ObjectHeader->PointerCount); 837 838 /* Check if caller is forcing user mode */ 839 if (HandleAttributes & OBJ_FORCE_ACCESS_CHECK) 840 { 841 /* Force it */ 842 ProbeMode = UserMode; 843 } 844 else 845 { 846 /* Keep original setting */ 847 ProbeMode = AccessMode; 848 } 849 850 /* Lock the object */ 851 ObpAcquireObjectLock(ObjectHeader); 852 853 /* Charge quota and remove the creator info flag */ 854 Status = ObpChargeQuotaForObject(ObjectHeader, ObjectType, &NewObject); 855 if (!NT_SUCCESS(Status)) return Status; 856 857 /* Check if the open is exclusive */ 858 if (HandleAttributes & OBJ_EXCLUSIVE) 859 { 860 /* Check if the object allows this, or if the inherit flag was given */ 861 if ((HandleAttributes & OBJ_INHERIT) || 862 !(ObjectHeader->Flags & OB_FLAG_EXCLUSIVE)) 863 { 864 /* Incorrect attempt */ 865 Status = STATUS_INVALID_PARAMETER; 866 goto Quickie; 867 } 868 869 /* Check if we have access to it */ 870 ExclusiveProcess = OBJECT_HEADER_TO_EXCLUSIVE_PROCESS(ObjectHeader); 871 if ((!(ExclusiveProcess) && (ObjectHeader->HandleCount)) || 872 ((ExclusiveProcess) && (ExclusiveProcess != PsGetCurrentProcess()))) 873 { 874 /* This isn't the right process */ 875 Status = STATUS_ACCESS_DENIED; 876 goto Quickie; 877 } 878 879 /* Now you got exclusive access */ 880 Exclusive = TRUE; 881 } 882 else if ((ObjectHeader->Flags & OB_FLAG_EXCLUSIVE) && 883 (OBJECT_HEADER_TO_EXCLUSIVE_PROCESS(ObjectHeader))) 884 { 885 /* Caller didn't want exclusive access, but the object is exclusive */ 886 Status = STATUS_ACCESS_DENIED; 887 goto Quickie; 888 } 889 890 /* Check for exclusive kernel object */ 891 NameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader); 892 if ((NameInfo) && (NameInfo->QueryReferences & OB_FLAG_KERNEL_EXCLUSIVE) && 893 (ProbeMode != KernelMode)) 894 { 895 /* Caller is not kernel, but the object is kernel exclusive */ 896 Status = STATUS_ACCESS_DENIED; 897 goto Quickie; 898 } 899 900 /* 901 * Check if this is an object that went from 0 handles back to existence, 902 * but doesn't have an open procedure, only a close procedure. This means 903 * that it will never realize that the object is back alive, so we must 904 * fail the request. 905 */ 906 if (!(ObjectHeader->HandleCount) && 907 !(NewObject) && 908 (ObjectType->TypeInfo.MaintainHandleCount) && 909 !(ObjectType->TypeInfo.OpenProcedure) && 910 (ObjectType->TypeInfo.CloseProcedure)) 911 { 912 /* Fail */ 913 Status = STATUS_UNSUCCESSFUL; 914 goto Quickie; 915 } 916 917 /* Check if we're opening an existing handle */ 918 if ((OpenReason == ObOpenHandle) || 919 ((OpenReason == ObDuplicateHandle) && (AccessState))) 920 { 921 /* Validate the caller's access to this object */ 922 if (!ObCheckObjectAccess(Object, 923 AccessState, 924 TRUE, 925 ProbeMode, 926 &Status)) 927 { 928 /* Access was denied, so fail */ 929 goto Quickie; 930 } 931 } 932 else if (OpenReason == ObCreateHandle) 933 { 934 /* Convert MAXIMUM_ALLOWED to GENERIC_ALL */ 935 if (AccessState->RemainingDesiredAccess & MAXIMUM_ALLOWED) 936 { 937 /* Mask out MAXIMUM_ALLOWED and stick GENERIC_ALL instead */ 938 AccessState->RemainingDesiredAccess &= ~MAXIMUM_ALLOWED; 939 AccessState->RemainingDesiredAccess |= GENERIC_ALL; 940 } 941 942 /* Check if we have to map the GENERIC mask */ 943 if (AccessState->RemainingDesiredAccess & GENERIC_ACCESS) 944 { 945 /* Map it to the correct access masks */ 946 RtlMapGenericMask(&AccessState->RemainingDesiredAccess, 947 &ObjectType->TypeInfo.GenericMapping); 948 } 949 950 /* Check if the caller is trying to access system security */ 951 if (AccessState->RemainingDesiredAccess & ACCESS_SYSTEM_SECURITY) 952 { 953 /* FIXME: TODO */ 954 DPRINT1("ACCESS_SYSTEM_SECURITY not validated!\n"); 955 } 956 } 957 958 /* Check if this is an exclusive handle */ 959 if (Exclusive) 960 { 961 /* Save the owner process */ 962 OBJECT_HEADER_TO_QUOTA_INFO(ObjectHeader)->ExclusiveProcess = Process; 963 } 964 965 /* Increase the handle count */ 966 InterlockedIncrementSizeT(&ObjectHeader->HandleCount); 967 ProcessHandleCount = 0; 968 969 /* Check if we have a handle database */ 970 if (ObjectType->TypeInfo.MaintainHandleCount) 971 { 972 /* Increment the handle database */ 973 Status = ObpIncrementHandleDataBase(ObjectHeader, 974 Process, 975 &ProcessHandleCount); 976 if (!NT_SUCCESS(Status)) 977 { 978 /* FIXME: This should never happen for now */ 979 DPRINT1("Unhandled case\n"); 980 ASSERT(FALSE); 981 goto Quickie; 982 } 983 } 984 985 /* Release the lock */ 986 ObpReleaseObjectLock(ObjectHeader); 987 988 /* Check if we have an open procedure */ 989 Status = STATUS_SUCCESS; 990 if (ObjectType->TypeInfo.OpenProcedure) 991 { 992 /* Call it */ 993 ObpCalloutStart(&CalloutIrql); 994 Status = ObjectType->TypeInfo.OpenProcedure(OpenReason, 995 Process, 996 Object, 997 AccessState ? 998 AccessState-> 999 PreviouslyGrantedAccess : 1000 0, 1001 ProcessHandleCount); 1002 ObpCalloutEnd(CalloutIrql, "Open", ObjectType, Object); 1003 1004 /* Check if the open procedure failed */ 1005 if (!NT_SUCCESS(Status)) 1006 { 1007 /* FIXME: This should never happen for now */ 1008 DPRINT1("Unhandled case\n"); 1009 ASSERT(FALSE); 1010 return Status; 1011 } 1012 } 1013 1014 /* Check if this is a create operation */ 1015 if (OpenReason == ObCreateHandle) 1016 { 1017 /* Check if we have creator info */ 1018 CreatorInfo = OBJECT_HEADER_TO_CREATOR_INFO(ObjectHeader); 1019 if (CreatorInfo) 1020 { 1021 /* We do, acquire the lock */ 1022 ObpEnterObjectTypeMutex(ObjectType); 1023 1024 /* Insert us on the list */ 1025 InsertTailList(&ObjectType->TypeList, &CreatorInfo->TypeList); 1026 1027 /* Release the lock */ 1028 ObpLeaveObjectTypeMutex(ObjectType); 1029 } 1030 } 1031 1032 /* Increase total number of handles */ 1033 Total = InterlockedIncrement((PLONG)&ObjectType->TotalNumberOfHandles); 1034 if (Total > ObjectType->HighWaterNumberOfHandles) 1035 { 1036 /* Fixup count */ 1037 ObjectType->HighWaterNumberOfHandles = Total; 1038 } 1039 1040 /* Trace call and return */ 1041 OBTRACE(OB_HANDLE_DEBUG, 1042 "%s - Incremented count for: %p. Reason: %lx HC PC %lx %lx\n", 1043 __FUNCTION__, 1044 Object, 1045 OpenReason, 1046 ObjectHeader->HandleCount, 1047 ObjectHeader->PointerCount); 1048 return Status; 1049 1050 Quickie: 1051 /* Release lock and return */ 1052 ObpReleaseObjectLock(ObjectHeader); 1053 return Status; 1054 } 1055 1056 /*++ 1057 * @name ObpIncrementUnnamedHandleCount 1058 * 1059 * The ObpIncrementUnnamedHandleCount routine <FILLMEIN> 1060 * 1061 * @param Object 1062 * <FILLMEIN>. 1063 * 1064 * @param AccessState 1065 * <FILLMEIN>. 1066 * 1067 * @param AccessMode 1068 * <FILLMEIN>. 1069 * 1070 * @param HandleAttributes 1071 * <FILLMEIN>. 1072 * 1073 * @param Process 1074 * <FILLMEIN>. 1075 * 1076 * @param OpenReason 1077 * <FILLMEIN>. 1078 * 1079 * @return <FILLMEIN>. 1080 * 1081 * @remarks None. 1082 * 1083 *--*/ 1084 NTSTATUS 1085 NTAPI 1086 ObpIncrementUnnamedHandleCount(IN PVOID Object, 1087 IN PACCESS_MASK DesiredAccess, 1088 IN KPROCESSOR_MODE AccessMode, 1089 IN ULONG HandleAttributes, 1090 IN PEPROCESS Process) 1091 { 1092 POBJECT_HEADER ObjectHeader; 1093 POBJECT_TYPE ObjectType; 1094 ULONG ProcessHandleCount; 1095 NTSTATUS Status; 1096 PEPROCESS ExclusiveProcess; 1097 BOOLEAN Exclusive = FALSE, NewObject; 1098 POBJECT_HEADER_CREATOR_INFO CreatorInfo; 1099 KIRQL CalloutIrql; 1100 ULONG Total; 1101 1102 /* Get the object header and type */ 1103 ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object); 1104 ObjectType = ObjectHeader->Type; 1105 OBTRACE(OB_HANDLE_DEBUG, 1106 "%s - Incrementing count for: %p. UNNAMED. HC PC %lx %lx\n", 1107 __FUNCTION__, 1108 Object, 1109 ObjectHeader->HandleCount, 1110 ObjectHeader->PointerCount); 1111 1112 /* Lock the object */ 1113 ObpAcquireObjectLock(ObjectHeader); 1114 1115 /* Charge quota and remove the creator info flag */ 1116 Status = ObpChargeQuotaForObject(ObjectHeader, ObjectType, &NewObject); 1117 if (!NT_SUCCESS(Status)) return Status; 1118 1119 /* Check if the open is exclusive */ 1120 if (HandleAttributes & OBJ_EXCLUSIVE) 1121 { 1122 /* Check if the object allows this, or if the inherit flag was given */ 1123 if ((HandleAttributes & OBJ_INHERIT) || 1124 !(ObjectHeader->Flags & OB_FLAG_EXCLUSIVE)) 1125 { 1126 /* Incorrect attempt */ 1127 Status = STATUS_INVALID_PARAMETER; 1128 goto Quickie; 1129 } 1130 1131 /* Check if we have access to it */ 1132 ExclusiveProcess = OBJECT_HEADER_TO_EXCLUSIVE_PROCESS(ObjectHeader); 1133 if ((!(ExclusiveProcess) && (ObjectHeader->HandleCount)) || 1134 ((ExclusiveProcess) && (ExclusiveProcess != PsGetCurrentProcess()))) 1135 { 1136 /* This isn't the right process */ 1137 Status = STATUS_ACCESS_DENIED; 1138 goto Quickie; 1139 } 1140 1141 /* Now you got exclusive access */ 1142 Exclusive = TRUE; 1143 } 1144 else if ((ObjectHeader->Flags & OB_FLAG_EXCLUSIVE) && 1145 (OBJECT_HEADER_TO_EXCLUSIVE_PROCESS(ObjectHeader))) 1146 { 1147 /* Caller didn't want exclusive access, but the object is exclusive */ 1148 Status = STATUS_ACCESS_DENIED; 1149 goto Quickie; 1150 } 1151 1152 /* 1153 * Check if this is an object that went from 0 handles back to existence, 1154 * but doesn't have an open procedure, only a close procedure. This means 1155 * that it will never realize that the object is back alive, so we must 1156 * fail the request. 1157 */ 1158 if (!(ObjectHeader->HandleCount) && 1159 !(NewObject) && 1160 (ObjectType->TypeInfo.MaintainHandleCount) && 1161 !(ObjectType->TypeInfo.OpenProcedure) && 1162 (ObjectType->TypeInfo.CloseProcedure)) 1163 { 1164 /* Fail */ 1165 Status = STATUS_UNSUCCESSFUL; 1166 goto Quickie; 1167 } 1168 1169 /* Convert MAXIMUM_ALLOWED to GENERIC_ALL */ 1170 if (*DesiredAccess & MAXIMUM_ALLOWED) 1171 { 1172 /* Mask out MAXIMUM_ALLOWED and stick GENERIC_ALL instead */ 1173 *DesiredAccess &= ~MAXIMUM_ALLOWED; 1174 *DesiredAccess |= GENERIC_ALL; 1175 } 1176 1177 /* Check if we have to map the GENERIC mask */ 1178 if (*DesiredAccess & GENERIC_ACCESS) 1179 { 1180 /* Map it to the correct access masks */ 1181 RtlMapGenericMask(DesiredAccess, 1182 &ObjectType->TypeInfo.GenericMapping); 1183 } 1184 1185 /* Check if this is an exclusive handle */ 1186 if (Exclusive) 1187 { 1188 /* Save the owner process */ 1189 OBJECT_HEADER_TO_QUOTA_INFO(ObjectHeader)->ExclusiveProcess = Process; 1190 } 1191 1192 /* Increase the handle count */ 1193 InterlockedIncrementSizeT(&ObjectHeader->HandleCount); 1194 ProcessHandleCount = 0; 1195 1196 /* Check if we have a handle database */ 1197 if (ObjectType->TypeInfo.MaintainHandleCount) 1198 { 1199 /* Increment the handle database */ 1200 Status = ObpIncrementHandleDataBase(ObjectHeader, 1201 Process, 1202 &ProcessHandleCount); 1203 if (!NT_SUCCESS(Status)) 1204 { 1205 /* FIXME: This should never happen for now */ 1206 DPRINT1("Unhandled case\n"); 1207 ASSERT(FALSE); 1208 goto Quickie; 1209 } 1210 } 1211 1212 /* Release the lock */ 1213 ObpReleaseObjectLock(ObjectHeader); 1214 1215 /* Check if we have an open procedure */ 1216 Status = STATUS_SUCCESS; 1217 if (ObjectType->TypeInfo.OpenProcedure) 1218 { 1219 /* Call it */ 1220 ObpCalloutStart(&CalloutIrql); 1221 Status = ObjectType->TypeInfo.OpenProcedure(ObCreateHandle, 1222 Process, 1223 Object, 1224 *DesiredAccess, 1225 ProcessHandleCount); 1226 ObpCalloutEnd(CalloutIrql, "Open", ObjectType, Object); 1227 1228 /* Check if the open procedure failed */ 1229 if (!NT_SUCCESS(Status)) 1230 { 1231 /* FIXME: This should never happen for now */ 1232 DPRINT1("Unhandled case\n"); 1233 ASSERT(FALSE); 1234 return Status; 1235 } 1236 } 1237 1238 /* Check if we have creator info */ 1239 CreatorInfo = OBJECT_HEADER_TO_CREATOR_INFO(ObjectHeader); 1240 if (CreatorInfo) 1241 { 1242 /* We do, acquire the lock */ 1243 ObpEnterObjectTypeMutex(ObjectType); 1244 1245 /* Insert us on the list */ 1246 InsertTailList(&ObjectType->TypeList, &CreatorInfo->TypeList); 1247 1248 /* Release the lock */ 1249 ObpLeaveObjectTypeMutex(ObjectType); 1250 } 1251 1252 /* Increase total number of handles */ 1253 Total = InterlockedIncrement((PLONG)&ObjectType->TotalNumberOfHandles); 1254 if (Total > ObjectType->HighWaterNumberOfHandles) 1255 { 1256 /* Fixup count */ 1257 ObjectType->HighWaterNumberOfHandles = Total; 1258 } 1259 1260 /* Trace call and return */ 1261 OBTRACE(OB_HANDLE_DEBUG, 1262 "%s - Incremented count for: %p. UNNAMED HC PC %lx %lx\n", 1263 __FUNCTION__, 1264 Object, 1265 ObjectHeader->HandleCount, 1266 ObjectHeader->PointerCount); 1267 return Status; 1268 1269 Quickie: 1270 /* Release lock and return */ 1271 ObpReleaseObjectLock(ObjectHeader); 1272 return Status; 1273 } 1274 1275 /*++ 1276 * @name ObpCreateUnnamedHandle 1277 * 1278 * The ObpCreateUnnamedHandle routine <FILLMEIN> 1279 * 1280 * @param Object 1281 * <FILLMEIN>. 1282 * 1283 * @param DesiredAccess 1284 * <FILLMEIN>. 1285 * 1286 * @param AdditionalReferences 1287 * <FILLMEIN>. 1288 * 1289 * @param HandleAttributes 1290 * <FILLMEIN>. 1291 * 1292 * @param AccessMode 1293 * <FILLMEIN>. 1294 * 1295 * @param ReturnedObject 1296 * <FILLMEIN>. 1297 * 1298 * @param ReturnedHandle 1299 * <FILLMEIN>. 1300 * 1301 * @return <FILLMEIN>. 1302 * 1303 * @remarks None. 1304 * 1305 *--*/ 1306 NTSTATUS 1307 NTAPI 1308 ObpCreateUnnamedHandle(IN PVOID Object, 1309 IN ACCESS_MASK DesiredAccess, 1310 IN ULONG AdditionalReferences, 1311 IN ULONG HandleAttributes, 1312 IN KPROCESSOR_MODE AccessMode, 1313 OUT PVOID *ReturnedObject, 1314 OUT PHANDLE ReturnedHandle) 1315 { 1316 HANDLE_TABLE_ENTRY NewEntry; 1317 POBJECT_HEADER ObjectHeader; 1318 HANDLE Handle; 1319 KAPC_STATE ApcState; 1320 BOOLEAN AttachedToProcess = FALSE, KernelHandle = FALSE; 1321 PVOID HandleTable; 1322 NTSTATUS Status; 1323 ACCESS_MASK GrantedAccess; 1324 POBJECT_TYPE ObjectType; 1325 PAGED_CODE(); 1326 1327 /* Get the object header and type */ 1328 ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object); 1329 ObjectType = ObjectHeader->Type; 1330 OBTRACE(OB_HANDLE_DEBUG, 1331 "%s - Creating handle for: %p. UNNAMED. HC PC %lx %lx\n", 1332 __FUNCTION__, 1333 Object, 1334 ObjectHeader->HandleCount, 1335 ObjectHeader->PointerCount); 1336 1337 /* Save the object header */ 1338 NewEntry.Object = ObjectHeader; 1339 1340 /* Mask out the internal attributes */ 1341 NewEntry.ObAttributes |= HandleAttributes & OBJ_HANDLE_ATTRIBUTES; 1342 1343 /* Check if this is a kernel handle */ 1344 if (HandleAttributes & OBJ_KERNEL_HANDLE) 1345 { 1346 /* Set the handle table */ 1347 HandleTable = ObpKernelHandleTable; 1348 KernelHandle = TRUE; 1349 1350 /* Check if we're not in the system process */ 1351 if (PsGetCurrentProcess() != PsInitialSystemProcess) 1352 { 1353 /* Attach to the system process */ 1354 KeStackAttachProcess(&PsInitialSystemProcess->Pcb, &ApcState); 1355 AttachedToProcess = TRUE; 1356 } 1357 } 1358 else 1359 { 1360 /* Get the current handle table */ 1361 HandleTable = PsGetCurrentProcess()->ObjectTable; 1362 } 1363 1364 /* Increment the handle count */ 1365 Status = ObpIncrementUnnamedHandleCount(Object, 1366 &DesiredAccess, 1367 AccessMode, 1368 HandleAttributes, 1369 PsGetCurrentProcess()); 1370 if (!NT_SUCCESS(Status)) 1371 { 1372 /* 1373 * We failed (meaning security failure, according to NT Internals) 1374 * detach and return 1375 */ 1376 if (AttachedToProcess) KeUnstackDetachProcess(&ApcState); 1377 return Status; 1378 } 1379 1380 /* Remove what's not in the valid access mask */ 1381 GrantedAccess = DesiredAccess & (ObjectType->TypeInfo.ValidAccessMask | 1382 ACCESS_SYSTEM_SECURITY); 1383 1384 /* Handle extra references */ 1385 if (AdditionalReferences) 1386 { 1387 /* Add them to the header */ 1388 InterlockedExchangeAddSizeT(&ObjectHeader->PointerCount, 1389 AdditionalReferences); 1390 } 1391 1392 /* Save the access mask */ 1393 NewEntry.GrantedAccess = GrantedAccess; 1394 1395 /* 1396 * Create the actual handle. We'll need to do this *after* calling 1397 * ObpIncrementHandleCount to make sure that Object Security is valid 1398 * (specified in Gl00my documentation on Ob) 1399 */ 1400 OBTRACE(OB_HANDLE_DEBUG, 1401 "%s - Handle Properties: [%p-%lx-%lx]\n", 1402 __FUNCTION__, 1403 NewEntry.Object, NewEntry.ObAttributes & 3, NewEntry.GrantedAccess); 1404 Handle = ExCreateHandle(HandleTable, &NewEntry); 1405 1406 /* Make sure we got a handle */ 1407 if (Handle) 1408 { 1409 /* Check if this was a kernel handle */ 1410 if (KernelHandle) Handle = ObMarkHandleAsKernelHandle(Handle); 1411 1412 /* Return handle and object */ 1413 *ReturnedHandle = Handle; 1414 1415 /* Return the new object only if caller wanted it biased */ 1416 if ((AdditionalReferences) && (ReturnedObject)) 1417 { 1418 /* Return it */ 1419 *ReturnedObject = Object; 1420 } 1421 1422 /* Detach if needed */ 1423 if (AttachedToProcess) KeUnstackDetachProcess(&ApcState); 1424 1425 /* Trace and return */ 1426 OBTRACE(OB_HANDLE_DEBUG, 1427 "%s - Returning Handle: %p HC PC %lx %lx\n", 1428 __FUNCTION__, 1429 Handle, 1430 ObjectHeader->HandleCount, 1431 ObjectHeader->PointerCount); 1432 return STATUS_SUCCESS; 1433 } 1434 1435 /* Handle extra references */ 1436 if (AdditionalReferences) 1437 { 1438 /* Dereference it as many times as required */ 1439 InterlockedExchangeAddSizeT(&ObjectHeader->PointerCount, 1440 -(LONG)AdditionalReferences); 1441 } 1442 1443 /* Decrement the handle count and detach */ 1444 ObpDecrementHandleCount(&ObjectHeader->Body, 1445 PsGetCurrentProcess(), 1446 GrantedAccess, 1447 ObjectType); 1448 1449 /* Detach and fail */ 1450 if (AttachedToProcess) KeUnstackDetachProcess(&ApcState); 1451 return STATUS_INSUFFICIENT_RESOURCES; 1452 } 1453 1454 /*++ 1455 * @name ObpCreateHandle 1456 * 1457 * The ObpCreateHandle routine <FILLMEIN> 1458 * 1459 * @param OpenReason 1460 * <FILLMEIN>. 1461 * 1462 * @param Object 1463 * <FILLMEIN>. 1464 * 1465 * @param Type 1466 * <FILLMEIN>. 1467 * 1468 * @param AccessState 1469 * <FILLMEIN>. 1470 * 1471 * @param AdditionalReferences 1472 * <FILLMEIN>. 1473 * 1474 * @param HandleAttributes 1475 * <FILLMEIN>. 1476 * 1477 * @param AccessMode 1478 * <FILLMEIN>. 1479 * 1480 * @param ReturnedObject 1481 * <FILLMEIN>. 1482 * 1483 * @param ReturnedHandle 1484 * <FILLMEIN>. 1485 * 1486 * @return <FILLMEIN>. 1487 * 1488 * @remarks Cleans up the Lookup Context on return. 1489 * 1490 *--*/ 1491 NTSTATUS 1492 NTAPI 1493 ObpCreateHandle(IN OB_OPEN_REASON OpenReason, 1494 IN PVOID Object, 1495 IN POBJECT_TYPE Type OPTIONAL, 1496 IN PACCESS_STATE AccessState, 1497 IN ULONG AdditionalReferences, 1498 IN ULONG HandleAttributes, 1499 IN POBP_LOOKUP_CONTEXT Context, 1500 IN KPROCESSOR_MODE AccessMode, 1501 OUT PVOID *ReturnedObject, 1502 OUT PHANDLE ReturnedHandle) 1503 { 1504 HANDLE_TABLE_ENTRY NewEntry; 1505 POBJECT_HEADER ObjectHeader; 1506 HANDLE Handle; 1507 KAPC_STATE ApcState; 1508 BOOLEAN AttachedToProcess = FALSE, KernelHandle = FALSE; 1509 POBJECT_TYPE ObjectType; 1510 PVOID HandleTable; 1511 NTSTATUS Status; 1512 ACCESS_MASK DesiredAccess, GrantedAccess; 1513 PAUX_ACCESS_DATA AuxData; 1514 PAGED_CODE(); 1515 1516 /* Get the object header and type */ 1517 ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object); 1518 ObjectType = ObjectHeader->Type; 1519 OBTRACE(OB_HANDLE_DEBUG, 1520 "%s - Creating handle for: %p. Reason: %lx. HC PC %lx %lx\n", 1521 __FUNCTION__, 1522 Object, 1523 OpenReason, 1524 ObjectHeader->HandleCount, 1525 ObjectHeader->PointerCount); 1526 1527 /* Check if the types match */ 1528 if ((Type) && (ObjectType != Type)) 1529 { 1530 /* They don't, cleanup */ 1531 if (Context) ObpReleaseLookupContext(Context); 1532 return STATUS_OBJECT_TYPE_MISMATCH; 1533 } 1534 1535 /* Save the object header */ 1536 NewEntry.Object = ObjectHeader; 1537 1538 /* Check if this is a kernel handle */ 1539 if (HandleAttributes & OBJ_KERNEL_HANDLE) 1540 { 1541 /* Set the handle table */ 1542 HandleTable = ObpKernelHandleTable; 1543 KernelHandle = TRUE; 1544 1545 /* Check if we're not in the system process */ 1546 if (PsGetCurrentProcess() != PsInitialSystemProcess) 1547 { 1548 /* Attach to the system process */ 1549 KeStackAttachProcess(&PsInitialSystemProcess->Pcb, &ApcState); 1550 AttachedToProcess = TRUE; 1551 } 1552 } 1553 else 1554 { 1555 /* Get the current handle table */ 1556 HandleTable = PsGetCurrentProcess()->ObjectTable; 1557 } 1558 1559 /* Increment the handle count */ 1560 Status = ObpIncrementHandleCount(Object, 1561 AccessState, 1562 AccessMode, 1563 HandleAttributes, 1564 PsGetCurrentProcess(), 1565 OpenReason); 1566 if (!NT_SUCCESS(Status)) 1567 { 1568 /* 1569 * We failed (meaning security failure, according to NT Internals) 1570 * detach and return 1571 */ 1572 if (Context) ObpReleaseLookupContext(Context); 1573 if (AttachedToProcess) KeUnstackDetachProcess(&ApcState); 1574 return Status; 1575 } 1576 1577 /* Check if we are doing audits on close */ 1578 if (AccessState->GenerateOnClose) 1579 { 1580 /* Force the attribute on */ 1581 HandleAttributes |= OBJ_AUDIT_OBJECT_CLOSE; 1582 } 1583 1584 /* Mask out the internal attributes */ 1585 NewEntry.ObAttributes |= (HandleAttributes & OBJ_HANDLE_ATTRIBUTES); 1586 1587 /* Get the original desired access */ 1588 DesiredAccess = AccessState->RemainingDesiredAccess | 1589 AccessState->PreviouslyGrantedAccess; 1590 1591 /* Remove what's not in the valid access mask */ 1592 GrantedAccess = DesiredAccess & (ObjectType->TypeInfo.ValidAccessMask | 1593 ACCESS_SYSTEM_SECURITY); 1594 1595 /* Update the value in the access state */ 1596 AccessState->PreviouslyGrantedAccess = GrantedAccess; 1597 1598 /* Get the auxiliary data */ 1599 AuxData = AccessState->AuxData; 1600 1601 /* Handle extra references */ 1602 if (AdditionalReferences) 1603 { 1604 /* Add them to the header */ 1605 InterlockedExchangeAddSizeT(&ObjectHeader->PointerCount, 1606 AdditionalReferences); 1607 } 1608 1609 /* Now we can release the object */ 1610 if (Context) ObpReleaseLookupContext(Context); 1611 1612 /* Save the access mask */ 1613 NewEntry.GrantedAccess = GrantedAccess; 1614 1615 /* 1616 * Create the actual handle. We'll need to do this *after* calling 1617 * ObpIncrementHandleCount to make sure that Object Security is valid 1618 * (specified in Gl00my documentation on Ob) 1619 */ 1620 OBTRACE(OB_HANDLE_DEBUG, 1621 "%s - Handle Properties: [%p-%lx-%lx]\n", 1622 __FUNCTION__, 1623 NewEntry.Object, NewEntry.ObAttributes & 3, NewEntry.GrantedAccess); 1624 Handle = ExCreateHandle(HandleTable, &NewEntry); 1625 1626 /* Make sure we got a handle */ 1627 if (Handle) 1628 { 1629 /* Check if this was a kernel handle */ 1630 if (KernelHandle) Handle = ObMarkHandleAsKernelHandle(Handle); 1631 1632 /* Return it */ 1633 *ReturnedHandle = Handle; 1634 1635 /* Check if we need to generate on audit */ 1636 if (AccessState->GenerateAudit) 1637 { 1638 /* Audit the handle creation */ 1639 //SeAuditHandleCreation(AccessState, Handle); 1640 } 1641 1642 /* Check if this was a create */ 1643 if (OpenReason == ObCreateHandle) 1644 { 1645 /* Check if we need to audit the privileges */ 1646 if ((AuxData->PrivilegeSet) && 1647 (AuxData->PrivilegeSet->PrivilegeCount)) 1648 { 1649 /* Do the audit */ 1650 #if 0 1651 SePrivilegeObjectAuditAlarm(Handle, 1652 &AccessState-> 1653 SubjectSecurityContext, 1654 GrantedAccess, 1655 AuxData->PrivilegeSet, 1656 TRUE, 1657 ExGetPreviousMode()); 1658 #endif 1659 } 1660 } 1661 1662 /* Return the new object only if caller wanted it biased */ 1663 if ((AdditionalReferences) && (ReturnedObject)) 1664 { 1665 /* Return it */ 1666 *ReturnedObject = Object; 1667 } 1668 1669 /* Detach if needed */ 1670 if (AttachedToProcess) KeUnstackDetachProcess(&ApcState); 1671 1672 /* Trace and return */ 1673 OBTRACE(OB_HANDLE_DEBUG, 1674 "%s - Returning Handle: %p HC PC %lx %lx\n", 1675 __FUNCTION__, 1676 Handle, 1677 ObjectHeader->HandleCount, 1678 ObjectHeader->PointerCount); 1679 return STATUS_SUCCESS; 1680 } 1681 1682 /* Decrement the handle count and detach */ 1683 ObpDecrementHandleCount(&ObjectHeader->Body, 1684 PsGetCurrentProcess(), 1685 GrantedAccess, 1686 ObjectType); 1687 1688 /* Handle extra references */ 1689 if (AdditionalReferences) 1690 { 1691 /* Check how many extra references were added */ 1692 if (AdditionalReferences > 1) 1693 { 1694 /* Dereference it many times */ 1695 InterlockedExchangeAddSizeT(&ObjectHeader->PointerCount, 1696 -(LONG)(AdditionalReferences - 1)); 1697 } 1698 1699 /* Dereference the object one last time */ 1700 ObDereferenceObject(Object); 1701 } 1702 1703 /* Detach if necessary and fail */ 1704 if (AttachedToProcess) KeUnstackDetachProcess(&ApcState); 1705 return STATUS_INSUFFICIENT_RESOURCES; 1706 } 1707 1708 /*++ 1709 * @name ObpCloseHandle 1710 * 1711 * The ObpCloseHandle routine <FILLMEIN> 1712 * 1713 * @param Handle 1714 * <FILLMEIN>. 1715 * 1716 * @param AccessMode 1717 * <FILLMEIN>. 1718 * 1719 * @return <FILLMEIN>. 1720 * 1721 * @remarks None. 1722 * 1723 *--*/ 1724 NTSTATUS 1725 NTAPI 1726 ObpCloseHandle(IN HANDLE Handle, 1727 IN KPROCESSOR_MODE AccessMode) 1728 { 1729 PVOID HandleTable; 1730 BOOLEAN AttachedToProcess = FALSE; 1731 KAPC_STATE ApcState; 1732 PHANDLE_TABLE_ENTRY HandleTableEntry; 1733 NTSTATUS Status; 1734 PEPROCESS Process = PsGetCurrentProcess(); 1735 PAGED_CODE(); 1736 OBTRACE(OB_HANDLE_DEBUG, 1737 "%s - Closing handle: %p\n", __FUNCTION__, Handle); 1738 1739 if (AccessMode == KernelMode && Handle == (HANDLE)-1) 1740 return STATUS_INVALID_HANDLE; 1741 1742 /* Check if we're dealing with a kernel handle */ 1743 if (ObpIsKernelHandle(Handle, AccessMode)) 1744 { 1745 /* Use the kernel table and convert the handle */ 1746 HandleTable = ObpKernelHandleTable; 1747 Handle = ObKernelHandleToHandle(Handle); 1748 1749 /* Check if we're not in the system process */ 1750 if (Process != PsInitialSystemProcess) 1751 { 1752 /* Attach to the system process */ 1753 KeStackAttachProcess(&PsInitialSystemProcess->Pcb, &ApcState); 1754 AttachedToProcess = TRUE; 1755 } 1756 } 1757 else 1758 { 1759 /* Use the process's handle table */ 1760 HandleTable = Process->ObjectTable; 1761 } 1762 1763 /* Enter a critical region to protect handle access */ 1764 KeEnterCriticalRegion(); 1765 1766 /* Get the handle entry */ 1767 HandleTableEntry = ExMapHandleToPointer(HandleTable, Handle); 1768 if (HandleTableEntry) 1769 { 1770 /* Now close the entry */ 1771 Status = ObpCloseHandleTableEntry(HandleTable, 1772 HandleTableEntry, 1773 Handle, 1774 AccessMode, 1775 FALSE); 1776 1777 /* We can quit the critical region now */ 1778 KeLeaveCriticalRegion(); 1779 1780 /* Detach and return success */ 1781 if (AttachedToProcess) KeUnstackDetachProcess(&ApcState); 1782 } 1783 else 1784 { 1785 /* We failed, quit the critical region */ 1786 KeLeaveCriticalRegion(); 1787 1788 /* Detach */ 1789 if (AttachedToProcess) KeUnstackDetachProcess(&ApcState); 1790 1791 /* Check if we have a valid handle that's not the process or thread */ 1792 if ((Handle) && 1793 (Handle != NtCurrentProcess()) && 1794 (Handle != NtCurrentThread())) 1795 { 1796 /* Check if we came from user mode */ 1797 if (AccessMode != KernelMode) 1798 { 1799 /* Check if we have no debug port */ 1800 if (Process->DebugPort) 1801 { 1802 /* Make sure we're not attached */ 1803 if (!KeIsAttachedProcess()) 1804 { 1805 /* Raise an exception */ 1806 return KeRaiseUserException(STATUS_INVALID_HANDLE); 1807 } 1808 } 1809 } 1810 else 1811 { 1812 /* This is kernel mode. Check if we're exiting */ 1813 if (!(PsIsThreadTerminating(PsGetCurrentThread())) && 1814 (Process->Peb)) 1815 { 1816 /* Check if the debugger is enabled */ 1817 if (KdDebuggerEnabled) 1818 { 1819 /* Bugcheck */ 1820 KeBugCheckEx(INVALID_KERNEL_HANDLE, (ULONG_PTR)Handle, 1, 0, 0); 1821 } 1822 } 1823 } 1824 } 1825 1826 /* Set invalid status */ 1827 Status = STATUS_INVALID_HANDLE; 1828 } 1829 1830 /* Return status */ 1831 OBTRACE(OB_HANDLE_DEBUG, 1832 "%s - Closed handle: %p S: %lx\n", 1833 __FUNCTION__, Handle, Status); 1834 return Status; 1835 } 1836 1837 /*++ 1838 * @name ObpSetHandleAttributes 1839 * 1840 * The ObpSetHandleAttributes routine <FILLMEIN> 1841 * 1842 * @param HandleTableEntry 1843 * <FILLMEIN>. 1844 * 1845 * @param Context 1846 * <FILLMEIN>. 1847 * 1848 * @return <FILLMEIN>. 1849 * 1850 * @remarks None. 1851 * 1852 *--*/ 1853 BOOLEAN 1854 NTAPI 1855 ObpSetHandleAttributes(IN OUT PHANDLE_TABLE_ENTRY HandleTableEntry, 1856 IN ULONG_PTR Context) 1857 { 1858 POBP_SET_HANDLE_ATTRIBUTES_CONTEXT SetHandleInfo = (PVOID)Context; 1859 POBJECT_HEADER ObjectHeader = ObpGetHandleObject(HandleTableEntry); 1860 1861 /* Check if making the handle inheritable */ 1862 if (SetHandleInfo->Information.Inherit) 1863 { 1864 /* Check if inheriting is not supported for this object */ 1865 if (ObjectHeader->Type->TypeInfo.InvalidAttributes & OBJ_INHERIT) 1866 { 1867 /* Fail without changing anything */ 1868 return FALSE; 1869 } 1870 1871 /* Set the flag */ 1872 HandleTableEntry->ObAttributes |= OBJ_INHERIT; 1873 } 1874 else 1875 { 1876 /* Otherwise this implies we're removing the flag */ 1877 HandleTableEntry->ObAttributes &= ~OBJ_INHERIT; 1878 } 1879 1880 /* Check if making the handle protected */ 1881 if (SetHandleInfo->Information.ProtectFromClose) 1882 { 1883 /* Set the flag */ 1884 HandleTableEntry->GrantedAccess |= ObpAccessProtectCloseBit; 1885 } 1886 else 1887 { 1888 /* Otherwise, remove it */ 1889 HandleTableEntry->GrantedAccess &= ~ObpAccessProtectCloseBit; 1890 } 1891 1892 /* Return success */ 1893 return TRUE; 1894 } 1895 1896 /*++ 1897 * @name ObpCloseHandleCallback 1898 * 1899 * The ObpCloseHandleCallback routine <FILLMEIN> 1900 * 1901 * @param HandleTable 1902 * <FILLMEIN>. 1903 * 1904 * @param Object 1905 * <FILLMEIN>. 1906 * 1907 * @param GrantedAccess 1908 * <FILLMEIN>. 1909 * 1910 * @param Context 1911 * <FILLMEIN>. 1912 * 1913 * @return <FILLMEIN>. 1914 * 1915 * @remarks None. 1916 * 1917 *--*/ 1918 BOOLEAN 1919 NTAPI 1920 ObpCloseHandleCallback(IN PHANDLE_TABLE_ENTRY HandleTableEntry, 1921 IN HANDLE Handle, 1922 IN PVOID Context) 1923 { 1924 POBP_CLOSE_HANDLE_CONTEXT CloseContext = (POBP_CLOSE_HANDLE_CONTEXT)Context; 1925 1926 /* Simply decrement the handle count */ 1927 ObpCloseHandleTableEntry(CloseContext->HandleTable, 1928 HandleTableEntry, 1929 Handle, 1930 CloseContext->AccessMode, 1931 TRUE); 1932 return TRUE; 1933 } 1934 1935 /*++ 1936 * @name ObpDuplicateHandleCallback 1937 * 1938 * The ObpDuplicateHandleCallback routine <FILLMEIN> 1939 * 1940 * @param HandleTable 1941 * <FILLMEIN>. 1942 * 1943 * @param HandleTableEntry 1944 * <FILLMEIN>. 1945 * 1946 * @param Context 1947 * <FILLMEIN>. 1948 * 1949 * @return <FILLMEIN>. 1950 * 1951 * @remarks None. 1952 * 1953 *--*/ 1954 BOOLEAN 1955 NTAPI 1956 ObpDuplicateHandleCallback(IN PEPROCESS Process, 1957 IN PHANDLE_TABLE HandleTable, 1958 IN PHANDLE_TABLE_ENTRY OldEntry, 1959 IN PHANDLE_TABLE_ENTRY HandleTableEntry) 1960 { 1961 POBJECT_HEADER ObjectHeader; 1962 BOOLEAN Ret = FALSE; 1963 ACCESS_STATE AccessState; 1964 NTSTATUS Status; 1965 PAGED_CODE(); 1966 1967 /* Make sure that the handle is inheritable */ 1968 Ret = (HandleTableEntry->ObAttributes & OBJ_INHERIT) != 0; 1969 if (Ret) 1970 { 1971 /* Get the object header */ 1972 ObjectHeader = ObpGetHandleObject(HandleTableEntry); 1973 1974 /* Increment the pointer count */ 1975 InterlockedIncrementSizeT(&ObjectHeader->PointerCount); 1976 1977 /* Release the handle lock */ 1978 ExUnlockHandleTableEntry(HandleTable, OldEntry); 1979 1980 /* Setup the access state */ 1981 AccessState.PreviouslyGrantedAccess = HandleTableEntry->GrantedAccess; 1982 1983 /* Call the shared routine for incrementing handles */ 1984 Status = ObpIncrementHandleCount(&ObjectHeader->Body, 1985 &AccessState, 1986 KernelMode, 1987 HandleTableEntry->ObAttributes & OBJ_HANDLE_ATTRIBUTES, 1988 Process, 1989 ObInheritHandle); 1990 if (!NT_SUCCESS(Status)) 1991 { 1992 /* Return failure */ 1993 ObDereferenceObject(&ObjectHeader->Body); 1994 Ret = FALSE; 1995 } 1996 } 1997 else 1998 { 1999 /* Release the handle lock */ 2000 ExUnlockHandleTableEntry(HandleTable, OldEntry); 2001 } 2002 2003 /* Return duplication result */ 2004 return Ret; 2005 } 2006 2007 /*++ 2008 * @name ObClearProcessHandleTable 2009 * 2010 * The ObClearProcessHandleTable routine clears the handle table 2011 * of the given process. 2012 * 2013 * @param Process 2014 * The process of which the handle table should be cleared. 2015 * 2016 * @return None. 2017 * 2018 * @remarks None. 2019 * 2020 *--*/ 2021 VOID 2022 NTAPI 2023 ObClearProcessHandleTable(IN PEPROCESS Process) 2024 { 2025 PHANDLE_TABLE HandleTable; 2026 OBP_CLOSE_HANDLE_CONTEXT Context; 2027 KAPC_STATE ApcState; 2028 BOOLEAN AttachedToProcess = FALSE; 2029 2030 ASSERT(Process); 2031 2032 /* Ensure the handle table doesn't go away while we use it */ 2033 HandleTable = ObReferenceProcessHandleTable(Process); 2034 if (!HandleTable) return; 2035 2036 /* Attach to the current process if needed */ 2037 if (PsGetCurrentProcess() != Process) 2038 { 2039 KeStackAttachProcess(&Process->Pcb, &ApcState); 2040 AttachedToProcess = TRUE; 2041 } 2042 2043 /* Enter a critical region */ 2044 KeEnterCriticalRegion(); 2045 2046 /* Fill out the context */ 2047 Context.AccessMode = UserMode; 2048 Context.HandleTable = HandleTable; 2049 2050 /* Sweep the handle table to close all handles */ 2051 ExSweepHandleTable(HandleTable, 2052 ObpCloseHandleCallback, 2053 &Context); 2054 2055 /* Leave the critical region */ 2056 KeLeaveCriticalRegion(); 2057 2058 /* Detach if needed */ 2059 if (AttachedToProcess) 2060 KeUnstackDetachProcess(&ApcState); 2061 2062 /* Let the handle table go */ 2063 ObDereferenceProcessHandleTable(Process); 2064 } 2065 2066 /*++ 2067 * @name ObInitProcess 2068 * 2069 * The ObInitProcess routine initializes the handle table for the process 2070 * to be initialized, by either creating a new one or duplicating it from 2071 * the parent process. 2072 * 2073 * @param Parent 2074 * A parent process (optional). 2075 * 2076 * @param Process 2077 * The process to initialize. 2078 * 2079 * @return Success or failure. 2080 * 2081 * @remarks None. 2082 * 2083 *--*/ 2084 NTSTATUS 2085 NTAPI 2086 ObInitProcess(IN PEPROCESS Parent OPTIONAL, 2087 IN PEPROCESS Process) 2088 { 2089 PHANDLE_TABLE ParentTable, ObjectTable; 2090 2091 /* Check for a parent */ 2092 if (Parent) 2093 { 2094 /* Reference the parent's table */ 2095 ParentTable = ObReferenceProcessHandleTable(Parent); 2096 if (!ParentTable) return STATUS_PROCESS_IS_TERMINATING; 2097 2098 /* Duplicate it */ 2099 ObjectTable = ExDupHandleTable(Process, 2100 ParentTable, 2101 ObpDuplicateHandleCallback, 2102 OBJ_INHERIT); 2103 } 2104 else 2105 { 2106 /* Otherwise just create a new table */ 2107 ParentTable = NULL; 2108 ObjectTable = ExCreateHandleTable(Process); 2109 } 2110 2111 /* Make sure we have a table */ 2112 if (ObjectTable) 2113 { 2114 /* Associate it */ 2115 Process->ObjectTable = ObjectTable; 2116 2117 /* Check for auditing */ 2118 if (SeDetailedAuditingWithToken(NULL)) 2119 { 2120 /* FIXME: TODO */ 2121 DPRINT1("Need auditing!\n"); 2122 } 2123 2124 /* Get rid of the old table now */ 2125 if (ParentTable) ObDereferenceProcessHandleTable(Parent); 2126 2127 /* We are done */ 2128 return STATUS_SUCCESS; 2129 } 2130 else 2131 { 2132 /* Fail */ 2133 Process->ObjectTable = NULL; 2134 if (ParentTable) ObDereferenceProcessHandleTable(Parent); 2135 return STATUS_INSUFFICIENT_RESOURCES; 2136 } 2137 } 2138 2139 /*++ 2140 * @name ObKillProcess 2141 * 2142 * The ObKillProcess routine performs rundown operations on the process, 2143 * then clears and destroys its handle table. 2144 * 2145 * @param Process 2146 * The process to be killed. 2147 * 2148 * @return None. 2149 * 2150 * @remarks Called by the Object Manager cleanup code (kernel) 2151 * when a process is to be destroyed. 2152 * 2153 *--*/ 2154 VOID 2155 NTAPI 2156 ObKillProcess(IN PEPROCESS Process) 2157 { 2158 PHANDLE_TABLE HandleTable; 2159 OBP_CLOSE_HANDLE_CONTEXT Context; 2160 BOOLEAN HardErrors; 2161 PAGED_CODE(); 2162 2163 /* Wait for process rundown and then complete it */ 2164 ExWaitForRundownProtectionRelease(&Process->RundownProtect); 2165 ExRundownCompleted(&Process->RundownProtect); 2166 2167 /* Get the object table */ 2168 HandleTable = Process->ObjectTable; 2169 if (!HandleTable) return; 2170 2171 /* Disable hard errors while we close handles */ 2172 HardErrors = IoSetThreadHardErrorMode(FALSE); 2173 2174 /* Enter a critical region */ 2175 KeEnterCriticalRegion(); 2176 2177 /* Fill out the context */ 2178 Context.AccessMode = KernelMode; 2179 Context.HandleTable = HandleTable; 2180 2181 /* Sweep the handle table to close all handles */ 2182 ExSweepHandleTable(HandleTable, 2183 ObpCloseHandleCallback, 2184 &Context); 2185 ASSERT(HandleTable->HandleCount == 0); 2186 2187 /* Leave the critical region */ 2188 KeLeaveCriticalRegion(); 2189 2190 /* Re-enable hard errors */ 2191 IoSetThreadHardErrorMode(HardErrors); 2192 2193 /* Destroy the object table */ 2194 Process->ObjectTable = NULL; 2195 ExDestroyHandleTable(HandleTable, NULL); 2196 } 2197 2198 NTSTATUS 2199 NTAPI 2200 ObDuplicateObject(IN PEPROCESS SourceProcess, 2201 IN HANDLE SourceHandle, 2202 IN PEPROCESS TargetProcess OPTIONAL, 2203 IN PHANDLE TargetHandle OPTIONAL, 2204 IN ACCESS_MASK DesiredAccess, 2205 IN ULONG HandleAttributes, 2206 IN ULONG Options, 2207 IN KPROCESSOR_MODE PreviousMode) 2208 { 2209 HANDLE_TABLE_ENTRY NewHandleEntry; 2210 BOOLEAN AttachedToProcess = FALSE; 2211 PVOID SourceObject; 2212 POBJECT_HEADER ObjectHeader; 2213 POBJECT_TYPE ObjectType; 2214 HANDLE NewHandle; 2215 KAPC_STATE ApcState; 2216 NTSTATUS Status; 2217 ACCESS_MASK TargetAccess, SourceAccess; 2218 ACCESS_STATE AccessState; 2219 PACCESS_STATE PassedAccessState = NULL; 2220 AUX_ACCESS_DATA AuxData; 2221 PHANDLE_TABLE HandleTable; 2222 OBJECT_HANDLE_INFORMATION HandleInformation; 2223 ULONG AuditMask; 2224 BOOLEAN KernelHandle = FALSE; 2225 2226 PAGED_CODE(); 2227 OBTRACE(OB_HANDLE_DEBUG, 2228 "%s - Duplicating handle: %p for %p into %p\n", 2229 __FUNCTION__, 2230 SourceHandle, 2231 SourceProcess, 2232 TargetProcess); 2233 2234 /* Assume failure */ 2235 if (TargetHandle) *TargetHandle = NULL; 2236 2237 /* Check if we're not duplicating the same access */ 2238 if (!(Options & DUPLICATE_SAME_ACCESS)) 2239 { 2240 /* Validate the desired access */ 2241 Status = STATUS_SUCCESS; //ObpValidateDesiredAccess(DesiredAccess); 2242 if (!NT_SUCCESS(Status)) return Status; 2243 } 2244 2245 /* Reference the object table */ 2246 HandleTable = ObReferenceProcessHandleTable(SourceProcess); 2247 if (!HandleTable) return STATUS_PROCESS_IS_TERMINATING; 2248 2249 /* Reference the process object */ 2250 Status = ObpReferenceProcessObjectByHandle(SourceHandle, 2251 SourceProcess, 2252 HandleTable, 2253 PreviousMode, 2254 &SourceObject, 2255 &HandleInformation, 2256 &AuditMask); 2257 if (!NT_SUCCESS(Status)) 2258 { 2259 /* Fail */ 2260 ObDereferenceProcessHandleTable(SourceProcess); 2261 return Status; 2262 } 2263 else 2264 { 2265 /* Check if we have to don't have to audit object close */ 2266 if (!(HandleInformation.HandleAttributes & OBJ_AUDIT_OBJECT_CLOSE)) 2267 { 2268 /* Then there is no audit mask */ 2269 AuditMask = 0; 2270 } 2271 } 2272 2273 /* Check if there's no target process */ 2274 if (!TargetProcess) 2275 { 2276 /* Check if the caller wanted actual duplication */ 2277 if (!(Options & DUPLICATE_CLOSE_SOURCE)) 2278 { 2279 /* Invalid request */ 2280 Status = STATUS_INVALID_PARAMETER; 2281 } 2282 else 2283 { 2284 /* Otherwise, do the attach */ 2285 KeStackAttachProcess(&SourceProcess->Pcb, &ApcState); 2286 2287 /* Close the handle and detach */ 2288 NtClose(SourceHandle); 2289 KeUnstackDetachProcess(&ApcState); 2290 } 2291 2292 /* Return */ 2293 ObDereferenceProcessHandleTable(SourceProcess); 2294 ObDereferenceObject(SourceObject); 2295 return Status; 2296 } 2297 2298 /* Create a kernel handle if asked, but only in the system process */ 2299 if (PreviousMode == KernelMode && 2300 HandleAttributes & OBJ_KERNEL_HANDLE && 2301 TargetProcess == PsInitialSystemProcess) 2302 { 2303 KernelHandle = TRUE; 2304 } 2305 2306 /* Get the target handle table */ 2307 HandleTable = ObReferenceProcessHandleTable(TargetProcess); 2308 if (!HandleTable) 2309 { 2310 /* Check if the caller wanted us to close the handle */ 2311 if (Options & DUPLICATE_CLOSE_SOURCE) 2312 { 2313 /* Do the attach */ 2314 KeStackAttachProcess(&SourceProcess->Pcb, &ApcState); 2315 2316 /* Close the handle and detach */ 2317 NtClose(SourceHandle); 2318 KeUnstackDetachProcess(&ApcState); 2319 } 2320 2321 /* Return */ 2322 ObDereferenceProcessHandleTable(SourceProcess); 2323 ObDereferenceObject(SourceObject); 2324 return STATUS_PROCESS_IS_TERMINATING; 2325 } 2326 2327 /* Get the source access */ 2328 SourceAccess = HandleInformation.GrantedAccess; 2329 2330 /* Check if we're not in the target process */ 2331 if (TargetProcess != PsGetCurrentProcess()) 2332 { 2333 /* Attach to it */ 2334 KeStackAttachProcess(&TargetProcess->Pcb, &ApcState); 2335 AttachedToProcess = TRUE; 2336 } 2337 2338 /* Check if we're duplicating the attributes */ 2339 if (Options & DUPLICATE_SAME_ATTRIBUTES) 2340 { 2341 /* Duplicate them */ 2342 HandleAttributes = HandleInformation.HandleAttributes; 2343 } 2344 else 2345 { 2346 /* Don't allow caller to bypass auditing */ 2347 HandleAttributes |= HandleInformation.HandleAttributes & 2348 OBJ_AUDIT_OBJECT_CLOSE; 2349 } 2350 2351 /* Check if we're duplicating the access */ 2352 if (Options & DUPLICATE_SAME_ACCESS) DesiredAccess = SourceAccess; 2353 2354 /* Get object data */ 2355 ObjectHeader = OBJECT_TO_OBJECT_HEADER(SourceObject); 2356 ObjectType = ObjectHeader->Type; 2357 2358 /* Fill out the entry */ 2359 RtlZeroMemory(&NewHandleEntry, sizeof(HANDLE_TABLE_ENTRY)); 2360 NewHandleEntry.Object = ObjectHeader; 2361 NewHandleEntry.ObAttributes |= (HandleAttributes & OBJ_HANDLE_ATTRIBUTES); 2362 2363 /* Check if we're using a generic mask */ 2364 if (DesiredAccess & GENERIC_ACCESS) 2365 { 2366 /* Map it */ 2367 RtlMapGenericMask(&DesiredAccess, 2368 &ObjectType->TypeInfo.GenericMapping); 2369 } 2370 2371 /* Set the target access, always propagate ACCESS_SYSTEM_SECURITY */ 2372 TargetAccess = DesiredAccess & (ObjectType->TypeInfo.ValidAccessMask | 2373 ACCESS_SYSTEM_SECURITY); 2374 NewHandleEntry.GrantedAccess = TargetAccess; 2375 2376 /* Check if we're asking for new access */ 2377 if (TargetAccess & ~SourceAccess) 2378 { 2379 /* We are. We need the security procedure to validate this */ 2380 if (ObjectType->TypeInfo.SecurityProcedure == SeDefaultObjectMethod) 2381 { 2382 /* Use our built-in access state */ 2383 PassedAccessState = &AccessState; 2384 Status = SeCreateAccessState(&AccessState, 2385 &AuxData, 2386 TargetAccess, 2387 &ObjectType->TypeInfo.GenericMapping); 2388 } 2389 else 2390 { 2391 /* Otherwise we can't allow this privilege elevation */ 2392 Status = STATUS_ACCESS_DENIED; 2393 } 2394 } 2395 else 2396 { 2397 /* We don't need an access state */ 2398 Status = STATUS_SUCCESS; 2399 } 2400 2401 /* Make sure the access state was created OK */ 2402 if (NT_SUCCESS(Status)) 2403 { 2404 /* Add a new handle */ 2405 Status = ObpIncrementHandleCount(SourceObject, 2406 PassedAccessState, 2407 PreviousMode, 2408 HandleAttributes, 2409 PsGetCurrentProcess(), 2410 ObDuplicateHandle); 2411 } 2412 2413 /* Check if we were attached */ 2414 if (AttachedToProcess) 2415 { 2416 /* We can safely detach now */ 2417 KeUnstackDetachProcess(&ApcState); 2418 AttachedToProcess = FALSE; 2419 } 2420 2421 /* Check if we have to close the source handle */ 2422 if (Options & DUPLICATE_CLOSE_SOURCE) 2423 { 2424 /* Attach and close */ 2425 KeStackAttachProcess(&SourceProcess->Pcb, &ApcState); 2426 NtClose(SourceHandle); 2427 KeUnstackDetachProcess(&ApcState); 2428 } 2429 2430 /* Check if we had an access state */ 2431 if (PassedAccessState) SeDeleteAccessState(PassedAccessState); 2432 2433 /* Now check if incrementing actually failed */ 2434 if (!NT_SUCCESS(Status)) 2435 { 2436 /* Dereference handle tables */ 2437 ObDereferenceProcessHandleTable(SourceProcess); 2438 ObDereferenceProcessHandleTable(TargetProcess); 2439 2440 /* Dereference the source object */ 2441 ObDereferenceObject(SourceObject); 2442 return Status; 2443 } 2444 2445 if (NewHandleEntry.ObAttributes & OBJ_PROTECT_CLOSE) 2446 { 2447 NewHandleEntry.ObAttributes &= ~OBJ_PROTECT_CLOSE; 2448 NewHandleEntry.GrantedAccess |= ObpAccessProtectCloseBit; 2449 } 2450 2451 /* Now create the handle */ 2452 NewHandle = ExCreateHandle(HandleTable, &NewHandleEntry); 2453 if (!NewHandle) 2454 { 2455 /* Undo the increment */ 2456 ObpDecrementHandleCount(SourceObject, 2457 TargetProcess, 2458 TargetAccess, 2459 ObjectType); 2460 2461 /* Deference the object and set failure status */ 2462 ObDereferenceObject(SourceObject); 2463 Status = STATUS_INSUFFICIENT_RESOURCES; 2464 } 2465 2466 /* Mark it as a kernel handle if requested */ 2467 if (KernelHandle) 2468 { 2469 NewHandle = ObMarkHandleAsKernelHandle(NewHandle); 2470 } 2471 2472 /* Return the handle */ 2473 if (TargetHandle) *TargetHandle = NewHandle; 2474 2475 /* Dereference handle tables */ 2476 ObDereferenceProcessHandleTable(SourceProcess); 2477 ObDereferenceProcessHandleTable(TargetProcess); 2478 2479 /* Return status */ 2480 OBTRACE(OB_HANDLE_DEBUG, 2481 "%s - Duplicated handle: %p for %p into %p. Source: %p HC PC %lx %lx\n", 2482 __FUNCTION__, 2483 NewHandle, 2484 SourceProcess, 2485 TargetProcess, 2486 SourceObject, 2487 ObjectHeader->PointerCount, 2488 ObjectHeader->HandleCount); 2489 return Status; 2490 } 2491 2492 /* PUBLIC FUNCTIONS *********************************************************/ 2493 2494 /*++ 2495 * @name ObOpenObjectByName 2496 * @implemented NT4 2497 * 2498 * The ObOpenObjectByName routine <FILLMEIN> 2499 * 2500 * @param ObjectAttributes 2501 * <FILLMEIN>. 2502 * 2503 * @param ObjectType 2504 * <FILLMEIN>. 2505 * 2506 * @param AccessMode 2507 * <FILLMEIN>. 2508 * 2509 * @param PassedAccessState 2510 * <FILLMEIN>. 2511 * 2512 * @param DesiredAccess 2513 * <FILLMEIN>. 2514 * 2515 * @param ParseContext 2516 * <FILLMEIN>. 2517 * 2518 * @param Handle 2519 * <FILLMEIN>. 2520 * 2521 * @return <FILLMEIN>. 2522 * 2523 * @remarks None. 2524 * 2525 *--*/ 2526 NTSTATUS 2527 NTAPI 2528 ObOpenObjectByName(IN POBJECT_ATTRIBUTES ObjectAttributes, 2529 IN POBJECT_TYPE ObjectType, 2530 IN KPROCESSOR_MODE AccessMode, 2531 IN PACCESS_STATE PassedAccessState, 2532 IN ACCESS_MASK DesiredAccess, 2533 IN OUT PVOID ParseContext, 2534 OUT PHANDLE Handle) 2535 { 2536 PVOID Object = NULL; 2537 UNICODE_STRING ObjectName; 2538 NTSTATUS Status, Status2; 2539 POBJECT_HEADER ObjectHeader; 2540 PGENERIC_MAPPING GenericMapping = NULL; 2541 OB_OPEN_REASON OpenReason; 2542 POB_TEMP_BUFFER TempBuffer; 2543 PAGED_CODE(); 2544 2545 /* Assume failure */ 2546 *Handle = NULL; 2547 2548 /* Check if we didn't get any Object Attributes */ 2549 if (!ObjectAttributes) 2550 { 2551 /* Fail with special status code */ 2552 return STATUS_INVALID_PARAMETER; 2553 } 2554 2555 /* Allocate the temporary buffer */ 2556 TempBuffer = ExAllocatePoolWithTag(NonPagedPool, 2557 sizeof(OB_TEMP_BUFFER), 2558 TAG_OB_TEMP_STORAGE); 2559 if (!TempBuffer) return STATUS_INSUFFICIENT_RESOURCES; 2560 2561 /* Capture all the info */ 2562 Status = ObpCaptureObjectCreateInformation(ObjectAttributes, 2563 AccessMode, 2564 AccessMode, 2565 TRUE, 2566 &TempBuffer->ObjectCreateInfo, 2567 &ObjectName); 2568 if (!NT_SUCCESS(Status)) 2569 { 2570 /* Fail */ 2571 ExFreePoolWithTag(TempBuffer, TAG_OB_TEMP_STORAGE); 2572 return Status; 2573 } 2574 2575 /* Check if we didn't get an access state */ 2576 if (!PassedAccessState) 2577 { 2578 /* Try to get the generic mapping if we can */ 2579 if (ObjectType) GenericMapping = &ObjectType->TypeInfo.GenericMapping; 2580 2581 /* Use our built-in access state */ 2582 PassedAccessState = &TempBuffer->LocalAccessState; 2583 Status = SeCreateAccessState(&TempBuffer->LocalAccessState, 2584 &TempBuffer->AuxData, 2585 DesiredAccess, 2586 GenericMapping); 2587 if (!NT_SUCCESS(Status)) goto Quickie; 2588 } 2589 2590 /* Get the security descriptor */ 2591 if (TempBuffer->ObjectCreateInfo.SecurityDescriptor) 2592 { 2593 /* Save it in the access state */ 2594 PassedAccessState->SecurityDescriptor = 2595 TempBuffer->ObjectCreateInfo.SecurityDescriptor; 2596 } 2597 2598 /* Validate the access mask */ 2599 Status = ObpValidateAccessMask(PassedAccessState); 2600 if (!NT_SUCCESS(Status)) 2601 { 2602 /* Cleanup after lookup */ 2603 ObpReleaseLookupContext(&TempBuffer->LookupContext); 2604 goto Cleanup; 2605 } 2606 2607 /* Now do the lookup */ 2608 Status = ObpLookupObjectName(TempBuffer->ObjectCreateInfo.RootDirectory, 2609 &ObjectName, 2610 TempBuffer->ObjectCreateInfo.Attributes, 2611 ObjectType, 2612 AccessMode, 2613 ParseContext, 2614 TempBuffer->ObjectCreateInfo.SecurityQos, 2615 NULL, 2616 PassedAccessState, 2617 &TempBuffer->LookupContext, 2618 &Object); 2619 if (!NT_SUCCESS(Status)) 2620 { 2621 /* Cleanup after lookup */ 2622 ObpReleaseLookupContext(&TempBuffer->LookupContext); 2623 goto Cleanup; 2624 } 2625 2626 /* Check if this object has create information */ 2627 ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object); 2628 if (ObjectHeader->Flags & OB_FLAG_CREATE_INFO) 2629 { 2630 /* Then we are creating a new handle */ 2631 OpenReason = ObCreateHandle; 2632 2633 /* Check if we still have create info */ 2634 if (ObjectHeader->ObjectCreateInfo) 2635 { 2636 /* Free it */ 2637 ObpFreeObjectCreateInformation(ObjectHeader-> 2638 ObjectCreateInfo); 2639 ObjectHeader->ObjectCreateInfo = NULL; 2640 } 2641 } 2642 else 2643 { 2644 /* Otherwise, we are merely opening it */ 2645 OpenReason = ObOpenHandle; 2646 } 2647 2648 /* Check if we have invalid object attributes */ 2649 if (ObjectHeader->Type->TypeInfo.InvalidAttributes & 2650 TempBuffer->ObjectCreateInfo.Attributes) 2651 { 2652 /* Set failure code */ 2653 Status = STATUS_INVALID_PARAMETER; 2654 2655 /* Cleanup after lookup */ 2656 ObpReleaseLookupContext(&TempBuffer->LookupContext); 2657 2658 /* Dereference the object */ 2659 ObDereferenceObject(Object); 2660 } 2661 else 2662 { 2663 /* Create the actual handle now */ 2664 Status2 = ObpCreateHandle(OpenReason, 2665 Object, 2666 ObjectType, 2667 PassedAccessState, 2668 0, 2669 TempBuffer->ObjectCreateInfo.Attributes, 2670 &TempBuffer->LookupContext, 2671 AccessMode, 2672 NULL, 2673 Handle); 2674 if (!NT_SUCCESS(Status2)) 2675 { 2676 ObDereferenceObject(Object); 2677 Status = Status2; 2678 } 2679 } 2680 2681 Cleanup: 2682 /* Delete the access state */ 2683 if (PassedAccessState == &TempBuffer->LocalAccessState) 2684 { 2685 SeDeleteAccessState(PassedAccessState); 2686 } 2687 2688 Quickie: 2689 /* Release the object attributes and temporary buffer */ 2690 ObpReleaseObjectCreateInformation(&TempBuffer->ObjectCreateInfo); 2691 if (ObjectName.Buffer) ObpFreeObjectNameBuffer(&ObjectName); 2692 ExFreePoolWithTag(TempBuffer, TAG_OB_TEMP_STORAGE); 2693 2694 /* Return status */ 2695 OBTRACE(OB_HANDLE_DEBUG, 2696 "%s - returning Object %p with PC S: %lx %lx\n", 2697 __FUNCTION__, 2698 Object, 2699 Object ? OBJECT_TO_OBJECT_HEADER(Object)->PointerCount : -1, 2700 Status); 2701 return Status; 2702 } 2703 2704 /*++ 2705 * @name ObOpenObjectByPointer 2706 * @implemented NT4 2707 * 2708 * The ObOpenObjectByPointer routine <FILLMEIN> 2709 * 2710 * @param Object 2711 * <FILLMEIN>. 2712 * 2713 * @param HandleAttributes 2714 * <FILLMEIN>. 2715 * 2716 * @param PassedAccessState 2717 * <FILLMEIN>. 2718 * 2719 * @param DesiredAccess 2720 * <FILLMEIN>. 2721 * 2722 * @param ObjectType 2723 * <FILLMEIN>. 2724 * 2725 * @param AccessMode 2726 * <FILLMEIN>. 2727 * 2728 * @param Handle 2729 * <FILLMEIN>. 2730 * 2731 * @return <FILLMEIN>. 2732 * 2733 * @remarks None. 2734 * 2735 *--*/ 2736 NTSTATUS 2737 NTAPI 2738 ObOpenObjectByPointer(IN PVOID Object, 2739 IN ULONG HandleAttributes, 2740 IN PACCESS_STATE PassedAccessState, 2741 IN ACCESS_MASK DesiredAccess, 2742 IN POBJECT_TYPE ObjectType, 2743 IN KPROCESSOR_MODE AccessMode, 2744 OUT PHANDLE Handle) 2745 { 2746 POBJECT_HEADER Header; 2747 NTSTATUS Status; 2748 ACCESS_STATE AccessState; 2749 AUX_ACCESS_DATA AuxData; 2750 PAGED_CODE(); 2751 2752 /* Assume failure */ 2753 *Handle = NULL; 2754 2755 /* Reference the object */ 2756 Status = ObReferenceObjectByPointer(Object, 2757 0, 2758 ObjectType, 2759 AccessMode); 2760 if (!NT_SUCCESS(Status)) return Status; 2761 2762 /* Get the Header Info */ 2763 Header = OBJECT_TO_OBJECT_HEADER(Object); 2764 2765 /* Check if we didn't get an access state */ 2766 if (!PassedAccessState) 2767 { 2768 /* Use our built-in access state */ 2769 PassedAccessState = &AccessState; 2770 Status = SeCreateAccessState(&AccessState, 2771 &AuxData, 2772 DesiredAccess, 2773 &Header->Type->TypeInfo.GenericMapping); 2774 if (!NT_SUCCESS(Status)) 2775 { 2776 /* Fail */ 2777 ObDereferenceObject(Object); 2778 return Status; 2779 } 2780 } 2781 2782 /* Check if we have invalid object attributes */ 2783 if (Header->Type->TypeInfo.InvalidAttributes & HandleAttributes) 2784 { 2785 /* Delete the access state */ 2786 if (PassedAccessState == &AccessState) 2787 { 2788 SeDeleteAccessState(PassedAccessState); 2789 } 2790 2791 /* Dereference the object */ 2792 ObDereferenceObject(Object); 2793 return STATUS_INVALID_PARAMETER; 2794 } 2795 2796 /* Create the handle */ 2797 Status = ObpCreateHandle(ObOpenHandle, 2798 Object, 2799 ObjectType, 2800 PassedAccessState, 2801 0, 2802 HandleAttributes, 2803 NULL, 2804 AccessMode, 2805 NULL, 2806 Handle); 2807 if (!NT_SUCCESS(Status)) ObDereferenceObject(Object); 2808 2809 /* Delete the access state */ 2810 if (PassedAccessState == &AccessState) 2811 { 2812 SeDeleteAccessState(PassedAccessState); 2813 } 2814 2815 /* Return */ 2816 OBTRACE(OB_HANDLE_DEBUG, 2817 "%s - returning Object with PC S: %lx %lx\n", 2818 __FUNCTION__, 2819 OBJECT_TO_OBJECT_HEADER(Object)->PointerCount, 2820 Status); 2821 return Status; 2822 } 2823 2824 /*++ 2825 * @name ObFindHandleForObject 2826 * @implemented NT4 2827 * 2828 * The ObFindHandleForObject routine <FILLMEIN> 2829 * 2830 * @param Process 2831 * <FILLMEIN>. 2832 * 2833 * @param Object 2834 * <FILLMEIN>. 2835 * 2836 * @param ObjectType 2837 * <FILLMEIN>. 2838 * 2839 * @param HandleInformation 2840 * <FILLMEIN>. 2841 * 2842 * @param HandleReturn 2843 * <FILLMEIN>. 2844 * 2845 * @return <FILLMEIN>. 2846 * 2847 * @remarks None. 2848 * 2849 *--*/ 2850 BOOLEAN 2851 NTAPI 2852 ObFindHandleForObject(IN PEPROCESS Process, 2853 IN PVOID Object, 2854 IN POBJECT_TYPE ObjectType, 2855 IN POBJECT_HANDLE_INFORMATION HandleInformation, 2856 OUT PHANDLE Handle) 2857 { 2858 OBP_FIND_HANDLE_DATA FindData; 2859 BOOLEAN Result = FALSE; 2860 PVOID ObjectTable; 2861 2862 /* Make sure we have an object table */ 2863 ObjectTable = ObReferenceProcessHandleTable(Process); 2864 if (ObjectTable) 2865 { 2866 /* Check if we have an object */ 2867 if (Object) 2868 { 2869 /* Set its header */ 2870 FindData.ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object); 2871 } 2872 else 2873 { 2874 /* Otherwise, no object to match*/ 2875 FindData.ObjectHeader = NULL; 2876 } 2877 2878 /* Set other information */ 2879 FindData.ObjectType = ObjectType; 2880 FindData.HandleInformation = HandleInformation; 2881 2882 /* Enumerate the handle table */ 2883 if (ExEnumHandleTable(Process->ObjectTable, 2884 ObpEnumFindHandleProcedure, 2885 &FindData, 2886 Handle)) 2887 { 2888 /* Set success */ 2889 Result = TRUE; 2890 } 2891 2892 /* Let go of the table */ 2893 ObDereferenceProcessHandleTable(Process); 2894 } 2895 2896 /* Return the result */ 2897 return Result; 2898 } 2899 2900 /*++ 2901 * @name ObInsertObject 2902 * @implemented NT4 2903 * 2904 * The ObInsertObject routine <FILLMEIN> 2905 * 2906 * @param Object 2907 * <FILLMEIN>. 2908 * 2909 * @param PassedAccessState 2910 * <FILLMEIN>. 2911 * 2912 * @param DesiredAccess 2913 * <FILLMEIN>. 2914 * 2915 * @param AdditionalReferences 2916 * <FILLMEIN>. 2917 * 2918 * @param ReferencedObject 2919 * <FILLMEIN>. 2920 * 2921 * @param Handle 2922 * <FILLMEIN>. 2923 * 2924 * @return <FILLMEIN>. 2925 * 2926 * @remarks None. 2927 * 2928 *--*/ 2929 NTSTATUS 2930 NTAPI 2931 ObInsertObject(IN PVOID Object, 2932 IN PACCESS_STATE AccessState OPTIONAL, 2933 IN ACCESS_MASK DesiredAccess, 2934 IN ULONG ObjectPointerBias, 2935 OUT PVOID *NewObject OPTIONAL, 2936 OUT PHANDLE Handle) 2937 { 2938 POBJECT_CREATE_INFORMATION ObjectCreateInfo; 2939 POBJECT_HEADER ObjectHeader; 2940 POBJECT_TYPE ObjectType; 2941 PUNICODE_STRING ObjectName; 2942 PVOID InsertObject; 2943 PSECURITY_DESCRIPTOR ParentDescriptor = NULL; 2944 BOOLEAN SdAllocated = FALSE; 2945 POBJECT_HEADER_NAME_INFO ObjectNameInfo; 2946 OBP_LOOKUP_CONTEXT Context; 2947 ACCESS_STATE LocalAccessState; 2948 AUX_ACCESS_DATA AuxData; 2949 OB_OPEN_REASON OpenReason; 2950 KPROCESSOR_MODE PreviousMode; 2951 NTSTATUS Status = STATUS_SUCCESS, RealStatus; 2952 BOOLEAN IsNewObject; 2953 PAGED_CODE(); 2954 2955 /* Get the Header */ 2956 ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object); 2957 2958 /* Detect invalid insert */ 2959 if (!(ObjectHeader->Flags & OB_FLAG_CREATE_INFO)) 2960 { 2961 /* Display warning and break into debugger */ 2962 DPRINT1("OB: Attempting to insert existing object %p\n", Object); 2963 DbgBreakPoint(); 2964 2965 /* Allow debugger to continue */ 2966 ObDereferenceObject(Object); 2967 return STATUS_INVALID_PARAMETER; 2968 } 2969 2970 /* Get the create and name info, as well as the object type */ 2971 ObjectCreateInfo = ObjectHeader->ObjectCreateInfo; 2972 ObjectNameInfo = ObpReferenceNameInfo(ObjectHeader); 2973 ObjectType = ObjectHeader->Type; 2974 ObjectName = NULL; 2975 2976 /* Check if this is an named object */ 2977 if ((ObjectNameInfo) && (ObjectNameInfo->Name.Buffer)) 2978 { 2979 /* Get the object name */ 2980 ObjectName = &ObjectNameInfo->Name; 2981 } 2982 2983 /* Sanity check */ 2984 ASSERT((Handle) || 2985 ((ObjectPointerBias == 0) && 2986 (ObjectName == NULL) && 2987 (ObjectType->TypeInfo.SecurityRequired) && 2988 (NewObject == NULL))); 2989 2990 /* Check if the object is unnamed and also doesn't have security */ 2991 PreviousMode = KeGetPreviousMode(); 2992 if (!(ObjectType->TypeInfo.SecurityRequired) && !(ObjectName)) 2993 { 2994 /* Assume failure */ 2995 *Handle = NULL; 2996 ObjectHeader->ObjectCreateInfo = NULL; 2997 2998 /* Create the handle */ 2999 Status = ObpCreateUnnamedHandle(Object, 3000 DesiredAccess, 3001 ObjectPointerBias + 1, 3002 ObjectCreateInfo->Attributes, 3003 PreviousMode, 3004 NewObject, 3005 Handle); 3006 3007 /* Free the create information */ 3008 ObpFreeObjectCreateInformation(ObjectCreateInfo); 3009 3010 /* Release the object name information */ 3011 ObpDereferenceNameInfo(ObjectNameInfo); 3012 3013 /* Remove the extra keep-alive reference */ 3014 ObDereferenceObject(Object); 3015 3016 /* Return */ 3017 OBTRACE(OB_HANDLE_DEBUG, 3018 "%s - returning Object with PC S: %lx %lx\n", 3019 __FUNCTION__, 3020 ObjectHeader->PointerCount, 3021 Status); 3022 return Status; 3023 } 3024 3025 /* Check if we didn't get an access state */ 3026 if (!AccessState) 3027 { 3028 /* Use our built-in access state */ 3029 AccessState = &LocalAccessState; 3030 Status = SeCreateAccessState(&LocalAccessState, 3031 &AuxData, 3032 DesiredAccess, 3033 &ObjectType->TypeInfo.GenericMapping); 3034 if (!NT_SUCCESS(Status)) 3035 { 3036 /* Fail */ 3037 ObpDereferenceNameInfo(ObjectNameInfo); 3038 ObDereferenceObject(Object); 3039 return Status; 3040 } 3041 } 3042 3043 /* Save the security descriptor */ 3044 AccessState->SecurityDescriptor = ObjectCreateInfo->SecurityDescriptor; 3045 3046 /* Validate the access mask */ 3047 Status = ObpValidateAccessMask(AccessState); 3048 if (!NT_SUCCESS(Status)) 3049 { 3050 /* Fail */ 3051 ObpDereferenceNameInfo(ObjectNameInfo); 3052 ObDereferenceObject(Object); 3053 return Status; 3054 } 3055 3056 /* Setup a lookup context */ 3057 ObpInitializeLookupContext(&Context); 3058 InsertObject = Object; 3059 OpenReason = ObCreateHandle; 3060 3061 /* Check if the object is named */ 3062 if (ObjectName) 3063 { 3064 /* Look it up */ 3065 Status = ObpLookupObjectName(ObjectCreateInfo->RootDirectory, 3066 ObjectName, 3067 ObjectCreateInfo->Attributes, 3068 ObjectType, 3069 (ObjectHeader->Flags & OB_FLAG_KERNEL_MODE) ? 3070 KernelMode : UserMode, 3071 ObjectCreateInfo->ParseContext, 3072 ObjectCreateInfo->SecurityQos, 3073 Object, 3074 AccessState, 3075 &Context, 3076 &InsertObject); 3077 3078 /* Check if we found an object that doesn't match the one requested */ 3079 if ((NT_SUCCESS(Status)) && (InsertObject) && (Object != InsertObject)) 3080 { 3081 /* This means we're opening an object, not creating a new one */ 3082 OpenReason = ObOpenHandle; 3083 3084 /* Make sure the caller said it's OK to do this */ 3085 if (ObjectCreateInfo->Attributes & OBJ_OPENIF) 3086 { 3087 /* He did, but did he want this type? */ 3088 if (ObjectType != OBJECT_TO_OBJECT_HEADER(InsertObject)->Type) 3089 { 3090 /* Wrong type, so fail */ 3091 Status = STATUS_OBJECT_TYPE_MISMATCH; 3092 } 3093 else 3094 { 3095 /* Right type, so warn */ 3096 Status = STATUS_OBJECT_NAME_EXISTS; 3097 } 3098 } 3099 else 3100 { 3101 /* Check if this was a symbolic link */ 3102 if (OBJECT_TO_OBJECT_HEADER(InsertObject)->Type == 3103 ObpSymbolicLinkObjectType) 3104 { 3105 /* Dereference it */ 3106 ObDereferenceObject(InsertObject); 3107 } 3108 3109 /* Caller wanted to create a new object, fail */ 3110 Status = STATUS_OBJECT_NAME_COLLISION; 3111 } 3112 } 3113 3114 /* Check if anything until now failed */ 3115 if (!NT_SUCCESS(Status)) 3116 { 3117 /* Cleanup after lookup */ 3118 ObpReleaseLookupContext(&Context); 3119 3120 /* Remove query reference that we added */ 3121 ObpDereferenceNameInfo(ObjectNameInfo); 3122 3123 /* Dereference the object and delete the access state */ 3124 ObDereferenceObject(Object); 3125 if (AccessState == &LocalAccessState) 3126 { 3127 /* We used a local one; delete it */ 3128 SeDeleteAccessState(AccessState); 3129 } 3130 3131 /* Return failure code */ 3132 return Status; 3133 } 3134 else 3135 { 3136 /* Check if this is a symbolic link */ 3137 if (ObjectType == ObpSymbolicLinkObjectType) 3138 { 3139 /* Create the internal name */ 3140 ObpCreateSymbolicLinkName(Object); 3141 } 3142 } 3143 } 3144 3145 /* Now check if this object is being created */ 3146 if (InsertObject == Object) 3147 { 3148 /* Check if it's named or forces security */ 3149 if ((ObjectName) || (ObjectType->TypeInfo.SecurityRequired)) 3150 { 3151 /* Make sure it's inserted into an object directory */ 3152 if ((ObjectNameInfo) && (ObjectNameInfo->Directory)) 3153 { 3154 /* Get the current descriptor */ 3155 ObGetObjectSecurity(ObjectNameInfo->Directory, 3156 &ParentDescriptor, 3157 &SdAllocated); 3158 } 3159 3160 /* Now assign it */ 3161 Status = ObAssignSecurity(AccessState, 3162 ParentDescriptor, 3163 Object, 3164 ObjectType); 3165 3166 /* Check if we captured one */ 3167 if (ParentDescriptor) 3168 { 3169 /* We did, release it */ 3170 ObReleaseObjectSecurity(ParentDescriptor, SdAllocated); 3171 } 3172 else if (NT_SUCCESS(Status)) 3173 { 3174 /* Other we didn't, but we were able to use the current SD */ 3175 SeReleaseSecurityDescriptor(ObjectCreateInfo->SecurityDescriptor, 3176 ObjectCreateInfo->ProbeMode, 3177 TRUE); 3178 3179 /* Clear the current one */ 3180 AccessState->SecurityDescriptor = 3181 ObjectCreateInfo->SecurityDescriptor = NULL; 3182 } 3183 } 3184 3185 /* Check if anything until now failed */ 3186 if (!NT_SUCCESS(Status)) 3187 { 3188 /* Check if the directory was added */ 3189 if (Context.DirectoryLocked) 3190 { 3191 /* Weird case where we need to do a manual delete */ 3192 DPRINT1("Unhandled path\n"); 3193 ASSERT(FALSE); 3194 } 3195 3196 /* Cleanup the lookup */ 3197 ObpReleaseLookupContext(&Context); 3198 3199 /* Remove query reference that we added */ 3200 ObpDereferenceNameInfo(ObjectNameInfo); 3201 3202 /* Dereference the object and delete the access state */ 3203 ObDereferenceObject(Object); 3204 if (AccessState == &LocalAccessState) 3205 { 3206 /* We used a local one; delete it */ 3207 SeDeleteAccessState(AccessState); 3208 } 3209 3210 /* Return failure code */ 3211 ASSERT(FALSE); 3212 return Status; 3213 } 3214 } 3215 3216 /* Save the actual status until here */ 3217 RealStatus = Status; 3218 3219 /* Check if caller wants us to create a handle */ 3220 ObjectHeader->ObjectCreateInfo = NULL; 3221 if (Handle) 3222 { 3223 /* Create the handle */ 3224 Status = ObpCreateHandle(OpenReason, 3225 InsertObject, 3226 NULL, 3227 AccessState, 3228 ObjectPointerBias + 1, 3229 ObjectCreateInfo->Attributes, 3230 &Context, 3231 PreviousMode, 3232 NewObject, 3233 Handle); 3234 if (!NT_SUCCESS(Status)) 3235 { 3236 /* If the object had a name, backout everything */ 3237 if (ObjectName) ObpDeleteNameCheck(Object); 3238 3239 /* Return the status of the failure */ 3240 *Handle = NULL; 3241 RealStatus = Status; 3242 } 3243 3244 /* Remove a query reference */ 3245 ObpDereferenceNameInfo(ObjectNameInfo); 3246 3247 /* Remove the extra keep-alive reference */ 3248 ObDereferenceObject(Object); 3249 } 3250 else 3251 { 3252 /* Otherwise, lock the object */ 3253 ObpAcquireObjectLock(ObjectHeader); 3254 3255 /* And charge quota for the process to make it appear as used */ 3256 RealStatus = ObpChargeQuotaForObject(ObjectHeader, 3257 ObjectType, 3258 &IsNewObject); 3259 3260 /* Release the lock */ 3261 ObpReleaseObjectLock(ObjectHeader); 3262 3263 /* Check if we failed and dereference the object if so */ 3264 if (!NT_SUCCESS(RealStatus)) ObDereferenceObject(Object); 3265 } 3266 3267 /* We can delete the Create Info now */ 3268 ObpFreeObjectCreateInformation(ObjectCreateInfo); 3269 3270 /* Check if we created our own access state and delete it if so */ 3271 if (AccessState == &LocalAccessState) SeDeleteAccessState(AccessState); 3272 3273 /* Return status code */ 3274 OBTRACE(OB_HANDLE_DEBUG, 3275 "%s - returning Object with PC RS/S: %lx %lx %lx\n", 3276 __FUNCTION__, 3277 OBJECT_TO_OBJECT_HEADER(Object)->PointerCount, 3278 RealStatus, Status); 3279 return RealStatus; 3280 } 3281 3282 /*++ 3283 * @name ObSetHandleAttributes 3284 * @implemented NT5.1 3285 * 3286 * The ObSetHandleAttributes routine <FILLMEIN> 3287 * 3288 * @param Handle 3289 * <FILLMEIN>. 3290 * 3291 * @param HandleFlags 3292 * <FILLMEIN>. 3293 * 3294 * @param PreviousMode 3295 * <FILLMEIN>. 3296 * 3297 * @return <FILLMEIN>. 3298 * 3299 * @remarks None. 3300 * 3301 *--*/ 3302 NTSTATUS 3303 NTAPI 3304 ObSetHandleAttributes(IN HANDLE Handle, 3305 IN POBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleFlags, 3306 IN KPROCESSOR_MODE PreviousMode) 3307 { 3308 OBP_SET_HANDLE_ATTRIBUTES_CONTEXT SetHandleAttributesContext; 3309 BOOLEAN Result, AttachedToSystemProcess = FALSE; 3310 PHANDLE_TABLE HandleTable; 3311 KAPC_STATE ApcState; 3312 PAGED_CODE(); 3313 3314 /* Check if this is a kernel handle */ 3315 if (ObpIsKernelHandle(Handle, PreviousMode)) 3316 { 3317 /* Use the kernel table and convert the handle */ 3318 HandleTable = ObpKernelHandleTable; 3319 Handle = ObKernelHandleToHandle(Handle); 3320 3321 /* Check if we're not in the system process */ 3322 if (PsGetCurrentProcess() != PsInitialSystemProcess) 3323 { 3324 /* Attach to the system process */ 3325 KeStackAttachProcess(&PsInitialSystemProcess->Pcb, &ApcState); 3326 AttachedToSystemProcess = TRUE; 3327 } 3328 } 3329 else 3330 { 3331 /* Get the current process' handle table */ 3332 HandleTable = PsGetCurrentProcess()->ObjectTable; 3333 } 3334 3335 /* Initialize the handle attribute context */ 3336 SetHandleAttributesContext.PreviousMode = PreviousMode; 3337 SetHandleAttributesContext.Information = *HandleFlags; 3338 3339 /* Invoke the ObpSetHandleAttributes callback */ 3340 Result = ExChangeHandle(HandleTable, 3341 Handle, 3342 ObpSetHandleAttributes, 3343 (ULONG_PTR)&SetHandleAttributesContext); 3344 3345 /* Did we attach to the system process? */ 3346 if (AttachedToSystemProcess) 3347 { 3348 /* Detach from it */ 3349 KeUnstackDetachProcess(&ApcState); 3350 } 3351 3352 /* Return the result as an NTSTATUS value */ 3353 return Result ? STATUS_SUCCESS : STATUS_ACCESS_DENIED; 3354 } 3355 3356 /*++ 3357 * @name ObCloseHandle 3358 * @implemented NT5.1 3359 * 3360 * The ObCloseHandle routine <FILLMEIN> 3361 * 3362 * @param Handle 3363 * <FILLMEIN>. 3364 * 3365 * @param AccessMode 3366 * <FILLMEIN>. 3367 * 3368 * @return <FILLMEIN>. 3369 * 3370 * @remarks None. 3371 * 3372 *--*/ 3373 NTSTATUS 3374 NTAPI 3375 ObCloseHandle(IN HANDLE Handle, 3376 IN KPROCESSOR_MODE AccessMode) 3377 { 3378 /* Call the internal API */ 3379 return ObpCloseHandle(Handle, AccessMode); 3380 } 3381 3382 /*++ 3383 * @name NtClose 3384 * @implemented NT4 3385 * 3386 * The NtClose routine <FILLMEIN> 3387 * 3388 * @param Handle 3389 * <FILLMEIN>. 3390 * 3391 * @return <FILLMEIN>. 3392 * 3393 * @remarks None. 3394 * 3395 *--*/ 3396 NTSTATUS 3397 NTAPI 3398 NtClose(IN HANDLE Handle) 3399 { 3400 /* Call the internal API */ 3401 return ObpCloseHandle(Handle, ExGetPreviousMode()); 3402 } 3403 3404 NTSTATUS 3405 NTAPI 3406 NtDuplicateObject(IN HANDLE SourceProcessHandle, 3407 IN HANDLE SourceHandle, 3408 IN HANDLE TargetProcessHandle OPTIONAL, 3409 OUT PHANDLE TargetHandle OPTIONAL, 3410 IN ACCESS_MASK DesiredAccess, 3411 IN ULONG HandleAttributes, 3412 IN ULONG Options) 3413 { 3414 PEPROCESS SourceProcess, TargetProcess, Target; 3415 HANDLE hTarget; 3416 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); 3417 NTSTATUS Status; 3418 OBTRACE(OB_HANDLE_DEBUG, 3419 "%s - Duplicating handle: %p for %p into %p.\n", 3420 __FUNCTION__, 3421 SourceHandle, 3422 SourceProcessHandle, 3423 TargetProcessHandle); 3424 3425 /* Check if we have a target handle */ 3426 if ((TargetHandle) && (PreviousMode != KernelMode)) 3427 { 3428 /* Enter SEH */ 3429 _SEH2_TRY 3430 { 3431 /* Probe the handle and assume failure */ 3432 ProbeForWriteHandle(TargetHandle); 3433 *TargetHandle = NULL; 3434 } 3435 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 3436 { 3437 /* Return the exception code */ 3438 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 3439 } 3440 _SEH2_END; 3441 } 3442 3443 /* Now reference the input handle */ 3444 Status = ObReferenceObjectByHandle(SourceProcessHandle, 3445 PROCESS_DUP_HANDLE, 3446 PsProcessType, 3447 PreviousMode, 3448 (PVOID*)&SourceProcess, 3449 NULL); 3450 if (!NT_SUCCESS(Status)) return Status; 3451 3452 /* Check if got a target handle */ 3453 if (TargetProcessHandle) 3454 { 3455 /* Now reference the output handle */ 3456 Status = ObReferenceObjectByHandle(TargetProcessHandle, 3457 PROCESS_DUP_HANDLE, 3458 PsProcessType, 3459 PreviousMode, 3460 (PVOID*)&TargetProcess, 3461 NULL); 3462 if (NT_SUCCESS(Status)) 3463 { 3464 /* Use this target process */ 3465 Target = TargetProcess; 3466 } 3467 else 3468 { 3469 /* No target process */ 3470 Target = NULL; 3471 } 3472 } 3473 else 3474 { 3475 /* No target process */ 3476 Status = STATUS_SUCCESS; 3477 Target = NULL; 3478 } 3479 3480 /* Call the internal routine */ 3481 Status = ObDuplicateObject(SourceProcess, 3482 SourceHandle, 3483 Target, 3484 &hTarget, 3485 DesiredAccess, 3486 HandleAttributes, 3487 Options, 3488 PreviousMode); 3489 3490 /* Check if the caller wanted the return handle */ 3491 if (TargetHandle) 3492 { 3493 /* Protect the write to user mode */ 3494 _SEH2_TRY 3495 { 3496 /* Write the new handle */ 3497 *TargetHandle = hTarget; 3498 } 3499 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 3500 { 3501 /* Otherwise, get the exception code */ 3502 Status = _SEH2_GetExceptionCode(); 3503 } 3504 _SEH2_END; 3505 } 3506 3507 /* Dereference the processes */ 3508 OBTRACE(OB_HANDLE_DEBUG, 3509 "%s - Duplicated handle: %p into %p S %lx\n", 3510 __FUNCTION__, 3511 hTarget, 3512 TargetProcessHandle, 3513 Status); 3514 if (Target) ObDereferenceObject(Target); 3515 ObDereferenceObject(SourceProcess); 3516 return Status; 3517 } 3518 3519 BOOLEAN 3520 NTAPI 3521 ObIsKernelHandle(IN HANDLE Handle) 3522 { 3523 /* Use the inlined version. We know we are in kernel mode. */ 3524 return ObpIsKernelHandle(Handle, KernelMode); 3525 } 3526 3527 /* EOF */ 3528