Как вызвать функцию из EXE???
Windows, SysUtils, Classes, Dialogs;
type
// СТРУКТУРА ДЛЯ ПЕРЕДАЧИ ПАРАМЕТРОВ В ФУНКЦИЮ ///
PFunctionData = ^TFunctionData;
TFunctionData = packed record
Address: CARDINAL;
PId: CARDINAL;
end;
var
MyFunc: procedure(Param: PFunctionData); stdcall;
{$R *.res}
// ВЫЗОВ ФУНКЦИИ ИЗ ЕХЕ
procedure CallFunc(Param: PFunctionData); stdcall; export;
var
MyArg: TFunctionData;
begin
MyArg := Param^;
MyFunc(Addr(MyArg));
end;
// ФУНКЦИЯ ВЫЗЫВАЕТСЯ ПРИ ЗАГРУЗКЕ DLL И ПРИНИМАЕТ АДРЕС ФУНКЦИИ ИЗ ЕХЕ
procedure MyDLLInit(Param: POINTER); stdcall; export;
begin
@MyFunc := Param;
end;
Exports
CallFunc, MyDLLInit;
begin
end.
Эта библиотека грузится в мой процесс при создании формы, и сразу вызывается MyDLLInit и передаётся адрес вызываемой функции.
По кнопке 1 я вызываю функцию из библиотеки, а та в свою очередь из ехе:
...
// СТРУКТУРА ДЛЯ ПЕРЕДАЧИ ПАРАМЕТРОВ В ФУНКЦИЮ ///
PFunctionData = ^TFunctionData;
TFunctionData = packed record
Address: CARDINAL;
PId: CARDINAL;
end;
/////////////////////////////////////////////////
var
Form1: TForm1;
...
CallDLL: procedure(Data: PFunctionData); stdcall;
implementation
{$R *.dfm}
...
procedure TForm1.Button1Click(Sender: TObject);
var
Data: TFunctionData;
begin
Data.PId := 12345678;
@CallDLL := GetProcAddress(HMyModule, PAnsiChar('CallFunc'));
CallDLL(Addr(Data));
end;
Кодом по кнопке 2 я вызываю функцию из своей длл внедрённой в другой свой процесс(кстати та прога на С++):
var
DataForDLL: TFunctionData;
InitAddr: POINTER;
begin
DataForDLL.PId := GetCurrentProcessId; // Тут передаётся PId моего процесса который будет очень нужен в DLL
InitAddr := GetProcAddressInAnotherProcess(ProcessInfo.dwProcessId, PWideChar('mwwin32.dll'), PWideChar('Init'));
CallRemoteProc(ProcessInfo.dwProcessId, InitAddr, Addr(DataForDLL));
end;
Последние две функции самописаные
Но из этой длл во втором процессе не получается вызвать ту же самую CallFunc из длл в первом процессе.
Причём адрес CallFunc получается извлеч функцией GetProcAddressInAnotherProcess.
Отладчик ред студии сообщает код ошибки: 0x0eedfade
Если просто запускать ехе то при нажатии кнопки 2 процесс 1 разрушается, процесс 2 остаётся работать.
Про ошибку ничего не получается нагуглить.
Что из ЕХЕ не вызвать функцию без шаманства я понял, но почему не выходит вызвать функцию из DLL ?
Все проекты компилировались в релиз моде с отключенной опцией Build with runtime packages.
Вторую прогу я запускаю из под первой при помощи CreateProcess, вот так:
Но хочу заметить на это:
разница между исполнимым файлом и динамической библиотекой - минимальна. При определенных допущениях их можно считать полностью одинаковыми - т.е. вызов функции из dll ничем не отличается от вызова из EXE. Может в этом проблема?
По моему я ничего не забыл, какждой указал что она будет экспортированна, занёс их в секцию экспорта.
Из первого процесса(куда грузится DLL) обе функции вызываются, всё работает.
Проблема с вызовом из другого процесса. Я там вызываю функцию из процесса 1 во внедрённой DLL, а та в свою очередь должна вызвать функцию CallFunc из DLL в процессе 1.
Прототипы вызываемых функций везде одинаковые, вызываются одними и теми же кодами. Вот реализация функции
CallRemoteProc:
function CallRemoteProc(ProcessId: CARDINAL; FuncAddr: POINTER; FuncArg: PFunctionData): BOOL;
var
RemotePMem: POINTER;
HProcess, RealWrite, MyThread, CRT : CARDINAL;
begin
HProcess := OpenProcess(PROCESS_ALL_ACCESS, FALSE, ProcessId);
if HProcess = 0 then
begin
Result := FALSE;
Exit;
end
else RemotePMem := VirtualAllocEx(HProcess, NIL, SizeOf(FuncArg^) * 2, MEM_COMMIT, PAGE_READWRITE);
if not Assigned(RemotePMem) then
begin
CloseHandle(HProcess);
Result := FALSE;
Exit;
end
else if not WriteProcessMemory(HProcess, RemotePMem, FuncArg, SizeOf(FuncArg^) * 2, RealWrite) then
begin
CloseHandle(HProcess);
Result := FALSE;
Exit;
end
else CRT := CreateRemoteThread(HProcess, NIL, 0, FuncAddr, RemotePMem, 0, MyThread);
if CRT = 0 then
begin
CloseHandle(HProcess);
Result := FALSE;
Exit;
end
else
CloseHandle(HProcess);
Result := TRUE;
end;
Всётаки такое может быть что процесс 2 не может например выполнить VirtualAllocEx или WriteProcessMemory или CreateRemoteThread?
В ProcessExplorer видно что процесс 1 родитель для процесса 2. Это как то может мешать вышеописанным функциям или функции OpenProcess?
Можно ли используя CreateProcess запустить програму не от себя, а от эксплорера?
Я тоже так считал. Но на разных форумах пишут что ехе не проходит какую то инициализацию как длл при загрузке в память, что у них разные точки входа EntryPoint и DLLEntryPoint и в купе с этим ещё там какой то трабл был. Хотя экзеха являясь PE файлом может иметь секцию экспорта(как собственно все PE).
По этому я и решил не шаманить с ехе, а написать длл(куда казалось бы проще?)
Да, спасибо я уже понял что своё.
Жалко поздно начал заниматься программированием, не застал эпоху 98 и Me.
Интересно как бы там я решал свои задачи. Там меня бы наверно синие экраны задолбали.
Тут, в линейке NT, главное не делать как в общем случае =)
Может по коду ошибки 0x0eedfade у кого какая инфа есть? Так сказать что она может означать в общем случае.