- Fix compile issues caused by previous patch.
[reactos.git] / reactos / ntoskrnl / ob / dirobj.c
index cc6bd8e..e2558f0 100644 (file)
-/*
+/* $Id$
+ *
  * COPYRIGHT:      See COPYING in the top level directory
  * PROJECT:        ReactOS kernel
  * FILE:           ntoskrnl/ob/dirobj.c
  * PURPOSE:        Interface functions to directory object
- * PROGRAMMER:     David Welch (welch@mcmail.com)
- * UPDATE HISTORY:
- *                 22/05/98: Created
+ *
+ * PROGRAMMERS:    David Welch (welch@mcmail.com)
  */
 
 /* INCLUDES ***************************************************************/
 
-#include <windows.h>
-#include <wstring.h>
-#include <ddk/ntddk.h>
-#include <internal/ob.h>
-#include <internal/io.h>
-#include <internal/string.h>
-
+#include <ntoskrnl.h>
 #define NDEBUG
 #include <internal/debug.h>
 
 
 /* FUNCTIONS **************************************************************/
 
-NTSTATUS NtOpenDirectoryObject(PHANDLE DirectoryHandle,
-                              ACCESS_MASK DesiredAccess,
-                              POBJECT_ATTRIBUTES ObjectAttributes)
-{
-   return(ZwOpenDirectoryObject(DirectoryHandle,
-                               DesiredAccess,
-                               ObjectAttributes));
-}
 
-NTSTATUS ZwOpenDirectoryObject(PHANDLE DirectoryHandle,
-                              ACCESS_MASK DesiredAccess,
-                              POBJECT_ATTRIBUTES ObjectAttributes)
-/*
- * FUNCTION: Opens a namespace directory object
- * ARGUMENTS:
- *       DirectoryHandle (OUT) = Variable which receives the directory handle
- *       DesiredAccess = Desired access to the directory
- *       ObjectAttributes = Structure describing the directory
- * RETURNS: Status
- * NOTES: Undocumented
+/**********************************************************************
+ * NAME                                                        EXPORTED
+ *     NtOpenDirectoryObject
+ *
+ * DESCRIPTION
+ *     Opens a namespace directory object.
+ *
+ * ARGUMENTS
+ *     DirectoryHandle (OUT)
+ *             Variable which receives the directory handle.
+ *
+ *     DesiredAccess
+ *             Desired access to the directory.
+ *
+ *     ObjectAttributes
+ *             Structure describing the directory.
+ *
+ * RETURN VALUE
+ *     Status.
+ *
+ * NOTES
+ *     Undocumented.
  */
+NTSTATUS STDCALL
+NtOpenDirectoryObject (OUT PHANDLE DirectoryHandle,
+                      IN ACCESS_MASK DesiredAccess,
+                      IN POBJECT_ATTRIBUTES ObjectAttributes)
 {
-   PVOID Object;
-   NTSTATUS Status;
-   
-   *DirectoryHandle = 0;
-   
-   Status = ObReferenceObjectByName(ObjectAttributes->ObjectName,
-                                   ObjectAttributes->Attributes,
-                                   NULL,
-                                   DesiredAccess,
-                                   ObDirectoryType,
-                                   UserMode,
-                                   NULL,
-                                   &Object);
-   if (!NT_SUCCESS(Status))
-     {
-       return(Status);
-     }
-       
-   Status = ObCreateHandle(PsGetCurrentProcess(),
-                          Object,
-                          DesiredAccess,
-                          FALSE,
-                          DirectoryHandle);
-   return(STATUS_SUCCESS);
-}
+   HANDLE hDirectory;
+   KPROCESSOR_MODE PreviousMode;
+   NTSTATUS Status = STATUS_SUCCESS;
 
-NTSTATUS NtQueryDirectoryObject(IN HANDLE DirObjHandle,
-                               OUT POBJDIR_INFORMATION DirObjInformation, 
-                               IN ULONG                BufferLength, 
-                               IN BOOLEAN              GetNextIndex, 
-                               IN BOOLEAN              IgnoreInputIndex, 
-                               IN OUT PULONG           ObjectIndex,
-                               OUT PULONG              DataWritten OPTIONAL)
-{
-   return(ZwQueryDirectoryObject(DirObjHandle,
-                                DirObjInformation,
-                                BufferLength,
-                                GetNextIndex,
-                                IgnoreInputIndex,
-                                ObjectIndex,
-                                DataWritten));
-}
+   PAGED_CODE();
 
