NT驱动使用设备扩展的例子

前言

设备扩展,可以消掉操作每个设备时需要的全局变量.

试验记录

模拟向文件中写入2次字符串,第二次写时调整文件指针的位置.然后调整文件指针,从文件头开始读字符串.
设备IO采用缓冲区方式.
设备扩展是DEVICE_OBJECT.DeviceExtension, 不是DEVICE_OBJECT.DeviceObjectExtension, 这个有可能会看错.
这里写图片描述

R3

// hw.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <WinIoCtl.h>

#define SYM_LINK_NAME_R3 L"\\\\?\\TestVf"
#define LEN_BUFFER_ON_DEVICE_EXT 4096

#define CTL_BASE 0x1000
#define MY_CTL_CODE(x) CTL_CODE(FILE_DEVICE_UNKNOWN, CTL_BASE + (x), METHOD_BUFFERED, FILE_ANY_ACCESS)

#define MY_IOCTL_GET_FILE_SIZE  MY_CTL_CODE(1)
#define MY_IOCTL_SET_FILE_POS   MY_CTL_CODE(2)

int main(int argc, char* argv[])
{
    HANDLE hFile = INVALID_HANDLE_VALUE;
    char szBuf[LEN_BUFFER_ON_DEVICE_EXT] = {'\0'};
    size_t nLenWrite = 0;
    DWORD dwCnt = 0;
    ULONG ulFileSize = 0;
    ULONG ulFilePos = 0;
    DWORD dwRc = 0;
    printf("CreateFile...\r\n");
    hFile = CreateFileW(
                SYM_LINK_NAME_R3,
                GENERIC_READ | GENERIC_WRITE,
                0,
                NULL,
                OPEN_EXISTING,
                FILE_ATTRIBUTE_NORMAL,
                NULL);

    if (INVALID_HANDLE_VALUE != hFile) {
        if (::DeviceIoControl(hFile, MY_IOCTL_GET_FILE_SIZE,
                              &ulFileSize, sizeof(ulFileSize),
                              &ulFileSize, sizeof(ulFileSize), &dwRc, NULL)) {
            printf("ulFileSize = 0x%X\r\n", ulFileSize);
        }

        strcpy(szBuf, "hello_");

        if (WriteFile(hFile, szBuf, strlen(szBuf), &dwCnt, NULL)) {
            nLenWrite += dwCnt;
        }

        ZeroMemory(szBuf, sizeof(szBuf));
        ReadFile(hFile, szBuf, nLenWrite, &dwCnt, NULL);
        printf("dwCnt = %d, ReadFrom Drv is : %s\r\n", dwCnt, szBuf);
        strcpy(szBuf, "world");

        ulFilePos = 6;
        if (::DeviceIoControl(hFile, MY_IOCTL_SET_FILE_POS,
            &ulFilePos, sizeof(ulFilePos),
            &ulFilePos, sizeof(ulFilePos), &dwRc, NULL)) {
            printf("ulFilePos = 0x%X\r\n", ulFilePos);
        }

        if (WriteFile(hFile, szBuf, strlen(szBuf), &dwCnt, NULL)) {
            nLenWrite += dwCnt;
        }

        ulFilePos = 0;
        if (::DeviceIoControl(hFile, MY_IOCTL_SET_FILE_POS,
            &ulFilePos, sizeof(ulFilePos),
            &ulFilePos, sizeof(ulFilePos), &dwRc, NULL)) {
            printf("ulFilePos = 0x%X\r\n", ulFilePos);
        }

        ZeroMemory(szBuf, sizeof(szBuf));
        ReadFile(hFile, szBuf, nLenWrite, &dwCnt, NULL);
        printf("dwCnt = %d, ReadFrom Drv is : %s\r\n", dwCnt, szBuf);
        CloseHandle(hFile);
        hFile = NULL;
    } else {
        printf("failed : CreateFile errSn = %d\r\n", GetLastError());
    }

    system("pause");
    return 0;
}

R0

// @file hw.c
// @brief 设备扩展的例子

#include <ntddk.h>

#define DEVICE_NAME L"\\device\\TestVf"
#define SYM_LINK_NAME_R0 L"\\??\\TestVf"
#define SYM_LINK_NAME_R3 L"\\\\?\\TestVf"
#define POOL_TAG_DEVICE_EXT 'ext1'
#define LEN_BUFFER_ON_DEVICE_EXT 4096

