打开和关闭文件
下面的函数用于打开一个文件。
函数原型:
NTSTATUS ZwCreateFile(
_Out_ PHANDLE FileHandle,
_In_ ACCESS_MASK DesiredAccess,
_In_ POBJECT_ATTRIBUTES ObjectAttributes,
_Out_ PIO_STATUS_BLOCK IoStatusBlock,
_In_opt_ PLARGE_INTEGER AllocationSize,
_In_ ULONG FileAttributes,
_In_ ULONG ShareAccess,
_In_ ULONG CreateDisposition,
_In_ ULONG CreateOptions,
_In_opt_ PVOID EaBuffer,
_In_ ULONG EaLength
);
参数说明:
FileHandle:一个句柄的指针。如果这个函数成功调用,那么打开的文件句柄就返回在这个地址内。
DisiredAddress: 申请的权限,如果打开写文件内容,请使用
FILE_WITE_DATA;如果需要读写文件内容,请使用
FILE_READ_DATA;如果血药删除文件或者把文件改名,使用
DELETE;若要设置文件属性,请使用
FILE_WRITE_ATTRIBUTES。反之,读写文件属性则使用
FILE_READ_ATTRIBUTES。这些条件可用 | (位或) 来组合。有两个宏分别组合了常用的读写权限,分别为
GENERIC_READ 和
GENERIC_WRITE。还有一个宏代表全部权限,是
GENERIC_ALL,此外想同步地打开文件,加上
SYNCHRONZINE。
ObjectAttribute: 对象描述。
IoStatusBlock:也是一个结构体,这个机构体在内核开发中经常使用,用于表示一个操作的结果。具体结构如下:
typedef struct _IO_STATUS_BLOCK {
union {
NTSTATUS Status;
PVOID Pointer;
};
ULONG_PTR Information;
} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
一般地,返回结果在
status中,成则为
STATUS_SUCCESS,相反,则为一个错误代码。错误信息代码 如下:
FILE_CREATED: 文件 被成功的新建
FILE_OPENED: 文件被打开了
FILE_OVERWRITTEN : 文件被覆盖了
FILE_SUPERESEDED : 文件被替代
FILE_EXISTS: 文件已经存在。
FILE_DOES_NOT_EXIST : 文件打开失败。
ZwCreateFile的参数:
AllocationSize。这个参数用的
很少,我们通常都设置为
NULL。
FileAttributes: 控制新建的文件的属性。通常,我们设置为:
FILE_ATTRIBUTE_NORMAL。
ShareAccess : 这是在本代码打开 这个文件的时候,允许别的代码同时打开这个文件所持有的权限。可以设置的标志位有:
FILE_SHARE_READ、
FILE_SHARE_WRITE、
FILE_SHARE_DELETE。当然也可以用 按位 或 组合。
下面接着说
ZwCreateFile的参数:
CreateDisposition。该参数说明了文件打开的目的。可以设置为下面的值(不能组合):
FILE_CREATE: 新建文件。若文件已经存在,则这个请求失败。
FILE_OPEN : 打开文件。若文件不存在,则请求失败
FILE_OPEN_IF : 打开或者新建。若文件存在,则打卡,若不存在,则失败
FILE_OVERWRITE: 覆盖。若文件存在,则打开并覆盖文件内容,相反,则请求失败.
FILE_OVERWRITE_IF : 新建或覆盖。若打开的文件已经存在则打开它,并覆盖其内容,相反,则简单地生成新文件。
ZwCreateFile的最后一个参数是:
CreateOptions 。可以设置为:
FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT。这样设置,文件此时同步打开,而且打开的是文件(不是文件目录。创建目录用
FILE_DIRECTORY_FILE)。同步打开文件的意义是:以后每次操作文件的时候,比如写文件,调用函数ZwCreateFile 在ZwCreateFile函数返回的时候,文件写操作已经得到完成,而不会有返回STATUS_PENDING(未决)的情况。
要同步打开,
DesiredAccess
必须包含
SYNCHRONIZE
。
下面备注下 下面的情况:
若不想通过缓冲操作文件,希望每次读/写文件都是直接往磁盘上操作的,在填写参数
CreateOptions 时,应带有 标记
FILE_NO_INTERMEDIATE_BUFFERING。注意,带上了这个标记,每次操作文件读/写必须以磁盘扇区大小对齐(常见的是512字节),否则,将返回出错。
下面的这个示例来自 <天书夜读-从汇编到Windows内核编程>,关于文件的打开与关闭。
//---要返回的文件句柄
HANDLE file_handle = NULL;
//--返回值
NTSTATUS status;
//--初始化含有文件路径的 OBJECT_ATTRIBUTES
OBJECT_ATTRIBUTES object_attributes;
UNICODE_STRING ufile_name = RTL_CONST_STRING(l"\\?\\D:test.dat");
InitializeObjectAttributes(
&object_attributes,
&ufile_name,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
NULL,
NULL);
//--- OPEN_IF 的方式打开
status = ZwCreateFile(
&file_handle,
GENERIC_READ | GENERIC_WRITE,
&object_attributes,
&io_status,
NULL,
FILE_ATTRIBUTES_NORMAL,
FILE_SHARE_READ,
FILE_OPEN_IF,
FILE_NON_DIRECTORY_FILE | FILE_RANDON_ACCESS | FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0);
上面的写法:\\?\\Dtest.dat 。说明下。这里并不是简单的写成:D\\test.dat。因为,ZwCreateFile使用的是对象路径,”D:“是一个符号连接对象,符号链接对象一般都在“\\??\\” 路径下。
文件句柄的关闭很简单,调用ZwClose 即可。内核句柄的关闭不需要和打开在同一进程中。比如:
ZwClose(file_handle);
续.....~~~~~~~~~~~~~~~~~~~~~~~~~~~~~