-NTSTATUS ZwQueryDirectoryObject(IN HANDLE DirObjHandle,
-                               OUT POBJDIR_INFORMATION DirObjInformation, 
-                               IN ULONG                BufferLength, 
-                               IN BOOLEAN              GetNextIndex, 
-                               IN BOOLEAN              IgnoreInputIndex, 
-                               IN OUT PULONG           ObjectIndex,
-                               OUT PULONG              DataWritten OPTIONAL)
-/*
- * FUNCTION: Reads information from a namespace directory
- * ARGUMENTS:
- *        DirObjInformation (OUT) = Buffer to hold the data read
- *        BufferLength = Size of the buffer in bytes
- *        GetNextIndex = If TRUE then set ObjectIndex to the index of the
- *                       next object
- *                       If FALSE then set ObjectIndex to the number of
- *                       objects in the directory
- *        IgnoreInputIndex = If TRUE start reading at index 0
- *                           If FALSE start reading at the index specified
- *                           by object index
- *        ObjectIndex = Zero based index into the directory, interpretation
- *                      depends on IgnoreInputIndex and GetNextIndex
- *        DataWritten (OUT) = Caller supplied storage for the number of bytes
- *                            written (or NULL)
- * RETURNS: Status
- */
-{
-   PDIRECTORY_OBJECT dir = NULL;
-   ULONG EntriesToRead;
-   PLIST_ENTRY current_entry;
-   POBJECT_HEADER current;
-   ULONG i=0;
-   ULONG EntriesToSkip;
-   NTSTATUS Status;
-   
-   DPRINT("ZwQueryDirectoryObject(DirObjHandle %x)\n",DirObjHandle);
-   DPRINT("dir %x namespc_root %x\n",dir,HEADER_TO_BODY(&(namespc_root.hdr)));
-   
-//   assert_irql(PASSIVE_LEVEL);
-   
-   Status = ObReferenceObjectByHandle(DirObjHandle,
-                                     DIRECTORY_QUERY,
-                                     ObDirectoryType,
-                                     UserMode,
-                                     (PVOID*)&dir,
-                                     NULL);
-   if (Status != STATUS_SUCCESS)
+   PreviousMode = ExGetPreviousMode();
+
+   if(PreviousMode != KernelMode)
+   {
+     _SEH_TRY
      {
-       return(Status);
+       ProbeForWriteHandle(DirectoryHandle);
      }
-   
-   EntriesToRead = BufferLength / sizeof(OBJDIR_INFORMATION);
-   *DataWritten = 0;
-   
-   DPRINT("EntriesToRead %d\n",EntriesToRead);
-   
-   current_entry = dir->head.Flink;
-   
-   /*
-    * Optionally, skip over some entries at the start of the directory
-    */
-   if (!IgnoreInputIndex)
+     _SEH_HANDLE
      {
-       CHECKPOINT;
-       
-       EntriesToSkip = *ObjectIndex;
-       while ( i<EntriesToSkip && current_entry!=NULL)
-         {
-            current_entry = current_entry->Flink;
-         }
+       Status = _SEH_GetExceptionCode();
      }
-   
-   DPRINT("DirObjInformation %x\n",DirObjInformation);
-   
-   /*
-    * Read the maximum entries possible into the buffer
-    */
-   while ( i<EntriesToRead && current_entry!=(&(dir->head)))
+     _SEH_END;
+
+     if(!NT_SUCCESS(Status))
      {
-       current = CONTAINING_RECORD(current_entry,OBJECT_HEADER,Entry);
-       DPRINT("Scanning %w\n",current->Name.Buffer);
-       DirObjInformation[i].ObjectName.Buffer = 
-                      ExAllocatePool(NonPagedPool,(current->Name.Length+1)*2);
-       DirObjInformation[i].ObjectName.Length = current->Name.Length;
-       DirObjInformation[i].ObjectName.MaximumLength = current->Name.Length;
-       DPRINT("DirObjInformation[i].ObjectName.Buffer %x\n",
-              DirObjInformation[i].ObjectName.Buffer);
-       RtlCopyUnicodeString(&DirObjInformation[i].ObjectName,
-                            &(current->Name));
-       i++;
-       current_entry = current_entry->Flink;
-       (*DataWritten) = (*DataWritten) + sizeof(OBJDIR_INFORMATION);
-       CHECKPOINT;
+       DPRINT1("NtOpenDirectoryObject failed, Status: 0x%x\n", Status);
+       return Status;
      }
-   CHECKPOINT;
-   
-   /*
-    * Optionally, count the number of entries in the directory
-    */
-   if (GetNextIndex)
+   }
+
+   Status = ObOpenObjectByName(ObjectAttributes,
+                               ObDirectoryType,
+                               NULL,
+                               PreviousMode,
+                               DesiredAccess,
+                               NULL,
+                               &hDirectory);
+   if(NT_SUCCESS(Status))
+   {
+     _SEH_TRY
      {
-       *ObjectIndex=i;
+       *DirectoryHandle = hDirectory;
      }
-   else
+     _SEH_HANDLE
      {
-       while ( current_entry!=(&(dir->head)) )
-         {
-            current_entry=current_entry->Flink;
-            i++;
-         }
-       *ObjectIndex=i;
+       Status = _SEH_GetExceptionCode();
      }
-   return(STATUS_SUCCESS);
-}
+     _SEH_END;
+   }
 
