diff --git a/ntoskrnl/include/internal/ob.h b/ntoskrnl/include/internal/ob.h index ce8c5a0dc75..b2d7037d9dc 100644 --- a/ntoskrnl/include/internal/ob.h +++ b/ntoskrnl/include/internal/ob.h @@ -399,9 +399,9 @@ ObReferenceFileObjectForWrite( // NTSTATUS NTAPI -ObpCreateDeviceMap( - IN HANDLE DirectoryHandle -); +ObSetDeviceMap( + IN PEPROCESS Process, + IN HANDLE DirectoryHandle); VOID NTAPI diff --git a/ntoskrnl/ob/devicemap.c b/ntoskrnl/ob/devicemap.c index 32f45fa4a64..c79838bbabd 100644 --- a/ntoskrnl/ob/devicemap.c +++ b/ntoskrnl/ob/devicemap.c @@ -17,11 +17,14 @@ 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; } diff --git a/ntoskrnl/ob/obname.c b/ntoskrnl/ob/obname.c index f9ccb914022..6c996132d87 100644 --- a/ntoskrnl/ob/obname.c +++ b/ntoskrnl/ob/obname.c @@ -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;