您的位置:首页 > 其它

Windows内核函数(2) - 内核模式下的文件操作

2013-11-29 23:34 363 查看
转载自;http://mzf2008.blog.163.com/blog/static/35599786201011124648756/

1. 文件的创建

对文件的创建或者打开都是通过内核函数ZwCreateFile实现的。和Windows API类似,这个内核函数返回一个文件句柄,文件的所有操作都是依靠这个句柄进行操作的。在文件操作完毕后,要关闭这个文件句柄。

NTSTATUS

ZwCreateFile(

OUT PHANDLE
FileHandle,

IN ACCESS_MASK
DesiredAccess,

IN POBJECT_ATTRIBUTES
ObjectAttributes,

OUT PIO_STATUS_BLOCK
IoStatusBlock,

IN PLARGE_INTEGER
AllocationSize OPTIONAL,

IN ULONG
FileAttributes,

IN ULONG
ShareAccess,

IN ULONG
CreateDisposition,

IN ULONG
CreateOptions,

IN PVOID
EaBuffer OPTIONAL,

IN ULONG
EaLength

);

FileHandle:返回打开文件的句柄

DesiredAccess:一般指定为GENERIC_READ 或者 GENERIC_WRITE

ObjectAttributes:是OBJECT_ATTRIBUTES结构的地址,该结构包含要打开的文件名。

IoStatusBlock:指向一个IO_STATUS_BLOCK结构体,该结构接收ZwCreateFile操作的结果状态。

AllocationSize是一个指针,指向一个64位整数,该数指定文件初始分配时的大小、该参数仅关系到创建或重写文件操作。如果忽略它,那么文件长度将从0开始,并随着写入而增长。

FileAttributes指定新创建文件的属性,一般为0或FILE_ATTRIBUTE_NORMAL

ShareAccess:指定文件的共享方式,0或者FILE_SHARE_READ

CreateDisposition:指定当文件存在或不存在时,该如何处理

CreateOptions:FILE_SYNCHRONOUS_IO_NONALERT,指定控制打开操作和句柄使用的附加标志位。

EaBuffer:一个指针,指向可选的扩展属性区

EaLength:扩展属性区的长度

要创建的文件的文件名是通过第三个参数传入的。这个参数是一个OBJECT_ATTRIBUTES得结构。DDK提供了对OBJECT_ATTRIBUTES初始化的宏:

VOID

InitializeObjectAttributes(

OUT POBJECT_ATTRIBUTES
InitializedAttributes,

IN PUNICODE_STRING
ObjectName,//文件名

IN ULONG Attributes,//一般为OBJ_CASE_INSENSITIVE,对大小写敏感

IN HANDLE RootDirectory,//一般为NULL

IN PSECURITY_DESCRIPTOR SecurityDescriptor //一般为NULL

);

示例代码:

VOID TetsCreateFile()

{

UNICODE_STRING string;

RtlInitUnicodeString(&string, L"\\??\\C:\\1.log");

OBJECT_ATTRIBUTES objattr;

InitializeObjectAttributes(&objattr,

&string, OBJ_CASE_INSENSITIVE, NULL, NULL);

HANDLE hFile;

IO_STATUS_BLOCK iostatus;

NTSTATUS status = ZwCreateFile(&hFile,

GENERIC_READ | GENERIC_WRITE, &objattr, &iostatus,

NULL, FILE_ATTRIBUTE_NORMAL, 0,

FILE_OPEN_IF, FILE_SYNCHRONOUS_IO_NONALERT,

NULL, 0);

if (!NT_SUCCESS(status))

{

KdPrint(("文件创建失败!\n"));

}

else

{

KdPrint(("文件创建成功!\n"));

}

//文件操作

//......

//关闭文件句柄

ZwClose(hFile);

}

2. 文件的创建

除了可以用ZwCreateFile函数打开文件,DDK还为我们提供了一个ZwOpenFile函数用来打开文件,以简化文件的打开操作。

NTSTATUS

ZwOpenFile(

OUT PHANDLE
FileHandle,

IN ACCESS_MASK
DesiredAccess, //打开权限,一般为GENERIC_ALL

IN POBJECT_ATTRIBUTES ObjectAttributes,

OUT PIO_STATUS_BLOCK
IoStatusBlock,

IN ULONG
ShareAccess,

IN ULONG
OpenOptions//打开选项,一般为FILE_SYNCHRONOUS_IO_NONALERT

);

3. 获取或修改文件属性

获取和修改文件属性,包括获取文件大小,获取或修改文件指针位置,获取或修改文件名,获取或修改文件属性(只读属性,隐藏属性),获取或修改文件创建,修改日期。

NTSTATUS

ZwSetInformationFile(

IN HANDLE
FileHandle,

OUT PIO_STATUS_BLOCK
IoStatusBlock,

IN PVOID
FileInformation,

IN ULONG
Length,

IN FILE_INFORMATION_CLASS
FileInformationClass

);

NTSTATUS

ZwQueryInformationFile(

IN HANDLE
FileHandle,

OUT PIO_STATUS_BLOCK
IoStatusBlock,

OUT PVOID
FileInformation,

IN ULONG
Length,

IN FILE_INFORMATION_CLASS
FileInformationClass

);

FileInformation:依据FileInformationClass不同而不同。

Length:FileInformation数据的长度

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;

