               32 

       

      

    --   "" 
        32-  16-    . 
    --  "" 
    "        . 
    --  
       32 ,  16- DLL. 

     .        . 
  ,     thunk     
,        - .  
 ,     16-   32-  
       ,     
     .  ,       ! 
          16-   
32-        
16- DLL, 32-    (   
   DLL  ).   
,  32 DLL     
.       . 
   
    733 


      

       (thunking)    16-  
32- DLL  .     , 
      .  . 32.1  
     . 

     32.1.   

    			 

    	16^32 32^16 ;	16^32	32^16	1632	32>16 

    Win32s	* 				 
    Windows NT	 				 
    Windows 95	 		 i 	 
    * 	 . |		i 
    ' 

      

      (Universal ThunK)   Win32s,  
      ,     . 
 Win32s   ( 16-,  32-)     
         
.    API    (UTRegister  
UTUnRegister)    KERNEL32.  Delphi 3.0  
    Win32s,       
     .      ! 

      

      (Generic ThunK)    16-   
32- DLL  Windows 95   Windows NT.  ,    
 16- DLL  32- .  ,  
   32- DLL,    Win32 
API,         Common Controls  
Windows 95  Windows NT.      , 
      16- . 
         Delphi 2.0  
,        Delphi.  
,   ,     
 ^. 

      

      (Flat ThunK)    32-   
16-,   16-   32-.   , 
    . ,    
 ,  , ,   .  ,  
   Windows 95.  ,   
Microsoft,  ,      .  , 
 THUNK. ,   ,    
 (     DLL),   ,    
 . 
     ,         ( , 
,       
 ). 6      Windows 95 
  (Matt Pietrek)   API QT Thunk.    
    .       
  Windows NT,   !   QT_Thunk 
    . 

     ? 

          ,  
  Windows NT,         
16-   32-.      
  WM_COPYDATA.      ,    
,   ,   ,     ,  
  32-   16- DLL.      : 

    734                                        VI.   

     16- DLL   ,     ,  
    16- DLL,     
(  ,        
16- DLL      ).    
   . 

      WM_COPYDATA 

     WM_COPYDATA        
(     ).    
    wparam     
TCopyDataStruct   Iparam. -     
        .   
    0:32  16:16   Windows  
.     TCopyDataStruct. 

    PCopyDataStruct = ''TCopyDataStruct; 
    TCopyDataStruct = packed record 
    dwData: DWORD; 
    cbData: DWORD; 
    IpData: pointer; 
    end; 

     dwData    ,  
.  cbData    ,   
 IpData. 

     1 
       WM_COPYDATA   SendMessage,   
Post.M.e.ssage,        
   SendMessage. 

    ,  32-      
16-.      . 16-  
     .    16 
        16- 
   ,        
 ,       .   
32.1    32- ,    
  . 

     32.1. \UDELPHI3\CHP32\WMCOPYDATA\CPYDAT32. . 32- 
 -   

    unit CpyDat32; 
    interface 
    uses 
    Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; 
    type 
    TCopy32 = class(TForm) 
    Labell: TLabel; 
    Label2: TLabel; 
    Label3: TLabel; 
    Send: TButton; 
    Editi: TEdit; 
    Edit2: TEdit; 
    Edit3: TEdit; 
    procedure SendClick(Sender: TObject) ; 
    private 
    { Private declarations ) 
    public 
    { Public declarations } 
    end; 
    var 
    Copy32: TCopy32; 


     32.                                              735 


    implementation 
    {$R *.DFM) 
    type 
    TMyRec = packed record 
    Fl : Smallint;   // 16- . 
    F2 : Double; 
    F3 : String[20]; 
    end; 
    procedure TCopy32.SendClick(Sender: TObject); 
    var 
    RecSize: integer; 
    MyRec: TMyRec; 
    CopyDataStruct: TCopyDataStruct; 
    TargetWnd: hWnd; 
    begin 
    //.        
    //     . 
    // hWnd 16- . 
    TargetWnd := Findwindow(nil,'16-bit Receiving Application'); 
    //  . 
    RecSize := SizeOf(TMyRec) ; 
    with CopyDataStruct, MyRec do begin 
    Fl := StrToInt(Editl.Text) ; 
    F2 := StrToFloat(Edit2.Text); 
    F3 := Edit3.Text; 
    dwData := 5; //   ,  . 
    cbData := RecSize; 
    IpData := @MyRec; 
    end; 
    //   WM_CopyData. 
    SendMessage(TargetWnd, WM_COPYDATA, Handle, Longint(SCopyDataStruct)) ; 
    end; 
    end. 

     Delphi 1.0  WM_COPYDATA   TCopyDataStruct  
16-   Win32s,      WINPROC,   
WINTYPES,         .   
32.2      . 

     32.2. \UDELPHI3\CHP32\WMCOPYDATA\CPYDAT16. PAS. 16- 
 -   

    unit Cpydatl6; 
    interface 
    uses 
    SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls, 
Forms, Dialogs, StdCtrls; 
    const 
    (  WM_COPYDATA.) WM_COPYDATA = $004A; 
    type 
    TCopyl6 = class(TForm) Editi: TEdit; 


    736                                        VI.   


    Edit2: TEdit; 
    Edit3: TEdit; 
    Labell: TLabel; 
    Label2: TLabel; 
    Label3: TLabel; 
    Edit4: TEdit; 
    Label4: TLabel; 
    private 
    ( Private declarations ) 
    procedure WMCopyData(var M: TMessage); message WM_COPYDATA; 
    public 
    { Public declarations } 
    end; 
    var 
    Copy 16: TCopyl6; 
    implementation 
    ($R *.DFM) 
    type 
    PMyRec = ^TMyRec; 
    TMyRec = packed record 
    Fl : Integer;  { 32- Smalllnt.) 
    F2 : Double; 
    F3 : String[20]; 
    end; 
    (   WM_COPYDATA.) 
    PCopyDataStruct = ^TCopyDataStruct; 
    TCopyDataStruct = packed record 
    dwData: Longint; ( 32- DWORD.) 
    cbData: Longint; ( 32- DWORD.} 
    IpData: Pointer; 
    end; 
    procedure TCopyl6.WMCopyData(var M: TMessage); 
    var 
    MyRec: TMyRec; 
    begin 
    MyRec := PMyRec (PCopyDataStruct (M. IParam) . IpData) /\; 
    Editl.Text := IntToSTr(MyRec.Fl) ; 
    Edit2.Text := FloatToStr(MyRec.F2); 
    Edit3.Text := MyRec.F3; 
    Edit4.Text := IntToStr(PCopyDataStruct(M.IParam) -- .dwData) end; 
    end. 

     . 32.1       .  
    32-      Send 
16-     . 

    Integer )1234_____________ 
    Double J5678.9____________ 
    String   Data froni 32-bit App          ii" 
    Ii "" Send" ""'I               . .User Defined Data )5              j 

    . 32.1.    WM_COPYDATA 

     -       , 
     ,    
  ,    32- . 

     32.                                              737 
    24  Delphi 3.   


        QTJTiunk 

    QT_Thunk   API,     
     ,    
Windows 95.   QT_Thunk    EDX,  
  16- ,       . 
,    QT_Thunk   asm,   ,  
      ,  .       " """"""" 
        16:16   EDX   asm  
  QT_Thunk   Pascal,    ,  
   ,   . ,  ,  
  ,      ! 
      QT_Thunk      
 . 
              
 ,       $W+. 
         $   ,  QT_Thunk  
   . 
       16- DLL,     
   DLL     API 
LoadLibraryl6, GetProcAddressl6  FreeLibraryi'6"" ~ 
              
