NT驱动框架复习

版权声明:欢迎转载,注明出处 https://blog.csdn.net/youyou519/article/details/83825334

下面是NT框架

#include <ntddk.h>

#define DEVICE_NAME L"\\device\\ntmodeldrv"  //设备名device开头固定,后面随便取,一般和编译出的.sys一致
#define LINK_NAME L"\\dosdevices\\ntmodeldrv"

#define IOCTRL_BASE 0X8000  //定义IoControl起始范围

#define MYIOCTRL_CODE(i) \
	CTL_CODE(FILE_DEVICE_UNKNOWN,IOCTRL_BASE+i,METHOD_BUFFERED,FILE_ANY_ACCESS)//这里倒数第二个参数是访问模式

#define CTL_HELLO MYIOCTRL_CODE(0)
#define CTL_PRINT MYIOCTRL_CODE(1)
#define CTL_BYE MYIOCTRL_CODE(2)

//定义Ring3的分发函数

//创建分发函数
NTSTATUS DispatchCommon(PDEVICE_OBJECT pObject, PIRP pIrp)
{
	pIrp->IoStatus.Status = STATUS_SUCCESS;//这个是给ring3的返回值
	pIrp->IoStatus.Information = 0;//记录Irp特殊数据,比如读写就是有效字节数
	
	IoCompleteRequest(pIrp, IO_NO_INCREMENT);

	return STATUS_SUCCESS;//这个是给内核驱动管理框架的
}

NTSTATUS DispatchCreate(PDEVICE_OBJECT pObject, PIRP pIrp)//第一个参数驱动设备对象,在DriverEntry创建
{
	pIrp->IoStatus.Status = STATUS_SUCCESS;//这个是给ring3的返回值
	pIrp->IoStatus.Information = 0;//记录Irp特殊数据,比如读写就是有效字节数

	IoCompleteRequest(pIrp, IO_NO_INCREMENT);

	return STATUS_SUCCESS;//这个是给内核驱动管理框架的
}

NTSTATUS DispatchRead(PDEVICE_OBJECT pObject,PIRP pIrp)
{
	//定义读Buffer指针
	PVOID pReadBuffer = NULL;
	ULONG uReadLength = 0;
	PIO_STACK_LOCATION pStack = NULL;
	ULONG uMin = 0;
	ULONG uHelloStr = 0;

	uHelloStr = (wcslen(L"hello world") + 1)*sizeof(WCHAR);

	
	pReadBuffer = pIrp->AssociatedIrp.SystemBuffer;//地址

	pStack = IoGetCurrentIrpStackLocation(pIrp);//获得当前层IRP栈的指针
	
	uReadLength = pStack->Parameters.Read.Length;//从栈的结构体里的联合体获得长度
	uMin = uReadLength > uHelloStr ? uHelloStr : uReadLength;

	RtlCopyMemory(pReadBuffer, L"hello world", uMin);//这里要用目的和源最小的,以防泄露和溢出

	pIrp->IoStatus.Status = STATUS_SUCCESS;
	pIrp->IoStatus.Information = uMin;

	IoCompleteRequest(pIrp, IO_NO_INCREMENT);

	return STATUS_SUCCESS;

}

NTSTATUS DispatchWrite(PDEVICE_OBJECT pObject, PIRP pIrp)
{
	PVOID pWriteBuffer = NULL;
	ULONG uWriteLength = 0;
	PIO_STACK_LOCATION pStack = NULL;

	PVOID pBuffer = NULL;

	pWriteBuffer = pIrp->AssociatedIrp.SystemBuffer;

	pStack = IoGetCurrentIrpStackLocation(pIrp);
	uWriteLength = pStack->Parameters.Write.Length;

	//模拟写,就是分配个内存拷进去数据

	pBuffer = ExAllocatePoolWithTag(PagedPool, uWriteLength, 'NQRY');

	if (NULL == pBuffer)
	{
		pIrp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
		pIrp->IoStatus.Information = 0;
		IoCompleteRequest(pIrp, IO_NO_INCREMENT);

		return STATUS_INSUFFICIENT_RESOURCES;
	}


	//分配成功
	//初始化申请的内存

	memset(pBuffer, 0, uWriteLength);
	RtlCopyMemory(pBuffer, pWriteBuffer, uWriteLength);

	//释放buffer
	ExFreePool(pBuffer);
	pBuffer = NULL;

	pIrp->IoStatus.Status = STATUS_SUCCESS;
	pIrp->IoStatus.Information = uWriteLength;
	IoCompleteRequest(pIrp, IO_NO_INCREMENT);
	return STATUS_SUCCESS;

}

