- Fix compile issues caused by previous patch.
[reactos.git] / reactos / ntoskrnl / ob / dirobj.c
index fab1f3d..e2558f0 100644 (file)
@@ -4,7 +4,7 @@
  * PROJECT:        ReactOS kernel
  * FILE:           ntoskrnl/ob/dirobj.c
  * PURPOSE:        Interface functions to directory object
- * 
+ *
  * PROGRAMMERS:    David Welch (welch@mcmail.com)
  */
 
  *
  * 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.
  */
@@ -49,30 +49,30 @@ NtOpenDirectoryObject (OUT PHANDLE DirectoryHandle,
    HANDLE hDirectory;
    KPROCESSOR_MODE PreviousMode;
    NTSTATUS Status = STATUS_SUCCESS;
-   
+
+   PAGED_CODE();
+
    PreviousMode = ExGetPreviousMode();
-   
+
    if(PreviousMode != KernelMode)
    {
      _SEH_TRY
      {
-       ProbeForWrite(DirectoryHandle,
-                     sizeof(HANDLE),
-                     sizeof(ULONG));
+       ProbeForWriteHandle(DirectoryHandle);
      }
      _SEH_HANDLE
      {
        Status = _SEH_GetExceptionCode();
      }
      _SEH_END;
-     
+
      if(!NT_SUCCESS(Status))
      {
        DPRINT1("NtOpenDirectoryObject failed, Status: 0x%x\n", Status);
        return Status;
      }
    }
-   
+
    Status = ObOpenObjectByName(ObjectAttributes,
                                ObDirectoryType,
                                NULL,
@@ -92,7 +92,7 @@ NtOpenDirectoryObject (OUT PHANDLE DirectoryHandle,
      }
      _SEH_END;
    }
-   
+
    return Status;
 }
 
@@ -100,35 +100,35 @@ NtOpenDirectoryObject (OUT PHANDLE DirectoryHandle,
 /**********************************************************************
  * 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).
@@ -167,8 +167,11 @@ NtQueryDirectoryObject (IN HANDLE DirectoryHandle,
   KPROCESSOR_MODE PreviousMode;
   ULONG SkipEntries = 0;
   ULONG NextEntry = 0;
+  ULONG CopyBytes = 0;
   NTSTATUS Status = STATUS_SUCCESS;
-  
+
+  PAGED_CODE();
+
   PreviousMode = ExGetPreviousMode();
 
   if(PreviousMode != KernelMode)
@@ -181,18 +184,14 @@ NtQueryDirectoryObject (IN HANDLE DirectoryHandle,
       ProbeForWrite(Buffer,
                     BufferLength,
                     sizeof(WCHAR));
-      ProbeForWrite(Context,
-                    sizeof(ULONG),
-                    sizeof(ULONG));
+      ProbeForWriteUlong(Context);
       if(!RestartScan)
       {
         SkipEntries = *Context;
       }
       if(ReturnLength != NULL)
       {
-        ProbeForWrite(ReturnLength,
-                      sizeof(ULONG),
-                      sizeof(ULONG));
+        ProbeForWriteUlong(ReturnLength);
       }
     }
     _SEH_HANDLE
@@ -211,7 +210,7 @@ NtQueryDirectoryObject (IN HANDLE DirectoryHandle,
   {
     SkipEntries = *Context;
   }
-  
+
   Status = ObReferenceObjectByHandle(DirectoryHandle,
                                      DIRECTORY_QUERY,
                                      ObDirectoryType,
@@ -220,17 +219,17 @@ NtQueryDirectoryObject (IN HANDLE DirectoryHandle,
                                      NULL);
   if(NT_SUCCESS(Status))
   {
-    PVOID TemporaryBuffer = ExAllocatePool(PagedPool,
+    PVOID TemporaryBuffer = ExAllocatePool(NonPagedPool,
                                            BufferLength);
     if(TemporaryBuffer != NULL)
     {
       POBJECT_HEADER EntryHeader;
       PLIST_ENTRY ListEntry;
       KIRQL OldLevel;
-      ULONG RequiredSize = 0;
+      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);
@@ -248,11 +247,11 @@ NtQueryDirectoryObject (IN HANDLE DirectoryHandle,
           EntryHeader = CONTAINING_RECORD(ListEntry, OBJECT_HEADER, Entry);
 
           /* calculate the size of the required buffer space for this entry */
-          Name = (EntryHeader->Name.Length != 0 ? &EntryHeader->Name : NULL);
-          Type = &EntryHeader->ObjectType->TypeName;
+          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->ObjectType->TypeName.Length + sizeof(WCHAR);
+                      (ULONG)EntryHeader->Type->Name.Length + sizeof(WCHAR);
 
           if(RequiredSize + EntrySize <= BufferLength)
           {
@@ -270,7 +269,7 @@ NtQueryDirectoryObject (IN HANDLE DirectoryHandle,
 
             nDirectories++;
             RequiredSize += EntrySize;
-            
+
             Status = STATUS_SUCCESS;
 
             if(ReturnSingleEntry)
@@ -290,12 +289,12 @@ NtQueryDirectoryObject (IN HANDLE DirectoryHandle,
               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;
           }
@@ -306,7 +305,7 @@ NtQueryDirectoryObject (IN HANDLE DirectoryHandle,
           SkipEntries--;
         }
       }
-      
+
       if(!ReturnSingleEntry && ListEntry != &Directory->head)
       {
         /* there are more entries to enumerate but the buffer is already full.
@@ -314,63 +313,67 @@ NtQueryDirectoryObject (IN HANDLE DirectoryHandle,
         Status = STATUS_MORE_ENTRIES;
       }
 
-      if(NT_SUCCESS(Status))
+      if(NT_SUCCESS(Status) && nDirectories > 0)
       {
-        if(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++)
         {
-          _SEH_TRY
-          {
-            POBJECT_DIRECTORY_INFORMATION DestDirInfo = (POBJECT_DIRECTORY_INFORMATION)Buffer;
-            PWSTR strbuf = (PWSTR)((POBJECT_DIRECTORY_INFORMATION)Buffer + nDirectories);
-
-            /* copy all OBJECT_DIRECTORY_INFORMATION structures to the buffer and
-               just append all strings (whose pointers are stored in the buffer!)
-               and replace the pointers */
-            for(DirInfo = (POBJECT_DIRECTORY_INFORMATION)TemporaryBuffer;
-                nDirectories > 0;
-                nDirectories--, DirInfo++, DestDirInfo++)
-            {
-              if(DirInfo->ObjectName.Length > 0)
-              {
-                DestDirInfo->ObjectName.Length = DirInfo->ObjectName.Length;
-                DestDirInfo->ObjectName.MaximumLength = DirInfo->ObjectName.MaximumLength;
-                DestDirInfo->ObjectName.Buffer = strbuf;
-                RtlCopyMemory(strbuf,
-                              DirInfo->ObjectName.Buffer,
-                              DirInfo->ObjectName.Length);
-                /* NULL-terminate the string */
-                strbuf[DirInfo->ObjectName.Length / sizeof(WCHAR)] = L'\0';
-                strbuf += (DirInfo->ObjectName.Length / sizeof(WCHAR)) + 1;
-              }
-              
-              DestDirInfo->ObjectTypeName.Length = DirInfo->ObjectTypeName.Length;
-              DestDirInfo->ObjectTypeName.MaximumLength = DirInfo->ObjectTypeName.MaximumLength;
-              DestDirInfo->ObjectTypeName.Buffer = strbuf;
-              RtlCopyMemory(strbuf,
-                            DirInfo->ObjectTypeName.Buffer,
-                            DirInfo->ObjectTypeName.Length);
-              /* NULL-terminate the string */
-              strbuf[DirInfo->ObjectTypeName.Length / sizeof(WCHAR)] = L'\0';
-              strbuf += (DirInfo->ObjectTypeName.Length / sizeof(WCHAR)) + 1;
-            }
-          }
-          _SEH_HANDLE
+          ULONG NameLength;
+
+          if(DirInfo->ObjectName.Length > 0)
           {
-            Status = _SEH_GetExceptionCode();
+            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);
           }
-          _SEH_END;
+
+          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);
-      
-      ExFreePool(TemporaryBuffer);
 
       if(NT_SUCCESS(Status) || ReturnSingleEntry)
       {
         _SEH_TRY
         {
+          if(CopyBytes != 0)
+          {
+            RtlCopyMemory(Buffer,
+                          TemporaryBuffer,
+                          CopyBytes);
+          }
           *Context = NextEntry;
           if(ReturnLength != NULL)
           {
@@ -383,13 +386,15 @@ NtQueryDirectoryObject (IN HANDLE DirectoryHandle,
         }
         _SEH_END;
       }
+
+      ExFreePool(TemporaryBuffer);
     }
     else
     {
       Status = STATUS_INSUFFICIENT_RESOURCES;
     }
   }
