Windows内核编程之:文件操作

一:文件的创建
/*
*********************************************************************** * 函数名称:ZwCreateFile * 功能描述:文件的创建 * 参数列表: FileHandle:返回打开文件的句柄 DesiredAccess:对打开文件操作的描述,读,写或是其他。一般指定为GENERIC_READ 或 GENERIC_WRITE ObjectAttributes:是OBJECT_ATTRIBUTES结构的地址,该结构包含要打开的文件名 IoStatusBlock:指向一个IO_STATUS_BLOCK结构,该结构接收ZwCreateFile操作的结果状态 AllocationSize:是一个指针,指向一个64位整数,该数指定文件初始分配时的大小 该参数仅关系到创建或重写文件操作,如果忽略它,那么文件长度从0开始 病随着写入而增长 FileAttributes:0或FILE_ATTRIBUTE_NORMAL,指定新创建文件的属性 ShareAccess:FILE_SHARE_READ或0,指定文件的共享方式。 如果为写数据而打开文件,可能不希望其他线程访问该文件 CreateDisposition:FILE_OPEN或FILE_OVERWRITE_IF,表明当指定文件存在或不存在时应如何处理 CreateOptions:FILE_SYNCHARONOUS_IO_NONALERT,指定控制打开操作和句柄使用的附加标志位 EaBuffer:一个指针,指向可选的扩展属性区 EaLength:扩展属性区的长度 * 返回 值: NTSTATUS *************************************************************************/ 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); /* *备注: * 1、CreateDisposition参数。 * 如果想打开文件,CreateDisposition参数设置成FILE_OPEN. * 如果想创建文件,CreateDisposition参数设置成FILE_OVERWRITE_IF * 此时,无论文件是否存在,都会创建新文件 * 2、文件名是通过第三个参数ObjectAttributes * 这个参数是一个OBJECT_ATTRIBUTES结构体 * 通过InitializeObjectAttributes初始化 */
/************************************************************************

* 函数名称:InitializeObjectAttributes

* 功能描述:初始化OBJECT_ATTRIBUTES结构体

* 参数列表:

        InitializedAttributes:返回的OBJECT_ATTRIBUTES结构体

        ObjectName:对象名称,用UNICODE_STRING描述,这里设置的是文件名

        Attributes:一般设置为OBJ_CASE_INSENSITIVE,对大小写敏感

        RootDirectory:一般设置为NULL

        SecurityDescriptor:一般设置为NULL

* 返回 值:相等的字节数

        不一致返回零        

*************************************************************************/

VOID InitializeObjectAttributes(

    OUT POBJECT_ATTRIBUTES InitializedAttributes,

    IN PUNICODE_STRING ObjectName,

    IN ULONG Attributes,

    IN HANDLE RootDirectory,

    IN PSECURITY_DESCRIPTOR SecurityDescriptor);



/*

*备注:

* 1、文件名[必须]是符号链接或者是设备名

* 2、例如:盘符 "c:",就是一个符号链接

*        这里应该用 "\??\c:" 代替 

*        "c:\1.log" 要写成 "\??\c:\1.log"

* 3、其中 "\??\c:" 是符号链接,内核会将它转换成设备名 "\Device\HarddiskColume1"

*/

(1)创建文件

OBJECT_ATTRIBUTES objectAttributes;

IO_STATUS_BLOCK iostatus;

HANDLE hfile;

UNICODE_STRING logFileUnicodeString;



//初始化UNICODE_STRING字符串

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

//或者改写成  "\\Device\\HarddiskVolume1\\1.log"



//初始化objectAttributes

InitializeObjectAttributes(&objectAttributes,

    &logFileUnicodeString,

    OBJ_CASE_INSENSITIVE,

    NULL,

    NULL);



//创建文件

NTSTATUS ntStatus = ZwCreateFile(&hfile, //打开文件的句柄

    GENERIC_WRITE, //读,写

    &objectAttributes, //OBJECT_ATTRIBUTES结构的地址 包含文件名

    &iostatus,  //接收ZwCreateFile操作的结果状态

    NULL, //初始分配时的大小

    FILE_ATTRIBUTE_NORMAL, //新创建文件的属性

    FILE_SHARE_READ, //共享方式

    FILE_OPEN_IF, //当指定文件存在或不存在时应如何处理

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

    NULL, //指向可选的扩展属性区

    0); //扩展属性区的长度



if( NT_SUCCESS(ntStatus) )

{

    KdPrint(("Create file successfully!\n"));

}

else

{

    KdPrint(("Create file unsuccessfully!\n"));

}



//文件操作

//......



//关闭文件句柄

ZwClose(hfile);

(2)打开文件

OBJECT_ATTRIBUTES objectAttributes;

IO_STATUS_BLOCK iostatus;

