编写NT驱动使得APP能够读取PCI设备配置信息
来源:互联网 发布:国际云计算大会 编辑:程序博客网 时间:2024/05/21 20:38
驱动程序是一个软件组件,可以让操作系统和设备之间实现通信。一般操作系统可以分为两个主要组成部分,即User Mode和Kernel Mode。用户的APP运行在系统的User Mode下,而驱动程序则运行在系统的Kernel Mode下。由于Windows在User Mode下做了许多限制,使得在用户模式下的APP有很多资源不能访问到,这时候就可以通过驱动来实现对Kernel Mode下的资源进行访问,如图5.1所示。
图 5.1
NT驱动程序一般是由3部分组成,即DriverEntry、DispatchRoutine和DriveUnload。其中DriverEntry主要进行驱动程序的初始化,即:创建设备和DispatchRoutine的注册工作。当Driver被加载时,DriverEntry会被系统进程调用;DriverUnLoad在驱动被卸载时被调用,做回收资源操作,如删除创建的设备与设备符号连接、删除程序中定义的句柄等;DispatchRoutine是由一系列回调函数组成,系统在对设备进行操作或者响应设备中断时会调用这些回调函数。与此对应的,需要在User Mode中的APP编写驱动的加载函数LoadDriver,驱动的卸载函数UnLoadDriver以及APP给Driver的派遣函数IRP。APP指令与NT Driver指令的对应关系如图5.2所示。
图 5.2
其中APP与NT Driver之间的通信流程如下图5.3所示。
图 5.3
DispatchRoutine得到IRP函数后,根据MajorFunction找到对应的派遣函数,随后再根据MiniFunction完成相应的任务。
//////////////////////////////////////////////////////////////////////////////////////////
NT Driver代码如下:
#include "ntddk.h"typedef unsigned long DWORD;#define IN#define DEBUGMSG//IOCTL宏#define DEVICE_PCI_INDEX 0x860#define READ_PCI_INFO CTL_CODE(FILE_DEVICE_UNKNOWN,DEVICE_PCI_INDEX,METHOD_BUFFERED,FILE_ANY_ACCESS)#define NT_DEVICE_NAME L"\\Device\\wdkApp"#define DOS_DEVICE_NAME L"\\DosDevices\\wdkApp" //符号连接 ,应该与App中的CreateFile里的“\\\\.\\wakApp对应起来”typedef struct _DEVICE_EXTENSION{ PDEVICE_OBJECT pDevice; UNICODE_STRING DeviceName; UNICODE_STRING SymLinkName;}DEVICE_EXTENSION,*PDEVICE_EXTENSION;VOID DriverUnload (IN PDRIVER_OBJECT DriverObject);NTSTATUS DispatchRoutine (IN PDEVICE_OBJECT DeviceObject,IN PIRP pIrp);extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) { NTSTATUS ntStatus = STATUS_SUCCESS; PDEVICE_OBJECT lpDeviceObject = NULL; UNICODE_STRING DeviceNameString = {0}; UNICODE_STRING DeviceLinkString = {0}; RtlInitUnicodeString(&DeviceNameString,NT_DEVICE_NAME); //创建设备 ntStatus = IoCreateDevice(DriverObject,0,&DeviceNameString,FILE_DEVICE_UNKNOWN,0,false,&lpDeviceObject); if (!NT_SUCCESS(ntStatus)) { return ntStatus; } RtlInitUnicodeString(&DeviceLinkString,DOS_DEVICE_NAME); //创建符号链接 ntStatus=IoCreateSymbolicLink(&DeviceLinkString,&DeviceNameString); if (!NT_SUCCESS(ntStatus)) { if (lpDeviceObject) { IoDeleteDevice(lpDeviceObject); } return ntStatus; } DriverObject->DriverUnload = DriverUnload; DriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchRoutine; DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchRoutine; return STATUS_SUCCESS; }NTSTATUS DispatchRoutine (IN PDEVICE_OBJECT DeviceObject,IN PIRP pIrp) { NTSTATUS ntStatus=STATUS_SUCCESS; PIO_STACK_LOCATION IrpStack=NULL; //IRP堆栈 ULONG IoControlCodes=0; //I/O控制代码 //设置IRP状态 pIrp->IoStatus.Status=STATUS_SUCCESS; pIrp->IoStatus.Information=0; #ifdef DEBUGMSG DbgPrint("Starting HelloWorldDispatch()\n"); #endif IrpStack=IoGetCurrentIrpStackLocation(pIrp); //得到当前调用者的IRP switch (IrpStack->MajorFunction) { case IRP_MJ_CREATE: #ifdef DEBUGMSG DbgPrint("IRP_MJ_CREATE\n"); #endif break; case IRP_MJ_DEVICE_CONTROL: #ifdef DEBUGMSG DbgPrint("IRP_MJ_DEVICE_CONTROL\n"); #endif //取得I/O控制代码 IoControlCodes=IrpStack->Parameters.DeviceIoControl.IoControlCode; switch (IoControlCodes) { case READ_PCI_INFO: {#ifdef DEBUGMSG DbgPrint("READ_PCI_INFO\n"); #endif//获得PCI设备信息ULONG *INBuffer = (PULONG)pIrp->AssociatedIrp.SystemBuffer;WRITE_PORT_ULONG((PULONG)0xCF8,INBuffer[0]);ULONG *OutBuffer = (PULONG)pIrp->AssociatedIrp.SystemBuffer;OutBuffer[0] = READ_PORT_ULONG((PULONG)0xCFC);#ifdef DEBUGMSG DbgPrint("%lx\n",OutBuffer[0]); #endifbreak; } default: pIrp->IoStatus.Status=STATUS_INVALID_PARAMETER; break; } break; default: break; } ntStatus=pIrp->IoStatus.Status; pIrp->IoStatus.Information = 4; IoCompleteRequest(pIrp,IO_NO_INCREMENT); return ntStatus; } VOID DriverUnload (IN PDRIVER_OBJECT DriverObject) { UNICODE_STRING DeviceLinkString={0}; PDEVICE_OBJECT DeviceObjectTemp1=NULL; PDEVICE_OBJECT DeviceObjectTemp2=NULL; #ifdef DEBUGMSG DbgPrint("Starting HelloWorldUnLoad()\n"); #endif RtlInitUnicodeString(&DeviceLinkString,DOS_DEVICE_NAME); if (DeviceLinkString.Buffer) IoDeleteSymbolicLink(&DeviceLinkString); if (DriverObject) { DeviceObjectTemp1=DriverObject->DeviceObject; while (DeviceObjectTemp1) { DeviceObjectTemp2=DeviceObjectTemp1; DeviceObjectTemp1=DeviceObjectTemp1->NextDevice; IoDeleteDevice(DeviceObjectTemp2); } } }
////////////////////////////////////////////////////////////////////////////////////
对应的APP代码如下:
// App.cpp#include "stdafx.h"#include <windows.h>#include <stdio.h>#define DEVICE_PCI_INDEX 0x860//IOCTL宏#define READ_PCI_INFO CTL_CODE(FILE_DEVICE_UNKNOWN,DEVICE_PCI_INDEX,METHOD_BUFFERED,FILE_ANY_ACCESS)//用来判断CreateFile是否成功int flag = 0;void TestDriver();//加载驱动//lpszDriverName:驱动程序在注册表中的名字//分为3部,1.新建驱动服务并判断是否有错误发生;2.打开驱动服务;3.开始驱动服务bool LoadNTDriver(wchar_t* lpszDriverName, wchar_t* lpszDriverPath) //驱动名&&驱动路径{wchar_t szDriverPath[MAX_PATH];GetFullPathName(lpszDriverPath, MAX_PATH, szDriverPath, NULL);printf("%s\n", szDriverPath); //输出C,表示C盘SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);if (hSCM == NULL){printf("OpenSCManager error:%d\n", GetLastError());return false;}//创建驱动服务SC_HANDLE hDriver = CreateService(hSCM, lpszDriverName, lpszDriverName, SERVICE_ALL_ACCESS,SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_IGNORE,szDriverPath, NULL, NULL, NULL, NULL, NULL);DWORD dwError;if (hDriver == NULL){dwError = GetLastError();if (dwError != ERROR_IO_PENDING && dwError != ERROR_SERVICE_EXISTS){printf("CreateService error:%d\n", dwError);CloseServiceHandle(hSCM);return false;}else{printf("Service already Created.\n");}hDriver = OpenService(hSCM, lpszDriverName, SERVICE_ALL_ACCESS);if (hDriver == NULL){printf("OpenService error:%d\n", GetLastError());CloseServiceHandle(hSCM);return false; }else{printf("OpenService OK!\n");}}else{printf("CreateService OK!\n");}dwError = StartService(hDriver,NULL,NULL);if (!dwError){dwError = GetLastError();if (dwError != ERROR_IO_PENDING && dwError != ERROR_SERVICE_ALREADY_RUNNING){printf("StartService error:%d\n", dwError);CloseServiceHandle(hSCM);CloseServiceHandle(hDriver);return false;}else{printf("Service already run\n");CloseServiceHandle(hSCM);CloseServiceHandle(hDriver);return true;} }return true;}//卸载驱动//szSrvName:即为lpServiceName//3步:1.找到对应的驱动服务;2.停止此驱动服务;3.删除该驱动服务bool UnLoadNTDriver(wchar_t* szSrvName){SC_HANDLE hSCM = NULL;SC_HANDLE hSrv = NULL;hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);if (hSCM == NULL){printf("OpenSCManager error:%d\n", GetLastError());return false;}else{printf("OpenSCManager OK!\n");}hSrv = OpenService(hSCM, szSrvName, SERVICE_ALL_ACCESS);if (hSrv == NULL){printf("OpenService error:%d\n", GetLastError());CloseServiceHandle(hSCM);return false; }else{printf("OpenService OK!\n");}SERVICE_STATUS ss;if (!ControlService(hSrv, SERVICE_CONTROL_STOP, &ss)){printf("ControlService error:%d\n", GetLastError());CloseServiceHandle(hSCM);CloseServiceHandle(hSrv);return false;}else{printf("ControlService ok!\n");}if (!DeleteService(hSrv)){printf("DeleteService error:%d\n", GetLastError());CloseServiceHandle(hSCM);CloseServiceHandle(hSrv);return false;}else{printf("DeleteService ok!\n");}return TRUE;}int main(void){bool bRet = LoadNTDriver(L"wdkApp",L"C:\\wdkApp.sys");if (!bRet){printf("LoadNTDriver error\n");return -1;}printf("Press any key to Test Driver!\n");getchar();TestDriver();printf("Press any key to Unload Driver!\n");getchar();bRet = UnLoadNTDriver(L"wdkApp");if (!bRet){printf("UnLoadNTDriver error\n");return -1;}return 0;}void TestDriver(){DWORD PCI_Addr,PCI_Data;DWORD bus,dev,func;ULONG nOutput;HANDLE hDriver = CreateFile(L"\\\\.\\wdkApp", GENERIC_READ|GENERIC_READ,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);if (hDriver!= INVALID_HANDLE_VALUE){printf("Open Driver OK!\n");flag = 1;/* 接收数据 */for(bus = 0;bus<=0xFF;++bus){for (dev = 0; dev<=0x1F; ++dev){for (func = 0; func<=0x07; ++func){PCI_Addr = 0x80000000 + (bus<<16) + (dev<<11) + (func<<8);DeviceIoControl(hDriver,READ_PCI_INFO,&PCI_Addr,4,&PCI_Data,4,&nOutput,NULL);if((PCI_Data&0xFFFF)!=0xFFFF){printf("%04x\t%04x\t%04x\t%04x\t%04x\n",bus,dev,func,PCI_Data>>16,PCI_Data);}}}}getchar();}else{printf("Open Driver fail,error:%d\n", GetLastError());flag = 0;}CloseHandle(hDriver);}
- 编写NT驱动使得APP能够读取PCI设备配置信息
- PCI设备读取配置空间
- PCI设备读取配置空间
- PCI设备读取配置空间
- PCI设备读取配置空间
- 基于vxworks的PCI设备驱动编写
- Linux读取PCI设备的信息
- Linux PCI/PCI-E设备配置空间读取与修改
- Linux PCI/PCI-E设备配置空间读取与修改
- Linux环境下无配置信息PCI设备的驱动开发
- PCI设备驱动
- PCI设备驱动开发
- pci设备驱动
- PCI设备驱动
- PCI设备驱动开发
- pci问号设备驱动
- PCI设备驱动知识点
- PCI设备驱动开发
- JavaScript编程风格
- js本地图片预览
- hibernate中使用数据库关键字(保留字)
- 基于HTML5的超级玛丽游戏demo http://www.cnblogs.com/Cson/archive/2012/02/14/2350652.html
- URAL 1036
- 编写NT驱动使得APP能够读取PCI设备配置信息
- 传阿里整合资源,进军O2O市场
- 你真的懂【售罄率】吗?
- cookie相关
- sql中 in 、not in 、exists、not exists 用法和差别http://blog.csdn.net/lihan6415151528/article/details/4466914
- sax解析xml简单实例
- struts hibernate spring easyui 报修系统 录像
- hdu find the most comfortable road
- The principles of program design