在网上搜索此类问题,搜索到有用的内容相当少,可能是因为比较少人发表这种文章,也不排除比较少人使用内核模式的办法。今晚通过在网上看到的一点资料,结合自己近期研究的课题,使用NtQueryInformationFile实现了根据文件的Handle获取文件路径,程序在VC2008下调试通过,源代码如下:
虽然没有使用编写驱动程序,但使用的API跟内核模式的一样的,使用ntdll.dll里的API。类型定义全部从DDK 2003 SP1中摘出来的。
对于NtQueryInformationFile获取到的文件路径,是不带盘符的,如“\test\Debug\test.txt”。还有一个内核API可以根据文件的Handle获取文件路径,就是NtQueryObject,使用它获取的路径是MS-DOS设备路径,如“\Device\HarddiskVolume3\test\Debug\test.txt”。
#include "stdafx.h"
#include <windows.h>
#include <tchar.h>
typedef long NTSTATUS;
#define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0)
// Define the base asynchronous I/O argument types
typedef struct _IO_STATUS_BLOCK
{
union
{
NTSTATUS Status;
PVOID Pointer;
};
ULONG_PTR Information;
} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
typedef enum _FILE_INFORMATION_CLASS
{
// end_wdm
FileDirectoryInformation = 1,
FileFullDirectoryInformation, // 2
FileBothDirectoryInformation, // 3
FileBasicInformation, // 4 wdm
FileStandardInformation, // 5 wdm
FileInternalInformation, // 6
FileEaInformation, // 7
FileAccessInformation, // 8
FileNameInformation, // 9
FileRenameInformation, // 10
FileLinkInformation, // 11
FileNamesInformation, // 12
FileDispositionInformation, // 13
FilePositionInformation, // 14 wdm
FileFullEaInformation, // 15
FileModeInformation, // 16
FileAlignmentInformation, // 17
FileAllInformation, // 18
FileAllocationInformation, // 19
FileEndOfFileInformation, // 20 wdm
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
FileMaximumInformation
// begin_wdm
} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
typedef struct _UNICODE_STRING
{
USHORT Length;
USHORT MaximumLength;
#ifdef MIDL_PASS
[size_is(MaximumLength / 2), length_is((Length) / 2) ] USHORT * Buffer;
#else // MIDL_PASS
PWSTR Buffer;
#endif // MIDL_PASS
} UNICODE_STRING, *PUNICODE_STRING;
typedef struct _OBJECT_NAME_INFORMATION
{
UNICODE_STRING Name;
} OBJECT_NAME_INFORMATION, *POBJECT_NAME_INFORMATION;
typedef NTSTATUS (NTAPI *NTQUERYINFORMATIONFILE)(
IN HANDLE FileHandle,
OUT PIO_STATUS_BLOCK IoStatusBlock,
OUT PVOID FileInformation,
IN DWORD Length,
IN FILE_INFORMATION_CLASS FileInformationClass
);
NTQUERYINFORMATIONFILE NtQueryInformationFile = NULL;
void _tmain(int argc, _TCHAR* argv[])
{
_tsetlocale(0, _T("chs"));
NTSTATUS status = -1;
HMODULE hNtdll = NULL;
HANDLE hFile = INVALID_HANDLE_VALUE;
IO_STATUS_BLOCK IoStatus = {0};
POBJECT_NAME_INFORMATION pfni = NULL;
size_t allocSize = 0;
hNtdll = LoadLibrary(_T("ntdll.dll"));
NtQueryInformationFile = (NTQUERYINFORMATIONFILE)GetProcAddress(hNtdll, "NtQueryInformationFile");
hFile = CreateFile(_T("E:\\test\\Debug\\test.txt"), GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL);
if (hFile != INVALID_HANDLE_VALUE)
{
allocSize = sizeof(OBJECT_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR);
pfni = (POBJECT_NAME_INFORMATION)malloc(allocSize);
if (pfni != NULL)
{
RtlZeroMemory(pfni, allocSize);
status = NtQueryInformationFile(hFile, &IoStatus, pfni, allocSize, FileNameInformation);
if (NT_SUCCESS(status))
wprintf(L"文件名: %s\n", pfni->Name.Buffer);
free(pfni);
}
CloseHandle(hFile);
}
FreeLibrary(hNtdll);
}
#include <windows.h>
#include <tchar.h>
typedef long NTSTATUS;
#define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0)
// Define the base asynchronous I/O argument types
typedef struct _IO_STATUS_BLOCK
{
union
{
NTSTATUS Status;
PVOID Pointer;
};
ULONG_PTR Information;
} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
typedef enum _FILE_INFORMATION_CLASS
{
// end_wdm
FileDirectoryInformation = 1,
FileFullDirectoryInformation, // 2
FileBothDirectoryInformation, // 3
FileBasicInformation, // 4 wdm
FileStandardInformation, // 5 wdm
FileInternalInformation, // 6
FileEaInformation, // 7
FileAccessInformation, // 8
FileNameInformation, // 9
FileRenameInformation, // 10
FileLinkInformation, // 11
FileNamesInformation, // 12
FileDispositionInformation, // 13
FilePositionInformation, // 14 wdm
FileFullEaInformation, // 15
FileModeInformation, // 16
FileAlignmentInformation, // 17
FileAllInformation, // 18
FileAllocationInformation, // 19
FileEndOfFileInformation, // 20 wdm
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
FileMaximumInformation
// begin_wdm
} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
typedef struct _UNICODE_STRING
{
USHORT Length;
USHORT MaximumLength;
#ifdef MIDL_PASS
[size_is(MaximumLength / 2), length_is((Length) / 2) ] USHORT * Buffer;
#else // MIDL_PASS
PWSTR Buffer;
#endif // MIDL_PASS
} UNICODE_STRING, *PUNICODE_STRING;
typedef struct _OBJECT_NAME_INFORMATION
{
UNICODE_STRING Name;
} OBJECT_NAME_INFORMATION, *POBJECT_NAME_INFORMATION;
typedef NTSTATUS (NTAPI *NTQUERYINFORMATIONFILE)(
IN HANDLE FileHandle,
OUT PIO_STATUS_BLOCK IoStatusBlock,
OUT PVOID FileInformation,
IN DWORD Length,
IN FILE_INFORMATION_CLASS FileInformationClass
);
NTQUERYINFORMATIONFILE NtQueryInformationFile = NULL;
void _tmain(int argc, _TCHAR* argv[])
{
_tsetlocale(0, _T("chs"));
NTSTATUS status = -1;
HMODULE hNtdll = NULL;
HANDLE hFile = INVALID_HANDLE_VALUE;
IO_STATUS_BLOCK IoStatus = {0};
POBJECT_NAME_INFORMATION pfni = NULL;
size_t allocSize = 0;
hNtdll = LoadLibrary(_T("ntdll.dll"));
NtQueryInformationFile = (NTQUERYINFORMATIONFILE)GetProcAddress(hNtdll, "NtQueryInformationFile");
hFile = CreateFile(_T("E:\\test\\Debug\\test.txt"), GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL);
if (hFile != INVALID_HANDLE_VALUE)
{
allocSize = sizeof(OBJECT_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR);
pfni = (POBJECT_NAME_INFORMATION)malloc(allocSize);
if (pfni != NULL)
{
RtlZeroMemory(pfni, allocSize);
status = NtQueryInformationFile(hFile, &IoStatus, pfni, allocSize, FileNameInformation);
if (NT_SUCCESS(status))
wprintf(L"文件名: %s\n", pfni->Name.Buffer);
free(pfni);
}
CloseHandle(hFile);
}
FreeLibrary(hNtdll);
}
虽然没有使用编写驱动程序,但使用的API跟内核模式的一样的,使用ntdll.dll里的API。类型定义全部从DDK 2003 SP1中摘出来的。
对于NtQueryInformationFile获取到的文件路径,是不带盘符的,如“\test\Debug\test.txt”。还有一个内核API可以根据文件的Handle获取文件路径,就是NtQueryObject,使用它获取的路径是MS-DOS设备路径,如“\Device\HarddiskVolume3\test\Debug\test.txt”。