Archive: System::Call not working with custom DLL


System::Call not working with custom DLL
Hi,

I've written a function in my own DLL to find out if the user has permission to install the software version (based on a hardware dongle setting, but that detail is irrelevant). My function, in C, is something like this:

int WINAPI CanUserInstall(void)
{
int Ret = FALSE;

// do various checks
// if user is allowed to install, set Ret to TRUE;

return Ret;
}

This function is being exported by the DLL correctly (according to Microsoft's Dependency Walker app).

In my NSIS script, I have the following code:

SetOutPath "$TEMP"
File "installer.dll"
System::Call 'installer.dll::CanUserInstall(v) i.R0 ?e'
Pop $0
MessageBox MB_OK "Return value = $R0, lasterr = $0"
IntCmp $R0 1 OkToInstall CancelInstall

CancelInstall:
Abort "Not allowed to install"

OkToInstall:
; ... do the install

Firstly, the messagebox returns this:
"Return value = error, lasterr = 0"
Then the IntCmp always goes to the CancelInstall as $R0 always equals 0.

Any ideas where I'm going wrong? The error return implies it either can't load the DLL, or can't find the function in it, but I can't see where I've gone wrong.

Thanks for any help.
Nick.


you don't need ".dll". you don't need v, just () is fine, other than that it looks ok to me. And I'm sure you know, in this example, ?e is pointless since you don't call SetLastError or other windows api's


Re: System::Call not working with custom DLL

Originally posted by njshaw2

[B]Hi,

I've written a function in my own DLL to find out if the user has permission to install the software version (based
Last time i fiddled with System::Call I ended up with:

!define GetPrivateProfileString "kernel32::GetPrivateProfileStringA(t,t,t,t,i,t) i"


and
System::Call "${GetPrivateProfileString}('Version', 'DriverVer', '', .r1, ${NSIS_MAX_STRLEN}, r1) .s"

before it worked.

So in your case:

!define CanUserInstall "installer::CanUserInstall(v) i"

and
System::Call "${CanUserInstall} () .R0"


Maybe omitting the ".dll" already helps....

Good luck

AxelMock, dude, you know nsis already has .ini support?

and a define will not help at all, thats all precompiler magic and does not change the end result


Thanks for the suggestions. I've already tried without the ".dll", without the (v) and without the ?e - all give the same result.

I'm at the stage where I can't see the DLL is actually loaded - I've put OutputDebugStrings in the DLL's DllMain() which are never being called, so either NSIS is failing to load the DLL, or the DLL is not loading properly. Does the DLL need any specific calling convention or build property? I'm using WINAPI for the functions, and the project is built with Multi-threaded DLL support. It's also being built in VS2008, can't see why that could be an issue, but just in case.

It looks, from the replies, like I'm doing all the right stuff in NSIS (I can do calls to Win32 APIs fine, so I know the system.dll is working and my syntax is pretty much ok) - back to the old VS2008 debugging, it looks like.


Process Monitor from sysinternals should be able to help out. You can see both the filesystem operations to make sure it finds the file, and possible errors when the loader tries to map the dll


Originally posted by Anders
AxelMock, dude, you know nsis already has .ini support?
Yes, I know ConfigRead but it does NOT work on a Unicode inf-file.
GetPrivateProfileString works. And I can set the section in which to look for the value.

And converting the inf-file to ANSI did not work on the japanese/chinese Windows machine.

And last week I didn't have the Unicode to UTF-8 conversion...

I've found the problem I was having. Subtle. You need to include the path of your dll in the System::Call() information if your dll is not in the system path. The documentation doesn't specify this; it implies it will load it from the last configured "SetOutPath". Obviously not.

So I used:

SetOutPath "$TEMP"
File "Data\MyFile.dll"
System:Call "$TEMP\MyFile.dll:MyFunc() i.r0"

and from then on it was happy. :)


I think if you extract your dll to the same folder as the System.dll then it will work (i.e. $PLUGINSDIR).

Stu