驅動開發——WDM+創建設備+與應用層交互

1、內核層代碼

#include <ntddk.h>

#define DEVICE_NAME     L"\\Device\\MyFirstDevice"
#define SYM_NAME        L"\\??\\MyFirstDevice"
#define IOCTL_MUL       CTL_CODE(FILE_DEVICE_UNKNOWN, 0x9888, METHOD_BUFFERED, FILE_ANY_ACCESS)

void DriverUnload(PDRIVER_OBJECT pdriver)
{
    DbgPrint("Unload\n");
    if (pdriver->DeviceObject)
    {
        IoDeleteDevice(pdriver->DeviceObject);
        pdriver->DeviceObject = NULL;

        UNICODE_STRING symName = { 0 };
        RtlInitUnicodeString(&symName, SYM_NAME);
        IoDeleteSymbolicLink(&symName);
    }

}

/**
 * 派遣函數,dispatch
 */
NTSTATUS MyCreate(PDEVICE_OBJECT pDevice, PIRP pirp)
{
    NTSTATUS status = STATUS_SUCCESS;
    DbgPrint("My Device has be opened\n");
    pirp->IoStatus.Status = status;
    pirp->IoStatus.Information = 0;
    IoCompleteRequest(pirp, IO_NO_INCREMENT);
    return status;
}

NTSTATUS MyClose(PDEVICE_OBJECT pDevice, PIRP pirp)
{
    NTSTATUS status = STATUS_SUCCESS;
    DbgPrint("My Device has be closed\n");
    pirp->IoStatus.Status = status;
    pirp->IoStatus.Information = 0;
    IoCompleteRequest(pirp, IO_NO_INCREMENT);
    return status;
}

NTSTATUS MyCleanUp(PDEVICE_OBJECT pDevice, PIRP pirp)
{
    NTSTATUS status = STATUS_SUCCESS;
    DbgPrint("My Device has be cleaned\n");
    pirp->IoStatus.Status = status;
    pirp->IoStatus.Information = 0;
    IoCompleteRequest(pirp, IO_NO_INCREMENT);
    return status;
}

