Delphi - Keresési algoritmus DLL betöltésére

forráskód letöltése
A cikkben bemutatásra kerülő függvény különleges tulajdonsága, hogy az exe-ből meghívni kívánt DLL-t különböző keresési algoritmusok segítségével képes felkutatni. Amennyiben a betölteni kívánt DLL az őt meghívó exe könyvtárában nem található meg, a beállításoktól függően egy algoritmus szerint a függvény megkeresi azt.
A függvény felépítése a következő:
LoadLibraryEx
HMODULE LoadLibraryEx(
LPCTSTR lpFileName,
HANDLE hFile,
DWORD dwFlags
);
Paraméterek
LPCTSTR lpFileName
A betöltendő futtatható állományra (.dll vagy .exe fájl) mutató string.
Amennyiben a string egy elérési útvonalat határoz meg, de a betöltendő modul azon nem található, a függvény futása sikertelen lesz.
Amennyiben a string nem határoz meg elérési útvonalat, a függvény egy standard keresési stratégiát használ a fájl keresésére. Erről a későbbiekben olvashatunk.
Amennyiben a fájl neve nem tartalmaz kiterjesztést, úgy az alapértelmezett .dll kiterjesztést fűzi hozzá a rendszer.
HANDLE hFile
Ez a paraméter a jövőbeni fejlesztések részére készült, értéke NULL kell, hogy legyen.
DWORD dwFlags
Különböző műveleteket határoz meg, melyek a modul betöltésekor hajtódnak végre.
Értékei a következők lehetnek:
  • DONT_RESOLVE_DLL_REFERENCES: Amennyiben ezt az értéket használjuk egy DLL betöltésére, a rendszer nem hívja meg a DllMain-t az inicializáláshoz, illetve a memória felszabadításához, valamint nem tölti be azokat a futtatható modulokat, melyekre a betöltendő modulban hivatkozunk. Windows Me/98/95 alatt ez az érték nem támogatott.
  • LOAD_IGNORE_CODE_AUTHZ_LEVEL: Amennyiben ezt az értéket állítjuk be, a rendszer nem vizsgálja, hogy az adott DLL, illetve az abban meghívott egyéb modulok betöltéséhez van-e hozzáférési jogunk. Windows 2000/NT/Me/98/95 alatt ez az érték nem támogatott.
  • LOAD_LIBRARY_AS_DATAFILE: Használatakor a rendszer úgy tölti be a hívó fél részére a modult, mintha az egy adatfájl lenne. Használata akkor javasolt, ha a DLL-t csak üzenetek megjelenítésére vagy tárolására használjuk.
  • LOAD_WITH_ALTERED_SEARCH_PATH: Amennyiben ezt az értéket állítjuk be, és az lpFileName egy valós elérési útvonalat specifikál, a rendszer egy alternatív keresési módszert használ a betöltendő futtatható modul keresésére.
Amennyiben nem ezt az értéket használjuk, vagy az lpFileName-ben nincs megadva elérési út, a rendszer a standard keresési stratégiát alkalmazza a modul felkutatására.
Keresési módszerek:
A standard módszer az alábbi sorrendben keresi a betöltendő modult:
1. Az a könyvtár, melyben a hívó alkalmazás exe-je található
2. Az aktuális könyvtár
3. A Windows System könyvtára
4. A 16 bites System könyvtár (Windows ME/98/95 alatt nem létezik ilyen)
5. A Windows könyvtára
6. A rendszer PATH környezeti változójában megadott elérési útvonalak
Az alternatív módszer keresési sorrendje a következő:
1. Az lpFileName-ben specifikált útvonal, azaz az a könyvtár, melyben maga a DLL foglal helyet
2. Az aktuális könyvtár
3. A Windows System könyvtára
4. A 16 bites System könyvtár (Windows ME/98/95 alatt nem létezik ilyen)
5. A Windows könyvtára
6. A rendszer PATH környezeti változójában megadott elérési útvonalak
Fenti sorrendek eltérőek lehetnek Windows Server 2003, illetve Windows XP esetében.
Példaprogram:
A programunk két részből áll. Az egyikkel létrehozzuk magát a DLL-t, illetve azon belül egy függvényt, melyet az exe-ből meghívunk.
function ShowModalForm: integer; stdcall;
begin
  Form1:=TForm1.Create(nil);
  result:=Form1.ShowModal;
  Form1.Free;
end;
Az exe-ben betöltjük a LoadLibraryEx függvény segítségével a FormTest.dll-t. Keresési módnak a LOAD_WITH_ALTERED_SEARCH_PATH paramétert állítottuk be, így a DLL-t nem szükséges a hívó exe könyvtárában elhelyezni. Kipróbálhatjuk, hogy amennyiben a Windows System könyvtárába helyezzük a DLL-t, a program ott is meg fogja találni.
  dll:=LoadLibraryEx('FormTest.dll',0,LOAD_WITH_ALTERED_SEARCH_PATH);
  if dll<>0 then begin
    @ShowModalForm:=GetProcAddress(dll, 'ShowModalForm');
    ShowModalForm;
Amennyiben a modul sikeresen betöltődött, a GetProcAddress függvénnyel lekérdezzük a számunkra szükséges függvény címét, majd megjelenítjük azt.
    FreeLibrary(dll);
Ezután a FreeLibrary() segítségével felszabadítjuk a modul által lefoglalt memóriaterületet.
  end else begin
    ShowMessage('A FormTest.dll nem található!');
  end;
Amennyiben a DLL keresése nem jár sikerrel, azaz a megadott keresési mód által specifikált egyik könyvtárban sem található, üzenetet küldünk a felhasználó felé.