(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;

示例代码:

VOID TetsFile()

{

UNICODE_STRING string;

RtlInitUnicodeString(&string, L"\\??\\C:\\1.log");

OBJECT_ATTRIBUTES objattr;

InitializeObjectAttributes(&objattr,

&string, OBJ_CASE_INSENSITIVE, NULL, NULL);

HANDLE hFile;

IO_STATUS_BLOCK iostatus;

//打开文件

NTSTATUS status = ZwCreateFile(&hFile, GENERIC_READ,

&objattr, &iostatus, NULL, FILE_ATTRIBUTE_NORMAL, 0, F

ILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);

if (!NT_SUCCESS(status))

{

KdPrint(("文件打开失败!\n"));

}

else

{

KdPrint(("文件打开成功!\n"));

FILE_BASIC_INFORMATION fbi;

//查询文件基本信息

status = ZwQueryInformationFile(hFile, &iostatus, &fbi, sizeof(FILE_BASIC_INFORMATION),

FileBasicInformation);

if (NT_SUCCESS(status))

{

KdPrint(("查询文件属性成功!\n"));

}

//设置文件只读属性

fbi.FileAttributes |= FILE_ATTRIBUTE_READONLY;

status = ZwSetInformationFile(hFile, &iostatus, &fbi, sizeof(FILE_BASIC_INFORMATION),

FileBasicInformation);

if (NT_SUCCESS(status))

{

KdPrint(("设置文件只读属性成功!\n"));

}

//关闭文件句柄

ZwClose(hFile);

}

}

4. 文件的写操作

NTSTATUS

ZwWriteFile(

IN HANDLE
FileHandle,

IN HANDLE
Event OPTIONAL, //一般设为NULL

IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, //一般设为NULL

IN PVOID ApcContext OPTIONAL, //一般设为NULL

OUT PIO_STATUS_BLOCK IoStatusBlock, //记录实际写的字节数

IN PVOID Buffer, //从这个缓冲区中开始往文件里写

IN ULONG Length, //准备写多少字节

IN PLARGE_INTEGER ByteOffset OPTIONAL, //从文件的多少偏移开始写

IN PULONG Key OPTIONAL //一般设为NULL

);

IoStatusBlockIoStatusBlock.Information记录实际写了多少字节。

示例代码:

#define BUFFER_SIZE 1024

#pragma INITCODE

VOID TetsFile()

{

UNICODE_STRING string;

RtlInitUnicodeString(&string, L"\\??\\C:\\1.log");

OBJECT_ATTRIBUTES objattr;

InitializeObjectAttributes(&objattr, &string, OBJ_CASE_INSENSITIVE,

NULL, NULL);

HANDLE hFile;

IO_STATUS_BLOCK iostatus;

//打开文件

NTSTATUS status = ZwCreateFile(&hFile, GENERIC_WRITE,

&objattr, &iostatus,

NULL, FILE_ATTRIBUTE_NORMAL,

FILE_SHARE_WRITE,

FILE_OPEN_IF, FILE_SYNCHRONOUS_IO_NONALERT,

NULL, 0);

//分配Buffer空间

PUCHAR pBuffer = (PUCHAR)ExAllocatePool(PagedPool, BUFFER_SIZE);

RtlFillMemory(pBuffer, BUFFER_SIZE, 'A');

//写文件

status = ZwWriteFile(hFile, NULL, NULL, NULL, &iostatus,

pBuffer, BUFFER_SIZE, NULL, NULL);

LARGE_INTEGER ByteOffset;

ByteOffset.QuadPart = 1024i64; //设置文件指针偏移

RtlFillMemory(pBuffer, BUFFER_SIZE, 'B');

status = ZwWriteFile(hFile, NULL, NULL, NULL, &iostatus,

pBuffer, BUFFER_SIZE, &ByteOffset, NULL);

//关闭文件句柄

ZwClose(hFile);

//释放内存

ExFreePool(pBuffer);

}

5. 文件的读操作

NTSTATUS

ZwReadFile(

IN HANDLE
FileHandle,

IN HANDLE
Event OPTIONAL,

IN PIO_APC_ROUTINE
ApcRoutine OPTIONAL,

IN PVOID
ApcContext OPTIONAL,

OUT PIO_STATUS_BLOCK
IoStatusBlock,

OUT PVOID
Buffer,

IN ULONG
Length,

IN PLARGE_INTEGER
ByteOffset OPTIONAL,

IN PULONG
Key OPTIONAL

);


如果需要读取整个文件,那么得知道文件的大小,我们可以用ZwQueryInformationFile来实现。

示例代码:

#pragma INITCODE

VOID TetsFile()

{

UNICODE_STRING string;

RtlInitUnicodeString(&string, L"\\??\\C:\\1.log");

OBJECT_ATTRIBUTES objattr;

InitializeObjectAttributes(&objattr, &string, OBJ_CASE_INSENSITIVE, NULL, NULL);

HANDLE hFile;

IO_STATUS_BLOCK iostatus;

//打开文件

NTSTATUS status = ZwCreateFile(&hFile, GENERIC_READ, &objattr, &iostatus,

NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,

FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);

//获得文件的大小

FILE_STANDARD_INFORMATION fsi;

status = ZwQueryInformationFile(hFile,

&iostatus, &fsi,

sizeof(FILE_STANDARD_INFORMATION),

FileStandardInformation);

//分配Buffer空间

PUCHAR pBuffer = (PUCHAR)ExAllocatePool(PagedPool,

(LONG)fsi.EndOfFile.QuadPart);

//读文件

status = ZwReadFile(hFile, NULL, NULL, NULL,

&iostatus, pBuffer, (LONG)fsi.EndOfFile.QuadPart, NULL, NULL);

KdPrint(("Read %d bytes\n", iostatus.Information));

//关闭文件句柄

ZwClose(hFile);

//释放内存

ExFreePool(pBuffer);

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: