ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

obhandle.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.