第六课 读写磁盘文件
相关内核API
ZwCreateFile
是一个打开文件,这个AIP既可以创建一个,也可以打开文件,他具备创建和打开两种功能,共11个参数
NTSTATUS ZwCreateFile(//有11个参数
_Out_ PHANDLE FileHandle,//1.handle类型的指针,提供这个函数的,让这个函数输入一个句柄给我们,这个
句柄就是一个文件句柄,以后
我们对这个文件进行操作全部用过这个FileHandle来进行的.
_In_ ACCESS_MASK DesiredAccess,//2.描述访问的状态,我们以哪种权限访问的,比如我们以只读,可读可写
的,全部权限的形式进行访
问(GENERIC_ALL).
_In_ POBJECT_ATTRIBUTES ObjectAttributes,//3.这是一个对象的属性,他是一个结构,_OBJECT_ATTRIBUTES//
结构在下面
_Out_ PIO_STATUS_BLOCK IoStatusBlock,//4.返回值,代表,比如我们创建一个文件,创建好了,返回之后我们
就可以看这个文件的访问权
限,对这个文件可以创建,或者对这个文件可以打开,或者对这个文件干什么其他的一些东西.
_In_opt_ PLARGE_INTEGER AllocationSize,//5.这个就是分配的大小值,一个指针,该数指定为文件初始分配时
的大小.
_In_ ULONG FileAttributes,//6.文件的一些属性啊,这个文件假如是我们创建的一个文件的话,那我们指定
这些文件的属性,等一会编程
的时候再说.
_In_ ULONG ShareAccess,//7.共享的一些属性,我们创建之后呢,别的程序对这个文件进行访问的话,他是以
哪种权限进行的,共享读,共
享写,或者是共享删除.
_In_ ULONG CreateDisposition,//8.文件附加的一些属性,指定一个文件,如果这个文件不存在,那么取下面
的这个值,(FILE_OPEN_IF)
_In_ ULONG CreateOptions,//9.控制打开操作和句柄标志位
_In_opt_ PVOID EaBuffer,//10.附加的一个扩展描述的区域,
_In_ ULONG EaLength//11.填写0
);
在写代码的时候的参数----以下带&的需要设置变量,其他都是常量值
Status=ZwCreateFile(&hFile,//1.句柄
GENERIC_ALL,//2.访问权限
&FileObjAttr,//3.包含了创建路径和名字
//RtlInitUnicodeString(&usFileName,L"\\??\\c:\\1.txt");-->memset(&FileObjAttr,0,sizeof(OBJECT_ATTRIBUTES))
;//初始化清零
//--->InitializeObjectAttributes(&FileObjAttr,&usFileName,OBJ_CASE_INSENSITIVE,NULL,NULL);
//这个个宏来的,OBJ_CASE_INSENSITIVE(对大小写不敏感)
&IoStatusBlock,//4.这参数不用管,后面也用不到
NULL,//5.创建文件的时候分配的大小,比如分配1m或者1kb大小
FILE_ATTRIBUTE_NORMAL,// 6.
FILE_SHARE_READ,//7.共享读
FILE_OPEN_IF,//8.如果不存在这个文件,我们就创建,如果存在的话我就打开
FILE_NON_DIRECTORY_FILE,//9.这个文件不是一个目录,FILE_DIRECTORY_FILE 这是一个目录
NULL,//10.不用管
0
);
typedef struct _OBJECT_ATTRIBUTES {//共6个参数
ULONG Length;//1.文件的长度
HANDLE RootDirectory;//2.文件的根目录
PUNICODE_STRING ObjectName;//3.文件名字----我们只关心这个,我们创建的名字是什么,这里就要写入名字,这
个是必须写上的
ULONG Attributes;//4.文件属性
PVOID SecurityDescriptor;//5.安全相关的
PVOID SecurityQualityOfService;//6.安全相关的
} OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES;
初始化ObjectAttributes需用用到宏InitializeObjectAttributes--共5个参数
#define InitializeObjectAttributes( p, n, a, r, s ) { \
(p)->Length = sizeof( OBJECT_ATTRIBUTES ); \
(p)->RootDirectory = r; \
(p)->Attributes = a; \
(p)->ObjectName = n; \
(p)->SecurityDescriptor = s; \
(p)->SecurityQualityOfService = NULL; \
}
//参数
P,我们提供的这个结构体
n,初始化的时候指定的名字,ObjectName
a,Attributes 文件的属性
r,根目录
s,文件的一些安全描述之类的
编程目的的不同,我们可以写入很多值,一般情况下,我们写入的值是固定的,只需要写入少数的几个值,这个函数返回
0的话,说明这个函数调用成
功了,如果返回一个非0值的话,就代表一个错误码,你可以去头文件当中看这个创建为什么是错误的,//
ZwOpenFile
这个API只能打开文件,既然已经有ZwCreateFile,为什么还需要一个打开文件呢,为什么微软还提供ZwOpenFile,因为
ZwOpenFile的函数比较简
单一点,ZwCreateFile参数比较麻烦一点.
NTSTATUS ZwOpenFile(//6个参数
_Out_ PHANDLE FileHandle,//1.打开文件的句柄
_In_ ACCESS_MASK DesiredAccess,//2.打开文件的权限,以只读,可读可写的
_In_ POBJECT_ATTRIBUTES ObjectAttributes,//3.这是一个对象的属性,他是一个结构,_OBJECT_ATTRIBUTES
_Out_ PIO_STATUS_BLOCK IoStatusBlock,//4.返回值,代表,比如我们创建一个文件,创建好了,返回之后我们就
可以看这个文件的访问权限,对这个文件可以创建,或者对这个文件可以打开,或者对这个文件干什么其他的一些东西
.
_In_ ULONG ShareAccess,//5.共享的一些属性,我们创建之后呢,别的程序对这个文件进行访问的话,他是以哪
种权限进行的,共享读,共享写,或者是共享删除.
_In_ ULONG OpenOptions//6.打开文件时指定要应用的选项---打开一个标志要参考ZwCreateFile的第9个参数
,FILE_NON_DIRECTORY_FILE,//这个//文件不是一个目录,FILE_DIRECTORY_FILE 这是一个目录
);
Status=ZwOpenFile(
&hsFile,//1.句柄
GENERIC_ALL,//2.访问权限
&FileObjAttr,//3.包含了创建路径和名字
&IoStatusBlock,//4.这参数不用管,后面也用不到
FILE_SHARE_READ,//5.共享读
FILE_NON_DIRECTORY_FILE//6.这个文件不是一个目录,FILE_DIRECTORY_FILE---这是一个目录
);
ZwSetInforMationFile
这是设置文件的一些信息,比如说他的文件名字,他创建的时间,他的大小,等等一些信息,我们都可以用这个函数进行
设置.
如果我们没有先查询(ZwQueryInformationFile)的话,直接就设置(ZwSetInforMationFile)文件信息为我们的属性的
话,会把本来的
属性给淹没掉的,可能会导致错误,也可能会导致修改不了,所以呢,为了安全起见,在设置之前,我们进行查询(ZwQueryInformationFile)
一下
NTSTATUS ZwSetInformationFile(//有5个参数
_In_ HANDLE FileHandle,//文件句柄
_Out_ PIO_STATUS_BLOCK IoStatusBlock,//输出参数
_In_ PVOID FileInformation,//一个结构体的指针,是根据最后一个参数FILE_INFORMATION_CLASS//这个参数
来指定的FileInformation
//到底是什么结构体
_In_ ULONG Length,//---第三个参数FileInformation//这个结构体的大小
_In_ FILE_INFORMATION_CLASS FileInformationClass//有很多种取值,根据不同的取值设定不同的信息,比如
说
//,如果指定为 FileBasicInformation的话,msdn上面共有10种取值.
);
结构体FileBasicInformation
typedef struct _FILE_BASIC_INFORMATION {
LARGE_INTEGER CreationTime;//创建的时间
LARGE_INTEGER LastAccessTime;//上次访问的时间
LARGE_INTEGER LastWriteTime;//最后修改文件的时间
LARGE_INTEGER ChangeTime;//改变的时间
ULONG FileAttributes;//(在msdn上有17个属性值)文件的属性,文件拥有可写属性,可读属性等等,
//这里根据不同的值可以设置一些文件的属性
//这个参数,在我们设置文件的属性之前,文件本来就具备一些属性的,一般具备可读可写的属性,&Fbi,我们要设置的
话,首先要获取
//文件本来是什么属性,然后再进行一些修改,如果直接设置的话,可能会设置失败的,所以呢,如果要设置文件的属性
之前,需要用
//ZwQueryInformationFile//来进行一些查询工作
} FILE_BASIC_INFORMATION, *PFILE_BASIC_INFORMATION;
ZwQueryInformationFile
查询文件的一些信息,比如说时间啊,名字啊之类的.
NTSTATUS ZwQueryInformationFile(//有5个参数跟ZwSetInformationFile的参数差不多
_In_ HANDLE FileHandle,//文件句柄
_Out_ PIO_STATUS_BLOCK IoStatusBlock,//输出参数
_In_ PVOID FileInformation,//一个结构体的指针,是根据最后一个参数FILE_INFORMATION_CLASS//这个参数
来指定的FileInformation
//到底是什么结构体
_In_ ULONG Length,//---第三个参数FileInformation//这个结构体的大小
_In_ FILE_INFORMATION_CLASS FileInformationClass//有很多种取值,根据不同的取值设定不同的信息,比如
说
//,如果指定为 FileBasicInformation的话,msdn上面共有10种取值.
);
ZwReadFile
读取文件
NTSTATUS ZwReadFile(//有9个参数
_In_ HANDLE FileHandle,//1.句柄
_In_opt_ HANDLE Event,//2.事件,读操作是否完成了,如果这个读信号完成了,就会把这个事件置成有信号的,一
般填写NULL
_In_opt_ PIO_APC_ROUTINE ApcRoutine,//3.如果是设备或者是中间层驱动的话,你可以指定这个参数为NULL,
//这个读操作如果完成的话,你给他一个APC历程,APC实际上是一种,和第二个参数事件(Event)差不多功能
_In_opt_ PVOID ApcContext,//4.APC历程的参数,直接写NULL就可以了
_Out_ PIO_STATUS_BLOCK IoStatusBlock,//5.返回读完成的一些状态,你用这个结构去接收一些完成的状态
信息,然后呢
//这个结构下面的参数Information是接收从文件读了多少个字节
_Out_ PVOID Buffer,//6.就是我们提供的一个读的缓冲区,输出的参数
_In_ ULONG Length,//7.我们读取的长度
_In_opt_ PLARGE_INTEGER ByteOffset,//8.读的偏移,从多少个偏移量开始读,意思是从哪个位置开始读.
//记住啊PLARGE_INTEGER//是一个结构赋值的时候需要ReadOffset.QuadPart=0;(表示从第1个开始读)
_In_opt_ PULONG Key//9.设置为NULL.
);
ZwWriteFile
写入一个文件
NTSTATUS ZwWriteFile(//有9个参数
_In_ HANDLE FileHandle,//1.句柄
_In_opt_ HANDLE Event,//2.事件,写入操作是否完成了,如果这个读信号完成了,就会把这个事件置成有信号的
,一般填写NULL
_In_opt_ PIO_APC_ROUTINE ApcRoutine,//3.如果是设备或者是中间层驱动的话,你可以指定这个参数为NULL,
//这个写入操作如果完成的话,你给他一个APC历程,APC实际上是一种,和第二个参数事件(Event)差不多功能
_In_opt_ PVOID ApcContext,//4.APC历程的参数,直接写NULL就可以了
_Out_ PIO_STATUS_BLOCK IoStatusBlock,//5.返回写入完成的一些状态,你用这个结构去接收一些完成的状
态信息,然后呢
//这个结构下面的参数Information是接收从文件读了多少个字节
_Out_ PVOID Buffer,//6.就是我们提供的一个写入的缓冲区,输出的参数
_In_ ULONG Length,//7.我们写入的长度
_In_opt_ PLARGE_INTEGER ByteOffset,//8.写入的偏移,从多少个偏移量开始写入,意思是从哪个位置开始写入
.
//记住啊PLARGE_INTEGER//是一个结构赋值的时候需要ReadOffset.QuadPart=0;(表示从第1个开始读)
_In_opt_ PULONG Key//9.设置为NULL.
);