window內核驅動開發學習--應用程序與驅動程序交互(緩衝模式)

新建exe控制檯程序

#include "pch.h"
#include <windows.h>
#include <iostream>
#include <WinIoCtl.h>

#include "ctl_code.h"

using namespace std;
#pragma warning(disable: 4789)
int add(HANDLE hDevice, int a, int b)
{
	int port[2] = {0x00};
	int buffret;
	ULONG dwWrite;
	port[0] = a;
	port[1] = b;
	::DeviceIoControl(hDevice, add_code, &port, 8, &buffret, 4, &dwWrite, NULL);
	return buffret;
}
int main()
{
	HANDLE hDevice = ::CreateFileA("\\\\.\\MySysData",
		GENERIC_READ|GENERIC_WRITE,
		0,
		NULL,
		OPEN_EXISTING,
		FILE_ATTRIBUTE_NORMAL,
		NULL);
	if (hDevice == INVALID_HANDLE_VALUE)
	{
		cout << "獲取驅動句柄失敗" <<GetLastError() <<endl;
	}
	int a, b;
	while (true)
	{
		cin >> a >> b;
		int r = add(hDevice, a, b);
		cout << a << " + " << b << " = " << r << endl;
		getchar();
	}

    std::cout << "Hello World!\n"; 
}

ctl_code.h代碼

#pragma once
#include <WinIoCtl.h>
#define add_code CTL_CODE(FILE_DEVICE_UNKNOWN, 	0x800, 	METHOD_BUFFERED,FILE_ANY_ACCESS)
#define sub_code CTL_CODE(FILE_DEVICE_UNKNOWN, 	0x801, 	METHOD_BUFFERED,FILE_ANY_ACCESS)

新建kmdf空工程,代碼如下

#include <ntddk.h>

#include "clt_code.h"

#define INITCODE code_seg("INIT");
#define PAGECODE code_seg("PAGE");

NTSTATUS CreateMyDevice(IN PDRIVER_OBJECT pDriverObject)
{
	NTSTATUS status;
	UNICODE_STRING devName;  //設備名稱
	UNICODE_STRING sysLinkName;  //系統符號鏈接名
	PDEVICE_OBJECT pDevObject;    //用於返回創建設備

	RtlInitUnicodeString(&devName, L"\\Device\\MyDevObj");
	status = IoCreateDevice(pDriverObject, 0, &devName, FILE_DEVICE_UNKNOWN, 0, TRUE, &pDevObject);
	if (!NT_SUCCESS(status))
	{
		if (status == STATUS_INSUFFICIENT_RESOURCES)
		{
			KdPrint(("資源不足\n"));
		}
		if (status == STATUS_OBJECT_NAME_EXISTS)
		{
			KdPrint(("指定對象名存在\n"));
		}
		if (status == STATUS_OBJECT_NAME_COLLISION)
		{
			KdPrint(("對象名有衝突"));
		}
		return status;
	}
	KdPrint(("設備創建成功\n"));
	pDevObject->Flags |= DO_BUFFERED_IO; //緩衝區方式讀寫
	RtlInitUnicodeString(&sysLinkName, L"\\??\\MySysData");
	IoDeleteSymbolicLink(&sysLinkName);
	status = IoCreateSymbolicLink(&sysLinkName, &devName); //判斷生成符號鏈接是否成功
	if (!NT_SUCCESS(status))
	{
		KdPrint(("生成符號鏈接失敗\n"));
		IoDeleteDevice(pDevObject);
		return status;
	}
	KdPrint(("生成符號鏈接成功"));

	return STATUS_SUCCESS;
}

VOID DriverUnload(PDRIVER_OBJECT pDriverObject)
{
	PDEVICE_OBJECT pDevObject;
	UNICODE_STRING sysLinkName;

	pDevObject = pDriverObject->DeviceObject;
	IoDeleteDevice(pDevObject);	//取得設備並刪除
	KdPrint(("成功刪除設備\n"));

	RtlInitUnicodeString(&sysLinkName, L"\\??\\MySysData");
	IoDeleteSymbolicLink(&sysLinkName);	//取得符號鏈接並刪除
	KdPrint(("成功刪除符號鏈接\n"));

	KdPrint(("驅動成功卸載\n"));
}


//NTSTATUS MyDispatchRoutine(IN PDEVICE_OBJECT pDevobj, IN PIRP pIrp)
//{
//	return STATUS_SUCCESS;
//}


NTSTATUS MyDispatchRoutine(IN PDEVICE_OBJECT pDevobj, IN PIRP pIrp)
{
	ULONG info;
	PIO_STACK_LOCATION psl = IoGetCurrentIrpStackLocation(pIrp);

	switch (psl->MajorFunction)
	{
		case IRP_MJ_CREATE:
			break;
		case IRP_MJ_CLOSE:
			break;
		case IRP_MJ_READ:
			break;
		case IRP_MJ_WRITE:
			break;
		case IRP_MJ_DEVICE_CONTROL:
		{
			NTSTATUS status = STATUS_SUCCESS;
			ULONG cbin = psl->Parameters.DeviceIoControl.InputBufferLength; //獲取輸入緩衝區大小
			ULONG cbout = psl->Parameters.DeviceIoControl.OutputBufferLength; //獲取輸出緩衝區大小
			ULONG code = psl->Parameters.DeviceIoControl.IoControlCode; //得到IOCTL
			KdPrint(("Enter IRP_MJ_DEVICE_CONTROL\n"));
			switch (code)
			{
			case add_code:
			{
				int a, b, r;
				int * inputBuffer = (int*)pIrp->AssociatedIrp.SystemBuffer;
				int * outBuffer = (int *)pIrp->AssociatedIrp.SystemBuffer;
				KdPrint(("Enter add_code\n"));
				a = *inputBuffer;
				b = *(inputBuffer + 1);

				KdPrint(("a=%d, b=%d\n", a, b));
				r = a + b;
				*outBuffer = r;

				KdPrint(("a+b=%d\n", r));
				info = 4;
				break;
			}
			case sub_code:
			{
				break;
			}

			}
		}
		default:
		{
			KdPrint(("其它處理"));
			break;
		}
	}

	pIrp->IoStatus.Information = info;			//設置操作的字節數爲0,這裏無實際意義
	pIrp->IoStatus.Status = STATUS_SUCCESS;		//返回成功
	IoCompleteRequest(pIrp, IO_NO_INCREMENT);	//指示完成此IRP
	KdPrint(("離開派遣函數\n"));				//調試信息
	return STATUS_SUCCESS;
}
#pragma INITCODE
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING reg_path)
{
	KdPrint(("驅動加載成功\n"));
	pDriverObject->MajorFunction[IRP_MJ_CREATE] = MyDispatchRoutine;
	pDriverObject->MajorFunction[IRP_MJ_CLOSE] = MyDispatchRoutine;
	pDriverObject->MajorFunction[IRP_MJ_READ] = MyDispatchRoutine;
	pDriverObject->MajorFunction[IRP_MJ_WRITE] = MyDispatchRoutine;
	pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = MyDispatchRoutine;
	CreateMyDevice(pDriverObject);
	pDriverObject->DriverUnload = DriverUnload;
	return STATUS_SUCCESS;
}

在測試機中用instdrv驅動加載工具加載並啓動驅動程序:

在cmd下運行exe程序,輸入a b,計算a+b,運行結果如下:

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