UMDF
看了一周的UMDF,今天就将这些天的心得记下来。
一开始,老大推荐看《竹林蹊径:深入浅出Windows驱动开发完美补全版.张佩马勇董鉴源.扫描版》。这本书看了前三章,这本书讲的太细,作者又奔着深入的想法写的,所以看完后感觉和没看一样,白白浪费一天时间。不过了解了许多基本概念。
后来找到了《Windows 7 Device Driver(Windows 7设备驱动程序开发)》这本书,CSDN上有个带标签的不错,因为我只用到UMDF,所以只看了前两部分,这下我对整个体系结构和程序流程了解多了。这时候MSDN也起到很大的帮助。
这本书中有一个对UMDF Driver Skeleton Sample (UMDF Version 1)程序的详解,程序在
http://code.msdn.microsoft.com/windowshardware/SKELETON-3a06c09e
可以下载。
上面这些看完后,就打算写个最简单的IOCTL了。但是书上没有例子,只能在网上找了。找到一个
http://www.codeproject.com/Articles/9504/Driver-Development-Part-1-Introduction-to-Drivers
http://www.codeproject.com/Articles/9575/Driver-Development-Part-2-Introduction-to-Implemen
作者写的相当不错,而且有源码可以参考。PS:这是一个系列的,我觉得蛮好的。
下面这个是对上面的翻译:
http://blogs.ejb.cc/archives/6253/windows-driver-development-a-what-is-the-drive
但是我使用的是Windows的UMDF框架,所以还要改变一些。不过也很简单。首先新建一个UMDF框架。然后在Internal.h中添加
#define IOCTL_EXAMPLE_SAMPLE_DIRECT_IN_IO \
CTL_CODE(FILE_DEVICE_UNKNOWN, \
0x800, \
METHOD_IN_DIRECT, \
FILE_READ_DATA | FILE_WRITE_DATA)
然后在IoQueue.cpp中的OnDeviceIoControl函数中添加
//
// Process the IOCTLs
// switch (ControlCode)
{
case IOCTL_EXAMPLE_SAMPLE_DIRECT_IN_IO: OutputDebugString("Hello"); break; }
在这里一个最简单的IOCTL驱动就写成了,然后就进行Build。
在这里可能会碰到 link error 2019 错误,无法解析的外部命令。这是错误输出框里是哪个函数,很有可能没有VS找不到这个函数的函数库。解决这种问题基本就是三步走:
下面以无法解析setupAPI的某些函数为例:
- VS2中点击项目 -->右键-->属性-->配置属性-->链接器-->输入-->附加依赖项:将相关的lib文件加入到附加依赖项中:
- 找到setupApi.h所在的目录,我的是在C:\Program Files\Windows Kits\8.0\Include\um。这时候就可以在配置属性-->VC++目录-->包含目录中加入上面的路径。
- 找到setupApi.lib所在的目录,注意你所需要时32位的还是64位的版本,我的是32位,所以选择C:\Program Files\Windows Kits\8.0\Lib\win8\um\x86。 这时候就可以在配置属性-->VC++目录-->库目录中加入上面的路径。
第三部新建一个测试工程,我选择的是Win32 console,名字为test。然后在test.cpp中添加
// testapp.cpp : Defines the entry point for the console application.
// #include "stdafx.h"
#include <windows.h>
#include <stdlib.h>
#include <Setupapi.h>
#include <strsafe.h>
#include "devioctl.h"
#include <initguid.h> #define CTL_CODE( DeviceType, Function, Method, Access ) ( \
((DeviceType) << ) | ((Access) << ) | ((Function) << ) | (Method) \
) #define IOCTL_EXAMPLE_SAMPLE_DIRECT_IN_IO \
CTL_CODE(FILE_DEVICE_UNKNOWN, \
0x800, \
METHOD_IN_DIRECT, \
FILE_READ_DATA | FILE_WRITE_DATA) //
//在这里的GUID 应该和Internal中的保持一致
//
DEFINE_GUID(GUID_DEVINTERFACE_UMDFTestDriver,
0x57bc27d7,0x935c,0x4b57,0x97,0xa3,0x83,0xed,0x17,0x3b,0xbc,0x29); #define countof(x) (sizeof(x) / sizeof(x[0])) _Success_ (return != FALSE) BOOL
GetDevicePath(
IN LPGUID InterfaceGuid,
_Out_writes_(BufLen) PWSTR DevicePath,
_In_ size_t BufLen
)
{
HDEVINFO HardwareDeviceInfo;
SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;
PSP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetailData = NULL;
ULONG Length, RequiredLength = ;
BOOL bResult;
HRESULT hr; HardwareDeviceInfo = SetupDiGetClassDevs(
InterfaceGuid,
NULL,
NULL,
(DIGCF_PRESENT | DIGCF_DEVICEINTERFACE)); if (HardwareDeviceInfo == INVALID_HANDLE_VALUE) {
wprintf(L"SetupDiGetClassDevs failed!\n");
return FALSE;
} DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); bResult = SetupDiEnumDeviceInterfaces(HardwareDeviceInfo,
,
InterfaceGuid,
,
&DeviceInterfaceData); if (bResult == FALSE) { LPVOID lpMsgBuf; if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPWSTR) &lpMsgBuf,
,
NULL
)) { printf("SetupDiEnumDeviceInterfaces failed: %s", (LPSTR)lpMsgBuf);
LocalFree(lpMsgBuf);
} SetupDiDestroyDeviceInfoList(HardwareDeviceInfo);
return FALSE;
} SetupDiGetDeviceInterfaceDetail(
HardwareDeviceInfo,
&DeviceInterfaceData,
NULL,
,
&RequiredLength,
NULL
); DeviceInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)
LocalAlloc(LMEM_FIXED, RequiredLength); if (DeviceInterfaceDetailData == NULL) {
SetupDiDestroyDeviceInfoList(HardwareDeviceInfo);
wprintf(L"Failed to allocate memory.\n");
return FALSE;
} DeviceInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); Length = RequiredLength; bResult = SetupDiGetDeviceInterfaceDetail(
HardwareDeviceInfo,
&DeviceInterfaceData,
DeviceInterfaceDetailData,
Length,
&RequiredLength,
NULL); if (bResult == FALSE) { LPVOID lpMsgBuf; if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPWSTR) &lpMsgBuf,
,
NULL)) { printf("Error in SetupDiGetDeviceInterfaceDetail: %s\n", (LPSTR)lpMsgBuf);
LocalFree(lpMsgBuf);
} SetupDiDestroyDeviceInfoList(HardwareDeviceInfo);
LocalFree(DeviceInterfaceDetailData);
return FALSE;
} hr = StringCchCopy(DevicePath,
BufLen,
DeviceInterfaceDetailData->DevicePath);
if (FAILED(hr)) {
SetupDiDestroyDeviceInfoList(HardwareDeviceInfo);
LocalFree(DeviceInterfaceDetailData);
return FALSE;
} SetupDiDestroyDeviceInfoList(HardwareDeviceInfo);
LocalFree(DeviceInterfaceDetailData); return TRUE; } HANDLE
OpenDevice(
_In_ BOOL Synchronous
) /*++
Routine Description: Called by main() to open an instance of our device after obtaining its name Arguments: Synchronous - TRUE, if Device is to be opened for synchronous access.
FALSE, otherwise. Return Value: Device handle on success else INVALID_HANDLE_VALUE --*/ {
HANDLE hDev;
WCHAR completeDeviceName[MAX_DEVPATH_LENGTH]; if ( !GetDevicePath(
(LPGUID) &GUID_DEVINTERFACE_UMDFTestDriver,
completeDeviceName,
countof(completeDeviceName)) )
{
return INVALID_HANDLE_VALUE;
} wprintf(L"DeviceName = (%s)\n", completeDeviceName); hDev = CreateFile(completeDeviceName,
GENERIC_WRITE | GENERIC_READ,
FILE_SHARE_WRITE | FILE_SHARE_READ,
NULL, // default security
OPEN_EXISTING,
((Synchronous ? FILE_ATTRIBUTE_NORMAL : FILE_FLAG_OVERLAPPED) | SECURITY_IMPERSONATION),
NULL); if (hDev == INVALID_HANDLE_VALUE) {
wprintf(L"Failed to open the device, error - %d", GetLastError());
} else {
wprintf(L"Opened the device successfully.\n");
} return hDev;
} int _tmain(int argc, _TCHAR* argv[])
{ HANDLE deviceHandle;
DWORD code;
ULONG index;
deviceHandle = OpenDevice(FALSE); if (deviceHandle == INVALID_HANDLE_VALUE) { wprintf(L"Unable to find any OSR FX2 devices!\n");
return FALSE;
} if (!DeviceIoControl(deviceHandle,
IOCTL_EXAMPLE_SAMPLE_DIRECT_IN_IO,
NULL, // Ptr to InBuffer
, // Length of InBuffer
NULL, // Ptr to OutBuffer
, // Length of OutBuffer
&index, // BytesReturned
)) { // Ptr to Overlapped structure
code = GetLastError();
wprintf(L"DeviceIoControl failed with error 0x%x\n", code);
}
return ;
}
具体可以参考:
http://tech.ddvip.com/2008-09/122084165361557.html
在这里代码都已经敲完了。需要做的就是将驱动安装上。可以参考这篇:
http://joeyliu.blog.51cto.com/3647812/943368
OK,接下来就是测试环节,我们使用的是DebugView。可以参考这篇:
http://blog.sina.com.cn/s/blog_9bd8f0f80100z55t.html
最后出现:
就大功告成了!!
UMDF的更多相关文章
- 用Visual Studio 2015 编写第一个UMDF驱动遇到的问题!!
前提:Visual Studio 2015已经成功安装了驱动环境,WDK都已经完全正常安装了,在Visual Studio 2015的菜单可以看到"Driver"菜单项了.这说明已 ...
- 用Visual Studio 2015成功编译、发布UMDF驱动到目标机!!
开发工具:Visual Studio 2015企业版 主 机:windows10 X64企业版,主机是安装了Visual Studio 2015的操作系统,主要进行驱动开发和调试. 目 标 ...
- WDF驱动中KMDF与UMDF区别
抄的 早期的Windows 95/98的设备驱动是VxD(Virtual Device Driver),其中x表示某一类设备.从Windows 2000开始,开发驱动程序必以WDM(Windows D ...
- Windows 驱动程序工具包中的头文件
MSDN原文:https://msdn.microsoft.com/zh-cn/library/windows/hardware/ff554695(v=vs.85).aspx Windows 驱动程序 ...
- Windows Internals学习笔记(六)Windows关键系统组件
参考资料: 1. <Windows Internals> 2. Dependency Walker 3. Ntoskrnl.exe 4. Livekd的使用 5. WinDbg的使用(一) ...
- 基于WDF的PCI/PCIe接口卡Windows驱动程序(1)-WDF概述及开发环境搭建
原文出处:http://www.cnblogs.com/jacklu/p/4619110.html 本科毕业设计是这方面的工作,所以想开几篇博客来介绍使用WDF开发PCI/PCIe接口卡的驱动程序方法 ...
- Mac OS X 安装ruby环境
1.查看版本 $ ruby -v ruby 2.0.0p481 (2014-05-08 revision 45883) [universal.x86_64-darwin14] 2.查看源 $ gem ...
- IOS开发UI基础之UIScrollView
什么是UIScrollView ● 移动设备的屏幕⼤大⼩小是极其有限的,因此直接展⽰示在⽤用户眼前的内容也相当有限 ● 当展⽰示的内容较多,超出⼀一个屏幕时,⽤用户可通过滚动⼿手势来查看屏幕以外的内容 ...
- window 安装 sass compass 记录
1.安装Ruby 安装sass 和compass 需要 Ruby 的环境,还区分xp 和win7-8 下版本区别 ruby 官网中文 ruby 官网英文 注意: xp: 下载 [xp不能下载包含64位 ...
随机推荐
- python学习笔记9(对文件的操作)
一.文件对象 我理解的文件对象就是一个接口,通过这个接口对文件进行相关操作. 二.相关函数 [1].内建函数:open() 提供了初始化输入/输出(I/O)操作的通用接口,成功打开一个文件后会返回一个 ...
- 演示demo开发问题及解决方案集锦
模型处理问题: 1. 3Dmax模型导入Unity单位设置: 自定义->单位设置->系统单位设置与显示单位比例都调成厘米 2. 3Dmax中材质贴图: 点击材质编辑器[在模式下可以选择精简 ...
- bnuoj 31796 键盘上的蚂蚁(搜索模拟)
http://www.bnuoj.com/bnuoj/contest_show.php?cid=2876#problem/31796 [题意]: 如题,注意大小写情况 [code]: #include ...
- Angular指令封装jQuery日期时间插件datetimepicker实现双向绑定
一放假就高产似母猪了. 00.混乱的前端界 Angular1.x确实是个学习成本很高的框架,刚开始实习那会儿,前端啥也不懂,工头说用Angular,我们这群小弟也只能硬着头皮学.在这之前,前端的东西大 ...
- java模拟OSUnMapTbl[]
问题描述: 任务就绪表,记录当前就绪的任务,就绪表中把64个优先级的任务分成8组,优先级的1-3bit表示OSRdyTbl[]中组别OSRedyGrp,优先级的4-6bit表示每组中就绪任务的位置,当 ...
- 原创新闻 11 个最佳 jQuery 滚动条插件
通过jQuery滚动条插件,你可以换掉千篇一律的默认浏览器滚动条,让你的网站或web项目更具特色,更有吸引力.本文收集了11款非常漂亮.实用的jQuery滚动条插件,你可以轻松将它们应用在自己的网站中 ...
- PAT-乙级-1026. 程序运行时间(15)
1026. 程序运行时间(15) 时间限制 200 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 CHEN, Yue 要获得一个C语言程序的运行时间, ...
- 服务器部署_linux下部署jprofiler简单备忘
1.windows安装jprofiler 2.linux下安装jprofiler服务端,记好安装路径.假设是安装在/ex/bin/下 3. 配置tomcat的启动sh文件,在后面加入以下参数: -a ...
- 情人节红攻瑰--Delphi版本
在oschina上看到了用c写的红玫瑰, 以前只见过用js写的, 就随手用delphi翻译了c的代码, 效果还不错哈.... 原c作者jokeym贴子 http://www.oschina.net/c ...
- 102. Binary Tree Level Order Traversal
题目: Given a binary tree, return the level order traversal of its nodes' values. (ie, from left to ri ...