-
-NTSTATUS NtCreateDirectoryObject(PHANDLE DirectoryHandle,
-                                ACCESS_MASK DesiredAccess,
-                                POBJECT_ATTRIBUTES ObjectAttributes)
-{
-   return(ZwCreateDirectoryObject(DirectoryHandle,
-                                 DesiredAccess,
-                                 ObjectAttributes));
+   return Status;
 }
 
-NTSTATUS ZwCreateDirectoryObject(PHANDLE DirectoryHandle,
-                                ACCESS_MASK DesiredAccess,
-                                POBJECT_ATTRIBUTES ObjectAttributes)
-/*
- * FUNCTION: Creates or opens a directory object (a container for other
- * objects)
- * ARGUMENTS:
- *        DirectoryHandle (OUT) = Caller supplied storage for the handle
- *                                of the directory
- *        DesiredAccess = Access desired to the directory
- *        ObjectAttributes = Object attributes initialized with
- *                           InitializeObjectAttributes
- * RETURNS: Status
+
+/**********************************************************************
+ * NAME                                                        EXPORTED
+ *     NtQueryDirectoryObject
+ *
+ * DESCRIPTION
+ *     Reads information from a directory in the system namespace.
+ *
+ * ARGUMENTS
+ *     DirectoryHandle
+ *             Handle, obtained with NtOpenDirectoryObject(), which
+ *             must grant DIRECTORY_QUERY access to the directory
+ *             object.
+ *
+ *     Buffer (OUT)
+ *             Buffer to hold the data read.
+ *
+ *     BufferLength
+ *             Size of the buffer in bytes.
+ *
+ *     ReturnSingleEntry
+ *             When TRUE, only 1 entry is written in DirObjInformation;
+ *             otherwise as many as will fit in the buffer.
+ *
+ *     RestartScan
+ *             If TRUE start reading at index 0.
+ *             If FALSE start reading at the index specified
+ *             by object index *ObjectIndex.
+ *
+ *     Context
+ *             Zero based index into the directory, interpretation
+ *             depends on RestartScan.
+ *
+ *     ReturnLength (OUT)
+ *             Caller supplied storage for the number of bytes
+ *             written (or NULL).
+ *
+ * RETURN VALUE
+ *     STATUS_SUCCESS - At least one (possibly more, depending on
+ *                       parameters and buffer size) dir entry is
+ *                       returned.
+ *      STATUS_NO_MORE_ENTRIES - Directory is exhausted
+ *      STATUS_BUFFER_TOO_SMALL - There isn't enough room in the
+ *                                buffer to return even 1 entry.
+ *                                ReturnLength will hold the required
+ *                                buffer size to return all remaining
+ *                                dir entries
+ *      Other - Status code
+ *
+ *
+ * NOTES
+ *      Although you can iterate over the directory by calling this
+ *      function multiple times, the directory is unlocked between
+ *      calls. This means that another thread can change the directory
+ *      and so iterating doesn't guarantee a consistent picture of the
+ *      directory. Best thing is to retrieve all directory entries in
+ *      one call.
  */
