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