aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/nt_path_converter/nt2dos.c
diff options
context:
space:
mode:
authorEgor Tensin <Egor.Tensin@gmail.com>2015-05-06 22:22:41 +0300
committerEgor Tensin <Egor.Tensin@gmail.com>2015-05-06 22:22:41 +0300
commit116d1ede0cc0d5d57f593264251668531252c74b (patch)
treeab4618829e4ab95e231e059133b8b7d1533ab6c2 /src/nt_path_converter/nt2dos.c
downloadwindows7-drivers-116d1ede0cc0d5d57f593264251668531252c74b.tar.gz
windows7-drivers-116d1ede0cc0d5d57f593264251668531252c74b.zip
initial commit
Diffstat (limited to 'src/nt_path_converter/nt2dos.c')
-rw-r--r--src/nt_path_converter/nt2dos.c142
1 files changed, 142 insertions, 0 deletions
diff --git a/src/nt_path_converter/nt2dos.c b/src/nt_path_converter/nt2dos.c
new file mode 100644
index 0000000..fb0fd80
--- /dev/null
+++ b/src/nt_path_converter/nt2dos.c
@@ -0,0 +1,142 @@
+/**
+ * \file
+ * \author Egor Tensin <Egor.Tensin@gmail.com>
+ * \copyright This file is licensed under the terms of the MIT License.
+ * See LICENSE.txt for details.
+ */
+
+#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;
+}