NTSTATUS DispatchClose(PDEVICE_OBJECT pObject, PIRP pIrp)
{
	pIrp->IoStatus.Status = STATUS_SUCCESS;//这个是给ring3的返回值
	pIrp->IoStatus.Information = 0;//记录Irp特殊数据,比如读写就是有效字节数

	IoCompleteRequest(pIrp, IO_NO_INCREMENT);

	return STATUS_SUCCESS;//这个是给内核驱动管理框架的
}

NTSTATUS DispatchClean(PDEVICE_OBJECT pObject, PIRP pIrp)
{
	pIrp->IoStatus.Status = STATUS_SUCCESS;//这个是给ring3的返回值
	pIrp->IoStatus.Information = 0;//记录Irp特殊数据,比如读写就是有效字节数

	IoCompleteRequest(pIrp, IO_NO_INCREMENT);

	return STATUS_SUCCESS;//这个是给内核驱动管理框架的
}

NTSTATUS DispatchIoControl(PDEVICE_OBJECT pObject, PIRP pIrp)
{
	ULONG uIoCtrlCode = 0;
	PVOID pInputBuffer = NULL;
	PVOID pOutputBuffer = NULL;

	ULONG uInputLengrh = 0;
	ULONG uOutputLength = 0;

	PIO_STACK_LOCATION pStack = NULL;
	pInputBuffer = pOutputBuffer = pIrp->AssociatedIrp.SystemBuffer;

	pStack = IoGetCurrentIrpStackLocation(pIrp);

	uInputLengrh = pStack->Parameters.DeviceIoControl.InputBufferLength;
	uOutputLength = pStack->Parameters.DeviceIoControl.OutputBufferLength;

	uIoCtrlCode = pStack->Parameters.DeviceIoControl.IoControlCode;

	//根据不同code处理不同代码

	switch (uIoCtrlCode)
	{
	case CTL_HELLO:
		DbgPrint("Hello IoCtrlControl\n");
		break;
	case CTL_PRINT:
		DbgPrint("%ws\n",pInputBuffer);
		break;
	case CTL_BYE:
		DbgPrint("Good Bye\n");
		break;
	default:
		DbgPrint("UnKown IoCtrlControl\n");
		break;
	}

	pIrp->IoStatus.Status = STATUS_SUCCESS;
	pIrp->IoStatus.Information = 0;
	IoCompleteRequest(pIrp, IO_NO_INCREMENT);

	return STATUS_SUCCESS;

}

