aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/km/src/special/nt_namespace
diff options
context:
space:
mode:
Diffstat (limited to 'km/src/special/nt_namespace')
-rw-r--r--km/src/special/nt_namespace/control_codes.h12
-rw-r--r--km/src/special/nt_namespace/device.c203
-rw-r--r--km/src/special/nt_namespace/device.h13
-rw-r--r--km/src/special/nt_namespace/main.c27
-rw-r--r--km/src/special/nt_namespace/makefile1
-rw-r--r--km/src/special/nt_namespace/nt2dos.c151
-rw-r--r--km/src/special/nt_namespace/nt2dos.h12
-rw-r--r--km/src/special/nt_namespace/sources3
8 files changed, 422 insertions, 0 deletions
diff --git a/km/src/special/nt_namespace/control_codes.h b/km/src/special/nt_namespace/control_codes.h
new file mode 100644
index 0000000..3fb2aff
--- /dev/null
+++ b/km/src/special/nt_namespace/control_codes.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2015 Egor Tensin <Egor.Tensin@gmail.com>
+ * This file is part of the "Windows 7 drivers" project.
+ * For details, see https://github.com/egor-tensin/windows7-drivers.
+ * Distributed under the MIT License.
+ */
+
+#pragma once
+
+#include <ntddk.h>
+
+#define CONVERT_NT_PATH CTL_CODE(0x8000, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)
diff --git a/km/src/special/nt_namespace/device.c b/km/src/special/nt_namespace/device.c
new file mode 100644
index 0000000..6d88dc4
--- /dev/null
+++ b/km/src/special/nt_namespace/device.c
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2015 Egor Tensin <Egor.Tensin@gmail.com>
+ * This file is part of the "Windows 7 drivers" project.
+ * For details, see https://github.com/egor-tensin/windows7-drivers.
+ * Distributed under the MIT License.
+ */
+
+#include "control_codes.h"
+#include "device.h"
+#include "nt2dos.h"
+
+#include <ntddk.h>
+
+static NTSTATUS device_open(DEVICE_OBJECT *device_object, IRP *irp)
+{
+ NTSTATUS status = STATUS_SUCCESS;
+
+ UNREFERENCED_PARAMETER(device_object);
+
+ irp->IoStatus.Status = status;
+ irp->IoStatus.Information = 0;
+ IoCompleteRequest(irp, IO_NO_INCREMENT);
+ return status;
+}
+
+typedef NTSTATUS (*ioctl_handler)(
+ void *, unsigned long,
+ void *, unsigned long,
+ ULONG_PTR *);
+
+static NTSTATUS handle_convert_nt_path(
+ void *in_buf,
+ unsigned long in_buf_size,
+ void *out_buf,
+ unsigned long out_buf_size,
+ ULONG_PTR *nbwritten)
+{
+ UNICODE_STRING uUnresolved, uResolved;
+ NTSTATUS status = STATUS_SUCCESS;
+
+ DbgPrint("nt_namespace: unresolved path: %ws\n", (WCHAR *) in_buf);
+ DbgPrint("nt_namespace: unresolved size: %lu\n", in_buf_size);
+
+ RtlInitUnicodeString(&uUnresolved, (WCHAR *) in_buf);
+ status = nt2dos(&uResolved, &uUnresolved);
+
+ if (!NT_SUCCESS(status))
+ return status;
+
+ *nbwritten = uResolved.Length + sizeof(WCHAR);
+
+ DbgPrint("nt_namespace: resolved path: %wZ\n", &uResolved);
+ DbgPrint("nt_namespace: resolved size: %Iu\n", *nbwritten);
+
+ if (out_buf_size < *nbwritten)
+ {
+ status = STATUS_BUFFER_OVERFLOW;
+ goto free_resolved;
+ }
+
+ RtlFillMemory(out_buf, *nbwritten, L'\0');
+ RtlCopyMemory(out_buf, uResolved.Buffer, uResolved.Length);
+
+free_resolved:
+ ExFreePool(uResolved.Buffer);
+
+ return status;
+}
+
+static NTSTATUS device_ioctl(DEVICE_OBJECT *device_object, IRP *irp)
+{
+ IO_STACK_LOCATION *io_stack_loc;
+ void* in_buf, *out_buf;
+ unsigned long in_buf_size, out_buf_size;
+ ioctl_handler handler;
+ NTSTATUS status = STATUS_UNSUCCESSFUL;
+
+ UNREFERENCED_PARAMETER(device_object);
+
+ irp->IoStatus.Status = status;
+ irp->IoStatus.Information = 0;
+ io_stack_loc = IoGetCurrentIrpStackLocation(irp);
+
+ in_buf = out_buf = irp->AssociatedIrp.SystemBuffer;
+ in_buf_size = io_stack_loc->Parameters.DeviceIoControl.InputBufferLength;
+ out_buf_size = io_stack_loc->Parameters.DeviceIoControl.OutputBufferLength;
+
+ switch (io_stack_loc->Parameters.DeviceIoControl.IoControlCode)
+ {
+ case CONVERT_NT_PATH:
+ handler = handle_convert_nt_path;
+ break;
+
+ default:
+ status = irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
+ goto complete_request;
+ }
+
+ status = irp->IoStatus.Status = handler(
+ in_buf, in_buf_size,
+ out_buf, out_buf_size,
+ &irp->IoStatus.Information);
+
+complete_request:
+ IoCompleteRequest(irp, IO_NO_INCREMENT);
+
+ return status;
+}
+
+typedef struct
+{
+ const wchar_t *path;
+ const wchar_t *symlink;
+}
+DeviceInfo;
+
+typedef struct
+{
+ DEVICE_OBJECT *object;
+ UNICODE_STRING path;
+ UNICODE_STRING symlink;
+}
+Device;
+
+#define NUMOF_DEVICES 1
+
+static DeviceInfo devices_info[NUMOF_DEVICES] =
+{
+ {
+ L"\\Device\\nt_namespace",
+ L"\\DosDevices\\nt_namespace",
+ },
+};
+
+static Device devices[NUMOF_DEVICES];
+
+static void destroy_device(int i)
+{
+ IoDeleteSymbolicLink(&devices[i].symlink);
+ IoDeleteDevice(devices[i].object);
+}
+
+void destroy_devices()
+{
+ int i;
+ for (i = 0; i < NUMOF_DEVICES; ++i)
+ destroy_device(i);
+}
+
+static NTSTATUS set_up_device(DRIVER_OBJECT *driver_object, int i)
+{
+ NTSTATUS status = STATUS_SUCCESS;
+
+ RtlInitUnicodeString(&devices[i].path, devices_info[i].path);
+ RtlInitUnicodeString(&devices[i].symlink, devices_info[i].symlink);
+
+ status = IoCreateDevice(
+ driver_object,
+ 0,
+ &devices[i].path,
+ FILE_DEVICE_UNKNOWN,
+ FILE_DEVICE_SECURE_OPEN,
+ FALSE,
+ &devices[i].object);
+
+ if (!NT_SUCCESS(status))
+ return status;
+
+ devices[i].object->Flags |= DO_BUFFERED_IO;
+ devices[i].object->Flags &= ~DO_DEVICE_INITIALIZING;
+
+ if (!NT_SUCCESS(status = IoCreateSymbolicLink(
+ &devices[i].symlink, &devices[i].path)))
+ goto delete_device;
+
+ return status;
+
+delete_device:
+ IoDeleteDevice(devices[i].object);
+
+ return status;
+}
+
+NTSTATUS set_up_devices(DRIVER_OBJECT *driver_object)
+{
+ int i, j;
+ NTSTATUS status = STATUS_SUCCESS;
+
+ for (i = 0; i < NUMOF_DEVICES; ++i)
+ if (!NT_SUCCESS(status = set_up_device(driver_object, i)))
+ goto destroy_devices;
+
+ driver_object->MajorFunction[IRP_MJ_CREATE] = device_open;
+ driver_object->MajorFunction[IRP_MJ_DEVICE_CONTROL] = device_ioctl;
+
+ return status;
+
+destroy_devices:
+ for (j = 0; j < i; ++j)
+ destroy_device(j);
+
+ return status;
+}
diff --git a/km/src/special/nt_namespace/device.h b/km/src/special/nt_namespace/device.h
new file mode 100644
index 0000000..4f117e9
--- /dev/null
+++ b/km/src/special/nt_namespace/device.h
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2015 Egor Tensin <Egor.Tensin@gmail.com>
+ * This file is part of the "Windows 7 drivers" project.
+ * For details, see https://github.com/egor-tensin/windows7-drivers.
+ * Distributed under the MIT License.
+ */
+
+#pragma once
+
+#include <ntddk.h>
+
+NTSTATUS set_up_devices(DRIVER_OBJECT *);
+void destroy_devices();
diff --git a/km/src/special/nt_namespace/main.c b/km/src/special/nt_namespace/main.c
new file mode 100644
index 0000000..a1c08e8
--- /dev/null
+++ b/km/src/special/nt_namespace/main.c
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2015 Egor Tensin <Egor.Tensin@gmail.com>
+ * This file is part of the "Windows 7 drivers" project.
+ * For details, see https://github.com/egor-tensin/windows7-drivers.
+ * Distributed under the MIT License.
+ */
+
+#include "device.h"
+
+#include <ntddk.h>
+
+static void on_driver_unload(DRIVER_OBJECT *driver_object)
+{
+ UNREFERENCED_PARAMETER(driver_object);
+
+ destroy_devices();
+}
+
+NTSTATUS DriverEntry(
+ DRIVER_OBJECT *driver_object,
+ UNICODE_STRING *registry_path)
+{
+ UNREFERENCED_PARAMETER(registry_path);
+
+ driver_object->DriverUnload = on_driver_unload;
+ return set_up_devices(driver_object);
+}
diff --git a/km/src/special/nt_namespace/makefile b/km/src/special/nt_namespace/makefile
new file mode 100644
index 0000000..5acbbd2
--- /dev/null
+++ b/km/src/special/nt_namespace/makefile
@@ -0,0 +1 @@
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/km/src/special/nt_namespace/nt2dos.c b/km/src/special/nt_namespace/nt2dos.c
new file mode 100644
index 0000000..d1bdb3d
--- /dev/null
+++ b/km/src/special/nt_namespace/nt2dos.c
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2015 Egor Tensin <Egor.Tensin@gmail.com>
+ * This file is part of the "Windows 7 drivers" project.
+ * For details, see https://github.com/egor-tensin/windows7-drivers.
+ * Distributed under the MIT License.
+ */
+
+#include <ntifs.h>
+
+#include "nt2dos.h"
+
+static NTSTATUS get_object_name_info(
+ void *object,
+ OBJECT_NAME_INFORMATION **object_name_info)
+{
+ unsigned long nbneeded;
+ NTSTATUS status = STATUS_SUCCESS;
+
+ status = ObQueryNameString(object, NULL, 0, &nbneeded);
+
+ if (status != STATUS_INFO_LENGTH_MISMATCH)
+ return status;
+
+ *object_name_info = ExAllocatePoolWithTag(PagedPool, nbneeded, '1l');
+
+ if (*object_name_info == NULL)
+ return STATUS_INSUFFICIENT_RESOURCES;
+
+ status = ObQueryNameString(object, *object_name_info, nbneeded, &nbneeded);
+
+ if (!NT_SUCCESS(status))
+ goto free_object_name_info;
+
+ return status;
+
+free_object_name_info:
+ ExFreePool(*object_name_info);
+
+ return status;
+}
+
+NTSTATUS nt2dos(UNICODE_STRING *u_resolved, UNICODE_STRING *u_unresolved)
+{
+ IO_STATUS_BLOCK io_status_block;
+ DEVICE_OBJECT *volume_object;
+ FILE_OBJECT *file_object;
+ HANDLE file;
+ OBJECT_ATTRIBUTES file_attrs;
+ OBJECT_NAME_INFORMATION *file_name_info, *volume_name_info;
+ UNICODE_STRING u_dos_name;
+ USHORT u_resolved_size;
+ NTSTATUS status = STATUS_SUCCESS;
+
+ InitializeObjectAttributes(
+ &file_attrs,
+ u_unresolved,
+ OBJ_CASE_INSENSITIVE | OBJ_OPENIF,
+ NULL,
+ NULL);
+
+ status = ZwCreateFile(
+ &file,
+ FILE_READ_ATTRIBUTES,
+ &file_attrs,
+ &io_status_block,
+ NULL,
+ FILE_ATTRIBUTE_NORMAL,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ FILE_OPEN,
+ FILE_SYNCHRONOUS_IO_NONALERT,
+ NULL,
+ 0);
+
+ if (!NT_SUCCESS(status))
+ return status;
+
+ status = ObReferenceObjectByHandle(
+ file,
+ FILE_READ_ATTRIBUTES,
+ *IoFileObjectType,
+ KernelMode,
+ &file_object,
+ NULL);
+
+ if (!NT_SUCCESS(status))
+ goto close_file;
+
+ status = get_object_name_info(file_object, &file_name_info);
+
+ if (!NT_SUCCESS(status))
+ goto close_file;
+
+ if (file_object->Vpb == NULL)
+ {
+ u_resolved->Buffer = ExAllocatePoolWithTag(
+ PagedPool, file_name_info->Name.Length, '1l');
+
+ if (u_resolved->Buffer == NULL)
+ {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ goto free_file_name_info;
+ }
+
+ RtlInitEmptyUnicodeString(
+ u_resolved, u_resolved->Buffer, file_name_info->Name.Length);
+ RtlCopyUnicodeString(u_resolved, &file_name_info->Name);
+ goto free_file_name_info;
+ }
+
+ volume_object = file_object->Vpb->RealDevice;
+ status = get_object_name_info(volume_object, &volume_name_info);
+
+ if (!NT_SUCCESS(status))
+ goto free_file_name_info;
+
+ status = IoVolumeDeviceToDosName(volume_object, &u_dos_name);
+
+ if (!NT_SUCCESS(status))
+ goto free_volume_name_info;
+
+ u_resolved_size = file_name_info->Name.Length - volume_name_info->Name.Length + u_dos_name.Length;
+
+ u_resolved->Buffer = ExAllocatePoolWithTag(PagedPool, u_resolved_size, '1l');
+
+ if (u_resolved->Buffer == NULL)
+ {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ goto free_dos_name;
+ }
+
+ RtlInitEmptyUnicodeString(u_resolved, u_resolved->Buffer, u_resolved_size);
+
+ RtlCopyUnicodeString(u_resolved, &u_dos_name);
+ file_name_info->Name.Buffer += volume_name_info->Name.Length / sizeof(wchar_t);
+ file_name_info->Name.Length -= volume_name_info->Name.Length;
+ RtlUnicodeStringCat(u_resolved, &file_name_info->Name);
+
+free_dos_name:
+ ExFreePool(u_dos_name.Buffer);
+
+free_volume_name_info:
+ ExFreePool(volume_name_info);
+
+free_file_name_info:
+ ExFreePool(file_name_info);
+
+close_file:
+ ZwClose(file);
+
+ return status;
+}
diff --git a/km/src/special/nt_namespace/nt2dos.h b/km/src/special/nt_namespace/nt2dos.h
new file mode 100644
index 0000000..ce0b690
--- /dev/null
+++ b/km/src/special/nt_namespace/nt2dos.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2015 Egor Tensin <Egor.Tensin@gmail.com>
+ * This file is part of the "Windows 7 drivers" project.
+ * For details, see https://github.com/egor-tensin/windows7-drivers.
+ * Distributed under the MIT License.
+ */
+
+#pragma once
+
+#include <ntstrsafe.h>
+
+NTSTATUS nt2dos(UNICODE_STRING *resolved, UNICODE_STRING *unresolved);
diff --git a/km/src/special/nt_namespace/sources b/km/src/special/nt_namespace/sources
new file mode 100644
index 0000000..7629a23
--- /dev/null
+++ b/km/src/special/nt_namespace/sources
@@ -0,0 +1,3 @@
+TARGETTYPE = DRIVER
+TARGETNAME = nt_namespace
+SOURCES = device.c main.c nt2dos.c