• 【驱动笔记3】在驱动中读写文件

    2009-01-02

    分类:内核编程

    版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明
    http://nokyo.blogbus.com/logs/33307633.html

    文章作者:grayfox
    作者主页:http://nokyo.blogbus.com
    原始出处:http://nokyo.blogbus.com/logs/33307633.html 

        对文件的读写操作一直是我们需要熟练掌握的内容,在ring3我们可以使用CreateFile、ReadFile、WriteFile等API,在ring0同样很相似,不过函数变成了ZwCreateFile、ZwReadFile、ZwWriteFile等函数。
        在“【驱动笔记1】第一个驱动程序”一文中我们曾经用到过ZwCreateFile,并且成功使用它创建了一个新文件,但那个文件里面什么内容也没有。本节我们就对那个程序进行扩充,实现一个MyCopyFile函数,通过文件的读写来复制文件。
        下面的代码来自楚狂人的《Windows驱动编程基础教程》,我把它前面省略的文件打开和缓冲区分配过程都补充完整了,下面是该函数的完整代码。

    BOOLEAN
    MyCopyFile(
               IN PUNICODE_STRING    ustrDestFile,
               IN PUNICODE_STRING    ustrSrcFile
                )
    {
        HANDLE    hSrcFile, hDestFile;
        PVOID    buffer = NULL;
        ULONG    length = 0;
        LARGE_INTEGER    offset = {0};
        IO_STATUS_BLOCK Io_Status_Block = {0};
        OBJECT_ATTRIBUTES obj_attrib;
        NTSTATUS status;
        BOOLEAN  bRet = FALSE;

        do
        {
            // 打开源文件
            InitializeObjectAttributes(    &obj_attrib,
                ustrSrcFile,
                OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
                NULL,
                NULL);
            status = ZwCreateFile(    &hSrcFile,
                GENERIC_READ,
                &obj_attrib,
                &Io_Status_Block,
                NULL,
                FILE_ATTRIBUTE_NORMAL,
                FILE_SHARE_READ,
                FILE_OPEN,
                FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
                NULL,
                0 );
            if (!NT_SUCCESS(status))
            {
                bRet = FALSE;
                goto END;
            }

            // 打开目标文件
            InitializeObjectAttributes(    &obj_attrib,
                                    ustrDestFile,
                                    OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
                                    NULL,
                                    NULL);
            status = ZwCreateFile(    &hDestFile,
                GENERIC_WRITE,
                &obj_attrib,
                &Io_Status_Block,
                NULL,
                FILE_ATTRIBUTE_NORMAL,
                FILE_SHARE_READ,
                FILE_OPEN_IF,
                FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
                NULL,
                0 );
            if (!NT_SUCCESS(status))
            {
                bRet = FALSE;
                goto END;
            }

            // 为buffer分配4KB空间
            buffer = ExAllocatePool(NonPagedPool, 1024 * 4);
            if (buffer == NULL)
            {
                bRet = FALSE;
                goto END;
            }

            // 复制文件
            while (1)
            {
                length = 4 * 1024;
                // 读取源文件
                status = ZwReadFile(hSrcFile,
                                NULL,
                                NULL,
                                NULL,
                                &Io_Status_Block,
                                buffer,
                                length,
                                &offset,
                                NULL);
                if (!NT_SUCCESS(status))
                {
                    // 如果状态为STATUS_END_OF_FILE,说明文件已经读取到末尾
                    if (status == STATUS_END_OF_FILE)
                    {
                        bRet = TRUE;
                        goto END;
                    }
                }

                // 获得实际读取的长度
                length = Io_Status_Block.Information;

                // 写入到目标文件
                status = ZwWriteFile(    hDestFile,
                                    NULL,
                                    NULL,
                                    NULL,
                                    &Io_Status_Block,
                                    buffer,
                                    length,
                                    &offset,
                                    NULL);
                if (!NT_SUCCESS(status))
                {
                    bRet = FALSE;
                    goto END;
                }
               
                // 移动文件指针
                offset.QuadPart += length;
            }

        } while (0);

    END:
        if (hSrcFile)
        {
            ZwClose(hSrcFile);
        }
        if (hDestFile)
        {
            ZwClose(hDestFile);
        }
        if (buffer = NULL)
        {
            ExFreePool(buffer);
        }

        return bRet;
    }

        在DriverEntry中调用该函数的测试代码如下所示:

        // 测试函数
        RtlInitUnicodeString(&ustrSrcFile, L"
    \\??\\C:\\windows\\notepad.exe");
        RtlInitUnicodeString(&ustrDestFile, L"
    \\??\\C:\\notepad.exe");

        if(MyCopyFile(&ustrDestFile, &ustrSrcFile))
        {
             KdPrint(("[ReadFileTest] CopyFile Success!"));
        }
        else
        {  
             KdPrint(("[ReadFileTest] CopyFile Error!"));
        }

        OK,这个时候我们就算完工了,把编译出的sys复制到虚拟机中执行,效果如下图所示:


    历史上的今天:





    评论

  • 晕,我传的有图啊,我在几个同学那里测试都能看到啊,我用的巴巴变网络相册,blogbus自己的空间太小了,10M很快就能用完。
  • 你文章的图都是叉叉呢 BLOGBUS可以上传图片的好不 在“插入图片”里面可以上传。