1、1Windows XP驱动程序编写方法驱动程序编写方法Step by Step2 本电子讲义可以作为几年前本人所写的本电子讲义可以作为几年前本人所写的驱动开发驱动开发上、下电子讲义的后续篇,主要是将开发平台从上、下电子讲义的后续篇,主要是将开发平台从Windows98/2000,DriverStudio 2.7升级到以下环境:升级到以下环境:1. 驱动程序的开发环境驱动程序的开发环境 以上四项中,前以上四项中,前3项为项为Microsoft公司产品,可以只用公司产品,可以只用2,3来开发驱动程序。为了方便起见,也可以使用第三来开发驱动程序。为了方便起见,也可以使用第三方的开发工具方的开发工具D
2、river Studio ,它将,它将DDK的内容封装成的内容封装成类,而且提供一个快速方便地生成驱动框架的工具。类,而且提供一个快速方便地生成驱动框架的工具。3.2版本可能是版本可能是Compuware公司推出的最后一个版本。公司推出的最后一个版本。3*通常,开发不同操作系统下的驱动程序需要不同的通常,开发不同操作系统下的驱动程序需要不同的DDK做支持:做支持:*本电子讲义假设大家已经会本电子讲义假设大家已经会VC编程及熟悉编程及熟悉VS IDE的使用。的使用。42. 驱动程序开发工具包驱动程序开发工具包DriverStudio2.1 DriverStudio 3.2所包含的工具所包含的工具
3、 VToolsD 是一个用来开发针对是一个用来开发针对Win9X (Windows 95 和和 Windows 98)操作系统下设备驱动程序操作系统下设备驱动程序(VxD)的工具。的工具。VToolsD 中包括生成驱动程序源代码的工具,中包括生成驱动程序源代码的工具,run-time 和和 interface 库,以及一些可以用来作为各种类型的设备驱动库,以及一些可以用来作为各种类型的设备驱动程序基础的驱动程序样本。程序基础的驱动程序样本。 DriverWorks提供针对提供针对Windows NT 4和和Win32驱动模型驱动模型(WDM)的的设备驱动程序开发的完全支持。设备驱动程序开发的完
4、全支持。DriverWorks中中包含一个非常完善的源代码生成工具包含一个非常完善的源代码生成工具(DriverWizard) 以及以及相应的类库和驱动程序样本,它提供了在相应的类库和驱动程序样本,它提供了在C+下进行设备下进行设备驱动程序开发的支持。它驱动程序开发的支持。它可以集成到可以集成到msvc6和和中中,还需要最新的,还需要最新的Windows DDK的支持。的支持。 5 DriverNetworks 是针对是针对Windows网络驱动开发人员网络驱动开发人员的一个模块。它的核心部分,是一个针对的一个模块。它的核心部分,是一个针对NDIS drivers 和和 TDI clients
5、 (DriverSockets)的的 C+ 的类库的类库。DriverNetworks 中也有中也有Quick Miniport Wizard 用用来直接开始一个来直接开始一个NDIS Miniport , ,Intermediate 或协议或协议驱动程序驱动程序工程。它可以让你在采用工程。它可以让你在采用DriverNetworks C+ 类库编写类库编写NDIS驱动程序的时候驱动程序的时候, ,快速的生成编译快速的生成编译、安装和调试所需要的所有文件、安装和调试所需要的所有文件 。它可以集成到。它可以集成到msvc6和和中,还需要最新的中,还需要最新的Windows DDK的的支持。支持。
6、 6 SoftICE 系列调试器包含了可以调试各种代码的多系列调试器包含了可以调试各种代码的多种工具。它可以调试诸如种工具。它可以调试诸如BIOS代码、中断例程以及代码、中断例程以及系统系统I/O。这些工具与强大的硬件调试板一起支持符。这些工具与强大的硬件调试板一起支持符号级调试,可以显示源码、全局或局部数据。其中:号级调试,可以显示源码、全局或局部数据。其中:7 DriverMonitor不仅可以显示不仅可以显示WDM和和VxD在操作系在操作系统核心层次输出的调试语句,还可以装载和卸载统核心层次输出的调试语句,还可以装载和卸载VxD驱动和驱动和NT4系统的驱动程序。系统的驱动程序。 这是一个
7、无需经过设备管理器或这是一个无需经过设备管理器或“添加新硬件添加新硬件”功功能就能为能就能为Windows 2000/XP动态加载和卸载动态加载和卸载WDM驱动驱动程序的小实用程序。程序的小实用程序。 用来设置设备驱动程序创建的环境。当我们用用来设置设备驱动程序创建的环境。当我们用Visual Studio(VC+)编译驱动程序源程序的时候,需要用)编译驱动程序源程序的时候,需要用SetDDKGo来设置环境变量,之后来设置环境变量,之后SetDDKGo会自动启会自动启动动Visual Studio(VC+)编译环境。)编译环境。8 这是这是DriverStudio以及用户工具的集成环境和宿主。
8、以及用户工具的集成环境和宿主。DS的大多数工具全部被集成到这个开发环境中。的大多数工具全部被集成到这个开发环境中。 它提供了参数验证和系统测试来检测和跟踪不同的设它提供了参数验证和系统测试来检测和跟踪不同的设备驱动程序与其他操作系统模块之间的交互。配置备驱动程序与其他操作系统模块之间的交互。配置 这是一个能让这是一个能让Windows NT/2000/XP设备驱动程序的设备驱动程序的编写者确定驱动程序性能瓶颈的性能分析工具。对于编写者确定驱动程序性能瓶颈的性能分析工具。对于编写设备驱动程序或核心代码的程序员,这很有用。编写设备驱动程序或核心代码的程序员,这很有用。 它能帮助程序员检测其代码的哪
9、部分被测试过,哪它能帮助程序员检测其代码的哪部分被测试过,哪部分还需要测试。可帮助程序员提高程序的稳定性。部分还需要测试。可帮助程序员提高程序的稳定性。92.2 DriverStudio 3.2的安装的安装 Intel x86兼容兼容系统或系统或X64系统(包含系统(包含IA64和和AMD64以以及及Itanium) Windows XP内存内存: 最少最少256MB,推荐使用推荐使用512 MB硬盘硬盘:完全安装需要完全安装需要大约大约182 MB针对针对 SoftICE的远程调试的远程调试: NE2000-兼容兼容网卡或网卡或 3Com 网卡网卡针对针对 DriverWorks: Micr
10、osoft XP DDK,Visual C+.NET10: 在安装在安装DriverWorks之前,首先要保证你的计算机之前,首先要保证你的计算机上已经安装了上已经安装了Microsoft Visual C+.NET以及以及Windows XP DDK。 11第二步:第二步:安装安装Windows XP DDK(Driver Development Kits)。)。1)在安装)在安装DDK的时候请选择完全安装。的时候请选择完全安装。 2)安装中,不需要安装安装中,不需要安装64BIT IA64Binaries 3)安装好后,对于)安装好后,对于 XP DDK不需要手动配置环境变量不需要手动配置
11、环境变量,只需在开始菜单中点击,只需在开始菜单中点击Checked Build Envirment 则则DDK会自动调用会自动调用setenv配置环境变量,并监测相应的配置环境变量,并监测相应的SDK以及以及Visual Studio.NET IDE 第一步:第一步: 安装安装Visual Studio C+.NET第三步:第三步: 安装安装DriverStudio 3.2(按照安装提示安装)。(按照安装提示安装)。12Driver Studio 3.2支持单机调试或双机调试两种模式。支持单机调试或双机调试两种模式。在安装的时候也有在安装的时候也有Host和和Target两种模式。两种模式。
12、单机调试需要在同一个机器中将单机调试需要在同一个机器中将Host和和Target两种两种模式都安装模式都安装 双机调试的时候需要在一个机器上安装双机调试的时候需要在一个机器上安装Host模式,模式,在另一个机器上安装在另一个机器上安装Target模式。模式。13:1)使用)使用DDK Build Setting工具定义工具定义BASEDIR环境变量环境变量并启动并启动MSVC.NET,14151617182)打开下列地址上的建立库文件工程)打开下列地址上的建立库文件工程VdwLibs2002.sln如果是如果是VS.NET2003, 则打开则打开 VdwLibs2003.sln193)选择选择
13、“生成生成-批生成批生成”,打开下面的窗口,从中,打开下面的窗口,从中选则需要编译的配置。选则需要编译的配置。 Checked是调试版本,是调试版本,Free是发布版本是发布版本204)点击点击“重新重新生成生成”编译所选择的库文件。编译所选择的库文件。213.Driver Works的使用的使用2223工程文件名工程文件名工程文件目录工程文件目录24选择驱动类型选择驱动类型选择框架类型选择框架类型25创建功能驱动程序创建功能驱动程序创建过滤器驱动程序创建过滤器驱动程序26选择相应总线选择相应总线本例不驱动硬件本例不驱动硬件27选择需要选择需要处理的消处理的消息句柄息句柄28添加和应用程序之添
14、加和应用程序之间通信的控制代码间通信的控制代码2930313233343536373839驱动类驱动类设备类设备类队列管理类队列管理类40驱动类文件驱动类文件设备类文件设备类文件测试用的控制测试用的控制台程序文件台程序文件驱动安装驱动安装指导文件指导文件队列管理类队列管理类41 此时已经具备了一个驱动程序以及做测试此时已经具备了一个驱动程序以及做测试用的应用程序的基本框架,我们可以在用的应用程序的基本框架,我们可以在VC集集成环境下修改有关程序,增加相关的具体操成环境下修改有关程序,增加相关的具体操作代码,然后就可以编译和调试了。作代码,然后就可以编译和调试了。42 该驱动程序框架包含了几个最
15、基本的类,这些类是:该驱动程序框架包含了几个最基本的类,这些类是:class SampleDriver : public KDriver SAFE_DESTRUCTORSpublic: virtual NTSTATUS DriverEntry(PUNICODE_STRING RegistryPath); virtual NTSTATUS AddDevice(PDEVICE_OBJECT Pdo); virtual VOID Unload(VOID); void LoadRegistryParameters(PUNICODE_STRING RegistryPath);protected: int
16、 m_Unit;43class SampleDevice : public KPnpDevice public:SAFE_DESTRUCTORS;SampleDevice(PDEVICE_OBJECT Pdo, ULONG Unit);SampleDevice();VOID Invalidate(void);DEVMEMBER_DISPATCHERSvirtual NTSTATUS OnStartDevice(KIrp I);virtual NTSTATUS OnStopDevice(KIrp I);virtual NTSTATUS OnRemoveDevice(KIrp I);virtual
17、 NTSTATUS OnDevicePowerUp(KIrp I);virtual NTSTATUS OnDeviceSleep(KIrp I);virtual NTSTATUS DefaultPnp(KIrp I);virtual NTSTATUS DefaultPower(KIrp I);void LoadRegistryParameters(); 44void SerialRead(KIrp I);void SerialWrite(KIrp I);NTSTATUS SAMPLE_IOCTL_Read_Handler(KIrp I);NTSTATUS SAMPLE_IOCTL_Write_
18、Handler(KIrp I);NTSTATUS SAMPLE_IOCTL_ReadWrite_Handler(KIrp I);protected:KPnpLowerDevicem_Lower;sampleQueueReadQueue;sampleQueueWriteQueue;#ifdef _COMMENT_ONLYvirtual NTSTATUS Create(KIrp I); virtual NTSTATUS Close(KIrp I);virtual NTSTATUS Read(KIrp I);virtual NTSTATUS Write(KIrp I);virtual NTSTATU
19、S DeviceControl(KIrp Ivirtual NTSTATUS SystemControl(KIrp I); #endif ;45由于一个可能是由于一个可能是DriverStudio 3.2中的中的BUG,所以及时所以及时生成的一个空工程项目也无法编译通过,需要对生成生成的一个空工程项目也无法编译通过,需要对生成的工程文件做以下手工修改:的工程文件做以下手工修改:把把sample项目中的项目中的sources文件中的文件中的: 这一行去掉就可以编译通过了这一行去掉就可以编译通过了 46先编译驱动先编译驱动程序工程程序工程在在VS2002的集成环境中的集成环境中下面我们讲解编译、执
20、行和调试这个驱动程序。下面我们讲解编译、执行和调试这个驱动程序。生成目生成目标文件标文件47确认生成的确认生成的是驱动程序是驱动程序48在在VS2002的集成环境中的集成环境中生成目生成目标文件标文件再编译测试应再编译测试应用程序工程用程序工程49确认生成的是测确认生成的是测试用应用程序试用应用程序50 下面使用下面使用DriverStudio带的工具加载驱动程序和查看带的工具加载驱动程序和查看调试信息。调试信息。驱动程序监视,可实驱动程序监视,可实时看到驱动程序发出时看到驱动程序发出的调试输出语句的调试输出语句驱动程序装载驱动程序装载器,可动态调器,可动态调用驱动程序用驱动程序5152为了防
21、止其他驱动程为了防止其他驱动程序的干扰,在序的干扰,在Filter Message对话框中设对话框中设置消息过滤规则,只置消息过滤规则,只让有让有sample的消息通的消息通过。过。535455565758YANGQS59DriverStudio 3.2给出的驱动测试软件是一个给出的驱动测试软件是一个Win32的窗的窗口程序,而不是先前版本的控制台程序。为了在调试口程序,而不是先前版本的控制台程序。为了在调试输出的时候有所区别我们将测试程序的调试输出语句输出的时候有所区别我们将测试程序的调试输出语句的句头由原来的的句头由原来的sample:改成改成sampleAPP: (在在sampleAPP
22、.cpp文件中文件中)VOID sampleOutputText(LPCTSTR Format, .) TCHAR strMAX_STRING_LENGTH; va_list vaList; va_start(vaList, Format); _vstprintf(str, Format, vaList); OutputDebugString(_T( ); OutputDebugString(str); OutputDebugString(_T(n); va_end(vaList); return;60运行编译好的运行编译好的sampleAPP.exe6162如果在执行如果在执行sampleA
23、PP.exe之前,驱动程序之前,驱动程序sample.sys还没有加载到内存中,则在还没有加载到内存中,则在DriverMonitor程序中就可程序中就可以看到以下信息:以看到以下信息:6364656667 下面我们来修改有关代码,以便增加驱动程序和应下面我们来修改有关代码,以便增加驱动程序和应用程序之间相互通信的内容。需要增加的内容包括:用程序之间相互通信的内容。需要增加的内容包括:a. 使用使用Read和和Write方式分别从驱动程序读入字符和方式分别从驱动程序读入字符和 向驱动程序写字符。向驱动程序写字符。b. 使用使用IO控制代码方式分别从驱动程序读入字符和控制代码方式分别从驱动程序读
24、入字符和 向驱动程序写字符。向驱动程序写字符。c. 使用使用IO控制代码方式向驱动程序写字符串再从驱动控制代码方式向驱动程序写字符串再从驱动程序中读出该字符串,并返回反馈串信息。程序中读出该字符串,并返回反馈串信息。 :程序中:程序中是我们添加或修改过的语句是我们添加或修改过的语句,其他是,其他是DriverWorks自动生成的。自动生成的。是要删除是要删除的语句。省略号的部分是不变的。语句中的语句。省略号的部分是不变的。语句中T.Trace(TraceInfo, _FUNCTION_“xxxx”)这样的语句是向调试软件输出信息,这样的语句是向调试软件输出信息,该信息可在该信息可在Driver
25、Monitor或其他调试监视器中看到。或其他调试监视器中看到。68a.1 使用使用Read方式读方式读void SampleDevice:SerialRead(KIrp I)T.Trace(TraceInfo, _FUNCTION_+. IRP %pn, I);NTSTATUS status= STATUS_SUCCESS;PUCHARpBuffer= (PUCHAR) I.BufferedReadDest();ULONG readSize = I.ReadSize( ); ULONG bytesRead = 0;I.Information() = bytesRead;I.Status() =
26、 status;m_DriverManagedQueue.PnpNextIrp(I);6970ULONG sampleExecuteIo(HWND hDlg) PSAMPLE_LIST_ITEM ioItem; GetDlgItemText(hDlg, IDC_OUT_SIZE_EDIT, str, MAX_STRING_LENGTH); ioItem-OutSize = _ttol(str); hWnd = GetDlgItem(hDlg, IDC_OP_TYPE_COMBO); itemIndex = (DWORD)SendMessage(hWnd, CB_GETCURSEL, 0, 0)
27、; SendMessage(hWnd, CB_GETLBTEXT, (WPARAM)itemIndex, (LPARAM)str); if (!_tcscmp(str, _T(“ReadFile”) & (ioItem-OutSize 0) ioItem-OutBuffer = (PCHAR)malloc(ioItem-OutSize);71 if (!ReadFile( g_hDevice, ioItem-OutBuffer, ioItem-OutSize, NULL, &ioItem-IoOverlapped) & (GetLastError() != ERROR_IO_PENDING)
28、error = GetLastError(); sampleOutputText(_T(ReadFile failed with error (%d), error); break; ioItem-Callback = sampleReadCompleteCallback; 72VOID sampleReadCompleteCallback(PVOID Context) PSAMPLE_LIST_ITEM ioItem = (PSAMPLE_LIST_ITEM)Context; sampleOutputText( _T(Executed ReadFile: buffer size (%d),
29、return length (%d) error (%d) ), ioItem-OutSize, ioItem-ReturnLength, ioItem-Error); sampleOutputBuffer(ioItem-OutBuffer, ioItem-ReturnLength); free(ioItem-OutBuffer); CloseHandle(ioItem-IoOverlapped.hEvent); free(ioItem); return;7374a.2 使用使用Write方式写方式写void SampleDevice:SerialWrite(KIrp I)T.Trace(Tr
30、aceInfo, _FUNCTION_+. IRP %pn, I);NTSTATUS status = STATUS_SUCCESS;PUCHAR pBuffer = (PUCHAR)I.BufferedWriteSourceULONG writeSize = I.WriteSize( );ULONG bytesSent = 0;I.Information() = bytesSent;I.Status() = status;m_DriverManagedQueue.PnpNextIrp(I);7576ULONG sampleExecuteIo(HWND hDlg) PSAMPLE_LIST_I
31、TEM ioItem; GetDlgItemText(hDlg, IDC_IN_DATA_EDIT, str, MAX_STRING_LENGTH); hWnd = GetDlgItem(hDlg, IDC_OP_TYPE_COMBO); itemIndex = (DWORD)SendMessage(hWnd, CB_GETCURSEL, 0, 0); SendMessage(hWnd, CB_GETLBTEXT, (WPARAM)itemIndex, (LPARAM)str);77if (!_tcscmp(str, _T(“ReadFile”) & (ioItem-OutSize 0) io
32、Item-InBuffer = (PCHAR)malloc(ioItem-InSize); if (!WriteFile(g_hDevice,ioItem-InBuffer,ioItem-InSize,NULL, &ioItem-IoOverlapped) &(GetLastError() != ERROR_IO_PENDING) error = GetLastError(); sampleOutputText(_T(WriteFile failed with error (%d), error); break; ioItem-Callback = sampleWriteCompleteCal
33、lback; 7879b.1 使用使用IO控制代码方式读控制代码方式读NTSTATUS sampleDevice:SAMPLE_IOCTL_Read_Handler(KIrp I) T.Trace(TraceInfo, _FUNCTION_+. IRP %pn, I); NTSTATUS status = STATUS_SUCCESS; ULONG inputSize = I.IoctlInputBufferSize(); ULONG outputSize = I.IoctlOutputBufferSize();80 T.Trace(NT_SUCCESS(status)?TraceInfo:T
34、raceWarning, _FUNCTION_-. IRP %p, STATUS %xn, I, status); return status;81ULONG sampleExecuteIo(HWND hDlg) PSAMPLE_LIST_ITEM ioItem; if (!_tcscmp(str, _T(SAMPLE_IOCTL_Read) & (ioItem-OutSize 0) | (ioItem-InSize 0) if (ioItem-OutSize 0) ioItem-OutBuffer = (PCHAR)malloc(ioItem-OutSize); 82 if (!Device
35、IoControl( g_hDevice, SAMPLE_IOCTL_Read, ioItem-InBuffer, ioItem-InSize, ioItem-OutBuffer, ioItem-OutSize, NULL, &ioItem-IoOverlapped) & (GetLastError() != ERROR_IO_PENDING) error = GetLastError(); sampleOutputText(_T(SAMPLE_IOCTL_Read failed with error (%d), error); break; ioItem-Callback = sampleS
36、AMPLE_IOCTL_ReadCompleteCallback; 83VOID sampleSAMPLE_IOCTL_ReadCompleteCallback(PVOID Context) PSAMPLE_LIST_ITEM ioItem = (PSAMPLE_LIST_ITEM)Context; sampleOutputText( _T(“Executed SAMPLE_IOCTL_Read request: in buffer size (%d), out buffer size(%d), return length (%d) error (%d) ), ioItem-InSize, i
37、oItem-OutSize, ioItem-ReturnLength, ioItem-Error, );8485b.2 使用使用IO控制代码方式写控制代码方式写NTSTATUS sampleDevice:SAMPLE_IOCTL_Write_Handler(KIrp I) T.Trace(TraceInfo, _FUNCTION_+. IRP %pn, I); NTSTATUS status = STATUS_SUCCESS; ULONG inputSize = I.IoctlInputBufferSize(); ULONG outputSize = I.IoctlOutputBufferSi
38、ze(); 86 T.Trace(NT_SUCCESS(status)?TraceInfo:TraceWarning, _FUNCTION_-. IRP %p, STATUS %xn, I, status);return status;87ULONG sampleExecuteIo(HWND hDlg) PSAMPLE_LIST_ITEM ioItem; GetDlgItemText(hDlg, IDC_IN_DATA_EDIT, str, MAX_STRING_LENGTH); hWnd = GetDlgItem(hDlg, IDC_OP_TYPE_COMBO); itemIndex = (
39、DWORD)SendMessage(hWnd, CB_GETCURSEL, 0, 0); SendMessage(hWnd, CB_GETLBTEXT, (WPARAM)itemIndex, (LPARAM)str);88if (!_tcscmp(str, _T(“SAMPLEIOCTL_Write”) & (ioItem-OutSize 0) | (ioItem-InSize 0)/ ioItem-InBuffer = (PCHAR)malloc(ioItem-InSize); if (!DeviceIoControl(g_hDevice, SAMPLE_IOCTL_Write, ioIte
40、m-InBuffer, ioItem-InSize, ioItem-OutBuffer, ioItem-OutSize, NULL, &ioItem-IoOverlapped) & (GetLastError() != ERROR_IO_PENDING) ioItem-Callback = sampleSAMPLEIOCTL_WriteCompleteCallback; 8990c. 使用使用IO控制代码方式写并且读控制代码方式写并且读NTSTATUS sampleDevice:IOCTL_ReadWrite_Handler(KIrp I) Trace(TraceInfo, _FUNCTION
41、_+. IRP %pn, I); NTSTATUS status = STATUS_SUCCESS; ULONG inputSize = I.IoctlInputBufferSize(); ULONG outputSize = I.IoctlOutputBufferSize(); 91T.Trace(NT_SUCCESS(status)?TraceInfo:TraceWarning, _FUNCTION_-. IRP %p, STATUS %xn, I, status);return status;92ULONG sampleExecuteIo(HWND hDlg) PSAMPLE_LIST_
42、ITEM ioItem; GetDlgItemText(hDlg, IDC_IN_DATA_EDIT, str, MAX_STRING_LENGTH); hWnd = GetDlgItem(hDlg, IDC_OP_TYPE_COMBO); itemIndex = (DWORD)SendMessage(hWnd, CB_GETCURSEL, 0, 0); SendMessage(hWnd, CB_GETLBTEXT, (WPARAM)itemIndex, (LPARAM)str);93if (!_tcscmp(str, _T(“IOCTL_ReadWrite”) & (ioItem-OutSi
43、ze 0) | (ioItem-InSize 0) ioItem-InBuffer = (PCHAR)malloc(ioItem-InSize); if (!DeviceIoControl(g_hDevice, IOCTL_ReadWrite, ioItem-InBuffer, ioItem-InSize, ioItem-OutBuffer, ioItem-OutSize, NULL, &ioItem-IoOverlapped) & (GetLastError() != ERROR_IO_PENDING) ioItem-Callback = sampleIOCTL_ReadWriteCompl
44、eteCallback; 94VOID sampleIOCTL_ReadWriteCompleteCallback(PVOID Context) PSAMPLE_LIST_ITEM ioItem = (PSAMPLE_LIST_ITEM)Context; sampleOutputText( _T(Executed IOCTL_ReadWrite request: in buffer size (%d), out buffer size (%d), return length (%d) error (%d) ), ioItem-InSize, ioItem-OutSize, ioItem-Ret
45、urnLength,ioItem-Error ); 9596 DriverStudio提供了提供了KIoRange类来将外部总线的类来将外部总线的I/O地地址空间范围映射到处理器总线的地址空间范围。址空间范围映射到处理器总线的地址空间范围。 构造函数构造函数 (4 种格式种格式) 初始化和重新初始化一个实例初始化和重新初始化一个实例 (3种格式种格式) 析构函数析构函数 从已初始化状态删除该对象从已初始化状态删除该对象 测试该对象是否已经初始化测试该对象是否已经初始化读一个或多个字节读一个或多个字节 (2 种形式种形式)写一个或多个字节写一个或多个字节 (2 种形式种形式)读一个或多个字读一个
46、或多个字 (2 种形式种形式)写一个或多个字写一个或多个字 (2 种形式种形式) 读一个或多个双字读一个或多个双字 (2 种形式种形式) 写一个或多个双字写一个或多个双字 (2 种形式种形式)97FORM 3 (WDM):KIoRange( ULONGLONG CpuPhysicalAddress, BOOLEAN InCpuIoSpace, ULONG Count, BOOLEAN MapToSystemVirtual =TRUE);FORM 4 (WDM): ()KIoRange( PCM_RESOURCE_LIST pTranslatedResourceList, ULONG Ordin
47、al=0, BOOLEAN MapToSystemVirtual =TRUE);FORM 5 (WDM):KIoRange( PCM_RESOURCE_LIST pTranslatedResourceList, PCM_RESOURCE_LIST pRawResourceList, ULONG Ordinal=0, BOOLEAN MapToSystemVirtual =TRUE);构造构造 KIoRange类。类。98 FORM 2 (WDM):NTSTATUS Initialize( ULONGLONG CpuPhysicalAddress, BOOLEAN InCpuIoSpace, U
48、LONG Count, BOOLEAN MapToSystemVirtual=TRUE);FORM 3 (WDM): ()NTSTATUS Initialize( PCM_RESOURCE_LIST pTranslatedResourceList, ULONG Ordinal=0, BOOLEAN MapToSystemVirtual =TRUE);FORM 4 (WDM):Initialize( PCM_RESOURCE_LIST pTranslatedResourceList, PCM_RESOURCE_LIST pRawResourceList, ULONG Ordinal=0, BOO
49、LEAN MapToSystemVirtual =TRUE);初始化或重新初始化初始化或重新初始化KIoRange的实例。的实例。99FORM 1:UCHAR inb( ULONG ByteOffset );FORM 2:VOID inb( ULONG ByteOffset, PUCHAR Buffer, ULONG Count);从映射空间读一个或多个字节。从映射空间读一个或多个字节。100FORM 1:VOID outb( ULONG ByteOffset, UCHAR Data );FORM 2:VOID outb( ULONG ByteOffset, PUCHAR Buffer, UL
50、ONG Count );101 写端口(写端口( 索引信息索引信息, 地址地址70H)m_ParPortIos.outb(0,0 x02); 读端口(读分钟信息,地址读端口(读分钟信息,地址71H)UCHAR data = m_ParPortIos.inb(1);下面我们来访问下面我们来访问CMOS的数据。的数据。 首先定义类首先定义类KIoRange的一个实例的一个实例,以定义相关地址空,以定义相关地址空间。间。KIoRange m_ParPortIos; 初始化实例(指定初始化实例(指定CMOS的端口首地址,并映射)的端口首地址,并映射)status = m_ParPortIos.Init