HANDLE hfile;

UNICODE_STRING logFileUnicodeString;



//初始化UNICODE_STRING字符串

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

//或者改写成  "\\Device\\HarddiskVolume1\\1.log"



//初始化objectAttributes

InitializeObjectAttributes(&objectAttributes,

    &logFileUnicodeString,

    OBJ_CASE_INSENSITIVE, //对大小写敏感

    NULL,

    NULL);



//创建文件

NTSTATUS ntStatus = ZwCreateFile(&hfile, //打开文件的句柄

    GENERIC_READ, //

    &objectAttributes, //OBJECT_ATTRIBUTES结构的地址 包含文件名

    &iostatus,  //接收ZwCreateFile操作的结果状态

    NULL, //初始分配时的大小

    FILE_ATTRIBUTE_NORMAL, //新创建文件的属性

    FILE_SHARE_READ, //共享方式

    FILE_OPEN, //打开文件,如果不存在,则返回错误

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

    NULL, //指向可选的扩展属性区

    0); //扩展属性区的长度



if( NT_SUCCESS(ntStatus) )

{

    KdPrint(("Open file successfully!\n"));

}

else

{

    KdPrint(("Open file unsuccessfully!\n"));

}



//文件操作

//......



//关闭文件句柄

ZwClose(hfile);

 

二:文件的打开

/************************************************************************

* 函数名称:ZwOpenFile

* 功能描述:打开文件

* 参数列表:

        FileHandle:返回打开的文件句柄

        DesiredAccess:打开的权限,一般设为GENERIC_ALL

        ObjectAttributes:objectAttributes结构

        IoStatusBlock:指向一个结构体的指针。该结构体指明打开文件的状态

        ShareAccess:共享的权限。可以是FILE_SHARE_READ或者FILE_SHARE_WRITE

        OpenOptions:打开选项,一般设为FILE_SYNCHRONOUS_IO_NONALERT

* 返回 值:指明文件是否被成功打开

*************************************************************************/

NTSTATUS ZwOpenFile(

    OUT PHANDLE FileHandle,

    IN ACCESS_MASK DesiredAccess,

    IN POBJECT_ATTRIBUTES ObjectAttributes,

    OUT PIO_STATUS_BLOCK IoStatusBlock,

    IN ULONG ShareAccess,

    IN ULONG OpenOptions);

如何使用ZwOpenFile打开文件

OBJECT_ATTRIBUTES objectAttributes;

IO_STATUS_BLOCK iostatus;

HANDLE hfile;

UNICODE_STRING logFileUnicodeString;



//初始化UNICODE_STRING字符串

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

//或者写成 \\Device\\HarddiskVolume1\\1.log



//初始化objectAttributes

InitializeObjectAttributes(

    &objectAttributes,

    &logFileUnicodeString,

    OBJ_CASE_INSENSITIVE,

    NULL,

    NULL);



//创建文件

NTSTATUS ntStatus = ZwOpenFile(&hfile,

                               GENERIC_ALL,

                               &objectAttributes,

                               &iostatus,

                               FILE_SHARE_READ || FILE_SHARE_WRITE,

                               FILE_SYNCHRONOUS_IO_NONALERT);

if( NT_SUCCESS(ntStatus) )

{

    KdPrint(("Create FILE successfully!\n"));

}

else

{

    KdPrint(("Create FILE unsuccessfully!\n"));

}



//文件操作

//..........



//关闭文件句柄

ZwClose(hfile);

三:获取或修改文件属性

/************************************************************************

* 函数名称:ZwSetInformationFile

* 功能描述:设置文件属性

* 参数列表:

        FileHandle:文件句柄

        IoStatusBlock:返回设置的状态

        FileInformation:依据FileInformationClass不同而不同。作为输入信息

        Length:FileInformation数据的长度

        FileInformationClass:描述修改属性的类型

* 返回 值:设置属性是否成功

*************************************************************************/

NTSTATUS ZwSetInformationFile(

            IN HANDLE FileHandle,

            OUT PIO_STATUS_BLOCK IoStatusBlock,

            IN PVOID FileInformation,

            IN ULONG Length,

            IN FILE_INFORMATION_CLASS FileInformationClass);
/************************************************************************

* 函数名称:ZwQueryInformationFile

* 功能描述:获取文件属性

* 参数列表:

        FileHandle:文件句柄

        IoStatusBlock:返回设置的状态

        FileInformation:依据FileInformationClass不同而不同。作为输出信息

        Length:FileInformation数据的长度

        FileInformationClass:描述修改属性的类型

* 返回 值:设置属性查询

*************************************************************************/

