Почему FindWindowW через @ и GetProcAddress дает разные адреса?
При работе с функциями Windows API в Delphi и Pascal разработчики часто сталкиваются с необходимостью получения адреса определенной функции. Вопрос о различиях в адресах, возвращаемых оператором @ и функцией GetProcAddress, может показаться запутанным, но его можно легко разрешить, разобравшись в особенностях статической и динамической связи в процессе компиляции и выполнения программы.
Проблема
Разработчик столкнулся с ситуацией, когда при попытке получить адрес функции FindWindowW из Windows API, используя оператор @ и функцию GetProcAddress, результаты были различными. Это приводит к вопросу: почему возвращаемые значения адресов функций не совпадают?
var
p1, p2 : Pointer;
begin
p1:= @Winapi.Windows.FindWindowW;
p2:= GetProcAddress(GetModuleHandle('user32.dll'), 'FindWindowW');
ShowMessage(Format('p1 %p p2 %p ', [p1, p2]));
end;
Разъяснение
Адрес, возвращаемый оператором @, указывает на статическую версию функции в модуле Windows.pas, которая известна во время компиляции. В то время как GetProcAddress возвращает адрес функции в динамически подгружаемой библиотеке user32.dll, который известен только во время выполнения программы.
Подтвержденный ответ
Различие в адресах обусловлено использованием статической связи (статический вызов через jump table) и динамической связи (прямой вызов функции из библиотеки). Адрес p1 указывает на инструкцию перехода, которая, в свою очередь, указывает на реальный адрес функции FindWindowW. Это связано с тем, что при статической линковке используется таблица перехода (thunk jump table), которая позволяет вызвать функцию из DLL. Адрес p2 же является корректным адресом функции FindWindowW в процессе выполнения программы.
Альтернативный ответ и комментарии
Следует отметить, что использование thunk облегчает работу загрузчика исполняемых файлов, поскольку без него загрузчик должен был бы выполнить множество исправлений в процессе выполнения кода, где вызывается функция из DLL. С thunk необходимо исправить только сам thunk.
Заключение
Таким образом, различие в адресах, возвращаемых @ и GetProcAddress, является нормальным и обусловлено особенностями статической и динамической линковки в Delphi. Для корректной работы, например, при хоукинге функций, необходимо понимать эти различия и использовать соответствующий подход.
При использовании оператора `@` и функции `GetProcAddress` для получения адреса функции `FindWindowW` в Delphi, разные адреса объясняются различием между статической и динамической связью: `@` указывает на адрес в таблице перехода (thunk jump table), в т
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.