Как вызывать функцию 16-битной DLL из 32-битного приложения? |
Previous Top Next |
Надо использовать Thunks.
Кусок работающего только под Windows 95 кода -
Code: |
const Gfsr_SystemResources = 0; Gfsr_GdiResources = 1; Gfsr_UserResources = 2; var hInst16: THandle; GFSR: Pointer; { Undocumented Kernel32 calls. } function LoadLibrary16(LibraryName: PChar): THandle; stdcall; external kernel32 index 35; procedure FreeLibrary16(HInstance: THandle); stdcall; external kernel32 index 36; function GetProcAddress16(Hinstance: THandle; ProcName: PChar): Pointer; stdcall; external kernel32 index 37; procedure QT_Thunk; cdecl; external kernel32 name 'QT_Thunk'; { QT_Thunk needs a stack frame. } {$StackFrames On} { Thunking call to 16-bit USER.EXE. The ThunkTrash argument allocates space on the stack for QT_Thunk. } function NewGetFreeSystemResources(SysResource: Word): Word; var ThunkTrash: array[0..$20] of Word; begin { Prevent the optimizer from getting rid of ThunkTrash. } ThunkTrash[0] := hInst16; hInst16 := LoadLibrary16('user.exe'); if hInst16 < 32 then raise Exception.Create('Cannot load USER.EXE!'); { Decrement the usage count. This doesn't really free the library, since USER.EXE is always loaded. } FreeLibrary16(hInst16); { Get the function pointer for the 16-bit function in USER.EXE. } GFSR := GetProcAddress16(hInst16, 'GetFreeSystemResources'); if GFSR = nil then raise Exception.Create('Cannot get address of GetFreeSystemResources!'); { Thunk down to USER.EXE. } asm push SysResource { push arguments } mov edx, GFSR { load 16-bit procedure pointer } call QT_Thunk { call thunk } mov Result, ax { save the result } end; end; |
Автор - Quality freeware from Sight&Sound, Slovenia : http://www.sight-sound.si
Андрей Гусев (Andrey Gusev)
Взято из Akzhan's Delphi-related VCL&WinAPI Tips'n'Tricks
©Drkb::02006
Посылаю код для определения системных ресурсов (как в "Индикаторе ресурсов"). Использовалась статья "Calling 16-bit code from 32-bit in Windows 95".
Code: |
{ GetFeeSystemResources routine for 32-bit Delphi.
Works only under Windows 9x }
unit SysRes32;
interface
const //Constants whitch specifies the type of resource to be checked
GFSR_SYSTEMRESOURCES = $0000; GFSR_GDIRESOURCES = $0001; GFSR_USERRESOURCES = $0002;
// 32-bit function exported from this unit
function GetFeeSystemResources(SysResource: Word):Word;
implementation
uses
SysUtils, Windows;
type
//Procedural variable for testing for a nil
TGetFSR = function(ResType: Word): Word; stdcall;
//Declare our class exeptions
EThunkError = class(Exception); EFOpenError = class(Exception);
var
User16Handle : THandle = 0; GetFSR : TGetFSR = nil;
//Prototypes for some undocumented API
function LoadLibrary16(LibFileName: PAnsiChar): THandle; stdcall; external kernel32 index 35;
function FreeLibrary16(LibModule: THandle): THandle; stdcall; external kernel32 index 36;
function GetProcAddress16(Module: THandle; ProcName: LPCSTR): TFarProc;stdcall; external kernel32 index 37;
procedure QT_Thunk; cdecl; external 'kernel32.dll' name 'QT_Thunk';
{$StackFrames On}
function GetFeeSystemResources(SysResource: Word):Word; var
EatStackSpace: String[$3C]; begin // Ensure buffer isn't optimised away
EatStackSpace := ''; @GetFSR:=GetProcAddress16(User16Handle,'GETFREESYSTEMRESOURCES'); if Assigned(GetFSR) then //Test result for nil asm //Manually push onto the stack type of resource to be checked first
push SysResource //Load routine address into EDX
mov edx, [GetFSR] //Call routine
call QT_Thunk //Assign result to the function
mov @Result, ax end else raise EFOpenError.Create('GetProcAddress16 failed!'); end;
initialization
//Check Platform for Windows 9x if Win32Platform <> VER_PLATFORM_WIN32_WINDOWS then
raise EThunkError.Create('Flat thunks only supported under Windows 9x');
//Load 16-bit DLL (USER.EXE) User16Handle:= LoadLibrary16(PChar('User.exe'));
if User16Handle < 32 then raise EFOpenError.Create('LoadLibrary16 failed!');
finalization
//Release 16-bit DLL when done if User16Handle <> 0 then
FreeLibrary16(User16Handle);
end. |
©Drkb::02007
Взято с http://delphiworld.narod.ru