NTSTATUS ZwQueryInformationFile(

            IN HANDLE FileHandle,

            OUT PIO_STATUS_BLOCK IoStatusBlock,

            OUT PVOID FileInformation,

            IN ULONG Length,

            IN FILE_INFORMATION_CLASS 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的整数,该整数代表从1601年经过多少个100ns(纳秒)

//FileAttributes描述文件属性。

    //FILE_ATTRIBUTE_NORMAL描述一般文件

    //FILE_ATTRIBUTE_DIRECTORY描述是目录

    //FILE_ATTRIBUTE_READONLY描述是只读

    //FILE_ATTRIBUTE_SYSTEM代表系统文件

(3)当FileInformationClass是FileNameInformation时,
输入和输出的数据时FILE_NAME_INFORMATION结构体,描述文件的基本信息

    typedef struct _FILE_NAME_INFORMATION(

            ULONG FileNameLength; //文件名长度

            WCHAR Filename; //文件名

        )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 objectAttributes;

IO_STATUS_BLOCK iostatus;

HANDLE hfile;

UNICODE_STRING logFileUnicodeString;



//初始化UNICODE_STRING字符串

RtlInitUnicodeString(&logFileUnicodeString,

                     L"\\??\\C:\\1.log");

//或者写成 "\\Device\\HarddisVolume1\\1.log"



//初始化objectAttributes

InitializeObjectAttributes(&objectAttributes,

                           &logFileUnicodeString,

                           OBJ_CASE_INSENSITIVE, //对大小写敏感

                           NULL,

                           NULL);



//创建文件

NTSTATUS  ntStatus = ZwCreateFile(&hfile,

                                  GENERIC_READ,

                                  &objectAttributes,

                                  &iostatus,

                                  NULL,

                                  FILE_ATTRIBUTE_NORMAL,

                                  0,

                                  FILE_OPEN, //打开文件,如果不存在则返回错误

                                  FILE_SYNCHRONOUS_IO_NONALERT,

                                  NULL,

                                  0);

if( NT_SUCCESS(ntStatus) )

{

    KdPrint(("Open FILE successFully!\n"));

}

else

{

    KdPrint(("Open FILE unsuccessFully!\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);

 

四:文件的写操作

/************************************************************************

* 函数名称:ZwWriteFile

* 功能描述:文件的写操作

* 参数列表:

        FileHandle:文件打开的句柄

        Event:很少用到,一般设为NULL

        ApcRoutine:很少用到,一般设为NULL

        ApcContext:很少用到,一般设为NULL

        IoStatusBlock:记录些操作的状态。其中,IoStatusBlock.Infomation记录实际写了多少字节

        Buffer:从这个缓冲区开始往文件里写

        Length:准备写多少字节

        Byteoffset:从文件的多少便宜地址开始写

        Key:很少用到,一般设为NULL

* 返回 值:

*************************************************************************/

NTSTATUS ZwWriteFile(

    IN HANDLE FileHandle,

    IN HANDLE Event OPTIONAL,

    IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,

    IN PVOID ApcContext OPTIONAL,

    OUT PIO_STATUS_BLOCK IoStatusBlock,

    IN PVOID Buffer,

    IN ULONG Length,

    IN PLARGE_INTEGER Byteoffset OPTIONAL,

    IN PULONG Key OPTIONAL);

演示如何对文件进行写操作

OBJECT_ATTRIBUTES objectAttributes;

IO_STATUS_BLOCK iostatus;

HANDLE hfile;

UNICODE_STRING logFileUnicodeString;



//初始化UNICODE_STRING字符串

RtlInitUnicodeString(&logFileUnicodeString,

    L"\\??\\C:\\1.log");

//或者写成 "\\Device\\HarddiskVolume1\\1.LOG"



//初始化objectAttributes

InitializeObjectAttributes(&objectAttributes,

    &logFileUnicodeString,

    OBJ_CASE_INSENSITIVE,//对大小写敏感

    NULL,

    NULL);



//创建文件

NTSTATUS ntStatus = ZwCreateFile(&hfile,

    GENERIC_WRITE,

    &objectAttributes,

    &iostatus,

    NULL,

    FILE_ATTRIBUTE_NORMAL,

    FILE_SHARE_WRITE,

    FILE_OPEN_IF, //即使存在该文件, 也创建

    FILE_SYNCHRONOUS_IO_NONALERT,

    NULL,

    0);

if( NT_SUCCESS(ntStatus) )

{

    KdPrint(("Create file successfully!\n"));

}

else

{

    KdPrint(("Create file unsuccessfully!\n"));

}



#define BUFFER_SIZE 1024



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

//构造要填充的数据

RtlFillMemory(pBuffer, BUFFER_SIZE, 0xAA);



KdPrint(("Thr program will write %d bytes\n", BUFFER_SIZE));



//写文件

NTSTATUS ntStatus = ZwWriteFile(hfile,

    NULL,

    NULL,

    NULL,

    &iostatus,

    pBuffer,

    BUFFER_SIZE,

    NULL,

    NULL);



if( NT_SUCCESS(ntStatus) )

{

    KdPrint(("Write file successfully!\n"));

}

else

{

    KdPrint(("Write file unsuccessfully!\n"));

}



//构造要填充的数据

RtlFillMemory(pBuffer, BUFFER_SIZE, 0xBB);

KdPrint(("The program will append %d bytes\n", BUFFER_SIZE));



//追加数据

LARGE_INTEGER number;

number.QuadPart = 1024i64; //设置文件指针

//对文件进行附加写

NTSTATUS ntStatus = ZwWriteFile(hfile,

    NULL,

    NULL,

    NULL,

    &iostatus,

    pBuffer,

    BUFFER_SIZE,

    &number,

    NULL);



if( NT_SUCCESS(ntStatus) )

{

    KdPrint(("Write file successfully!\n"));

}

else

{

    KdPrint(("Write file unsuccessfully!\n"));

}



KdPrint(("The program really appended %d bytes\n", iostatus.Information));



//关闭文件句柄

ZwClose(hfile);



ExFreePool(pBuffer);

五:文件的读操作

/************************************************************************

* 函数名称:ZwReadFile

* 功能描述:文件的读操作

* 参数列表:

        FileHandle:文件打开的句柄

        Event:很少用到,一般设为NULL

        ApcRoutine:很少用到,一般设为NULL

        ApcContext:很少用到,一般设为NULL

        IoStatusBlock:记录些操作的状态。其中,IoStatusBlock.Infomation记录实际写了多少字节

        Buffer:从这个缓冲区开始开始从文件里读

        Length:准备读多少字节

        Byteoffset:从文件的多少偏移地址开始读

        Key:很少用到,一般设为NULL

* 返回 值:

*************************************************************************/

NTSTATUS ZwReadFile(

    IN HANDLE FileHandle,

    IN HANDLE Event OPTIONAL,

    IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,

    IN PVOID ApcContext OPTIONAL,

    OUT PIO_STATUS_BLOCK IoStatusBlock,

    IN PVOID Buffer,

    IN ULONG Length,

    IN PLARGE_INTEGER Byteoffset OPTIONAL,

    IN PULONG Key OPTIONAL);

演示如何对文件进行读操作

OBJECT_ATTRIBUTES objectAttributes;

IO_STATUS_BLOCK iostatus;

HANDLE hfile;

UNICODE_STRING logFileUnicodeString;



//初始化UNICODE_STRING字符串

RtlInitUnicodeString(&logFileUnicodeString,

    L"\\??\\C:\\1.log");

//或者写成 "\\Device\\HarddiskVolume1\\1.LOG"



//初始化objectAttributes

InitializeObjectAttributes(&objectAttributes,

    &logFileUnicodeString,

    OBJ_CASE_INSENSITIVE,//对大小写敏感

    NULL,

    NULL);



//创建文件

NTSTATUS ntStatus = ZwCreateFile(&hfile,

    GENERIC_WRITE,

    &objectAttributes,

    &iostatus,

    NULL,

    FILE_ATTRIBUTE_NORMAL,

    FILE_SHARE_WRITE,

    FILE_OPEN,

    FILE_SYNCHRONOUS_IO_NONALERT,

    NULL,

    0);

if( !NT_SUCCESS(ntStatus) )

{

    KdPrint(("The file is nor exist!\n"));

    return;

}



FILE_STANDARD_INFORMATION fsi;



//读取文件长度

ntStatus = ZwQueryInformationFile(hfile,

    &iostatus,

    &fsi,

    sizeof(FILE_STANDARD_INFORMATION),

    FileStandardInformation);



KdPrint(("Thr program want to read %d bytes\n", fsi.EndOfFile.QuadPart));



//为读取的文件分配缓冲区

PUCHAR pBuffer = (PUCHAR)ExAllocatePool(PagedPool, (LONG)fsi.EndOfFile.QuadPart);



//读文件

NTSTATUS ntStatus = ZwReadFile(hfile,

    NULL,

    NULL,

    NULL,

    &iostatus,

    pBuffer,

    BUFFER_SIZE,

    (LONG)fsi.EndOfFile.QuadPart,

    NULL);



if( NT_SUCCESS(ntStatus) )

{

    KdPrint(("Read file successfully!\n"));

}

else

{

    KdPrint(("Read file unsuccessfully!\n"));

}



KdPrint(("The program really read %d bytes\n", iostatus.Information));



//关闭文件句柄

ZwClose(hfile);



//释放缓冲区

ExFreePool(pBuffer);

 

你可能感兴趣的:(windows)