,  QT_Thunk   . 
      32.3       QT_Thunk  
   API,    "  ". 
     32.3. \UDELPHI3\CHP32\QT_THUNK\QTTHUNKU. .    
 API   QT_Thunk 

    unit QTThunkU; 
    //. . 
    interface 
    uses 
    Windows; 
    type 
    //  16-  
    // ( Delphi 3.0  32-). 
    TShortHandle = Word; 
    // API  WOW32.DLL. 
    function WOWGetVDMPointer(vp, dwBytes: DWord; 
    fProtectedMode: Bool): Pointer; stdcall; 
    function WOWGetVDMPointerFix(vp, dwBytes: DWord; 
    fProtectedMode: Bool): Pointer; stdcall; 
    procedure WOWGetVDMPointerUnfix(vp: DWord); stdcall; 
    //  Windows 95 API  Kernel32.DLL. 
    function GlobalAllocl6(Flags: Integer; Bytes: Longint): 
    TShortHandle; stdcall; 
    function GlobalLockl6(Mem: TShortHandle): Pointer; stdcall; 
    function GlobalUnLockl6(Mem: TShortHandle): WordBool; stdcall; 
    function GlobalFreel6(Mem: TShortHandle): TShortHandle; stdcall; 
    function LoadLibraryl6(LibFileName: PChar): THandle; stdcall; 
    function GetProcAddressl6(Module: HModule; ProcName: PChar): 
    TFarProc; stdcall; 
    procedure FreeLibraryl6(LibModule: THandle); stdcall; 
    procedure QT_Thunk; 


    738                                        VI.   


    implementation 
    uses 
    SysUtils, Classes; 
    type 
    EVersionError = class(Exception); 
    //  API  WOW32.DLL. 
    function WOWGetVDMPointer;      external 'wow32.dll'; 
    function WOWGetVDMPointerFix;   external 'wow32.dll'; . 
    procedure WOWGetVDMPointerUnfix; external 'wow32.dll';  
    //  API  Kernel32.DLL                   \ 
    function GlobalAllocl6;    external 'kernel32.dll' indejj 24 
    function GlobalLockl6;     external 'kernel32.dll' index 25 
    function GlobalUnLockl6;   external 'kernel32.dll' index 26 
    function GlobalFreel6;     external 'kernel32.dll' index 31 
    function LoadLibraryl6;    external 'kernel32.dll' index 35 
    procedure FreeLibraryl6;    external 'kernel32.dll' index 36 
    function GetProcAddressl6; external 'kernel32.dll' index 37 
    procedure QT_Thunk;         external 'kernel32.dll' index 559; 
    initialization 
    // . 
    if Win32Platform <> Ver_Platform_Win32_Windows then 
    raise EVersionError.Create('QT_Thunk only works '+ 
    'under Windows 95!'+#13#10+ 
    'For Windows NT use the'+ 
    ' WM_COPYDATA technique.'); 
    end. 

          ,   
Pascal-   -,  " 16- DLL.  
   , "   " longfnt, 
        . ,   , 
 32- DLL     32- . 
-     longint    .  
 32.4     . 

    I  32.4. \UDELPHl3\CHP32\QT_THUNK\QT_TESTU. PAS. 32- 
  

    unit QT_TestU; 
    interface 
    uses 
    Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, 
