• <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>
  • C++語言的VxD與外界通信的所有接口

    發表于:2007-07-04來源:作者:點擊數: 標簽:
    北京信息工程學院 馬文曉 一、什么是VxD 從多任務操作系統Windows 3 ?1 起, 計算機中的任一物理設備x 可同時被基于Dos 或Windows 的多個進程使用, 這種一對多的關系稱為“設備虛擬化”, 各進程通過運行在核心層的VxD( 虛擬x 設備驅動程序) 存取物理設備x。操
    北京信息工程學院 馬文曉

      一、什么是VxD

      從多任務操作系統Windows 3 ?1 起, 計算機中的任一物理設備x 可同時被基于Dos 或Windows 的多個進程使用, 這種一對多的關系稱為“設備虛擬化”, 各進程通過運行在核心層的VxD( 虛擬x 設備驅動程序) 存取物理設備x。操作系統提供給用戶的軟件服務也可以用VxD 實現。計算機中的其他資源, 如CPU、內存等也可同時被多個進程使用, 各進程在系統提供的虛擬機(VM) 環境下存取這類資源。
      VxD 可由虛擬機管理器(VMM) 在開機時裝入核心層( 稱靜態裝入, 即置VxD 于c:\windows\system 目錄下, 在c:\windows\system.ini 文件中, 對節[386Enh] 加一行“device= 此VxD 文件名"), 或由應用程序實時裝入( 稱動態裝入), 而后, 各進程便可存取鎖定在內存中的VxD 數據區, 以實時控制VxD 的行為,VxD 的內部結構可防止兩個進程同時存取其數據區。VxD 通過響應VMM 發給它的事件與外界交互。

      Windows 95 中, 基于Dos 的每個進程在單獨的VM 中運行( 稱在V86 模式下運行), 既可按Dos 單進程方式, 在640k 低內存中運行( 稱在實模式下運行), 又可利用多進程環境的優點, 在整個內存中運行( 稱在保護模式下運行), 通過95 的DPMI 接口存取內存高端的Windows 圖形環境。其他16 位或32 位應用程序均在同一系統VM 中運行。

      下面只討論95 環境下的VxD。

      二、VxD 的創建

      1. 由匯編語言創建VxD: 需安裝微軟公司的Win32 SDK 及DDK。
      2. 由C 或C ++語言創建VxD: 需安裝VC2.0 或BC4.0, 及Vireo Software 公司的VToolsD 軟件包。

      VToolsD 含3 個實用工具: 可創建VxD 框架的QuickVxD; 可動態裝卸VxD 的VxD Loader; 可顯示內存VxD 特性的VxD Viewer。

      QuickVxD 含7 個對話頁:

      (1) Device Parameters 頁

      包括最多8 個字符的VxD 名, 唯一標識號(ID), 相對其他VxD 的裝入順序(VxD Viewer 可顯出某VxD 的裝入順序值Init Order, 若指定新VxD 的裝入順序小于此Init Order, 則新VxD 將在此VxD 前被裝入), 實現語言(C 或C ++) 靜、動態裝入方式等。

      (2) VxD Services 頁

      可被其他VxD 訪問的接口( 稱為VxD 服務), 要求本VxD 的ID>0, 且未與內存各VxD 的ID 值沖突。

      此ID 可向微軟公司申請, 也可使用Vireo 公司的VIREO_TEST_ID(3180h)。下稱此類ID 為接口ID。

      (3) API 頁

      可被應用程序在實模式/V86 模式下、保護模式下、DPMI 的實模式/V86 模式下、DPMI 的保護模式下訪問的接口( 統稱應用接口), 前兩者要求本VxD 提供接口ID, 后兩者只要求本VxD 提供以0 結尾的唯一標識串; 訪問前, 先要靜態或動態裝入本VxD( 第4 者要求靜態裝入)。

      第1、3 者可被普通匯編程序訪問, 第2、4 者可被在BC 的Windows 3 ?x(16) 平臺上生成的Windows 程序訪問。

      (4) Control Messages 頁

      對出現在Windows 3 ?1 及Windows 95 中各消息的響應, 如靜態裝入時的DTNAMIC_INIT 消息。

      (5) Windows95 Control Messages 頁

      對只出現在Windows 95 中各消息的響應, 如動態裝入時的SYS_DYNAMIC_INIT 消息。

      (6) 用C ++實現VxD 時的Classes 頁

      從虛擬設備驅動程序類VDevice 派生的類名( 如MyDevice), 此類的成員函數將接收(4) 及(5) 頁中出現的大多數消息。

      從VM 實例類VVirtualMachine 派生的類名( 如MyVM), 此類的成員函數將接收貫穿在VM 生命期中的各消息, 如系統VM 初啟消息Sys_VM_Init;

      從線程實例類VThread 派生的類名( 如MyThread)。此類的成員函數將接收貫穿在線程生命期中的各消息, 如新線程初啟消息THREAD_INIT。

      (7) Output Files 頁

      體現以上內容的3 個VxD 文件(.h,.c 或.cpp,.mak) 將被存放的目錄位置。

      三、C ++語言的VxD

      與外界通信的所有接口
      我們將簡要實現my ?VxD 的應用接口及服務, 它們均作為類的函數成員, 存于my ?h,my ?cpp 中。

      1 ?被32 位C 應用程序訪問的接口

      應用程序先用CreateFile 打開VxD, 后用DeviceIoControl 使VMM 發送W32_DEVICEIOCONTROL 消息給VxD:

       HANDLE h;char ibuf[2],obuf[2];
       BOOL r;DWORD oc;OVERLAPPED o;
       h=CreateFile("\\\\.\\my.vxd",0,0,0,0,
       FILE_FLAG_DELETE_ON_CLOSE,0);
       // 打開靜態my ?VxD, 或動態裝入my ?VxD
       r=DeviceIoControl(h, 命令碼C,ibuf,sizeof(ibuf),
        obuf,sizeof(obuf), &oc,NULL 或&o);
       / *與my ?VxD 的事件過程OnW32DeviceIoControl
       交換數據, 用ibuf 向VxD 傳數據,
       用obuf 從VxD 取數據,VxD 傳回的數據
       總量放在oc 中*/
      CloseHandle(h);// 關閉或動態卸下VxD
      my ?VxD 應在Windows 95 control messages 頁上選
       W32_DEVICEIOCONTROL 事件, 在DWORD
       MyDevice::OnW32DeviceIoControl(PIOCTLPARAMS p)
       事件過程中寫:
      switch(p ->dioc_IOCtlCode){
      case 命令碼C:
      用p 指向的IOCTLPARAMS 結構,
       與應用程序交換數據;
       if ( 成功) return(0); / *使DeviceIoControl 的
       返回值r 為TRUE */
       else return(1);
      default:
       return(0);
    }
      以上做法要求VxD 立即交換數據( 同步通訊), 值FILE_FLAG_DELETE_ON_CLOSE 指明CloseHandle 將不在內存中保留引用記數為0 的VxD。

      VxD 也可延遲交換數據, 此時, 應用程序先傳值FILE_FLAG_DELETE_ON_CLOSE|FILE_FLAG_OVERLAPPED

      到CreateFile, 用o ?hEvent=CreateEvent(0,TRUE,0,NULL) 創建事件, 再傳o 的地址到DeviceIoControl, 然后用GetOverlappedResult(h, &o, &oc,TRUE) 在o 上睡眠。

      此時,p ->lpoOverlapped 一定大于0,VxD 可用VMM 服務_LinPageLock, 按頁上鎖p ->dioc_InBuf 指向的應用程序ibuf 區,p ->dioc_OutBuf 指向的obuf 區,p ->lpoOverlapped 指向的o 結構。要交換數據時, 可置數據及數據總量到p ->dioc_OutBuf 及p ->lpoOverlapped ->O_InternalHigh, 然后調用VMM 服務VWIN32_DIOCCompletionRoutine(p ->lpoOverlapped ->O_Internal) 喚醒應用程序。

      VMM 動態裝卸VxD 時, 以命令碼0 及-1 發送W32_DEVICEIOCONTROL 消息給VxD, 故Vireo 公司建議命令碼C 取[2048,4095]。

      2 . 被Real/V86 模式下16 位應用程序訪問的接口

      my-VxD 先要指定接口ID( 如3180h), 再在API 頁上選Standard Application Entry Points 框中的Real/V86 Mode 標簽, 即可生成MyDevice::V86_API_Entry 入口, 訪問它的匯編程序是:

    entry    dd    ?
        mov    ax,1684h    ; 功能號
        mov    bx,3180h    ; 接口ID
        int    2fh        ; 取入口的段/ 偏移到es/di,
             成功時,di 及es 返回非零值
        mov     ax,es
        or     ax,di
        jz     L0
        mov    word ptr [entry],di
        mov    word ptr [entry +2],es
        mov    ah, 碼C
        call     [entry]
    L0:    錯誤處理
        MyDevice::V86_API_Entry
     (VMHANDLE hVM,CLIENT_STRUCT *p) 入口可以是:
        if (p ->CBRS.Client_AH== 碼C) p ->CBRS.Client_AL=0;
      3.?被保護模式下16 位應用程序訪問的接口

      與第2 條類似, 但選Protected Mode 標簽, 即可生成MyDevice::PM_API_Entry 入口, 訪問它的程序是:

      int PASCAL WinMain(HANDLE h1,
    HANDLE h0,LPSTR lpCmdLine,int nCmdShow){
    FARPROC entry; //32 位
      _asm{
        mov    ax,1684h
        mov    bx,3180h
        int    2fh   ; 取入口的選擇符/ 偏移到es/di,
             成功時,di 及es 返回非零值
        mov     ax,es
        or     ax,di
        jz     L0
        mov    word ptr [entry],di
        mov    word ptr [entry +2],es
        mov    ah, 碼C
        call  [entry]
      }
      對PM_API_Entry 的處理如第2 條。
      4 . 被DPMI 的實模式/V86 模式下16 位應用程序訪問的接口

      與第2 條類似, 但在API 頁上選Vendor Specific Application Entry Points 中的Real/V86 Mode 標簽, 然后在Vendor ID String 中輸入唯一標識串my, 即可生成My_V86VendorEntry::handler 入口, 訪問它的程序是:

    str    db 'my',0     ;VxD 的唯一標識串
    entry    dd ?
        mov ax,168Ah     ; 功能號
        lea si,str  ; 要求ds/si 值是str 的段值/ 偏移值
        int 2Fh    ; 取入口的段/ 偏移到es/di, 成功時,al 返回0
        cmp al,0
        jne L0
        mov word ptr [entry],di
        mov word ptr [entry +2],es
        ...
        call [entry]
        對handler 的處理如第二條。
      5.?被DPMI 的保護模式下16 位應用程序訪問的接口

      與第4 條類似, 但選Protected Mode 標簽, 即可生成My_ProtVendorEntry::handler 入口, 訪問它的程序是:

    int PASCAL WinMain(HANDLE h1,HANDLE h0,
      LPSTR lpCmdLine,int nCmdShow){
    char *id="my";
    FARPROC entry;
      _asm{
         mov ax,168Ah
        mov si,id
        int 2Fh ; 取入口的選擇符/ 偏移到es/di
        cmp al,0
        ...
      }
    }
       對handler 的處理如第2 條。
      6 .?可被其他VxD 訪問的接口

      若your.VxD 欲調my.VxD 的做兩數相減的minus 接口, 需在my.VxD 的VxD service 頁上輸入原型

      DWORD _cdecl minus(DWORD i,DWORD j), 再在MyDevice::minus 中, 寫return(i -j);

      your.mak 中, 需處理中間文件wrap.cpp:
    OBJECTS=your.OBJ wrap.obj
    ...
    wrap.OBJ:wrap.cpp my.h
      wrap.cpp 中, 對帶參數的VxD 服務, 需用VMM 宏指令VxDJmp 轉入, 各參數進入wrap 時, 已按C 的調用約定入棧; 對不帶參數VxD 服務, 可調用VMM 宏指令VxDCall( 接口名):

    #include "my.h"
    DWORD _cdecl MyDevice::minus(DWORD i,DWORD j){
        VxDJmp(minus);
    }
      your.cpp 的某一函數f, 可用VMM 服務Get_DDB, 查my.VxD 是否已裝入, 若未裝入, 則用VxDLDR 服務

      VxDLDR_LoadDevice 將其裝入:

    #define DEVICE_MAIN
    #include "your.h"
    Declare_Virtual_Device(YOUR)
    #undef DEVICE_MAIN
    #include "my.h" // 此行需在DEVICE_MAIN 外
    VOID f(){
    PDEVICEINFO pinfo;
    PDDB pddb;
    DWORD r;
    pddb=Get_DDB(0,"MY    ");
    // 用空格補全長度小于8 的VxD 名
    if (pddb==0) {// 未裝入
    r=VxDLDR_LoadDevice("my.VxD",
    VxDLDR_INIT_DEVICE, &pinfo, &pddb);
    if (r!=0) //VxDLDR_LoadDevice
    未能成功裝入my.VxD
    return;
    }
    MyDevice::minus( 值1, 值2);
    } 

    原文轉自:http://www.kjueaiud.com

    老湿亚洲永久精品ww47香蕉图片_日韩欧美中文字幕北美法律_国产AV永久无码天堂影院_久久婷婷综合色丁香五月

  • <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>