+NTSTATUS STDCALL
+NtQueryDirectoryObject (IN HANDLE DirectoryHandle,
+                       OUT PVOID Buffer,
+                       IN ULONG BufferLength,
+                       IN BOOLEAN ReturnSingleEntry,
+                       IN BOOLEAN RestartScan,
+                       IN OUT PULONG Context,
+                       OUT PULONG ReturnLength OPTIONAL)
 {
-   PDIRECTORY_OBJECT dir;
-   
-   dir = ObCreateObject(DirectoryHandle,
-                       DesiredAccess,
-                       ObjectAttributes,
-                       ObDirectoryType);
-   return(STATUS_SUCCESS);
+  PDIRECTORY_OBJECT Directory;
+  KPROCESSOR_MODE PreviousMode;
+  ULONG SkipEntries = 0;
+  ULONG NextEntry = 0;
+  ULONG CopyBytes = 0;
+  NTSTATUS Status = STATUS_SUCCESS;
+
+  PAGED_CODE();
+
+  PreviousMode = ExGetPreviousMode();
+
+  if(PreviousMode != KernelMode)
+  {
+    _SEH_TRY
+    {
+      /* a test showed that the Buffer pointer just has to be 16 bit aligned,
+         propably due to the fact that most information that needs to be copied
+         is unicode strings */
+      ProbeForWrite(Buffer,
+                    BufferLength,
+                    sizeof(WCHAR));
+      ProbeForWriteUlong(Context);
+      if(!RestartScan)
+      {
+        SkipEntries = *Context;
+      }
+      if(ReturnLength != NULL)
+      {
+        ProbeForWriteUlong(ReturnLength);
+      }
+    }
+    _SEH_HANDLE
+    {
+      Status = _SEH_GetExceptionCode();
+    }
+    _SEH_END;
+
+    if(!NT_SUCCESS(Status))
+    {
+      DPRINT1("NtQueryDirectoryObject failed, Status: 0x%x\n", Status);
+      return Status;
+    }
+  }
+  else if(!RestartScan)
+  {
+    SkipEntries = *Context;
+  }
+
+  Status = ObReferenceObjectByHandle(DirectoryHandle,
+                                     DIRECTORY_QUERY,
+                                     ObDirectoryType,
+                                     PreviousMode,
+                                     (PVOID*)&Directory,
+                                     NULL);
+  if(NT_SUCCESS(Status))
+  {
+    PVOID TemporaryBuffer = ExAllocatePool(NonPagedPool,
+                                           BufferLength);
+    if(TemporaryBuffer != NULL)
+    {
+      POBJECT_HEADER EntryHeader;
+      PLIST_ENTRY ListEntry;
+      KIRQL OldLevel;
+      ULONG RequiredSize = sizeof(OBJECT_DIRECTORY_INFORMATION);
+      ULONG nDirectories = 0;
+      POBJECT_DIRECTORY_INFORMATION DirInfo = (POBJECT_DIRECTORY_INFORMATION)TemporaryBuffer;
+
+      Status = STATUS_NO_MORE_ENTRIES;
+
+      KeAcquireSpinLock(&Directory->Lock, &OldLevel);
+
+      for(ListEntry = Directory->head.Flink;
+          ListEntry != &Directory->head;
+          ListEntry = ListEntry->Flink)
+      {
+        NextEntry++;
+        if(SkipEntries == 0)
+        {
+          PUNICODE_STRING Name, Type;
+          ULONG EntrySize;
+
+          EntryHeader = CONTAINING_RECORD(ListEntry, OBJECT_HEADER, Entry);
+
+          /* calculate the size of the required buffer space for this entry */
+          Name = (HEADER_TO_OBJECT_NAME(EntryHeader)->Name.Length != 0 ? &HEADER_TO_OBJECT_NAME(EntryHeader)->Name : NULL);
+          Type = &EntryHeader->Type->Name;
+          EntrySize = sizeof(OBJECT_DIRECTORY_INFORMATION) +
+                      ((Name != NULL) ? ((ULONG)Name->Length + sizeof(WCHAR)) : 0) +
+                      (ULONG)EntryHeader->Type->Name.Length + sizeof(WCHAR);
+
+          if(RequiredSize + EntrySize <= BufferLength)
+          {
+            /* the buffer is large enough to receive this entry. It would've
+               been much easier if the strings were directly appended to the
+               OBJECT_DIRECTORY_INFORMATION structured written into the buffer */
+            if(Name != NULL)
+              DirInfo->ObjectName = *Name;
+            else
+            {
+              DirInfo->ObjectName.Length = DirInfo->ObjectName.MaximumLength = 0;
+              DirInfo->ObjectName.Buffer = NULL;
+            }
+            DirInfo->ObjectTypeName = *Type;
+
+            nDirectories++;
+            RequiredSize += EntrySize;
+
+            Status = STATUS_SUCCESS;
+
+            if(ReturnSingleEntry)
+            {
+              /* we're only supposed to query one entry, so bail and copy the
+                 strings to the buffer */
+              break;
+            }
+            DirInfo++;
+          }
+          else
+          {
+            if(ReturnSingleEntry)
+            {
+              /* the buffer is too small, so return the number of bytes that
+                 would've been required for this query */
+              RequiredSize += EntrySize;
+              Status = STATUS_BUFFER_TOO_SMALL;
+            }
+
+            /* we couldn't query this entry, so leave the index that will be stored
+               in Context to this entry so the caller can query it the next time
+               he queries (hopefully with a buffer that is large enough then...) */
+            NextEntry--;
+
+            /* just copy the entries that fit into the buffer */
+            break;
+          }
+        }
+        else
+        {
+          /* skip the entry */
+          SkipEntries--;
+        }
+      }
+
+      if(!ReturnSingleEntry && ListEntry != &Directory->head)
+      {
+        /* there are more entries to enumerate but the buffer is already full.
+           only tell this to the user if he queries multiple entries */
+        Status = STATUS_MORE_ENTRIES;
+      }
+
+      if(NT_SUCCESS(Status) && nDirectories > 0)
+      {
+        PWSTR strbuf = (PWSTR)((POBJECT_DIRECTORY_INFORMATION)TemporaryBuffer + nDirectories + 1);
+        PWSTR deststrbuf = (PWSTR)((POBJECT_DIRECTORY_INFORMATION)Buffer + nDirectories + 1);
+        memset((POBJECT_DIRECTORY_INFORMATION)TemporaryBuffer + nDirectories, 0, sizeof(OBJECT_DIRECTORY_INFORMATION));
+
+        CopyBytes = (nDirectories + 1) * sizeof(OBJECT_DIRECTORY_INFORMATION);
+
+        /* copy the names from the objects and append them to the list of the
+           objects. copy to the temporary buffer only because the directory
+           lock can't be released and the buffer might be pagable memory! */
+        for(DirInfo = (POBJECT_DIRECTORY_INFORMATION)TemporaryBuffer;
+            nDirectories > 0;
+            nDirectories--, DirInfo++)
+        {
+          ULONG NameLength;
+
+          if(DirInfo->ObjectName.Length > 0)
+          {
+            RtlCopyMemory(strbuf,
+                          DirInfo->ObjectName.Buffer,
+                          DirInfo->ObjectName.Length);
+            /* change the buffer pointer to the buffer */
+            DirInfo->ObjectName.Buffer = deststrbuf;
+            NameLength = DirInfo->ObjectName.Length / sizeof(WCHAR);
+            /* NULL-terminate the string */
+            strbuf[NameLength] = L'\0';
+            strbuf += NameLength + 1;
+            deststrbuf += NameLength + 1;
+
+            CopyBytes += (NameLength + 1) * sizeof(WCHAR);
+          }
+
+          RtlCopyMemory(strbuf,
+                        DirInfo->ObjectTypeName.Buffer,
+                        DirInfo->ObjectTypeName.Length);
+          /* change the buffer pointer to the buffer */
+          DirInfo->ObjectTypeName.Buffer = deststrbuf;
+          NameLength = DirInfo->ObjectTypeName.Length / sizeof(WCHAR);
+          /* NULL-terminate the string */
+          strbuf[NameLength] = L'\0';
+          strbuf += NameLength + 1;
+          deststrbuf += NameLength + 1;
+
+          CopyBytes += (NameLength + 1) * sizeof(WCHAR);
+        }
+      }
+
+      KeReleaseSpinLock(&Directory->Lock, OldLevel);
+      ObDereferenceObject(Directory);
+
+      if(NT_SUCCESS(Status) || ReturnSingleEntry)
+      {
+        _SEH_TRY
+        {
+          if(CopyBytes != 0)
+          {
+            RtlCopyMemory(Buffer,
+                          TemporaryBuffer,
+                          CopyBytes);
+          }
+          *Context = NextEntry;
+          if(ReturnLength != NULL)
+          {
+            *ReturnLength = RequiredSize;
+          }
+        }
+        _SEH_HANDLE
+        {
+          Status = _SEH_GetExceptionCode();
+        }
+        _SEH_END;
+      }
+
+      ExFreePool(TemporaryBuffer);
+    }
+    else
+    {
+      Status = STATUS_INSUFFICIENT_RESOURCES;
+    }
+  }
+
+  return Status;
 }
 
