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;
}