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

oblife.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/oblife.c
00005  * PURPOSE:         Manages the lifetime of an Object, including its creation,
00006  *                  and deletion, as well as setting or querying any of its
00007  *                  information while it is active. Since Object Types are also
00008  *                  Objects, those are also managed here.
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 extern ULONG NtGlobalFlag;
00021 
00022 POBJECT_TYPE ObpTypeObjectType = NULL;
00023 KEVENT ObpDefaultObject;
00024 KGUARDED_MUTEX ObpDeviceMapLock;
00025 
00026 GENERAL_LOOKASIDE ObpNameBufferLookasideList, ObpCreateInfoLookasideList;
00027 
00028 WORK_QUEUE_ITEM ObpReaperWorkItem;
00029 volatile PVOID ObpReaperList;
00030 
00031 ULONG ObpObjectsCreated, ObpObjectsWithName, ObpObjectsWithPoolQuota;
00032 ULONG ObpObjectsWithHandleDB, ObpObjectsWithCreatorInfo;
00033 POBJECT_TYPE ObpObjectTypes[32];
00034 
00035 /* PRIVATE FUNCTIONS *********************************************************/
00036 
00037 VOID
00038 FASTCALL
00039 ObpDeallocateObject(IN PVOID Object)
00040 {
00041     PVOID HeaderLocation;
00042     POBJECT_HEADER Header;
00043     POBJECT_TYPE ObjectType;
00044     POBJECT_HEADER_HANDLE_INFO HandleInfo;
00045     POBJECT_HEADER_NAME_INFO NameInfo;
00046     POBJECT_HEADER_CREATOR_INFO CreatorInfo;
00047     POBJECT_HEADER_QUOTA_INFO QuotaInfo;
00048     ULONG PagedPoolCharge, NonPagedPoolCharge;
00049     PAGED_CODE();
00050 
00051     /* Get the header and assume this is what we'll free */
00052     Header = OBJECT_TO_OBJECT_HEADER(Object);
00053     ObjectType = Header->Type;
00054     HeaderLocation = Header;
00055 
00056     /* To find the header, walk backwards from how we allocated */
00057     if ((CreatorInfo = OBJECT_HEADER_TO_CREATOR_INFO(Header)))
00058     {
00059         HeaderLocation = CreatorInfo;
00060     }
00061     if ((NameInfo = OBJECT_HEADER_TO_NAME_INFO(Header)))
00062     {
00063         HeaderLocation = NameInfo;
00064     }
00065     if ((HandleInfo = OBJECT_HEADER_TO_HANDLE_INFO(Header)))
00066     {
00067         HeaderLocation = HandleInfo;
00068     }
00069     if ((QuotaInfo = OBJECT_HEADER_TO_QUOTA_INFO(Header)))
00070     {
00071         HeaderLocation = QuotaInfo;
00072     }
00073 
00074     /* Decrease the total */
00075     InterlockedDecrement((PLONG)&ObjectType->TotalNumberOfObjects);
00076 
00077     /* Check if we have create info */
00078     if (Header->Flags & OB_FLAG_CREATE_INFO)
00079     {
00080         /* Double-check that it exists */
00081         if (Header->ObjectCreateInfo)
00082         {
00083             /* Free it */
00084             ObpFreeObjectCreateInformation(Header->ObjectCreateInfo);
00085             Header->ObjectCreateInfo = NULL;
00086         }
00087     }
00088     else
00089     {
00090         /* Check if it has a quota block */
00091         if (Header->QuotaBlockCharged)
00092         {
00093             /* Check if we have quota information */
00094             if (QuotaInfo)
00095             {
00096                 /* Get charges from quota information */
00097                 PagedPoolCharge = QuotaInfo->PagedPoolCharge +
00098                                   QuotaInfo->SecurityDescriptorCharge;
00099                 NonPagedPoolCharge = QuotaInfo->NonPagedPoolCharge;
00100             }
00101             else
00102             {
00103                 /* Get charges from object type */
00104                 PagedPoolCharge = ObjectType->TypeInfo.DefaultPagedPoolCharge;
00105                 NonPagedPoolCharge = ObjectType->
00106                                      TypeInfo.DefaultNonPagedPoolCharge;
00107 
00108                 /* Add the SD charge too */
00109                 if (Header->Flags & OB_FLAG_SECURITY) PagedPoolCharge += 2048;
00110             }
00111 
00112             /* Return the quota */
00113             DPRINT("FIXME: Should return quotas: %lx %lx\n", PagedPoolCharge, NonPagedPoolCharge);
00114 #if 0
00115             PsReturnSharedPoolQuota(ObjectHeader->QuotaBlockCharged,
00116                                     PagedPoolCharge,
00117                                     NonPagedPoolCharge);
00118 #endif
00119 
00120         }
00121     }
00122 
00123     /* Check if a handle database was active */
00124     if ((HandleInfo) && !(Header->Flags & OB_FLAG_SINGLE_PROCESS))
00125     {
00126         /* Free it */
00127         ExFreePool(HandleInfo->HandleCountDatabase);
00128         HandleInfo->HandleCountDatabase = NULL;
00129     }
00130 
00131     /* Check if we have a name */
00132     if ((NameInfo) && (NameInfo->Name.Buffer))
00133     {
00134         /* Free it */
00135         ExFreePool(NameInfo->Name.Buffer);
00136         NameInfo->Name.Buffer = NULL;
00137     }
00138 
00139     /* Catch invalid access */
00140     Header->Type = (POBJECT_TYPE)0xBAADB0B0;
00141 
00142     /* Free the object using the same allocation tag */
00143     ExFreePoolWithTag(HeaderLocation, ObjectType->Key);
00144 }
00145 
00146 VOID
00147 NTAPI
00148 ObpDeleteObject(IN PVOID Object,
00149                 IN BOOLEAN CalledFromWorkerThread)
00150 {
00151     POBJECT_HEADER Header;
00152     POBJECT_TYPE ObjectType;
00153     POBJECT_HEADER_NAME_INFO NameInfo;
00154     POBJECT_HEADER_CREATOR_INFO CreatorInfo;
00155     KIRQL CalloutIrql;
00156     PAGED_CODE();
00157 
00158     /* Get the header and type */
00159     Header = OBJECT_TO_OBJECT_HEADER(Object);
00160     ObjectType = Header->Type;
00161 
00162     /* Get creator and name information */
00163     NameInfo = OBJECT_HEADER_TO_NAME_INFO(Header);
00164     CreatorInfo = OBJECT_HEADER_TO_CREATOR_INFO(Header);
00165 
00166     /* Check if the object is on a type list */
00167     if ((CreatorInfo) && !(IsListEmpty(&CreatorInfo->TypeList)))
00168     {
00169         /* Lock the object type */
00170         ObpEnterObjectTypeMutex(ObjectType);
00171 
00172         /* Remove the object from the type list */
00173         RemoveEntryList(&CreatorInfo->TypeList);
00174 
00175         /* Release the lock */
00176         ObpLeaveObjectTypeMutex(ObjectType);
00177     }
00178 
00179     /* Check if we have a name */
00180     if ((NameInfo) && (NameInfo->Name.Buffer))
00181     {
00182         /* Free it */
00183         ExFreePool(NameInfo->Name.Buffer);
00184         RtlInitEmptyUnicodeString(&NameInfo->Name, NULL, 0);
00185     }
00186 
00187     /* Check if we have a security descriptor */
00188     if (Header->SecurityDescriptor)
00189     {
00190         /* Call the security procedure to delete it */
00191         ObpCalloutStart(&CalloutIrql);
00192         ObjectType->TypeInfo.SecurityProcedure(Object,
00193                                                DeleteSecurityDescriptor,
00194                                                0,
00195                                                NULL,
00196                                                NULL,
00197                                                &Header->SecurityDescriptor,
00198                                                0,
00199                                                NULL);
00200         ObpCalloutEnd(CalloutIrql, "Security", ObjectType, Object);
00201     }
00202 
00203     /* Check if we have a delete procedure */
00204     if (ObjectType->TypeInfo.DeleteProcedure)
00205     {
00206         /* Save whether we were deleted from worker thread or not */
00207         if (!CalledFromWorkerThread) Header->Flags |= OB_FLAG_DEFER_DELETE;
00208 
00209         /* Call it */
00210         ObpCalloutStart(&CalloutIrql);
00211         ObjectType->TypeInfo.DeleteProcedure(Object);
00212         ObpCalloutEnd(CalloutIrql, "Delete", ObjectType, Object);
00213     }
00214 
00215     /* Now de-allocate all object members */
00216     ObpDeallocateObject(Object);
00217 }
00218 
00219 VOID
00220 NTAPI
00221 ObpReapObject(IN PVOID Parameter)
00222 {
00223     POBJECT_HEADER ReapObject, NextObject;
00224 
00225     /* Start reaping */
00226     do
00227     {
00228         /* Get the reap object */
00229         ReapObject = InterlockedExchangePointer(&ObpReaperList, (PVOID)1);
00230 
00231         /* Start deletion loop */
00232         do
00233         {
00234             /* Get the next object */
00235             NextObject = ReapObject->NextToFree;
00236 
00237             /* Delete the object */
00238             ObpDeleteObject(&ReapObject->Body, TRUE);
00239 
00240             /* Move to the next one */
00241             ReapObject = NextObject;
00242         } while ((ReapObject) && (ReapObject != (PVOID)1));
00243     } while ((ObpReaperList != (PVOID)1) ||
00244              (InterlockedCompareExchange((PLONG)&ObpReaperList, 0, 1) != 1));
00245 }
00246 
00247 /*++
00248 * @name ObpSetPermanentObject
00249 *
00250 *     The ObpSetPermanentObject routine makes an sets or clears the permanent
00251 *     flag of an object, thus making it either permanent or temporary.
00252 *
00253 * @param ObjectBody
00254 *        Pointer to the object to make permanent or temporary.
00255 *
00256 * @param Permanent
00257 *        Flag specifying which operation to perform.
00258 *
00259 * @return None.
00260 *
00261 * @remarks If the object is being made temporary, then it will be checked
00262 *          as a candidate for immediate removal from the namespace.
00263 *
00264 *--*/
00265 VOID
00266 FASTCALL
00267 ObpSetPermanentObject(IN PVOID ObjectBody,
00268                       IN BOOLEAN Permanent)
00269 {
00270     POBJECT_HEADER ObjectHeader;
00271 
00272     /* Get the header */
00273     ObjectHeader = OBJECT_TO_OBJECT_HEADER(ObjectBody);
00274 
00275     /* Acquire object lock */
00276     ObpAcquireObjectLock(ObjectHeader);
00277 
00278     /* Check what we're doing to it */
00279     if (Permanent)
00280     {
00281         /* Set it to permanent */
00282         ObjectHeader->Flags |= OB_FLAG_PERMANENT;
00283 
00284         /* Release the lock */
00285         ObpReleaseObjectLock(ObjectHeader);
00286     }
00287     else
00288     {
00289         /* Remove the flag */
00290         ObjectHeader->Flags &= ~OB_FLAG_PERMANENT;
00291 
00292         /* Release the lock */
00293         ObpReleaseObjectLock(ObjectHeader);
00294 
00295         /* Check if we should delete the object now */
00296         ObpDeleteNameCheck(ObjectBody);
00297     }
00298 }
00299 
00300 PWCHAR
00301 NTAPI
00302 ObpAllocateObjectNameBuffer(IN ULONG Length,
00303                             IN BOOLEAN UseLookaside,
00304                             IN OUT PUNICODE_STRING ObjectName)
00305 {
00306     ULONG MaximumLength;
00307     PVOID Buffer;
00308 
00309     /* Set the maximum length to the length plus the terminator */
00310     MaximumLength = Length + sizeof(UNICODE_NULL);
00311 
00312     /* Check if we should use the lookaside buffer */
00313     if (!(UseLookaside) || (MaximumLength > OBP_NAME_LOOKASIDE_MAX_SIZE))
00314     {
00315         /* Nope, allocate directly from pool */
00316         /* Since we later use MaximumLength to detect that we're not allocating
00317          * from a list, we need at least MaximumLength + sizeof(UNICODE_NULL)
00318          * here.
00319          *
00320          * People do call this with UseLookasideList FALSE so the distinction
00321          * is critical.
00322          */
00323         if (MaximumLength <= OBP_NAME_LOOKASIDE_MAX_SIZE)
00324         {
00325             MaximumLength = OBP_NAME_LOOKASIDE_MAX_SIZE + sizeof(UNICODE_NULL);
00326         }
00327         Buffer = ExAllocatePoolWithTag(PagedPool,
00328                                        MaximumLength,
00329                                        OB_NAME_TAG);
00330     }
00331     else
00332     {
00333         /* Allocate from the lookaside */
00334         MaximumLength = OBP_NAME_LOOKASIDE_MAX_SIZE;
00335         Buffer = ObpAllocateObjectCreateInfoBuffer(LookasideNameBufferList);
00336     }
00337 
00338     /* Setup the string */
00339     ObjectName->MaximumLength = (USHORT)MaximumLength;
00340     ObjectName->Length = (USHORT)Length;
00341     ObjectName->Buffer = Buffer;
00342     return Buffer;
00343 }
00344 
00345 VOID
00346 NTAPI
00347 ObpFreeObjectNameBuffer(IN PUNICODE_STRING Name)
00348 {
00349     PVOID Buffer = Name->Buffer;
00350 
00351     /* We know this is a pool-allocation if the size doesn't match */
00352     if (Name->MaximumLength != OBP_NAME_LOOKASIDE_MAX_SIZE)
00353     {
00354         /* Free it from the pool */
00355         ExFreePool(Buffer);
00356     }
00357     else
00358     {
00359         /* Otherwise, free from the lookaside */
00360         ObpFreeCapturedAttributes(Buffer, LookasideNameBufferList);
00361     }
00362 }
00363 
00364 NTSTATUS
00365 NTAPI
00366 ObpCaptureObjectName(IN OUT PUNICODE_STRING CapturedName,
00367                      IN PUNICODE_STRING ObjectName,
00368                      IN KPROCESSOR_MODE AccessMode,
00369                      IN BOOLEAN UseLookaside)
00370 {
00371     NTSTATUS Status = STATUS_SUCCESS;
00372     ULONG StringLength;
00373     PWCHAR StringBuffer = NULL;
00374     UNICODE_STRING LocalName;
00375     PAGED_CODE();
00376 
00377     /* Initialize the Input String */
00378     RtlInitEmptyUnicodeString(CapturedName, NULL, 0);
00379 
00380     /* Protect everything */
00381     _SEH2_TRY
00382     {
00383         /* Check if we came from user mode */
00384         if (AccessMode != KernelMode)
00385         {
00386             /* First Probe the String */
00387             LocalName = ProbeForReadUnicodeString(ObjectName);
00388             ProbeForRead(LocalName.Buffer, LocalName.Length, sizeof(WCHAR));
00389         }
00390         else
00391         {
00392             /* No probing needed */
00393             LocalName = *ObjectName;
00394         }
00395 
00396         /* Make sure there really is a string */
00397         if ((StringLength = LocalName.Length))
00398         {
00399             /* Check that the size is a valid WCHAR multiple */
00400             if ((StringLength & (sizeof(WCHAR) - 1)) ||
00401                 /* Check that the NULL-termination below will work */
00402                 (StringLength == (MAXUSHORT - sizeof(UNICODE_NULL) + 1)))
00403             {
00404                 /* PS: Please keep the checks above expanded for clarity */
00405                 Status = STATUS_OBJECT_NAME_INVALID;
00406             }
00407             else
00408             {
00409                 /* Allocate the string buffer */
00410                 StringBuffer = ObpAllocateObjectNameBuffer(StringLength,
00411                                                            UseLookaside,
00412                                                            CapturedName);
00413                 if (!StringBuffer)
00414                 {
00415                     /* Set failure code */
00416                     Status = STATUS_INSUFFICIENT_RESOURCES;
00417                 }
00418                 else
00419                 {
00420                     /* Copy the name */
00421                     RtlCopyMemory(StringBuffer, LocalName.Buffer, StringLength);
00422                     StringBuffer[StringLength / sizeof(WCHAR)] = UNICODE_NULL;
00423                 }
00424             }
00425         }
00426     }
00427     _SEH2_EXCEPT(ExSystemExceptionFilter())
00428     {
00429         /* Handle exception and free the string buffer */
00430         Status = _SEH2_GetExceptionCode();
00431         if (StringBuffer)
00432         {
00433             ObpFreeObjectNameBuffer(CapturedName);
00434         }
00435     }
00436     _SEH2_END;
00437 
00438     /* Return */
00439     return Status;
00440 }
00441 
00442 NTSTATUS
00443 NTAPI
00444 ObpCaptureObjectCreateInformation(IN POBJECT_ATTRIBUTES ObjectAttributes,
00445                                   IN KPROCESSOR_MODE AccessMode,
00446                                   IN KPROCESSOR_MODE CreatorMode,
00447                                   IN BOOLEAN AllocateFromLookaside,
00448                                   IN POBJECT_CREATE_INFORMATION ObjectCreateInfo,
00449                                   OUT PUNICODE_STRING ObjectName)
00450 {
00451     NTSTATUS Status = STATUS_SUCCESS;
00452     PSECURITY_DESCRIPTOR SecurityDescriptor;
00453     PSECURITY_QUALITY_OF_SERVICE SecurityQos;
00454     PUNICODE_STRING LocalObjectName = NULL;
00455     PAGED_CODE();
00456 
00457     /* Zero out the Capture Data */
00458     RtlZeroMemory(ObjectCreateInfo, sizeof(OBJECT_CREATE_INFORMATION));
00459 
00460     /* SEH everything here for protection */
00461     _SEH2_TRY
00462     {
00463         /* Check if we got attributes */
00464         if (ObjectAttributes)
00465         {
00466             /* Check if we're in user mode */
00467             if (AccessMode != KernelMode)
00468             {
00469                 /* Probe the attributes */
00470                 ProbeForRead(ObjectAttributes,
00471                              sizeof(OBJECT_ATTRIBUTES),
00472                              sizeof(ULONG));
00473             }
00474 
00475             /* Validate the Size and Attributes */
00476             if ((ObjectAttributes->Length != sizeof(OBJECT_ATTRIBUTES)) ||
00477                 (ObjectAttributes->Attributes & ~OBJ_VALID_ATTRIBUTES))
00478             {
00479                 /* Invalid combination, fail */
00480                 _SEH2_YIELD(return STATUS_INVALID_PARAMETER);
00481             }
00482 
00483             /* Set some Create Info and do not allow user-mode kernel handles */
00484             ObjectCreateInfo->RootDirectory = ObjectAttributes->RootDirectory;
00485             ObjectCreateInfo->Attributes = ObjectAttributes->Attributes & OBJ_VALID_ATTRIBUTES;
00486             if (CreatorMode != KernelMode) ObjectCreateInfo->Attributes &= ~OBJ_KERNEL_HANDLE;
00487             LocalObjectName = ObjectAttributes->ObjectName;
00488             SecurityDescriptor = ObjectAttributes->SecurityDescriptor;
00489             SecurityQos = ObjectAttributes->SecurityQualityOfService;
00490 
00491             /* Check if we have a security descriptor */
00492             if (SecurityDescriptor)
00493             {
00494                 /* Capture it */
00495                 Status = SeCaptureSecurityDescriptor(SecurityDescriptor,
00496                                                      AccessMode,
00497                                                      NonPagedPool,
00498                                                      TRUE,
00499                                                      &ObjectCreateInfo->
00500                                                      SecurityDescriptor);
00501                 if (!NT_SUCCESS(Status))
00502                 {
00503                     /* Capture failed, quit */
00504                     ObjectCreateInfo->SecurityDescriptor = NULL;
00505                     _SEH2_YIELD(return Status);
00506                 }
00507 
00508                 /* Save the probe mode and security descriptor size */
00509                 ObjectCreateInfo->SecurityDescriptorCharge = 2048; /* FIXME */
00510                 ObjectCreateInfo->ProbeMode = AccessMode;
00511             }
00512 
00513             /* Check if we have QoS */
00514             if (SecurityQos)
00515             {
00516                 /* Check if we came from user mode */
00517                 if (AccessMode != KernelMode)
00518                 {
00519                     /* Validate the QoS */
00520                     ProbeForRead(SecurityQos,
00521                                  sizeof(SECURITY_QUALITY_OF_SERVICE),
00522                                  sizeof(ULONG));
00523                 }
00524 
00525                 /* Save Info */
00526                 ObjectCreateInfo->SecurityQualityOfService = *SecurityQos;
00527                 ObjectCreateInfo->SecurityQos =
00528                     &ObjectCreateInfo->SecurityQualityOfService;
00529             }
00530         }
00531         else
00532         {
00533             /* We don't have a name */
00534             LocalObjectName = NULL;
00535         }
00536     }
00537     _SEH2_EXCEPT(ExSystemExceptionFilter())
00538     {
00539         /* Cleanup and return the exception code */
00540         ObpReleaseObjectCreateInformation(ObjectCreateInfo);
00541         _SEH2_YIELD(return _SEH2_GetExceptionCode());
00542     }
00543     _SEH2_END;
00544 
00545     /* Now check if the Object Attributes had an Object Name */
00546     if (LocalObjectName)
00547     {
00548         Status = ObpCaptureObjectName(ObjectName,
00549                                       LocalObjectName,
00550                                       AccessMode,
00551                                       AllocateFromLookaside);
00552     }
00553     else
00554     {
00555         /* Clear the string */
00556         RtlInitEmptyUnicodeString(ObjectName, NULL, 0);
00557 
00558         /* He can't have specified a Root Directory */
00559         if (ObjectCreateInfo->RootDirectory)
00560         {
00561             Status = STATUS_OBJECT_NAME_INVALID;
00562         }
00563     }
00564 
00565     /* Cleanup if we failed */
00566     if (!NT_SUCCESS(Status))
00567     {
00568         ObpReleaseObjectCreateInformation(ObjectCreateInfo);
00569     }
00570 
00571     /* Return status to caller */
00572     return Status;
00573 }
00574 
00575 VOID
00576 NTAPI
00577 ObFreeObjectCreateInfoBuffer(IN POBJECT_CREATE_INFORMATION ObjectCreateInfo)
00578 {
00579     /* Call the macro. We use this function to isolate Ob internals from Io */
00580     ObpFreeCapturedAttributes(ObjectCreateInfo, LookasideCreateInfoList);
00581 }
00582 
00583 NTSTATUS
00584 NTAPI
00585 ObpAllocateObject(IN POBJECT_CREATE_INFORMATION ObjectCreateInfo,
00586                   IN PUNICODE_STRING ObjectName,
00587                   IN POBJECT_TYPE ObjectType,
00588                   IN ULONG ObjectSize,
00589                   IN KPROCESSOR_MODE PreviousMode,
00590                   IN POBJECT_HEADER *ObjectHeader)
00591 {
00592     POBJECT_HEADER Header;
00593     ULONG QuotaSize, HandleSize, NameSize, CreatorSize;
00594     POBJECT_HEADER_HANDLE_INFO HandleInfo;
00595     POBJECT_HEADER_NAME_INFO NameInfo;
00596     POBJECT_HEADER_CREATOR_INFO CreatorInfo;
00597     POBJECT_HEADER_QUOTA_INFO QuotaInfo;
00598     POOL_TYPE PoolType;
00599     ULONG FinalSize;
00600     ULONG Tag;
00601     PAGED_CODE();
00602 
00603     /* Accounting */
00604     ObpObjectsCreated++;
00605 
00606     /* Check if we don't have an Object Type yet */
00607     if (!ObjectType)
00608     {
00609         /* Use default tag and non-paged pool */
00610         PoolType = NonPagedPool;
00611         Tag = 'TjbO';
00612     }
00613     else
00614     {
00615         /* Use the pool and tag given */
00616         PoolType = ObjectType->TypeInfo.PoolType;
00617         Tag = ObjectType->Key;
00618     }
00619 
00620     /* Check if we have no create information (ie: we're an object type) */
00621     if (!ObjectCreateInfo)
00622     {
00623         /* Use defaults */
00624         QuotaSize = HandleSize = 0;
00625         NameSize = sizeof(OBJECT_HEADER_NAME_INFO);
00626         CreatorSize = sizeof(OBJECT_HEADER_CREATOR_INFO);
00627     }
00628     else
00629     {
00630         /* Check if we have quota */
00631         if ((((ObjectCreateInfo->PagedPoolCharge !=
00632                ObjectType->TypeInfo.DefaultPagedPoolCharge) ||
00633               (ObjectCreateInfo->NonPagedPoolCharge !=
00634                ObjectType->TypeInfo.DefaultNonPagedPoolCharge) ||
00635               (ObjectCreateInfo->SecurityDescriptorCharge > 2048)) &&
00636              (PsGetCurrentProcess() != PsInitialSystemProcess)) ||
00637             (ObjectCreateInfo->Attributes & OBJ_EXCLUSIVE))
00638         {
00639             /* Set quota size */
00640             QuotaSize = sizeof(OBJECT_HEADER_QUOTA_INFO);
00641             ObpObjectsWithPoolQuota++;
00642         }
00643         else
00644         {
00645             /* No Quota */
00646             QuotaSize = 0;
00647         }
00648 
00649         /* Check if we have a handle database */
00650         if (ObjectType->TypeInfo.MaintainHandleCount)
00651         {
00652             /* Set handle database size */
00653             HandleSize = sizeof(OBJECT_HEADER_HANDLE_INFO);
00654             ObpObjectsWithHandleDB++;
00655         }
00656         else
00657         {
00658             /* None */
00659             HandleSize = 0;
00660         }
00661 
00662         /* Check if the Object has a name */
00663         if (ObjectName->Buffer)
00664         {
00665             /* Set name size */
00666             NameSize = sizeof(OBJECT_HEADER_NAME_INFO);
00667             ObpObjectsWithName++;
00668         }
00669         else
00670         {
00671             /* No name */
00672             NameSize = 0;
00673         }
00674 
00675         /* Check if the Object maintains type lists */
00676         if (ObjectType->TypeInfo.MaintainTypeList)
00677         {
00678             /* Set owner/creator size */
00679             CreatorSize = sizeof(OBJECT_HEADER_CREATOR_INFO);
00680             ObpObjectsWithCreatorInfo++;
00681         }
00682         else
00683         {
00684             /* No info */
00685             CreatorSize = 0;
00686         }
00687     }
00688 
00689     /* Set final header size */
00690     FinalSize = QuotaSize +
00691                 HandleSize +
00692                 NameSize +
00693                 CreatorSize +
00694                 FIELD_OFFSET(OBJECT_HEADER, Body);
00695 
00696     /* Allocate memory for the Object and Header */
00697     Header = ExAllocatePoolWithTag(PoolType, FinalSize + ObjectSize, Tag);
00698     if (!Header) return STATUS_INSUFFICIENT_RESOURCES;
00699 
00700     /* Check if we have a quota header */
00701     if (QuotaSize)
00702     {
00703         /* Initialize quota info */
00704         QuotaInfo = (POBJECT_HEADER_QUOTA_INFO)Header;
00705         QuotaInfo->PagedPoolCharge = ObjectCreateInfo->PagedPoolCharge;
00706         QuotaInfo->NonPagedPoolCharge = ObjectCreateInfo->NonPagedPoolCharge;
00707         QuotaInfo->SecurityDescriptorCharge = ObjectCreateInfo->SecurityDescriptorCharge;
00708         QuotaInfo->ExclusiveProcess = NULL;
00709         Header = (POBJECT_HEADER)(QuotaInfo + 1);
00710     }
00711 
00712     /* Check if we have a handle database header */
00713     if (HandleSize)
00714     {
00715         /* Initialize Handle Info */
00716         HandleInfo = (POBJECT_HEADER_HANDLE_INFO)Header;
00717         HandleInfo->SingleEntry.HandleCount = 0;
00718         Header = (POBJECT_HEADER)(HandleInfo + 1);
00719     }
00720 
00721     /* Check if we have a name header */
00722     if (NameSize)
00723     {
00724         /* Initialize the Object Name Info */
00725         NameInfo = (POBJECT_HEADER_NAME_INFO)Header;
00726         NameInfo->Name = *ObjectName;
00727         NameInfo->Directory = NULL;
00728         NameInfo->QueryReferences = 1;
00729 
00730         /* Check if this is a call with the special protection flag */
00731         if ((PreviousMode == KernelMode) &&
00732             (ObjectCreateInfo) &&
00733             (ObjectCreateInfo->Attributes & 0x10000))
00734         {
00735             /* Set flag which will make the object protected from user-mode */
00736             NameInfo->QueryReferences |= 0x40000000;
00737         }
00738 
00739         /* Set the header pointer */
00740         Header = (POBJECT_HEADER)(NameInfo + 1);
00741     }
00742 
00743     /* Check if we have a creator header */
00744     if (CreatorSize)
00745     {
00746         /* Initialize Creator Info */
00747         CreatorInfo = (POBJECT_HEADER_CREATOR_INFO)Header;
00748         CreatorInfo->CreatorBackTraceIndex = 0;
00749         CreatorInfo->CreatorUniqueProcess = PsGetCurrentProcessId();
00750         InitializeListHead(&CreatorInfo->TypeList);
00751         Header = (POBJECT_HEADER)(CreatorInfo + 1);
00752     }
00753 
00754     /* Check for quota information */
00755     if (QuotaSize)
00756     {
00757         /* Set the offset */
00758         Header->QuotaInfoOffset = (UCHAR)(QuotaSize +
00759                                           HandleSize +
00760                                           NameSize +
00761                                           CreatorSize);
00762     }
00763     else
00764     {
00765         /* No offset */
00766         Header->QuotaInfoOffset = 0;
00767     }
00768 
00769     /* Check for handle information */
00770     if (HandleSize)
00771     {
00772         /* Set the offset */
00773         Header->HandleInfoOffset = (UCHAR)(HandleSize +
00774                                            NameSize +
00775                                            CreatorSize);
00776     }
00777     else
00778     {
00779         /* No offset */
00780         Header->HandleInfoOffset = 0;
00781     }
00782 
00783     /* Check for name information */
00784     if (NameSize)
00785     {
00786         /* Set the offset */
00787         Header->NameInfoOffset = (UCHAR)(NameSize + CreatorSize);
00788     }
00789     else
00790     {
00791         /* No Name */
00792         Header->NameInfoOffset = 0;
00793     }
00794 
00795     /* Set the new object flag */
00796     Header->Flags = OB_FLAG_CREATE_INFO;
00797 
00798     /* Remember if we have creator info */
00799     if (CreatorSize) Header->Flags |= OB_FLAG_CREATOR_INFO;
00800 
00801     /* Remember if we have handle info */
00802     if (HandleSize) Header->Flags |= OB_FLAG_SINGLE_PROCESS;
00803 
00804     /* Initialize the object header */
00805     Header->PointerCount = 1;
00806     Header->HandleCount = 0;
00807     Header->Type = ObjectType;
00808     Header->ObjectCreateInfo = ObjectCreateInfo;
00809     Header->SecurityDescriptor = NULL;
00810 
00811     /* Check if this is a permanent object */
00812     if ((ObjectCreateInfo) && (ObjectCreateInfo->Attributes & OBJ_PERMANENT))
00813     {
00814         /* Set the needed flag so we can check */
00815         Header->Flags |= OB_FLAG_PERMANENT;
00816     }
00817 
00818     /* Check if this is an exclusive object */
00819     if ((ObjectCreateInfo) && (ObjectCreateInfo->Attributes & OBJ_EXCLUSIVE))
00820     {
00821         /* Set the needed flag so we can check */
00822         Header->Flags |= OB_FLAG_EXCLUSIVE;
00823     }
00824 
00825     /* Set kernel-mode flag */
00826     if (PreviousMode == KernelMode) Header->Flags |= OB_FLAG_KERNEL_MODE;
00827 
00828     /* Check if we have a type */
00829     if (ObjectType)
00830     {
00831         /* Increase the number of objects of this type */
00832         InterlockedIncrement((PLONG)&ObjectType->TotalNumberOfObjects);
00833 
00834         /* Update the high water */
00835         ObjectType->HighWaterNumberOfObjects = max(ObjectType->
00836                                                    TotalNumberOfObjects,
00837                                                    ObjectType->
00838                                                    HighWaterNumberOfObjects);
00839     }
00840 
00841     /* Return Header */
00842     *ObjectHeader = Header;
00843     return STATUS_SUCCESS;
00844 }
00845 
00846 NTSTATUS
00847 NTAPI
00848 ObQueryTypeInfo(IN POBJECT_TYPE ObjectType,
00849                 OUT POBJECT_TYPE_INFORMATION ObjectTypeInfo,
00850                 IN ULONG Length,
00851                 OUT PULONG ReturnLength)
00852 {
00853     NTSTATUS Status = STATUS_SUCCESS;
00854     PWSTR InfoBuffer;
00855 
00856     /* Enter SEH */
00857     _SEH2_TRY
00858     {
00859         /* Set return length aligned to 4-byte boundary */
00860         *ReturnLength += sizeof(*ObjectTypeInfo) +
00861                          ALIGN_UP(ObjectType->Name.MaximumLength, ULONG);
00862 
00863         /* Check if thats too much though. */
00864         if (Length < *ReturnLength)
00865         {
00866             _SEH2_YIELD(return STATUS_INFO_LENGTH_MISMATCH);
00867         }
00868 
00869         /* Build the data */
00870         ObjectTypeInfo->TotalNumberOfHandles =
00871             ObjectType->TotalNumberOfHandles;
00872         ObjectTypeInfo->TotalNumberOfObjects =
00873             ObjectType->TotalNumberOfObjects;
00874         ObjectTypeInfo->HighWaterNumberOfHandles =
00875             ObjectType->HighWaterNumberOfHandles;
00876         ObjectTypeInfo->HighWaterNumberOfObjects =
00877             ObjectType->HighWaterNumberOfObjects;
00878         ObjectTypeInfo->PoolType =
00879             ObjectType->TypeInfo.PoolType;
00880         ObjectTypeInfo->DefaultNonPagedPoolCharge =
00881             ObjectType->TypeInfo.DefaultNonPagedPoolCharge;
00882         ObjectTypeInfo->DefaultPagedPoolCharge =
00883             ObjectType->TypeInfo.DefaultPagedPoolCharge;
00884         ObjectTypeInfo->ValidAccessMask =
00885             ObjectType->TypeInfo.ValidAccessMask;
00886         ObjectTypeInfo->SecurityRequired =
00887             ObjectType->TypeInfo.SecurityRequired;
00888         ObjectTypeInfo->InvalidAttributes =
00889             ObjectType->TypeInfo.InvalidAttributes;
00890         ObjectTypeInfo->GenericMapping =
00891             ObjectType->TypeInfo.GenericMapping;
00892         ObjectTypeInfo->MaintainHandleCount =
00893             ObjectType->TypeInfo.MaintainHandleCount;
00894 
00895         /* Setup the name buffer */
00896         InfoBuffer = (PWSTR)(ObjectTypeInfo + 1);
00897         ObjectTypeInfo->TypeName.Buffer = InfoBuffer;
00898         ObjectTypeInfo->TypeName.MaximumLength = ObjectType->Name.MaximumLength;
00899         ObjectTypeInfo->TypeName.Length = ObjectType->Name.Length;
00900 
00901         /* Copy it */
00902         RtlCopyMemory(InfoBuffer,
00903                       ObjectType->Name.Buffer,
00904                       ObjectType->Name.Length);
00905 
00906         /* Null-terminate it */
00907         (InfoBuffer)[ObjectType->Name.Length / sizeof(WCHAR)] = UNICODE_NULL;
00908     }
00909     _SEH2_EXCEPT(ExSystemExceptionFilter())
00910     {
00911         /* Otherwise, get the exception code */
00912         Status = _SEH2_GetExceptionCode();
00913     }
00914     _SEH2_END;
00915 
00916     /* Return status to caller */
00917     return Status;
00918 }
00919 
00920 
00921 /* PUBLIC FUNCTIONS **********************************************************/
00922 
00923 NTSTATUS
00924 NTAPI
00925 ObCreateObject(IN KPROCESSOR_MODE ProbeMode OPTIONAL,
00926                IN POBJECT_TYPE Type,
00927                IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
00928                IN KPROCESSOR_MODE AccessMode,
00929                IN OUT PVOID ParseContext OPTIONAL,
00930                IN ULONG ObjectSize,
00931                IN ULONG PagedPoolCharge OPTIONAL,
00932                IN ULONG NonPagedPoolCharge OPTIONAL,
00933                OUT PVOID *Object)
00934 {
00935     NTSTATUS Status;
00936     POBJECT_CREATE_INFORMATION ObjectCreateInfo;
00937     UNICODE_STRING ObjectName;
00938     POBJECT_HEADER Header;
00939 
00940     /* Allocate a capture buffer */
00941     ObjectCreateInfo = ObpAllocateObjectCreateInfoBuffer(LookasideCreateInfoList);
00942     if (!ObjectCreateInfo) return STATUS_INSUFFICIENT_RESOURCES;
00943 
00944     /* Capture all the info */
00945     Status = ObpCaptureObjectCreateInformation(ObjectAttributes,
00946                                                ProbeMode,
00947                                                AccessMode,
00948                                                FALSE,
00949                                                ObjectCreateInfo,
00950                                                &ObjectName);
00951     if (NT_SUCCESS(Status))
00952     {
00953         /* Validate attributes */
00954         if (Type->TypeInfo.InvalidAttributes & ObjectCreateInfo->Attributes)
00955         {
00956             /* Fail */
00957             Status = STATUS_INVALID_PARAMETER;
00958         }
00959         else
00960         {
00961             /* Check if we have a paged charge */
00962             if (!PagedPoolCharge)
00963             {
00964                 /* Save it */
00965                 PagedPoolCharge = Type->TypeInfo.DefaultPagedPoolCharge;
00966             }
00967 
00968             /* Check for nonpaged charge */
00969             if (!NonPagedPoolCharge)
00970             {
00971                 /* Save it */
00972                 NonPagedPoolCharge = Type->TypeInfo.DefaultNonPagedPoolCharge;
00973             }
00974 
00975             /* Write the pool charges */
00976             ObjectCreateInfo->PagedPoolCharge = PagedPoolCharge;
00977             ObjectCreateInfo->NonPagedPoolCharge = NonPagedPoolCharge;
00978 
00979             /* Allocate the Object */
00980             Status = ObpAllocateObject(ObjectCreateInfo,
00981                                        &ObjectName,
00982                                        Type,
00983                                        ObjectSize,
00984                                        AccessMode,
00985                                        &Header);
00986             if (NT_SUCCESS(Status))
00987             {
00988                 /* Return the Object */
00989                 *Object = &Header->Body;
00990 
00991                 /* Check if this is a permanent object */
00992                 if (Header->Flags & OB_FLAG_PERMANENT)
00993                 {
00994                     /* Do the privilege check */
00995                     if (!SeSinglePrivilegeCheck(SeCreatePermanentPrivilege,
00996                                                 ProbeMode))
00997                     {
00998                         /* Fail */
00999                         ObpDeallocateObject(*Object);
01000                         Status = STATUS_PRIVILEGE_NOT_HELD;
01001                     }
01002                 }
01003 
01004                 /* Return status */
01005                 return Status;
01006             }
01007         }
01008 
01009         /* Release the Capture Info, we don't need it */
01010         ObpFreeObjectCreateInformation(ObjectCreateInfo);
01011         if (ObjectName.Buffer) ObpFreeObjectNameBuffer(&ObjectName);
01012     }
01013 
01014     /* We failed, so release the Buffer */
01015     ObpFreeCapturedAttributes(ObjectCreateInfo, LookasideCreateInfoList);
01016     return Status;
01017 }
01018 
01019 NTSTATUS
01020 NTAPI
01021 ObCreateObjectType(IN PUNICODE_STRING TypeName,
01022                    IN POBJECT_TYPE_INITIALIZER ObjectTypeInitializer,
01023                    IN PVOID Reserved,
01024                    OUT POBJECT_TYPE *ObjectType)
01025 {
01026     POBJECT_HEADER Header;
01027     POBJECT_TYPE LocalObjectType;
01028     ULONG HeaderSize;
01029     NTSTATUS Status;
01030     CHAR Tag[4];
01031     OBP_LOOKUP_CONTEXT Context;
01032     PWCHAR p;
01033     ULONG i;
01034     UNICODE_STRING ObjectName;
01035     POBJECT_HEADER_CREATOR_INFO CreatorInfo;
01036 
01037     /* Verify parameters */
01038     if (!(TypeName) ||
01039         !(TypeName->Length) ||
01040         (TypeName->Length % sizeof(WCHAR)) ||
01041         !(ObjectTypeInitializer) ||
01042         (ObjectTypeInitializer->Length != sizeof(*ObjectTypeInitializer)) ||
01043         (ObjectTypeInitializer->InvalidAttributes & ~OBJ_VALID_ATTRIBUTES) ||
01044         (ObjectTypeInitializer->MaintainHandleCount &&
01045          (!(ObjectTypeInitializer->OpenProcedure) &&
01046           !ObjectTypeInitializer->CloseProcedure)) ||
01047         ((!ObjectTypeInitializer->UseDefaultObject) &&
01048          (ObjectTypeInitializer->PoolType != NonPagedPool)))
01049     {
01050         /* Fail */
01051         return STATUS_INVALID_PARAMETER;
01052     }
01053 
01054     /* Make sure the name doesn't have a separator */
01055     p = TypeName->Buffer;
01056     i = TypeName->Length / sizeof(WCHAR);
01057     while (i--)
01058     {
01059         /* Check for one and fail */
01060         if (*p++ == OBJ_NAME_PATH_SEPARATOR) return STATUS_OBJECT_NAME_INVALID;
01061     }
01062 
01063     /* Setup a lookup context */
01064     ObpInitializeLookupContext(&Context);
01065 
01066     /* Check if we've already created the directory of types */
01067     if (ObpTypeDirectoryObject)
01068     {
01069         /* Acquire the directory lock */
01070         ObpAcquireDirectoryLockExclusive(ObpTypeDirectoryObject, &Context);
01071 
01072         /* Do the lookup */
01073         if (ObpLookupEntryDirectory(ObpTypeDirectoryObject,
01074                                     TypeName,
01075                                     OBJ_CASE_INSENSITIVE,
01076                                     FALSE,
01077                                     &Context))
01078         {
01079             /* We have already created it, so fail */
01080             ObpReleaseLookupContext(&Context);
01081             return STATUS_OBJECT_NAME_COLLISION;
01082         }
01083     }
01084 
01085     /* Now make a copy of the object name */
01086     ObjectName.Buffer = ExAllocatePoolWithTag(PagedPool,
01087                                               TypeName->MaximumLength,
01088                                               OB_NAME_TAG);
01089     if (!ObjectName.Buffer)
01090     {
01091         /* Out of memory, fail */
01092         ObpReleaseLookupContext(&Context);
01093         return STATUS_INSUFFICIENT_RESOURCES;
01094     }
01095 
01096     /* Set the length and copy the name */
01097     ObjectName.MaximumLength = TypeName->MaximumLength;
01098     RtlCopyUnicodeString(&ObjectName, TypeName);
01099 
01100     /* Allocate the Object */
01101     Status = ObpAllocateObject(NULL,
01102                                &ObjectName,
01103                                ObpTypeObjectType,
01104                                sizeof(OBJECT_TYPE),
01105                                KernelMode,
01106                                &Header);
01107     if (!NT_SUCCESS(Status))
01108     {
01109         /* Free the name and fail */
01110         ObpReleaseLookupContext(&Context);
01111         ExFreePool(ObjectName.Buffer);
01112         return Status;
01113     }
01114 
01115     /* Setup the flags and name */
01116     LocalObjectType = (POBJECT_TYPE)&Header->Body;
01117     LocalObjectType->Name = ObjectName;
01118     Header->Flags |= OB_FLAG_KERNEL_MODE | OB_FLAG_PERMANENT;
01119 
01120     /* Clear accounting data */
01121     LocalObjectType->TotalNumberOfObjects =
01122     LocalObjectType->TotalNumberOfHandles =
01123     LocalObjectType->HighWaterNumberOfObjects =
01124     LocalObjectType->HighWaterNumberOfHandles = 0;
01125 
01126     /* Check if this is the first Object Type */
01127     if (!ObpTypeObjectType)
01128     {
01129         /* It is, so set this as the type object */
01130         ObpTypeObjectType = LocalObjectType;
01131         Header->Type = ObpTypeObjectType;
01132 
01133         /* Set the hard-coded key and object count */
01134         LocalObjectType->TotalNumberOfObjects = 1;
01135         LocalObjectType->Key = 'TjbO';
01136     }
01137     else
01138     {
01139         /* Set Tag */
01140         Tag[0] = (CHAR)TypeName->Buffer[0];
01141         Tag[1] = (CHAR)TypeName->Buffer[1];
01142         Tag[2] = (CHAR)TypeName->Buffer[2];
01143         Tag[3] = (CHAR)TypeName->Buffer[3];
01144         LocalObjectType->Key = *(PULONG)Tag;
01145     }
01146 
01147     /* Set up the type information */
01148     LocalObjectType->TypeInfo = *ObjectTypeInitializer;
01149     LocalObjectType->TypeInfo.PoolType = ObjectTypeInitializer->PoolType;
01150 
01151     /* Check if we have to maintain a type list */
01152     if (NtGlobalFlag & FLG_MAINTAIN_OBJECT_TYPELIST)
01153     {
01154         /* Enable support */
01155         LocalObjectType->TypeInfo.MaintainTypeList = TRUE;
01156     }
01157 
01158     /* Calculate how much space our header'll take up */
01159     HeaderSize = sizeof(OBJECT_HEADER) +
01160                  sizeof(OBJECT_HEADER_NAME_INFO) +
01161                  (ObjectTypeInitializer->MaintainHandleCount ?
01162                   sizeof(OBJECT_HEADER_HANDLE_INFO) : 0);
01163 
01164     /* Check the pool type */
01165     if (ObjectTypeInitializer->PoolType == NonPagedPool)
01166     {
01167         /* Update the NonPaged Pool charge */
01168         LocalObjectType->TypeInfo.DefaultNonPagedPoolCharge += HeaderSize;
01169     }
01170     else
01171     {
01172         /* Update the Paged Pool charge */
01173         LocalObjectType->TypeInfo.DefaultPagedPoolCharge += HeaderSize;
01174     }
01175 
01176     /* All objects types need a security procedure */
01177     if (!ObjectTypeInitializer->SecurityProcedure)
01178     {
01179         LocalObjectType->TypeInfo.SecurityProcedure = SeDefaultObjectMethod;
01180     }
01181 
01182     /* Select the Wait Object */
01183     if (LocalObjectType->TypeInfo.UseDefaultObject)
01184     {
01185         /* Add the SYNCHRONIZE access mask since it's waitable */
01186         LocalObjectType->TypeInfo.ValidAccessMask |= SYNCHRONIZE;
01187 
01188         /* Use the "Default Object", a simple event */
01189         LocalObjectType->DefaultObject = &ObpDefaultObject;
01190     }
01191     /* The File Object gets an optimized hack so it can be waited on */
01192     else if ((TypeName->Length == 8) && !(wcscmp(TypeName->Buffer, L"File")))
01193     {
01194         /* Wait on the File Object's event directly */
01195         LocalObjectType->DefaultObject = (PVOID)FIELD_OFFSET(FILE_OBJECT,
01196                                                              Event);
01197     }
01198     else if ((TypeName->Length == 24) && !(wcscmp(TypeName->Buffer, L"WaitablePort")))
01199     {
01200         /* Wait on the LPC Port's object directly */
01201         LocalObjectType->DefaultObject = (PVOID)FIELD_OFFSET(LPCP_PORT_OBJECT,
01202                                                              WaitEvent);
01203     }
01204     else
01205     {
01206         /* No default Object */
01207         LocalObjectType->DefaultObject = NULL;
01208     }
01209 
01210     /* Initialize Object Type components */
01211     ExInitializeResourceLite(&LocalObjectType->Mutex);
01212     for (i = 0; i < 4; i++)
01213     {
01214         /* Initialize the object locks */
01215         ExInitializeResourceLite(&LocalObjectType->ObjectLocks[i]);
01216     }
01217     InitializeListHead(&LocalObjectType->TypeList);
01218 
01219     /* Lock the object type */
01220     ObpEnterObjectTypeMutex(LocalObjectType);
01221 
01222     /* Get creator info and insert it into the type list */
01223     CreatorInfo = OBJECT_HEADER_TO_CREATOR_INFO(Header);
01224     if (CreatorInfo) InsertTailList(&ObpTypeObjectType->TypeList,
01225                                     &CreatorInfo->TypeList);
01226 
01227     /* Set the index and the entry into the object type array */
01228     LocalObjectType->Index = ObpTypeObjectType->TotalNumberOfObjects;
01229     if (LocalObjectType->Index < 32)
01230     {
01231         /* It fits, insert it */
01232         ObpObjectTypes[LocalObjectType->Index - 1] = LocalObjectType;
01233     }
01234 
01235     /* Release the object type */
01236     ObpLeaveObjectTypeMutex(LocalObjectType);
01237 
01238     /* Check if we're actually creating the directory object itself */
01239     if (!(ObpTypeDirectoryObject) ||
01240         (ObpInsertEntryDirectory(ObpTypeDirectoryObject, &Context, Header)))
01241     {
01242         /* Check if the type directory exists */
01243         if (ObpTypeDirectoryObject)
01244         {
01245             /* Reference it */
01246             ObReferenceObject(ObpTypeDirectoryObject);
01247         }
01248 
01249         /* Cleanup the lookup context */
01250         ObpReleaseLookupContext(&Context);
01251 
01252         /* Return the object type and success */
01253         *ObjectType = LocalObjectType;
01254         return STATUS_SUCCESS;
01255     }
01256 
01257     /* If we got here, then we failed */
01258     ObpReleaseLookupContext(&Context);
01259     return STATUS_INSUFFICIENT_RESOURCES;
01260 }
01261 
01262 VOID
01263 NTAPI
01264 ObpDeleteObjectType(IN PVOID Object)
01265 {
01266     ULONG i;
01267     POBJECT_TYPE ObjectType = (PVOID)Object;
01268 
01269     /* Loop our locks */
01270     for (i = 0; i < 4; i++)
01271     {
01272         /* Delete each one */
01273         ExDeleteResourceLite(&ObjectType->ObjectLocks[i]);
01274     }
01275 
01276     /* Delete our main mutex */
01277     ExDeleteResourceLite(&ObjectType->Mutex);
01278 }
01279 
01280 /*++
01281 * @name ObMakeTemporaryObject
01282 * @implemented NT4
01283 *
01284 *     The ObMakeTemporaryObject routine <FILLMEIN>
01285 *
01286 * @param ObjectBody
01287 *        <FILLMEIN>
01288 *
01289 * @return None.
01290 *
01291 * @remarks None.
01292 *
01293 *--*/
01294 VOID
01295 NTAPI
01296 ObMakeTemporaryObject(IN PVOID ObjectBody)
01297 {
01298     PAGED_CODE();
01299 
01300     /* Call the internal API */
01301     ObpSetPermanentObject(ObjectBody, FALSE);
01302 }
01303 
01304 /*++
01305 * @name NtMakeTemporaryObject
01306 * @implemented NT4
01307 *
01308 *     The NtMakeTemporaryObject routine <FILLMEIN>
01309 *
01310 * @param ObjectHandle
01311 *        <FILLMEIN>
01312 *
01313 * @return STATUS_SUCCESS or appropriate error value.
01314 *
01315 * @remarks None.
01316 *
01317 *--*/
01318 NTSTATUS
01319 NTAPI
01320 NtMakeTemporaryObject(IN HANDLE ObjectHandle)
01321 {
01322     PVOID ObjectBody;
01323     NTSTATUS Status;
01324     PAGED_CODE();
01325 
01326     /* Reference the object for DELETE access */
01327     Status = ObReferenceObjectByHandle(ObjectHandle,
01328                                        DELETE,
01329                                        NULL,
01330                                        KeGetPreviousMode(),
01331                                        &ObjectBody,
01332                                        NULL);
01333     if (Status != STATUS_SUCCESS) return Status;
01334 
01335     /* Set it as temporary and dereference it */
01336     ObpSetPermanentObject(ObjectBody, FALSE);
01337     ObDereferenceObject(ObjectBody);
01338     return STATUS_SUCCESS;
01339 }
01340 
01341 /*++
01342 * @name NtMakePermanentObject
01343 * @implemented NT4
01344 *
01345 *     The NtMakePermanentObject routine <FILLMEIN>
01346 *
01347 * @param ObjectHandle
01348 *        <FILLMEIN>
01349 *
01350 * @return STATUS_SUCCESS or appropriate error value.
01351 *
01352 * @remarks None.
01353 *
01354 *--*/
01355 NTSTATUS
01356 NTAPI
01357 NtMakePermanentObject(IN HANDLE ObjectHandle)
01358 {
01359     PVOID ObjectBody;
01360     NTSTATUS Status;
01361     KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
01362     PAGED_CODE();
01363 
01364     /* Make sure that the caller has SeCreatePermanentPrivilege */
01365     Status = SeSinglePrivilegeCheck(SeCreatePermanentPrivilege,
01366                                     PreviousMode);
01367     if (!NT_SUCCESS(Status)) return STATUS_PRIVILEGE_NOT_HELD;
01368 
01369     /* Reference the object */
01370     Status = ObReferenceObjectByHandle(ObjectHandle,
01371                                        0,
01372                                        NULL,
01373                                        PreviousMode,
01374                                        &ObjectBody,
01375                                        NULL);
01376     if (Status != STATUS_SUCCESS) return Status;
01377 
01378     /* Set it as permanent and dereference it */
01379     ObpSetPermanentObject(ObjectBody, TRUE);
01380     ObDereferenceObject(ObjectBody);
01381     return STATUS_SUCCESS;
01382 }
01383 
01384 /*++
01385 * @name NtQueryObject
01386 * @implemented NT4
01387 *
01388 *     The NtQueryObject routine <FILLMEIN>
01389 *
01390 * @param ObjectHandle
01391 *        <FILLMEIN>
01392 *
01393 * @param ObjectInformationClass
01394 *        <FILLMEIN>
01395 *
01396 * @param ObjectInformation
01397 *        <FILLMEIN>
01398 *
01399 * @param Length
01400 *        <FILLMEIN>
01401 *
01402 * @param ResultLength
01403 *        <FILLMEIN>
01404 *
01405 * @return STATUS_SUCCESS or appropriate error value.
01406 *
01407 * @remarks None.
01408 *
01409 *--*/
01410 NTSTATUS
01411 NTAPI
01412 NtQueryObject(IN HANDLE ObjectHandle,
01413               IN OBJECT_INFORMATION_CLASS ObjectInformationClass,
01414               OUT PVOID ObjectInformation,
01415               IN ULONG Length,
01416               OUT PULONG ResultLength OPTIONAL)
01417 {
01418     OBJECT_HANDLE_INFORMATION HandleInfo;
01419     POBJECT_HEADER ObjectHeader = NULL;
01420     POBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleFlags;
01421     POBJECT_BASIC_INFORMATION BasicInfo;
01422     ULONG InfoLength;
01423     PVOID Object = NULL;
01424     NTSTATUS Status;
01425     KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
01426     PAGED_CODE();
01427 
01428     /* Check if the caller is from user mode */
01429     if (PreviousMode != KernelMode)
01430     {
01431         /* Protect validation with SEH */
01432         _SEH2_TRY
01433         {
01434             /* Probe the input structure */
01435             ProbeForWrite(ObjectInformation, Length, sizeof(UCHAR));
01436 
01437             /* If we have a result length, probe it too */
01438             if (ResultLength) ProbeForWriteUlong(ResultLength);
01439         }
01440         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
01441         {
01442             /* Return the exception code */
01443             _SEH2_YIELD(return _SEH2_GetExceptionCode());
01444         }
01445         _SEH2_END;
01446     }
01447 
01448     /*
01449      * Make sure this isn't a generic type query, since the caller doesn't
01450      * have to give a handle for it
01451      */
01452     if (ObjectInformationClass != ObjectTypesInformation)
01453     {
01454         /* Reference the object */
01455         Status = ObReferenceObjectByHandle(ObjectHandle,
01456                                            0,
01457                                            NULL,
01458                                            KeGetPreviousMode(),
01459                                            &Object,
01460                                            &HandleInfo);
01461         if (!NT_SUCCESS (Status)) return Status;
01462 
01463         /* Get the object header */
01464         ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
01465     }
01466 
01467     _SEH2_TRY
01468     {
01469         /* Check the information class */
01470         switch (ObjectInformationClass)
01471         {
01472             /* Basic info */
01473             case ObjectBasicInformation:
01474 
01475                 /* Validate length */
01476                 InfoLength = sizeof(OBJECT_BASIC_INFORMATION);
01477                 if (Length != sizeof(OBJECT_BASIC_INFORMATION))
01478                 {
01479                     /* Fail */
01480                     Status = STATUS_INFO_LENGTH_MISMATCH;
01481                     break;
01482                 }
01483 
01484                 /* Fill out the basic information */
01485                 BasicInfo = (POBJECT_BASIC_INFORMATION)ObjectInformation;
01486                 BasicInfo->Attributes = HandleInfo.HandleAttributes;
01487                 BasicInfo->GrantedAccess = HandleInfo.GrantedAccess;
01488                 BasicInfo->HandleCount = ObjectHeader->HandleCount;
01489                 BasicInfo->PointerCount = ObjectHeader->PointerCount;
01490 
01491                 /* Permanent/Exclusive Flags are NOT in Handle attributes! */
01492                 if (ObjectHeader->Flags & OB_FLAG_EXCLUSIVE)
01493                 {
01494                     /* Set the flag */
01495                     BasicInfo->Attributes |= OBJ_EXCLUSIVE;
01496                 }
01497                 if (ObjectHeader->Flags & OB_FLAG_PERMANENT)
01498                 {
01499                     /* Set the flag */
01500                     BasicInfo->Attributes |= OBJ_PERMANENT;
01501                 }
01502 
01503                 /* Copy quota information */
01504                 BasicInfo->PagedPoolCharge = 0; /* FIXME*/
01505                 BasicInfo->NonPagedPoolCharge = 0; /* FIXME*/
01506 
01507                 /* Copy name information */
01508                 BasicInfo->NameInfoSize = 0; /* FIXME*/
01509                 BasicInfo->TypeInfoSize = 0; /* FIXME*/
01510 
01511                 /* Copy security information */
01512                 BasicInfo->SecurityDescriptorSize = 0; /* FIXME*/
01513 
01514                 /* Check if this is a symlink */
01515                 if (ObjectHeader->Type == ObSymbolicLinkType)
01516                 {
01517                     /* Return the creation time */
01518                     BasicInfo->CreationTime.QuadPart =
01519                         ((POBJECT_SYMBOLIC_LINK)Object)->CreationTime.QuadPart;
01520                 }
01521                 else
01522                 {
01523                     /* Otherwise return 0 */
01524                     BasicInfo->CreationTime.QuadPart = (ULONGLONG)0;
01525                 }
01526 
01527                 /* Break out with success */
01528                 Status = STATUS_SUCCESS;
01529                 break;
01530 
01531             /* Name information */
01532             case ObjectNameInformation:
01533 
01534                 /* Call the helper and break out */
01535                 Status = ObQueryNameString(Object,
01536                                            (POBJECT_NAME_INFORMATION)
01537                                            ObjectInformation,
01538                                            Length,
01539                                            &InfoLength);
01540                 break;
01541 
01542             /* Information about this type */
01543             case ObjectTypeInformation:
01544 
01545                 /* Call the helper and break out */
01546                 Status = ObQueryTypeInfo(ObjectHeader->Type,
01547                                          (POBJECT_TYPE_INFORMATION)
01548                                          ObjectInformation,
01549                                          Length,
01550                                          &InfoLength);
01551                 break;
01552 
01553             /* Information about all types */
01554             case ObjectTypesInformation:
01555                 DPRINT1("NOT IMPLEMENTED!\n");
01556                 InfoLength = Length;
01557                 Status = STATUS_NOT_IMPLEMENTED;
01558                 break;
01559 
01560             /* Information about the handle flags */
01561             case ObjectHandleFlagInformation:
01562 
01563                 /* Validate length */
01564                 InfoLength = sizeof (OBJECT_HANDLE_ATTRIBUTE_INFORMATION);
01565                 if (Length != sizeof (OBJECT_HANDLE_ATTRIBUTE_INFORMATION))
01566                 {
01567                     Status = STATUS_INFO_LENGTH_MISMATCH;
01568                     break;
01569                 }
01570 
01571                 /* Get the structure */
01572                 HandleFlags = (POBJECT_HANDLE_ATTRIBUTE_INFORMATION)
01573                                ObjectInformation;
01574 
01575                 /* Set the flags */
01576                 HandleFlags->Inherit = HandleInfo.HandleAttributes & OBJ_INHERIT;
01577                 HandleFlags->ProtectFromClose = (HandleInfo.HandleAttributes &
01578                                                  OBJ_PROTECT_CLOSE) != 0;
01579 
01580                 /* Break out with success */
01581                 Status = STATUS_SUCCESS;
01582                 break;
01583 
01584             /* Anything else */
01585             default:
01586 
01587                 /* Fail it */
01588                 InfoLength = Length;
01589                 Status = STATUS_INVALID_INFO_CLASS;
01590                 break;
01591         }
01592 
01593         /* Check if the caller wanted the return length */
01594         if (ResultLength)
01595         {
01596             /* Write the length */
01597             *ResultLength = InfoLength;
01598         }
01599     }
01600     _SEH2_EXCEPT(ExSystemExceptionFilter())
01601     {
01602         /* Otherwise, get the exception code */
01603         Status = _SEH2_GetExceptionCode();
01604     }
01605     _SEH2_END;
01606 
01607     /* Dereference the object if we had referenced it */
01608     if (Object) ObDereferenceObject(Object);
01609 
01610     /* Return status */
01611     return Status;
01612 }
01613 
01614 /*++
01615 * @name NtSetInformationObject
01616 * @implemented NT4
01617 *
01618 *     The NtSetInformationObject routine <FILLMEIN>
01619 *
01620 * @param ObjectHandle
01621 *        <FILLMEIN>
01622 *
01623 * @param ObjectInformationClass
01624 *        <FILLMEIN>
01625 *
01626 * @param ObjectInformation
01627 *        <FILLMEIN>
01628 *
01629 * @param Length
01630 *        <FILLMEIN>
01631 *
01632 * @return STATUS_SUCCESS or appropriate error value.
01633 *
01634 * @remarks None.
01635 *
01636 *--*/
01637 NTSTATUS
01638 NTAPI
01639 NtSetInformationObject(IN HANDLE ObjectHandle,
01640                        IN OBJECT_INFORMATION_CLASS ObjectInformationClass,
01641                        IN PVOID ObjectInformation,
01642                        IN ULONG Length)
01643 {
01644     NTSTATUS Status;
01645     OBP_SET_HANDLE_ATTRIBUTES_CONTEXT Context;
01646     PVOID ObjectTable;
01647     KAPC_STATE ApcState;
01648     POBJECT_DIRECTORY Directory;
01649     KPROCESSOR_MODE PreviousMode;
01650     BOOLEAN AttachedToProcess = FALSE;
01651     PAGED_CODE();
01652 
01653     /* Validate the information class */
01654     switch (ObjectInformationClass)
01655     {
01656         case ObjectHandleFlagInformation:
01657         
01658             /* Validate the length */
01659             if (Length != sizeof(OBJECT_HANDLE_ATTRIBUTE_INFORMATION))
01660             {
01661                 /* Invalid length */
01662                 return STATUS_INFO_LENGTH_MISMATCH;
01663             }
01664             
01665             /* Save the previous mode */
01666             Context.PreviousMode = ExGetPreviousMode();
01667 
01668             /* Check if we were called from user mode */
01669             if (Context.PreviousMode != KernelMode)
01670             {
01671                 /* Enter SEH */
01672                 _SEH2_TRY
01673                 {
01674                     /* Probe and capture the attribute buffer */
01675                     ProbeForRead(ObjectInformation,
01676                                  sizeof(OBJECT_HANDLE_ATTRIBUTE_INFORMATION),
01677                                  sizeof(BOOLEAN));
01678                     Context.Information = *(POBJECT_HANDLE_ATTRIBUTE_INFORMATION)
01679                                             ObjectInformation;
01680                 }
01681                 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
01682                 {
01683                     /* Return the exception code */
01684                     _SEH2_YIELD(return _SEH2_GetExceptionCode());
01685                 }
01686                 _SEH2_END;
01687             }
01688             else
01689             {
01690                 /* Just copy the buffer directly */
01691                 Context.Information = *(POBJECT_HANDLE_ATTRIBUTE_INFORMATION)
01692                                         ObjectInformation;
01693             }
01694 
01695             /* Check if this is a kernel handle */
01696             if (ObIsKernelHandle(ObjectHandle, Context.PreviousMode))
01697             {
01698                 /* Get the actual handle */
01699                 ObjectHandle = ObKernelHandleToHandle(ObjectHandle);
01700                 ObjectTable = ObpKernelHandleTable;
01701 
01702                 /* Check if we're not in the system process */
01703                 if (PsGetCurrentProcess() != PsInitialSystemProcess)
01704                 {
01705                     /* Attach to it */
01706                     KeStackAttachProcess(&PsInitialSystemProcess->Pcb, &ApcState);
01707                     AttachedToProcess = TRUE;
01708                 }
01709             }
01710             else
01711             {
01712                 /* Use the current table */
01713                 ObjectTable = PsGetCurrentProcess()->ObjectTable;
01714             }
01715 
01716             /* Change the handle attributes */
01717             if (!ExChangeHandle(ObjectTable,
01718                                 ObjectHandle,
01719                                 ObpSetHandleAttributes,
01720                                 (ULONG_PTR)&Context))
01721             {
01722                 /* Some failure */
01723                 Status = STATUS_ACCESS_DENIED;
01724             }
01725             else
01726             {
01727                 /* We are done */
01728                 Status = STATUS_SUCCESS;
01729             }
01730 
01731             /* De-attach if we were attached, and return status */
01732             if (AttachedToProcess) KeUnstackDetachProcess(&ApcState);
01733             break;
01734         
01735         case ObjectSessionInformation:
01736         
01737             /* Only a system process can do this */
01738             PreviousMode = ExGetPreviousMode();
01739             if (!SeSinglePrivilegeCheck(SeTcbPrivilege, PreviousMode))
01740             {
01741                 /* Fail */
01742                 DPRINT1("Privilege not held\n");
01743                 Status = STATUS_PRIVILEGE_NOT_HELD;
01744             }
01745             else
01746             {
01747                 /* Get the object directory */
01748                 Status = ObReferenceObjectByHandle(ObjectHandle, 
01749                                                    0, 
01750                                                    ObDirectoryType,
01751                                                    PreviousMode,
01752                                                    (PVOID*)&Directory,
01753                                                    NULL);
01754                 if (NT_SUCCESS(Status))
01755                 {
01756                     /* FIXME: Missng locks */
01757                     /* Set its session ID */
01758                     Directory->SessionId = PsGetCurrentProcessSessionId();
01759                     ObDereferenceObject(Directory);
01760                 }
01761             }
01762             break;
01763         
01764         default:
01765             /* Unsupported class */
01766             Status = STATUS_INVALID_INFO_CLASS;
01767             break;
01768     }
01769 
01770     return Status;
01771 }
01772 
01773 /* 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.