如何在 Windows 95、 Windows 98 和 Windows Me 的 32 位元程式碼從呼叫 16 位元的程式碼

文章翻譯 文章翻譯
文章編號: 155763 - 檢視此文章適用的產品。
全部展開 | 全部摺疊

在此頁中

結論

身為開發人員可能需要存取您的 Win32 應用程式從一個 16 位元動態連結程式庫 (DLL) 所提供的功能。特別是當您沒有來源程式碼為 DLL,以便您可以在 Win32 到連接埠時,這是,則為 True。本文將告訴您,32 位元 DLL 可以呼叫 16 位元 DLL 的機制。機制稱為一個 Thunk 及實作下 Microsoft Windows 95,Windows 98 的方法,而 Windows 千禧版就稱為平面 Thunk。

以下說明在建立平面 Thunk 所需的三個主要步驟:
  1. 建立 Thunk 指令碼。
  2. 建置 32 位元 DLL。
  3. 建置 16 位元 DLL。

其他相關資訊

平面 Thunk 是由 32 位元和共同作業的 16 位元 DLL 所組成。 Win32 應用程式呼叫 32 位元的 DLL,32 位元 DLL 呼叫可匯出的函式在 16 位元 DLL 中。在 16 位元 DLL 函式傳回時, 它會傳回至 32 位元 DLL 會輪流傳回回到 Win32 應用程式。32 位元和 16 位元 DLL 工作藉由呼叫 Windows 95 32年位元和 16 位元] kernels 來處理所有讓從 32 位元為 16 位元的程式碼轉換以及備份所需的低階詳細資料。

設計新的平面 Thunk 牽涉到建立 Thunk 指令碼 (.thk 檔案)。 此指令碼以 Thunk 編譯器編譯到組件語言檔案兩次 ; 一次與每個兩個旗標的-DIS_32 和 DIS_16 然後組合。這可讓您建立 32 位元和 16 位元的物件模組。這些物件模組會分別連結在 32 位元和 16 位元的 DLL 中。下列圖表摘要了參與建置 DLL 檔案:
                         +------------+
                         | 32to16.thk |
                         +------------+
                               |
                         +------------+
                         | 32to16.asm |
                         +------------+
                           /         \ 
                  -DIS_32 /           \ -DIS_16
                        /              \ 
                  +-----------+  +-----------+
                  | 32THK.obj |  | 16THK.obj |
                  +-----------+  +-----------+
                        /                 \ 
        +-------+    +-------+             +-------+
        | APP32 | -> | DLL32 | -- THUNK -- | DLL16 |
        +-------+    +-------+             +-------+
				

建置平面 Thunk 所需的工具

  • Microsoft Visual C++ 版本 1.5 x 的 16 位元邊的建立 Thunk (16 位元) 編譯器。此 Thunk 的 16 位元側邊是 16 位元 DLL。
  • Microsoft Visual C++ 版本 2.x 或更高 (32 位元) 編譯器建立的 Thunk 32 位元側邊。此 Thunk 的 32 位元側邊是 32 位元 DLL。
  • Thunk 編譯器 (Thunk.exe) 從 Microsoft Win32 SDK 的編譯 Thunk 指令碼。
  • Microsoft 巨集組譯工具 (MASM) 6.1 或更高的組譯 Thunk 編譯器的組件語言輸出的版本。
  • 16 位元 Rc.exe BINW16 目錄檔的 Microsoft Win32 SDK 來標示為版本 4.0 16 位元 Thunk DLL。

正在建立 Thunk 指令碼

您需要建立指令碼可以由 Thunk 編譯器用來建立一個 Thunk。Thunk 指令碼是包含型別定義您想要透過 Thunk 呼叫之函式的函式原型和每個函式的參數方向規格的文字檔。比方說有些函數則需要輸入和輸出參數而有些則可能只需要輸入的參數。Thunk 指令檔使用特殊的語法來描述是否輸入參數、 輸出,或輸入和輸出。

以下列的陳述式開始 32-16 Thunk > 的 Thunk 指令碼:
enablemapdirect3216 = true ;
Thunk 編譯器必須將 Thunk 的 32 位元側邊宣告為 __stdcall,和 16 位元側邊是 __far __pascal。(WINAPI 宣告負責這兩面)。Thunk 編譯器不支援 __cdecl 和 __fastcall 呼叫慣例。 但是,注意 Thunk 編譯器不會實際接受 __far、 __pascal 或 __stdcall 關鍵字 ; 它們會假設。

下列範例會示範 Thunk 指令碼沒有參數的函式:
   enablemapdirect3216 = true;

   void MyThunk16()
   {
   }
				
此相等的宣告會是:
   C   language:  void WINAPI MyThunk16(void);
   C++ language:  extern "C" void WINAPI MyThunk16();
				