VOID DriverUnload(PDRIVER_OBJECT pDriverObject)
{
	UNICODE_STRING uLinkName = { 0 };
	RtlInitUnicodeString(&uLinkName, LINK_NAME);
	//删除符号链接
	IoDeleteSymbolicLink(&uLinkName);
	//释放设备对象
	IoDeleteDevice(pDriverObject->DeviceObject);

	DbgPrint("Driver UnLoaded\n");
}

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject,
	PUNICODE_STRING pRegPath)
{
	UNICODE_STRING uDeviceName = { 0 };
	UNICODE_STRING uLinkName = { 0 };
	NTSTATUS ntStatus = 0;
	PDEVICE_OBJECT pDeviceObject = NULL;
	ULONG i = 0;

	DbgPrint("Driver load begin\n");

	//创建设备对象,将之前定义的设备名传入,接收IRP
	RtlInitUnicodeString(&uDeviceName, DEVICE_NAME);
	RtlInitUnicodeString(&uLinkName, LINK_NAME);

	ntStatus = IoCreateDevice(pDriverObject,
		0, &uDeviceName, FILE_DEVICE_UNKNOWN, 0, FALSE, &pDeviceObject);
	if (!NT_SUCCESS(ntStatus))
	{
		DbgPrint("IoCreateDevice Failed:%x\n", ntStatus);
		return ntStatus;
	}

	pDeviceObject->Flags |= DO_BUFFERED_IO;//ring3和ring0通讯协议

	//创建符号链接,为了让Ring3看到识别驱动
	ntStatus = IoCreateSymbolicLink(&uLinkName, &uDeviceName);
	if (!NT_SUCCESS(ntStatus))
	{
		IoDeleteDevice(pDeviceObject);//失败先删掉
		DbgPrint("IoCreateDevice Failed:%x\n", ntStatus);
		return ntStatus;
	}
	//初始和注册化分发函数
	for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
	{
		pDriverObject->MajorFunction[i] = DispatchCommon;

	}
	//初始化特殊分发
	pDriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchCreate;
	pDriverObject->MajorFunction[IRP_MJ_READ] = DispatchRead;
	pDriverObject->MajorFunction[IRP_MJ_WRITE] = DispatchWrite;
	pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchIoControl;
	pDriverObject->MajorFunction[IRP_MJ_CLEANUP] = DispatchClean;
	pDriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchClose;

	pDriverObject->DriverUnload = DriverUnload;

	DbgPrint("Driver load OK!\n");

	//

	return STATUS_SUCCESS;
}

下面是测试

// R3LoadDrv.cpp : This file contains the 'main' function. Program execution begins and ends there.
//
//这个是R3的安装驱动程序
#include "pch.h"
#include <Windows.h>
#include <winsvc.h>
#include <conio.h>
#include <stdio.h>
#include <winioctl.h>

#define DRIVER_NAME "NTModelDrv"
#define DRIVER_PATH "C:\\DriverTest\\NTModelDrv.sys"

#define IOCTRL_BASE 0x8000
#define MYIOCTRL_CODE(i)\
	CTL_CODE(FILE_DEVICE_UNKNOWN,IOCTRL_BASE+i,METHOD_BUFFERED,FILE_ANY_ACCESS)
#define CTL_HELLO MYIOCTRL_CODE(0)
#define CTL_PRINT MYIOCTRL_CODE(1)
#define CTL_BYE MYIOCTRL_CODE(2)

