获取和修改文件属性,包括获取文件大小、获取或修改文件指针位置、获取或修改文件名、获取或修改文属性(只读属性、隐藏属性)、获取或修改文件创建、修改日期等。DDK提供了内核函数 ZwSetInformationFile 和 ZwQueryInformationFile 函数来进行获取和修改文件属性。
NTSTATUS ZwSetInformationFile(
IN HANDLE FileHandle,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN PVOID FileInformation,
IN ULONG Length,
IN FILE_INFORMATION_CLASS FileInformationClass
);
// FileHandle: 文件句柄
// IoStatusBlock:返回设置的状态
// FileInformation:依据 FileInformation 不同而不同。作为输入信息、
// Length:FileInformation 数据的长度
// FileInformationClass:描述修改属性的类型
NTSTATUS ZwQueryInformationFile(
IN HANDLE FileHandle,
OUT PIO_STATUS_BLOCK IoStatusBlock,
OUT PVOID FileInformation,
IN ULONG Length,
IN FILE_INFORMATION_CLASS FileInformationClass
);
// FileHandle: 文件句柄
// IoStatusBlock:返回设置的状态
// FileInformation:依据 FileInformation 不同而不同。作为输入信息、
// Length:FileInformation 数据的长度
// FileInformationClass:描述修改属性的类型
这两个函数的参数基本相同。其中 FileInformationClass执行修改或者查询的类别。
(1). 当 FileInformationClass 是 FileStandardInformation 时,输入和输出的数据是 FILE_STANDARD_INFORMATION 结构体,描述文件的基本信息。
typedef struct _FILE_STANDARD_INFORMATION {
LARGE_INTEGER AllocationSize; // 为文件分配的大小(注:这个不是文件大小,而是可能所需要的大小)
LARGE_INTEGER EndOfFile; // 距离文件结束还有多少个字节
ULONG NumberOfLinks; // 有多少个链接文件
BOOLEAN DeletePending; // 是否准备删除
BOOLEAN Directory; // 是否为目录
} FILE_STANDARD_INFORMATION, *PFILE_STANDARD_INFORMATION;
(2). 当 FileInformationClass 是 FileBasicInformation 时,输入和输出的数据是 FILE_BASIC_INFORMATION 结构体,描述文件的基本信息。
typedef struct _FILE_BASIC_INFORMATION {
LARGE_INTEGER CreationTime; // 文件创建时间
LARGE_INTEGER LastAccessTime; // 最后访问时间
LARGE_INTEGER LastWriteTime; // 最后写时间
LARGE_INTEGER ChangeTime; // 修改修改时间
ULONG FileAttributes; // 文件属性
} FILE_BASIC_INFORMATION, *PFILE_BASIC_INFORMATION;
其中,时间参数是从一个LARGE_INTEGER的整数,该证书代表从1901年经过多少个10ns(纳秒)。
FileAttributes 描述文件属性。
FILE_ATTRIBUTE_NORMAL 描述一般文件。
FILE_ATTRIBUTE_DIRECTORY 描述是目录。
FILE_ATTRIBUTE_READONLY 描述该文件为只读。
FILE_ATTRIBUTE_HIDDEN 代表隐含文件。
FILE_ATTRIBUTE_SYSTEM 代表系统文件。
(3). 当 FileInformationClass 是 FileNameInformation时,输入和输出的数据是 FILE_NAME_INFORMATION 结构体,描述文件名信息。
typedef struct _FILE_NAME_INFORMATION {
ULONG FileNameLength; // 文件名长度
WCHAR FileName[1]; // 文件名
} FILE_NAME_INFORMATION, *PFILE_NAME_INFORMATION;
注意: 这里指定文件名的字符串是宽字符集字符串。
(4). 当 FileInformationClass 是 FilePositionInformation 时, 输入和输出的数据是 FILE_POSITION_INFORMATION 结构体,描述文件名信息。
typedef struct _FILE_POSITION_INFORMATION {
LARGE_INTEGER CurrentByteOffset; // 代表当前文件指针位置
} FILE_POSITION_INFORMATION, *PFILE_POSITION_INFORMATION;
下面的代码演示了如何使用ZwQueryInformationFile函数查询、修改文件属性。
OBJECT_ATTRIBUTES objectAttri;
IO_STATUS_BLOCK iostatus;
HANDLE hfile;
UNICODE_STRING logFileUnicodeStr;
// 初始化 UNICODE_STRING 字符串
RtlInitUnicodeString(&logFileUnicodeStr, L"\\?\\C:\\1.LOG");
// 或者写成 “\\Device\\hARDDISKvOLUME\\1.LOG”
// 初始化 objectAttri
InitializeObjectAttributes(&objectAttri,
&logFileUnicodeStr,
OBJ_CASE_INSENSITIVE,
NULL,
NULL
);
// 创建文件
NTSTATUS ntStatus = ZwCreateFile(&hfile,
GENERIC_READ,
&objectAttri,
&iostatus,
NULL,
FILE_ATTRIBUTE_NORMAL,
0,
FILE_OPEN, // 打开文件,如果不存在则返回错误
FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0
);
if (NT_SUCCESS(ntStatus))
{
KdPrint(("Open file successuflly. \n"));
}
FILE_STANDARD_INFORMATION fsi;
ntStatus = ZwQueryInformationFile(hfile,
&iostatus,
&fsi,
sizeof(FILE_STANDARD_INFORMATION),
FileStandardInformation
);
if (NT_SUCCESS(ntStatus))
{
KdPrint(("file length: %u\n", fsi.EndOfFile.QuadPart));
}
// 修改当前文件指针
FILE_POSITION_INFORMATION fpi;
fpi.CurrentByteOffset.QuadPart = 100i64;
ntStatus = ZwSetInformationFile(hfile,
&iostatus,
&fpi,
sizeof(FILE_POSITION_INFORMATION),
FilePositionInformation
);
if (NT_SUCCESS(ntStatus))
{
KdPrint(("update the file pointer successfully. \n"));
}
// 关闭文件句柄
ZwClose(hfile);