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