![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Динамический импорт функции из DLL [D7]
Igit © (2005-06-23 11:43:00)Здравтсвйте мастера! Есть у меня одлин модуль, в нем описываются функции вызываемые из NTDLL.DLL... они видны в таблице импорта... и из-за них под вин9x программа не запускается вовсе... (у меня в программе идет проверка какая винда и в зависимости от этого исп. тот или иной метод). Так вот, как можно переписать например вот это
Function DbgUiConnectToDbg(): NTStatus;stdcall;external 'ntdll.dll';
на такое чтоб не жестко привязывалось к ntdll а динамически?
Igit (2005-06-23 13:04:00) [21]-=XP=- Если модуль имеет объявления extrnal процедур/функций - то библиотека будет загружена автоматически при запуске приложения; если библиотека не обнаружится на компьютере
NativeAPI в NT берутся из ntdll... все АПИ используют NativeAPI, значит в NT она по идее загружена всегда.
-=XP=- (2005-06-23 12:56:00) [22]GetModuleHandle() просто ищет модуль в АП процесса, возвращает его хэндл ( в случае с НТ - гарантированно)
Почему?
-=XP=- (2005-06-23 12:54:00) [23]она ведь в NT всегда загружена
Библиотека загружается или динамически (LoadLibrary) или статически (с указанием external).
Если модуль имеет объявления extrnal процедур/функций - то библиотека будет загружена автоматически при запуске приложения; если библиотека не обнаружится на компьютере - приложение не запустится никогда. Если нет явного указания (статического) использования внешних процедур/функций из этой библиотеки - она (библиотека) не будет загружена автоматически никогда. Для динамической загрузки используйте LoadLibrary.
Резюмируя: хотите кроссплатформенности - используйте динамическую загрузку библиотек; использование статического подключения библиотек, при отсутствии оных на компьютрере пользователя, вызовет аварийное завершение работы программы.
Digitman (2005-06-23 12:52:00) [24]
> может неоязательно загружать библиотеку ntdd, она ведь в
> NT всегда загружена?
может и необязательно.
GetModulehandle() в дан.случае даст тот же результат, что и LoadLibrary()
разница в дан.случае практически неощутима - Load/FreeLibrary() инкрементирует/декрементирует некий (детали неважны) внутрисистемный сч-к использования библ-ки, кроме собссно ее штатной загрузки/иниц-ии/деиниц-ции/выгрузки, в то время как GetModuleHandle() просто ищет модуль в АП процесса, возвращает его хэндл (в случае с НТ - гарантированно), и этот хэндл в любой момент можно передать на вход GetProcAddress(), без опасений ан тему неактуальности в некий момент времени полученного адреса.
Igit (2005-06-23 12:44:00) [25]Я не доконца понял, но навязался такой вопрос, может он глупый, но возник :) Т.к. функции в этом модуле вызываются только если запущена WinNT, то может неоязательно загружать библиотеку ntdd, она ведь в NT всегда загружена?
-=XP=- (2005-06-23 12:37:00) [26]stdcall; - естественно, тоже указать. :)
-=XP=- (2005-06-23 12:34:00) [27]
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;
А если потом удастся загрузить внешнюю библиотеку - будете пользоваться ею.
Igit (2005-06-23 12:16:00) [28]Я запутался... =(
Вот есть примерный модуль.
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:12:00) [29]Э-э-э... А stdcall не помешает?
Э-э-э-э... естественно. :)
Для пущей надежности - safecall.
В контексте, автору:
TDbgUiConnectToDbg = function({параметры}): NTStatus; stdcall; {safecall;}
begin...end (2005-06-23 12:04:00) [30]> -=XP=- © (23.06.05 11:53) [2]
Э-э-э... А stdcallне помешает?
Igit (2005-06-23 12:02:00) [31]Все, понял, буду разбираться, спасибо!
-=XP=- (2005-06-23 11:53:00) [32]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;
PVOzerski (2005-06-23 11:45:00) [33]В общем виде, используют сочетание функций LoadLibrary и GetProcAddress применительно к процедурной переменной.