Window内核函数 - 文件的创建

        在驱动程序开发中,经常会对文件进行操作。与Win32API不同,DDK提供另一套对文件的操作函数。

        对文件的创建或者打开都是通过内核函数 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,
    IN ULONG FileAttributes,
    IN ULONG ShareAccess,
    IN ULONG CreateDisposition,
    IN ULONG CreateOptions,
    IN PVOID EaBuffer,
    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: FILE_SHARED_READ或0,指定文件的共享方式。如果仅为读数据而打开文件,则可以与其他线程同时读取该文件。如果为写数据而打开文件,可能不希望其他线程访问该文件。
// CreateDisposition: FILE_OPEN 或 FILE_OVERWRITE_IF, 表明当指定文件存在或不存在时应如何处理。
// CreateOptions: FILE_SYNCHRONOUS_IO_NONALERT, 制定控制打开操作和句柄使用的附加标志位。
// EaBuffer: 一个指针,指向可选的扩展属性区。
// EaLength: 扩展属性区的长度。
这个函数需要填写CreateDisposition参数。如果想打开文件,CreateDisposition参数设置成FILE_OPEN。如果想创建文件,CreateDisposition参数设置成FILE_OVERWRITE_IF。此时,无论文件是否存在,都会创建新文件。


        文件名的指定是通过设定第三个参数ObjectAttributes。这个参数是一个 OBJECT_ATTRIBUTES 结构。DDK提供对OBJECT_ATTRIBUTES结构初始化的宏 InitializeObjectAttributes.

 VOID InitializeObjectAttributes(
     OUT POBJECT_ATTRIBUTES InitializedAttributes,
     IN PUNICODE_STRING ObjectName,
     IN ULONG Attributes,
     IN HANDLE RootDirectory,
     IN PSECURITY_DESCRIPTOR RecurityDescriptor
     );
// InitializedAttributes:返回的 POBJECT_ATTRIBUTES 结构;
// ObjectName: 对象名称, 用UNICODE_STRING描述,这里设置的是文件名。
// Attributes: 一般设为OBJ_CASE_INSENSITIVE, 对大小写敏感。
// RootDirectory:一般设为NULL。
// RecurityDescriptor: 一般设为NULL。

        另外文件名必须是符号链接或者是设备名。符号链接的概念在前面已经说过。如, 盘符“C:”就是一个符号链接。这里应该用“\??\c:”代替,“c:\1.log”要写成"\??\c:\1.log"。

        其中, "\??\c:"是符号链接,内核会将它转换成设备名“\Device\HarddiskVolume1”。下面的代码演示了如何在驱动程序中创建文件和打开文件。

(1)创建文件

OBJECT_ATTRIBUTES objectAttributes;
IO_STATUS_BLOCK iostatus;
HANDLE hfile;
UNICODE_STRING logFileUnicodeStr1;

// 初始化UNICODE_STRING字符串
RtlInitUnicodeString(&logFileUnicodeStr1, L"\\?\\C:\\1.log");
// 或者写成 L"\\Device\\HarddiskVolume1\\1.log"

// 初始化objectAttributes
InitializeObjectAttributes(&objectAttributes,
                        &logFileUnicodeStr1,
                        OBJ_CASE_INSENSITIVE,
                        NULL,
                        NULL);
                        
// 创建文件
NTSTATUS ntStatus = ZwCreateFile(&hfile,
                            GENERIC_WRITE,
                            &objectAttributes,
                            &iostatus,
                            NULL,
                            FILE_ATTRIBUTE_NOMAL,
                            FILE_SHARE_READ,
                            FILE_OPEN_IF,
                            FILE_SYNCHARONOUS_IO_NONALERT,
                            NULL,
                            0);
if(NT_STATUS(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 logFileUnicodeStr1;

// 初始化UNICODE_STRING字符串
RtlInitUnicodeString(&logFileUnicodeStr1, L"\\?\\C:\\1.log");
// 或者写成 L"\\Device\\HarddiskVolume1\\1.log"

// 初始化objectAttributes
InitializeObjectAttributes(&objectAttributes,
                        &logFileUnicodeStr1,
                        OBJ_CASE_INSENSITIVE,
                        NULL,
                        NULL);
                        
// 创建文件
NTSTATUS ntStatus = ZwCreateFile(&hfile,
                            GENERIC_READ,
                            &objectAttributes,
                            &iostatus,
                            NULL,
                            FILE_ATTRIBUTE_NOMAL,
                            FILE_SHARE_READ,
                            FILE_OPEN,  // 打开文件,如果不存在,则返回错误
                            FILE_SYNCHARONOUS_IO_NONALERT,
                            NULL,
                            0);
if(NT_STATUS(ntStatus))
{
    KdPrint(("Create file successfully!\n"));
)
else
{
    KdPrint(("Create file unsuccessfully!\n"));
}

// 文件操作 
// ……

// 关闭文件句柄
ZwClose(hfile);


        我们可以观察打开文件和创建文件的不同操作方法。需要注意的是,文件被打开后,一定要记得关闭句柄,关闭句柄使用ZwClose内核函数。

  • 9
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

WendyWJGu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值