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