Reagieren auf dliFailLoadLib (delay loaded dlls)



  • Hallo Leute,

    ich sitzt den ganzen Tag nun an folgendem Problem und verzweifle fast: Ich möchte eine shared library (unter windows) zur Laufzeit laden. Das klappt auch wunderbar.
    Habe das gemacht wie auch beim Laden zur Programminitialisierung (Linken mit der lib für dynamisches linken). Einzige Änderung in den Linker Optionen:
    "/DelayLoad:Dll.Dll"
    und
    "/Delay:unload"
    Wie gesagt. Stimmt der pfad zur dll klappt das dynamische laden auch wunderbar.

    Nun aber angenommen der vorgebene Pfad zur dll stimmt nicht. Es soll daraufhin ein OpenFileFiledialog aufpoppen, indem der Nutzer den Pfad zur Dll manuell angeben kann.

    Zum Minimalbeispiel:

    #include <iostream>
    
    #include <lib/header.h>
    #include <windows.h>
    #include <DelayImp.h>
    
    FARPROC WINAPI delayHook(unsigned dliNotify, PDelayLoadInfo pdli)
    {
        switch (dliNotify) 
    	{
            case dliFailLoadLib : 
    			{
    				std::string msg(pdli->szDll);
    				msg += " not found!";
    				throw std::exception(msg.c_str());
    
    				std::wstring newlibname(L"C:\\test\\delay_load_test\\debug\\_lib.dll");
    				HMODULE h = LoadLibrary(newlibname.c_str());
    				//return *h;
    			}
                break;
    
            case dliFailGetProc :
    			{
    				throw std::exception("procAdress not found!");
    			}
                break;
    
            default :
                return NULL;
        }
    
        return NULL;
    }
    
    //set the hook failure function to my one
    PfnDliHook __pfnDliFailureHook2 = delayHook;
    
    //the external function
    __declspec(dllexport) double add(double i, double j);
    
    int main()
    {
    	try
    	{
    		std::cout << "1.2 + 2.4 = " << add(1.2 , 2.4) <<std::endl;
    	}catch(const std::exception & e)
    	{
    		std::cerr << "could not load dll" << std::endl;
    		std::cerr << "message: "<< e.what() << std::endl;
    	}
    
    	return 0;
    }
    

    Funktioniert soweit schonmal ganz gut. Beim fehlerhaften laden (dll einfach umbenannt) wird die Funktion delayHook mit dliNotify==dliFailLoadLib auch aufgerufen.

    Nun das Problem: Ich möchte nun auf die Fehlermeldung geeignet reagieren. Also einen neuen Pfad setzen.

    Unter
    http://msdn.microsoft.com/de-de/library/sfcfb0a3(v=vs.80).aspx
    (und auch in den Sourcen von VC8) steht, dass dann ein neues HMODULE zurück gegeben werden muss. Das versteh ich als:

    HMODULE h = LoadLibrary(newlibname.c_str());
    return h;
    

    Dummerweise lässt sich das HMODULE aber nicht zu einer FARPROC casten.
    Oder seh ich da was falsch?

    Viele Grüße,
    Ka55ipeia.

    PS:
    Die Signatur für die delayHook Funktion habe ich von
    http://msdn.microsoft.com/de-de/library/f0fkfy9y.aspx



  • Ka55i0peia schrieb:

    Dummerweise lässt sich das HMODULE aber nicht zu einer FARPROC casten.

    Wieso nicht? Ich sehe da kein Problem, FARPROC ist jeweils so breit wie ein Zeiger.
    Kurzer Test:

    FARPROC GetModule()
    {
    	HMODULE h = GetModuleHandle(0);
    	return reinterpret_cast<FARPROC>(h);
    }
    int main()
    { 
    	char c[512];
    	HMODULE mod = reinterpret_cast<HMODULE>(GetModule());
    	GetModuleFileName(mod,c,512);
    	std::cout << c << '\n';
    
    	std::cout << std::hex << ((DWORD_PTR)(mod)) << '\n';
    	// Ausgabe bei mir:
    	// 400000 (32 Bit)
    	// 140000000 (64 Bit)
    }
    

    Nur wird bei dir der Code nicht erreicht.



  • Hey Thorgrim,

    return reinterpret_cast<FARPROC>(h);
    

    und fertig ist der Schuh 🙄

    Vielen Dank für die schnelle, kompetente Hilfe! 👍


Anmelden zum Antworten