-  
+
   return Status;
 }
 
@@ -397,23 +402,23 @@ NtQueryDirectoryObject (IN HANDLE DirectoryHandle,
 /**********************************************************************
  * 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 
+ *             Caller supplied storage for the handle of the
  *             directory.
- *             
+ *
  *     DesiredAccess
  *             Access desired to the directory.
- *             
+ *
  *     ObjectAttributes
  *             Object attributes initialized with
  *             InitializeObjectAttributes.
- *             
+ *
  * RETURN VALUE
  *     Status.
  */
@@ -426,10 +431,12 @@ NtCreateDirectoryObject (OUT PHANDLE DirectoryHandle,
   HANDLE hDirectory;
   KPROCESSOR_MODE PreviousMode;
   NTSTATUS Status = STATUS_SUCCESS;
-  
+
+  PAGED_CODE();
+
   DPRINT("NtCreateDirectoryObject(DirectoryHandle %x, "
-        "DesiredAccess %x, ObjectAttributes %x\n",
-        DirectoryHandle, DesiredAccess, ObjectAttributes);
+         "DesiredAccess %x, ObjectAttributes %x\n",
+          DirectoryHandle, DesiredAccess, ObjectAttributes);
 
   PreviousMode = ExGetPreviousMode();
 
@@ -437,9 +444,7 @@ NtCreateDirectoryObject (OUT PHANDLE DirectoryHandle,
   {
     _SEH_TRY
     {
-      ProbeForWrite(DirectoryHandle,
-                    sizeof(HANDLE),
-                    sizeof(ULONG));
+      ProbeForWriteHandle(DirectoryHandle);
     }
     _SEH_HANDLE
     {
@@ -463,6 +468,7 @@ NtCreateDirectoryObject (OUT PHANDLE DirectoryHandle,
                           0,
                           0,
                           (PVOID*)&Directory);
+
   if(NT_SUCCESS(Status))
   {
     Status = ObInsertObject((PVOID)Directory,
@@ -471,6 +477,10 @@ NtCreateDirectoryObject (OUT PHANDLE DirectoryHandle,
                             0,
                             NULL,
                             &hDirectory);
+    if (!NT_SUCCESS(Status))
+    {
+       ObMakeTemporaryObject(Directory);
+    }
     ObDereferenceObject(Directory);
 
     if(NT_SUCCESS(Status))