//装载NT驱动框架
BOOL LoadDriver(char* lpszDriverName, char* lpszDriverPath)
{
	
	/************************ 加载NT驱动的代码*******************************
   ① 调用OpenSCManager,打开SCM管理器.如果返回NULL,则返回失败,否则继续
   ② 调用CreateService,创建服务,创建成功则转步骤 ⑥
	  ③ 用GetLastError的得到错误返回值
   ④ 返回值为ERROR_IO_PENDING,说明服务已经创建过,用OpenService打开此服务.
   ⑤ 返回值为其他值, 创建服务失败,返回失败.
   ⑥ 调用StartService开启服务
   ⑦ 成功返回
************************************************************************/

    //char szDriverImagePath[256] = "C:\\DriverTest\\ntmodelDrv.sys";
	char szDriverImagePath[256] = { 0 };
	//得到完整驱动路径
	//GetFullPathName(lpszDriverName, 256, szDriverImagePath, NULL);
	BOOL bRet = FALSE;
	SC_HANDLE hServiceMgr = NULL; //SCM管理器的句柄
	SC_HANDLE hServiceDDK = NULL;//NT驱动程序的服务句柄

	//打开服务控制管理器
	hServiceMgr = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);

	if (NULL == hServiceMgr)
	{
		//OpenSCManger失败
		printf("OpenSCManger() Faild %d !\n", GetLastError());
		bRet = FALSE;
		goto BeforeLeave;
	}
	else
	{
		printf("OpenSCManger() OK!\n");
	}
	//创建驱动所对应的服务
	hServiceDDK=CreateService(
		hServiceMgr,
		lpszDriverName,//驱动程序在注册表中的名字
		lpszDriverName, // 注册表驱动程序的 DisplayName 值  
		SERVICE_ALL_ACCESS, // 加载驱动程序的访问权限  
		SERVICE_KERNEL_DRIVER,// 表示加载的服务是驱动程序  
		SERVICE_DEMAND_START, // 注册表驱动程序的 Start 值  
		SERVICE_ERROR_IGNORE, // 注册表驱动程序的 ErrorControl 值  
		szDriverImagePath, // 注册表驱动程序的 ImagePath 值  
		NULL,  //GroupOrder HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\GroupOrderList
		NULL,
		NULL,
		NULL,
		NULL);
	DWORD dwRtn;
	if (NULL == hServiceDDK)
	{
		dwRtn = GetLastError();
		if (dwRtn != ERROR_IO_PENDING && dwRtn != ERROR_SERVICE_EXISTS)
		{
			//由于其他原因创建服务失败
			printf("CreateService() Faild %d !\n", dwRtn);
			bRet = FALSE;
			goto BeforeLeave;
		}
		else
		{
			//服务创建失败,是由于服务已经创立过
			printf("CrateService() Faild Service is ERROR_IO_PENDING or ERROR_SERVICE_EXISTS! \n");
		}

		// 驱动程序已经加载,只需要打开  
		hServiceDDK = OpenService(hServiceMgr, lpszDriverName, SERVICE_ALL_ACCESS);
		if (NULL == hServiceDDK)
		{
			//如果打开服务也失败,则意味错误
			dwRtn = GetLastError();
			printf("OpenService() Faild %d ! \n", dwRtn);
			bRet = FALSE;
			goto BeforeLeave;
		}
		else
		{
			printf("OpenService() ok ! \n");
		}
	}
	else
	{
		printf("CrateService() ok ! \n");
	}
	//开启此项服务
	bRet = StartService(hServiceDDK, NULL, NULL);
	if (!bRet)
	{
		DWORD dwRtn = GetLastError();
		if (dwRtn != ERROR_IO_PENDING && dwRtn != ERROR_SERVICE_ALREADY_RUNNING)
		{
			printf("StartService() Faild %d ! \n", dwRtn);
			bRet = FALSE;
			goto BeforeLeave;
		}
		else
		{
			if (dwRtn == ERROR_IO_PENDING)
			{
				//设备被挂住
				printf("StartService() Faild ERROR_IO_PENDING ! \n");
				bRet = FALSE;
				goto BeforeLeave;
			}
			else
			{
				//服务已经开启
				printf("StartService() Faild ERROR_SERVICE_ALREADY_RUNNING ! \n");
				bRet = TRUE;
				goto BeforeLeave;
			}
		}
	}
	bRet = TRUE;
	
	//离开前关闭句柄
BeforeLeave:
	if (hServiceDDK)
	{
		CloseServiceHandle(hServiceDDK);
	}
	if (hServiceMgr)
	{
		CloseServiceHandle(hServiceMgr);
	}
	return bRet;
}


//卸载驱动程序  

