Форум: "WinAPI";
Текущий архив: 2005.08.21;
Скачать: [xml.tar.bz2];
ВнизДинамический импорт функции из DLL Найти похожие ветки
← →
Igit (2005-06-23 11:43) [0]Здравтсвйте мастера! Есть у меня одлин модуль, в нем описываются функции вызываемые из NTDLL.DLL... они видны в таблице импорта... и из-за них под вин9x программа не запускается вовсе... (у меня в программе идет проверка какая винда и в зависимости от этого исп. тот или иной метод). Так вот, как можно переписать например вот это
Function DbgUiConnectToDbg(): NTStatus;stdcall;external "ntdll.dll";
на такое чтоб не жестко привязывалось к ntdll а динамически?
← →
PVOzerski © (2005-06-23 11:45) [1]В общем виде, используют сочетание функций LoadLibrary и GetProcAddress применительно к процедурной переменной.
← →
-=XP=- © (2005-06-23 11:53) [2]type
TDbgUiConnectToDbg = function({параметры}): NTStatus; // Обявление процедурного типа
var
Lib: THandle;
DbgUiConnectToDbg: TDbgUiConnectToDbg; // "Будущая" процедура/функция
Status: NTStatus;
begin
Lib := LoadLibrary("ntdll.dll"); // Загрузка библиотеки
if Lib <> 0 then // Если удачно, то
try
DbgUiConnectToDbg := GetProcAddress(Lib, "DbgUiConnectToDbg"); // Получение адреса процедуры/функции
if Assigned(DbgUiConnectToDbg) then // Если процедура/функция найдена (адрес задан)
Status := DbgUiConnectToDbg({параметры}); // Вызов процедуры/функции с передачей параметров и получением результата
finally
FreeLibrary(Lib); // Выгрузка библиотеки
end;
end;
← →
Igit (2005-06-23 12:02) [3]Все, понял, буду разбираться, спасибо!
← →
begin...end © (2005-06-23 12:04) [4]> -=XP=- © (23.06.05 11:53) [2]
Э-э-э... А stdcall не помешает?
← →
-=XP=- © (2005-06-23 12:12) [5]Э-э-э... А stdcall не помешает?
Э-э-э-э... естественно. :)
Для пущей надежности - safecall.
В контексте, автору:
TDbgUiConnectToDbg = function({параметры}): NTStatus; stdcall; {safecall;}
← →
Igit (2005-06-23 12:16) [6]Я запутался... =(
Вот есть примерный модуль.unit SuUnit;
interface
uses windows;
////////////////////////// Ntdll.dll Functions ///////////////////////
Function ZwCreateThread(ThreadHandle: pdword;
DesiredAccess: ACCESS_MASK;
ObjectAttributes: pointer;
ProcessHandle: THandle;
ClientId: PClientID;
ThreadContext: pointer;
UserStack: pointer;
CreateSuspended: boolean):NTStatus;
stdcall;external "ntdll.dll";
implementation
end.
Как мне изменить его так, чтобы в самой программе и в других модулях использующих этот прошло все прозрачно, т.е. менять ничего не нужно было бы.
← →
-=XP=- © (2005-06-23 12:34) [7]
unit SuUnit;
interface
uses
Windows;
type
TZwCreateThread = function(ThreadHandle: pdword;
DesiredAccess: ACCESS_MASK;
ObjectAttributes: pointer;
ProcessHandle: THandle;
ClientId: PClientID;
ThreadContext: pointer;
UserStack: pointer;
CreateSuspended: boolean):NTStatus;
stdcall;
var
ZwCreateThread: TZwCreateThread;
implementation
end.
Только вот библиотеку загрузить надо. И указатель на функцию получить. В противном случае, при использовании неинициализированной процедурной переменной будет вызван Access Violation. Когда это (загрузку) сделать - Ваше дело. Главное, чтобы это было сделано до первого использования функции. Ну, или в любом месте, где используется эта функция - делать проверку:if Assigned(ZwCreateThread) then ZwCreateThread({параметры});
Но, судя по вопросу - такая проверка невозможна.
Поэтому, можете пойти по другому пути - написать "подставную" функцию, возвращающую "подставной" результат. В разделе инициализации модуля написать:implementation
function ZwCreateThread_Int({параметры}): NTStatus;
begin
// Не забудьте определить возвращаемые значения
end;
initialization
ZwCreateThread := @ZwCreateThread_Int;
end;
А если потом удастся загрузить внешнюю библиотеку - будете пользоваться ею.
← →
-=XP=- © (2005-06-23 12:37) [8]stdcall; - естественно, тоже указать. :)
← →
Igit (2005-06-23 12:44) [9]Я не доконца понял, но навязался такой вопрос, может он глупый, но возник :) Т.к. функции в этом модуле вызываются только если запущена WinNT, то может неоязательно загружать библиотеку ntdd, она ведь в NT всегда загружена?
← →
Digitman © (2005-06-23 12:52) [10]
> может неоязательно загружать библиотеку ntdd, она ведь в
> NT всегда загружена?
может и необязательно.
GetModulehandle() в дан.случае даст тот же результат, что и LoadLibrary()
разница в дан.случае практически неощутима - Load/FreeLibrary() инкрементирует/декрементирует некий (детали неважны) внутрисистемный сч-к использования библ-ки, кроме собссно ее штатной загрузки/иниц-ии/деиниц-ции/выгрузки, в то время как GetModuleHandle() просто ищет модуль в АП процесса, возвращает его хэндл (в случае с НТ - гарантированно), и этот хэндл в любой момент можно передать на вход GetProcAddress(), без опасений ан тему неактуальности в некий момент времени полученного адреса.
← →
-=XP=- © (2005-06-23 12:54) [11]она ведь в NT всегда загружена
Библиотека загружается или динамически (LoadLibrary) или статически (с указанием external).
Если модуль имеет объявления extrnal процедур/функций - то библиотека будет загружена автоматически при запуске приложения; если библиотека не обнаружится на компьютере - приложение не запустится никогда. Если нет явного указания (статического) использования внешних процедур/функций из этой библиотеки - она (библиотека) не будет загружена автоматически никогда. Для динамической загрузки используйте LoadLibrary.
Резюмируя: хотите кроссплатформенности - используйте динамическую загрузку библиотек; использование статического подключения библиотек, при отсутствии оных на компьютрере пользователя, вызовет аварийное завершение работы программы.
← →
-=XP=- © (2005-06-23 12:56) [12]GetModuleHandle() просто ищет модуль в АП процесса, возвращает его хэндл (в случае с НТ - гарантированно)
Почему?
← →
Igit (2005-06-23 13:04) [13]-=XP=- Если модуль имеет объявления extrnal процедур/функций - то библиотека будет загружена автоматически при запуске приложения; если библиотека не обнаружится на компьютере
NativeAPI в NT берутся из ntdll... все АПИ используют NativeAPI, значит в NT она по идее загружена всегда.
← →
-=XP=- © (2005-06-23 13:08) [14]Так ntdd или ntdll? :)
Я описал ситуацию в общем, применительно к любой библиотеке.
Что делать в конкретном случае - Ваше дело. ;)
← →
Digitman © (2005-06-23 13:14) [15]
> -=XP=- © (23.06.05 12:56) [12]
> Почему?
речь, очевидно, шла о ntdll.dll
импорт ее - статический
гоняй туда-сюда ее счетчик - выгрузить штатными ср-вами тебе ее не удастся
потому и сабж
← →
-=XP=- © (2005-06-23 13:21) [16]NativeAPI в NT берутся из ntdll... все АПИ используют NativeAPI, значит в NT она по идее загружена всегда.
program Test;
var
f: TextFile;
begin
AssignFile(f, "c:\test.txt");
Rewrite(f);
Writeln(f, "Я подозреваю, что в адресное пространство этого "приложения" не загружено ни одной библиотеки");
CloseFile(f);
end.
Но это так, к примеру.
Еще раз: если в приложении есть статическая линковка какой-то библиотеки, то эта библиотека будет загружена в АП. Если статической линковки нет - библиотека загружена не будет. Исключение - когда одна библиотека линкует другую библиотеку. Но опираться на этот факт не стоит, ибо это недокументированное поведение.
Хотите в приложении знать, загружена ли библиотека, или нет - используйте как приведено в [10], но, все же, проверяйте Handle на валидность.
← →
-=XP=- © (2005-06-23 13:26) [17]речь, очевидно, шла о ntdll.dll
Если так - то да, в приложениях Delphi (с использованием VCL), работающих под NT, эта библиотека загружена всегда. Хотя, это поведение, насколько мне известно - не документированно Microsoft?
← →
Igit (2005-06-23 13:58) [18]Так, проверить решил..
Заморозил выполнение на CloseFile(f); и посмотрел в LordPE. Вместе сней загружены такие dll
rptc4.dll
advapi32.dll
gdi32.dll
user32.dll
kernel32.dll
ntdll.dll
И еще вопрос, я не понял, в коде
-=XP=- © (23.06.05 12:34) [7] куда передавать хэнд загруженной dll?
← →
-=XP=- © (2005-06-23 14:20) [19]Так, проверить решил..
О как! Век живи - век учись! :о)
куда передавать хэнд загруженной dll
В GetProcAddress(<Handle>, "<ProcName>");
← →
Igit (2005-06-23 14:28) [20]Нет, неправильно выразился, в этом модуле
unit SuUnit;
interface
uses
Windows;
type
TZwCreateThread = function(ThreadHandle: pdword;
DesiredAccess: ACCESS_MASK;
ObjectAttributes: pointer;
ProcessHandle: THandle;
ClientId: PClientID;
ThreadContext: pointer;
UserStack: pointer;
CreateSuspended: boolean):NTStatus;
stdcall;
var
ZwCreateThread: TZwCreateThread;
implementation
end.
Куда нужно всавить GetModuleHandle и GetProcAddress чтобы в других модулях использующих эту функцию не нужно было ничего изменять?
← →
-=XP=- © (2005-06-23 14:45) [21]
<...>
implementation
<...>
var
Lib: THandle;
<...>
initialization
if (<Под NT>) then
begin
Lib := LoadLibrary(<...>);
ZwCreateThread := GetProcAddress(Lib, <...>);
<...>
end
else
<...>
finalization
if (Lib <> 0) then FreeLibrary(Lib);
end.
← →
Igit (2005-06-23 16:11) [22]Все зделал как положено, но
type
Function TZwCreateThread(<параметры>):NTStatus;stdcall;
выдает ошибку "Identifier expected but FUNCTION found"
Что я не так сделал?
← →
Digitman © (2005-06-23 16:21) [23]
> Что я не так сделал?
ты нарушил языковые соглашения Паскаля, который ожидает в дан.случае следующее :
type
TZwCreateThread = Function(<параметры>):NTStatus;stdcall;
где TZwCreateThread - это тот самый cимвольный идентификатор типа, который expected, но вместо которого компилятор встретил зарезервированное ключ.слово function
строки в секции type должны соответствовать правилу
Символьный_Идентификатор_Типа = Выражение_описывающее_тип;
← →
-=XP=- © (2005-06-23 16:34) [24]Все зделал как положено, но
А это кому написано было:
type
TZwCreateThread = function(ThreadHandle: pdword;
DesiredAccess: ACCESS_MASK;
ObjectAttributes: pointer;
ProcessHandle: THandle;
ClientId: PClientID;
ThreadContext: pointer;
UserStack: pointer;
CreateSuspended: boolean):NTStatus;
stdcall;
← →
Igit (2005-06-23 16:44) [25]Спасибо большое всем вам за помощь! У меня все получилось... зделал для себя вывод: забыл я все, нужно прочитать про синтаксис паскаля, и организацию модулей.
← →
Игорь Шевченко © (2005-06-23 19:13) [26]http://www.schevchenko.net.ru/SRC/Common_60.zip
Там пример (ntdll.pas) который меня ни разу не подводил. Изучай.
← →
GrayFace © (2005-06-23 20:16) [27]А если надо, чтобы библиотека загружалась динамически, но навсегда, нормально ли вызывать много раз LoadLibrary, не вызывая Free?
← →
Digitman © (2005-06-24 08:20) [28]
> нормально ли вызывать много раз LoadLibrary, не вызывая
> Free?
достаточно один раз вызвать LoadLibrary
← →
GrayFace © (2005-06-27 10:49) [29]Digitman © (24.06.05 8:20) [28]
достаточно один раз вызвать LoadLibrary
Это требует определенных усилий - сохранять, какие библиотеки загружены, какие - нет. А если проверять GetModuleHandle, то ее могут выгрузить. Просто маленькая функция для динамической загрузки - часть моего пакета.
← →
-=XP=- © (2005-06-27 11:17) [30]достаточно один раз вызвать LoadLibrary
Мне тут "под руку" попался какой-то китайский менеджер памяти (вместо ShareMem) - называется, кажется, ShareMemRep.pas (но это к слову). Единственное, чем интересен - не требует borlandmm.dll в комплекте с программой поставлять.
Так вот, этот менеджер, при завершении приложения, проверяет динамически загруженные библиотеки, и очень настойчиво ругается (возможна утечка памяти, говорит), если хоть одна библиотека осталась в памяти. Приходится четко отслеживать процесс выгрузки.
← →
evvcom © (2005-06-27 11:31) [31]
> Это требует определенных усилий - сохранять, какие библиотеки
> загружены, какие - нет. А если проверять GetModuleHandle,
> то ее могут выгрузить.
А ты возьми себе за правило, что если ты в классе вызвал LoadLibrary, то в нем же вызываешь и FreeLibrary, когда более она не нужна. И так в каждом классе. И никаких глобальных счетчиков и проч. Этот счетчик уже есть в системе и работает он лучше, чем напишешь ты.
← →
GrayFace © (2005-06-28 20:59) [32]evvcom © (27.06.05 11:31) [31]
У меня не класс, а маленькая функция для динамической загрузки. (См. [29])
← →
GrayFace © (2005-06-28 21:00) [33]-=XP=- © (27.06.05 11:17) [30]
Единственное, чем интересен - не требует borlandmm.dll в комплекте с программой поставлять.
Неужто, обычный требует?
Страницы: 1 вся ветка
Форум: "WinAPI";
Текущий архив: 2005.08.21;
Скачать: [xml.tar.bz2];
Память: 0.55 MB
Время: 0.049 c