Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenobhandle.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: ReactOS Kernel 00003 * LICENSE: GPL - See COPYING in the top level directory 00004 * FILE: ntoskrnl/ob/obhandle.c 00005 * PURPOSE: Manages all functions related to the Object Manager handle 00006 * implementation, including creating and destroying handles 00007 * and/or handle tables, duplicating objects, and setting the 00008 * permanent or temporary flags. 00009 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) 00010 * Eric Kohl 00011 * Thomas Weidenmueller (w3seek@reactos.org) 00012 */ 00013 00014 /* INCLUDES ******************************************************************/ 00015 00016 #include <ntoskrnl.h> 00017 #define NDEBUG 00018 #include <debug.h> 00019 00020 PHANDLE_TABLE ObpKernelHandleTable = NULL; 00021 ULONG ObpAccessProtectCloseBit = MAXIMUM_ALLOWED; 00022 00023 #define TAG_OB_HANDLE 'dHbO' 00024 00025 /* PRIVATE FUNCTIONS *********************************************************/ 00026 00027 PHANDLE_TABLE 00028 NTAPI 00029 ObReferenceProcessHandleTable(IN PEPROCESS Process) 00030 { 00031 PHANDLE_TABLE HandleTable = NULL; 00032 00033 /* Lock the process */ 00034 if (ExAcquireRundownProtection(&Process->RundownProtect)) 00035 { 00036 /* Get the handle table */ 00037 HandleTable = Process->ObjectTable; 00038 if (!HandleTable) 00039 { 00040 /* No table, release the lock */ 00041 ExReleaseRundownProtection(&Process->RundownProtect); 00042 } 00043 } 00044 00045 /* Return the handle table */ 00046 return HandleTable; 00047 } 00048 00049 VOID 00050 NTAPI 00051 ObDereferenceProcessHandleTable(IN PEPROCESS Process) 00052 { 00053 /* Release the process lock */ 00054 ExReleaseRundownProtection(&Process->RundownProtect); 00055 } 00056 00057 ULONG 00058 NTAPI 00059 ObGetProcessHandleCount(IN PEPROCESS Process) 00060 { 00061 ULONG HandleCount; 00062 PHANDLE_TABLE HandleTable; 00063 00064 ASSERT(Process); 00065 00066 /* Ensure the handle table doesn't go away while we use it */ 00067 HandleTable = ObReferenceProcessHandleTable(Process); 00068 00069 if (HandleTable != NULL) 00070 { 00071 /* Count the number of handles the process has */ 00072 HandleCount = HandleTable->HandleCount; 00073 00074 /* Let the handle table go */ 00075 ObDereferenceProcessHandleTable(Process); 00076 } 00077 else 00078 { 00079 /* No handle table, no handles */ 00080 HandleCount = 0; 00081 } 00082 00083 return HandleCount; 00084 } 00085 00086 NTSTATUS 00087 NTAPI 00088 ObpReferenceProcessObjectByHandle(IN HANDLE Handle, 00089 IN PEPROCESS Process, 00090 IN PHANDLE_TABLE HandleTable, 00091 IN KPROCESSOR_MODE AccessMode, 00092 OUT PVOID *Object, 00093 OUT POBJECT_HANDLE_INFORMATION HandleInformation, 00094 OUT PACCESS_MASK AuditMask) 00095 { 00096 PHANDLE_TABLE_ENTRY HandleEntry; 00097 POBJECT_HEADER ObjectHeader; 00098 ACCESS_MASK GrantedAccess; 00099 ULONG Attributes; 00100 PETHREAD Thread = PsGetCurrentThread(); 00101 NTSTATUS Status; 00102 00103 /* Assume failure */ 00104 *Object = NULL; 00105 00106 /* Check if this is a special handle */ 00107 if (HandleToLong(Handle) < 0) 00108 { 00109 /* Check if the caller wants the current process */ 00110 if (Handle == NtCurrentProcess()) 00111 { 00112 /* Return handle info */ 00113 HandleInformation->HandleAttributes = 0; 00114 HandleInformation->GrantedAccess = Process->GrantedAccess; 00115 00116 /* No audit mask */ 00117 *AuditMask = 0; 00118 00119 /* Reference ourselves */ 00120 ObjectHeader = OBJECT_TO_OBJECT_HEADER(Process); 00121 InterlockedIncrement(&ObjectHeader->PointerCount); 00122 00123 /* Return the pointer */ 00124 *Object = Process; 00125 ASSERT(*Object != NULL); 00126 return STATUS_SUCCESS; 00127 } 00128 00129 /* Check if the caller wants the current thread */ 00130 if (Handle == NtCurrentThread()) 00131 { 00132 /* Return handle information */ 00133 HandleInformation->HandleAttributes = 0; 00134 HandleInformation->GrantedAccess = Thread->GrantedAccess; 00135 00136 /* Reference ourselves */ 00137 ObjectHeader = OBJECT_TO_OBJECT_HEADER(Thread); 00138 InterlockedExchangeAdd(&ObjectHeader->PointerCount, 1); 00139 00140 /* No audit mask */ 00141 *AuditMask = 0; 00142 00143 /* Return the pointer */ 00144 *Object = Thread; 00145 ASSERT(*Object != NULL); 00146 return STATUS_SUCCESS; 00147 } 00148 00149 /* This is a kernel handle... do we have access? */ 00150 if (AccessMode == KernelMode) 00151 { 00152 /* Use the kernel handle table and get the actual handle value */ 00153 Handle = ObKernelHandleToHandle(Handle); 00154 HandleTable = ObpKernelHandleTable; 00155 } 00156 else 00157 { 00158 /* This is an illegal attempt to access a kernel handle */ 00159 return STATUS_INVALID_HANDLE; 00160 } 00161 } 00162 00163 /* Enter a critical region while we touch the handle table */ 00164 ASSERT(HandleTable != NULL); 00165 KeEnterCriticalRegion(); 00166 00167 /* Get the handle entry */ 00168 HandleEntry = ExMapHandleToPointer(HandleTable, Handle); 00169 if (HandleEntry) 00170 { 00171 /* Get the object header and validate the type*/ 00172 ObjectHeader = ObpGetHandleObject(HandleEntry); 00173 00174 /* Get the granted access and validate it */ 00175 GrantedAccess = HandleEntry->GrantedAccess; 00176 00177 /* Mask out the internal attributes */ 00178 Attributes = HandleEntry->ObAttributes & OBJ_HANDLE_ATTRIBUTES; 00179 00180 /* Fill out the information */ 00181 HandleInformation->HandleAttributes = Attributes; 00182 HandleInformation->GrantedAccess = GrantedAccess; 00183 00184 /* No audit mask (FIXME!) */ 00185 *AuditMask = 0; 00186 00187 /* Return the pointer */ 00188 *Object = &ObjectHeader->Body; 00189 00190 /* Add a reference */ 00191 InterlockedExchangeAdd(&ObjectHeader->PointerCount, 1); 00192 00193 /* Unlock the handle */ 00194 ExUnlockHandleTableEntry(HandleTable, HandleEntry); 00195 KeLeaveCriticalRegion(); 00196 00197 /* Return success */ 00198 ASSERT(*Object != NULL); 00199 return STATUS_SUCCESS; 00200 } 00201 else 00202 { 00203 /* Invalid handle */ 00204 Status = STATUS_INVALID_HANDLE; 00205 } 00206 00207 /* Return failure status */ 00208 KeLeaveCriticalRegion(); 00209 return Status; 00210 } 00211 00212 BOOLEAN 00213 NTAPI 00214 ObpEnumFindHandleProcedure(IN PHANDLE_TABLE_ENTRY HandleEntry, 00215 IN HANDLE Handle, 00216 IN PVOID Context) 00217 { 00218 POBJECT_HEADER ObjectHeader; 00219 ACCESS_MASK GrantedAccess; 00220 ULONG HandleAttributes; 00221 POBP_FIND_HANDLE_DATA FindData = Context; 00222 00223 /* Get the object header */ 00224 ObjectHeader = ObpGetHandleObject(HandleEntry); 00225 00226 /* Make sure it's valid and matching */ 00227 if ((FindData->ObjectHeader) && (FindData->ObjectHeader != ObjectHeader)) 00228 { 00229 /* No match, fail */ 00230 return FALSE; 00231 } 00232 00233 /* Now attempt to match the object type */ 00234 if ((FindData->ObjectType) && (FindData->ObjectType != ObjectHeader->Type)) 00235 { 00236 /* No match, fail */ 00237 return FALSE; 00238 } 00239 00240 /* Check if we have extra information */ 00241 if (FindData->HandleInformation) 00242 { 00243 /* Get the granted access and attributes */ 00244 GrantedAccess = HandleEntry->GrantedAccess; 00245 HandleAttributes = HandleEntry->ObAttributes & OBJ_HANDLE_ATTRIBUTES; 00246 00247 /* Attempt to match them */ 00248 if ((FindData->HandleInformation->HandleAttributes != HandleAttributes) || 00249 (FindData->HandleInformation->GrantedAccess != GrantedAccess)) 00250 { 00251 /* No match, fail */ 00252 return FALSE; 00253 } 00254 } 00255 00256 /* We have a match */ 00257 return TRUE; 00258 } 00259 00260 POBJECT_HANDLE_COUNT_ENTRY 00261 NTAPI 00262 ObpInsertHandleCount(IN POBJECT_HEADER ObjectHeader) 00263 { 00264 POBJECT_HEADER_HANDLE_INFO HandleInfo; 00265 POBJECT_HANDLE_COUNT_ENTRY FreeEntry; 00266 POBJECT_HANDLE_COUNT_DATABASE HandleDatabase, OldHandleDatabase; 00267 ULONG i; 00268 ULONG Size, OldSize; 00269 OBJECT_HANDLE_COUNT_DATABASE SingleDatabase; 00270 PAGED_CODE(); 00271 00272 /* Get the handle info */ 00273 HandleInfo = OBJECT_HEADER_TO_HANDLE_INFO(ObjectHeader); 00274 if (!HandleInfo) return NULL; 00275 00276 /* Check if we only have one entry */ 00277 if (ObjectHeader->Flags & OB_FLAG_SINGLE_PROCESS) 00278 { 00279 /* Fill out the single entry */ 00280 SingleDatabase.CountEntries = 1; 00281 SingleDatabase.HandleCountEntries[0] = HandleInfo->SingleEntry; 00282 00283 /* Use this as the old size */ 00284 OldHandleDatabase = &SingleDatabase; 00285 OldSize = sizeof(SingleDatabase); 00286 00287 /* Now we'll have two entries, and an entire DB */ 00288 i = 2; 00289 Size = sizeof(OBJECT_HANDLE_COUNT_DATABASE) + 00290 ((i - 1) * sizeof(OBJECT_HANDLE_COUNT_ENTRY)); 00291 } 00292 else 00293 { 00294 /* We already have a DB, get the information from it */ 00295 OldHandleDatabase = HandleInfo->HandleCountDatabase; 00296 i = OldHandleDatabase->CountEntries; 00297 OldSize = sizeof(OBJECT_HANDLE_COUNT_DATABASE) + 00298 ((i - 1) * sizeof(OBJECT_HANDLE_COUNT_ENTRY)); 00299 00300 /* Add 4 more entries */ 00301 i += 4; 00302 Size = OldSize + (4 * sizeof(OBJECT_HANDLE_COUNT_ENTRY)); 00303 } 00304 00305 /* Allocate the DB */ 00306 HandleDatabase = ExAllocatePoolWithTag(PagedPool, Size, TAG_OB_HANDLE); 00307 if (!HandleDatabase) return NULL; 00308 00309 /* Copy the old database */ 00310 RtlCopyMemory(HandleDatabase, OldHandleDatabase, OldSize); 00311 00312 /* Check if we he had a single entry before */ 00313 if (ObjectHeader->Flags & OB_FLAG_SINGLE_PROCESS) 00314 { 00315 /* Now we have more */ 00316 ObjectHeader->Flags &= ~OB_FLAG_SINGLE_PROCESS; 00317 } 00318 else 00319 { 00320 /* Otherwise we had a DB, free it */ 00321 ExFreePoolWithTag(OldHandleDatabase, TAG_OB_HANDLE); 00322 } 00323 00324 /* Find the end of the copy and zero out the new data */ 00325 FreeEntry = (PVOID)((ULONG_PTR)HandleDatabase + OldSize); 00326 RtlZeroMemory(FreeEntry, Size - OldSize); 00327 00328 /* Set the new information and return the free entry */ 00329 HandleDatabase->CountEntries = i; 00330 HandleInfo->HandleCountDatabase = HandleDatabase; 00331 return FreeEntry; 00332 } 00333 00334 NTSTATUS 00335 NTAPI 00336 ObpIncrementHandleDataBase(IN POBJECT_HEADER ObjectHeader, 00337 IN PEPROCESS Process, 00338 IN OUT PULONG NewProcessHandleCount) 00339 { 00340 POBJECT_HEADER_HANDLE_INFO HandleInfo; 00341 POBJECT_HANDLE_COUNT_ENTRY HandleEntry, FreeEntry = NULL; 00342 POBJECT_HANDLE_COUNT_DATABASE HandleDatabase; 00343 ULONG i; 00344 PAGED_CODE(); 00345 00346 /* Get the handle info and check if we only have one entry */ 00347 HandleInfo = OBJECT_HEADER_TO_HANDLE_INFO(ObjectHeader); 00348 if (ObjectHeader->Flags & OB_FLAG_SINGLE_PROCESS) 00349 { 00350 /* Check if the entry is free */ 00351 if (!HandleInfo->SingleEntry.HandleCount) 00352 { 00353 /* Add ours */ 00354 HandleInfo->SingleEntry.HandleCount = 1; 00355 HandleInfo->SingleEntry.Process = Process; 00356 00357 /* Return success and 1 handle */ 00358 *NewProcessHandleCount = 1; 00359 return STATUS_SUCCESS; 00360 } 00361 else if (HandleInfo->SingleEntry.Process == Process) 00362 { 00363 /* Busy entry, but same process */ 00364 *NewProcessHandleCount = ++HandleInfo->SingleEntry.HandleCount; 00365 return STATUS_SUCCESS; 00366 } 00367 else 00368 { 00369 /* Insert a new entry */ 00370 FreeEntry = ObpInsertHandleCount(ObjectHeader); 00371 if (!FreeEntry) return STATUS_INSUFFICIENT_RESOURCES; 00372 ASSERT(!FreeEntry->Process); 00373 ASSERT(!FreeEntry->HandleCount); 00374 00375 /* Fill it out */ 00376 FreeEntry->Process = Process; 00377 FreeEntry->HandleCount = 1; 00378 00379 /* Return success and 1 handle */ 00380 *NewProcessHandleCount = 1; 00381 return STATUS_SUCCESS; 00382 } 00383 } 00384 00385 /* We have a database instead */ 00386 HandleDatabase = HandleInfo->HandleCountDatabase; 00387 if (HandleDatabase) 00388 { 00389 /* Get the entries and loop them */ 00390 i = HandleDatabase->CountEntries; 00391 HandleEntry = &HandleDatabase->HandleCountEntries[0]; 00392 while (i) 00393 { 00394 /* Check if this is a match */ 00395 if (HandleEntry->Process == Process) 00396 { 00397 /* Found it, get the process handle count */ 00398 *NewProcessHandleCount = ++HandleEntry->HandleCount; 00399 return STATUS_SUCCESS; 00400 } 00401 else if (!HandleEntry->HandleCount) 00402 { 00403 /* Found a free entry */ 00404 FreeEntry = HandleEntry; 00405 } 00406 00407 /* Keep looping */ 00408 HandleEntry++; 00409 i--; 00410 } 00411 00412 /* Check if we couldn't find a free entry */ 00413 if (!FreeEntry) 00414 { 00415 /* Allocate one */ 00416 FreeEntry = ObpInsertHandleCount(ObjectHeader); 00417 if (!FreeEntry) return STATUS_INSUFFICIENT_RESOURCES; 00418 ASSERT(!FreeEntry->Process); 00419 ASSERT(!FreeEntry->HandleCount); 00420 } 00421 00422 /* Fill out the entry */ 00423 FreeEntry->Process = Process; 00424 FreeEntry->HandleCount = 1; 00425 *NewProcessHandleCount = 1; 00426 } 00427 00428 /* Return success if we got here */ 00429 return STATUS_SUCCESS; 00430 } 00431 00432 NTSTATUS 00433 NTAPI 00434 ObpChargeQuotaForObject(IN POBJECT_HEADER ObjectHeader, 00435 IN POBJECT_TYPE ObjectType, 00436 OUT PBOOLEAN NewObject) 00437 { 00438 POBJECT_HEADER_QUOTA_INFO ObjectQuota; 00439 ULONG PagedPoolCharge, NonPagedPoolCharge; 00440 00441 /* Get quota information */ 00442 ObjectQuota = OBJECT_HEADER_TO_QUOTA_INFO(ObjectHeader); 00443 *NewObject = FALSE; 00444 00445 /* Check if this is a new object */ 00446 if (ObjectHeader->Flags & OB_FLAG_CREATE_INFO) 00447 { 00448 /* Remove the flag */ 00449 ObjectHeader->Flags &= ~ OB_FLAG_CREATE_INFO; 00450 if (ObjectQuota) 00451 { 00452 /* We have a quota, get the charges */ 00453 PagedPoolCharge = ObjectQuota->PagedPoolCharge; 00454 NonPagedPoolCharge = ObjectQuota->NonPagedPoolCharge; 00455 } 00456 else 00457 { 00458 /* Get it from the object type */ 00459 PagedPoolCharge = ObjectType->TypeInfo.DefaultPagedPoolCharge; 00460 NonPagedPoolCharge = ObjectType->TypeInfo.DefaultNonPagedPoolCharge; 00461 } 00462 00463 /* Charge the quota */ 00464 ObjectHeader->QuotaBlockCharged = (PVOID)1; 00465 DPRINT("FIXME: Should charge: %lx %lx\n", PagedPoolCharge, NonPagedPoolCharge); 00466 #if 0 00467 PsChargeSharedPoolQuota(PsGetCurrentProcess(), 00468 PagedPoolCharge, 00469 NonPagedPoolCharge); 00470 #endif 00471 00472 /* Check if we don't have a quota block */ 00473 if (!ObjectHeader->QuotaBlockCharged) return STATUS_QUOTA_EXCEEDED; 00474 00475 /* Now set the flag */ 00476 *NewObject = TRUE; 00477 } 00478 00479 /* Return success */ 00480 return STATUS_SUCCESS; 00481 } 00482 00483 NTSTATUS 00484 NTAPI 00485 ObpValidateAccessMask(IN PACCESS_STATE AccessState) 00486 { 00487 /* TODO */ 00488 return STATUS_SUCCESS; 00489 } 00490 00491 /*++ 00492 * @name ObpDecrementHandleCount 00493 * 00494 * The ObpDecrementHandleCount routine <FILLMEIN> 00495 * 00496 * @param ObjectBody 00497 * <FILLMEIN>. 00498 * 00499 * @param Process 00500 * <FILLMEIN>. 00501 * 00502 * @param GrantedAccess 00503 * <FILLMEIN>. 00504 * 00505 * @return None. 00506 * 00507 * @remarks None. 00508 * 00509 *--*/ 00510 VOID 00511 NTAPI 00512 ObpDecrementHandleCount(IN PVOID ObjectBody, 00513 IN PEPROCESS Process, 00514 IN ACCESS_MASK GrantedAccess, 00515 IN POBJECT_TYPE ObjectType) 00516 { 00517 POBJECT_HEADER ObjectHeader; 00518 LONG SystemHandleCount, ProcessHandleCount; 00519 LONG NewCount; 00520 KIRQL CalloutIrql; 00521 POBJECT_HEADER_HANDLE_INFO HandleInfo; 00522 POBJECT_HANDLE_COUNT_ENTRY HandleEntry; 00523 POBJECT_HANDLE_COUNT_DATABASE HandleDatabase; 00524 ULONG i; 00525 PAGED_CODE(); 00526 00527 /* Get the object type and header */ 00528 ObjectHeader = OBJECT_TO_OBJECT_HEADER(ObjectBody); 00529 OBTRACE(OB_HANDLE_DEBUG, 00530 "%s - Decrementing count for: %p. HC PC %lx %lx\n", 00531 __FUNCTION__, 00532 ObjectBody, 00533 ObjectHeader->HandleCount, 00534 ObjectHeader->PointerCount); 00535 00536 /* Lock the object */ 00537 ObpAcquireObjectLock(ObjectHeader); 00538 00539 /* Set default counts */ 00540 SystemHandleCount = ObjectHeader->HandleCount; 00541 ProcessHandleCount = 0; 00542 00543 /* Decrement the handle count */ 00544 NewCount = InterlockedDecrement(&ObjectHeader->HandleCount); 00545 00546 /* Check if we're out of handles and this was an exclusive object */ 00547 if (!(NewCount) && (ObjectHeader->Flags & OB_FLAG_EXCLUSIVE)) 00548 { 00549 /* Clear the exclusive flag */ 00550 OBJECT_HEADER_TO_QUOTA_INFO(ObjectHeader)->ExclusiveProcess = NULL; 00551 } 00552 00553 /* Is the object type keeping track of handles? */ 00554 if (ObjectType->TypeInfo.MaintainHandleCount) 00555 { 00556 /* Get handle information */ 00557 HandleInfo = OBJECT_HEADER_TO_HANDLE_INFO(ObjectHeader); 00558 00559 /* Check if there's only a single entry */ 00560 if (ObjectHeader->Flags & OB_FLAG_SINGLE_PROCESS) 00561 { 00562 /* It should be us */ 00563 ASSERT(HandleInfo->SingleEntry.Process == Process); 00564 ASSERT(HandleInfo->SingleEntry.HandleCount > 0); 00565 00566 /* Get the handle counts */ 00567 ProcessHandleCount = HandleInfo->SingleEntry.HandleCount--; 00568 HandleEntry = &HandleInfo->SingleEntry; 00569 } 00570 else 00571 { 00572 /* Otherwise, get the database */ 00573 HandleDatabase = HandleInfo->HandleCountDatabase; 00574 if (HandleDatabase) 00575 { 00576 /* Get the entries and loop them */ 00577 i = HandleDatabase->CountEntries; 00578 HandleEntry = &HandleDatabase->HandleCountEntries[0]; 00579 while (i) 00580 { 00581 /* Check if this is a match */ 00582 if ((HandleEntry->HandleCount) && 00583 (HandleEntry->Process == Process)) 00584 { 00585 /* Found it, get the process handle count */ 00586 ProcessHandleCount = HandleEntry->HandleCount--; 00587 break; 00588 } 00589 00590 /* Keep looping */ 00591 HandleEntry++; 00592 i--; 00593 } 00594 } 00595 else 00596 { 00597 /* No database, so no entry */ 00598 HandleEntry = NULL; 00599 } 00600 } 00601 00602 /* Check if this is the last handle */ 00603 if (ProcessHandleCount == 1) 00604 { 00605 /* Then clear the entry */ 00606 HandleEntry->Process = NULL; 00607 HandleEntry->HandleCount = 0; 00608 } 00609 } 00610 00611 /* Release the lock */ 00612 ObpReleaseObjectLock(ObjectHeader); 00613 00614 /* Check if we have a close procedure */ 00615 if (ObjectType->TypeInfo.CloseProcedure) 00616 { 00617 /* Call it */ 00618 ObpCalloutStart(&CalloutIrql); 00619 ObjectType->TypeInfo.CloseProcedure(Process, 00620 ObjectBody, 00621 GrantedAccess, 00622 ProcessHandleCount, 00623 SystemHandleCount); 00624 ObpCalloutEnd(CalloutIrql, "Close", ObjectType, ObjectBody); 00625 } 00626 00627 /* Check if we should delete the object */ 00628 ObpDeleteNameCheck(ObjectBody); 00629 00630 /* Decrease the total number of handles for this type */ 00631 InterlockedDecrement((PLONG)&ObjectType->TotalNumberOfHandles); 00632 OBTRACE(OB_HANDLE_DEBUG, 00633 "%s - Decremented count for: %p. HC PC %lx %lx\n", 00634 __FUNCTION__, 00635 ObjectBody, 00636 ObjectHeader->HandleCount, 00637 ObjectHeader->PointerCount); 00638 } 00639 00640 /*++ 00641 * @name ObpCloseHandleTableEntry 00642 * 00643 * The ObpCloseHandleTableEntry routine <FILLMEIN> 00644 * 00645 * @param HandleTable 00646 * <FILLMEIN>. 00647 * 00648 * @param HandleEntry 00649 * <FILLMEIN>. 00650 * 00651 * @param Handle 00652 * <FILLMEIN>. 00653 * 00654 * @param AccessMode 00655 * <FILLMEIN>. 00656 * 00657 * @param IgnoreHandleProtection 00658 * <FILLMEIN>. 00659 * 00660 * @return <FILLMEIN>. 00661 * 00662 * @remarks None. 00663 * 00664 *--*/ 00665 NTSTATUS 00666 NTAPI 00667 ObpCloseHandleTableEntry(IN PHANDLE_TABLE HandleTable, 00668 IN PHANDLE_TABLE_ENTRY HandleEntry, 00669 IN HANDLE Handle, 00670 IN KPROCESSOR_MODE AccessMode, 00671 IN BOOLEAN IgnoreHandleProtection) 00672 { 00673 PVOID Body; 00674 POBJECT_TYPE ObjectType; 00675 POBJECT_HEADER ObjectHeader; 00676 ACCESS_MASK GrantedAccess; 00677 KIRQL CalloutIrql; 00678 PAGED_CODE(); 00679 00680 /* Get the object data */ 00681 ObjectHeader = ObpGetHandleObject(HandleEntry); 00682 ObjectType = ObjectHeader->Type; 00683 Body = &ObjectHeader->Body; 00684 GrantedAccess = HandleEntry->GrantedAccess; 00685 OBTRACE(OB_HANDLE_DEBUG, 00686 "%s - Closing handle: %lx for %p. HC PC %lx %lx\n", 00687 __FUNCTION__, 00688 Handle, 00689 Body, 00690 ObjectHeader->HandleCount, 00691 ObjectHeader->PointerCount); 00692 00693 /* Check if the object has an Okay To Close procedure */ 00694 if (ObjectType->TypeInfo.OkayToCloseProcedure) 00695 { 00696 /* Call it and check if it's not letting us close it */ 00697 ObpCalloutStart(&CalloutIrql); 00698 if (!ObjectType->TypeInfo.OkayToCloseProcedure(PsGetCurrentProcess(), 00699 Body, 00700 Handle, 00701 AccessMode)) 00702 { 00703 /* Fail */ 00704 ObpCalloutEnd(CalloutIrql, "NtClose", ObjectType, Body); 00705 ExUnlockHandleTableEntry(HandleTable, HandleEntry); 00706 return STATUS_HANDLE_NOT_CLOSABLE; 00707 } 00708 00709 /* Success, validate callout retrn */ 00710 ObpCalloutEnd(CalloutIrql, "NtClose", ObjectType, Body); 00711 } 00712 00713 /* The callback allowed us to close it, but does the handle itself? */ 00714 if ((HandleEntry->ObAttributes & OBJ_PROTECT_CLOSE) && 00715 !(IgnoreHandleProtection)) 00716 { 00717 /* It doesn't, are we from user mode? */ 00718 if (AccessMode != KernelMode) 00719 { 00720 /* We are! Unlock the entry */ 00721 ExUnlockHandleTableEntry(HandleTable, HandleEntry); 00722 00723 /* Make sure we have a debug port */ 00724 if (PsGetCurrentProcess()->DebugPort) 00725 { 00726 /* Raise an exception */ 00727 return KeRaiseUserException(STATUS_HANDLE_NOT_CLOSABLE); 00728 } 00729 else 00730 { 00731 /* Return the error instead */ 00732 return STATUS_HANDLE_NOT_CLOSABLE; 00733 } 00734 } 00735 else 00736 { 00737 /* Otherwise, bugcheck the OS */ 00738 KeBugCheckEx(INVALID_KERNEL_HANDLE, (ULONG_PTR)Handle, 0, 0, 0); 00739 } 00740 } 00741 00742 /* Destroy and unlock the handle entry */ 00743 ExDestroyHandle(HandleTable, Handle, HandleEntry); 00744 00745 /* Now decrement the handle count */ 00746 ObpDecrementHandleCount(Body, 00747 PsGetCurrentProcess(), 00748 GrantedAccess, 00749 ObjectType); 00750 00751 /* Dereference the object as well */ 00752 ObDereferenceObject(Body); 00753 00754 /* Return to caller */ 00755 OBTRACE(OB_HANDLE_DEBUG, 00756 "%s - Closed handle: %lx for %p.\n", 00757 __FUNCTION__, 00758 Handle, 00759 Body); 00760 return STATUS_SUCCESS; 00761 } 00762 00763 /*++ 00764 * @name ObpIncrementHandleCount 00765 * 00766 * The ObpIncrementHandleCount routine <FILLMEIN> 00767 * 00768 * @param Object 00769 * <FILLMEIN>. 00770 * 00771 * @param AccessState 00772 * <FILLMEIN>. 00773 * 00774 * @param AccessMode 00775 * <FILLMEIN>. 00776 * 00777 * @param HandleAttributes 00778 * <FILLMEIN>. 00779 * 00780 * @param Process 00781 * <FILLMEIN>. 00782 * 00783 * @param OpenReason 00784 * <FILLMEIN>. 00785 * 00786 * @return <FILLMEIN>. 00787 * 00788 * @remarks None. 00789 * 00790 *--*/ 00791 NTSTATUS 00792 NTAPI 00793 ObpIncrementHandleCount(IN PVOID Object, 00794 IN PACCESS_STATE AccessState OPTIONAL, 00795 IN KPROCESSOR_MODE AccessMode, 00796 IN ULONG HandleAttributes, 00797 IN PEPROCESS Process, 00798 IN OB_OPEN_REASON OpenReason) 00799 { 00800 POBJECT_HEADER ObjectHeader; 00801 POBJECT_TYPE ObjectType; 00802 ULONG ProcessHandleCount; 00803 NTSTATUS Status; 00804 PEPROCESS ExclusiveProcess; 00805 BOOLEAN Exclusive = FALSE, NewObject; 00806 POBJECT_HEADER_CREATOR_INFO CreatorInfo; 00807 KIRQL CalloutIrql; 00808 KPROCESSOR_MODE ProbeMode; 00809 ULONG Total; 00810 PAGED_CODE(); 00811 00812 /* Get the object header and type */ 00813 ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object); 00814 ObjectType = ObjectHeader->Type; 00815 OBTRACE(OB_HANDLE_DEBUG, 00816 "%s - Incrementing count for: %p. Reason: %lx. HC PC %lx %lx\n", 00817 __FUNCTION__, 00818 Object, 00819 OpenReason, 00820 ObjectHeader->HandleCount, 00821 ObjectHeader->PointerCount); 00822 00823 /* Check if caller is forcing user mode */ 00824 if (HandleAttributes & OBJ_FORCE_ACCESS_CHECK) 00825 { 00826 /* Force it */ 00827 ProbeMode = UserMode; 00828 } 00829 else 00830 { 00831 /* Keep original setting */ 00832 ProbeMode = AccessMode; 00833 } 00834 00835 /* Lock the object */ 00836 ObpAcquireObjectLock(ObjectHeader); 00837 00838 /* Charge quota and remove the creator info flag */ 00839 Status = ObpChargeQuotaForObject(ObjectHeader, ObjectType, &NewObject); 00840 if (!NT_SUCCESS(Status)) return Status; 00841 00842 /* Check if the open is exclusive */ 00843 if (HandleAttributes & OBJ_EXCLUSIVE) 00844 { 00845 /* Check if the object allows this, or if the inherit flag was given */ 00846 if ((HandleAttributes & OBJ_INHERIT) || 00847 !(ObjectHeader->Flags & OB_FLAG_EXCLUSIVE)) 00848 { 00849 /* Incorrect attempt */ 00850 Status = STATUS_INVALID_PARAMETER; 00851 goto Quickie; 00852 } 00853 00854 /* Check if we have access to it */ 00855 ExclusiveProcess = OBJECT_HEADER_TO_EXCLUSIVE_PROCESS(ObjectHeader); 00856 if ((!(ExclusiveProcess) && (ObjectHeader->HandleCount)) || 00857 ((ExclusiveProcess) && (ExclusiveProcess != PsGetCurrentProcess()))) 00858 { 00859 /* This isn't the right process */ 00860 Status = STATUS_ACCESS_DENIED; 00861 goto Quickie; 00862 } 00863 00864 /* Now you got exclusive access */ 00865 Exclusive = TRUE; 00866 } 00867 else if ((ObjectHeader->Flags & OB_FLAG_EXCLUSIVE) && 00868 (OBJECT_HEADER_TO_EXCLUSIVE_PROCESS(ObjectHeader))) 00869 { 00870 /* Caller didn't want exclusive access, but the object is exclusive */ 00871 Status = STATUS_ACCESS_DENIED; 00872 goto Quickie; 00873 } 00874 00875 /* 00876 * Check if this is an object that went from 0 handles back to existence, 00877 * but doesn't have an open procedure, only a close procedure. This means 00878 * that it will never realize that the object is back alive, so we must 00879 * fail the request. 00880 */ 00881 if (!(ObjectHeader->HandleCount) && 00882 !(NewObject) && 00883 (ObjectType->TypeInfo.MaintainHandleCount) && 00884 !(ObjectType->TypeInfo.OpenProcedure) && 00885 (ObjectType->TypeInfo.CloseProcedure)) 00886 { 00887 /* Fail */ 00888 Status = STATUS_UNSUCCESSFUL; 00889 goto Quickie; 00890 } 00891 00892 /* Check if we're opening an existing handle */ 00893 if ((OpenReason == ObOpenHandle) || 00894 ((OpenReason == ObDuplicateHandle) && (AccessState))) 00895 { 00896 /* Validate the caller's access to this object */ 00897 if (!ObCheckObjectAccess(Object, 00898 AccessState, 00899 TRUE, 00900 ProbeMode, 00901 &Status)) 00902 { 00903 /* Access was denied, so fail */ 00904 goto Quickie; 00905 } 00906 } 00907 else if (OpenReason == ObCreateHandle) 00908 { 00909 /* Convert MAXIMUM_ALLOWED to GENERIC_ALL */ 00910 if (AccessState->RemainingDesiredAccess & MAXIMUM_ALLOWED) 00911 { 00912 /* Mask out MAXIMUM_ALLOWED and stick GENERIC_ALL instead */ 00913 AccessState->RemainingDesiredAccess &= ~MAXIMUM_ALLOWED; 00914 AccessState->RemainingDesiredAccess |= GENERIC_ALL; 00915 } 00916 00917 /* Check if we have to map the GENERIC mask */ 00918 if (AccessState->RemainingDesiredAccess & GENERIC_ACCESS) 00919 { 00920 /* Map it to the correct access masks */ 00921 RtlMapGenericMask(&AccessState->RemainingDesiredAccess, 00922 &ObjectType->TypeInfo.GenericMapping); 00923 } 00924 00925 /* Check if the caller is trying to access system security */ 00926 if (AccessState->RemainingDesiredAccess & ACCESS_SYSTEM_SECURITY) 00927 { 00928 /* FIXME: TODO */ 00929 DPRINT1("ACCESS_SYSTEM_SECURITY not validated!\n"); 00930 } 00931 } 00932 00933 /* Check if this is an exclusive handle */ 00934 if (Exclusive) 00935 { 00936 /* Save the owner process */ 00937 OBJECT_HEADER_TO_QUOTA_INFO(ObjectHeader)->ExclusiveProcess = Process; 00938 } 00939 00940 /* Increase the handle count */ 00941 InterlockedIncrement(&ObjectHeader->HandleCount); 00942 ProcessHandleCount = 0; 00943 00944 /* Check if we have a handle database */ 00945 if (ObjectType->TypeInfo.MaintainHandleCount) 00946 { 00947 /* Increment the handle database */ 00948 Status = ObpIncrementHandleDataBase(ObjectHeader, 00949 Process, 00950 &ProcessHandleCount); 00951 if (!NT_SUCCESS(Status)) 00952 { 00953 /* FIXME: This should never happen for now */ 00954 DPRINT1("Unhandled case\n"); 00955 ASSERT(FALSE); 00956 goto Quickie; 00957 } 00958 } 00959 00960 /* Release the lock */ 00961 ObpReleaseObjectLock(ObjectHeader); 00962 00963 /* Check if we have an open procedure */ 00964 Status = STATUS_SUCCESS; 00965 if (ObjectType->TypeInfo.OpenProcedure) 00966 { 00967 /* Call it */ 00968 ObpCalloutStart(&CalloutIrql); 00969 Status = ObjectType->TypeInfo.OpenProcedure(OpenReason, 00970 Process, 00971 Object, 00972 AccessState ? 00973 AccessState-> 00974 PreviouslyGrantedAccess : 00975 0, 00976 ProcessHandleCount); 00977 ObpCalloutEnd(CalloutIrql, "Open", ObjectType, Object); 00978 00979 /* Check if the open procedure failed */ 00980 if (!NT_SUCCESS(Status)) 00981 { 00982 /* FIXME: This should never happen for now */ 00983 DPRINT1("Unhandled case\n"); 00984 ASSERT(FALSE); 00985 return Status; 00986 } 00987 } 00988 00989 /* Check if this is a create operation */ 00990 if (OpenReason == ObCreateHandle) 00991 { 00992 /* Check if we have creator info */ 00993 CreatorInfo = OBJECT_HEADER_TO_CREATOR_INFO(ObjectHeader); 00994 if (CreatorInfo) 00995 { 00996 /* We do, acquire the lock */ 00997 ObpEnterObjectTypeMutex(ObjectType); 00998 00999 /* Insert us on the list */ 01000 InsertTailList(&ObjectType->TypeList, &CreatorInfo->TypeList); 01001 01002 /* Release the lock */ 01003 ObpLeaveObjectTypeMutex(ObjectType); 01004 } 01005 } 01006 01007 /* Increase total number of handles */ 01008 Total = InterlockedIncrement((PLONG)&ObjectType->TotalNumberOfHandles); 01009 if (Total > ObjectType->HighWaterNumberOfHandles) 01010 { 01011 /* Fixup count */ 01012 ObjectType->HighWaterNumberOfHandles = Total; 01013 } 01014 01015 /* Trace call and return */ 01016 OBTRACE(OB_HANDLE_DEBUG, 01017 "%s - Incremented count for: %p. Reason: %lx HC PC %lx %lx\n", 01018 __FUNCTION__, 01019 Object, 01020 OpenReason, 01021 ObjectHeader->HandleCount, 01022 ObjectHeader->PointerCount); 01023 return Status; 01024 01025 Quickie: 01026 /* Release lock and return */ 01027 ObpReleaseObjectLock(ObjectHeader); 01028 return Status; 01029 } 01030 01031 /*++ 01032 * @name ObpIncrementUnnamedHandleCount 01033 * 01034 * The ObpIncrementUnnamedHandleCount routine <FILLMEIN> 01035 * 01036 * @param Object 01037 * <FILLMEIN>. 01038 * 01039 * @param AccessState 01040 * <FILLMEIN>. 01041 * 01042 * @param AccessMode 01043 * <FILLMEIN>. 01044 * 01045 * @param HandleAttributes 01046 * <FILLMEIN>. 01047 * 01048 * @param Process 01049 * <FILLMEIN>. 01050 * 01051 * @param OpenReason 01052 * <FILLMEIN>. 01053 * 01054 * @return <FILLMEIN>. 01055 * 01056 * @remarks None. 01057 * 01058 *--*/ 01059 NTSTATUS 01060 NTAPI 01061 ObpIncrementUnnamedHandleCount(IN PVOID Object, 01062 IN PACCESS_MASK DesiredAccess, 01063 IN KPROCESSOR_MODE AccessMode, 01064 IN ULONG HandleAttributes, 01065 IN PEPROCESS Process) 01066 { 01067 POBJECT_HEADER ObjectHeader; 01068 POBJECT_TYPE ObjectType; 01069 ULONG ProcessHandleCount; 01070 NTSTATUS Status; 01071 PEPROCESS ExclusiveProcess; 01072 BOOLEAN Exclusive = FALSE, NewObject; 01073 POBJECT_HEADER_CREATOR_INFO CreatorInfo; 01074 KIRQL CalloutIrql; 01075 ULONG Total; 01076 01077 /* Get the object header and type */ 01078 ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object); 01079 ObjectType = ObjectHeader->Type; 01080 OBTRACE(OB_HANDLE_DEBUG, 01081 "%s - Incrementing count for: %p. UNNAMED. HC PC %lx %lx\n", 01082 __FUNCTION__, 01083 Object, 01084 ObjectHeader->HandleCount, 01085 ObjectHeader->PointerCount); 01086 01087 /* Lock the object */ 01088 ObpAcquireObjectLock(ObjectHeader); 01089 01090 /* Charge quota and remove the creator info flag */ 01091 Status = ObpChargeQuotaForObject(ObjectHeader, ObjectType, &NewObject); 01092 if (!NT_SUCCESS(Status)) return Status; 01093 01094 /* Check if the open is exclusive */ 01095 if (HandleAttributes & OBJ_EXCLUSIVE) 01096 { 01097 /* Check if the object allows this, or if the inherit flag was given */ 01098 if ((HandleAttributes & OBJ_INHERIT) || 01099 !(ObjectHeader->Flags & OB_FLAG_EXCLUSIVE)) 01100 { 01101 /* Incorrect attempt */ 01102 Status = STATUS_INVALID_PARAMETER; 01103 goto Quickie; 01104 } 01105 01106 /* Check if we have access to it */ 01107 ExclusiveProcess = OBJECT_HEADER_TO_EXCLUSIVE_PROCESS(ObjectHeader); 01108 if ((!(ExclusiveProcess) && (ObjectHeader->HandleCount)) || 01109 ((ExclusiveProcess) && (ExclusiveProcess != PsGetCurrentProcess()))) 01110 { 01111 /* This isn't the right process */ 01112 Status = STATUS_ACCESS_DENIED; 01113 goto Quickie; 01114 } 01115 01116 /* Now you got exclusive access */ 01117 Exclusive = TRUE; 01118 } 01119 else if ((ObjectHeader->Flags & OB_FLAG_EXCLUSIVE) && 01120 (OBJECT_HEADER_TO_EXCLUSIVE_PROCESS(ObjectHeader))) 01121 { 01122 /* Caller didn't want exclusive access, but the object is exclusive */ 01123 Status = STATUS_ACCESS_DENIED; 01124 goto Quickie; 01125 } 01126 01127 /* 01128 * Check if this is an object that went from 0 handles back to existence, 01129 * but doesn't have an open procedure, only a close procedure. This means 01130 * that it will never realize that the object is back alive, so we must 01131 * fail the request. 01132 */ 01133 if (!(ObjectHeader->HandleCount) && 01134 !(NewObject) && 01135 (ObjectType->TypeInfo.MaintainHandleCount) && 01136 !(ObjectType->TypeInfo.OpenProcedure) && 01137 (ObjectType->TypeInfo.CloseProcedure)) 01138 { 01139 /* Fail */ 01140 Status = STATUS_UNSUCCESSFUL; 01141 goto Quickie; 01142 } 01143 01144 /* Convert MAXIMUM_ALLOWED to GENERIC_ALL */ 01145 if (*DesiredAccess & MAXIMUM_ALLOWED) 01146 { 01147 /* Mask out MAXIMUM_ALLOWED and stick GENERIC_ALL instead */ 01148 *DesiredAccess &= ~MAXIMUM_ALLOWED; 01149 *DesiredAccess |= GENERIC_ALL; 01150 } 01151 01152 /* Check if we have to map the GENERIC mask */ 01153 if (*DesiredAccess & GENERIC_ACCESS) 01154 { 01155 /* Map it to the correct access masks */ 01156 RtlMapGenericMask(DesiredAccess, 01157 &ObjectType->TypeInfo.GenericMapping); 01158 } 01159 01160 /* Check if this is an exclusive handle */ 01161 if (Exclusive) 01162 { 01163 /* Save the owner process */ 01164 OBJECT_HEADER_TO_QUOTA_INFO(ObjectHeader)->ExclusiveProcess = Process; 01165 } 01166 01167 /* Increase the handle count */ 01168 InterlockedIncrement(&ObjectHeader->HandleCount); 01169 ProcessHandleCount = 0; 01170 01171 /* Check if we have a handle database */ 01172 if (ObjectType->TypeInfo.MaintainHandleCount) 01173 { 01174 /* Increment the handle database */ 01175 Status = ObpIncrementHandleDataBase(ObjectHeader, 01176 Process, 01177 &ProcessHandleCount); 01178 if (!NT_SUCCESS(Status)) 01179 { 01180 /* FIXME: This should never happen for now */ 01181 DPRINT1("Unhandled case\n"); 01182 ASSERT(FALSE); 01183 goto Quickie; 01184 } 01185 } 01186 01187 /* Release the lock */ 01188 ObpReleaseObjectLock(ObjectHeader); 01189 01190 /* Check if we have an open procedure */ 01191 Status = STATUS_SUCCESS; 01192 if (ObjectType->TypeInfo.OpenProcedure) 01193 { 01194 /* Call it */ 01195 ObpCalloutStart(&CalloutIrql); 01196 Status = ObjectType->TypeInfo.OpenProcedure(ObCreateHandle, 01197 Process, 01198 Object, 01199 *DesiredAccess, 01200 ProcessHandleCount); 01201 ObpCalloutEnd(CalloutIrql, "Open", ObjectType, Object); 01202 01203 /* Check if the open procedure failed */ 01204 if (!NT_SUCCESS(Status)) 01205 { 01206 /* FIXME: This should never happen for now */ 01207 DPRINT1("Unhandled case\n"); 01208 ASSERT(FALSE); 01209 return Status; 01210 } 01211 } 01212 01213 /* Check if we have creator info */ 01214 CreatorInfo = OBJECT_HEADER_TO_CREATOR_INFO(ObjectHeader); 01215 if (CreatorInfo) 01216 { 01217 /* We do, acquire the lock */ 01218 ObpEnterObjectTypeMutex(ObjectType); 01219 01220 /* Insert us on the list */ 01221 InsertTailList(&ObjectType->TypeList, &CreatorInfo->TypeList); 01222 01223 /* Release the lock */ 01224 ObpLeaveObjectTypeMutex(ObjectType); 01225 } 01226 01227 /* Increase total number of handles */ 01228 Total = InterlockedIncrement((PLONG)&ObjectType->TotalNumberOfHandles); 01229 if (Total > ObjectType->HighWaterNumberOfHandles) 01230 { 01231 /* Fixup count */ 01232 ObjectType->HighWaterNumberOfHandles = Total; 01233 } 01234 01235 /* Trace call and return */ 01236 OBTRACE(OB_HANDLE_DEBUG, 01237 "%s - Incremented count for: %p. UNNAMED HC PC %lx %lx\n", 01238 __FUNCTION__, 01239 Object, 01240 ObjectHeader->HandleCount, 01241 ObjectHeader->PointerCount); 01242 return Status; 01243 01244 Quickie: 01245 /* Release lock and return */ 01246 ObpReleaseObjectLock(ObjectHeader); 01247 return Status; 01248 } 01249 01250 /*++ 01251 * @name ObpCreateUnnamedHandle 01252 * 01253 * The ObpCreateUnnamedHandle routine <FILLMEIN> 01254 * 01255 * @param Object 01256 * <FILLMEIN>. 01257 * 01258 * @param DesiredAccess 01259 * <FILLMEIN>. 01260 * 01261 * @param AdditionalReferences 01262 * <FILLMEIN>. 01263 * 01264 * @param HandleAttributes 01265 * <FILLMEIN>. 01266 * 01267 * @param AccessMode 01268 * <FILLMEIN>. 01269 * 01270 * @param ReturnedObject 01271 * <FILLMEIN>. 01272 * 01273 * @param ReturnedHandle 01274 * <FILLMEIN>. 01275 * 01276 * @return <FILLMEIN>. 01277 * 01278 * @remarks None. 01279 * 01280 *--*/ 01281 NTSTATUS 01282 NTAPI 01283 ObpCreateUnnamedHandle(IN PVOID Object, 01284 IN ACCESS_MASK DesiredAccess, 01285 IN ULONG AdditionalReferences, 01286 IN ULONG HandleAttributes, 01287 IN KPROCESSOR_MODE AccessMode, 01288 OUT PVOID *ReturnedObject, 01289 OUT PHANDLE ReturnedHandle) 01290 { 01291 HANDLE_TABLE_ENTRY NewEntry; 01292 POBJECT_HEADER ObjectHeader; 01293 HANDLE Handle; 01294 KAPC_STATE ApcState; 01295 BOOLEAN AttachedToProcess = FALSE, KernelHandle = FALSE; 01296 PVOID HandleTable; 01297 NTSTATUS Status; 01298 ACCESS_MASK GrantedAccess; 01299 POBJECT_TYPE ObjectType; 01300 PAGED_CODE(); 01301 01302 /* Get the object header and type */ 01303 ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object); 01304 ObjectType = ObjectHeader->Type; 01305 OBTRACE(OB_HANDLE_DEBUG, 01306 "%s - Creating handle for: %p. UNNAMED. HC PC %lx %lx\n", 01307 __FUNCTION__, 01308 Object, 01309 ObjectHeader->HandleCount, 01310 ObjectHeader->PointerCount); 01311 01312 /* Save the object header */ 01313 NewEntry.Object = ObjectHeader; 01314 01315 /* Mask out the internal attributes */ 01316 NewEntry.ObAttributes |= HandleAttributes & OBJ_HANDLE_ATTRIBUTES; 01317 01318 /* Check if this is a kernel handle */ 01319 if (HandleAttributes & OBJ_KERNEL_HANDLE) 01320 { 01321 /* Set the handle table */ 01322 HandleTable = ObpKernelHandleTable; 01323 KernelHandle = TRUE; 01324 01325 /* Check if we're not in the system process */ 01326 if (PsGetCurrentProcess() != PsInitialSystemProcess) 01327 { 01328 /* Attach to the system process */ 01329 KeStackAttachProcess(&PsInitialSystemProcess->Pcb, &ApcState); 01330 AttachedToProcess = TRUE; 01331 } 01332 } 01333 else 01334 { 01335 /* Get the current handle table */ 01336 HandleTable = PsGetCurrentProcess()->ObjectTable; 01337 } 01338 01339 /* Increment the handle count */ 01340 Status = ObpIncrementUnnamedHandleCount(Object, 01341 &DesiredAccess, 01342 AccessMode, 01343 HandleAttributes, 01344 PsGetCurrentProcess()); 01345 if (!NT_SUCCESS(Status)) 01346 { 01347 /* 01348 * We failed (meaning security failure, according to NT Internals) 01349 * detach and return 01350 */ 01351 if (AttachedToProcess) KeUnstackDetachProcess(&ApcState); 01352 return Status; 01353 } 01354 01355 /* Remove what's not in the valid access mask */ 01356 GrantedAccess = DesiredAccess & (ObjectType->TypeInfo.ValidAccessMask | 01357 ACCESS_SYSTEM_SECURITY); 01358 01359 /* Handle extra references */ 01360 if (AdditionalReferences) 01361 { 01362 /* Add them to the header */ 01363 InterlockedExchangeAdd(&ObjectHeader->PointerCount, 01364 AdditionalReferences); 01365 } 01366 01367 /* Save the access mask */ 01368 NewEntry.GrantedAccess = GrantedAccess; 01369 01370 /* 01371 * Create the actual handle. We'll need to do this *after* calling 01372 * ObpIncrementHandleCount to make sure that Object Security is valid 01373 * (specified in Gl00my documentation on Ob) 01374 */ 01375 OBTRACE(OB_HANDLE_DEBUG, 01376 "%s - Handle Properties: [%p-%lx-%lx]\n", 01377 __FUNCTION__, 01378 NewEntry.Object, NewEntry.ObAttributes & 3, NewEntry.GrantedAccess); 01379 Handle = ExCreateHandle(HandleTable, &NewEntry); 01380 01381 /* Make sure we got a handle */ 01382 if (Handle) 01383 { 01384 /* Check if this was a kernel handle */ 01385 if (KernelHandle) Handle = ObMarkHandleAsKernelHandle(Handle); 01386 01387 /* Return handle and object */ 01388 *ReturnedHandle = Handle; 01389 01390 /* Return the new object only if caller wanted it biased */ 01391 if ((AdditionalReferences) && (ReturnedObject)) 01392 { 01393 /* Return it */ 01394 *ReturnedObject = Object; 01395 } 01396 01397 /* Detach if needed */ 01398 if (AttachedToProcess) KeUnstackDetachProcess(&ApcState); 01399 01400 /* Trace and return */ 01401 OBTRACE(OB_HANDLE_DEBUG, 01402 "%s - Returning Handle: %lx HC PC %lx %lx\n", 01403 __FUNCTION__, 01404 Handle, 01405 ObjectHeader->HandleCount, 01406 ObjectHeader->PointerCount); 01407 return STATUS_SUCCESS; 01408 } 01409 01410 /* Handle extra references */ 01411 if (AdditionalReferences) 01412 { 01413 /* Dereference it as many times as required */ 01414 InterlockedExchangeAdd(&ObjectHeader->PointerCount, 01415 -(LONG)AdditionalReferences); 01416 } 01417 01418 /* Decrement the handle count and detach */ 01419 ObpDecrementHandleCount(&ObjectHeader->Body, 01420 PsGetCurrentProcess(), 01421 GrantedAccess, 01422 ObjectType); 01423 01424 /* Detach and fail */ 01425 if (AttachedToProcess) KeUnstackDetachProcess(&ApcState); 01426 return STATUS_INSUFFICIENT_RESOURCES; 01427 } 01428 01429 /*++ 01430 * @name ObpCreateHandle 01431 * 01432 * The ObpCreateHandle routine <FILLMEIN> 01433 * 01434 * @param OpenReason 01435 * <FILLMEIN>. 01436 * 01437 * @param Object 01438 * <FILLMEIN>. 01439 * 01440 * @param Type 01441 * <FILLMEIN>. 01442 * 01443 * @param AccessState 01444 * <FILLMEIN>. 01445 * 01446 * @param AdditionalReferences 01447 * <FILLMEIN>. 01448 * 01449 * @param HandleAttributes 01450 * <FILLMEIN>. 01451 * 01452 * @param AccessMode 01453 * <FILLMEIN>. 01454 * 01455 * @param ReturnedObject 01456 * <FILLMEIN>. 01457 * 01458 * @param ReturnedHandle 01459 * <FILLMEIN>. 01460 * 01461 * @return <FILLMEIN>. 01462 * 01463 * @remarks Cleans up the Lookup Context on return. 01464 * 01465 *--*/ 01466 NTSTATUS 01467 NTAPI 01468 ObpCreateHandle(IN OB_OPEN_REASON OpenReason, 01469 IN PVOID Object, 01470 IN POBJECT_TYPE Type OPTIONAL, 01471 IN PACCESS_STATE AccessState, 01472 IN ULONG AdditionalReferences, 01473 IN ULONG HandleAttributes, 01474 IN POBP_LOOKUP_CONTEXT Context, 01475 IN KPROCESSOR_MODE AccessMode, 01476 OUT PVOID *ReturnedObject, 01477 OUT PHANDLE ReturnedHandle) 01478 { 01479 HANDLE_TABLE_ENTRY NewEntry; 01480 POBJECT_HEADER ObjectHeader; 01481 HANDLE Handle; 01482 KAPC_STATE ApcState; 01483 BOOLEAN AttachedToProcess = FALSE, KernelHandle = FALSE; 01484 POBJECT_TYPE ObjectType; 01485 PVOID HandleTable; 01486 NTSTATUS Status; 01487 ACCESS_MASK DesiredAccess, GrantedAccess; 01488 PAUX_ACCESS_DATA AuxData; 01489 PAGED_CODE(); 01490 01491 /* Get the object header and type */ 01492 ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object); 01493 ObjectType = ObjectHeader->Type; 01494 OBTRACE(OB_HANDLE_DEBUG, 01495 "%s - Creating handle for: %p. Reason: %lx. HC PC %lx %lx\n", 01496 __FUNCTION__, 01497 Object, 01498 OpenReason, 01499 ObjectHeader->HandleCount, 01500 ObjectHeader->PointerCount); 01501 01502 /* Check if the types match */ 01503 if ((Type) && (ObjectType != Type)) 01504 { 01505 /* They don't, cleanup */ 01506 if (Context) ObpReleaseLookupContext(Context); 01507 return STATUS_OBJECT_TYPE_MISMATCH; 01508 } 01509 01510 /* Save the object header */ 01511 NewEntry.Object = ObjectHeader; 01512 01513 /* Check if this is a kernel handle */ 01514 if (HandleAttributes & OBJ_KERNEL_HANDLE) 01515 { 01516 /* Set the handle table */ 01517 HandleTable = ObpKernelHandleTable; 01518 KernelHandle = TRUE; 01519 01520 /* Check if we're not in the system process */ 01521 if (PsGetCurrentProcess() != PsInitialSystemProcess) 01522 { 01523 /* Attach to the system process */ 01524 KeStackAttachProcess(&PsInitialSystemProcess->Pcb, &ApcState); 01525 AttachedToProcess = TRUE; 01526 } 01527 } 01528 else 01529 { 01530 /* Get the current handle table */ 01531 HandleTable = PsGetCurrentProcess()->ObjectTable; 01532 } 01533 01534 /* Increment the handle count */ 01535 Status = ObpIncrementHandleCount(Object, 01536 AccessState, 01537 AccessMode, 01538 HandleAttributes, 01539 PsGetCurrentProcess(), 01540 OpenReason); 01541 if (!NT_SUCCESS(Status)) 01542 { 01543 /* 01544 * We failed (meaning security failure, according to NT Internals) 01545 * detach and return 01546 */ 01547 if (Context) ObpReleaseLookupContext(Context); 01548 if (AttachedToProcess) KeUnstackDetachProcess(&ApcState); 01549 return Status; 01550 } 01551 01552 /* Check if we are doing audits on close */ 01553 if (AccessState->GenerateOnClose) 01554 { 01555 /* Force the attribute on */ 01556 HandleAttributes |= OBJ_AUDIT_OBJECT_CLOSE; 01557 } 01558 01559 /* Mask out the internal attributes */ 01560 NewEntry.ObAttributes |= (HandleAttributes & OBJ_HANDLE_ATTRIBUTES); 01561 01562 /* Get the original desired access */ 01563 DesiredAccess = AccessState->RemainingDesiredAccess | 01564 AccessState->PreviouslyGrantedAccess; 01565 01566 /* Remove what's not in the valid access mask */ 01567 GrantedAccess = DesiredAccess & (ObjectType->TypeInfo.ValidAccessMask | 01568 ACCESS_SYSTEM_SECURITY); 01569 01570 /* Update the value in the access state */ 01571 AccessState->PreviouslyGrantedAccess = GrantedAccess; 01572 01573 /* Get the auxiliary data */ 01574 AuxData = AccessState->AuxData; 01575 01576 /* Handle extra references */ 01577 if (AdditionalReferences) 01578 { 01579 /* Add them to the header */ 01580 InterlockedExchangeAdd(&ObjectHeader->PointerCount, AdditionalReferences); 01581 } 01582 01583 /* Now we can release the object */ 01584 if (Context) ObpReleaseLookupContext(Context); 01585 01586 /* Save the access mask */ 01587 NewEntry.GrantedAccess = GrantedAccess; 01588 01589 /* 01590 * Create the actual handle. We'll need to do this *after* calling 01591 * ObpIncrementHandleCount to make sure that Object Security is valid 01592 * (specified in Gl00my documentation on Ob) 01593 */ 01594 OBTRACE(OB_HANDLE_DEBUG, 01595 "%s - Handle Properties: [%p-%lx-%lx]\n", 01596 __FUNCTION__, 01597 NewEntry.Object, NewEntry.ObAttributes & 3, NewEntry.GrantedAccess); 01598 Handle = ExCreateHandle(HandleTable, &NewEntry); 01599 01600 /* Make sure we got a handle */ 01601 if (Handle) 01602 { 01603 /* Check if this was a kernel handle */ 01604 if (KernelHandle) Handle = ObMarkHandleAsKernelHandle(Handle); 01605 01606 /* Return it */ 01607 *ReturnedHandle = Handle; 01608 01609 /* Check if we need to generate on audit */ 01610 if (AccessState->GenerateAudit) 01611 { 01612 /* Audit the handle creation */ 01613 //SeAuditHandleCreation(AccessState, Handle); 01614 } 01615 01616 /* Check if this was a create */ 01617 if (OpenReason == ObCreateHandle) 01618 { 01619 /* Check if we need to audit the privileges */ 01620 if ((AuxData->PrivilegeSet) && 01621 (AuxData->PrivilegeSet->PrivilegeCount)) 01622 { 01623 /* Do the audit */ 01624 #if 0 01625 SePrivilegeObjectAuditAlarm(Handle, 01626 &AccessState-> 01627 SubjectSecurityContext, 01628 GrantedAccess, 01629 AuxData->PrivilegeSet, 01630 TRUE, 01631 ExGetPreviousMode()); 01632 #endif 01633 } 01634 } 01635 01636 /* Return the new object only if caller wanted it biased */ 01637 if ((AdditionalReferences) && (ReturnedObject)) 01638 { 01639 /* Return it */ 01640 *ReturnedObject = Object; 01641 } 01642 01643 /* Detach if needed */ 01644 if (AttachedToProcess) KeUnstackDetachProcess(&ApcState); 01645 01646 /* Trace and return */ 01647 OBTRACE(OB_HANDLE_DEBUG, 01648 "%s - Returning Handle: %lx HC PC %lx %lx\n", 01649 __FUNCTION__, 01650 Handle, 01651 ObjectHeader->HandleCount, 01652 ObjectHeader->PointerCount); 01653 return STATUS_SUCCESS; 01654 } 01655 01656 /* Decrement the handle count and detach */ 01657 ObpDecrementHandleCount(&ObjectHeader->Body, 01658 PsGetCurrentProcess(), 01659 GrantedAccess, 01660 ObjectType); 01661 01662 /* Handle extra references */ 01663 if (AdditionalReferences) 01664 { 01665 /* Check how many extra references were added */ 01666 if (AdditionalReferences > 1) 01667 { 01668 /* Dereference it many times */ 01669 InterlockedExchangeAdd(&ObjectHeader->PointerCount, 01670 -(LONG)(AdditionalReferences - 1)); 01671 } 01672 01673 /* Dereference the object one last time */ 01674 ObDereferenceObject(Object); 01675 } 01676 01677 /* Detach if necessary and fail */ 01678 if (AttachedToProcess) KeUnstackDetachProcess(&ApcState); 01679 return STATUS_INSUFFICIENT_RESOURCES; 01680 } 01681 01682 /*++ 01683 * @name ObpCloseHandle 01684 * 01685 * The ObpCloseHandle routine <FILLMEIN> 01686 * 01687 * @param Handle 01688 * <FILLMEIN>. 01689 * 01690 * @param AccessMode 01691 * <FILLMEIN>. 01692 * 01693 * @return <FILLMEIN>. 01694 * 01695 * @remarks None. 01696 * 01697 *--*/ 01698 NTSTATUS 01699 NTAPI 01700 ObpCloseHandle(IN HANDLE Handle, 01701 IN KPROCESSOR_MODE AccessMode) 01702 { 01703 PVOID HandleTable; 01704 BOOLEAN AttachedToProcess = FALSE; 01705 KAPC_STATE ApcState; 01706 PHANDLE_TABLE_ENTRY HandleTableEntry; 01707 NTSTATUS Status; 01708 PEPROCESS Process = PsGetCurrentProcess(); 01709 PAGED_CODE(); 01710 OBTRACE(OB_HANDLE_DEBUG, 01711 "%s - Closing handle: %lx\n", __FUNCTION__, Handle); 01712 01713 if (AccessMode == KernelMode && Handle == (HANDLE)-1) 01714 return STATUS_INVALID_HANDLE; 01715 01716 /* Check if we're dealing with a kernel handle */ 01717 if (ObIsKernelHandle(Handle, AccessMode)) 01718 { 01719 /* Use the kernel table and convert the handle */ 01720 HandleTable = ObpKernelHandleTable; 01721 Handle = ObKernelHandleToHandle(Handle); 01722 01723 /* Check if we're not in the system process */ 01724 if (Process != PsInitialSystemProcess) 01725 { 01726 /* Attach to the system process */ 01727 KeStackAttachProcess(&PsInitialSystemProcess->Pcb, &ApcState); 01728 AttachedToProcess = TRUE; 01729 } 01730 } 01731 else 01732 { 01733 /* Use the process's handle table */ 01734 HandleTable = Process->ObjectTable; 01735 } 01736 01737 /* Enter a critical region to protect handle access */ 01738 KeEnterCriticalRegion(); 01739 01740 /* Get the handle entry */ 01741 HandleTableEntry = ExMapHandleToPointer(HandleTable, Handle); 01742 if (HandleTableEntry) 01743 { 01744 /* Now close the entry */ 01745 Status = ObpCloseHandleTableEntry(HandleTable, 01746 HandleTableEntry, 01747 Handle, 01748 AccessMode, 01749 FALSE); 01750 01751 /* We can quit the critical region now */ 01752 KeLeaveCriticalRegion(); 01753 01754 /* Detach and return success */ 01755 if (AttachedToProcess) KeUnstackDetachProcess(&ApcState); 01756 } 01757 else 01758 { 01759 /* We failed, quit the critical region */ 01760 KeLeaveCriticalRegion(); 01761 01762 /* Detach */ 01763 if (AttachedToProcess) KeUnstackDetachProcess(&ApcState); 01764 01765 /* Check if we have a valid handle that's not the process or thread */ 01766 if ((Handle) && 01767 (Handle != NtCurrentProcess()) && 01768 (Handle != NtCurrentThread())) 01769 { 01770 /* Check if we came from user mode */ 01771 if (AccessMode != KernelMode) 01772 { 01773 /* Check if we have no debug port */ 01774 if (Process->DebugPort) 01775 { 01776 /* Make sure we're not attached */ 01777 if (!KeIsAttachedProcess()) 01778 { 01779 /* Raise an exception */ 01780 return KeRaiseUserException(STATUS_INVALID_HANDLE); 01781 } 01782 } 01783 } 01784 else 01785 { 01786 /* This is kernel mode. Check if we're exiting */ 01787 if (!(PsIsThreadTerminating(PsGetCurrentThread())) && 01788 (Process->Peb)) 01789 { 01790 /* Check if the debugger is enabled */ 01791 if (KdDebuggerEnabled) 01792 { 01793 /* Bugcheck */ 01794 KeBugCheckEx(INVALID_KERNEL_HANDLE, (ULONG_PTR)Handle, 1, 0, 0); 01795 } 01796 } 01797 } 01798 } 01799 01800 /* Set invalid status */ 01801 Status = STATUS_INVALID_HANDLE; 01802 } 01803 01804 /* Return status */ 01805 OBTRACE(OB_HANDLE_DEBUG, 01806 "%s - Closed handle: %lx S: %lx\n", 01807 __FUNCTION__, Handle, Status); 01808 return Status; 01809 } 01810 01811 /*++ 01812 * @name ObpSetHandleAttributes 01813 * 01814 * The ObpSetHandleAttributes routine <FILLMEIN> 01815 * 01816 * @param HandleTableEntry 01817 * <FILLMEIN>. 01818 * 01819 * @param Context 01820 * <FILLMEIN>. 01821 * 01822 * @return <FILLMEIN>. 01823 * 01824 * @remarks None. 01825 * 01826 *--*/ 01827 BOOLEAN 01828 NTAPI 01829 ObpSetHandleAttributes(IN OUT PHANDLE_TABLE_ENTRY HandleTableEntry, 01830 IN ULONG_PTR Context) 01831 { 01832 POBP_SET_HANDLE_ATTRIBUTES_CONTEXT SetHandleInfo = (PVOID)Context; 01833 POBJECT_HEADER ObjectHeader = ObpGetHandleObject(HandleTableEntry); 01834 01835 /* Check if making the handle inheritable */ 01836 if (SetHandleInfo->Information.Inherit) 01837 { 01838 /* Check if inheriting is not supported for this object */ 01839 if (ObjectHeader->Type->TypeInfo.InvalidAttributes & OBJ_INHERIT) 01840 { 01841 /* Fail without changing anything */ 01842 return FALSE; 01843 } 01844 01845 /* Set the flag */ 01846 HandleTableEntry->ObAttributes |= OBJ_INHERIT; 01847 } 01848 else 01849 { 01850 /* Otherwise this implies we're removing the flag */ 01851 HandleTableEntry->ObAttributes &= ~OBJ_INHERIT; 01852 } 01853 01854 /* Check if making the handle protected */ 01855 if (SetHandleInfo->Information.ProtectFromClose) 01856 { 01857 /* Set the flag */ 01858 HandleTableEntry->GrantedAccess |= ObpAccessProtectCloseBit; 01859 } 01860 else 01861 { 01862 /* Otherwise, remove it */ 01863 HandleTableEntry->GrantedAccess &= ~ObpAccessProtectCloseBit; 01864 } 01865 01866 /* Return success */ 01867 return TRUE; 01868 } 01869 01870 /*++ 01871 * @name ObpCloseHandleCallback 01872 * 01873 * The ObpCloseHandleCallback routine <FILLMEIN> 01874 * 01875 * @param HandleTable 01876 * <FILLMEIN>. 01877 * 01878 * @param Object 01879 * <FILLMEIN>. 01880 * 01881 * @param GrantedAccess 01882 * <FILLMEIN>. 01883 * 01884 * @param Context 01885 * <FILLMEIN>. 01886 * 01887 * @return <FILLMEIN>. 01888 * 01889 * @remarks None. 01890 * 01891 *--*/ 01892 BOOLEAN 01893 NTAPI 01894 ObpCloseHandleCallback(IN PHANDLE_TABLE_ENTRY HandleTableEntry, 01895 IN HANDLE Handle, 01896 IN PVOID Context) 01897 { 01898 POBP_CLOSE_HANDLE_CONTEXT CloseContext = (POBP_CLOSE_HANDLE_CONTEXT)Context; 01899 01900 /* Simply decrement the handle count */ 01901 ObpCloseHandleTableEntry(CloseContext->HandleTable, 01902 HandleTableEntry, 01903 Handle, 01904 CloseContext->AccessMode, 01905 TRUE); 01906 return TRUE; 01907 } 01908 01909 /*++ 01910 * @name ObpDuplicateHandleCallback 01911 * 01912 * The ObpDuplicateHandleCallback routine <FILLMEIN> 01913 * 01914 * @param HandleTable 01915 * <FILLMEIN>. 01916 * 01917 * @param HandleTableEntry 01918 * <FILLMEIN>. 01919 * 01920 * @param Context 01921 * <FILLMEIN>. 01922 * 01923 * @return <FILLMEIN>. 01924 * 01925 * @remarks None. 01926 * 01927 *--*/ 01928 BOOLEAN 01929 NTAPI 01930 ObpDuplicateHandleCallback(IN PEPROCESS Process, 01931 IN PHANDLE_TABLE HandleTable, 01932 IN PHANDLE_TABLE_ENTRY OldEntry, 01933 IN PHANDLE_TABLE_ENTRY HandleTableEntry) 01934 { 01935 POBJECT_HEADER ObjectHeader; 01936 BOOLEAN Ret = FALSE; 01937 ACCESS_STATE AccessState; 01938 NTSTATUS Status; 01939 PAGED_CODE(); 01940 01941 /* Make sure that the handle is inheritable */ 01942 Ret = (HandleTableEntry->ObAttributes & OBJ_INHERIT) != 0; 01943 if (Ret) 01944 { 01945 /* Get the object header */ 01946 ObjectHeader = ObpGetHandleObject(HandleTableEntry); 01947 01948 /* Increment the pointer count */ 01949 InterlockedIncrement(&ObjectHeader->PointerCount); 01950 01951 /* Release the handle lock */ 01952 ExUnlockHandleTableEntry(HandleTable, OldEntry); 01953 01954 /* Setup the access state */ 01955 AccessState.PreviouslyGrantedAccess = HandleTableEntry->GrantedAccess; 01956 01957 /* Call the shared routine for incrementing handles */ 01958 Status = ObpIncrementHandleCount(&ObjectHeader->Body, 01959 &AccessState, 01960 KernelMode, 01961 HandleTableEntry->ObAttributes & OBJ_HANDLE_ATTRIBUTES, 01962 Process, 01963 ObInheritHandle); 01964 if (!NT_SUCCESS(Status)) 01965 { 01966 /* Return failure */ 01967 ObDereferenceObject(&ObjectHeader->Body); 01968 Ret = FALSE; 01969 } 01970 } 01971 else 01972 { 01973 /* Release the handle lock */ 01974 ExUnlockHandleTableEntry(HandleTable, OldEntry); 01975 } 01976 01977 /* Return duplication result */ 01978 return Ret; 01979 } 01980 01981 VOID 01982 NTAPI 01983 ObClearProcessHandleTable(IN PEPROCESS Process) 01984 { 01985 /* FIXME */ 01986 } 01987 01988 /*++ 01989 * @name ObpCreateHandleTable 01990 * 01991 * The ObpCreateHandleTable routine <FILLMEIN> 01992 * 01993 * @param Parent 01994 * <FILLMEIN>. 01995 * 01996 * @param Process 01997 * <FILLMEIN>. 01998 * 01999 * @return <FILLMEIN>. 02000 * 02001 * @remarks None. 02002 * 02003 *--*/ 02004 NTSTATUS 02005 NTAPI 02006 ObInitProcess(IN PEPROCESS Parent OPTIONAL, 02007 IN PEPROCESS Process) 02008 { 02009 PHANDLE_TABLE ParentTable, ObjectTable; 02010 02011 /* Check for a parent */ 02012 if (Parent) 02013 { 02014 /* Reference the parent's table */ 02015 ParentTable = ObReferenceProcessHandleTable(Parent); 02016 if (!ParentTable) return STATUS_PROCESS_IS_TERMINATING; 02017 02018 /* Duplicate it */ 02019 ObjectTable = ExDupHandleTable(Process, 02020 ParentTable, 02021 ObpDuplicateHandleCallback, 02022 OBJ_INHERIT); 02023 } 02024 else 02025 { 02026 /* Otherwise just create a new table */ 02027 ParentTable = NULL; 02028 ObjectTable = ExCreateHandleTable(Process); 02029 } 02030 02031 /* Make sure we have a table */ 02032 if (ObjectTable) 02033 { 02034 /* Associate it */ 02035 Process->ObjectTable = ObjectTable; 02036 02037 /* Check for auditing */ 02038 if (SeDetailedAuditingWithToken(NULL)) 02039 { 02040 /* FIXME: TODO */ 02041 DPRINT1("Need auditing!\n"); 02042 } 02043 02044 /* Get rid of the old table now */ 02045 if (ParentTable) ObDereferenceProcessHandleTable(Parent); 02046 02047 /* We are done */ 02048 return STATUS_SUCCESS; 02049 } 02050 else 02051 { 02052 /* Fail */ 02053 Process->ObjectTable = NULL; 02054 if (ParentTable) ObDereferenceProcessHandleTable(Parent); 02055 return STATUS_INSUFFICIENT_RESOURCES; 02056 } 02057 } 02058 02059 /*++ 02060 * @name ObKillProcess 02061 * 02062 * The ObKillProcess routine <FILLMEIN> 02063 * 02064 * @param Process 02065 * <FILLMEIN>. 02066 * 02067 * @return None. 02068 * 02069 * @remarks None. 02070 * 02071 *--*/ 02072 VOID 02073 NTAPI 02074 ObKillProcess(IN PEPROCESS Process) 02075 { 02076 PHANDLE_TABLE HandleTable; 02077 OBP_CLOSE_HANDLE_CONTEXT Context; 02078 BOOLEAN HardErrors; 02079 PAGED_CODE(); 02080 02081 /* Wait for process rundown and then complete it */ 02082 ExWaitForRundownProtectionRelease(&Process->RundownProtect); 02083 ExRundownCompleted(&Process->RundownProtect); 02084 02085 /* Get the object table */ 02086 HandleTable = Process->ObjectTable; 02087 if (!HandleTable) return; 02088 02089 /* Disable hard errors while we close handles */ 02090 HardErrors = IoSetThreadHardErrorMode(FALSE); 02091 02092 /* Enter a critical region */ 02093 KeEnterCriticalRegion(); 02094 02095 /* Fill out the context */ 02096 Context.AccessMode = KernelMode; 02097 Context.HandleTable = HandleTable; 02098 02099 /* Sweep the handle table to close all handles */ 02100 ExSweepHandleTable(HandleTable, 02101 ObpCloseHandleCallback, 02102 &Context); 02103 ASSERT(HandleTable->HandleCount == 0); 02104 02105 /* Leave the critical region */ 02106 KeLeaveCriticalRegion(); 02107 02108 /* Re-enable hard errors */ 02109 IoSetThreadHardErrorMode(HardErrors); 02110 02111 /* Destroy the object table */ 02112 Process->ObjectTable = NULL; 02113 ExDestroyHandleTable(HandleTable, NULL); 02114 } 02115 02116 NTSTATUS 02117 NTAPI 02118 ObDuplicateObject(IN PEPROCESS SourceProcess, 02119 IN HANDLE SourceHandle, 02120 IN PEPROCESS TargetProcess OPTIONAL, 02121 IN PHANDLE TargetHandle OPTIONAL, 02122 IN ACCESS_MASK DesiredAccess, 02123 IN ULONG HandleAttributes, 02124 IN ULONG Options, 02125 IN KPROCESSOR_MODE PreviousMode) 02126 { 02127 HANDLE_TABLE_ENTRY NewHandleEntry; 02128 BOOLEAN AttachedToProcess = FALSE; 02129 PVOID SourceObject; 02130 POBJECT_HEADER ObjectHeader; 02131 POBJECT_TYPE ObjectType; 02132 HANDLE NewHandle; 02133 KAPC_STATE ApcState; 02134 NTSTATUS Status; 02135 ACCESS_MASK TargetAccess, SourceAccess; 02136 ACCESS_STATE AccessState; 02137 PACCESS_STATE PassedAccessState = NULL; 02138 AUX_ACCESS_DATA AuxData; 02139 PHANDLE_TABLE HandleTable; 02140 OBJECT_HANDLE_INFORMATION HandleInformation; 02141 ULONG AuditMask; 02142 PAGED_CODE(); 02143 OBTRACE(OB_HANDLE_DEBUG, 02144 "%s - Duplicating handle: %lx for %p into %p\n", 02145 __FUNCTION__, 02146 SourceHandle, 02147 SourceProcess, 02148 TargetProcess); 02149 02150 /* Assume failure */ 02151 if (TargetHandle) *TargetHandle = NULL; 02152 02153 /* Check if we're not duplicating the same access */ 02154 if (!(Options & DUPLICATE_SAME_ACCESS)) 02155 { 02156 /* Validate the desired access */ 02157 Status = STATUS_SUCCESS; //ObpValidateDesiredAccess(DesiredAccess); 02158 if (!NT_SUCCESS(Status)) return Status; 02159 } 02160 02161 /* Reference the object table */ 02162 HandleTable = ObReferenceProcessHandleTable(SourceProcess); 02163 if (!HandleTable) return STATUS_PROCESS_IS_TERMINATING; 02164 02165 /* Reference the process object */ 02166 Status = ObpReferenceProcessObjectByHandle(SourceHandle, 02167 SourceProcess, 02168 HandleTable, 02169 PreviousMode, 02170 &SourceObject, 02171 &HandleInformation, 02172 &AuditMask); 02173 if (!NT_SUCCESS(Status)) 02174 { 02175 /* Fail */ 02176 ObDereferenceProcessHandleTable(SourceProcess); 02177 return Status; 02178 } 02179 else 02180 { 02181 /* Check if we have to don't have to audit object close */ 02182 if (!(HandleInformation.HandleAttributes & OBJ_AUDIT_OBJECT_CLOSE)) 02183 { 02184 /* Then there is no audit mask */ 02185 AuditMask = 0; 02186 } 02187 } 02188 02189 /* Check if there's no target process */ 02190 if (!TargetProcess) 02191 { 02192 /* Check if the caller wanted actual duplication */ 02193 if (!(Options & DUPLICATE_CLOSE_SOURCE)) 02194 { 02195 /* Invalid request */ 02196 Status = STATUS_INVALID_PARAMETER; 02197 } 02198 else 02199 { 02200 /* Otherwise, do the attach */ 02201 KeStackAttachProcess(&SourceProcess->Pcb, &ApcState); 02202 02203 /* Close the handle and detach */ 02204 NtClose(SourceHandle); 02205 KeUnstackDetachProcess(&ApcState); 02206 } 02207 02208 /* Return */ 02209 ObDereferenceProcessHandleTable(SourceProcess); 02210 ObDereferenceObject(SourceObject); 02211 return Status; 02212 } 02213 02214 /* Get the target handle table */ 02215 HandleTable = ObReferenceProcessHandleTable(TargetProcess); 02216 if (!HandleTable) 02217 { 02218 /* Check if the caller wanted us to close the handle */ 02219 if (Options & DUPLICATE_CLOSE_SOURCE) 02220 { 02221 /* Do the attach */ 02222 KeStackAttachProcess(&SourceProcess->Pcb, &ApcState); 02223 02224 /* Close the handle and detach */ 02225 NtClose(SourceHandle); 02226 KeUnstackDetachProcess(&ApcState); 02227 } 02228 02229 /* Return */ 02230 ObDereferenceProcessHandleTable(SourceProcess); 02231 ObDereferenceObject(SourceObject); 02232 return STATUS_PROCESS_IS_TERMINATING; 02233 } 02234 02235 /* Get the source access */ 02236 SourceAccess = HandleInformation.GrantedAccess; 02237 02238 /* Check if we're not in the target process */ 02239 if (TargetProcess != PsGetCurrentProcess()) 02240 { 02241 /* Attach to it */ 02242 KeStackAttachProcess(&TargetProcess->Pcb, &ApcState); 02243 AttachedToProcess = TRUE; 02244 } 02245 02246 /* Check if we're duplicating the attributes */ 02247 if (Options & DUPLICATE_SAME_ATTRIBUTES) 02248 { 02249 /* Duplicate them */ 02250 HandleAttributes = HandleInformation.HandleAttributes; 02251 } 02252 else 02253 { 02254 /* Don't allow caller to bypass auditing */ 02255 HandleAttributes |= HandleInformation.HandleAttributes & 02256 OBJ_AUDIT_OBJECT_CLOSE; 02257 } 02258 02259 /* Check if we're duplicating the access */ 02260 if (Options & DUPLICATE_SAME_ACCESS) DesiredAccess = SourceAccess; 02261 02262 /* Get object data */ 02263 ObjectHeader = OBJECT_TO_OBJECT_HEADER(SourceObject); 02264 ObjectType = ObjectHeader->Type; 02265 02266 /* Fill out the entry */ 02267 RtlZeroMemory(&NewHandleEntry, sizeof(HANDLE_TABLE_ENTRY)); 02268 NewHandleEntry.Object = ObjectHeader; 02269 NewHandleEntry.ObAttributes |= (HandleAttributes & OBJ_HANDLE_ATTRIBUTES); 02270 02271 /* Check if we're using a generic mask */ 02272 if (DesiredAccess & GENERIC_ACCESS) 02273 { 02274 /* Map it */ 02275 RtlMapGenericMask(&DesiredAccess, 02276 &ObjectType->TypeInfo.GenericMapping); 02277 } 02278 02279 /* Set the target access, always propagate ACCESS_SYSTEM_SECURITY */ 02280 TargetAccess = DesiredAccess & (ObjectType->TypeInfo.ValidAccessMask | 02281 ACCESS_SYSTEM_SECURITY); 02282 NewHandleEntry.GrantedAccess = TargetAccess; 02283 02284 /* Check if we're asking for new access */ 02285 if (TargetAccess & ~SourceAccess) 02286 { 02287 /* We are. We need the security procedure to validate this */ 02288 if (ObjectType->TypeInfo.SecurityProcedure == SeDefaultObjectMethod) 02289 { 02290 /* Use our built-in access state */ 02291 PassedAccessState = &AccessState; 02292 Status = SeCreateAccessState(&AccessState, 02293 &AuxData, 02294 TargetAccess, 02295 &ObjectType->TypeInfo.GenericMapping); 02296 } 02297 else 02298 { 02299 /* Otherwise we can't allow this privilege elevation */ 02300 Status = STATUS_ACCESS_DENIED; 02301 } 02302 } 02303 else 02304 { 02305 /* We don't need an access state */ 02306 Status = STATUS_SUCCESS; 02307 } 02308 02309 /* Make sure the access state was created OK */ 02310 if (NT_SUCCESS(Status)) 02311 { 02312 /* Add a new handle */ 02313 Status = ObpIncrementHandleCount(SourceObject, 02314 PassedAccessState, 02315 PreviousMode, 02316 HandleAttributes, 02317 PsGetCurrentProcess(), 02318 ObDuplicateHandle); 02319 } 02320 02321 /* Check if we were attached */ 02322 if (AttachedToProcess) 02323 { 02324 /* We can safely detach now */ 02325 KeUnstackDetachProcess(&ApcState); 02326 AttachedToProcess = FALSE; 02327 } 02328 02329 /* Check if we have to close the source handle */ 02330 if (Options & DUPLICATE_CLOSE_SOURCE) 02331 { 02332 /* Attach and close */ 02333 KeStackAttachProcess(&SourceProcess->Pcb, &ApcState); 02334 NtClose(SourceHandle); 02335 KeUnstackDetachProcess(&ApcState); 02336 } 02337 02338 /* Check if we had an access state */ 02339 if (PassedAccessState) SeDeleteAccessState(PassedAccessState); 02340 02341 /* Now check if incrementing actually failed */ 02342 if (!NT_SUCCESS(Status)) 02343 { 02344 /* Dereference handle tables */ 02345 ObDereferenceProcessHandleTable(SourceProcess); 02346 ObDereferenceProcessHandleTable(TargetProcess); 02347 02348 /* Dereference the source object */ 02349 ObDereferenceObject(SourceObject); 02350 return Status; 02351 } 02352 02353 /* Now create the handle */ 02354 NewHandle = ExCreateHandle(HandleTable, &NewHandleEntry); 02355 if (!NewHandle) 02356 { 02357 /* Undo the increment */ 02358 ObpDecrementHandleCount(SourceObject, 02359 TargetProcess, 02360 TargetAccess, 02361 ObjectType); 02362 02363 /* Deference the object and set failure status */ 02364 ObDereferenceObject(SourceObject); 02365 Status = STATUS_INSUFFICIENT_RESOURCES; 02366 } 02367 02368 /* Return the handle */ 02369 if (TargetHandle) *TargetHandle = NewHandle; 02370 02371 /* Dereference handle tables */ 02372 ObDereferenceProcessHandleTable(SourceProcess); 02373 ObDereferenceProcessHandleTable(TargetProcess); 02374 02375 /* Return status */ 02376 OBTRACE(OB_HANDLE_DEBUG, 02377 "%s - Duplicated handle: %lx for %p into %p. Source: %p HC PC %lx %lx\n", 02378 __FUNCTION__, 02379 NewHandle, 02380 SourceProcess, 02381 TargetProcess, 02382 SourceObject, 02383 ObjectHeader->PointerCount, 02384 ObjectHeader->HandleCount); 02385 return Status; 02386 } 02387 02388 /* PUBLIC FUNCTIONS *********************************************************/ 02389 02390 /*++ 02391 * @name ObOpenObjectByName 02392 * @implemented NT4 02393 * 02394 * The ObOpenObjectByName routine <FILLMEIN> 02395 * 02396 * @param ObjectAttributes 02397 * <FILLMEIN>. 02398 * 02399 * @param ObjectType 02400 * <FILLMEIN>. 02401 * 02402 * @param AccessMode 02403 * <FILLMEIN>. 02404 * 02405 * @param PassedAccessState 02406 * <FILLMEIN>. 02407 * 02408 * @param DesiredAccess 02409 * <FILLMEIN>. 02410 * 02411 * @param ParseContext 02412 * <FILLMEIN>. 02413 * 02414 * @param Handle 02415 * <FILLMEIN>. 02416 * 02417 * @return <FILLMEIN>. 02418 * 02419 * @remarks None. 02420 * 02421 *--*/ 02422 NTSTATUS 02423 NTAPI 02424 ObOpenObjectByName(IN POBJECT_ATTRIBUTES ObjectAttributes, 02425 IN POBJECT_TYPE ObjectType, 02426 IN KPROCESSOR_MODE AccessMode, 02427 IN PACCESS_STATE PassedAccessState, 02428 IN ACCESS_MASK DesiredAccess, 02429 IN OUT PVOID ParseContext, 02430 OUT PHANDLE Handle) 02431 { 02432 PVOID Object = NULL; 02433 UNICODE_STRING ObjectName; 02434 NTSTATUS Status; 02435 POBJECT_HEADER ObjectHeader; 02436 PGENERIC_MAPPING GenericMapping = NULL; 02437 OB_OPEN_REASON OpenReason; 02438 POB_TEMP_BUFFER TempBuffer; 02439 PAGED_CODE(); 02440 02441 /* Assume failure */ 02442 *Handle = NULL; 02443 02444 /* Check if we didn't get any Object Attributes */ 02445 if (!ObjectAttributes) 02446 { 02447 /* Fail with special status code */ 02448 return STATUS_INVALID_PARAMETER; 02449 } 02450 02451 /* Allocate the temporary buffer */ 02452 TempBuffer = ExAllocatePoolWithTag(NonPagedPool, 02453 sizeof(OB_TEMP_BUFFER), 02454 TAG_OB_TEMP_STORAGE); 02455 if (!TempBuffer) return STATUS_INSUFFICIENT_RESOURCES; 02456 02457 /* Capture all the info */ 02458 Status = ObpCaptureObjectCreateInformation(ObjectAttributes, 02459 AccessMode, 02460 AccessMode, 02461 TRUE, 02462 &TempBuffer->ObjectCreateInfo, 02463 &ObjectName); 02464 if (!NT_SUCCESS(Status)) 02465 { 02466 /* Fail */ 02467 ExFreePoolWithTag(TempBuffer, TAG_OB_TEMP_STORAGE); 02468 return Status; 02469 } 02470 02471 /* Check if we didn't get an access state */ 02472 if (!PassedAccessState) 02473 { 02474 /* Try to get the generic mapping if we can */ 02475 if (ObjectType) GenericMapping = &ObjectType->TypeInfo.GenericMapping; 02476 02477 /* Use our built-in access state */ 02478 PassedAccessState = &TempBuffer->LocalAccessState; 02479 Status = SeCreateAccessState(&TempBuffer->LocalAccessState, 02480 &TempBuffer->AuxData, 02481 DesiredAccess, 02482 GenericMapping); 02483 if (!NT_SUCCESS(Status)) goto Quickie; 02484 } 02485 02486 /* Get the security descriptor */ 02487 if (TempBuffer->ObjectCreateInfo.SecurityDescriptor) 02488 { 02489 /* Save it in the access state */ 02490 PassedAccessState->SecurityDescriptor = 02491 TempBuffer->ObjectCreateInfo.SecurityDescriptor; 02492 } 02493 02494 /* Now do the lookup */ 02495 Status = ObpLookupObjectName(TempBuffer->ObjectCreateInfo.RootDirectory, 02496 &ObjectName, 02497 TempBuffer->ObjectCreateInfo.Attributes, 02498 ObjectType, 02499 AccessMode, 02500 ParseContext, 02501 TempBuffer->ObjectCreateInfo.SecurityQos, 02502 NULL, 02503 PassedAccessState, 02504 &TempBuffer->LookupContext, 02505 &Object); 02506 if (!NT_SUCCESS(Status)) 02507 { 02508 /* Cleanup after lookup */ 02509 ObpReleaseLookupContext(&TempBuffer->LookupContext); 02510 goto Cleanup; 02511 } 02512 02513 /* Check if this object has create information */ 02514 ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object); 02515 if (ObjectHeader->Flags & OB_FLAG_CREATE_INFO) 02516 { 02517 /* Then we are creating a new handle */ 02518 OpenReason = ObCreateHandle; 02519 02520 /* Check if we still have create info */ 02521 if (ObjectHeader->ObjectCreateInfo) 02522 { 02523 /* Free it */ 02524 ObpFreeObjectCreateInformation(ObjectHeader-> 02525 ObjectCreateInfo); 02526 ObjectHeader->ObjectCreateInfo = NULL; 02527 } 02528 } 02529 else 02530 { 02531 /* Otherwise, we are merely opening it */ 02532 OpenReason = ObOpenHandle; 02533 } 02534 02535 /* Check if we have invalid object attributes */ 02536 if (ObjectHeader->Type->TypeInfo.InvalidAttributes & 02537 TempBuffer->ObjectCreateInfo.Attributes) 02538 { 02539 /* Set failure code */ 02540 Status = STATUS_INVALID_PARAMETER; 02541 02542 /* Cleanup after lookup */ 02543 ObpReleaseLookupContext(&TempBuffer->LookupContext); 02544 02545 /* Dereference the object */ 02546 ObDereferenceObject(Object); 02547 } 02548 else 02549 { 02550 /* Create the actual handle now */ 02551 Status = ObpCreateHandle(OpenReason, 02552 Object, 02553 ObjectType, 02554 PassedAccessState, 02555 0, 02556 TempBuffer->ObjectCreateInfo.Attributes, 02557 &TempBuffer->LookupContext, 02558 AccessMode, 02559 NULL, 02560 Handle); 02561 if (!NT_SUCCESS(Status)) ObDereferenceObject(Object); 02562 } 02563 02564 Cleanup: 02565 /* Delete the access state */ 02566 if (PassedAccessState == &TempBuffer->LocalAccessState) 02567 { 02568 SeDeleteAccessState(PassedAccessState); 02569 } 02570 02571 Quickie: 02572 /* Release the object attributes and temporary buffer */ 02573 ObpReleaseObjectCreateInformation(&TempBuffer->ObjectCreateInfo); 02574 if (ObjectName.Buffer) ObpFreeObjectNameBuffer(&ObjectName); 02575 ExFreePoolWithTag(TempBuffer, TAG_OB_TEMP_STORAGE); 02576 02577 /* Return status */ 02578 OBTRACE(OB_HANDLE_DEBUG, 02579 "%s - returning Object %p with PC S: %lx %lx\n", 02580 __FUNCTION__, 02581 Object, 02582 Object ? OBJECT_TO_OBJECT_HEADER(Object)->PointerCount : -1, 02583 Status); 02584 return Status; 02585 } 02586 02587 /*++ 02588 * @name ObOpenObjectByPointer 02589 * @implemented NT4 02590 * 02591 * The ObOpenObjectByPointer routine <FILLMEIN> 02592 * 02593 * @param Object 02594 * <FILLMEIN>. 02595 * 02596 * @param HandleAttributes 02597 * <FILLMEIN>. 02598 * 02599 * @param PassedAccessState 02600 * <FILLMEIN>. 02601 * 02602 * @param DesiredAccess 02603 * <FILLMEIN>. 02604 * 02605 * @param ObjectType 02606 * <FILLMEIN>. 02607 * 02608 * @param AccessMode 02609 * <FILLMEIN>. 02610 * 02611 * @param Handle 02612 * <FILLMEIN>. 02613 * 02614 * @return <FILLMEIN>. 02615 * 02616 * @remarks None. 02617 * 02618 *--*/ 02619 NTSTATUS 02620 NTAPI 02621 ObOpenObjectByPointer(IN PVOID Object, 02622 IN ULONG HandleAttributes, 02623 IN PACCESS_STATE PassedAccessState, 02624 IN ACCESS_MASK DesiredAccess, 02625 IN POBJECT_TYPE ObjectType, 02626 IN KPROCESSOR_MODE AccessMode, 02627 OUT PHANDLE Handle) 02628 { 02629 POBJECT_HEADER Header; 02630 NTSTATUS Status; 02631 ACCESS_STATE AccessState; 02632 AUX_ACCESS_DATA AuxData; 02633 PAGED_CODE(); 02634 02635 /* Assume failure */ 02636 *Handle = NULL; 02637 02638 /* Reference the object */ 02639 Status = ObReferenceObjectByPointer(Object, 02640 0, 02641 ObjectType, 02642 AccessMode); 02643 if (!NT_SUCCESS(Status)) return Status; 02644 02645 /* Get the Header Info */ 02646 Header = OBJECT_TO_OBJECT_HEADER(Object); 02647 02648 /* Check if we didn't get an access state */ 02649 if (!PassedAccessState) 02650 { 02651 /* Use our built-in access state */ 02652 PassedAccessState = &AccessState; 02653 Status = SeCreateAccessState(&AccessState, 02654 &AuxData, 02655 DesiredAccess, 02656 &Header->Type->TypeInfo.GenericMapping); 02657 if (!NT_SUCCESS(Status)) 02658 { 02659 /* Fail */ 02660 ObDereferenceObject(Object); 02661 return Status; 02662 } 02663 } 02664 02665 /* Check if we have invalid object attributes */ 02666 if (Header->Type->TypeInfo.InvalidAttributes & HandleAttributes) 02667 { 02668 /* Delete the access state */ 02669 if (PassedAccessState == &AccessState) 02670 { 02671 SeDeleteAccessState(PassedAccessState); 02672 } 02673 02674 /* Dereference the object */ 02675 ObDereferenceObject(Object); 02676 return STATUS_INVALID_PARAMETER; 02677 } 02678 02679 /* Create the handle */ 02680 Status = ObpCreateHandle(ObOpenHandle, 02681 Object, 02682 ObjectType, 02683 PassedAccessState, 02684 0, 02685 HandleAttributes, 02686 NULL, 02687 AccessMode, 02688 NULL, 02689 Handle); 02690 if (!NT_SUCCESS(Status)) ObDereferenceObject(Object); 02691 02692 /* Delete the access state */ 02693 if (PassedAccessState == &AccessState) 02694 { 02695 SeDeleteAccessState(PassedAccessState); 02696 } 02697 02698 /* Return */ 02699 OBTRACE(OB_HANDLE_DEBUG, 02700 "%s - returning Object with PC S: %lx %lx\n", 02701 __FUNCTION__, 02702 OBJECT_TO_OBJECT_HEADER(Object)->PointerCount, 02703 Status); 02704 return Status; 02705 } 02706 02707 /*++ 02708 * @name ObFindHandleForObject 02709 * @implemented NT4 02710 * 02711 * The ObFindHandleForObject routine <FILLMEIN> 02712 * 02713 * @param Process 02714 * <FILLMEIN>. 02715 * 02716 * @param Object 02717 * <FILLMEIN>. 02718 * 02719 * @param ObjectType 02720 * <FILLMEIN>. 02721 * 02722 * @param HandleInformation 02723 * <FILLMEIN>. 02724 * 02725 * @param HandleReturn 02726 * <FILLMEIN>. 02727 * 02728 * @return <FILLMEIN>. 02729 * 02730 * @remarks None. 02731 * 02732 *--*/ 02733 BOOLEAN 02734 NTAPI 02735 ObFindHandleForObject(IN PEPROCESS Process, 02736 IN PVOID Object, 02737 IN POBJECT_TYPE ObjectType, 02738 IN POBJECT_HANDLE_INFORMATION HandleInformation, 02739 OUT PHANDLE Handle) 02740 { 02741 OBP_FIND_HANDLE_DATA FindData; 02742 BOOLEAN Result = FALSE; 02743 PVOID ObjectTable; 02744 02745 /* Make sure we have an object table */ 02746 ObjectTable = ObReferenceProcessHandleTable(Process); 02747 if (ObjectTable) 02748 { 02749 /* Check if we have an object */ 02750 if (Object) 02751 { 02752 /* Set its header */ 02753 FindData.ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object); 02754 } 02755 else 02756 { 02757 /* Otherwise, no object to match*/ 02758 FindData.ObjectHeader = NULL; 02759 } 02760 02761 /* Set other information */ 02762 FindData.ObjectType = ObjectType; 02763 FindData.HandleInformation = HandleInformation; 02764 02765 /* Enumerate the handle table */ 02766 if (ExEnumHandleTable(Process->ObjectTable, 02767 ObpEnumFindHandleProcedure, 02768 &FindData, 02769 Handle)) 02770 { 02771 /* Set success */ 02772 Result = TRUE; 02773 } 02774 02775 /* Let go of the table */ 02776 ObDereferenceProcessHandleTable(Process); 02777 } 02778 02779 /* Return the result */ 02780 return Result; 02781 } 02782 02783 /*++ 02784 * @name ObInsertObject 02785 * @implemented NT4 02786 * 02787 * The ObInsertObject routine <FILLMEIN> 02788 * 02789 * @param Object 02790 * <FILLMEIN>. 02791 * 02792 * @param PassedAccessState 02793 * <FILLMEIN>. 02794 * 02795 * @param DesiredAccess 02796 * <FILLMEIN>. 02797 * 02798 * @param AdditionalReferences 02799 * <FILLMEIN>. 02800 * 02801 * @param ReferencedObject 02802 * <FILLMEIN>. 02803 * 02804 * @param Handle 02805 * <FILLMEIN>. 02806 * 02807 * @return <FILLMEIN>. 02808 * 02809 * @remarks None. 02810 * 02811 *--*/ 02812 NTSTATUS 02813 NTAPI 02814 ObInsertObject(IN PVOID Object, 02815 IN PACCESS_STATE AccessState OPTIONAL, 02816 IN ACCESS_MASK DesiredAccess, 02817 IN ULONG ObjectPointerBias, 02818 OUT PVOID *NewObject OPTIONAL, 02819 OUT PHANDLE Handle) 02820 { 02821 POBJECT_CREATE_INFORMATION ObjectCreateInfo; 02822 POBJECT_HEADER ObjectHeader; 02823 POBJECT_TYPE ObjectType; 02824 PUNICODE_STRING ObjectName; 02825 PVOID InsertObject; 02826 PSECURITY_DESCRIPTOR ParentDescriptor = NULL; 02827 BOOLEAN SdAllocated = FALSE; 02828 POBJECT_HEADER_NAME_INFO ObjectNameInfo; 02829 OBP_LOOKUP_CONTEXT Context; 02830 ACCESS_STATE LocalAccessState; 02831 AUX_ACCESS_DATA AuxData; 02832 OB_OPEN_REASON OpenReason; 02833 KPROCESSOR_MODE PreviousMode; 02834 NTSTATUS Status = STATUS_SUCCESS, RealStatus; 02835 BOOLEAN IsNewObject; 02836 PAGED_CODE(); 02837 02838 /* Get the Header */ 02839 ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object); 02840 02841 /* Detect invalid insert */ 02842 if (!(ObjectHeader->Flags & OB_FLAG_CREATE_INFO)) 02843 { 02844 /* Display warning and break into debugger */ 02845 DPRINT1("OB: Attempting to insert existing object %08x\n", Object); 02846 DbgBreakPoint(); 02847 02848 /* Allow debugger to continue */ 02849 ObDereferenceObject(Object); 02850 return STATUS_INVALID_PARAMETER; 02851 } 02852 02853 /* Get the create and name info, as well as the object type */ 02854 ObjectCreateInfo = ObjectHeader->ObjectCreateInfo; 02855 ObjectNameInfo = ObpReferenceNameInfo(ObjectHeader); 02856 ObjectType = ObjectHeader->Type; 02857 ObjectName = NULL; 02858 02859 /* Check if this is an named object */ 02860 if ((ObjectNameInfo) && (ObjectNameInfo->Name.Buffer)) 02861 { 02862 /* Get the object name */ 02863 ObjectName = &ObjectNameInfo->Name; 02864 } 02865 02866 /* Sanity check */ 02867 ASSERT((Handle) || 02868 ((ObjectPointerBias == 0) && 02869 (ObjectName == NULL) && 02870 (ObjectType->TypeInfo.SecurityRequired) && 02871 (NewObject == NULL))); 02872 02873 /* Check if the object is unnamed and also doesn't have security */ 02874 PreviousMode = KeGetPreviousMode(); 02875 if (!(ObjectType->TypeInfo.SecurityRequired) && !(ObjectName)) 02876 { 02877 /* Assume failure */ 02878 *Handle = NULL; 02879 ObjectHeader->ObjectCreateInfo = NULL; 02880 02881 /* Create the handle */ 02882 Status = ObpCreateUnnamedHandle(Object, 02883 DesiredAccess, 02884 ObjectPointerBias + 1, 02885 ObjectCreateInfo->Attributes, 02886 PreviousMode, 02887 NewObject, 02888 Handle); 02889 02890 /* Free the create information */ 02891 ObpFreeObjectCreateInformation(ObjectCreateInfo); 02892 02893 /* Release the object name information */ 02894 ObpDereferenceNameInfo(ObjectNameInfo); 02895 02896 /* Remove the extra keep-alive reference */ 02897 ObDereferenceObject(Object); 02898 02899 /* Return */ 02900 OBTRACE(OB_HANDLE_DEBUG, 02901 "%s - returning Object with PC S: %lx %lx\n", 02902 __FUNCTION__, 02903 ObjectHeader->PointerCount, 02904 Status); 02905 return Status; 02906 } 02907 02908 /* Check if we didn't get an access state */ 02909 if (!AccessState) 02910 { 02911 /* Use our built-in access state */ 02912 AccessState = &LocalAccessState; 02913 Status = SeCreateAccessState(&LocalAccessState, 02914 &AuxData, 02915 DesiredAccess, 02916 &ObjectType->TypeInfo.GenericMapping); 02917 if (!NT_SUCCESS(Status)) 02918 { 02919 /* Fail */ 02920 ObpDereferenceNameInfo(ObjectNameInfo); 02921 ObDereferenceObject(Object); 02922 return Status; 02923 } 02924 } 02925 02926 /* Save the security descriptor */ 02927 AccessState->SecurityDescriptor = ObjectCreateInfo->SecurityDescriptor; 02928 02929 /* Validate the access mask */ 02930 Status = ObpValidateAccessMask(AccessState); 02931 if (!NT_SUCCESS(Status)) 02932 { 02933 /* Fail */ 02934 ObpDereferenceNameInfo(ObjectNameInfo); 02935 ObDereferenceObject(Object); 02936 return Status; 02937 } 02938 02939 /* Setup a lookup context */ 02940 ObpInitializeLookupContext(&Context); 02941 InsertObject = Object; 02942 OpenReason = ObCreateHandle; 02943 02944 /* Check if the object is named */ 02945 if (ObjectName) 02946 { 02947 /* Look it up */ 02948 Status = ObpLookupObjectName(ObjectCreateInfo->RootDirectory, 02949 ObjectName, 02950 ObjectCreateInfo->Attributes, 02951 ObjectType, 02952 (ObjectHeader->Flags & OB_FLAG_KERNEL_MODE) ? 02953 KernelMode : UserMode, 02954 ObjectCreateInfo->ParseContext, 02955 ObjectCreateInfo->SecurityQos, 02956 Object, 02957 AccessState, 02958 &Context, 02959 &InsertObject); 02960 02961 /* Check if we found an object that doesn't match the one requested */ 02962 if ((NT_SUCCESS(Status)) && (InsertObject) && (Object != InsertObject)) 02963 { 02964 /* This means we're opening an object, not creating a new one */ 02965 OpenReason = ObOpenHandle; 02966 02967 /* Make sure the caller said it's OK to do this */ 02968 if (ObjectCreateInfo->Attributes & OBJ_OPENIF) 02969 { 02970 /* He did, but did he want this type? */ 02971 if (ObjectType != OBJECT_TO_OBJECT_HEADER(InsertObject)->Type) 02972 { 02973 /* Wrong type, so fail */ 02974 Status = STATUS_OBJECT_TYPE_MISMATCH; 02975 } 02976 else 02977 { 02978 /* Right type, so warn */ 02979 Status = STATUS_OBJECT_NAME_EXISTS; 02980 } 02981 } 02982 else 02983 { 02984 /* Check if this was a symbolic link */ 02985 if (OBJECT_TO_OBJECT_HEADER(InsertObject)->Type == 02986 ObSymbolicLinkType) 02987 { 02988 /* Dereference it */ 02989 ObDereferenceObject(InsertObject); 02990 } 02991 02992 /* Caller wanted to create a new object, fail */ 02993 Status = STATUS_OBJECT_NAME_COLLISION; 02994 } 02995 } 02996 02997 /* Check if anything until now failed */ 02998 if (!NT_SUCCESS(Status)) 02999 { 03000 /* Cleanup after lookup */ 03001 ObpReleaseLookupContext(&Context); 03002 03003 /* Remove query reference that we added */ 03004 ObpDereferenceNameInfo(ObjectNameInfo); 03005 03006 /* Dereference the object and delete the access state */ 03007 ObDereferenceObject(Object); 03008 if (AccessState == &LocalAccessState) 03009 { 03010 /* We used a local one; delete it */ 03011 SeDeleteAccessState(AccessState); 03012 } 03013 03014 /* Return failure code */ 03015 return Status; 03016 } 03017 else 03018 { 03019 /* Check if this is a symbolic link */ 03020 if (ObjectType == ObSymbolicLinkType) 03021 { 03022 /* Create the internal name */ 03023 ObpCreateSymbolicLinkName(Object); 03024 } 03025 } 03026 } 03027 03028 /* Now check if this object is being created */ 03029 if (InsertObject == Object) 03030 { 03031 /* Check if it's named or forces security */ 03032 if ((ObjectName) || (ObjectType->TypeInfo.SecurityRequired)) 03033 { 03034 /* Make sure it's inserted into an object directory */ 03035 if ((ObjectNameInfo) && (ObjectNameInfo->Directory)) 03036 { 03037 /* Get the current descriptor */ 03038 ObGetObjectSecurity(ObjectNameInfo->Directory, 03039 &ParentDescriptor, 03040 &SdAllocated); 03041 } 03042 03043 /* Now assign it */ 03044 Status = ObAssignSecurity(AccessState, 03045 ParentDescriptor, 03046 Object, 03047 ObjectType); 03048 03049 /* Check if we captured one */ 03050 if (ParentDescriptor) 03051 { 03052 /* We did, release it */ 03053 ObReleaseObjectSecurity(ParentDescriptor, SdAllocated); 03054 } 03055 else if (NT_SUCCESS(Status)) 03056 { 03057 /* Other we didn't, but we were able to use the current SD */ 03058 SeReleaseSecurityDescriptor(ObjectCreateInfo->SecurityDescriptor, 03059 ObjectCreateInfo->ProbeMode, 03060 TRUE); 03061 03062 /* Clear the current one */ 03063 AccessState->SecurityDescriptor = 03064 ObjectCreateInfo->SecurityDescriptor = NULL; 03065 } 03066 } 03067 03068 /* Check if anything until now failed */ 03069 if (!NT_SUCCESS(Status)) 03070 { 03071 /* Check if the directory was added */ 03072 if (Context.DirectoryLocked) 03073 { 03074 /* Weird case where we need to do a manual delete */ 03075 DPRINT1("Unhandled path\n"); 03076 ASSERT(FALSE); 03077 } 03078 03079 /* Cleanup the lookup */ 03080 ObpReleaseLookupContext(&Context); 03081 03082 /* Remove query reference that we added */ 03083 ObpDereferenceNameInfo(ObjectNameInfo); 03084 03085 /* Dereference the object and delete the access state */ 03086 ObDereferenceObject(Object); 03087 if (AccessState == &LocalAccessState) 03088 { 03089 /* We used a local one; delete it */ 03090 SeDeleteAccessState(AccessState); 03091 } 03092 03093 /* Return failure code */ 03094 ASSERT(FALSE); 03095 return Status; 03096 } 03097 } 03098 03099 /* Save the actual status until here */ 03100 RealStatus = Status; 03101 03102 /* Check if caller wants us to create a handle */ 03103 ObjectHeader->ObjectCreateInfo = NULL; 03104 if (Handle) 03105 { 03106 /* Create the handle */ 03107 Status = ObpCreateHandle(OpenReason, 03108 InsertObject, 03109 NULL, 03110 AccessState, 03111 ObjectPointerBias + 1, 03112 ObjectCreateInfo->Attributes, 03113 &Context, 03114 PreviousMode, 03115 NewObject, 03116 Handle); 03117 if (!NT_SUCCESS(Status)) 03118 { 03119 /* If the object had a name, backout everything */ 03120 if (ObjectName) ObpDeleteNameCheck(Object); 03121 03122 /* Return the status of the failure */ 03123 *Handle = NULL; 03124 RealStatus = Status; 03125 } 03126 03127 /* Remove a query reference */ 03128 ObpDereferenceNameInfo(ObjectNameInfo); 03129 03130 /* Remove the extra keep-alive reference */ 03131 ObDereferenceObject(Object); 03132 } 03133 else 03134 { 03135 /* Otherwise, lock the object */ 03136 ObpAcquireObjectLock(ObjectHeader); 03137 03138 /* And charge quota for the process to make it appear as used */ 03139 RealStatus = ObpChargeQuotaForObject(ObjectHeader, 03140 ObjectType, 03141 &IsNewObject); 03142 03143 /* Release the lock */ 03144 ObpReleaseObjectLock(ObjectHeader); 03145 03146 /* Check if we failed and dereference the object if so */ 03147 if (!NT_SUCCESS(RealStatus)) ObDereferenceObject(Object); 03148 } 03149 03150 /* We can delete the Create Info now */ 03151 ObpFreeObjectCreateInformation(ObjectCreateInfo); 03152 03153 /* Check if we created our own access state and delete it if so */ 03154 if (AccessState == &LocalAccessState) SeDeleteAccessState(AccessState); 03155 03156 /* Return status code */ 03157 OBTRACE(OB_HANDLE_DEBUG, 03158 "%s - returning Object with PC RS/S: %lx %lx %lx\n", 03159 __FUNCTION__, 03160 OBJECT_TO_OBJECT_HEADER(Object)->PointerCount, 03161 RealStatus, Status); 03162 return RealStatus; 03163 } 03164 03165 /*++ 03166 * @name ObCloseHandle 03167 * @implemented NT5.1 03168 * 03169 * The ObCloseHandle routine <FILLMEIN> 03170 * 03171 * @param Handle 03172 * <FILLMEIN>. 03173 * 03174 * @param AccessMode 03175 * <FILLMEIN>. 03176 * 03177 * @return <FILLMEIN>. 03178 * 03179 * @remarks None. 03180 * 03181 *--*/ 03182 NTSTATUS 03183 NTAPI 03184 ObCloseHandle(IN HANDLE Handle, 03185 IN KPROCESSOR_MODE AccessMode) 03186 { 03187 /* Call the internal API */ 03188 return ObpCloseHandle(Handle, AccessMode); 03189 } 03190 03191 /*++ 03192 * @name NtClose 03193 * @implemented NT4 03194 * 03195 * The NtClose routine <FILLMEIN> 03196 * 03197 * @param Handle 03198 * <FILLMEIN>. 03199 * 03200 * @return <FILLMEIN>. 03201 * 03202 * @remarks None. 03203 * 03204 *--*/ 03205 NTSTATUS 03206 NTAPI 03207 NtClose(IN HANDLE Handle) 03208 { 03209 /* Call the internal API */ 03210 return ObpCloseHandle(Handle, ExGetPreviousMode()); 03211 } 03212 03213 NTSTATUS 03214 NTAPI 03215 NtDuplicateObject(IN HANDLE SourceProcessHandle, 03216 IN HANDLE SourceHandle, 03217 IN HANDLE TargetProcessHandle OPTIONAL, 03218 OUT PHANDLE TargetHandle OPTIONAL, 03219 IN ACCESS_MASK DesiredAccess, 03220 IN ULONG HandleAttributes, 03221 IN ULONG Options) 03222 { 03223 PEPROCESS SourceProcess, TargetProcess, Target; 03224 HANDLE hTarget; 03225 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); 03226 NTSTATUS Status; 03227 OBTRACE(OB_HANDLE_DEBUG, 03228 "%s - Duplicating handle: %lx for %lx into %lx.\n", 03229 __FUNCTION__, 03230 SourceHandle, 03231 SourceProcessHandle, 03232 TargetProcessHandle); 03233 03234 /* Check if we have a target handle */ 03235 if ((TargetHandle) && (PreviousMode != KernelMode)) 03236 { 03237 /* Enter SEH */ 03238 _SEH2_TRY 03239 { 03240 /* Probe the handle and assume failure */ 03241 ProbeForWriteHandle(TargetHandle); 03242 *TargetHandle = NULL; 03243 } 03244 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 03245 { 03246 /* Return the exception code */ 03247 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 03248 } 03249 _SEH2_END; 03250 } 03251 03252 /* Now reference the input handle */ 03253 Status = ObReferenceObjectByHandle(SourceProcessHandle, 03254 PROCESS_DUP_HANDLE, 03255 PsProcessType, 03256 PreviousMode, 03257 (PVOID*)&SourceProcess, 03258 NULL); 03259 if (!NT_SUCCESS(Status)) return(Status); 03260 03261 /* Check if got a target handle */ 03262 if (TargetProcessHandle) 03263 { 03264 /* Now reference the output handle */ 03265 Status = ObReferenceObjectByHandle(TargetProcessHandle, 03266 PROCESS_DUP_HANDLE, 03267 PsProcessType, 03268 PreviousMode, 03269 (PVOID*)&TargetProcess, 03270 NULL); 03271 if (NT_SUCCESS(Status)) 03272 { 03273 /* Use this target process */ 03274 Target = TargetProcess; 03275 } 03276 else 03277 { 03278 /* No target process */ 03279 Target = NULL; 03280 } 03281 } 03282 else 03283 { 03284 /* No target process */ 03285 Status = STATUS_SUCCESS; 03286 Target = NULL; 03287 } 03288 03289 /* Call the internal routine */ 03290 Status = ObDuplicateObject(SourceProcess, 03291 SourceHandle, 03292 Target, 03293 &hTarget, 03294 DesiredAccess, 03295 HandleAttributes, 03296 Options, 03297 PreviousMode); 03298 03299 /* Check if the caller wanted the return handle */ 03300 if (TargetHandle) 03301 { 03302 /* Protect the write to user mode */ 03303 _SEH2_TRY 03304 { 03305 /* Write the new handle */ 03306 *TargetHandle = hTarget; 03307 } 03308 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 03309 { 03310 /* Otherwise, get the exception code */ 03311 Status = _SEH2_GetExceptionCode(); 03312 } 03313 _SEH2_END; 03314 } 03315 03316 /* Dereference the processes */ 03317 OBTRACE(OB_HANDLE_DEBUG, 03318 "%s - Duplicated handle: %lx into %lx S %lx\n", 03319 __FUNCTION__, 03320 hTarget, 03321 TargetProcessHandle, 03322 Status); 03323 if (Target) ObDereferenceObject(Target); 03324 ObDereferenceObject(SourceProcess); 03325 return Status; 03326 } 03327 03328 #undef ObIsKernelHandle 03329 BOOLEAN 03330 NTAPI 03331 ObIsKernelHandle(IN HANDLE Handle) 03332 { 03333 /* We know we're kernel mode, so just check for the kernel handle flag */ 03334 return (BOOLEAN)(((ULONG_PTR)Handle & KERNEL_HANDLE_FLAG) != 0); 03335 } 03336 03337 /* EOF */ Generated on Sat May 26 2012 04:36:31 for ReactOS by
1.7.6.1
|