[NTOSKRNL] Modify ObpCreateDeviceMap so that it can handle any process
authorPierre Schweitzer <pierre@reactos.org>
Sat, 1 Jun 2019 11:35:41 +0000 (13:35 +0200)
committerPierre Schweitzer <pierre@reactos.org>
Sat, 1 Jun 2019 11:35:41 +0000 (13:35 +0200)
It is now able to set the newly created device map to any
process and will default to current process if none is provided.
It also sets system device map if no process is specified.
It also deferences existing device map in the process if needed.
Finaly, it will make the directory object permanant.

ntoskrnl/include/internal/ob.h
ntoskrnl/ob/devicemap.c
ntoskrnl/ob/obname.c

index ce8c5a0..b2d7037 100644 (file)
@@ -399,9 +399,9 @@ ObReferenceFileObjectForWrite(
 //
 NTSTATUS
 NTAPI
-ObpCreateDeviceMap(
-    IN HANDLE DirectoryHandle
-);
+ObSetDeviceMap(
+    IN PEPROCESS Process,
+    IN HANDLE DirectoryHandle);
 
 VOID
 NTAPI
index 32f45fa..c79838b 100644 (file)
 
 NTSTATUS
 NTAPI
-ObpCreateDeviceMap(IN HANDLE DirectoryHandle)
+ObSetDeviceMap(IN PEPROCESS Process,
+               IN HANDLE DirectoryHandle)
 {
     POBJECT_DIRECTORY DirectoryObject = NULL;
-    PDEVICE_MAP DeviceMap = NULL;
+    PDEVICE_MAP DeviceMap = NULL, NewDeviceMap = NULL, OldDeviceMap;
     NTSTATUS Status;
+    PEPROCESS WorkProcess;
+    BOOLEAN MakePermanant = FALSE;
 
     Status = ObReferenceObjectByHandle(DirectoryHandle,
                                        DIRECTORY_TRAVERSE,
@@ -36,7 +39,7 @@ ObpCreateDeviceMap(IN HANDLE DirectoryHandle)
     }
 
     /* Allocate and initialize a new device map */
-    DeviceMap = ExAllocatePoolWithTag(NonPagedPool,
+    DeviceMap = ExAllocatePoolWithTag(PagedPool,
                                       sizeof(*DeviceMap),
                                       'mDbO');
     if (DeviceMap == NULL)
@@ -54,15 +57,85 @@ ObpCreateDeviceMap(IN HANDLE DirectoryHandle)
     KeAcquireGuardedMutex(&ObpDeviceMapLock);
 
     /* Attach the device map to the directory object */
-    DirectoryObject->DeviceMap = DeviceMap;
+    if (DirectoryObject->DeviceMap == NULL)
+    {
+        DirectoryObject->DeviceMap = DeviceMap;
+    }
+    else
+    {
+        NewDeviceMap = DeviceMap;
+
+        /* There's already a device map,
+           so reuse it */
+        DeviceMap = DirectoryObject->DeviceMap;
+        ++DeviceMap->ReferenceCount;
+    }
+
+    /* Caller gave a process, use it */
+    if (Process != NULL)
+    {
+        WorkProcess = Process;
+    }
+    /* If no process given, use current and
+     * set system device map */
+    else
+    {
+        WorkProcess = PsGetCurrentProcess();
+        ObSystemDeviceMap = DeviceMap;
+    }
+
+    /* If current object isn't system one, save system one in current
+     * device map */
+    if (DirectoryObject != ObSystemDeviceMap->DosDevicesDirectory)
+    {
+        /* We also need to make the object permanant */
+        DeviceMap->GlobalDosDevicesDirectory = ObSystemDeviceMap->DosDevicesDirectory;
+        MakePermanant = TRUE;
+    }
 
+    /* Save old process device map */
+    OldDeviceMap = WorkProcess->DeviceMap;
     /* Attach the device map to the process */
-    ObSystemDeviceMap = DeviceMap;
-    PsGetCurrentProcess()->DeviceMap = DeviceMap;
+    WorkProcess->DeviceMap = DeviceMap;
 
     /* Release the device map lock */
     KeReleaseGuardedMutex(&ObpDeviceMapLock);
 
+    /* If we have to make the object permamant, do it now */
+    if (MakePermanant)
+    {
+        POBJECT_HEADER ObjectHeader;
+        POBJECT_HEADER_NAME_INFO HeaderNameInfo;
+
+        ObjectHeader = OBJECT_TO_OBJECT_HEADER(DirectoryObject);
+        HeaderNameInfo = ObpReferenceNameInfo(ObjectHeader);
+
+        ObpEnterObjectTypeMutex(ObjectHeader->Type);
+        if (HeaderNameInfo != NULL && HeaderNameInfo->Directory != NULL)
+        {
+            ObjectHeader->Flags |= OB_FLAG_PERMANENT;
+        }
+        ObpLeaveObjectTypeMutex(ObjectHeader->Type);
+
+        if (HeaderNameInfo != NULL)
+        {
+            ObpDereferenceNameInfo(HeaderNameInfo);
+        }
+    }
+
+    /* Release useless device map if required */
+    if (NewDeviceMap != NULL)
+    {
+        ObfDereferenceObject(DirectoryObject);
+        ExFreePoolWithTag(NewDeviceMap, 'mDbO');
+    }
+
+    /* And dereference previous process device map */
+    if (OldDeviceMap != NULL)
+    {
+        ObfDereferenceDeviceMap(OldDeviceMap);
+    }
+
     return STATUS_SUCCESS;
 }
 
index f9ccb91..6c99613 100644 (file)
@@ -173,7 +173,7 @@ ObpCreateDosDevicesDirectory(VOID)
         goto done;
 
     /* Create the system device map */
-    Status = ObpCreateDeviceMap(Handle);
+    Status = ObSetDeviceMap(NULL, Handle);
     if (!NT_SUCCESS(Status))
         goto done;