下列範例指令碼說明一個函式接受兩個參數,並傳回值。第二個參數為輸出參數包含傳遞回至 32 位元 DLL 的指標。
   enablemapdirect3216 = true;

   typedef int   BOOL;
   typedef char *LPSTR;

   BOOL MyThunk16(LPSTR lpstrInput, LPSTR lpstrOutput)
   {
      lpstrInput  = input;    // optional; input is default
      lpstrOutput = output;
   }
				
陳述式"lpstrOutput = 輸出 」 會告訴 Thunk 編譯器 16 位元函式會傳回一個需要從選取器: 位移指標轉換成 32 位元線性位址的位址。

下列的 Thunk 指令碼會使用更複雜的參數型別,例如結構。本範例也示範如何指定輸入和輸出參數。
   enablemapdirect1632 = true;

   typedef unsigned int UINT;
   typedef char *LPSTR;

   typedef struct _POINT {
      UINT x;
      UINT y;
   }POINT, *LPPOINT;

   typedef struct _CIRCLE {
      POINT center;
      UINT  radius;
   }CIRCLE, *LPCIRCLE;

   void MyThunk32( LPCIRCLE lpCircleInOut)
   {
      lpCircleInOut = inout;
   }
				
陳述式"lpCircleInOut = 進出 」 會告訴指令碼編譯器,將這個指標用來進行輸入和輸出。如此 Thunk 編譯器 lpCircleInOut 從 32 位元線性位址時,轉換為選取器: 位移指標呼叫此函式,並在函式傳回時,再回到 32 位元線性位址。轉換是由 Thunk 編譯器所建立 Thunk 處理。

使用 Thunk 編譯器

Thunk 編譯器使用方式是,如下所示:
thunk.exe/選項 <inputfile>-o <outputfile>
下列的命令列會顯示如何編譯-16 Thunk 指令碼 > 32。 這一行採用名為 32to16.thk Thunk 指令碼,並產生名為 32to16.asm 組件語言檔。
Thunk-t thk 32to16.thk-o 32to16.asm
在"-t thk 」 選項是告訴 Thunk 編譯器 Thunk 函式"thk_] 組件語言檔案中的前置詞。這個前置詞時,連結至 DLL,一對多個 Thunk 指令碼使用,且有助於建立一組包含兩個 32-16 和 16-32 Thunk > 的 DLL。每個 Thunk 指令碼應該有唯一的前置詞。

建置 32 位元 DLL

  1. 32 位元 DLL 的將 DllMain] 函數中,您必須進行命名 thk_ThunkConnect32 為呼叫每個原因 DllMain dwReason 如下所示的 Thunk 編譯器所建立的函式的呼叫 (thk 」 是從 Thunk 編譯器-t 參數前置字元):
          // prototype for function in .obj file from the thunk script
          BOOL WINAPI thk_ThunkConnect32(LPSTR     lpDll16,
                                         LPSTR     lpDll32,
                                         HINSTANCE hDllInst,
                                         DWORD     dwReason);
    
          BOOL WINAPI DllMain(HINSTANCE hDLLInst,
                              DWORD     dwReason,
                              LPVOID    lpvReserved)
          {
             if (!thk_ThunkConnect32("DLL16.DLL", "DLL32.DLL",
                                     hDLLInst, dwReason))
             {
                return FALSE;
             }
             switch (dwReason)
             {
                case DLL_PROCESS_ATTACH:
                   break;
    
                case DLL_PROCESS_DETACH:
                   break;
    
                case DLL_THREAD_ATTACH:
                   break;
    
                case DLL_THREAD_DETACH:
                   break;
             }
             return TRUE;
          }
    						
  2. 32 位元 DLL 模組定義 (.def) 檔案匯出一節中包含下列各行。例如:
          
       thk_ThunkData32
    						
  3. 匯出 Win32 應用程式呼叫的函式。您可以使用 32 位元 DLL 模組定義 (.def) 檔或 __declspec(dllexport) 關鍵字。務必函式會宣告並定義為 __stdcall (或 WINAPI)。如果 32 位元 DLL 以 C + + 撰寫,請務必將該函式宣告為 extern"C"也。
  4. (如果尚未編譯),如下所示編譯 Thunk 指令碼:
          thunk -t thk 32to16.thk -o 32to16.asm
    						
  5. 組合所產生的 Thunk 編譯器做為 32 位元物件模組的組件語言檔案。例如:
          ml /DIS_32 /c /W3 /nologo /coff /Fo thk32.obj 32to16.asm
    						
  6. 連結此物件模組做為 32 位元 DLL 的一部分。
  7. 32 位元 DLL 的一部分將 Thunk32.lib 程式庫的連結。這是提供包含 Thunk 編譯器所建立的程式碼使用在 32 位元 thunking API 的參考 Win32 SDK 中的 32 位元匯入程式庫。

