http://qsyang.yeah.net
现代微机原理与接口技术
1
Windows98/2000驱动程序编写方法
(上)
杨全胜
http://qsyang.yeah.net
现代微机原理与接口技术
2
1,驱动程序的开发环境对于 VxD的开发,需要的开发环境是,
Visual C++ 5.0/6.0
Windosw 95DDK
如果想加快开发步骤,建议使用第三方的 VToolsD开发工具,它将 DDK的东西全部封装成 C++的类,可以直接用 Visual C++编写程序,而无须使用汇编。而且它提供的 QuickVxd能够方便快速地建立 VxD程序的框架。
http://qsyang.yeah.net
现代微机原理与接口技术
3
对于 WDM的开发,又分几种情况,
1)对于 Windows 98系统
Visual C++ 5.0
Windows 98DDK
2)对于 Windows Me/2000
Visual C++ 6.0
Windows 2000DDK
3)对于 Windows XP
Visual C++6.0/.net
Windows XPDDK
同样,为了方便起见,也可以使用第三方的开发工具 Driver Works,它也是将 DDK的内容封装成类
,而且提供一个快速方便地生成驱动框架的工具。
http://qsyang.yeah.net
现代微机原理与接口技术
4
2,驱动程序开发工具包 DriverStudio
2.1 DriverStudio 2.7所包含的工具
VToolsD
VToolsD 是一个用来开发针对 Win9X (Windows 95 和
Windows 98)操作系统下设备驱动程序 (VxD)的工具。
VToolsD 中包括生成驱动程序源代码的工具,run-time 和
interface 库,以及一些驱动程序样本,可以用来作为各种类型的设备驱动程序的基础部分。
DriverWorks
DriverWorks对于 Windows NT下和 Windows 98 与
Windows 2000共同支持的 Win32驱动模型 (WDM)设备驱动程序的开发提供完全的支持。 DriverWorks中包含一个非常完善的源代码生成工具 (DriverWizard) 以及相应的类库和驱动程序样本,它提供了在 C++下进行设备驱动程序开发的支持。
http://qsyang.yeah.net
现代微机原理与接口技术
5
DriverNetworks
DriverNetworks 是针对 Windows网络驱动开发人员的一个模块。在它的核心部分,DriverNetworks 是一个针对 NDIS drivers 和 TDI clients (DriverSockets)的
C++ 的类库。 DriverNetworks 中也有 Quick Miniport
Wizard 用来直接开始一个 NDIS Miniport 或
Intermediate Driver 工程。它可以让你快速的生成所有采用 DriverNetworks C++ 类库编写的 NDIS驱动程序的编译,安装和调试所需要的文件 。
SoftICE
SoftICE 是一个功能极其强大的内核模式调试器,它支持在配置一台单独的计算机或两台计算机下进行设备驱动程序的调试。
http://qsyang.yeah.net
现代微机原理与接口技术
6
DriverMonitor
DriverMonitor不仅可以显示 WDM和 VxD在操作系统核心层次输出的调试语句,还可以装载和卸载 VxD
驱动和 NT4系统的驱动程序。
EZDriverInstaller
EZDriverInstaller是一个无需经过设备管理器或“添加新硬件”功能就能为 Windows 2000/XP动态加载和卸载 WDM驱动程序的小实用程序。
SetDDKGo
SetDDKGo用来设置设备驱动程序创建的环境。当我们用 Visual Studio( VC++)编译驱动程序源程序的时候,需要用 SetDDKGo来设置环境变量,之后
SetDDKGo会自动启动 Visual Studio( VC++)编译环境。
http://qsyang.yeah.net
现代微机原理与接口技术
7
2.2 DriverStudio 2.7的安装安装需要的软硬件环境
PC-compatible Intel x86 系统
Windows 2000,(Optional,其中一些工具也支持
Windows 98 和 Windows 95.)
内存,最少 32 MB,推荐使用 64 MB
硬盘,完全安装需要 72 MB
针对 SoftICE的远程调试,NE2000-兼容 网卡或 3Com
网卡
针对 DriverWorks,Microsoft DDK,MS Visual C++
http://qsyang.yeah.net
现代微机原理与接口技术
8
安装步骤,
在安装 DriverWorks之前,首先要保证你的计算机上已经安装了 Microsoft Visual C++以及相应针对
Windows NT 或 WDM的 DDK的正确版本 。 所有这些包括 DriverStudio的安装都必须以系统管理员身份启动系统。并且要按照下面的顺序安装。
第一步:
安装 Microsoft Visual Studio C++ 6.0 (注意 Windows
2000DDK暂时对 Visual Studio.NET不支持)
http://qsyang.yeah.net
现代微机原理与接口技术
9
第二步:
安装 2000DDK( Driver Development Kits)。
注意:
1)如果本地机的操作系统为 Windows2000 请确认已经安装了 Windows SevicePack1或 Windows SevicePack2
在安装 DDK的时候请选择完全安装。
2)安装中,不需要安装 64BIT IA64Binaries
3)安装好后,对于 2000DDK不需要手动配置环境变量
,只需在开始菜单中点击 Checked Build Envirment 则
DDK会自动调用 setenv配置环境变量,并监测相应的
SDK以及 Visual Studio IDE
http://qsyang.yeah.net
现代微机原理与接口技术
10
第三步:
安装 DriverStudio 2.7(按照安装提示安装)。
注意,DriverStudio 2.7,包括最新的 DriverStudio 3.0不能在 Windows 2000的 SP4和
WindowsXP上使用,会引起蓝屏。遇到这种情况,请在安装好后不要重新启动机器,而是立即打上补丁。打补丁的方法是用新的 siwvid.sys(补丁的内容)替换掉
\%system%\system32\drivers\
下的老的 siwvid.sys
http://qsyang.yeah.net
现代微机原理与接口技术
11
DriverStudio安装后的设置,
1)使用 SetDDKGo工具定义 BASEDIR环境变量并启动
MSVC 5.0或 6.0,
http://qsyang.yeah.net
现代微机原理与接口技术
12
http://qsyang.yeah.net
现代微机原理与接口技术
13
http://qsyang.yeah.net
现代微机原理与接口技术
14
2)打开下列地址上的建立库文件工程
http://qsyang.yeah.net
现代微机原理与接口技术
15
3) 选择 Build|Batch Build(编译 |批构件),打开下面的窗口,从中选则需要编译的配置。
注意不要选择 IA64的各项,Checked是调试版本,Free
是发布版本
http://qsyang.yeah.net
现代微机原理与接口技术
16
4) 点击 Build编译所选择的库文件。
注意:库文件只需在安装完成后第一次使用前编译一次即可。 以后要使用 DriverWorks,只需通过 SetDDKGo
进入 MSVC即可。
http://qsyang.yeah.net
现代微机原理与接口技术
17
3,VtoolsD开发 VxD简介生成简单框架
http://qsyang.yeah.net
现代微机原理与接口技术
18
动态装载设备名编程语言生成调试用目标代码
http://qsyang.yeah.net
现代微机原理与接口技术
19
http://qsyang.yeah.net
现代微机原理与接口技术
20
http://qsyang.yeah.net
现代微机原理与接口技术
21
与应用程序通信的控制消息
http://qsyang.yeah.net
现代微机原理与接口技术
22
http://qsyang.yeah.net
现代微机原理与接口技术
23
虚拟机类名设备类名线程类名
http://qsyang.yeah.net
现代微机原理与接口技术
24
http://qsyang.yeah.net
现代微机原理与接口技术
25
http://qsyang.yeah.net
现代微机原理与接口技术
26
http://qsyang.yeah.net
现代微机原理与接口技术
27
http://qsyang.yeah.net
现代微机原理与接口技术
28
http://qsyang.yeah.net
现代微机原理与接口技术
29
http://qsyang.yeah.net
现代微机原理与接口技术
30
http://qsyang.yeah.net
现代微机原理与接口技术
31
// MYFIRST.h - include file for VxD MYFIRST
#include <vtoolscp.h>
#define DEVICE_CLASS MyfirstDevice
#define MYFIRST_DeviceID UNDEFINED_DEVICE_ID
#define MYFIRST_Init_Order UNDEFINED_INIT_ORDER
#define MYFIRST_Major 1
#define MYFIRST_Minor 0
#define DIOC_MY_IO CTL_CODE( FILE_DEVICE_UNKNOWN,
1,METHOD_NEITHER,FILE_ANY_ACCESS)
// 定义一个句柄用于应用程序与 VxD通信头文件
http://qsyang.yeah.net
现代微机原理与接口技术
32
class MyfirstDevice,public VDevice
{
public:
virtual DWORD OnW32DeviceIoControl( PIOCTLPARAMS
pDIOCParams);
};
class MyfirstVM,public VVirtualMachine
{
public:
MyfirstVM( VMHANDLE hVM);
};
class MyfirstThread,public VThread
{
public:
MyfirstThread( THREADHANDLE hThread);
};
http://qsyang.yeah.net
现代微机原理与接口技术
33
// MYFIRST.cpp - main module for VxD MYFIRST
#define DEVICE_MAIN
#include "myfirst.h"
Declare_Virtual_Device( MYFIRST)
#undef DEVICE_MAIN
MyfirstVM::MyfirstVM(VMHANDLE hVM):VVirtualMachine
( hVM) {}
MyfirstThread::MyfirstThread(THREADHANDLE hThread),
VThread( hThread) {}
DWORD MyfirstDevice::OnW32DeviceIoControl
( PIOCTLPARAMS pDIOCParams)
{
char* msg="欢迎进入虚拟机世界 !";
char* caption="Hello World!";
.cpp文件
http://qsyang.yeah.net
现代微机原理与接口技术
34
switch( pDIOCParams->dioc_IOCtlCode)
{
case DIOC_OPEN:dout<<"I am Opening!"; break;
//调用 CreateFile函数时响应该分支代码
case DIOC_MY_IO:dout<<"I am working!"<<endl;
SHELL_Message( pDIOCParams->dioc_hvm,MB_OK,msg,
caption,0,0,0);
break;
//调用 DeviceIoControl函数时响应该分支下的代码
case DIOC_CLOSEHANDLE,dout<<"I am Closing!"; break;
//调用 CloseHandle函数时响应该分支代码
}
return 0;
}
http://qsyang.yeah.net
现代微机原理与接口技术
35
# MYFIRST.mak - makefile for VxD MYFIRST
DEVICENAME = MYFIRST
DYNAMIC = 1
FRAMEWORK = CPP
DEBUG = 1
OBJECTS = myfirst.OBJ
!include $( VTOOLSD) \include\vtoolsd.mak
!include $( VTOOLSD) \include\vxdtarg.mak
myfirst.OBJ,myfirst.cpp myfirst.h
.mak文件
http://qsyang.yeah.net
现代微机原理与接口技术
36
http://qsyang.yeah.net
现代微机原理与接口技术
37
http://qsyang.yeah.net
现代微机原理与接口技术
38
#include <iostream.h>
#include <windows.h>
#include <winioctl.h>
#define DIOC_MY_IO CTL_CODE( FILE_DEVICE_UNKNOWN,
1,METHOD_NEITHER,FILE_ANY_ACCESS)
//定义一个句柄用于应用程序与 VxD通信
void main()
{
HANDLE hDevice;
hDevice=CreateFile ( "\\\\.\\myfirst.vxd",0,
0,0,OPEN_EXISTING,
FILE_FLAG_DELETE_ON_CLOSE,0);
// 文件名的路径一定是以 \\\\.\\打头,默认的 VXD的文件的目录是 C:\Windows\system,如果 VXD在 d:\myvxd目录下,
则这里应该写成 "\\\\.\\d,\\myvxd\\myfirst.vxd"
Win32环境下的控制台程序
http://qsyang.yeah.net
现代微机原理与接口技术
39
if( hDevice==INVALID_HANDLE_VALUE)
{
cout<<"Open VxD error"<<GetLastError() <<endl;
exit( 1);
}
DeviceIoControl( hDevice,DIOC_MY_IO,NULL,0,NULL,0,
NULL,NULL);
//使用句柄 DIOC_MY_IO与 VxD交互
CloseHandle( hDevice); //关闭设备句柄
}
http://qsyang.yeah.net
现代微机原理与接口技术
40
VToolsD的类库
http://qsyang.yeah.net
现代微机原理与接口技术
41
I/O类
class VIOPort
{
public:
VIOPort( DWORD port); //构造函数
~VIOPort(); //析构函数
BOOL hook(); //挂钩一个端口处理程序
BOOL unhook(); //摘钩一个端口处理程序
VOID localEnable( VMHANDLE); //允许监控指定虚拟机端口的 I/O操作
VOID localDisable( VMHANDLE); //禁止监控指定虚拟机端口的 I/O操作
VOID globalEnable(); //允许监控所有虚拟机端口的 I/O操作
VOID globalDisable(); //禁止监控所有虚拟机端口的 I/O操作
virtual DWORD handler( VMHANDLE,DWORD port,CLIENT_STRUCT*
pRegs,DWORD iotype,DWORD outdata); //端口处理程序
protected:
DWORD m_port;
BYTE m_thunk[IOPORTTHUNKSIZE];
};
http://qsyang.yeah.net
现代微机原理与接口技术
42
下面我们给出一个例子,该例子捕获端口 0xf0,当应用程序要读该端口时,它将上次写入该端口的资料返回给应用程序。 用
VToolsD生成的时候,基本上和生成 Myfirst的方法一样,只是在
Windows95控制消息中只选择 SYS_DYNAMIC_DEVICE_EXIT和
SYS_DYNAMIC_DEVICE_INIT两个消息而不选择
W32_DEVICEIOCONTROL。
// IOPORT.h - include file for VxD IOPORT
#include <vtoolscp.h>
#define DEVICE_CLASS IoportDevice
#define IOPORT_DeviceID UNDEFINED_DEVICE_ID
#define IOPORT_Init_Order UNDEFINED_INIT_ORDER
#define IOPORT_Major 1
#define IOPORT_Minor 0
#define PORT_NUM 0xf0 //要捕获的端口地址
……
http://qsyang.yeah.net
现代微机原理与接口技术
43
…………
class IoportPort,public VIOPort
{
public:
IoportPort( ),VIOPort( PORT_NUM) {};
DWORD handler( VMHANDLE hVM,DWORD
port,CLIENT_STRUCT* pRegs,DWORD iotype,
DWORD outdata) ;
};
…………
http://qsyang.yeah.net
现代微机原理与接口技术
44
// IOPORT.cpp - main module for VxD IOPORT
#define DEVICE_MAIN
#include "ioport.h"
Declare_Virtual_Device( IOPORT)
#undef DEVICE_MAIN
IoportPort* pio;
IoportVM:,IoportVM( VMHANDLE hVM)
,VVirtualMachine( hVM) {}
IoportThread:,IoportThread( THREADHANDLE hThread)
,VThread( hThread) {}
http://qsyang.yeah.net
现代微机原理与接口技术
45
BOOL IoportDevice:,OnSysDynamicDeviceInit( )
{ // 动态装载初始化的时候调用
pio=new( IoportPort) ;
if( pio)
{
if( pio->hook( )) // 挂上端口映射
{
dout<<"hook success"<<endl;
}
else
return FALSE;
}
else return FALSE;
return TRUE;
}
http://qsyang.yeah.net
现代微机原理与接口技术
46
BOOL IoportDevice:,OnSysDynamicDeviceExit( )
{ // 驱动程序被卸下时调用
if( pio)
{
if( pio->unhook( )) //将 I/O映射卸载下来
{
dout<<"unhook success"<<endl;
}
delete pio;
}
return TRUE;
}
DWORD IoportPort,,handler ( VMHANDLE hVM,DWORD
port,CLIENT_STRUCT* pRegs,DWORD
iotype,DWORD outdata)
{
static WORD count=0;
static DWORD buffer[20];
static BYTE inppt=0;
count++;
dout<<"entering handler"<<endl;
dout<<"entered count"<<count<<endl;
http://qsyang.yeah.net
现代微机原理与接口技术
47
switch( iotype)
{
case BYTE_INPUT,dout<<"buffer byte"<<( BYTE) buffer[inppt]<<endl;
inppt++;
return( BYTE) buffer[inppt-1];
case WORD_INPUT,dout<<"buffer word"<<( WORD) buffer[inppt]<<endl;
inppt++;
return( WORD) buffer[inppt-1];
case DWORD_INPUT,dout<< "buffer dword"<<( WORD) buffer[inppt]<<endl;
inppt++;
return( WORD) buffer[inppt-1];
case BYTE_OUTPUT,buffer[count-1]=outdata; dout<<"byte output data,"<<
( BYTE)
outdata<<endl; break;
case WORD_OUTPUT,buffer[count-1]=outdata; dout<<"word output data:
"<<( WORD)
outdata<<endl;
break;
case DWORD_OUTPUT,buffer[count-1]=outdata; dout<<"dword output data:
"<<
( DWORD) outdata<< endl;
break;
default,break;
} //对于输入,处理程序将数据输入到端口的缓冲,对于输出,处理程序将缓冲中的资料输出到端口
return 0;
}
http://qsyang.yeah.net
现代微机原理与接口技术
48
下面给出调用端口 0xf0的 Win32控制台程序。
#include "conio.h"
#include <iostream.h>
#include <windows.h>
#include <winioctl.h>
#define PORT_NUM 0xf0
void main( )
{
char* srcdata="This is IO Sample!!";
char* desdata=new char( 20) ;
HANDLE hDevice;
char ch;
_cprintf ( "1=load IOPORT VXD,x=exit,Others=Do not load
IOPORT VXD\n") ;
ch=_getch( ) ;
while( ch!='x')
{
if( ch=='1')
{
hDevice=CreateFile
(
"\\\\.\\Ioport.vxd",0,0,0,OPEN_EXISTING,FILE_FLAG_DELETE_ON_CLOS
E,0);
http://qsyang.yeah.net
现代微机原理与接口技术
49
if( hDevice==INVALID_HANDLE_VALUE)
{
cout<<"Open VXD error"<<GetLastError() <<endl;
exit( 1);
}
}
desdata[0]='\0';
_asm
{
mov dx,PORT_NUM
mov edi,srcdata
mov ecx,20
byteoutput,mov al,[edi]
out dx,al
inc edi
loop byteoutput
mov esi,desdata
mov ecx,20
byteinput,in al,dx
mov [esi],al
inc esi
loop byteinput
}
http://qsyang.yeah.net
现代微机原理与接口技术
50
if( ch=='1')
{
CloseHandle( hDevice); //关闭设备句柄
_cprintf( "scrdata and desdata should be the same!\n");
}
_cprintf( "srcdata,%s\n",srcdata);
_cprintf( "desdata,%s\n",desdata);
_cprintf( "1=load IOPORT VXD,x=exit,Others=Do not load
IOPORT VXD\n");
ch=_getch();
}
}
http://qsyang.yeah.net
现代微机原理与接口技术
51
中断类
class VHardwareInt
{
public:
VHardwareInt( int irq,DWORD flags,DWORD tout,PVOID
refdata);
//构造函数
~VHardwareInt(); //析构函数
virtual BOOL hook(); //挂钩虚拟 IRQ的处理程序
virtual BOOL unhook(); //摘钩虚拟 IRQ的处理程序
virtual VOID OnHardwareInt( VMHANDLE); //硬件中断信号处理程序
virtual VOID OnVirtualInt( VMHANDLE);
//虚拟中断信号处理程序 VPICD给 VxD的)
virtual VOID OnVirtualEOI( VMHANDLE);
//当虚拟机发出 EOI命令时被调用
virtual VOID OnVirtualMask( VMHANDLE,BOOL bMask);
//虚拟机改变屏蔽位的时候被调用
virtual VOID OnVirtualIRET( VMHANDLE);
//当虚拟机中中断处理程序返回控制给 VPICD时被调用
VOID assert( VMHANDLE); //在指定虚拟机中请求虚拟中断
VOID deassert( VMHANDLE); //撤消指定虚拟机中的虚拟中断
DWORD getStatus( VMHANDLE hVM); //返回虚拟 IRQ的部分状态信息
http://qsyang.yeah.net
现代微机原理与接口技术
52
DWORD getCompleteStatus( VMHANDLE hVM);
//返回虚拟 IRQ的全部状态信号
BOOL testPhysicalRequest(); //测试物理 IRQ的状态信息
VOID sendPhysicalEOI(); //向物理 PIC发出中断结束 EOI信号
VOID physicalMask(); //物理屏蔽 IRQ
VOID physicalUnmask(); //物理允许 IRQ
VOID setAutoMask(); //指示可编程中断控制器执行智能的 IRQ屏蔽
static LONG convertIntToIRQ( int vecno,VMHANDLE hVM);
//将中断号转换成 IRQ号
static LONG convertIRQToInt( int irq,VMHANDLE hVM);
//将 IRQ号转换成中断号
static BOOL forceDefaultOwner( int irq,VMHANDLE hVM);
//控制 IRQ的默认处理
protected:
WORD m_irq;
WORD m_flags;
DWORD m_timeout;
PVOID m_refdata;
IRQHANDLE m_handle;
BYTE m_thunk[HWITHUNKSIZE];
private:
VHardwareInt();
};
http://qsyang.yeah.net
现代微机原理与接口技术
53
class VSharedHardwareInt,public VHardwareInt
{
public:
VSharedHardwareInt( int irq,DWORD flags,
DWORD timeout,PVOID refdata) ;
virtual BOOL hook( ) ;
virtual BOOL OnSharedHardwareInt( VMHANDLE) ;
//中断处理程序
protected:
BYTE m_sthunk[SHWINTTHUNKSIZE];
private:
VSharedHardwareInt( void) ;
};
http://qsyang.yeah.net
现代微机原理与接口技术
54
下面我们使用 VsharedHardwareInt给一个 VxD的例子,该例子捕获鼠标中断。该例子也是用 VtoolsD生成的可动态加载的 VxD框架,然后在 VC6中修改的,我们只给出修改的部分。
// HARDINT.h - include file for VxD HARDINT
…
#define IRQ_NUM 12 //根据你的鼠标情况指定,COM1为 4,COM2为 3,PS/2
为 12
class HardintDevice,public VDevice
{
public:
virtual BOOLOnSysDynamicDeviceInit( ) ;
virtual BOOLOnSysDynamicDeviceExit( ) ;
};
…
class HardintInt,public VSharedHardwareInt
{
public:
HardintInt( ),VSharedHardwareInt( IRQ_NUM,0,0,0) {};
BOOL OnSharedHardwareInt( VMHANDLE hVM) ;
};
http://qsyang.yeah.net
现代微机原理与接口技术
55
// HARDINT.cpp - main module for VxD HARDINT
…
HardintInt* pshint;
…
BOOLHardintDevice:,OnSysDynamicDeviceInit( )
{
VMHANDLE hVM;
hVM=VMD_Get_Mouse_Owner( ) ;
dout<<"Mouse's VMHANDLE"<<( DWORD) hVM<<endl;
pshint=new( HardintInt) ;
if( pshint)
{
if( pshint->hook( ))
{
dout<<"shared interruppt hooked"<<endl;
}
else
{
dout<<"shared interruppt hook failed!"<<endl;
return FALSE;
}
}
http://qsyang.yeah.net
现代微机原理与接口技术
56
else return FALSE;
return TRUE;
}
BOOL HardintDevice:,OnSysDynamicDeviceExit( )
{
if( pshint)
{
if( pshint->unhook( ))
{
dout<<"shared interrupt unhooked"<<endl;
}
delete pshint;
}
return TRUE;
}
BOOL HardintInt:,OnSharedHardwareInt( VMHANDLE hVM)
{
static WORD count=0;
count++;
dout<<"hardware( Mouse) int count,"<<count<<endl;
return FALSE;
}
http://qsyang.yeah.net
现代微机原理与接口技术
57
热键类
class VHotKey
{
public:
VHotKey( BYTE scan,scanType_t st,
DWORD shift,DWORD flags,PVOID refData=0,
DWORD delay=0); //构造函数
~VHotKey() {unhook(); }; //析构函数
virtual VOID handler( BYTE scan,
keyAction_t ka,DWORD shift,PVOID refData,
DWORD elapased); //热键处理程序
BOOL hook(); //挂钩热键处理程序
BOOL unhook(); //摘钩热键处理程序
VOID localEnable( BOOL enable,VMHANDLE hVM);
//在指定的虚拟机中允许或禁止热键事件
VOID reflectToVM( VMHANDLE hVM,DWORD shift);
//指示 VxD把热键事件传到指定虚拟机中
static VOID cancelState(); //取消热键
http://qsyang.yeah.net
现代微机原理与接口技术
58
protected:
DWORD m_handle;
BYTE m_scanCode;
scanType_t m_scanType;
DWORD m_shiftState;
BYTE m_flags;
PVOID m_refData;
DWORD m_timeout;
BYTE m_thunk[HKTHUNKSIZE];
}
http://qsyang.yeah.net
现代微机原理与接口技术
59
下面这个例子截获 Ctrl+P键,当按下这两个键时,将弹出一个窗口,说明已经捕获。该例子也是用 VtoolsD生成的可动态加载的
VxD框架,然后在 VC6中修改的,我们只给出修改的部分。
// HOTKEY.h - include file for VxD HOTKEY
…
#define C_SCAN 0X19 //P键的扫描码
class HotkeyDevice,public VDevice
{
public:
virtual BOOL OnSysDynamicDeviceInit( ) ;
virtual BOOL OnSysDynamicDeviceExit( ) ;
};
…
class HotkeyHot,public VHotKey
{
public:
HotkeyHot ( ),VHotKey ( C_SCAN,SCAN_NORMAL,HKSS_Ctrl,
CallOnPress,"热键被按下 ! ",0) { };
void handler( BYTE scan,keyAction_t keyEvent,DWORD shift,
PVOID refData,
DWORD elapased) ;
};
http://qsyang.yeah.net
现代微机原理与接口技术
60
// HOTKEY.cpp - main module for VxD HOTKEY
…
HotkeyHot* pkey;
…
BOOL HotkeyDevice:,OnSysDynamicDeviceInit( )
{
pkey=new( HotkeyHot) ;
if( pkey)
{
if( pkey->hook( ))
{
dout<<"hot key hooked"<<endl;
}
else return FALSE;
}
else return FALSE;
return TRUE;
}
http://qsyang.yeah.net
现代微机原理与接口技术
61
BOOL HotkeyDevice:,OnSysDynamicDeviceExit( )
{
if( pkey)
{
if( pkey->unhook( ))
{
dout<<"hot key unhooked"<<endl;
}
delete pkey;
}
return TRUE;
}
void HotkeyHot:,handler( BYTE scan,keyAction_t keyEvent,
DWORD shift,PVOID
refData,DWORD elapased)
{
dout<<"entering handler"<<endl;
SHELL_Message ( Get_Cur_VM_Handle ( ),MB_OK,( char* )
refData,"CTRL+P Pressed",0,0,0) ; //显示一个消息框
pkey->reflectToVM( Get_Cur_VM_Handle( ),shift) ;
//将按键信息传送到当前虚拟机中
}
现代微机原理与接口技术
1
Windows98/2000驱动程序编写方法
(上)
杨全胜
http://qsyang.yeah.net
现代微机原理与接口技术
2
1,驱动程序的开发环境对于 VxD的开发,需要的开发环境是,
Visual C++ 5.0/6.0
Windosw 95DDK
如果想加快开发步骤,建议使用第三方的 VToolsD开发工具,它将 DDK的东西全部封装成 C++的类,可以直接用 Visual C++编写程序,而无须使用汇编。而且它提供的 QuickVxd能够方便快速地建立 VxD程序的框架。
http://qsyang.yeah.net
现代微机原理与接口技术
3
对于 WDM的开发,又分几种情况,
1)对于 Windows 98系统
Visual C++ 5.0
Windows 98DDK
2)对于 Windows Me/2000
Visual C++ 6.0
Windows 2000DDK
3)对于 Windows XP
Visual C++6.0/.net
Windows XPDDK
同样,为了方便起见,也可以使用第三方的开发工具 Driver Works,它也是将 DDK的内容封装成类
,而且提供一个快速方便地生成驱动框架的工具。
http://qsyang.yeah.net
现代微机原理与接口技术
4
2,驱动程序开发工具包 DriverStudio
2.1 DriverStudio 2.7所包含的工具
VToolsD
VToolsD 是一个用来开发针对 Win9X (Windows 95 和
Windows 98)操作系统下设备驱动程序 (VxD)的工具。
VToolsD 中包括生成驱动程序源代码的工具,run-time 和
interface 库,以及一些驱动程序样本,可以用来作为各种类型的设备驱动程序的基础部分。
DriverWorks
DriverWorks对于 Windows NT下和 Windows 98 与
Windows 2000共同支持的 Win32驱动模型 (WDM)设备驱动程序的开发提供完全的支持。 DriverWorks中包含一个非常完善的源代码生成工具 (DriverWizard) 以及相应的类库和驱动程序样本,它提供了在 C++下进行设备驱动程序开发的支持。
http://qsyang.yeah.net
现代微机原理与接口技术
5
DriverNetworks
DriverNetworks 是针对 Windows网络驱动开发人员的一个模块。在它的核心部分,DriverNetworks 是一个针对 NDIS drivers 和 TDI clients (DriverSockets)的
C++ 的类库。 DriverNetworks 中也有 Quick Miniport
Wizard 用来直接开始一个 NDIS Miniport 或
Intermediate Driver 工程。它可以让你快速的生成所有采用 DriverNetworks C++ 类库编写的 NDIS驱动程序的编译,安装和调试所需要的文件 。
SoftICE
SoftICE 是一个功能极其强大的内核模式调试器,它支持在配置一台单独的计算机或两台计算机下进行设备驱动程序的调试。
http://qsyang.yeah.net
现代微机原理与接口技术
6
DriverMonitor
DriverMonitor不仅可以显示 WDM和 VxD在操作系统核心层次输出的调试语句,还可以装载和卸载 VxD
驱动和 NT4系统的驱动程序。
EZDriverInstaller
EZDriverInstaller是一个无需经过设备管理器或“添加新硬件”功能就能为 Windows 2000/XP动态加载和卸载 WDM驱动程序的小实用程序。
SetDDKGo
SetDDKGo用来设置设备驱动程序创建的环境。当我们用 Visual Studio( VC++)编译驱动程序源程序的时候,需要用 SetDDKGo来设置环境变量,之后
SetDDKGo会自动启动 Visual Studio( VC++)编译环境。
http://qsyang.yeah.net
现代微机原理与接口技术
7
2.2 DriverStudio 2.7的安装安装需要的软硬件环境
PC-compatible Intel x86 系统
Windows 2000,(Optional,其中一些工具也支持
Windows 98 和 Windows 95.)
内存,最少 32 MB,推荐使用 64 MB
硬盘,完全安装需要 72 MB
针对 SoftICE的远程调试,NE2000-兼容 网卡或 3Com
网卡
针对 DriverWorks,Microsoft DDK,MS Visual C++
http://qsyang.yeah.net
现代微机原理与接口技术
8
安装步骤,
在安装 DriverWorks之前,首先要保证你的计算机上已经安装了 Microsoft Visual C++以及相应针对
Windows NT 或 WDM的 DDK的正确版本 。 所有这些包括 DriverStudio的安装都必须以系统管理员身份启动系统。并且要按照下面的顺序安装。
第一步:
安装 Microsoft Visual Studio C++ 6.0 (注意 Windows
2000DDK暂时对 Visual Studio.NET不支持)
http://qsyang.yeah.net
现代微机原理与接口技术
9
第二步:
安装 2000DDK( Driver Development Kits)。
注意:
1)如果本地机的操作系统为 Windows2000 请确认已经安装了 Windows SevicePack1或 Windows SevicePack2
在安装 DDK的时候请选择完全安装。
2)安装中,不需要安装 64BIT IA64Binaries
3)安装好后,对于 2000DDK不需要手动配置环境变量
,只需在开始菜单中点击 Checked Build Envirment 则
DDK会自动调用 setenv配置环境变量,并监测相应的
SDK以及 Visual Studio IDE
http://qsyang.yeah.net
现代微机原理与接口技术
10
第三步:
安装 DriverStudio 2.7(按照安装提示安装)。
注意,DriverStudio 2.7,包括最新的 DriverStudio 3.0不能在 Windows 2000的 SP4和
WindowsXP上使用,会引起蓝屏。遇到这种情况,请在安装好后不要重新启动机器,而是立即打上补丁。打补丁的方法是用新的 siwvid.sys(补丁的内容)替换掉
\%system%\system32\drivers\
下的老的 siwvid.sys
http://qsyang.yeah.net
现代微机原理与接口技术
11
DriverStudio安装后的设置,
1)使用 SetDDKGo工具定义 BASEDIR环境变量并启动
MSVC 5.0或 6.0,
http://qsyang.yeah.net
现代微机原理与接口技术
12
http://qsyang.yeah.net
现代微机原理与接口技术
13
http://qsyang.yeah.net
现代微机原理与接口技术
14
2)打开下列地址上的建立库文件工程
http://qsyang.yeah.net
现代微机原理与接口技术
15
3) 选择 Build|Batch Build(编译 |批构件),打开下面的窗口,从中选则需要编译的配置。
注意不要选择 IA64的各项,Checked是调试版本,Free
是发布版本
http://qsyang.yeah.net
现代微机原理与接口技术
16
4) 点击 Build编译所选择的库文件。
注意:库文件只需在安装完成后第一次使用前编译一次即可。 以后要使用 DriverWorks,只需通过 SetDDKGo
进入 MSVC即可。
http://qsyang.yeah.net
现代微机原理与接口技术
17
3,VtoolsD开发 VxD简介生成简单框架
http://qsyang.yeah.net
现代微机原理与接口技术
18
动态装载设备名编程语言生成调试用目标代码
http://qsyang.yeah.net
现代微机原理与接口技术
19
http://qsyang.yeah.net
现代微机原理与接口技术
20
http://qsyang.yeah.net
现代微机原理与接口技术
21
与应用程序通信的控制消息
http://qsyang.yeah.net
现代微机原理与接口技术
22
http://qsyang.yeah.net
现代微机原理与接口技术
23
虚拟机类名设备类名线程类名
http://qsyang.yeah.net
现代微机原理与接口技术
24
http://qsyang.yeah.net
现代微机原理与接口技术
25
http://qsyang.yeah.net
现代微机原理与接口技术
26
http://qsyang.yeah.net
现代微机原理与接口技术
27
http://qsyang.yeah.net
现代微机原理与接口技术
28
http://qsyang.yeah.net
现代微机原理与接口技术
29
http://qsyang.yeah.net
现代微机原理与接口技术
30
http://qsyang.yeah.net
现代微机原理与接口技术
31
// MYFIRST.h - include file for VxD MYFIRST
#include <vtoolscp.h>
#define DEVICE_CLASS MyfirstDevice
#define MYFIRST_DeviceID UNDEFINED_DEVICE_ID
#define MYFIRST_Init_Order UNDEFINED_INIT_ORDER
#define MYFIRST_Major 1
#define MYFIRST_Minor 0
#define DIOC_MY_IO CTL_CODE( FILE_DEVICE_UNKNOWN,
1,METHOD_NEITHER,FILE_ANY_ACCESS)
// 定义一个句柄用于应用程序与 VxD通信头文件
http://qsyang.yeah.net
现代微机原理与接口技术
32
class MyfirstDevice,public VDevice
{
public:
virtual DWORD OnW32DeviceIoControl( PIOCTLPARAMS
pDIOCParams);
};
class MyfirstVM,public VVirtualMachine
{
public:
MyfirstVM( VMHANDLE hVM);
};
class MyfirstThread,public VThread
{
public:
MyfirstThread( THREADHANDLE hThread);
};
http://qsyang.yeah.net
现代微机原理与接口技术
33
// MYFIRST.cpp - main module for VxD MYFIRST
#define DEVICE_MAIN
#include "myfirst.h"
Declare_Virtual_Device( MYFIRST)
#undef DEVICE_MAIN
MyfirstVM::MyfirstVM(VMHANDLE hVM):VVirtualMachine
( hVM) {}
MyfirstThread::MyfirstThread(THREADHANDLE hThread),
VThread( hThread) {}
DWORD MyfirstDevice::OnW32DeviceIoControl
( PIOCTLPARAMS pDIOCParams)
{
char* msg="欢迎进入虚拟机世界 !";
char* caption="Hello World!";
.cpp文件
http://qsyang.yeah.net
现代微机原理与接口技术
34
switch( pDIOCParams->dioc_IOCtlCode)
{
case DIOC_OPEN:dout<<"I am Opening!"; break;
//调用 CreateFile函数时响应该分支代码
case DIOC_MY_IO:dout<<"I am working!"<<endl;
SHELL_Message( pDIOCParams->dioc_hvm,MB_OK,msg,
caption,0,0,0);
break;
//调用 DeviceIoControl函数时响应该分支下的代码
case DIOC_CLOSEHANDLE,dout<<"I am Closing!"; break;
//调用 CloseHandle函数时响应该分支代码
}
return 0;
}
http://qsyang.yeah.net
现代微机原理与接口技术
35
# MYFIRST.mak - makefile for VxD MYFIRST
DEVICENAME = MYFIRST
DYNAMIC = 1
FRAMEWORK = CPP
DEBUG = 1
OBJECTS = myfirst.OBJ
!include $( VTOOLSD) \include\vtoolsd.mak
!include $( VTOOLSD) \include\vxdtarg.mak
myfirst.OBJ,myfirst.cpp myfirst.h
.mak文件
http://qsyang.yeah.net
现代微机原理与接口技术
36
http://qsyang.yeah.net
现代微机原理与接口技术
37
http://qsyang.yeah.net
现代微机原理与接口技术
38
#include <iostream.h>
#include <windows.h>
#include <winioctl.h>
#define DIOC_MY_IO CTL_CODE( FILE_DEVICE_UNKNOWN,
1,METHOD_NEITHER,FILE_ANY_ACCESS)
//定义一个句柄用于应用程序与 VxD通信
void main()
{
HANDLE hDevice;
hDevice=CreateFile ( "\\\\.\\myfirst.vxd",0,
0,0,OPEN_EXISTING,
FILE_FLAG_DELETE_ON_CLOSE,0);
// 文件名的路径一定是以 \\\\.\\打头,默认的 VXD的文件的目录是 C:\Windows\system,如果 VXD在 d:\myvxd目录下,
则这里应该写成 "\\\\.\\d,\\myvxd\\myfirst.vxd"
Win32环境下的控制台程序
http://qsyang.yeah.net
现代微机原理与接口技术
39
if( hDevice==INVALID_HANDLE_VALUE)
{
cout<<"Open VxD error"<<GetLastError() <<endl;
exit( 1);
}
DeviceIoControl( hDevice,DIOC_MY_IO,NULL,0,NULL,0,
NULL,NULL);
//使用句柄 DIOC_MY_IO与 VxD交互
CloseHandle( hDevice); //关闭设备句柄
}
http://qsyang.yeah.net
现代微机原理与接口技术
40
VToolsD的类库
http://qsyang.yeah.net
现代微机原理与接口技术
41
I/O类
class VIOPort
{
public:
VIOPort( DWORD port); //构造函数
~VIOPort(); //析构函数
BOOL hook(); //挂钩一个端口处理程序
BOOL unhook(); //摘钩一个端口处理程序
VOID localEnable( VMHANDLE); //允许监控指定虚拟机端口的 I/O操作
VOID localDisable( VMHANDLE); //禁止监控指定虚拟机端口的 I/O操作
VOID globalEnable(); //允许监控所有虚拟机端口的 I/O操作
VOID globalDisable(); //禁止监控所有虚拟机端口的 I/O操作
virtual DWORD handler( VMHANDLE,DWORD port,CLIENT_STRUCT*
pRegs,DWORD iotype,DWORD outdata); //端口处理程序
protected:
DWORD m_port;
BYTE m_thunk[IOPORTTHUNKSIZE];
};
http://qsyang.yeah.net
现代微机原理与接口技术
42
下面我们给出一个例子,该例子捕获端口 0xf0,当应用程序要读该端口时,它将上次写入该端口的资料返回给应用程序。 用
VToolsD生成的时候,基本上和生成 Myfirst的方法一样,只是在
Windows95控制消息中只选择 SYS_DYNAMIC_DEVICE_EXIT和
SYS_DYNAMIC_DEVICE_INIT两个消息而不选择
W32_DEVICEIOCONTROL。
// IOPORT.h - include file for VxD IOPORT
#include <vtoolscp.h>
#define DEVICE_CLASS IoportDevice
#define IOPORT_DeviceID UNDEFINED_DEVICE_ID
#define IOPORT_Init_Order UNDEFINED_INIT_ORDER
#define IOPORT_Major 1
#define IOPORT_Minor 0
#define PORT_NUM 0xf0 //要捕获的端口地址
……
http://qsyang.yeah.net
现代微机原理与接口技术
43
…………
class IoportPort,public VIOPort
{
public:
IoportPort( ),VIOPort( PORT_NUM) {};
DWORD handler( VMHANDLE hVM,DWORD
port,CLIENT_STRUCT* pRegs,DWORD iotype,
DWORD outdata) ;
};
…………
http://qsyang.yeah.net
现代微机原理与接口技术
44
// IOPORT.cpp - main module for VxD IOPORT
#define DEVICE_MAIN
#include "ioport.h"
Declare_Virtual_Device( IOPORT)
#undef DEVICE_MAIN
IoportPort* pio;
IoportVM:,IoportVM( VMHANDLE hVM)
,VVirtualMachine( hVM) {}
IoportThread:,IoportThread( THREADHANDLE hThread)
,VThread( hThread) {}
http://qsyang.yeah.net
现代微机原理与接口技术
45
BOOL IoportDevice:,OnSysDynamicDeviceInit( )
{ // 动态装载初始化的时候调用
pio=new( IoportPort) ;
if( pio)
{
if( pio->hook( )) // 挂上端口映射
{
dout<<"hook success"<<endl;
}
else
return FALSE;
}
else return FALSE;
return TRUE;
}
http://qsyang.yeah.net
现代微机原理与接口技术
46
BOOL IoportDevice:,OnSysDynamicDeviceExit( )
{ // 驱动程序被卸下时调用
if( pio)
{
if( pio->unhook( )) //将 I/O映射卸载下来
{
dout<<"unhook success"<<endl;
}
delete pio;
}
return TRUE;
}
DWORD IoportPort,,handler ( VMHANDLE hVM,DWORD
port,CLIENT_STRUCT* pRegs,DWORD
iotype,DWORD outdata)
{
static WORD count=0;
static DWORD buffer[20];
static BYTE inppt=0;
count++;
dout<<"entering handler"<<endl;
dout<<"entered count"<<count<<endl;
http://qsyang.yeah.net
现代微机原理与接口技术
47
switch( iotype)
{
case BYTE_INPUT,dout<<"buffer byte"<<( BYTE) buffer[inppt]<<endl;
inppt++;
return( BYTE) buffer[inppt-1];
case WORD_INPUT,dout<<"buffer word"<<( WORD) buffer[inppt]<<endl;
inppt++;
return( WORD) buffer[inppt-1];
case DWORD_INPUT,dout<< "buffer dword"<<( WORD) buffer[inppt]<<endl;
inppt++;
return( WORD) buffer[inppt-1];
case BYTE_OUTPUT,buffer[count-1]=outdata; dout<<"byte output data,"<<
( BYTE)
outdata<<endl; break;
case WORD_OUTPUT,buffer[count-1]=outdata; dout<<"word output data:
"<<( WORD)
outdata<<endl;
break;
case DWORD_OUTPUT,buffer[count-1]=outdata; dout<<"dword output data:
"<<
( DWORD) outdata<< endl;
break;
default,break;
} //对于输入,处理程序将数据输入到端口的缓冲,对于输出,处理程序将缓冲中的资料输出到端口
return 0;
}
http://qsyang.yeah.net
现代微机原理与接口技术
48
下面给出调用端口 0xf0的 Win32控制台程序。
#include "conio.h"
#include <iostream.h>
#include <windows.h>
#include <winioctl.h>
#define PORT_NUM 0xf0
void main( )
{
char* srcdata="This is IO Sample!!";
char* desdata=new char( 20) ;
HANDLE hDevice;
char ch;
_cprintf ( "1=load IOPORT VXD,x=exit,Others=Do not load
IOPORT VXD\n") ;
ch=_getch( ) ;
while( ch!='x')
{
if( ch=='1')
{
hDevice=CreateFile
(
"\\\\.\\Ioport.vxd",0,0,0,OPEN_EXISTING,FILE_FLAG_DELETE_ON_CLOS
E,0);
http://qsyang.yeah.net
现代微机原理与接口技术
49
if( hDevice==INVALID_HANDLE_VALUE)
{
cout<<"Open VXD error"<<GetLastError() <<endl;
exit( 1);
}
}
desdata[0]='\0';
_asm
{
mov dx,PORT_NUM
mov edi,srcdata
mov ecx,20
byteoutput,mov al,[edi]
out dx,al
inc edi
loop byteoutput
mov esi,desdata
mov ecx,20
byteinput,in al,dx
mov [esi],al
inc esi
loop byteinput
}
http://qsyang.yeah.net
现代微机原理与接口技术
50
if( ch=='1')
{
CloseHandle( hDevice); //关闭设备句柄
_cprintf( "scrdata and desdata should be the same!\n");
}
_cprintf( "srcdata,%s\n",srcdata);
_cprintf( "desdata,%s\n",desdata);
_cprintf( "1=load IOPORT VXD,x=exit,Others=Do not load
IOPORT VXD\n");
ch=_getch();
}
}
http://qsyang.yeah.net
现代微机原理与接口技术
51
中断类
class VHardwareInt
{
public:
VHardwareInt( int irq,DWORD flags,DWORD tout,PVOID
refdata);
//构造函数
~VHardwareInt(); //析构函数
virtual BOOL hook(); //挂钩虚拟 IRQ的处理程序
virtual BOOL unhook(); //摘钩虚拟 IRQ的处理程序
virtual VOID OnHardwareInt( VMHANDLE); //硬件中断信号处理程序
virtual VOID OnVirtualInt( VMHANDLE);
//虚拟中断信号处理程序 VPICD给 VxD的)
virtual VOID OnVirtualEOI( VMHANDLE);
//当虚拟机发出 EOI命令时被调用
virtual VOID OnVirtualMask( VMHANDLE,BOOL bMask);
//虚拟机改变屏蔽位的时候被调用
virtual VOID OnVirtualIRET( VMHANDLE);
//当虚拟机中中断处理程序返回控制给 VPICD时被调用
VOID assert( VMHANDLE); //在指定虚拟机中请求虚拟中断
VOID deassert( VMHANDLE); //撤消指定虚拟机中的虚拟中断
DWORD getStatus( VMHANDLE hVM); //返回虚拟 IRQ的部分状态信息
http://qsyang.yeah.net
现代微机原理与接口技术
52
DWORD getCompleteStatus( VMHANDLE hVM);
//返回虚拟 IRQ的全部状态信号
BOOL testPhysicalRequest(); //测试物理 IRQ的状态信息
VOID sendPhysicalEOI(); //向物理 PIC发出中断结束 EOI信号
VOID physicalMask(); //物理屏蔽 IRQ
VOID physicalUnmask(); //物理允许 IRQ
VOID setAutoMask(); //指示可编程中断控制器执行智能的 IRQ屏蔽
static LONG convertIntToIRQ( int vecno,VMHANDLE hVM);
//将中断号转换成 IRQ号
static LONG convertIRQToInt( int irq,VMHANDLE hVM);
//将 IRQ号转换成中断号
static BOOL forceDefaultOwner( int irq,VMHANDLE hVM);
//控制 IRQ的默认处理
protected:
WORD m_irq;
WORD m_flags;
DWORD m_timeout;
PVOID m_refdata;
IRQHANDLE m_handle;
BYTE m_thunk[HWITHUNKSIZE];
private:
VHardwareInt();
};
http://qsyang.yeah.net
现代微机原理与接口技术
53
class VSharedHardwareInt,public VHardwareInt
{
public:
VSharedHardwareInt( int irq,DWORD flags,
DWORD timeout,PVOID refdata) ;
virtual BOOL hook( ) ;
virtual BOOL OnSharedHardwareInt( VMHANDLE) ;
//中断处理程序
protected:
BYTE m_sthunk[SHWINTTHUNKSIZE];
private:
VSharedHardwareInt( void) ;
};
http://qsyang.yeah.net
现代微机原理与接口技术
54
下面我们使用 VsharedHardwareInt给一个 VxD的例子,该例子捕获鼠标中断。该例子也是用 VtoolsD生成的可动态加载的 VxD框架,然后在 VC6中修改的,我们只给出修改的部分。
// HARDINT.h - include file for VxD HARDINT
…
#define IRQ_NUM 12 //根据你的鼠标情况指定,COM1为 4,COM2为 3,PS/2
为 12
class HardintDevice,public VDevice
{
public:
virtual BOOLOnSysDynamicDeviceInit( ) ;
virtual BOOLOnSysDynamicDeviceExit( ) ;
};
…
class HardintInt,public VSharedHardwareInt
{
public:
HardintInt( ),VSharedHardwareInt( IRQ_NUM,0,0,0) {};
BOOL OnSharedHardwareInt( VMHANDLE hVM) ;
};
http://qsyang.yeah.net
现代微机原理与接口技术
55
// HARDINT.cpp - main module for VxD HARDINT
…
HardintInt* pshint;
…
BOOLHardintDevice:,OnSysDynamicDeviceInit( )
{
VMHANDLE hVM;
hVM=VMD_Get_Mouse_Owner( ) ;
dout<<"Mouse's VMHANDLE"<<( DWORD) hVM<<endl;
pshint=new( HardintInt) ;
if( pshint)
{
if( pshint->hook( ))
{
dout<<"shared interruppt hooked"<<endl;
}
else
{
dout<<"shared interruppt hook failed!"<<endl;
return FALSE;
}
}
http://qsyang.yeah.net
现代微机原理与接口技术
56
else return FALSE;
return TRUE;
}
BOOL HardintDevice:,OnSysDynamicDeviceExit( )
{
if( pshint)
{
if( pshint->unhook( ))
{
dout<<"shared interrupt unhooked"<<endl;
}
delete pshint;
}
return TRUE;
}
BOOL HardintInt:,OnSharedHardwareInt( VMHANDLE hVM)
{
static WORD count=0;
count++;
dout<<"hardware( Mouse) int count,"<<count<<endl;
return FALSE;
}
http://qsyang.yeah.net
现代微机原理与接口技术
57
热键类
class VHotKey
{
public:
VHotKey( BYTE scan,scanType_t st,
DWORD shift,DWORD flags,PVOID refData=0,
DWORD delay=0); //构造函数
~VHotKey() {unhook(); }; //析构函数
virtual VOID handler( BYTE scan,
keyAction_t ka,DWORD shift,PVOID refData,
DWORD elapased); //热键处理程序
BOOL hook(); //挂钩热键处理程序
BOOL unhook(); //摘钩热键处理程序
VOID localEnable( BOOL enable,VMHANDLE hVM);
//在指定的虚拟机中允许或禁止热键事件
VOID reflectToVM( VMHANDLE hVM,DWORD shift);
//指示 VxD把热键事件传到指定虚拟机中
static VOID cancelState(); //取消热键
http://qsyang.yeah.net
现代微机原理与接口技术
58
protected:
DWORD m_handle;
BYTE m_scanCode;
scanType_t m_scanType;
DWORD m_shiftState;
BYTE m_flags;
PVOID m_refData;
DWORD m_timeout;
BYTE m_thunk[HKTHUNKSIZE];
}
http://qsyang.yeah.net
现代微机原理与接口技术
59
下面这个例子截获 Ctrl+P键,当按下这两个键时,将弹出一个窗口,说明已经捕获。该例子也是用 VtoolsD生成的可动态加载的
VxD框架,然后在 VC6中修改的,我们只给出修改的部分。
// HOTKEY.h - include file for VxD HOTKEY
…
#define C_SCAN 0X19 //P键的扫描码
class HotkeyDevice,public VDevice
{
public:
virtual BOOL OnSysDynamicDeviceInit( ) ;
virtual BOOL OnSysDynamicDeviceExit( ) ;
};
…
class HotkeyHot,public VHotKey
{
public:
HotkeyHot ( ),VHotKey ( C_SCAN,SCAN_NORMAL,HKSS_Ctrl,
CallOnPress,"热键被按下 ! ",0) { };
void handler( BYTE scan,keyAction_t keyEvent,DWORD shift,
PVOID refData,
DWORD elapased) ;
};
http://qsyang.yeah.net
现代微机原理与接口技术
60
// HOTKEY.cpp - main module for VxD HOTKEY
…
HotkeyHot* pkey;
…
BOOL HotkeyDevice:,OnSysDynamicDeviceInit( )
{
pkey=new( HotkeyHot) ;
if( pkey)
{
if( pkey->hook( ))
{
dout<<"hot key hooked"<<endl;
}
else return FALSE;
}
else return FALSE;
return TRUE;
}
http://qsyang.yeah.net
现代微机原理与接口技术
61
BOOL HotkeyDevice:,OnSysDynamicDeviceExit( )
{
if( pkey)
{
if( pkey->unhook( ))
{
dout<<"hot key unhooked"<<endl;
}
delete pkey;
}
return TRUE;
}
void HotkeyHot:,handler( BYTE scan,keyAction_t keyEvent,
DWORD shift,PVOID
refData,DWORD elapased)
{
dout<<"entering handler"<<endl;
SHELL_Message ( Get_Cur_VM_Handle ( ),MB_OK,( char* )
refData,"CTRL+P Pressed",0,0,0) ; //显示一个消息框
pkey->reflectToVM( Get_Cur_VM_Handle( ),shift) ;
//将按键信息传送到当前虚拟机中
}