#define CTL_BASE 0x1000
#define MY_CTL_CODE(x) CTL_CODE(FILE_DEVICE_UNKNOWN, CTL_BASE + (x), METHOD_BUFFERED, FILE_ANY_ACCESS)

#define MY_IOCTL_GET_FILE_SIZE  MY_CTL_CODE(1)
#define MY_IOCTL_SET_FILE_POS   MY_CTL_CODE(2)

typedef struct _DEVICE_EXTENSION {
    PDEVICE_OBJECT pDevice;
    UNICODE_STRING strDeviceName;
    UNICODE_STRING strSymLinkName;

    PUCHAR pBuffer;
    ULONG uLenBuffer;
    ULONG ulFilePos;
    KEVENT EventBuffer;
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;

NTSTATUS DriverEntry(__in struct _DRIVER_OBJECT*  DriverObject, __in PUNICODE_STRING  RegistryPath);
#pragma alloc_text( "INIT", DriverEntry)

VOID OnUnload(__in struct _DRIVER_OBJECT* DriverObject);
#pragma alloc_text( "PAGE", OnUnload)

NTSTATUS DispatchEmpty(__in struct _DEVICE_OBJECT*  DeviceObject,
                       __in struct _IRP*  Irp);
#pragma alloc_text( "PAGE", DispatchEmpty)

NTSTATUS OnCreate(__in struct _DEVICE_OBJECT*  DeviceObject,
                  __in struct _IRP*  Irp);
#pragma alloc_text( "PAGE", OnCreate)

NTSTATUS OnRead(__in struct _DEVICE_OBJECT*  DeviceObject,
                __in struct _IRP*  Irp);
#pragma alloc_text( "PAGE", OnRead)

NTSTATUS OnWrite(__in struct _DEVICE_OBJECT*  DeviceObject,
                 __in struct _IRP*  Irp);
#pragma alloc_text( "PAGE", OnWrite)

NTSTATUS OnControl(__in struct _DEVICE_OBJECT*  DeviceObject,
                   __in struct _IRP*  Irp);
#pragma alloc_text( "PAGE", OnControl)

NTSTATUS OnClose(__in struct _DEVICE_OBJECT*  DeviceObject,
                 __in struct _IRP*  Irp);
#pragma alloc_text( "PAGE", OnClose)

NTSTATUS fnCreateDevice(IN PDRIVER_OBJECT pDriverObject);
#pragma alloc_text( "PAGE", fnCreateDevice)

NTSTATUS DriverEntry(__in struct _DRIVER_OBJECT*  DriverObject, __in PUNICODE_STRING  RegistryPath)
{
    DriverObject->DriverUnload = OnUnload;
    DriverObject->MajorFunction[IRP_MJ_CREATE] = OnCreate;
    DriverObject->MajorFunction[IRP_MJ_CLOSE] = OnClose;
    DriverObject->MajorFunction[IRP_MJ_READ] = OnRead;
    DriverObject->MajorFunction[IRP_MJ_WRITE] = OnWrite;
    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = OnControl;
    DriverObject->MajorFunction[IRP_MJ_CREATE_NAMED_PIPE] = DispatchEmpty;
    DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = DispatchEmpty;
    DriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] = DispatchEmpty;
    DriverObject->MajorFunction[IRP_MJ_QUERY_EA] = DispatchEmpty;
    DriverObject->MajorFunction[IRP_MJ_SET_EA] = DispatchEmpty;
    DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = DispatchEmpty;
    DriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] = DispatchEmpty;
    DriverObject->MajorFunction[IRP_MJ_SET_VOLUME_INFORMATION] = DispatchEmpty;
    DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] = DispatchEmpty;
    DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = DispatchEmpty;
    DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = DispatchEmpty;
    DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = DispatchEmpty;
    DriverObject->MajorFunction[IRP_MJ_LOCK_CONTROL] = DispatchEmpty;
    DriverObject->MajorFunction[IRP_MJ_CLEANUP] = DispatchEmpty;
    DriverObject->MajorFunction[IRP_MJ_CREATE_MAILSLOT] = DispatchEmpty;
    DriverObject->MajorFunction[IRP_MJ_QUERY_SECURITY] = DispatchEmpty;
    DriverObject->MajorFunction[IRP_MJ_SET_SECURITY] = DispatchEmpty;
    DriverObject->MajorFunction[IRP_MJ_POWER] = DispatchEmpty;
    DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = DispatchEmpty;
    DriverObject->MajorFunction[IRP_MJ_DEVICE_CHANGE] = DispatchEmpty;
    DriverObject->MajorFunction[IRP_MJ_QUERY_QUOTA] = DispatchEmpty;
    DriverObject->MajorFunction[IRP_MJ_SET_QUOTA] = DispatchEmpty;
    DriverObject->MajorFunction[IRP_MJ_PNP] = DispatchEmpty;
    return fnCreateDevice(DriverObject);
}

