对象编程方法的方便与快捷,因此仅就该点而言,使用DDK是不方便的。
4.VxD程序设计实例
我在开发可视电话音频卡的设计过程中,用VToolsD 2.03、VC++ 5.0为自制的PC/XT总线扩展卡开发了虚拟设备驱动程序Audcard.vxd。该卡每20ms申请一次中断,中断由应用程序动态载入系统的Audcard.vxd响应并加以处理。中断服务程序ISR(Interrupt Service Routine)结束后,调用函数Shell_PostMessage( )向应用程序窗口发送自定义消息。应用程序接受消息后,再通过函数DeviceIoControl( )与VxD的接口函数OnW32DeviceIoControl( )互传缓冲区数据。程序结束即可动态卸载VxD。下图表示在Win 95下VxD对硬件中断的处理过程。
图Win95下硬件中断的处理过程
当中断发生时,处理器转换为ring0级保护模式。Windows系统并不像DOS那样通过中断描述符表IDT(Interrupt Descriptor Table)直接指向中断处理过程,而是由IDT入口指向VMM中的程序。该程序将判断是否为中断调用,如果是,则把中断控制权交给虚拟可编程中断控制器VPICD(Virtual Programmable Interrupt Controller Device),VPICD实际上是一个重要的VxD。VPICD再将其交给另一个注册了该中断的VxD(如Audcard.vxd)来处理。VxD程序是通过调用VPICD服务VPICD_Virtualize_IRQ来
注册中断的。
虚拟设备驱动程序Audcard.vxd的部分源代码Audcard.h和Audcard.cpp在网上,网址为:www.pccomputing.com.cn。此应用程序使用了下列函数:CreateFile()动态加载VxD、CloseHandle()并动态卸载VxD、PreTranslateMessage()截获消息、DeviceIoControl()与VxD互传缓冲区数据。虚拟设备驱动程序Audcard.vxd经调试后工作正常,未发生过任何丢失数据或死机的现象。
下面是虚拟设备驱动程序Audcard.vxd的部分源代码Audcard.h和Audcard.cpp,限于篇幅,由QuickVxD自动生成的Audcard.mak未列出。
①Audcard.h
//AUDCARD.h - include file for VxD AUDCARD
#include
#define DEVICE_CLASS AudcardDevice
#define AUDCARD_DeviceID UNDEFINED_DEVICE_ID
#define AUDCARD_Init_Order UNDEFINED_INIT_ORDER#define AUDCARD_Major
#define AUDCARD_Minor 0
#define MY_IRQ 5 //定义5号中断
class MyHwInt:public VHardwareInt
{
public:
MyHwInt():VHardwareInt(MY_IRQ,0,0,0){}
virtual VOID OnHardwareInt(VMHANDLE);
};
class AudcardDevice : public VDevice
{
public:
virtual BOOL OnSysDynamicDeviceInit();
virtual BOOL OnSysDynamicDeviceExit();
virtual DWORD OnW32DeviceIoControl(PIOCTLPARAMS pDIOCParams);
MyHwInt* pMyIRQ;
};
class AudcardVM : public VVirtualMachine
{
public:
AudcardVM(VMHANDLE hVM);
};
class AudcardThread : public VThread
{
public:
AudcardThread(THREADHANDLE hThread);
};
②Audcard.cpp
//AUDCARD.cpp - main module for VxD AUDCARD
#define DEVICE_MAIN
#include "audcard.h"
Declare_Virtual_Device(AUDCARD)
#define WM_USER_POSTVXD 0x1000 //自定义消息
#undef DEVICE_MAIN
AudcardVM::AudcardVM(VMHANDLE hVM) : VVirtualMachine(hVM) {}
AudcardThread::AudcardThread(THREADHANDLE hThread) : VThread(hThread) {}
BOOL AudcardDevice::OnSysDynamicDeviceInit() //动态加载时初始化
{
//硬件初始化
pMyIRQ=new MyHwInt();
if(pMyIRQ&&pMyIRQ->hook()) //挂接中断
{
pMyIRQ->physicalUnmask