如何在递归模式下使用NtQueryDirectoryFile检索完整的文件名? [英] How retrieve complete filename with NtQueryDirectoryFile in recursive mode?

查看:91
本文介绍了如何在递归模式下使用NtQueryDirectoryFile检索完整的文件名?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用代码来递归遍历所有文件和目录.

I'm using this code to go through all files and directories recursively.

现在我想知道如何提取完整的文件名(路径+文件名+扩展名)?以下行(也出现在参考代码上)仅给出文件名+扩展名(不带目录名).

Now i want know how extract complete filename (path + filename + extension)? the following line(also present on reference code) give only filename + exension (without directory name).

DbgPrint("%s%8I64u <%wZ>\n", prefix, DirInfo->EndOfFile.QuadPart, &ObjectName);

谢谢.

推荐答案

如果我们不希望简单地枚举文件夹/文件而是使用全名,则需要编写适当的代码.例如:

if we want not simple enumerate folders/files but with full name, need write appropriate code. for example:

#define ALLOCSIZE PAGE_SIZE

// int nLevel, PSTR prefix for debug only
void ntTraverse(POBJECT_ATTRIBUTES poa, int nLevel, PSTR prefix)
{
    if (IoGetRemainingStackSize() < PAGE_SIZE)
    {
        DbgPrint("no stack!\n");
        return ;
    }

    if (!nLevel)
    {
        DbgPrint("!nLevel\n");
        return ;
    }

    HANDLE hFile;
    NTSTATUS status;
    IO_STATUS_BLOCK iosb;
    UNICODE_STRING ObjectName, *pObjectName = poa->ObjectName;

    DbgPrint("%s[<%wZ>]\n", prefix, pObjectName);

    if (0 <= (status = NtOpenFile(&hFile, FILE_GENERIC_READ, poa, &iosb, FILE_SHARE_VALID_FLAGS, 
        FILE_SYNCHRONOUS_IO_NONALERT|FILE_OPEN_REPARSE_POINT|FILE_OPEN_FOR_BACKUP_INTENT|FILE_DIRECTORY_FILE)))
    {
        if (PVOID buffer = ExAllocatePool(PagedPool, ALLOCSIZE))
        {
            union {
                PVOID pv;
                PBYTE pb;
                PFILE_DIRECTORY_INFORMATION DirInfo;
            };

            while (0 <= (status = NtQueryDirectoryFile(hFile, NULL, NULL, NULL, &iosb, 
                pv = buffer, ALLOCSIZE, FileDirectoryInformation, 0, NULL, FALSE)))
            {

                ULONG NextEntryOffset = 0;

                do 
                {
                    pb += NextEntryOffset;

                    ObjectName.Buffer = DirInfo->FileName;

                    switch (ObjectName.Length = (USHORT)DirInfo->FileNameLength)
                    {
                    case 2*sizeof(WCHAR):
                        if (ObjectName.Buffer[1] != '.') break;
                    case sizeof(WCHAR):
                        if (ObjectName.Buffer[0] == '.') continue;
                    }

                    ObjectName.MaximumLength = ObjectName.Length;

                    USHORT Length = pObjectName->Length;

                    if (0 <= RtlAppendUnicodeToString(pObjectName, L"\\") &&
                        0 <= RtlAppendUnicodeStringToString(pObjectName, &ObjectName))
                    {
                        if (FILE_ATTRIBUTE_DIRECTORY == (DirInfo->FileAttributes & 
                            (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_REPARSE_POINT)))
                        {
                            ntTraverse(poa, nLevel - 1, prefix - 1);
                        }
                        else
                        {
                            DbgPrint("%s%8I64u <%wZ>\n", prefix, DirInfo->EndOfFile.QuadPart, pObjectName);
                        }

                        pObjectName->Length = Length;
                    }

                } while (NextEntryOffset = DirInfo->NextEntryOffset);
            }

            ExFreePool(buffer);

            if (status == STATUS_NO_MORE_FILES)
            {
                status = STATUS_SUCCESS;
            }
        }

        NtClose(hFile);
    }

    if (0 > status)
    {
        DbgPrint("---- %x %wZ\n", status, pObjectName);
    }
}

void ntTraverse(PCWSTR path)
{
    char prefix[MAXUCHAR + 1];
    memset(prefix, '\t', MAXUCHAR);
    prefix[MAXUCHAR] = 0;

    UNICODE_STRING ObjectName = { 0, MAXUSHORT, (PWSTR)ExAllocatePool(PagedPool, MAXUSHORT) };
    if (ObjectName.Buffer)
    {
        if (0 <= RtlAppendUnicodeToString(&ObjectName, path))
        {
            OBJECT_ATTRIBUTES oa = { sizeof(oa), 0, &ObjectName };
            ntTraverse(&oa, MAXUCHAR, prefix + MAXUCHAR);
        }

        ExFreePool(ObjectName.Buffer);
    }
}

    ntTraverse(L"\\??\\c:\\users");
    ntTraverse(L"\\systemroot");

这篇关于如何在递归模式下使用NtQueryDirectoryFile检索完整的文件名?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