-VOID InitializeObjectAttributes(POBJECT_ATTRIBUTES InitializedAttributes,
-                               PUNICODE_STRING ObjectName,
-                               ULONG Attributes,
-                               HANDLE RootDirectory,
-                               PSECURITY_DESCRIPTOR SecurityDescriptor)
-/*
- * FUNCTION: Sets up a parameter of type OBJECT_ATTRIBUTES for a 
- * subsequent call to ZwCreateXXX or ZwOpenXXX
- * ARGUMENTS:
- *        InitializedAttributes (OUT) = Caller supplied storage for the
- *                                      object attributes
- *        ObjectName = Full path name for object
- *        Attributes = Attributes for the object
- *        RootDirectory = Where the object should be placed or NULL
- *        SecurityDescriptor = Ignored
- * 
- * NOTE:
- *     Either ObjectName is a fully qualified pathname or a path relative
- *     to RootDirectory
+
+/**********************************************************************
+ * NAME                                                (EXPORTED as Zw)
+ *     NtCreateDirectoryObject
+ *
+ * DESCRIPTION
+ *     Creates or opens a directory object (a container for other
+ *     objects).
+ *
+ * ARGUMENTS
+ *     DirectoryHandle (OUT)
+ *             Caller supplied storage for the handle of the
+ *             directory.
+ *
+ *     DesiredAccess
+ *             Access desired to the directory.
+ *
+ *     ObjectAttributes
+ *             Object attributes initialized with
+ *             InitializeObjectAttributes.
+ *
+ * RETURN VALUE
+ *     Status.
  */
