ObpCreateDosDevicesDirectory(VOID)
{
OBJECT_ATTRIBUTES ObjectAttributes;
- UNICODE_STRING Name, LinkName;
+ UNICODE_STRING RootName, TargetName, LinkName;
HANDLE Handle, SymHandle;
NTSTATUS Status;
- /* Create the '\??' directory */
- RtlInitUnicodeString(&Name, L"\\??");
+ /* Create the global DosDevices directory \?? */
+ RtlInitUnicodeString(&RootName, L"\\GLOBAL??");
InitializeObjectAttributes(&ObjectAttributes,
- &Name,
+ &RootName,
OBJ_PERMANENT,
NULL,
NULL);
Status = NtCreateDirectoryObject(&Handle,
DIRECTORY_ALL_ACCESS,
&ObjectAttributes);
- if (!NT_SUCCESS(Status)) return FALSE;
+ if (!NT_SUCCESS(Status)) return Status;
+
+ /*********************************************\
+ |*** HACK until we support device mappings ***|
+ |*** Add a symlink \??\ <--> \GLOBAL??\ ***|
+ \*********************************************/
+ RtlInitUnicodeString(&LinkName, L"\\??");
+ InitializeObjectAttributes(&ObjectAttributes,
+ &LinkName,
+ OBJ_PERMANENT,
+ NULL,
+ NULL);
+ Status = NtCreateSymbolicLinkObject(&SymHandle,
+ SYMBOLIC_LINK_ALL_ACCESS,
+ &ObjectAttributes,
+ &RootName);
+ if (NT_SUCCESS(Status)) NtClose(SymHandle);
+ /*********************************************\
+ \*********************************************/
- /* Initialize the GLOBALROOT path */
+ // FIXME: Create a device mapping for the global \?? directory
+
+ /*
+ * Initialize the \??\GLOBALROOT symbolic link
+ * pointing to the root directory \ .
+ */
RtlInitUnicodeString(&LinkName, L"GLOBALROOT");
- RtlInitUnicodeString(&Name, L"");
+ RtlInitUnicodeString(&TargetName, L"");
InitializeObjectAttributes(&ObjectAttributes,
&LinkName,
OBJ_PERMANENT,
Status = NtCreateSymbolicLinkObject(&SymHandle,
SYMBOLIC_LINK_ALL_ACCESS,
&ObjectAttributes,
- &Name);
+ &TargetName);
if (NT_SUCCESS(Status)) NtClose(SymHandle);
- /* Link \??\Global to \?? */
+ /*
+ * Initialize the \??\Global symbolic link pointing to the global
+ * DosDevices directory \?? . It is used to access the global \??
+ * by user-mode components which, by default, use a per-session
+ * DosDevices directory.
+ */
RtlInitUnicodeString(&LinkName, L"Global");
- RtlInitUnicodeString(&Name, L"\\??");
InitializeObjectAttributes(&ObjectAttributes,
&LinkName,
OBJ_PERMANENT,
Status = NtCreateSymbolicLinkObject(&SymHandle,
SYMBOLIC_LINK_ALL_ACCESS,
&ObjectAttributes,
- &Name);
+ &RootName);
if (NT_SUCCESS(Status)) NtClose(SymHandle);
/* Close the directory handle */
NtClose(Handle);
if (!NT_SUCCESS(Status)) return Status;
- /* Create link from '\DosDevices' to '\??' directory */
+ /*
+ * Initialize the \DosDevices symbolic link pointing to the global
+ * DosDevices directory \?? , for backward compatibility with
+ * Windows NT-2000 systems.
+ */
RtlCreateUnicodeString(&LinkName, L"\\DosDevices");
+ RtlInitUnicodeString(&RootName, (PCWSTR)&ObpDosDevicesShortNameRoot);
InitializeObjectAttributes(&ObjectAttributes,
&LinkName,
OBJ_PERMANENT,
Status = NtCreateSymbolicLinkObject(&SymHandle,
SYMBOLIC_LINK_ALL_ACCESS,
&ObjectAttributes,
- &Name);
+ &RootName);
if (NT_SUCCESS(Status)) NtClose(SymHandle);
/* FIXME: Hack Hack! */
NTAPI
ObDereferenceDeviceMap(IN PEPROCESS Process)
{
- //KIRQL OldIrql;
- PDEVICE_MAP DeviceMap = Process->DeviceMap;
+ PDEVICE_MAP DeviceMap;
- /* FIXME: We don't use Process Devicemaps yet */
+ /* Get the pointer to this process devicemap and reset it
+ holding devicemap lock */
+ KeAcquireGuardedMutex(&ObpDeviceMapLock);
+ DeviceMap = Process->DeviceMap;
+ Process->DeviceMap = NULL;
+ KeReleaseGuardedMutex(&ObpDeviceMapLock);
+
+ /* Continue only if there is a devicemap to dereference */
if (DeviceMap)
{
- /* FIXME: Acquire the DeviceMap Spinlock */
- // KeAcquireSpinLock(DeviceMap->Lock, &OldIrql);
+ KeAcquireGuardedMutex(&ObpDeviceMapLock);
/* Delete the device map link and dereference it */
- Process->DeviceMap = NULL;
if (--DeviceMap->ReferenceCount)
{
/* Nobody is referencing it anymore, unlink the DOS directory */
DeviceMap->DosDevicesDirectory->DeviceMap = NULL;
- /* FIXME: Release the DeviceMap Spinlock */
- // KeReleasepinLock(DeviceMap->Lock, OldIrql);
+ /* Release the devicemap lock */
+ KeReleaseGuardedMutex(&ObpDeviceMapLock);
/* Dereference the DOS Devices Directory and free the Device Map */
ObDereferenceObject(DeviceMap->DosDevicesDirectory);
}
else
{
- /* FIXME: Release the DeviceMap Spinlock */
- // KeReleasepinLock(DeviceMap->Lock, OldIrql);
+ /* Release the devicemap lock */
+ KeReleaseGuardedMutex(&ObpDeviceMapLock);
}
}
}
}
else if (!(ObjectName->Length) || !(ObjectName->Buffer))
{
- /* Just return the Root Directory if we didn't get a name*/
+ /* Just return the Root Directory if we didn't get a name */
Status = ObReferenceObjectByPointer(RootDirectory,
0,
ObjectType,
}
/* Reparse */
- while (Reparse)
+ while (Reparse && MaxReparse)
{
/* Get the name */
RemainingName = *ObjectName;
ObjectHeader)))
{
/* Either couldn't allocate the name, or insert failed */
- if (NewName) ExFreePool(NewName);
+ if (NewName) ExFreePoolWithTag(NewName, OB_NAME_TAG);
/* Fail due to memory reasons */
Status = STATUS_INSUFFICIENT_RESOURCES;
if (ObjectNameInfo->Name.Buffer)
{
/* Free it */
- ExFreePoolWithTag(ObjectNameInfo->Name.Buffer, OB_NAME_TAG );
+ ExFreePoolWithTag(ObjectNameInfo->Name.Buffer, OB_NAME_TAG);
}
/* Write new one */
{
/* Reparse again */
Reparse = TRUE;
+ --MaxReparse;
+ if (MaxReparse == 0)
+ {
+ Object = NULL;
+ break;
+ }
/* Start over from root if we got sent back there */
if ((Status == STATUS_REPARSE_OBJECT) ||
ULONG NameSize;
PWCH ObjectName;
BOOLEAN ObjectIsNamed;
+ NTSTATUS Status = STATUS_SUCCESS;
/* Get the Kernel Meta-Structures */
ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
/* Check if a Query Name Procedure is available */
if (ObjectHeader->Type->TypeInfo.QueryNameProcedure)
{
- /* Call the procedure */
+ /* Call the procedure inside SEH */
ObjectIsNamed = ((LocalInfo) && (LocalInfo->Name.Length > 0));
- return ObjectHeader->Type->TypeInfo.QueryNameProcedure(Object,
+
+ _SEH2_TRY
+ {
+ Status = ObjectHeader->Type->TypeInfo.QueryNameProcedure(Object,
ObjectIsNamed,
ObjectNameInfo,
Length,
ReturnLength,
KernelMode);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Return the exception code */
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
+
+ return Status;
}
/* Check if the object doesn't even have a name */
if (!(LocalInfo) || !(LocalInfo->Name.Buffer))
{
- /* We're returning the name structure */
- *ReturnLength = sizeof(OBJECT_NAME_INFORMATION);
+ Status = STATUS_SUCCESS;
- /* Check if we were given enough space */
- if (*ReturnLength > Length) return STATUS_INFO_LENGTH_MISMATCH;
+ _SEH2_TRY
+ {
+ /* We're returning the name structure */
+ *ReturnLength = sizeof(OBJECT_NAME_INFORMATION);
+
+ /* Check if we were given enough space */
+ if (*ReturnLength > Length)
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ }
+ else
+ {
+ /* Return an empty buffer */
+ RtlInitEmptyUnicodeString(&ObjectNameInfo->Name, NULL, 0);
+ }
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Return the exception code */
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
- /* Return an empty buffer */
- RtlInitEmptyUnicodeString(&ObjectNameInfo->Name, NULL, 0);
- return STATUS_SUCCESS;
+ return Status;
}
/*
* enough right at the beginning, not work our way through
* and find out at the end
*/
- if (Object == ObpRootDirectoryObject)
+ _SEH2_TRY
{
- /* Size of the '\' string */
- NameSize = sizeof(OBJ_NAME_PATH_SEPARATOR);
- }
- else
- {
- /* Get the Object Directory and add name of Object */
- ParentDirectory = LocalInfo->Directory;
- NameSize = sizeof(OBJ_NAME_PATH_SEPARATOR) + LocalInfo->Name.Length;
-
- /* Loop inside the directory to get the top-most one (meaning root) */
- while ((ParentDirectory != ObpRootDirectoryObject) && (ParentDirectory))
+ if (Object == ObpRootDirectoryObject)
+ {
+ /* Size of the '\' string */
+ NameSize = sizeof(OBJ_NAME_PATH_SEPARATOR);
+ }
+ else
{
- /* Get the Name Information */
- LocalInfo = OBJECT_HEADER_TO_NAME_INFO(
- OBJECT_TO_OBJECT_HEADER(ParentDirectory));
+ /* Get the Object Directory and add name of Object */
+ ParentDirectory = LocalInfo->Directory;
+ NameSize = sizeof(OBJ_NAME_PATH_SEPARATOR) + LocalInfo->Name.Length;
- /* Add the size of the Directory Name */
- if (LocalInfo && LocalInfo->Directory)
+ /* Loop inside the directory to get the top-most one (meaning root) */
+ while ((ParentDirectory != ObpRootDirectoryObject) && (ParentDirectory))
{
- /* Size of the '\' string + Directory Name */
- NameSize += sizeof(OBJ_NAME_PATH_SEPARATOR) +
- LocalInfo->Name.Length;
+ /* Get the Name Information */
+ LocalInfo = OBJECT_HEADER_TO_NAME_INFO(
+ OBJECT_TO_OBJECT_HEADER(ParentDirectory));
- /* Move to next parent Directory */
- ParentDirectory = LocalInfo->Directory;
- }
- else
- {
- /* Directory with no name. We append "...\" */
- NameSize += sizeof(L"...") + sizeof(OBJ_NAME_PATH_SEPARATOR);
- break;
+ /* Add the size of the Directory Name */
+ if (LocalInfo && LocalInfo->Directory)
+ {
+ /* Size of the '\' string + Directory Name */
+ NameSize += sizeof(OBJ_NAME_PATH_SEPARATOR) +
+ LocalInfo->Name.Length;
+
+ /* Move to next parent Directory */
+ ParentDirectory = LocalInfo->Directory;
+ }
+ else
+ {
+ /* Directory with no name. We append "...\" */
+ NameSize += sizeof(L"...") + sizeof(OBJ_NAME_PATH_SEPARATOR);
+ break;
+ }
}
}
- }
-
- /* Finally, add the name of the structure and the null char */
- *ReturnLength = NameSize +
- sizeof(OBJECT_NAME_INFORMATION) +
- sizeof(UNICODE_NULL);
- /* Check if we were given enough space */
- if (*ReturnLength > Length) return STATUS_INFO_LENGTH_MISMATCH;
+ /* Finally, add the name of the structure and the null char */
+ *ReturnLength = NameSize +
+ sizeof(OBJECT_NAME_INFORMATION) +
+ sizeof(UNICODE_NULL);
- /*
- * Now we will actually create the name. We work backwards because
- * it's easier to start off from the Name we have and walk up the
- * parent directories. We use the same logic as Name Length calculation.
- */
- LocalInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
- ObjectName = (PWCH)((ULONG_PTR)ObjectNameInfo + *ReturnLength);
- *--ObjectName = UNICODE_NULL;
-
- /* Check if the object is actually the Root directory */
- if (Object == ObpRootDirectoryObject)
- {
- /* This is already the Root Directory, return "\\" */
- *--ObjectName = OBJ_NAME_PATH_SEPARATOR;
- ObjectNameInfo->Name.Length = (USHORT)NameSize;
- ObjectNameInfo->Name.MaximumLength = (USHORT)(NameSize +
- sizeof(UNICODE_NULL));
- ObjectNameInfo->Name.Buffer = ObjectName;
- return STATUS_SUCCESS;
- }
- else
- {
- /* Start by adding the Object's Name */
- ObjectName = (PWCH)((ULONG_PTR)ObjectName -
- LocalInfo->Name.Length);
- RtlCopyMemory(ObjectName,
- LocalInfo->Name.Buffer,
- LocalInfo->Name.Length);
-
- /* Now parse the Parent directories until we reach the top */
- ParentDirectory = LocalInfo->Directory;
- while ((ParentDirectory != ObpRootDirectoryObject) && (ParentDirectory))
+ /* Check if we were given enough space */
+ if (*ReturnLength > Length) _SEH2_YIELD(return STATUS_INFO_LENGTH_MISMATCH);
+
+ /*
+ * Now we will actually create the name. We work backwards because
+ * it's easier to start off from the Name we have and walk up the
+ * parent directories. We use the same logic as Name Length calculation.
+ */
+ LocalInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
+ ObjectName = (PWCH)((ULONG_PTR)ObjectNameInfo + *ReturnLength);
+ *--ObjectName = UNICODE_NULL;
+
+ /* Check if the object is actually the Root directory */
+ if (Object == ObpRootDirectoryObject)
{
- /* Get the name information */
- LocalInfo = OBJECT_HEADER_TO_NAME_INFO(
- OBJECT_TO_OBJECT_HEADER(ParentDirectory));
+ /* This is already the Root Directory, return "\\" */
+ *--ObjectName = OBJ_NAME_PATH_SEPARATOR;
+ ObjectNameInfo->Name.Length = (USHORT)NameSize;
+ ObjectNameInfo->Name.MaximumLength = (USHORT)(NameSize +
+ sizeof(UNICODE_NULL));
+ ObjectNameInfo->Name.Buffer = ObjectName;
+ Status = STATUS_SUCCESS;
+ }
+ else
+ {
+ /* Start by adding the Object's Name */
+ ObjectName = (PWCH)((ULONG_PTR)ObjectName -
+ LocalInfo->Name.Length);
+ RtlCopyMemory(ObjectName,
+ LocalInfo->Name.Buffer,
+ LocalInfo->Name.Length);
+
+ /* Now parse the Parent directories until we reach the top */
+ ParentDirectory = LocalInfo->Directory;
+ while ((ParentDirectory != ObpRootDirectoryObject) && (ParentDirectory))
+ {
+ /* Get the name information */
+ LocalInfo = OBJECT_HEADER_TO_NAME_INFO(
+ OBJECT_TO_OBJECT_HEADER(ParentDirectory));
- /* Add the "\" */
- *(--ObjectName) = OBJ_NAME_PATH_SEPARATOR;
+ /* Add the "\" */
+ *(--ObjectName) = OBJ_NAME_PATH_SEPARATOR;
- /* Add the Parent Directory's Name */
- if (LocalInfo && LocalInfo->Name.Buffer)
- {
- /* Add the name */
- ObjectName = (PWCH)((ULONG_PTR)ObjectName -
- LocalInfo->Name.Length);
- RtlCopyMemory(ObjectName,
- LocalInfo->Name.Buffer,
- LocalInfo->Name.Length);
-
- /* Move to next parent */
- ParentDirectory = LocalInfo->Directory;
- }
- else
- {
- /* Directory without a name, we add "..." */
- ObjectName -= sizeof(L"...");
- ObjectName = L"...";
- break;
+ /* Add the Parent Directory's Name */
+ if (LocalInfo && LocalInfo->Name.Buffer)
+ {
+ /* Add the name */
+ ObjectName = (PWCH)((ULONG_PTR)ObjectName -
+ LocalInfo->Name.Length);
+ RtlCopyMemory(ObjectName,
+ LocalInfo->Name.Buffer,
+ LocalInfo->Name.Length);
+
+ /* Move to next parent */
+ ParentDirectory = LocalInfo->Directory;
+ }
+ else
+ {
+ /* Directory without a name, we add "..." */
+ ObjectName = (PWCH)((ULONG_PTR)ObjectName -
+ sizeof(L"...") +
+ sizeof(UNICODE_NULL));
+ RtlCopyMemory(ObjectName, L"...", sizeof(L"..."));
+ break;
+ }
}
- }
- /* Add Root Directory Name */
- *(--ObjectName) = OBJ_NAME_PATH_SEPARATOR;
- ObjectNameInfo->Name.Length = (USHORT)NameSize;
- ObjectNameInfo->Name.MaximumLength = (USHORT)(NameSize +
- sizeof(UNICODE_NULL));
- ObjectNameInfo->Name.Buffer = ObjectName;
+ /* Add Root Directory Name */
+ *(--ObjectName) = OBJ_NAME_PATH_SEPARATOR;
+ ObjectNameInfo->Name.Length = (USHORT)NameSize;
+ ObjectNameInfo->Name.MaximumLength =
+ (USHORT)(NameSize + sizeof(UNICODE_NULL));
+ ObjectNameInfo->Name.Buffer = ObjectName;
+ }
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Return the exception code */
+ Status = _SEH2_GetExceptionCode();
}
+ _SEH2_END;
/* Return success */
- return STATUS_SUCCESS;
+ return Status;
}
VOID
ObQueryDeviceMapInformation(IN PEPROCESS Process,
IN PPROCESS_DEVICEMAP_INFORMATION DeviceMapInfo)
{
- //KIRQL OldIrql ;
-
/*
* FIXME: This is an ugly hack for now, to always return the System Device Map
* instead of returning the Process Device Map. Not important yet since we don't use it
*/
- /* FIXME: Acquire the DeviceMap Spinlock */
- // KeAcquireSpinLock(DeviceMap->Lock, &OldIrql);
+ KeAcquireGuardedMutex(&ObpDeviceMapLock);
/* Make a copy */
DeviceMapInfo->Query.DriveMap = ObSystemDeviceMap->DriveMap;
ObSystemDeviceMap->DriveType,
sizeof(ObSystemDeviceMap->DriveType));
- /* FIXME: Release the DeviceMap Spinlock */
- // KeReleasepinLock(DeviceMap->Lock, OldIrql);
+ KeReleaseGuardedMutex(&ObpDeviceMapLock);
+}
+
+NTSTATUS
+NTAPI
+ObIsDosDeviceLocallyMapped(
+ IN ULONG Index,
+ OUT PUCHAR DosDeviceState)
+{
+ /* check parameters */
+ if (Index < 1 || Index > 26)
+ {
+ /* invalid index */
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ /* acquire lock */
+ KeAcquireGuardedMutex(&ObpDeviceMapLock);
+
+ /* get drive mapping status */
+ *DosDeviceState = (ObSystemDeviceMap->DriveMap & (1 << Index)) != 0;
+
+ /* release lock */
+ KeReleaseGuardedMutex(&ObpDeviceMapLock);
+
+ /* done */
+ return STATUS_SUCCESS;
}
/* EOF */