Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenobdir.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/obdir.c 00005 * PURPOSE: Manages the Object Manager's Directory Implementation, 00006 * such as functions for addition, deletion and lookup into 00007 * the Object Manager's namespace. These routines are separate 00008 * from the Namespace Implementation because they are largely 00009 * independent and could be used for other namespaces. 00010 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) 00011 * Thomas Weidenmueller (w3seek@reactos.org) 00012 */ 00013 00014 /* INCLUDES ***************************************************************/ 00015 00016 #include <ntoskrnl.h> 00017 #define NDEBUG 00018 #include <debug.h> 00019 00020 BOOLEAN ObpLUIDDeviceMapsEnabled; 00021 POBJECT_TYPE ObDirectoryType = NULL; 00022 00023 /* PRIVATE FUNCTIONS ******************************************************/ 00024 00025 /*++ 00026 * @name ObpInsertEntryDirectory 00027 * 00028 * The ObpInsertEntryDirectory routine <FILLMEIN>. 00029 * 00030 * @param Parent 00031 * <FILLMEIN>. 00032 * 00033 * @param Context 00034 * <FILLMEIN>. 00035 * 00036 * @param ObjectHeader 00037 * <FILLMEIN>. 00038 * 00039 * @return TRUE if the object was inserted, FALSE otherwise. 00040 * 00041 * @remarks None. 00042 * 00043 *--*/ 00044 BOOLEAN 00045 NTAPI 00046 ObpInsertEntryDirectory(IN POBJECT_DIRECTORY Parent, 00047 IN POBP_LOOKUP_CONTEXT Context, 00048 IN POBJECT_HEADER ObjectHeader) 00049 { 00050 POBJECT_DIRECTORY_ENTRY *AllocatedEntry; 00051 POBJECT_DIRECTORY_ENTRY NewEntry; 00052 POBJECT_HEADER_NAME_INFO HeaderNameInfo; 00053 00054 /* Make sure we have a name */ 00055 ASSERT(ObjectHeader->NameInfoOffset != 0); 00056 00057 /* Validate the context */ 00058 if ((Context->Object) || 00059 !(Context->DirectoryLocked) || 00060 (Parent != Context->Directory)) 00061 { 00062 /* Invalid context */ 00063 DPRINT1("OB: ObpInsertEntryDirectory - invalid context %p %ld\n", 00064 Context, Context->DirectoryLocked); 00065 ASSERT(FALSE); 00066 return FALSE; 00067 } 00068 00069 /* Allocate a new Directory Entry */ 00070 NewEntry = ExAllocatePoolWithTag(PagedPool, 00071 sizeof(OBJECT_DIRECTORY_ENTRY), 00072 OB_DIR_TAG); 00073 if (!NewEntry) return FALSE; 00074 00075 /* Save the hash */ 00076 NewEntry->HashValue = Context->HashValue; 00077 00078 /* Get the Object Name Information */ 00079 HeaderNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader); 00080 00081 /* Get the Allocated entry */ 00082 AllocatedEntry = &Parent->HashBuckets[Context->HashIndex]; 00083 00084 /* Set it */ 00085 NewEntry->ChainLink = *AllocatedEntry; 00086 *AllocatedEntry = NewEntry; 00087 00088 /* Associate the Object */ 00089 NewEntry->Object = &ObjectHeader->Body; 00090 00091 /* Associate the Directory */ 00092 HeaderNameInfo->Directory = Parent; 00093 return TRUE; 00094 } 00095 00096 /*++ 00097 * @name ObpLookupEntryDirectory 00098 * 00099 * The ObpLookupEntryDirectory routine <FILLMEIN>. 00100 * 00101 * @param Directory 00102 * <FILLMEIN>. 00103 * 00104 * @param Name 00105 * <FILLMEIN>. 00106 * 00107 * @param Attributes 00108 * <FILLMEIN>. 00109 * 00110 * @param SearchShadow 00111 * <FILLMEIN>. 00112 * 00113 * @param Context 00114 * <FILLMEIN>. 00115 * 00116 * @return Pointer to the object which was found, or NULL otherwise. 00117 * 00118 * @remarks None. 00119 * 00120 *--*/ 00121 PVOID 00122 NTAPI 00123 ObpLookupEntryDirectory(IN POBJECT_DIRECTORY Directory, 00124 IN PUNICODE_STRING Name, 00125 IN ULONG Attributes, 00126 IN UCHAR SearchShadow, 00127 IN POBP_LOOKUP_CONTEXT Context) 00128 { 00129 BOOLEAN CaseInsensitive = FALSE; 00130 POBJECT_HEADER_NAME_INFO HeaderNameInfo; 00131 POBJECT_HEADER ObjectHeader; 00132 ULONG HashValue; 00133 ULONG HashIndex; 00134 LONG TotalChars; 00135 WCHAR CurrentChar; 00136 POBJECT_DIRECTORY_ENTRY *AllocatedEntry; 00137 POBJECT_DIRECTORY_ENTRY *LookupBucket; 00138 POBJECT_DIRECTORY_ENTRY CurrentEntry; 00139 PVOID FoundObject = NULL; 00140 PWSTR Buffer; 00141 PAGED_CODE(); 00142 00143 /* Check if we should search the shadow directory */ 00144 if (!ObpLUIDDeviceMapsEnabled) SearchShadow = FALSE; 00145 00146 /* Fail if we don't have a directory or name */ 00147 if (!(Directory) || !(Name)) goto Quickie; 00148 00149 /* Get name information */ 00150 TotalChars = Name->Length / sizeof(WCHAR); 00151 Buffer = Name->Buffer; 00152 00153 /* Set up case-sensitivity */ 00154 if (Attributes & OBJ_CASE_INSENSITIVE) CaseInsensitive = TRUE; 00155 00156 /* Fail if the name is empty */ 00157 if (!(Buffer) || !(TotalChars)) goto Quickie; 00158 00159 /* Create the Hash */ 00160 for (HashValue = 0; TotalChars; TotalChars--) 00161 { 00162 /* Go to the next Character */ 00163 CurrentChar = *Buffer++; 00164 00165 /* Prepare the Hash */ 00166 HashValue += (HashValue << 1) + (HashValue >> 1); 00167 00168 /* Create the rest based on the name */ 00169 if (CurrentChar < 'a') HashValue += CurrentChar; 00170 else if (CurrentChar > 'z') HashValue += RtlUpcaseUnicodeChar(CurrentChar); 00171 else HashValue += (CurrentChar - ('a'-'A')); 00172 } 00173 00174 /* Merge it with our number of hash buckets */ 00175 HashIndex = HashValue % 37; 00176 00177 /* Save the result */ 00178 Context->HashValue = HashValue; 00179 Context->HashIndex = (USHORT)HashIndex; 00180 00181 /* Get the root entry and set it as our lookup bucket */ 00182 AllocatedEntry = &Directory->HashBuckets[HashIndex]; 00183 LookupBucket = AllocatedEntry; 00184 00185 /* Check if the directory is already locked */ 00186 if (!Context->DirectoryLocked) 00187 { 00188 /* Lock it */ 00189 ObpAcquireDirectoryLockShared(Directory, Context); 00190 } 00191 00192 /* Start looping */ 00193 while ((CurrentEntry = *AllocatedEntry)) 00194 { 00195 /* Do the hashes match? */ 00196 if (CurrentEntry->HashValue == HashValue) 00197 { 00198 /* Make sure that it has a name */ 00199 ObjectHeader = OBJECT_TO_OBJECT_HEADER(CurrentEntry->Object); 00200 00201 /* Get the name information */ 00202 ASSERT(ObjectHeader->NameInfoOffset != 0); 00203 HeaderNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader); 00204 00205 /* Do the names match? */ 00206 if ((Name->Length == HeaderNameInfo->Name.Length) && 00207 (RtlEqualUnicodeString(Name, &HeaderNameInfo->Name, CaseInsensitive))) 00208 { 00209 break; 00210 } 00211 } 00212 00213 /* Move to the next entry */ 00214 AllocatedEntry = &CurrentEntry->ChainLink; 00215 } 00216 00217 /* Check if we still have an entry */ 00218 if (CurrentEntry) 00219 { 00220 /* Set this entry as the first, to speed up incoming insertion */ 00221 if (AllocatedEntry != LookupBucket) 00222 { 00223 /* Check if the directory was locked or convert the lock */ 00224 if ((Context->DirectoryLocked) || 00225 (ExConvertPushLockSharedToExclusive(&Directory->Lock))) 00226 { 00227 /* Set the Current Entry */ 00228 *AllocatedEntry = CurrentEntry->ChainLink; 00229 00230 /* Link to the old Hash Entry */ 00231 CurrentEntry->ChainLink = *LookupBucket; 00232 00233 /* Set the new Hash Entry */ 00234 *LookupBucket = CurrentEntry; 00235 } 00236 } 00237 00238 /* Save the found object */ 00239 FoundObject = CurrentEntry->Object; 00240 goto Quickie; 00241 } 00242 else 00243 { 00244 /* Check if the directory was locked */ 00245 if (!Context->DirectoryLocked) 00246 { 00247 /* Release the lock */ 00248 ObpReleaseDirectoryLock(Directory, Context); 00249 } 00250 00251 /* Check if we should scan the shadow directory */ 00252 if ((SearchShadow) && (Directory->DeviceMap)) 00253 { 00254 /* FIXME: We don't support this yet */ 00255 ASSERT(FALSE); 00256 } 00257 } 00258 00259 Quickie: 00260 /* Check if we inserted an object */ 00261 if (FoundObject) 00262 { 00263 /* Get the object name information */ 00264 ObjectHeader = OBJECT_TO_OBJECT_HEADER(FoundObject); 00265 ObpReferenceNameInfo(ObjectHeader); 00266 00267 /* Reference the object being looked up */ 00268 ObReferenceObject(FoundObject); 00269 00270 /* Check if the directory was locked */ 00271 if (!Context->DirectoryLocked) 00272 { 00273 /* Release the lock */ 00274 ObpReleaseDirectoryLock(Directory, Context); 00275 } 00276 } 00277 00278 /* Check if we found an object already */ 00279 if (Context->Object) 00280 { 00281 /* We already did a lookup, so remove this object's query reference */ 00282 ObjectHeader = OBJECT_TO_OBJECT_HEADER(Context->Object); 00283 HeaderNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader); 00284 ObpDereferenceNameInfo(HeaderNameInfo); 00285 00286 /* Also dereference the object itself */ 00287 ObDereferenceObject(Context->Object); 00288 } 00289 00290 /* Return the object we found */ 00291 Context->Object = FoundObject; 00292 return FoundObject; 00293 } 00294 00295 /*++ 00296 * @name ObpDeleteEntryDirectory 00297 * 00298 * The ObpDeleteEntryDirectory routine <FILLMEIN>. 00299 * 00300 * @param Context 00301 * <FILLMEIN>. 00302 * 00303 * @return TRUE if the object was deleted, FALSE otherwise. 00304 * 00305 * @remarks None. 00306 * 00307 *--*/ 00308 BOOLEAN 00309 NTAPI 00310 ObpDeleteEntryDirectory(POBP_LOOKUP_CONTEXT Context) 00311 { 00312 POBJECT_DIRECTORY Directory; 00313 POBJECT_DIRECTORY_ENTRY *AllocatedEntry; 00314 POBJECT_DIRECTORY_ENTRY CurrentEntry; 00315 00316 /* Get the Directory */ 00317 Directory = Context->Directory; 00318 if (!Directory) return FALSE; 00319 00320 /* Get the Entry */ 00321 AllocatedEntry = &Directory->HashBuckets[Context->HashIndex]; 00322 CurrentEntry = *AllocatedEntry; 00323 00324 /* Unlink the Entry */ 00325 *AllocatedEntry = CurrentEntry->ChainLink; 00326 CurrentEntry->ChainLink = NULL; 00327 00328 /* Free it */ 00329 ExFreePoolWithTag(CurrentEntry, OB_DIR_TAG); 00330 00331 /* Return */ 00332 return TRUE; 00333 } 00334 00335 /* FUNCTIONS **************************************************************/ 00336 00337 /*++ 00338 * @name NtOpenDirectoryObject 00339 * @implemented NT4 00340 * 00341 * The NtOpenDirectoryObject routine opens a namespace directory object. 00342 * 00343 * @param DirectoryHandle 00344 * Variable which receives the directory handle. 00345 * 00346 * @param DesiredAccess 00347 * Desired access to the directory. 00348 * 00349 * @param ObjectAttributes 00350 * Structure describing the directory. 00351 * 00352 * @return STATUS_SUCCESS or appropriate error value. 00353 * 00354 * @remarks None. 00355 * 00356 *--*/ 00357 NTSTATUS 00358 NTAPI 00359 NtOpenDirectoryObject(OUT PHANDLE DirectoryHandle, 00360 IN ACCESS_MASK DesiredAccess, 00361 IN POBJECT_ATTRIBUTES ObjectAttributes) 00362 { 00363 HANDLE Directory; 00364 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); 00365 NTSTATUS Status; 00366 PAGED_CODE(); 00367 00368 /* Check if we need to do any probing */ 00369 if (PreviousMode != KernelMode) 00370 { 00371 _SEH2_TRY 00372 { 00373 /* Probe the return handle */ 00374 ProbeForWriteHandle(DirectoryHandle); 00375 } 00376 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00377 { 00378 /* Return the exception code */ 00379 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 00380 } 00381 _SEH2_END; 00382 } 00383 00384 /* Open the directory object */ 00385 Status = ObOpenObjectByName(ObjectAttributes, 00386 ObDirectoryType, 00387 PreviousMode, 00388 NULL, 00389 DesiredAccess, 00390 NULL, 00391 &Directory); 00392 if (NT_SUCCESS(Status)) 00393 { 00394 _SEH2_TRY 00395 { 00396 /* Write back the handle to the caller */ 00397 *DirectoryHandle = Directory; 00398 } 00399 _SEH2_EXCEPT(ExSystemExceptionFilter()) 00400 { 00401 /* Get the exception code */ 00402 Status = _SEH2_GetExceptionCode(); 00403 } 00404 _SEH2_END; 00405 } 00406 00407 /* Return the status to the caller */ 00408 return Status; 00409 } 00410 00411 /*++ 00412 * @name NtQueryDirectoryObject 00413 * @implemented NT4 00414 * 00415 * The NtQueryDirectoryObject routine reads information from a directory in 00416 * the system namespace. 00417 * 00418 * @param DirectoryHandle 00419 * Handle obtained with NtOpenDirectoryObject which 00420 * must grant DIRECTORY_QUERY access to the directory object. 00421 * 00422 * @param Buffer 00423 * Buffer to hold the data read. 00424 * 00425 * @param BufferLength 00426 * Size of the buffer in bytes. 00427 * 00428 * @param ReturnSingleEntry 00429 * When TRUE, only 1 entry is written in DirObjInformation; 00430 * otherwise as many as will fit in the buffer. 00431 * 00432 * @param RestartScan 00433 * If TRUE start reading at index 0. 00434 * If FALSE start reading at the index specified by *ObjectIndex. 00435 * 00436 * @param Context 00437 * Zero based index into the directory, interpretation 00438 * depends on RestartScan. 00439 * 00440 * @param ReturnLength 00441 * Caller supplied storage for the number of bytes 00442 * written (or NULL). 00443 * 00444 * @return STATUS_SUCCESS or appropriate error value. 00445 * 00446 * @remarks Although you can iterate over the directory by calling this 00447 * function multiple times, the directory is unlocked between 00448 * calls. This means that another thread can change the directory 00449 * and so iterating doesn't guarantee a consistent picture of the 00450 * directory. Best thing is to retrieve all directory entries in 00451 * one call. 00452 * 00453 *--*/ 00454 NTSTATUS 00455 NTAPI 00456 NtQueryDirectoryObject(IN HANDLE DirectoryHandle, 00457 OUT PVOID Buffer, 00458 IN ULONG BufferLength, 00459 IN BOOLEAN ReturnSingleEntry, 00460 IN BOOLEAN RestartScan, 00461 IN OUT PULONG Context, 00462 OUT PULONG ReturnLength OPTIONAL) 00463 { 00464 POBJECT_DIRECTORY Directory; 00465 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); 00466 ULONG SkipEntries = 0; 00467 NTSTATUS Status; 00468 PVOID LocalBuffer; 00469 POBJECT_DIRECTORY_INFORMATION DirectoryInfo; 00470 ULONG Length, TotalLength; 00471 ULONG Count, CurrentEntry; 00472 ULONG Hash; 00473 POBJECT_DIRECTORY_ENTRY Entry; 00474 POBJECT_HEADER ObjectHeader; 00475 POBJECT_HEADER_NAME_INFO ObjectNameInfo; 00476 UNICODE_STRING Name; 00477 PWSTR p; 00478 OBP_LOOKUP_CONTEXT LookupContext; 00479 PAGED_CODE(); 00480 00481 /* Initialize lookup */ 00482 ObpInitializeLookupContext(&LookupContext); 00483 00484 /* Check if we need to do any probing */ 00485 if (PreviousMode != KernelMode) 00486 { 00487 _SEH2_TRY 00488 { 00489 /* Probe the buffer (assuming it will hold Unicode characters) */ 00490 ProbeForWrite(Buffer, BufferLength, sizeof(WCHAR)); 00491 00492 /* Probe the context and copy it unless scan-restart was requested */ 00493 ProbeForWriteUlong(Context); 00494 if (!RestartScan) SkipEntries = *Context; 00495 00496 /* Probe the return length if the caller specified one */ 00497 if (ReturnLength) ProbeForWriteUlong(ReturnLength); 00498 } 00499 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00500 { 00501 /* Return the exception code */ 00502 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 00503 } 00504 _SEH2_END; 00505 } 00506 else if (!RestartScan) 00507 { 00508 /* This is kernel mode, save the context without probing, if needed */ 00509 SkipEntries = *Context; 00510 } 00511 00512 /* Allocate a buffer */ 00513 LocalBuffer = ExAllocatePoolWithTag(PagedPool, 00514 sizeof(OBJECT_DIRECTORY_INFORMATION) + 00515 BufferLength, 00516 OB_NAME_TAG); 00517 if (!LocalBuffer) return STATUS_INSUFFICIENT_RESOURCES; 00518 RtlZeroMemory(LocalBuffer, BufferLength); 00519 00520 /* Get a reference to directory */ 00521 Status = ObReferenceObjectByHandle(DirectoryHandle, 00522 DIRECTORY_QUERY, 00523 ObDirectoryType, 00524 PreviousMode, 00525 (PVOID*)&Directory, 00526 NULL); 00527 if (!NT_SUCCESS(Status)) 00528 { 00529 /* Free the buffer and fail */ 00530 ExFreePoolWithTag(LocalBuffer, OB_NAME_TAG); 00531 return Status; 00532 } 00533 00534 /* Lock directory in shared mode */ 00535 ObpAcquireDirectoryLockShared(Directory, &LookupContext); 00536 00537 /* Start at position 0 */ 00538 DirectoryInfo = (POBJECT_DIRECTORY_INFORMATION)LocalBuffer; 00539 TotalLength = sizeof(OBJECT_DIRECTORY_INFORMATION); 00540 00541 /* Start with 0 entries */ 00542 Count = 0; 00543 CurrentEntry = 0; 00544 00545 /* Set default status and start looping */ 00546 Status = STATUS_NO_MORE_ENTRIES; 00547 for (Hash = 0; Hash < 37; Hash++) 00548 { 00549 /* Get this entry and loop all of them */ 00550 Entry = Directory->HashBuckets[Hash]; 00551 while (Entry) 00552 { 00553 /* Check if we should process this entry */ 00554 if (SkipEntries == CurrentEntry++) 00555 { 00556 /* Get the header data */ 00557 ObjectHeader = OBJECT_TO_OBJECT_HEADER(Entry->Object); 00558 ObjectNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader); 00559 00560 /* Get the object name */ 00561 if (ObjectNameInfo) 00562 { 00563 /* Use the one we have */ 00564 Name = ObjectNameInfo->Name; 00565 } 00566 else 00567 { 00568 /* Otherwise, use an empty one */ 00569 RtlInitEmptyUnicodeString(&Name, NULL, 0); 00570 } 00571 00572 /* Calculate the length for this entry */ 00573 Length = sizeof(OBJECT_DIRECTORY_INFORMATION) + 00574 Name.Length + sizeof(UNICODE_NULL) + 00575 ObjectHeader->Type->Name.Length + sizeof(UNICODE_NULL); 00576 00577 /* Make sure this entry won't overflow */ 00578 if ((TotalLength + Length) > BufferLength) 00579 { 00580 /* Check if the caller wanted only an entry */ 00581 if (ReturnSingleEntry) 00582 { 00583 /* Then we'll fail and ask for more buffer */ 00584 TotalLength += Length; 00585 Status = STATUS_BUFFER_TOO_SMALL; 00586 } 00587 else 00588 { 00589 /* Otherwise, we'll say we're done for now */ 00590 Status = STATUS_MORE_ENTRIES; 00591 } 00592 00593 /* Decrease the entry since we didn't process */ 00594 CurrentEntry--; 00595 goto Quickie; 00596 } 00597 00598 /* Now fill in the buffer */ 00599 DirectoryInfo->Name.Length = Name.Length; 00600 DirectoryInfo->Name.MaximumLength = Name.Length + 00601 sizeof(UNICODE_NULL); 00602 DirectoryInfo->Name.Buffer = Name.Buffer; 00603 DirectoryInfo->TypeName.Length = ObjectHeader-> 00604 Type->Name.Length; 00605 DirectoryInfo->TypeName.MaximumLength = ObjectHeader-> 00606 Type->Name.Length + 00607 sizeof(UNICODE_NULL); 00608 DirectoryInfo->TypeName.Buffer = ObjectHeader-> 00609 Type->Name.Buffer; 00610 00611 /* Set success */ 00612 Status = STATUS_SUCCESS; 00613 00614 /* Increase statistics */ 00615 TotalLength += Length; 00616 DirectoryInfo++; 00617 Count++; 00618 00619 /* If the caller only wanted an entry, bail out */ 00620 if (ReturnSingleEntry) goto Quickie; 00621 00622 /* Increase the key by one */ 00623 SkipEntries++; 00624 } 00625 00626 /* Move to the next directory */ 00627 Entry = Entry->ChainLink; 00628 } 00629 } 00630 00631 Quickie: 00632 /* Make sure we got success */ 00633 if (NT_SUCCESS(Status)) 00634 { 00635 /* Clear the current pointer and set it */ 00636 RtlZeroMemory(DirectoryInfo, sizeof(OBJECT_DIRECTORY_INFORMATION)); 00637 DirectoryInfo++; 00638 00639 /* Set the buffer here now and loop entries */ 00640 p = (PWSTR)DirectoryInfo; 00641 DirectoryInfo = LocalBuffer; 00642 while (Count--) 00643 { 00644 /* Copy the name buffer */ 00645 RtlCopyMemory(p, 00646 DirectoryInfo->Name.Buffer, 00647 DirectoryInfo->Name.Length); 00648 00649 /* Now fixup the pointers */ 00650 DirectoryInfo->Name.Buffer = (PVOID)((ULONG_PTR)Buffer + 00651 ((ULONG_PTR)p - 00652 (ULONG_PTR)LocalBuffer)); 00653 00654 /* Advance in buffer and NULL-terminate */ 00655 p = (PVOID)((ULONG_PTR)p + DirectoryInfo->Name.Length); 00656 *p++ = UNICODE_NULL; 00657 00658 /* Now copy the type name buffer */ 00659 RtlCopyMemory(p, 00660 DirectoryInfo->TypeName.Buffer, 00661 DirectoryInfo->TypeName.Length); 00662 00663 /* Now fixup the pointers */ 00664 DirectoryInfo->TypeName.Buffer = (PVOID)((ULONG_PTR)Buffer + 00665 ((ULONG_PTR)p - 00666 (ULONG_PTR)LocalBuffer)); 00667 00668 /* Advance in buffer and NULL-terminate */ 00669 p = (PVOID)((ULONG_PTR)p + DirectoryInfo->TypeName.Length); 00670 *p++ = UNICODE_NULL; 00671 00672 /* Move to the next entry */ 00673 DirectoryInfo++; 00674 } 00675 00676 /* Set the key */ 00677 *Context = CurrentEntry; 00678 } 00679 00680 _SEH2_TRY 00681 { 00682 /* Copy the buffer */ 00683 RtlCopyMemory(Buffer, 00684 LocalBuffer, 00685 (TotalLength <= BufferLength) ? 00686 TotalLength : BufferLength); 00687 00688 /* Check if the caller requested the return length and return it*/ 00689 if (ReturnLength) *ReturnLength = TotalLength; 00690 } 00691 _SEH2_EXCEPT(ExSystemExceptionFilter()) 00692 { 00693 /* Get the exception code */ 00694 Status = _SEH2_GetExceptionCode(); 00695 } 00696 _SEH2_END; 00697 00698 /* Unlock the directory */ 00699 ObpReleaseDirectoryLock(Directory, &LookupContext); 00700 00701 /* Dereference the directory and free our buffer */ 00702 ObDereferenceObject(Directory); 00703 ExFreePoolWithTag(LocalBuffer, OB_NAME_TAG); 00704 00705 /* Return status to caller */ 00706 return Status; 00707 } 00708 00709 /*++ 00710 * @name NtCreateDirectoryObject 00711 * @implemented NT4 00712 * 00713 * The NtOpenDirectoryObject routine creates or opens a directory object. 00714 * 00715 * @param DirectoryHandle 00716 * Variable which receives the directory handle. 00717 * 00718 * @param DesiredAccess 00719 * Desired access to the directory. 00720 * 00721 * @param ObjectAttributes 00722 * Structure describing the directory. 00723 * 00724 * @return STATUS_SUCCESS or appropriate error value. 00725 * 00726 * @remarks None. 00727 * 00728 *--*/ 00729 NTSTATUS 00730 NTAPI 00731 NtCreateDirectoryObject(OUT PHANDLE DirectoryHandle, 00732 IN ACCESS_MASK DesiredAccess, 00733 IN POBJECT_ATTRIBUTES ObjectAttributes) 00734 { 00735 POBJECT_DIRECTORY Directory; 00736 HANDLE NewHandle; 00737 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); 00738 NTSTATUS Status; 00739 PAGED_CODE(); 00740 00741 /* Check if we need to do any probing */ 00742 if (PreviousMode != KernelMode) 00743 { 00744 _SEH2_TRY 00745 { 00746 /* Probe the return handle */ 00747 ProbeForWriteHandle(DirectoryHandle); 00748 } 00749 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00750 { 00751 /* Return the exception code */ 00752 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 00753 } 00754 _SEH2_END; 00755 } 00756 00757 /* Create the object */ 00758 Status = ObCreateObject(PreviousMode, 00759 ObDirectoryType, 00760 ObjectAttributes, 00761 PreviousMode, 00762 NULL, 00763 sizeof(OBJECT_DIRECTORY), 00764 0, 00765 0, 00766 (PVOID*)&Directory); 00767 if (!NT_SUCCESS(Status)) return Status; 00768 00769 /* Setup the object */ 00770 RtlZeroMemory(Directory, sizeof(OBJECT_DIRECTORY)); 00771 ExInitializePushLock(&Directory->Lock); 00772 Directory->SessionId = -1; 00773 00774 /* Insert it into the handle table */ 00775 Status = ObInsertObject((PVOID)Directory, 00776 NULL, 00777 DesiredAccess, 00778 0, 00779 NULL, 00780 &NewHandle); 00781 00782 /* Enter SEH to protect write */ 00783 _SEH2_TRY 00784 { 00785 /* Return the handle back to the caller */ 00786 *DirectoryHandle = NewHandle; 00787 } 00788 _SEH2_EXCEPT(ExSystemExceptionFilter()) 00789 { 00790 /* Get the exception code */ 00791 Status = _SEH2_GetExceptionCode(); 00792 } 00793 _SEH2_END; 00794 00795 /* Return status to caller */ 00796 return Status; 00797 } 00798 00799 /* EOF */ Generated on Sat May 26 2012 04:36:30 for ReactOS by
1.7.6.1
|