aboutsummaryrefslogblamecommitdiffstatshomepage
path: root/src/nt_path_converter/nt2dos.c
blob: d1bdb3de55c5eddc1cd6327a01ae44ed16a35bbf (plain) (tree)
1
2
3
4
5




                                                                    













                                                           
 

                                              
 
                                                                         
 

                                             
 
                                                                               
 

                                   
 



















                                                                         


















                                           



                            







                                       



                                                                
 






                                                          
 





                                                   

                                                                         










                                                                    
 


                                   


                                                                                                      
 








                                                                               

                                                                                   















                                                           
/*
 * 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;
}