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

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

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