NTSTATUS MyRead(PDEVICE_OBJECT pDevice, PIRP pirp)
{
    NTSTATUS status = STATUS_SUCCESS;
    DbgPrint("My Device has be readed\n");
    char strMsg[] = { "This Message Come From Kernel" };
    int nLen = strlen(strMsg);

    PIO_STACK_LOCATION pstack = IoGetCurrentIrpStackLocation(pirp);
    ///> 獲取應用層需要讀取多大長度
    ULONG uReadSize = pstack->Parameters.Read.Length;
    ///> 獲取應用層接受數據的緩衝區
    PCHAR pBuffer = pirp->AssociatedIrp.SystemBuffer;

    RtlCopyMemory(pBuffer, strMsg, nLen);

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

NTSTATUS MyWrite(PDEVICE_OBJECT pDevice, PIRP pirp)
{
    NTSTATUS status = STATUS_SUCCESS;
    DbgPrint("My Device has be writed\n");

    PIO_STACK_LOCATION pstack = IoGetCurrentIrpStackLocation(pirp);
    ///> 獲取應用層需要寫入多大長度
    ULONG uWriteSize = pstack->Parameters.Write.Length;
    ///> 獲取應用層寫入數據的緩衝區
    PCHAR pBuffer = pirp->AssociatedIrp.SystemBuffer;

    RtlZeroMemory(pDevice->DeviceExtension, 200);
    RtlCopyMemory(pDevice->DeviceExtension, pBuffer, uWriteSize);

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

/**
 * 自定義通信方式
 */
NTSTATUS MyControl(PDEVICE_OBJECT pDevice, PIRP pirp)
{
    NTSTATUS status = STATUS_SUCCESS;
    PIO_STACK_LOCATION pstack = IoGetCurrentIrpStackLocation(pirp);
    ULONG ioCode = pstack->Parameters.DeviceIoControl.IoControlCode;
    ULONG inLen = pstack->Parameters.DeviceIoControl.InputBufferLength;
    ULONG outLen = pstack->Parameters.DeviceIoControl.OutputBufferLength;
    ULONG ioInfo = 0;

    switch (ioCode)
    {
    case IOCTL_MUL:
    {
        DWORD32 dwInData = *(PDWORD32)pirp->AssociatedIrp.SystemBuffer;
        dwInData *= 5;
        *(PDWORD32)pirp->AssociatedIrp.SystemBuffer = dwInData;
        ioInfo = 4;
        break;
    }
    default:
        status = STATUS_UNSUCCESSFUL;
        break;
    }
    pirp->IoStatus.Status = status;
    pirp->IoStatus.Information = ioInfo;
    IoCompleteRequest(pirp, IO_NO_INCREMENT);
    return status;
}

/**
 * IRP請求 ---> IO_STACK 發送給一個設備(類似於應用層的消息)
 */
NTSTATUS DriverEntry(PDRIVER_OBJECT pdriver, PUNICODE_STRING reg_path)
{
    NTSTATUS status = STATUS_SUCCESS;
    UNICODE_STRING deviceName = { 0 };
    PDEVICE_OBJECT pDevice = NULL;

    pdriver->DriverUnload = DriverUnload;

    RtlInitUnicodeString(&deviceName, DEVICE_NAME);

    status = IoCreateDevice(pdriver, 200, &deviceName, FILE_DEVICE_UNKNOWN, 0, TRUE, &pDevice);

    if (!NT_SUCCESS(status))
    {
        DbgPrint("Create Device Fail, status = %x\n", status);
        return status;
    }

    ///> 設置設備的讀寫方式
    pDevice->Flags |= DO_BUFFERED_IO;

    ///> 創建符號連接
    UNICODE_STRING symName = { 0 };
    RtlInitUnicodeString(&symName, SYM_NAME);
    status = IoCreateSymbolicLink(&symName, &deviceName);

    if (!NT_SUCCESS(status))
    {
        DbgPrint("Create SymbolicLink Fail, status = %x\n", status);
        IoDeleteDevice(pDevice);
        return status;
    }

    pdriver->MajorFunction[IRP_MJ_CREATE] = MyCreate;
    pdriver->MajorFunction[IRP_MJ_CLOSE] = MyClose;
    pdriver->MajorFunction[IRP_MJ_CLEANUP] = MyCleanUp;
    pdriver->MajorFunction[IRP_MJ_READ] = MyRead;
    pdriver->MajorFunction[IRP_MJ_WRITE] = MyWrite;
    pdriver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = MyControl;
    return 0;
}

2、應用層代碼

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

#include "stdafx.h"
#include <Windows.h>
#include <stdio.h>
#include <WinIoCtl.h>

#define IOCTL_MUL       CTL_CODE(FILE_DEVICE_UNKNOWN, 0x9888, METHOD_BUFFERED, FILE_ANY_ACCESS)


int main()
{
    HANDLE hDevice = NULL;
    CHAR szBuffer[50] = { 0 };
    DWORD dwRead = 0;

    do
    {
        hDevice = ::CreateFileW(L"\\\\.\\MyFirstDevice",
            GENERIC_READ | GENERIC_WRITE,
            0,
            NULL,
            OPEN_EXISTING,
            FILE_ATTRIBUTE_NORMAL,
            NULL);

        if (INVALID_HANDLE_VALUE == hDevice)
        {
            printf("Open Device Fail\n");
            break;
        }

        printf("Open Device Success\n");
        ::ReadFile(hDevice, (LPVOID)szBuffer, 50, &dwRead, NULL);
        printf("----%p----%s----%d-----\n", szBuffer, szBuffer, dwRead);
        ::WriteFile(hDevice, "This Message Come From R3.", strlen("This Message Come From R3."), &dwRead, NULL);

        printf("DeviceIo\n");
        DWORD a = 888, b = 0;
        ::DeviceIoControl(hDevice, IOCTL_MUL, &a, 4, &b, 4, &dwRead, NULL);
        printf("a = %d, b = %d dwRead = %d", a, b, dwRead);
    } while (0);

    if (hDevice)
    {
        ::CloseHandle(hDevice);
    }
    system("pause");
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章