BOOL UnloadDriver(char * szSvrName)
{
	/************************* 卸载NT驱动的代码******************************
   ① 调用OpenSCManager,打开SCM管理器,如果返回NULL,则返回失败,否则继续.
   ② 调用OpenService.如果返回NULL,则返回失败,否则继续
   ③ 调用DeleteService卸载此项服务.
   ④ 成功返回.
************************************************************************/
	BOOL bRet = FALSE;
	SC_HANDLE hServiceMgr = NULL;//SCM管理器的句柄
	SC_HANDLE hServiceDDK = NULL;//NT驱动程序的服务句柄

	SERVICE_STATUS SvrSta;
	//打开SCM管理器

	hServiceMgr = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
	if (hServiceMgr == NULL)
	{
		//带开SCM管理器失败
		printf("OpenSCManager() Faild %d ! \n", GetLastError());
		bRet = FALSE;
		goto BeforeLeave;
	}
	else
	{
		//带开SCM管理器失败成功
		printf("OpenSCManager() ok ! \n");
	}

	//打开驱动所对应的服务
	hServiceDDK = OpenService(hServiceMgr, szSvrName, SERVICE_ALL_ACCESS);

	if (hServiceDDK == NULL)
	{
		//打开驱动所对应的服务失败
		printf("OpenService() Faild %d ! \n", GetLastError());
		bRet = FALSE;
		goto BeforeLeave;
	}
	else
	{
		printf("OpenService() ok ! \n");
	}
	//停止驱动程序,如果停止失败,只有重新启动才能,再动态加载。  
	if (!ControlService(hServiceDDK, SERVICE_CONTROL_STOP, &SvrSta))
	{
		printf("ControlService() Faild %d !\n", GetLastError());
	}
	else
	{
		//打开驱动所对应的失败
		printf("ControlService() ok !\n");
	}
	//动态卸载驱动程序。  
	if (!DeleteService(hServiceDDK))
	{
		//卸载失败
		printf("DeleteSrevice() Faild %d !\n", GetLastError());
	}
	else
	{
		//卸载成功
		printf("DelServer:eleteSrevice() ok !\n");
	}
	bRet = TRUE;
BeforeLeave:
	//离开前关闭打开的句柄
	if (hServiceDDK)
	{
		CloseServiceHandle(hServiceDDK);
	}
	if (hServiceMgr)
	{
		CloseServiceHandle(hServiceMgr);
	}
	return bRet;


}


void TestDriver()
{
	//测试驱动程序
	HANDLE hDevice = CreateFile(
		"\\\\.\\NTModelDrv",
		GENERIC_WRITE|GENERIC_READ,
		0,
		NULL,
		OPEN_EXISTING,
		0,
		NULL);
	if (hDevice != INVALID_HANDLE_VALUE)
	{
		printf("Create Device ok ! \n");
	}
	else
	{
		printf("Create Device faild %d ! \n", GetLastError());
		return;
	}

	CHAR bufRead[1024] = { 0 };
	CHAR bufWrite[1024] = "Hello, world";

	DWORD dwRead = 0;
	DWORD dwWrite = 0;

	ReadFile(hDevice, bufRead, 1024, &dwRead, NULL);
	CHAR bufInput[1024] = "Hello, world";
	CHAR bufOutput[1024] = { 0 };
	DWORD dwRet = 0;

	DeviceIoControl(hDevice, CTL_HELLO, bufInput, sizeof(bufInput),
		bufOutput, sizeof(bufOutput), &dwRet, NULL
	);

	CloseHandle(hDevice);
}

int main(int argc, char* argv[])
{
	//加载驱动
	BOOL bRet = LoadDriver((char*)DRIVER_NAME, (char*)DRIVER_PATH);
	if (!bRet)
	{
		printf("LoadNTDriver error\n");
		return 0;
	}
	//加载成功

	printf("press any to create device!\n");
	getchar();

	TestDriver();

	//这时候你可以通过注册表,或其他查看符号连接的软件验证。  
	printf("press any to unload the driver!\n");
	getchar();

	//卸载驱动
	UnloadDriver((char*)DRIVER_NAME);
	if (!bRet)
	{
		printf("UnloadNTDriver error\n");
		return 0;
	}

	return 0;
}

参考

https://www.cnblogs.com/ciangcic/p/3528139.html

猜你喜欢

转载自blog.csdn.net/youyou519/article/details/83825334
今日推荐