prion
27th April 2010 23:10 UTC
RegisterPluginCallback - Delphi
Hi,
I'm looking for an example or a reference on how to use the RegisterPluginCallback with delphi. I had a look at several plugins developed in delphi but couldn't find anyone using the new plugin api and the RegisterPluginCallback.
I would guess the callback works like passing the RegisterPluginCallback a pointer to a function so nsis can call it back, but the RegisterPluginCallback expects 2 integers (unknow and uknown2) and I can't really figure out what exactly to pass there.
So it would be great if you guys could perhaps give me a short example or point me to a reference explaining what nsis expects when using this function.
Thanks.
Anders
28th April 2010 01:38 UTC
int (NSISCALL *RegisterPluginCallback)(HMODULE, NSISPLUGINCALLBACK); // returns 0 on success, 1 if already registered and < 0 on errors
so, it takes the HMODULE aka HINSTANCE of your dll and a function pointer. NSISPLUGINCALLBACK is currently: typedef UINT_PTR (*NSISPLUGINCALLBACK)(enum NSPIM);
so, a __cdecl function that (currently) has a single int parameter and returns a uintptr_t (return 0/NULL)
prion
28th April 2010 08:57 UTC
Thanks for your reply.
RegisterPluginCallback now succeeds, but the installer crashes right after calling the InitPlugin function of my plugin. Could you please have a look at the code below, maybe you see what I'm doing wrong.
Plugin Code:
function NSISCallback(const NSPIM: Integer): Integer; cdecl;
begin
ShowMessage('NSISCallback ' + IntToStr(NSPIM));
Result := 0;
end;
procedure InitPlugin(const hwndParent: HWND; const string_size: integer;
const variables: PChar; const stacktop: pointer;
const extraparameters: pointer = nil); cdecl;
var
iResult: Integer;
begin
Init(hwndParent, string_size, variables, stacktop, extraparameters);
iResult := TRegisterPluginCallback(extrap.RegisterPluginCallback)(HINSTANCE,
Integer(@NSISCallback));
ShowMessage('RegisterPluginCallback ' + IntToStr(iResult));
end;
the above ShowMessage shows that RegisterPluginCallback results in 0.
NSIS Code:
nsTEST::InitPlugin
MessageBox MB_OK "1"
the above MessageBox never pops up, instead the installer crashes.
Thanks.
edit: formatting.
Anders
28th April 2010 21:08 UTC
What is HINSTANCE there? Does not look like a variable to me. You get the correct HINSTANCE in DllMain.
Another possible problem is Integer(@NSISCallback), maybe it should not be a @ (pointer?) Delphi supports asm IIRC, so try something like:
__asm push DWORD PTR 0;
__asm call Integer(@NSISCallback);
And what is TRegisterPluginCallback? Some kind of cast? I have not used Delphi in years so I don't remember anything other than the basics.
prion
28th April 2010 23:04 UTC
I finally found the solution. It's the declaration of RegisterPluginCallback in the NSIS Delphi header (nsis.pas) which is as follows:
TRegisterPluginCallback = function (const unknow: Integer; const uknown2: Integer): Integer; cdecl;
After your reply I had another look at the problem and declared my own RegisterPluginCallback (didn't want to modify nsis.pas). Since I don't usually use cdecl I accidently declared it as stdcall and that's actually it. I tried running my plugin and it works when using stdcall instead of cdecl:
TRegisterPluginCallback = function (const unknow: Integer; const uknown2: Integer): Integer; stdcall;
So like that nothing crashes, my plugin stays loaded and the callback function is called when closing the installer.
Anders
28th April 2010 23:22 UTC
Thanks, I updated nsis.pas so it will be fixed in the next release.
If you look at https://nsis.svn.sourceforge.net/svn.../exehead/api.h (should be used as reference for other languages) you see that it is indeed stdcall
prion
29th April 2010 09:02 UTC
Just tried your changes in nsis.pas and it's working fine.
And for anyone looking for a delphi example on how to use the new plugin api (like I was originally) I've attached a quick example.