建置 16 位元 DLL

  1. 16 位元 DLL 必須匯出函式名為"DllEntryPoint]。這個函式必須執行名為 thk__ThunkConnect16 Thunk 編譯器所建立的函式呼叫 (thk 」 是從 Thunk 編譯器-t 參數前置詞) 每次呼叫 DllEntryPoint:
          // prototype for function in .obj file from the thunk script
          BOOL WINAPI __export thk_ThunkConnect16(LPSTR lpDll16,
                                                  LPSTR lpDll32,
                                                  WORD  hInst,
                                                  DWORD dwReason);
    
          BOOL WINAPI __export DllEntryPoint(DWORD dwReason,
                                             WORD  hInst,
                                             WORD  wDS,
                                             WORD  wHeapSize,
                                             DWORD dwReserved1,
                                             WORD  wReserved 2)
          {
             if (!thk_ThunkConnect16("DLL16.DLL",
                                     "DLL32.DLL",
                                     hInst,
                                     dwReason))
             {
                return FALSE;
             }
             return TRUE;
          }
    						
  2. 16 位元 DLL 模組定義 (.def) 檔案匯入一節中包含下列各行。例如:
          C16ThkSL01      = KERNEL.631
          ThunkConnect16  = KERNEL.651
    						
  3. 16 位元 DLL 模組定義 (.def) 檔案匯出一節中包含下列各行。THK_THUNKDATA16 是在組合從 Thunk 編譯器輸出的目的檔中定義的。這兩個這些符號必須有 RESIDENTNAME] 關鍵字,但是可以有任何序數編號。
          THK_THUNKDATA16 @1  RESIDENTNAME
          DllEntryPoint   @2  RESIDENTNAME
    						
  4. 將 Thunk 函式加入至 16 位元 DLL 模組定義 (.def) 檔案匯出陳述式。務必他們宣告,定義為 __far __pascal __export (或 WINAPI __export)。如果 DLL 以 C + + 撰寫,請務必將它們宣告為 extern"C"也。此 Thunk 的 32 位元側邊呼叫這些函式。
  5. (如果尚未編譯),如下所示編譯 Thunk 指令碼:
          thunk -t thk 32to16.thk -o 32to16.asm
    						
  6. 組合所產生的 Thunk 編譯器做為 16 位元物件模組的組件語言檔案。例如:
          ml /DIS_16 /c /W3 /nologo /Fo thk16.obj 32to16.asm
    						
  7. 連結此物件模組做為 16 位元 DLL 的一部分。
  8. 將 16 位元 DLL 標記為 4.0 版。如果要執行這項操作,使用資源編譯器 (Rc.exe)。下面這一行顯示語法:
    rc-40 < DLL 檔案 >
    這個-40 選項僅可用資源編譯器所提供的 Win32 SDK 中。

    注意: 請確定使用 Rc.exe 檔案 BINW16 目錄中的,使 DLL 標有 4.0 版。16 位元版本的 Microsoft Visual C++ 的船隻 Rc.exe 檔案並不會將 DLL 標記為版本 4.0。

?考

如需有關如何偵錯平面 Thunk,請參閱下列文章 「 Microsoft 知識庫 」 中的資訊:
133722如何偵錯平面 Thunk

屬性

文章編號: 155763 - 上次校閱: 2005年7月11日 - 版次: 2.3
這篇文章中的資訊適用於:
  • Microsoft Win32 Application Programming Interface?應用於:
    • Microsoft Windows 95
    • Microsoft Windows 98 Standard Edition
    • Microsoft Windows Millennium Edition
    • Microsoft Platform Software Development Kit-January 2000 Edition
關鍵字:?
kbmt kbapi kbhowto kbkernbase kbnetwork kbprogramming kbthunks kbtshoot KB155763 KbMtzh
機器翻譯
重要:本文是以 Microsoft 機器翻譯軟體翻譯而成,而非使用人工翻譯而成。Microsoft 同時提供使用者人工翻譯及機器翻譯兩個版本的文章,讓使用者可以依其使用語言使用知識庫中的所有文章。但是,機器翻譯的文章可能不盡完美。這些文章中也可能出現拼字、語意或文法上的錯誤,就像外國人在使用本國語言時可能發生的錯誤。Microsoft 不為內容的翻譯錯誤或客戶對該內容的使用所產生的任何錯誤或損害負責。Microsoft也同時將不斷地就機器翻譯軟體進行更新。
按一下這裡查看此文章的英文版本:155763
Microsoft及(或)其供應商不就任何在本伺服器上發表的文字資料及其相關圖表資訊的恰當性作任何承諾。所有文字資料及其相關圖表均以「現狀」供應,不負任何擔保責任。Microsoft及(或)其供應商謹此聲明,不負任何對與此資訊有關之擔保責任,包括關於適售性、適用於某一特定用途、權利或不侵權的明示或默示擔保責任。Microsoft及(或)其供應商無論如何不對因或與使用本伺服器上資訊或與資訊的實行有關而引起的契約、過失或其他侵權行為之訴訟中的特別的、間接的、衍生性的損害或任何因使用而喪失所導致的之損害、資料或利潤負任何責任。

提供意見

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com