c++windowsdriverkernel-modent

How retrieve complete filename with NtQueryDirectoryFile in recursive mode?


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);

Thank you.


Solution

  • 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");