Top = 120
Width = 22
Height = 13
Caption = 'Area'
FocusControl = EditArea
end
objectLabel5: TLabel
Left = 6
Top = 158
Width = 50
Height = 13
Caption = 'Population'
FocusControl = EditPopulation
end
objectEditName: TDBEdit
Left = 6
Top = 21
Width = 135
Height = 21
DataField = 'Name'
DataSource = DataSource1
MaxLength = 0
TabOrder = 0
end
objectEditCapital: TDBEdit
Left = 6
Top = 59
Width = 135
Height = 21
DataField = 'Capital'
DataSource = DataSource1
MaxLength = 0
TabOrder = 1
end
objectEditContinent: TDBEdit
Left = 6
Top = 97
Width = 135
Height = 21
DataField = 'Continent'
DataSource = DataSource1
MaxLength = 0
TabOrder = 2
end
objectEditArea: TDBEdit
Left = 6
Top = 135
Width = 65
Height = 21
DataField = 'Area'
DataSource = DataSource1
MaxLength = 0
TabOrder = 3
end
objectEditPopulation: TDBEdit
Left = 6
Top = 173
Width = 65
Height = 21
DataField = 'Population'
DataSource = DataSource1
MaxLength = 0
TabOrder = 4
end
end
end
objectDataSource1: TDataSource
Left = 95
Top = 177
end
objectDatabase1: TDatabase
DatabaseName = 'DB1'
LoginPrompt = False
SessionName = 'Default'
Left = 128
Top = 176
end
end
Как вызывать функцию 16-битной DLL из 32-битного приложения?
Из советов Nomadic'a:
Надо использовать Thunks.
Кусок работающего только под Windows 95 кода —
const
Gfsr_SystemResources = 0;
Gfsr_GdiResources = 1;
Gfsr_UserResources = 2;
var
hInst16: THandle;
GFSR: Pointer;
{ Undocumented Kernel32 calls. }
functionLoadLibrary16(LibraryName: PChar): THandle; stdcall; externalkernel32 index35;
procedureFreeLibrary16(HInstance: THandle); stdcall; externalkernel32 index36;
functionGetProcAddress16(Hinstance: THandle; ProcName: PChar): Pointer; stdcall; externalkernel32 index37;
procedureQT_Thunk; cdecl; externalkernel32 name'QT_Thunk';
{ QT_Thunk needs a stack frame. }
{$StackFrames On}
{ Thunking call to 16-bit USER.EXE. The ThunkTrash argumentallocates space on the stack for QT_Thunk. }
functionNewGetFreeSystemResources(SysResource: Word): Word;
varThunkTrash: array[0..$20] ofWord;
begin
{ Prevent the optimizer from getting rid of ThunkTrash. }
ThunkTrash[0] := hInst16;
hInst16 := LoadLibrary16('user.exe');
ifhInst16 < 32 then raiseException.Create('Can''t 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');
ifGFSR = nil then raiseException.Create('Can''t 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;
Как написать DLL, которую можно было-бы выполнить с помощью RunDll, RunDll32?
Из советов Nomadic'a:
Вы должны определить в программе вызываемую снаружи функцию.
Функция должна быть __stdcall (или WINAPI, что то же самое ;)) и иметь четыре аргумента. Первый – HWND окна, порождаемого rundll32 (можно использовать в качестве owner'а своих dialog box'ов), второй – HINSTANCE задачи, третий – остаток командной строки (LPCSTR, даже под NT), четвертый – не знаю ;).
Hапример –
int __stdcall __declspec(dllexport) Test (HWND hWnd, HINSTANCE hInstance, LPCSTR lpCmdLine, DWORD dummy) {
MessageBox(hWnd, lpCmdLine, "Command Line", MB_OK);
return 0;
}
Исполняем таким образом –
rundll32 test.dll,_Test@16 this is a command line
выдаст message box со строкой «this is a command line».
На Паскале –
Functiontest(hWnd: Integer; hInstance: Integer; lpCmdLine: PChar; dummy: Longint): Integer; StdCall; export;
begin
Windows.MessageBox(hWnd, lpCmdLine, 'Command Line', MB_OK);
Result := 0;
end;
Давненько я ждал эту информацию! Сел проверять и наткнулся на очень забавную вещь. А именно – пусть у нас есть исходник на Си пpимерно такого вида:
int WINAPI RunDll(HWND hWnd, HINSTANCE hInstance, LPCSTR lpszCmdLine, DWORD dummy);
……
int WINAPI RunDllW(HWND hWnd, HINSTANCE hInstance, LPCWSTR lpszCmdLine, DWORD dummy);
Читать дальше