StdCtrls, ExtCtrls; 
    type 
    TCall32 = class(TForm) 
    PasProcNoParam: TButton; 
    PasProc2Param: TButton; 
    CFunc2Param: TButton; 
    procedure PasProcNoParamClick(Sender: TObject); 
    procedure PasProc2ParamClick(Sender: TObject); 
    procedure CFunc2ParamClick(Sender: TObject); 
    private 
    { Private declarations } 
    public 
    ( Public declarations } 
    end; 


     32.                                              739 


    var 
    Call32: TCall32; 
    implementation 
    ($R *.DFM} 
    //   . 
    ($W+} 
    uses 
    QTThunkU; 
    //    ,   
    //    QT_Thunk. 
    var 
    D1116Handle : THandle; 
    Procl6Addr : Pointer; 
    IntParamI : integer; 
    IntParam2 : integer; 
    PIntParam32 : "integer; 
    PIntParaml6 : "integer; 
    Return : integer; 
    function Lockl6Pointer(var P32: Pointer; Size: integer): Pointer; 
    begin 
    result := nil; 
    //    16- . 
    LongRec(result).Hi := GlobalAllocl6(GMEM_FIXED or 
    GMEM_ZEROINIT, Size) ; 
    // 16-   32-. 
    P32 := WOWGetVDMPointer(DWORD(Result), 0, True); 
    end; 
    procedure UnLockl6Pointer(P: Pointer); 
    begin 
    GlobalFreel6(LongRec(P).Hi); 
    end; 
    procedure TCall32.PasProcNoParamClick(Sender: TObject); 
    var 
    QT_Stack_Space : String[$3C]; 
    begin 
    // QT Stack Space,     . 
    QT_Stack_Space := ''; 
    //  16- DLL. 
    D1116Handle := LoadLibraryl6('Libl6DLL.DLL'); 
    Procl6Addr := GetProcAddressl6(D1116Handle, 'PasProcNoParam') ; 
    if Assigned(Procl6Addr) then 
    asm 
    mov edx, Procl6Addr 
    call QT_Thunk 
    end; 
    FreeLibraryl6(D1116Handle) ; 
    end; 
    procedure TCall32.PasProc2ParamClick(Sender: TObject); 
    //        
    //   . 
    var 
    QT_Stack_Space : String[$3C]; 
    begin 
    // QT Stack Space,     . 
    QT_Stack_Space := ''; 


    740                                        VI.   


    //  16- DLL. 
    D1116Handle := LoadLibraryl6('Libl6DLL.DLL'); 
    Procl6Addr := GetProcAddressl6(D1116Handle, 'PasProc2Params'); 
    if Assigned(Procl6Addr) then begin 
    IntParamI := 100; 
    IntParam2 := 200; 
    PIntParan>16 := Lockl6Pointer(Pointer(PIntParam32), SizeOf(IntParam2)) ; 
    // IntParam2   ,    
    //PIntParam32. 
    Move(IntParam2, PIntParam32^, sizeof(IntParam2)); 
    asm 
    push IntParamI 
    push PIntParaml6 
    mov edx, Procl6Addr 
    call QT_Thunk 
    end; 
    ShowMessage ('IntParam2 was 200 now it is '+ IntToStr (PIntParan^^) ) ; 
    UnLockl6Pointer(PIntParaml6) ; 
    end; 
    FreeLibraryl6(D1116Handle) ; 
    end; 
    procedure TCall32.CFunc2ParamClick(Sender: TObject); 
    //        -, 
    //   . 
    var 
    QT_Stack_Space : String[$3C]; 
    begin 
    // QT_Stack_Space,     . 
    QT_Stack_Space := ''; 
    //  16- DLL. 
    D1116Handle := LoadLibraryl6Libl6DLL.DLL'); 
    Procl6Addr := GetProcAddressl6(D1116Handle, 'CFunc2Params'); 
    if Assigned(Procl6Addr) then begin 
    IntParamI := 100; 
    IntParam2 := 200; 
    //  -      
    //    . 
    /asm 
    push IntParam2 
    push IntParamI 
    mov edx, Procl6Addr 
    call QT_Thunk 
    // . 
    add esp, 2*4 //  Longint no 4 . 
    mov Return.Word.2, dx 
    mov Return.Word.0, ax 
    end'' 
    ShowMessage(Format('%d + %d = %d', 
    [IntParamI,IntParam2,Return])) ; 
    end; 
    FreeLibraryl6(D1116Handle) ; 
    end; 
    end. 

     16- DLL ( - )   
 32.5. 

     32.                                              741 


     32.5. \UDELPHI3\CHP32\QTJHUNK\LIB16DLL.DPR. 16- DLL  
   QT_Thunk 

    library Libl6DLL; 
    uses 
    Dialogs, SysUtils; 
    procedure PasProcNoParam; export; 
    begin 
    ShowMessage('Pascal procedure called with no paramters'); 
    end; 
    procedure PasProc2Params(pi: Longint; var p2: Longint); export; 
    begin 
    ShowMessage(Format('Pascal procedure called '+ 'with parameters %d and 
%d', [pl, p2])) ; 
    p2 := p2 * 5; 
    end; 
    function CFunc2Params(pi, p2: Longint): Longint; cdecl; export; 
    begin 
    ShowMessage(Format(' Function called with '+ 'parameters %d and %d', [pl, p2])); 
    CFunc2Params := pl + p2; 
    end; 
    exports 
    PasProcNoParam, PasProc2Params, CFunc2Params; 
    begin 
    end. 


     

          16-   
32-  32-  16-      
 . ,       ,  
 , ,   ,      . 

    742                                        VI.   
