0
votes

I loaded multiple dlls using LoadLibrary in the NSIS script as part of my project. Because the other dlls are references of the main dll. After that how to call the function using GetProcAddress? Because i have loaded multiple DLLs.

Below is my code snippet:

    !include LogicLib.nsh
    
    Section
    SetOutPath $InstDir
    File testutil.dll
    System::Call 'KERNEL32::LoadLibrary(t "$InstDir\Testutil.dll")p.r8 ?e'
System::Call 'KERNEL32::LoadLibrary(t "$InstDir\TestControls.dll")p.r8 ?e'
System::Call 'KERNEL32::LoadLibrary(t "$InstDir\TestDevice.dll")p.r8 ?e'
System::Call 'KERNEL32::LoadLibrary(t "$InstDir\loadtestdll.dll")p.r8 ?e'
    Pop $7
    ${If} $8 P<> 0
        MessageBox MB_OK 'Successfully loaded "$InstDir\testutil.dll" @ $8'
        System::Call 'KERNEL32::GetProcAddress(pr8, m "IsTherePower")p.r9 ?e'
        Pop $7
        ${If} $9 P<> 0
            MessageBox MB_OK 'Successfully found "IsTherePower" @ $9'
        ${Else}
            MessageBox MB_ICONSTOP 'Unable to find "IsTherePower", error $7'
        ${EndIf}
        System::Call 'KERNEL32::FreeLibrary(pr8)'
    ${Else}
        MessageBox MB_ICONSTOP 'Unable to load "$InstDir\testutil.dll", error $7'
    ${EndIf}

When I run this script, it is loading the DLL successfully. But It is not loading the function. Could you please help me to resolve the issue?

1
What does IsUPSPresent look like in Dependency Walker? - Anders
Can we ask what information you are trying to obtain? You seem to be working on some managed code interoperability? - Stein Åsmul
We know you are trying to call the IsUPSPresent function but when you don't even know if the function is exported correctly then this is not really a NSIS question. First you must fix your .DLL, then you can ask specific NSIS questions... - Anders
Could the GetSystemPowerStatus() Win32 call get you the information you need? I don' know, I haven't used it. And just for your review. I don't fully understand your scenario - naturally - so this might not be terribly useful. Power Management Functions. - Stein Åsmul

1 Answers

2
votes

When I run this script, it is loading the DLL successfully.

You are checking the wrong HMODULE in your posted example! You are just checking if pdcdll.dll loaded correctly, not the .DLL you want to check.

Ideally you should have a fair bit of experience with Win32 when using the System plug-in.

LoadLibrary will load dependent .DLLs for you, you don't have to do it manually in most cases. One potential issue is that NSIS activates some extra hardening protections to avoid loading hijacking-.DLLs and this could prevent a .DLL from loading its dependencies.

I will give you a complete example here that loads each .DLL manually but you should not do this normally, just load the .DLL you need and let Windows resolve the rest for you.

!include LogicLib.nsh

Section
SetOutPath $InstDir
File drvutil.dll
File UPSControls.dll
File UPSDevice.dll
File pdcdll.dll

System::Call 'KERNEL32::AddDllDirectory(w "$InstDir")' ; Tell Windows we trust all .DLLs in this directory

System::Call 'KERNEL32::LoadLibrary(t "$InstDir\pdcdll.dll")p.r8'
${IfThen} $8 P= 0 ${|} MessageBox MB_ICONSTOP "DEBUG: Failed to load pdcdll.dll" ${|}
System::Call 'KERNEL32::LoadLibrary(t "$InstDir\UPSDevice.dll")p.r8'
${IfThen} $8 P= 0 ${|} MessageBox MB_ICONSTOP "DEBUG: Failed to load UPSDevice.dll" ${|}
System::Call 'KERNEL32::LoadLibrary(t "$InstDir\UPSControls.dll")p.r8'
${IfThen} $8 P= 0 ${|} MessageBox MB_ICONSTOP "DEBUG: Failed to load UPSControls.dll" ${|}

System::Call 'KERNEL32::LoadLibrary(t "$InstDir\drvutil.dll")p.r8 ?e'
Pop $7 ; Get ?e result
${IfThen} $8 P= 0 ${|} MessageBox MB_ICONSTOP "Failed to load drvutil.dll, error $7" ${|}
${If} $8 P<> 0
  System::Call 'KERNEL32::GetProcAddress(pr8, m "IsUPSPresent")p.r9 ?e'
  Pop $7 ; Get ?e result
  ${IfThen} $9 P= 0 ${|} MessageBox MB_ICONSTOP "Failed to find the exported function, error $7. Inspect the .DLL with Dependency Walker to make sure the function is exported with the correct un-decorated name!" ${|}
${EndIf}

SectionEnd

If you get the "Failed to load drvutil.dll" message then you need to look at the .DLLs dependencies etc.

If you get the "Failed to find the exported function" message then you have not exported the function correctly. The function name should not be decorated. Dependency Walker will show you the exported function name. If you are unable to remove the decoration then you can pass the decorated name directly to GetProcAddress but then you need to keep in mind that the name is probably not the same if you compile as 64-bit or if you change to another compiler vendor.

It should look like this:

Dependency Walker