NTSTATUS fnCreateDevice(IN PDRIVER_OBJECT pDriverObject)
{
    NTSTATUS status;
    PDEVICE_OBJECT pDevObj;
    PDEVICE_EXTENSION pDevExt;
    UNICODE_STRING strSymLinkName;
    UNICODE_STRING strDeviceName;

    // DbgBreakPoint();
    RtlInitUnicodeString(&strDeviceName, DEVICE_NAME);
    status = IoCreateDevice(pDriverObject,
                            sizeof(DEVICE_EXTENSION),
                            &strDeviceName,
                            FILE_DEVICE_UNKNOWN,
                            0, TRUE,
                            &pDevObj);

    if (!NT_SUCCESS(status)) {
        KdPrint(("IoCreateDevice failed"));
        return status;
    }

    pDevObj->Flags = DO_BUFFERED_IO;
    pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;
    pDevExt->pDevice = pDevObj;
    RtlInitUnicodeString(&pDevExt->strDeviceName, DEVICE_NAME);

    pDevExt->pBuffer = NULL;
    pDevExt->uLenBuffer = 0;
    pDevExt->ulFilePos = 0;

    RtlInitUnicodeString(&strSymLinkName, SYM_LINK_NAME_R0);
    RtlInitUnicodeString(&pDevExt->strSymLinkName, SYM_LINK_NAME_R0);

    status = IoCreateSymbolicLink(&strSymLinkName, &strDeviceName);

    if (!NT_SUCCESS(status)) {
        KdPrint(("IoCreateSymbolicLink failed"));
        IoDeleteDevice(pDevObj);
        return status;
    }

    KdPrint(("fnCreateDevice ok."));
    return STATUS_SUCCESS;
}

VOID OnUnload(__in struct _DRIVER_OBJECT* DriverObject)
{
    PDEVICE_EXTENSION pDevExt;
    PDEVICE_OBJECT  pNextObj = DriverObject->DeviceObject;
    KdPrint((">> fnDrvUnLoad"));
    // DbgBreakPoint();

    while (pNextObj != NULL) {
        pDevExt = (PDEVICE_EXTENSION)pNextObj->DeviceExtension;

        if (NULL != pDevExt) {
            KdPrint(("IoDeleteSymbolicLink %wZ", pDevExt->strSymLinkName));
            IoDeleteSymbolicLink(&pDevExt->strSymLinkName);
            IoDeleteDevice(pDevExt->pDevice);
        }

        pNextObj = pNextObj->NextDevice;
    }
}

NTSTATUS DispatchEmpty(__in struct _DEVICE_OBJECT*  DeviceObject,
                       __in struct _IRP*  Irp)
{
    return STATUS_SUCCESS;
}

NTSTATUS OnCreate(__in struct _DEVICE_OBJECT*  DeviceObject,
                  __in struct _IRP*  Irp)
{
    PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
    KdPrint((">> OnCreate\n"));
    // DbgBreakPoint();

    pDevExt->pBuffer = (PUCHAR)ExAllocatePoolWithTag(PagedPool, LEN_BUFFER_ON_DEVICE_EXT, POOL_TAG_DEVICE_EXT);
    pDevExt->uLenBuffer = LEN_BUFFER_ON_DEVICE_EXT;
    KeInitializeEvent(&pDevExt->EventBuffer, SynchronizationEvent, TRUE);
    return STATUS_SUCCESS;
}

