Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "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
1-1122590919
Marat_D
2005-07-29 02:48
2005.08.21
Нужна структура ISO-файла...


14-1122396313
БарЛог
2005-07-26 20:45
2005.08.21
Различные способы вычисления 2х2


14-1122893854
GRAND25
2005-08-01 14:57
2005.08.21
Во смекалка!


14-1122543830
Mx
2005-07-28 13:43
2005.08.21
О кроссплатформенности в Delphi 2005


11-1105566860
koller
2005-01-13 00:54
2005.08.21
FormatFloat





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский