You can use ZwQueryDirectoryFile with FileObjectIdInformation
, FileIdBothDirectoryInformation
, FileIdFullDirectoryInformation
to query for object ID information for the files in a directory. In the case you have to open only the directory having the file and not the file itself. It can be useful for example if the file is opened for exclusive access or of cause if you has no permission to open a file and not have or want not use backup privilege.
UPDATED: The following test example
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
typedef LONG NTSTATUS;
#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
#define NT_STATUS(x)((NTSTATUS) { x })
#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
#define STATUS_NO_MORE_FILES ((NTSTATUS)0x80000006L)
#define STATUS_INVALID_INFO_CLASS ((NTSTATUS)0xC0000003L)
typedef struct _UNICODE_STRING
{
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING, *PUNICODE_STRING;
typedef struct _IO_STATUS_BLOCK {
union {
NTSTATUS Status;
PVOID Pointer;
} DUMMYUNIONNAME;
ULONG_PTR Information;
} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
typedef VOID (NTAPI *PIO_APC_ROUTINE) (PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock, ULONG Reserved);
typedef enum _FILE_INFORMATION_CLASS {
FileDirectoryInformation = 1,
FileFullDirectoryInformation, // 2
FileBothDirectoryInformation, // 3
FileBasicInformation, // 4
FileStandardInformation, // 5
FileInternalInformation, // 6
FileEaInformation, // 7
FileAccessInformation, // 8
FileNameInformation, // 9
FileRenameInformation, // 10
FileLinkInformation, // 11
FileNamesInformation, // 12
FileDispositionInformation, // 13
FilePositionInformation, // 14
FileFullEaInformation, // 15
FileModeInformation, // 16
FileAlignmentInformation, // 17
FileAllInformation, // 18
FileAllocationInformation, // 19
FileEndOfFileInformation, // 20
FileAlternateNameInformation, // 21
FileStreamInformation, // 22
FilePipeInformation, // 23
FilePipeLocalInformation, // 24
FilePipeRemoteInformation, // 25
FileMailslotQueryInformation, // 26
FileMailslotSetInformation, // 27
FileCompressionInformation, // 28
FileObjectIdInformation, // 29
FileCompletionInformation, // 30
FileMoveClusterInformation, // 31
FileQuotaInformation, // 32
FileReparsePointInformation, // 33
FileNetworkOpenInformation, // 34
FileAttributeTagInformation, // 35
FileTrackingInformation, // 36
FileIdBothDirectoryInformation, // 37
FileIdFullDirectoryInformation, // 38
FileValidDataLengthInformation, // 39
FileShortNameInformation, // 40
FileIoCompletionNotificationInformation, // 41
FileIoStatusBlockRangeInformation, // 42
FileIoPriorityHintInformation, // 43
FileSfioReserveInformation, // 44
FileSfioVolumeInformation, // 45
FileHardLinkInformation, // 46
FileProcessIdsUsingFileInformation, // 47
FileNormalizedNameInformation, // 48
FileNetworkPhysicalNameInformation, // 49
FileIdGlobalTxDirectoryInformation, // 50
FileIsRemoteDeviceInformation, // 51
FileAttributeCacheInformation, // 52
FileNumaNodeInformation, // 53
FileStandardLinkInformation, // 54
FileRemoteProtocolInformation, // 55
FileMaximumInformation
} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
typedef struct _FILE_ID_FULL_DIR_INFORMATION {
ULONG NextEntryOffset;
ULONG FileIndex;
LARGE_INTEGER CreationTime;
LARGE_INTEGER LastAccessTime;
LARGE_INTEGER LastWriteTime;
LARGE_INTEGER ChangeTime;
LARGE_INTEGER EndOfFile;
LARGE_INTEGER AllocationSize;
ULONG FileAttributes;
ULONG FileNameLength;
ULONG EaSize;
LARGE_INTEGER FileId;
WCHAR FileName[1];
} FILE_ID_FULL_DIR_INFORMATION, *PFILE_ID_FULL_DIR_INFORMATION;
typedef struct _FILE_ID_BOTH_DIR_INFORMATION {
ULONG NextEntryOffset;
ULONG FileIndex;
LARGE_INTEGER CreationTime;
LARGE_INTEGER LastAccessTime;
LARGE_INTEGER LastWriteTime;
LARGE_INTEGER ChangeTime;
LARGE_INTEGER EndOfFile;
LARGE_INTEGER AllocationSize;
ULONG FileAttributes;
ULONG FileNameLength;
ULONG EaSize;
CCHAR ShortNameLength;
WCHAR ShortName[12];
LARGE_INTEGER FileId;
WCHAR FileName[1];
} FILE_ID_BOTH_DIR_INFORMATION, *PFILE_ID_BOTH_DIR_INFORMATION;
typedef struct _FILE_ID_GLOBAL_TX_DIR_INFORMATION {
ULONG NextEntryOffset;
ULONG FileIndex;
LARGE_INTEGER CreationTime;
LARGE_INTEGER LastAccessTime;
LARGE_INTEGER LastWriteTime;
LARGE_INTEGER ChangeTime;
LARGE_INTEGER EndOfFile;
LARGE_INTEGER AllocationSize;
ULONG FileAttributes;
ULONG FileNameLength;
LARGE_INTEGER FileId;
GUID LockingTransactionId;
ULONG TxInfoFlags;
WCHAR FileName[1];
} FILE_ID_GLOBAL_TX_DIR_INFORMATION, *PFILE_ID_GLOBAL_TX_DIR_INFORMATION;
#define FILE_ID_GLOBAL_TX_DIR_INFO_FLAG_WRITELOCKED 0x00000001
#define FILE_ID_GLOBAL_TX_DIR_INFO_FLAG_VISIBLE_TO_TX 0x00000002
#define FILE_ID_GLOBAL_TX_DIR_INFO_FLAG_VISIBLE_OUTSIDE_TX 0x00000004
typedef struct _FILE_OBJECTID_INFORMATION {
LONGLONG FileReference;
UCHAR ObjectId[16];
union {
struct {
UCHAR BirthVolumeId[16];
UCHAR BirthObjectId[16];
UCHAR DomainId[16];
} DUMMYSTRUCTNAME;
UCHAR ExtendedInfo[48];
} DUMMYUNIONNAME;
} FILE_OBJECTID_INFORMATION, *PFILE_OBJECTID_INFORMATION;
typedef NTSTATUS (WINAPI *PZW_QUERY_DIRECTORY_FILE) (HANDLE FileHandle,
HANDLE Event, PIO_APC_ROUTINE ApcRoutine, PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock,
PVOID FileInformation, ULONG Length, FILE_INFORMATION_CLASS FileInformationClass,
BOOLEAN ReturnSingleEntry, PUNICODE_STRING FileName, BOOLEAN RestartScan);
void DumpFileInformation (LPCWSTR pszDirName, LPCWSTR pszFileName)
{
WCHAR szFileName[32767];
UNICODE_STRING fn;
IO_STATUS_BLOCK iosb;
NTSTATUS status;
LONGLONG byBuffer[(32767+sizeof(FILE_ID_FULL_DIR_INFORMATION))/sizeof(LONGLONG)];
PFILE_ID_FULL_DIR_INFORMATION pFullInfo = (PFILE_ID_FULL_DIR_INFORMATION)byBuffer;
//PFILE_ID_GLOBAL_TX_DIR_INFORMATION pGlobalTxDirInfo = (PFILE_ID_GLOBAL_TX_DIR_INFORMATION)byBuffer;
HANDLE hDir = INVALID_HANDLE_VALUE;
PZW_QUERY_DIRECTORY_FILE ZwQueryDirectoryFile = (PZW_QUERY_DIRECTORY_FILE)
GetProcAddress(GetModuleHandle(L"ntdll.dll"),"ZwQueryDirectoryFile");
__try {
hDir = CreateFileW (pszDirName, FILE_LIST_DIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
if (hDir == INVALID_HANDLE_VALUE) {
_tprintf(TEXT("Can't open directory '%ls': Error %d\n"), pszDirName, GetLastError());
__leave;
}
lstrcpyW (szFileName, pszFileName);
fn.Buffer = (LPWSTR) szFileName;
fn.Length = lstrlen(szFileName)*sizeof(WCHAR);
fn.MaximumLength = sizeof(szFileName);
RtlZeroMemory ((PVOID)&iosb, sizeof(iosb));
status = ZwQueryDirectoryFile (hDir, NULL, NULL, NULL, &iosb, byBuffer, sizeof(byBuffer),
FileIdFullDirectoryInformation, TRUE, &fn, FALSE);
if (NT_SUCCESS(status)) {
_tprintf (TEXT("The file '%ls%ls%ls' has FileId: 0x%08X%08X\n"),
pszDirName,
fn.Length>0 && pszDirName[fn.Length/sizeof(WCHAR)-1] == L'\\' ? L"": L"\\",
szFileName,
pFullInfo->FileId.HighPart, pFullInfo->FileId.LowPart);
}
}
__finally {
if (hDir != INVALID_HANDLE_VALUE)
CloseHandle (hDir);
}
}
int _tmain ()
{
DumpFileInformation (L"C:\\", L"System Volume Information");
DumpFileInformation (L"C:\\", L"pagefile.sys");
return 0;
}
produce on my computer as the output:
The file 'C:\\System Volume Information' has FileId: 0x000100000000A2F0
The file 'C:\\pagefile.sys' has FileId: 0x006B00000000A673