NTSTATUS OnRead(__in struct _DEVICE_OBJECT*  DeviceObject,
                __in struct _IRP*  Irp)
{
    PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
    NTSTATUS status = STATUS_SUCCESS;
    PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
    ULONG ulLen = stack->Parameters.Read.Length;
    ULONG ulOffset = (ULONG)stack->Parameters.Read.ByteOffset.QuadPart;

    // DbgBreakPoint();
    if ((ulOffset + ulLen + pDevExt->ulFilePos) > pDevExt->uLenBuffer) {
        status = STATUS_FILE_INVALID;
        ulLen = 0;
    } else {
        KeWaitForSingleObject(&pDevExt->EventBuffer, Executive, KernelMode, FALSE , NULL);
        memcpy(Irp->AssociatedIrp.SystemBuffer, pDevExt->pBuffer + ulOffset + pDevExt->ulFilePos, ulLen);
        KeSetEvent(&pDevExt->EventBuffer, IO_NO_INCREMENT, FALSE);
        status = STATUS_SUCCESS;
    }

    Irp->IoStatus.Status = status;
    Irp->IoStatus.Information = ulLen;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    return status;
}

NTSTATUS OnWrite(__in struct _DEVICE_OBJECT*  DeviceObject,
                 __in struct _IRP*  Irp)
{
    NTSTATUS Status = STATUS_SUCCESS;
    PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
    PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
    ULONG ulLen = stack->Parameters.Write.Length;
    ULONG ulOffset = (ULONG)stack->Parameters.Write.ByteOffset.QuadPart;

    // DbgBreakPoint();
    if ((ulLen + ulOffset + pDevExt->ulFilePos) > pDevExt->uLenBuffer) {
        Status = STATUS_FILE_INVALID;
        ulLen = 0;
    } else {
        KeWaitForSingleObject(&pDevExt->EventBuffer, Executive, KernelMode, FALSE , NULL);
        memcpy(pDevExt->pBuffer + ulOffset + pDevExt->ulFilePos, Irp->AssociatedIrp.SystemBuffer, ulLen);
        KeSetEvent(&pDevExt->EventBuffer, IO_NO_INCREMENT, FALSE);
        Status = STATUS_SUCCESS;
    }

    Irp->IoStatus.Status = Status;
    Irp->IoStatus.Information = ulLen;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    return Status;
}

NTSTATUS OnControl(__in struct _DEVICE_OBJECT*  DeviceObject,
                   __in struct _IRP*  Irp)
{
    PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
    PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(Irp);
    ULONG nCtlCode = pIrpStack->Parameters.DeviceIoControl.IoControlCode;
    PVOID pBuf = Irp->AssociatedIrp.SystemBuffer;
    ULONG nInLength = pIrpStack->Parameters.DeviceIoControl.InputBufferLength;
    ULONG nOutLength = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength;
    NTSTATUS status = STATUS_UNSUCCESSFUL;
    ULONG nLength = 0;

    KdPrint(("DispatchControl\r\n"));
    // DbgBreakPoint();

    switch(nCtlCode)
    {
    case MY_IOCTL_GET_FILE_SIZE:
        KdPrint(("MY_IOCTL_GET_FILE_SIZE\r\n"));
        RtlCopyMemory(pBuf, &pDevExt->uLenBuffer, sizeof(ULONG));
        status = STATUS_SUCCESS;
        nLength = sizeof(ULONG);
        break;
    case MY_IOCTL_SET_FILE_POS:
        KdPrint(("MY_IOCTL_SET_FILE_POS\r\n"));
        RtlCopyMemory(&pDevExt->ulFilePos, pBuf, sizeof(ULONG));
        status = STATUS_SUCCESS;
        nLength = sizeof(ULONG);
        break;
    default:
        break;
    }

    //完成请求
    Irp->IoStatus.Status = status;
    Irp->IoStatus.Information = nLength; 
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    return STATUS_SUCCESS;
}

NTSTATUS OnClose(__in struct _DEVICE_OBJECT*  DeviceObject,
                 __in struct _IRP*  Irp)
{
    PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
    // DbgBreakPoint();
    ExFreePoolWithTag(pDevExt->pBuffer, POOL_TAG_DEVICE_EXT);
    return STATUS_SUCCESS;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值