文件短名转长名

主要实现函数为ZwQueryDirectoryFile,如果要转换一个文件名称为”c:\progam\a~1\b~1\hi~1.txt”的短名,需要先打开”c:\progam”获取其句柄作为函数第一个参数传入,之后将”a~1”作为函数倒数第二个参数传入,从函数第六个参数传入的缓冲区获取长名之后继续获取下一层短名,直至获取完成。

通过cmd命令 dir /x 可查询短名

封装函数如下,ConverShortToLongName为调用入口。

#include <ntifs.h>
#include <ntstrsafe.h>
#include <ntddk.h>
#include <windef.h>

BOOL IsRootDirecotry(WCHAR * wszDir)
{
    SIZE_T length = wcslen(wszDir);

    // c:
    if((length == 2) && (wszDir[1] == L':'))
        return TRUE;
    //\\??\\c:
    if((length == 6) && 
        (_wcsnicmp(wszDir, L"\\??\\", 4) == 0) &&
        (wszDir[5] == L':'))
        return TRUE;
    //\\DosDevices\\c:
    if((length == 14) && 
        (_wcsnicmp(wszDir, L"\\DosDevices\\", 12) == 0) &&
        (wszDir[13] == L':'))
        return TRUE;
    //\\Device\\HarddiskVolume1
    if((length == 23) &&
        (_wcsnicmp(wszDir, L"\\Device\\HarddiskVolume", 22) == 0))
        return TRUE;


    return FALSE;
}


BOOL IsDirectorySep(WCHAR ch) 
{
    return (ch == L'\\' || ch == L'/');
}

//C:\\Program\\123456~1
//wszRootdir为:c:\\Program
//wszShortName为:123456~1

BOOL QueryDirectoryForLongName(
                      WCHAR * wszRootDir, 
                      WCHAR * wszShortName, 
                      WCHAR *wszLongName, 
                      ULONG ulSize)
{
    UNICODE_STRING              ustrRootDir     = {0};
    UNICODE_STRING              ustrShortName   = {0};
    UNICODE_STRING              ustrLongName    = {0};
    OBJECT_ATTRIBUTES           oa              = {0};
    IO_STATUS_BLOCK             Iosb            = {0};
    NTSTATUS                    ntStatus        = 0;
    HANDLE                      hDirHandle      = 0;
    BYTE                        *Buffer         = NULL;
    WCHAR                       *wszRoot        = NULL;
    PFILE_BOTH_DIR_INFORMATION  pInfo           = NULL;

    RtlZeroMemory(&Iosb, sizeof(IO_STATUS_BLOCK));
    Iosb.Status = STATUS_NO_SUCH_FILE;

    wszRoot = ExAllocatePoolWithTag(PagedPool,
                                  MAX_PATH * sizeof(WCHAR),
                                  'L2S');
    if(wszRoot == NULL)
    {
        return FALSE;
    }

    RtlZeroMemory(wszRoot, MAX_PATH * sizeof(WCHAR));

    wcsncpy(wszRoot, wszRootDir, MAX_PATH);

    RtlInitUnicodeString(&ustrRootDir, wszRoot);
    RtlInitUnicodeString(&ustrShortName, wszShortName);

    if(IsRootDirecotry(wszRoot))
        RtlAppendUnicodeToString(&ustrRootDir, L"\\");

    InitializeObjectAttributes(&oa,
                               &ustrRootDir,
                               OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
                               0, 
                               0);  

    ntStatus = ZwCreateFile(&hDirHandle,
                            GENERIC_READ | SYNCHRONIZE,
                            &oa,
                            &Iosb,
                            0, 
                            FILE_ATTRIBUTE_DIRECTORY, 
                            FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 
                            FILE_OPEN, 
                            FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT , 
                            0,
                            0);

    if (!NT_SUCCESS(ntStatus)) 
    { 
        ExFreePool(wszRoot);
        return FALSE;
    }

    ExFreePool(wszRoot);

    Buffer = ExAllocatePoolWithTag(PagedPool,
                          1024,
                          'L2S');
    if(Buffer == NULL)
    {
        ZwClose(hDirHandle);
        return FALSE;
    }

    RtlZeroMemory(Buffer, 1024);

    ntStatus = ZwQueryDirectoryFile(hDirHandle,
                                NULL,
                                0,
                                0,
                                &Iosb,
                                Buffer,
                                1024,
                                FileBothDirectoryInformation,
                                TRUE,
                                &ustrShortName, //传回与 ustrShortName Match的项
                                TRUE);

    if (!NT_SUCCESS(ntStatus)) 
    {
        ExFreePool(Buffer);
        ZwClose(hDirHandle);
        return FALSE;
    }

    ZwClose(hDirHandle);

    pInfo = (PFILE_BOTH_DIR_INFORMATION) Buffer;

    if(pInfo->FileNameLength == 0)
    {
        ExFreePool(Buffer);
        return FALSE;
    }

    ustrShortName.Length  = (USHORT)pInfo->FileNameLength;
    ustrShortName.MaximumLength = (USHORT)pInfo->FileNameLength;
    ustrShortName.Buffer = pInfo->FileName; //长名

    if(ulSize < ustrShortName.Length)
    {   
        ExFreePool(Buffer);
        return FALSE;
    }

    ustrLongName.Length = 0;
    ustrLongName.MaximumLength = (USHORT)ulSize;
    ustrLongName.Buffer = wszLongName;

    RtlCopyUnicodeString(&ustrLongName, &ustrShortName);
    ExFreePool(Buffer);
    return TRUE;
}

