|
|
浅谈 VxD 回调 Win32 应用程序
作者:赵世平
Windows 95 / 98 的虚拟外壳设备( Virtual Shell Device )提供了 VxD 直接回调 Win16 应用程序函数的 VxD 服务,但是没有提供 VxD 直接回调 Win32 应用程序的 VxD 服务。不过 Windows 95 / 98 还是提供了两种 VxD 回调 Win32 应用程序的方法。方法之一是使用 VWIN32.VXD 提供的“异步过程调用( APC )”功能。 Win32 应用程序首先动态加载 VxD ,并使用 DeviceIoControl 函数将回调函数的地址传递给 VxD ,然后 Win32 应用程序调用 SleepEx / WaitForMultipleObjectsEx / WaitForSingleObjectEx 函数,将 Win32 应用程序自身置为“挂起”状态,这时 VxD 可以通过 VWIN32.VXD 提供的 _VWIN32_QueueUserApc 服务调用 Win32 应用程序的回调函数。该方法较简单,目前大多数回调 Win32 应用程序的 VxD 均使用该方法[例如瑞星杀毒软件( RAV )的实时监控 VxD ( RAV_IO.VXD )即使用该方法回调 Win32 查毒/杀毒程序],《 Windows 95 System Programming 4 》一书的配套光盘中有一个名为 IFSMONITOR 的实例程序详细讲述了该方法,由于该书的配套光盘在国内很多 FTP 服务器上都可以找到,此处就不再详述了。
方法之二是一种比较灵活的方法,这种方法充分利用了 Win32 应用程序的多线程特点和线程间通信的事件机制。 Win32 应用程序设置两个线程并定义一个事件,主线程负责动态加载/卸载 VxD 和通过 DeviceIoControl 函数与 VxD 通信,辅助线程通过 ResetEvent 函数和 WaitForSingleObject / WaitForSingleObjectEx 函数暂时挂起, VxD 可以通过 VWIN32.VXD 提供的 Win32 事件服务中的 _VWIN32_SetWin32Event 服务唤醒辅助线程,从而间接实现 VxD 回调 Win32 应用程序。由于 VWIN32.VXD 提供了与 Win32 API 几乎完全对应的 Win32 事件服务,所以该方法极其灵活,甚至可以通过定义两个事件实现 VxD 在回调 Win32 应用程序时与 Win32 应用程序完全同步。
笔者为了验证上述方法,编写了一个动态加载/卸载 VxD 的 Win32 应用程序和一个回调 Win32 应用程序的 VxD 。其中 Win32 应用程序用 Delphi 5.0 编写,选用 Delphi 5.0 的原因是 Delphi 5.0 实现多线程非常容易,而且不必将大量代码用在 Win32 应用程序界面上; VxD 使用 VToolsD 2.03 编写,是一个挂接实时钟中断( IRQ 8 )的 VxD ,该 VxD 参照 VToolsD 2.03 中的 CHIME 实例程序编写。程序代码如下:
Win32 应用程序工程文件( TMR_TEST.DPR ):
program TMR_TEST;
uses
Forms,
TT_MAIN in 'TT_MAIN.pas' {TimerTestMain},
TMR_CLBK in 'TMR_CLBK.pas';
{$R *.RES}
begin
Application.Initialize;
Application.CreateForm(TTimerTestMain, TimerTestMain);
Application.Run;
end.
Win32 应用程序主窗体/主线程( TT_MAIN.PAS ):
unit TT_MAIN;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
Menus, SyncObjs, TMR_CLBK, StdCtrls;
type
TOpenVxDHandle=function(hSource:THandle):THandle;stdcall;
TTimerTestMain = class(TForm)
MainMenu1: TMainMenu;
File1: TMenuItem;
Exit1: TMenuItem;
Callback1: TMenuItem;
Start1: TMenuItem;
Label1: TLabel;
procedure FormShow(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure Exit1Click(Sender: TObject);
procedure Start1Click(Sender: TObject);
private
{ Private declarations }
Handle1:THandle;
TimerCallback1:TTimerCallback;
public
{ Public declarations }
end;
const
TIMER_DIOC_SET_VXD_EVENT=101;
var
TimerTestMain: TTimerTestMain;
implementation
{$R *.DFM}
procedure TTimerTestMain.FormShow(Sender: TObj
网友评论:(评论内容只代表网友观点,与本站立场无关!) |
阅读排行
没有相关文章
|