VxD入门教程
站长多次与丁凯联系,但邮件都被退回来了,可能他的邮箱不能用了罢。
1.背景知识
为了看懂本篇所给的例子,需要C, 汇编及Windows 设备驱动程序的相关知识。
2.开发工具
需要 Microsoft Visual C++ 2.0 以上版本,MASM 6.11C, 及Windows 95 DDK
(以下采用 VC++ 6.0 为例)
3.目的
利用以上所列的开发工具,编写一个动态装入的 VxD, 利用该VxD可以读取内存地址 0
处的中断向量表。
4.开始
第一步:
用 VC++ 新建一个工程,取名为 MiniVxd, 类型为 Win32 App 或 Console App
因为VC++不提供直接生成VxD的App Wizard,所以只好自己在以上两种App中选择一个,然后
再进行手工修改一下,需要修改的内容只有一处,即在 Link 的命令行上加上一个选项
/VXD
第二步:
新建一个空文件,在其中输入以下代码:
TITLE MINIVXD - By Ding Kai
.386p
include vmm.inc
MINIVXD_DYNAMIC EQU 1
; 定义设备驱动程序块 DDB, 由于是动态装入的,所以设备ID和装入顺序可以取未定义值.
DECLARE_VIRTUAL_DEVICE MINIVXD, 1, 0, MsgDispatch,\
UNDEFINED_DEVICE_ID, Undefined_Init_Order, 0, 0
VXD_LOCKED_CODE_SEG
; 定义消息派遣表,本例中只需要一条消息,即W32_DEVICEIOCONTROL,用于从Win32 App中利用
; DeviceIoControl API函数同本VxD进行通讯.
BeginProc MsgDispatch
Control_Dispatch W32_DEVICEIOCONTROL, W32DeviceIoControl, sCall, <ecx,ebx,esi>
clc
ret
EndProc MsgDispatch
VXD_LOCKED_CODE_ENDS
END
将文件存盘,文件名取为 VxdStub.asm, 然后用下列命令编译该文件:
Aml -coff -W2 -DBLD_COFF -DIS_32 -c -Cx -DMASM6 -I\95DDK\INC32 VxdStub.asm
这将会生成 vxdstub.obj,将此OBJ文件加入到工程文件中。
第三步:
创建一个 C 语言文件,文件名取为 MiniVxd.c,在文件中输入以下代码:
#define WIN40SERVICES
#pragma warning (disable:4229)
#include <string.h>
#define WANTVXDWRAPS
#include <basedef.h>
#include <vmm.h>
#include <debug.h>
#include <vwin32.h>
#include <winerror.h>
#include <vxdwraps.h>
#include <ifs.h>
#include <shell.h>
#pragma intrinsic(memcpy)
#pragma VxD_LOCKED_DATA_SEG
// 此处可以定义任何在VxD中需要的全局变量.
char AnyData[200];
#pragma VxD_LOCKED_CODE_SEG
///////////////////////////////////////////
DWORD __stdcall GetMemory( DWORD dwDDB, PDIOCPARAMETERS pD )
{
BYTE *p;
// 此处忽略了参数检查,实际应用中切不可如此 !!
p = (PBYTE)pD->lpvOutBuffer;
memcpy(p, 0, 1024); // 读取中断向量表,共 1024 字节
return 1024;
}
///////////////////////////////////////////////////////
/* Win32 interface */
///////////////////////////////////////////////////////
int __stdcall
W32DeviceIoControl( DWORD dwIoCtrlCode, /*ecx*/
DWORD dwDDB, /*ebx*/
DWORD pDIOCParams ) /*esi*/
{
PDIOCPARAMETERS pD;
pD = (PDIOCPARAMETERS)pDIOCParams;
if ( dwIoCtrlCode == DIOC_OPEN ||
dwIoCtrlCode == DIOC_CLOSEHANDLE)
return 0L;
// Init returned value
if (pD->lpcbBytesReturned)
*(DWORD *)pD->lpcbBytesReturned = 0;
if (dwIoCtrlCode==1) { // 1 = DeviceIoControl代码
GetMemory(dwDDB, pD);
}
else
return ERROR_NOT_SUPPORTED;
return 0;
}
将本文件加入到工程文件中.
第四步:
创建一个模块定义文件,此文件将要定义最终生成的VxD文件的段属性并输出设备驱动程序块,
输入下面的代码,并将文件存为 MiniVxd.def,同时将其加入到工程文件中.
VXD MINIVXD DYNAMIC
DESCRIPTION 'Written by Ding Kai'
SEGMENTS
_LTEXT CLASS 'LCODE' PRELOAD NONDISCARDABLE
_LDATA CLASS 'LCODE' PRELOAD NONDISCARDABLE
_TLS CLASS 'LCODE' PRELOAD NONDISCARDABLE
_BSS CLASS 'LCODE' PRELOAD NONDISCARDABLE
_ITEXT CLASS 'ICODE' DISCARDABLE
_IDATA CLASS 'ICODE' DISCARDABLE
_PTEXT CLASS 'PCODE' NONDISCARDABLE
_PDATA CLASS 'PDATA' NONDISCARDABLE SHARED
HEAPSIZE 10240
STACKSIZE 40960
EXPORTS
MINIVXD_DDB @1
当然,其中有些段在本程序中不存在,此处列出来是想将此文件做为一个模板以供以后使用。
第五步:
加入本工程文件需要的最后一个,VxdWarps.clb, 这个文件是DDK的LIB目录中.
第六步:
所需的四个文件已经全部加入完毕,它们是:
vxdstub.obj
minivxd.c
minivxd.def
vxdwarps.clb
在进行make之前请检查一下文件路径, 在 Include 中一定要包含 DDK 目录中的 INC32 目录.
确认无误后可以按 F7 键进行 Make 了。
结果会在 DEBUG 目录或 Release 目录 (依赖于工程文件的设置) 生成 MiniVxd.vxd 文件。
至此,一个小小的Vxd文件生成完毕, 可以在程序中用下面的代码与本VxD进行通讯.
BYTE buffer[1024];
DeviceIoControl(hVxd, 1, NULL, NULL, buffer, 1024, NULL, 0);
结果,当前的中断向量表就会出现在 buffer 数组中。
本文不再提供完整的测试程序,需要的话请与作者联系
5.小结
本文用一个简单的示例介绍了如何在 Windows 95 下编写可动态安装的 VxD, 这种方法及用这种方法编写的
VxD在Windows 98 下同样适用。然而,在 Windows NT 不能采用这种方法,有兴趣的朋友请关注本主页的最新更
新或与本人联系.
丁凯草书于一九九九年五月十六日