内核文件读写操作--非MiniFilter模式

        日常驱动开发中文件读写操作十分频繁,经常写不少重复的轮子,这里把生产环境稳定的文件读写操作模版发出来,方便有需要的同学不必重复造轮子。注意,我这里驱动开发使用的是C++17或者更高,所以大部分都是c++代码或者Template模板代码,需要设置c++编译环境才能使用。(注意,这里的代码示例不能在MiniFilter中使用,会造成重入;MiniFilter中文件的读写会在另一个帖子中说明)

文件读操作模板


//读取文件内容(全部/指定偏移与大小),调用者需要释放返回的内存指针
template <typename T>
PVOID ReadFromFile(T* szFilePath, PLARGE_INTEGER uOffset, ULONG uReadLen)
{
    WKD_ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
    UNREFERENCED_PARAMETER(uOffset);
    PVOID pBufPtr = NULL;
    BOOLEAN bMalloc = FALSE;
    NTSTATUS Status = STATUS_SUCCESS;
    HANDLE hFile = NULL;
    ULONG uBufSize = 0;
    OBJECT_ATTRIBUTES objAttrs = { 0 };
    UNICODE_STRING uFilePath;
    IO_STATUS_BLOCK ioStatus;
    auto iModel = sizeof(T);
    if (iModel == 1)
    {
        ANSI_STRING asiPath;
        RtlInitAnsiString(&asiPath, (PCSZ)szFilePath);
        RtlAnsiStringToUnicodeString(&uFilePath, &asiPath, TRUE);
        bMalloc = TRUE;
    }
    else if (iModel == 2)
    {
        RtlInitUnicodeString(&uFilePath, (PCWSTR)szFilePath);
    }

    InitializeObjectAttributes(
        &objAttrs, &uFilePath,
        OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL
    );

    Status = ZwCreateFile(
        &hFile, GENERIC_READ, &objAttrs,
        &ioStatus, NULL, FILE_ATTRIBUTE_NORMAL,
        FILE_SHARE_READ, FILE_OPEN,
        FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
        NULL, 0);
    if (NT_SUCCESS(Status))
    {
        FILE_STANDARD_INFORMATION fsi = { 0 };
        Status = ZwQueryInformationFile(hFile,
            &ioStatus,
            &fsi,
            sizeof(FILE_STANDARD_INFORMATION),
            FileStandardInformation);

        if (uReadLen == 0)//0:表示读取全部文件,>0 读取指定数量的字节
        {
            uBufSize = fsi.EndOfFile.LowPart;
        }
        else if (uReadLen > 0 && uReadLen <= fsi.EndOfFile.LowPart)
        {
            uBufSize = uReadLen;
        }


        DbgPrint("file size:[%d]\n", uBufSize);


        uOffset->QuadPart = uBufSize;
        pBufPtr = kMalloc(uBufSize + 2);
        if (pBufPtr)
        {
            RtlZeroMemory(&ioStatus, sizeof(ioStatus));
            Status = ZwReadFile(hFile, NULL, NULL, NULL, &ioStatus, pBufPtr, uBufSize, NULL, NULL);
            if (!NT_SUCCESS(Status))
            {
                DbgPrint("ZwReadFile failed:[%08x]\n", Status);
                kFree(pBufPtr);
                pBufPtr = NULL;

            }
        }

        ZwClose(hFile);
    }
    else
    {
        DbgPrint("ZwCreateFile failed:%s\n",szFilePath);

    }
    if (bMalloc)
    {
        RtlFreeUnicodeString(&uFilePath);
    }
    return pBufPtr;
}

调用示例:

//用到的工具函数
    PVOID kMalloc(SIZE_T size)
    {
        PVOID pTmp = (PVOID)ExAllocatePoolWithTag(NonPagedPool, size, 'pmt9');
        if (pTmp)
        {
            RtlZeroMemory(pTmp, size);
        }
        return pTmp;
    }

    VOID kFree(PVOID pMem)
    {
        if (pMem)
        {
            ExFreePoolWithTag(pMem, '0GAT');
            pMem = 0;
        }
    }


    LARGE_INTEGER offset = { 0 };
    PVOID pExeBuf = ReadFromFile("\\??\\c:\\test.txt", &offset, 0);//全部读入
    if (pExeBuf)
    {
       //业务逻辑
       DbgPrint("read:%s\n", pExeBuf);


        //释放内存
        kFree(pExeBuf);
    }

文件写操作模板

//写文件(覆盖写/追加写)
enum _FILE_WRITE_TYPE
{
    _FILE_OVERWRITE,        //覆盖写
    _FILE_APPENDWRITE       //追加写
};

template <typename T, typename C>
NTSTATUS WriteToFile(T* szFilePath, C szBuf, int nLen, _FILE_WRITE_TYPE mType)
{
    WKD_ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);

    BOOLEAN bMalloc = FALSE;
    NTSTATUS Status = STATUS_SUCCESS;
    HANDLE hFile = NULL;
    LARGE_INTEGER offset;
    OBJECT_ATTRIBUTES objAttrs = { 0 };
    UNICODE_STRING uFilePath;
    IO_STATUS_BLOCK ioStatus;
    auto iModel = sizeof(T);
    if (iModel == 1)
    {
        ANSI_STRING asiPath;
        RtlInitAnsiString(&asiPath, (PCSZ)szFilePath);
        RtlAnsiStringToUnicodeString(&uFilePath, &asiPath, TRUE);
        bMalloc = TRUE;
    }
    else if (iModel == 2)
    {
        RtlInitUnicodeString(&uFilePath, (PCWSTR)szFilePath);
    }

    InitializeObjectAttributes(
        &objAttrs, &uFilePath,
        OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL
    );

    Status = ZwCreateFile(
        &hFile, GENERIC_ALL, &objAttrs,
        &ioStatus, NULL, FILE_ATTRIBUTE_NORMAL,
        FILE_SHARE_READ, (mType == _FILE_APPENDWRITE) ? FILE_OPEN_IF : FILE_SUPERSEDE,
        FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
        NULL, 0);
    if (NT_SUCCESS(Status))
    {

        //设置指针偏移
        switch (mType)
        {
        case _FILE_OVERWRITE:
        {
            offset.QuadPart = 0;
            break;
        }
        case _FILE_APPENDWRITE:
        {

            offset.QuadPart = -1;
            break;
        }
        }

        Status = ZwWriteFile(
            hFile, NULL, NULL, NULL,
            &ioStatus, (PVOID)szBuf, nLen,
            &offset, NULL);

        ZwClose(hFile);
    }

    if (bMalloc)
    {
        RtlFreeUnicodeString(&uFilePath);
    }
    return Status;
}

调用示例:

char* fpath = "\\??\\c:\\test.lnk";//注意路径需要拼接"\\??\\"
char* pData = "this is 中文数据";
WriteToFile(fpath, pData, strlen(pData), _FILE_APPENDWRITE);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值