[Sfilter]在SfCreate()函数一开始得到文件名的方法(含长短名转换)

转自:http://bbs3.driverdevelop.com/read.php?tid-110833.html

编译环境:ifs2003
目标系统:windowsXP + sp2
基本是按照楚狂人的教程来的,长短名转换确实挺麻烦,已通过测试。
在驱网看了很多好文章,心底有很多谢意,也许这个东西能对别人有用。
FYI:

//get the name with FILE_OBJECT's FileName and RelatedObject fields
void SfGetFileNameFromFileObject(
    IN PSFILTER_DEVICE_EXTENSION devExt,
    IN PFILE_OBJECT FileObject,
    OUT ULONG* FileNameLength,
    OUT PWCHAR buffer
    )
{
    POBJECT_NAME_INFORMATION nameInfo = NULL;
    ULONG returnLength;
    ULONG index;
    NTSTATUS status;
    ULONG i;
    BOOLEAN firstPassed;

    HANDLE hDir = NULL;
    PWCHAR s2li = NULL;
    PWCHAR start;
    PWCHAR wc;
    WCHAR longName[MAXPATHLEN];
    ULONG longNameIndex;
    UNICODE_STRING usDirName;
    OBJECT_ATTRIBUTES objectAttributes;
    IO_STATUS_BLOCK statusBlock;
    ULONG dirInfoLength;
    PVOID dirInfo;
    PFILE_BOTH_DIR_INFORMATION  dirEntryInfo; //for winXP;
    PWCHAR wci;
    PWCHAR wcj;
    ULONG j;
    BOOLEAN differ;
    HANDLE hEvent;

    //1) add the drive letter which I get it in SfFsControlMountVolume()
    buffer[0] = devExt->DriveLetter;
    buffer[1] = L':';
    index = 2;

    returnLength = 0;
    if(FileObject->RelatedFileObject != NULL)
    {
        nameInfo = ExAllocatePoolWithTag(
            PagedPool,
            sizeof(OBJECT_NAME_INFORMATION) + MAXPATHLEN * sizeof(WCHAR),
            CJTAG);
   
        status = ObQueryNameString(
            FileObject->RelatedFileObject,
            nameInfo,
            sizeof(OBJECT_NAME_INFORMATION) + MAXPATHLEN * sizeof(WCHAR),
            &returnLength);

        if(!NT_SUCCESS(status))
        {
            ExFreePool(nameInfo);
            return;
        }

        //2)add the directory's path if the file is queried by relative
        //the path gotten with ObQueryNameString is like:
        //"\Device\HarddiskVolume1\WINDOWS"
        KdPrint(("_CJDN: %wZ\n", nameInfo->Name));
        firstPassed = FALSE;
        for(i=1; i<nameInfo->Name.Length; i++)
        {
            if(nameInfo->Name.Buffer == L'\\')
            {
                if(firstPassed)
                    break;
                else
                    firstPassed = TRUE;
            }
        }
        RtlCopyMemory(buffer + index,
                    nameInfo->Name.Buffer + i,
                    nameInfo->Name.Length - i * sizeof(WCHAR));
        index += nameInfo->Name.Length / sizeof(WCHAR) - i;
    }
   
    if(FileObject->FileName.Length == 0)
    {
        if(nameInfo)
            ExFreePool(nameInfo);
        return;
    }
    RtlCopyMemory(&buffer[index], FileObject->FileName.Buffer, FileObject->FileName.Length);
    index += FileObject->FileName.Length / sizeof(WCHAR);
    buffer[index] = L'\0';

    //substitute short names if exist with their relative long names.
    //buffer now is like L"C:\\PROGRA~1" but the ZwCreateFile() need
    //file name like L"\\Device\\HarddiskVolume1\PROGRA~1".
    RtlCopyMemory(longName, devExt->DeviceName.Buffer, devExt->DeviceName.Length);
    longNameIndex = devExt->DeviceName.Length / sizeof(WCHAR);
    start = buffer + 2;
    while((s2li = wcschr(start, L'~')) != NULL)
    {
        for(wc=s2li; (*wc)!=L'\\'; wc--) //the previous L'\\'
            ;
        RtlCopyMemory(&longName[longNameIndex],
            start,
            (wc + 1 - start) * sizeof(WCHAR));
        longNameIndex += wc + 1 - start;

        for(wc=s2li; (*wc)!=L'\\' && (*wc)!=L'\0'; wc++) //the next L'\\' or end
            ;
        if(*wc == L'\0')
            break;

        longName[longNameIndex] = L'\0';//compose a temporary directory file path

        RtlInitUnicodeString(&usDirName, longName);
        InitializeObjectAttributes(&objectAttributes,
            &usDirName,
            OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
            NULL,
            NULL);
       
        status = ZwCreateFile(&hDir,
            FILE_READ_DATA | SYNCHRONIZE,
            &objectAttributes,
            &statusBlock,
            NULL,
            FILE_ATTRIBUTE_NORMAL,
            FILE_SHARE_READ,
            FILE_OPEN,
            FILE_SYNCHRONOUS_IO_NONALERT,
            NULL,
            0);

        if(!NT_SUCCESS(status))
        {
            if(nameInfo)
                ExFreePool(nameInfo);
            KdPrint(("_cj ZwCreateFile() @ SfGetFileNameFromFileObject() failed, status: 0x%x\n", status));
            return;
        }
        dirInfoLength = 4048;//one page size
        dirInfo = ExAllocatePoolWithTag(NonPagedPool, dirInfoLength, CJTAG);
        ZwCreateEvent(&hEvent, GENERIC_ALL, NULL, NotificationEvent, FALSE);
        status = ZwQueryDirectoryFile(hDir,
            hEvent,
            NULL,
            NULL,
            &statusBlock,
            dirInfo,
            dirInfoLength,
            FileBothDirectoryInformation,
            FALSE,
            NULL,
            TRUE);

        if(STATUS_PENDING == status)
        {
            ZwWaitForSingleObject(hEvent, TRUE, NULL);
        }
        else if(!NT_SUCCESS(status))
        {
            ExFreePool(dirInfo);
            ZwClose(hDir);
            if(nameInfo)
                ExFreePool(nameInfo);
            KdPrint(("_CJ ZwWaitForSingleObject() @ SfGetFileNameFromFileObject() failed, status: 0x%x\n", status));

            return;
        }

        dirEntryInfo = (PFILE_BOTH_DIR_INFORMATION)dirInfo;
        while(1)//compare the directory's entries one by one to find the one I want
        {
            //judge whether this entry is which I need.
            //start --- wc is like: L"PROGRA~1\\", while start is L'P', and wc is L'\\'
            if(dirEntryInfo->ShortNameLength / 2 == (wc - start -1))
            {
                differ = FALSE;
                wci = start + 1;
                wcj = dirEntryInfo->ShortName;
                for(; wci < wc; wci++, wcj++)
                {
                    if(*wci != *wcj)
                    {
                        differ = TRUE;
                        break;
                    }
                }

                if(differ == FALSE) //no difference found, so I get the appropriate one
                {
                    for(j=0; j<dirEntryInfo->FileNameLength/2; j++)
                    {
                        longName[longNameIndex] = dirEntryInfo->FileName[j];
                        longNameIndex++;
                    }

                    break;// break while(1)
                }
            }

            if(dirEntryInfo->NextEntryOffset == 0)
            {//can't find one, so this is a long name, such as "abc~def.txt"
                for(wci = start; wci < wc; wci++)
                {
                    longName[longNameIndex] = *wci;
                    longNameIndex++;
                }
                break;
            }
            else
                dirEntryInfo = (PFILE_BOTH_DIR_INFORMATION)((char*)dirEntryInfo + dirEntryInfo->NextEntryOffset);
        }

        ExFreePool(dirInfo);
        ZwClose(hDir);

        start = wc;
    }

    //the remainder doesn't have L'~', so I just make a copy.
    RtlCopyMemory(&longName[longNameIndex],
        start,
        (buffer + index - start) * sizeof(WCHAR));
    longNameIndex += buffer + index - start;


    //finally, I copy the result to my output buffer
    RtlCopyMemory(buffer + 2,
        longName + devExt->DeviceName.Length / sizeof(WCHAR),
        longNameIndex * sizeof(WCHAR) - devExt->DeviceName.Length);
    *FileNameLength = 2 * sizeof(WCHAR) + (longNameIndex * sizeof(WCHAR) - devExt->DeviceName.Length);

    if(nameInfo)
        ExFreePool(nameInfo);
}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值