Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenoblife.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
1.7.6.1
|