+NTSTATUS STDCALL
+NtCreateDirectoryObject (OUT PHANDLE DirectoryHandle,
+                        IN ACCESS_MASK DesiredAccess,
+                        IN POBJECT_ATTRIBUTES ObjectAttributes)
 {
-   DPRINT("InitializeObjectAttributes(InitializedAttributes %x "
-         "ObjectName %x Attributes %x RootDirectory %x)\n",
-         InitializedAttributes,ObjectName,Attributes,RootDirectory);
-   InitializedAttributes->Length=sizeof(OBJECT_ATTRIBUTES);
-   InitializedAttributes->RootDirectory=RootDirectory;
-   InitializedAttributes->ObjectName=ObjectName;
-   InitializedAttributes->Attributes=Attributes;
-   InitializedAttributes->SecurityDescriptor=SecurityDescriptor;
-   InitializedAttributes->SecurityQualityOfService=NULL;
+  PDIRECTORY_OBJECT Directory;
+  HANDLE hDirectory;
+  KPROCESSOR_MODE PreviousMode;
+  NTSTATUS Status = STATUS_SUCCESS;
+
+  PAGED_CODE();
+
+  DPRINT("NtCreateDirectoryObject(DirectoryHandle %x, "
+         "DesiredAccess %x, ObjectAttributes %x\n",
+          DirectoryHandle, DesiredAccess, ObjectAttributes);
+
+  PreviousMode = ExGetPreviousMode();
+
+  if(PreviousMode != KernelMode)
+  {
+    _SEH_TRY
+    {
+      ProbeForWriteHandle(DirectoryHandle);
+    }
+    _SEH_HANDLE
+    {
+      Status = _SEH_GetExceptionCode();
+    }
+    _SEH_END;
+
+    if(!NT_SUCCESS(Status))
+    {
+      DPRINT1("NtCreateDirectoryObject failed, Status: 0x%x\n", Status);
+      return Status;
+    }
+  }
+
+  Status = ObCreateObject(PreviousMode,
+                          ObDirectoryType,
+                          ObjectAttributes,
+                          PreviousMode,
+                          NULL,
+                          sizeof(DIRECTORY_OBJECT),
+                          0,
+                          0,
+                          (PVOID*)&Directory);
+
+  if(NT_SUCCESS(Status))
+  {
+    Status = ObInsertObject((PVOID)Directory,
+                            NULL,
+                            DesiredAccess,
+                            0,
+                            NULL,
+                            &hDirectory);
+    if (!NT_SUCCESS(Status))
+    {
+       ObMakeTemporaryObject(Directory);
+    }
+    ObDereferenceObject(Directory);
+
+    if(NT_SUCCESS(Status))
+    {
+      _SEH_TRY
+      {
+        *DirectoryHandle = hDirectory;
+      }
+      _SEH_HANDLE
+      {
+        Status = _SEH_GetExceptionCode();
+      }
+      _SEH_END;
+    }
+  }
+
+  return Status;
 }
 
+/* EOF */