BOOL QueryLongName(WCHAR * wszFullPath, WCHAR * wszLongName, ULONG size)
{
    BOOL        rtn             = FALSE;
    WCHAR *     pchStart        = wszFullPath;
    WCHAR *     pchEnd          = NULL;
    WCHAR *     wszShortName    = NULL;

    //c:\\Program\\Files1~1-->获得Files1~1的长名
    while(*pchStart)
    {
        if(IsDirectorySep(*pchStart))
            pchEnd = pchStart;

        pchStart++;
    }
    //wszFullPath=c:\\Program
    //pchEnd = Files~1

    if(pchEnd)
    {
        *pchEnd++ = L'\0';
        //c:\\Program\\Files1~1
        //wszFullPath:c:\\Program
        //pchEnd:Files1~1
        wszShortName = pchEnd;
        rtn = QueryDirectoryForLongName(wszFullPath, wszShortName, wszLongName, size);
        *(--pchEnd) = L'\\';
        //wszFullPath=c:\\Program\\Files1~1
    }
    return rtn;
}

//先把根目录拷贝到目标目录中,剩下的找到下一级目录是否含有~,如果有,则开始转化。
//如:c:\\Progam\\a~1\\b~1\hi~1.txt
//pchStart指向目录中前一个\\,pchEnd扫描并指向目录的下一个\\,其中如果发现了~,则是短名,需要转换。
//传c:\\Program\\a~1-->c:\\Progam\\ax
//传c:\\Program\\ax\\b~1-->c:\\Program\\ax\\by
//传c:\\Program\\ax\by\\hi~1.txt-->c:\\Program\\ax\by\\hiz.txt
BOOL ConverShortToLongName(WCHAR *wszLongName, WCHAR *wszShortName, ULONG size)
{
    WCHAR           *szResult       = NULL;
    WCHAR           *pchResult      = NULL;
    WCHAR           *pchStart       = wszShortName;
    INT             Offset          = 0;

    szResult = ExAllocatePoolWithTag(PagedPool,
                          sizeof(WCHAR) * (MAX_PATH * 2 + 1),
                          'L2S');

    if(szResult == NULL)
    {
        return FALSE;
    }

    RtlZeroMemory(szResult, sizeof(WCHAR) * (MAX_PATH * 2 + 1));
    pchResult = szResult;


    //C:\\x\\-->\\??\\c:
    if (pchStart[0] && pchStart[1] == L':') 
    {
        *pchResult++ = L'\\';
        *pchResult++ = L'?';
        *pchResult++ = L'?';
        *pchResult++ = L'\\';
        *pchResult++ = *pchStart++;
        *pchResult++ = *pchStart++;
        Offset = 4;
    }
    //\\DosDevices\\c:\\xx-->\\??\\c:
    else if (_wcsnicmp(pchStart, L"\\DosDevices\\", 12) == 0)
    {
        RtlStringCbCopyW(pchResult, sizeof(WCHAR) * (MAX_PATH * 2 + 1), L"\\??\\");
        pchResult += 4;
        pchStart += 12;
        while (*pchStart && !IsDirectorySep(*pchStart))
            *pchResult++ = *pchStart++;
        Offset = 4;
    }
    //\\Device\\HarddiskVolume1\\xx-->\\Device\\HarddiskVolume1
    else if (_wcsnicmp(pchStart, L"\\Device\\HardDiskVolume", 22) == 0)
    {
        RtlStringCbCopyW(pchResult, sizeof(WCHAR) * (MAX_PATH * 2 + 1),L"\\Device\\HardDiskVolume");
        pchResult += 22;
        pchStart += 22;
        while (*pchStart && !IsDirectorySep(*pchStart))
            *pchResult++ = *pchStart++;
    }
    //\\??\\c:\\xx-->\\??\\c:
    else if (_wcsnicmp(pchStart, L"\\??\\", 4) == 0)
    {
        RtlStringCbCopyW(pchResult, sizeof(WCHAR) * (MAX_PATH * 2 + 1), L"\\??\\");
        pchResult += 4;
        pchStart += 4;

        while (*pchStart && !IsDirectorySep(*pchStart))
            *pchResult++ = *pchStart++;
    }
    else
    {
        ExFreePool(szResult);
        return FALSE;
    }

    while (IsDirectorySep(*pchStart)) 
    {
        BOOL            bShortName          = FALSE;
        WCHAR           *pchEnd             = NULL;
        WCHAR           *pchReplacePos      = NULL;

        *pchResult++ = *pchStart++;

        pchEnd = pchStart;
        pchReplacePos = pchResult;

        while (*pchEnd && !IsDirectorySep(*pchEnd))
        {
            if(*pchEnd == L'~')
            {
                bShortName = TRUE;
            }

            *pchResult++ = *pchEnd++;
        }

        *pchResult = L'\0';

        if(bShortName)
        {
            WCHAR  * szLong = NULL;

            szLong = ExAllocatePoolWithTag(PagedPool,
                          sizeof(WCHAR) * MAX_PATH,
                          'L2S');
            if(szLong)
            {
                RtlZeroMemory(szLong,  sizeof(WCHAR) * MAX_PATH);

                if(QueryLongName(szResult, szLong, sizeof(WCHAR) * MAX_PATH))
                {
                    RtlStringCbCopyW(pchReplacePos, sizeof(WCHAR) * (MAX_PATH * 2 + 1), szLong);
                    pchResult = pchReplacePos + wcslen(pchReplacePos);
                }

                ExFreePool(szLong);
            }
        }

        pchStart = pchEnd;
    }

    wcsncpy(wszLongName, szResult + Offset, size/sizeof(WCHAR));
    ExFreePool(szResult);
    return TRUE;
}

BOOL IsShortNamePath(WCHAR * wszFileName)
{
    WCHAR *p = wszFileName;

    while(*p != L'\0')
    {
        if(*p == L'~')
        {
            return TRUE;
        }
        p++;
    }

    return FALSE;
}

VOID DriverUnload(PDRIVER_OBJECT pDriverObject)
{
    DbgPrint("Goodbye!\n");
}

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegPath)
{
    //dir /x看短名
    WCHAR   wszShortName[MAX_PATH] =L"\\??\\C:\\PROGRA~1\\COMMON~1\\MICROS~1\\VC\\1.txt";
    WCHAR   wszLongName[MAX_PATH] = {0};

    if(ConverShortToLongName(wszLongName, wszShortName, sizeof(wszLongName)))
    {
        DbgPrint("%ws\n", wszLongName);
    }

    pDriverObject->DriverUnload = DriverUnload;
    return STATUS_SUCCESS;
}

代码源于麦洛克菲

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值