Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Как вызвать функцию из EXE???

465
06 ноября 2012 года
QWERYTY
595 / / 25.03.2012
Сразу из ехе вызвать не удалось. Тогда я написал DLL для своей программы которая получала адрес функции из ехе которую необходимо вызывать, выглядит так:

Код:
uses
  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 я вызываю функцию из своей длл внедрённой в другой свой процесс(кстати та прога на С++):

Код:
procedure TForm1.Button2Click(Sender: TObject);
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 ?
465
06 ноября 2012 года
QWERYTY
595 / / 25.03.2012
Может быть забыл упомянуть важную информацию.

Все проекты компилировались в релиз моде с отключенной опцией Build with runtime packages.
Вторую прогу я запускаю из под первой при помощи CreateProcess, вот так:

 
Код:
CreateProcess(PWideChar('D:\PROJEKTS\CPP\TEST\Release\Test.exe'), PWideChar('Test.exe'), NIL, NIL, FALSE, 0, NIL, PWideChar('D:\PROJEKTS\CPP\TEST\Release\'), StartupInfo, ProcessInfo)
Я там не стал заморачиваться с атрибутами безопасности, может из за этого у второго процесса проблемы с доступом к первому?
1
06 ноября 2012 года
kot_
7.3K / / 20.01.2000
Честно говоря - хер поймешь - что надо что вызывается что не вызывается, поэтому внятно посоветовать что либо трудно.
Но хочу заметить на это:
Цитата:
из ЕХЕ не вызвать функцию без шаманства я понял, но почему не выходит вызвать функцию из DLL


разница между исполнимым файлом и динамической библиотекой - минимальна. При определенных допущениях их можно считать полностью одинаковыми - т.е. вызов функции из dll ничем не отличается от вызова из EXE. Может в этом проблема?

465
06 ноября 2012 года
QWERYTY
595 / / 25.03.2012
Проблема может и в этом. Но я пытаюсь вызвать функцию из DLL в которой всё как надо(первый код).
По моему я ничего не забыл, какждой указал что она будет экспортированна, занёс их в секцию экспорта.
Из первого процесса(куда грузится 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;
Реализацию GetProcAddressInAnotherProcess выкладывать не буду. Она длинная и я там ничего нигде не меняю и не записываю, только читаю память процесса

Всётаки такое может быть что процесс 2 не может например выполнить VirtualAllocEx или WriteProcessMemory или CreateRemoteThread?


В ProcessExplorer видно что процесс 1 родитель для процесса 2. Это как то может мешать вышеописанным функциям или функции OpenProcess?
Можно ли используя CreateProcess запустить програму не от себя, а от эксплорера?
465
06 ноября 2012 года
QWERYTY
595 / / 25.03.2012
Цитата: kot_
разница между исполнимым файлом и динамической библиотекой - минимальна. При определенных допущениях их можно считать полностью одинаковыми - т.е. вызов функции из dll ничем не отличается от вызова из EXE. Может в этом проблема?



Я тоже так считал. Но на разных форумах пишут что ехе не проходит какую то инициализацию как длл при загрузке в память, что у них разные точки входа EntryPoint и DLLEntryPoint и в купе с этим ещё там какой то трабл был. Хотя экзеха являясь PE файлом может иметь секцию экспорта(как собственно все PE).
По этому я и решил не шаманить с ехе, а написать длл(куда казалось бы проще?)

7
06 ноября 2012 года
@pixo $oft
3.4K / / 20.09.2006
У каждого процесса своё адресное пространство в Windows линейки NT,так что попытка что-то сделать из одного процесса в другом в общем случае обречена на провал
465
07 ноября 2012 года
QWERYTY
595 / / 25.03.2012
Цитата: @pixo $oft
У каждого процесса своё адресное пространство в Windows линейки NT,так что попытка что-то сделать из одного процесса в другом в общем случае обречена на провал


Да, спасибо я уже понял что своё.
Жалко поздно начал заниматься программированием, не застал эпоху 98 и Me.
Интересно как бы там я решал свои задачи. Там меня бы наверно синие экраны задолбали.

Тут, в линейке NT, главное не делать как в общем случае =)
Может по коду ошибки 0x0eedfade у кого какая инфа есть? Так сказать что она может означать в общем случае.

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог