Archive: RegisterPluginCallback - Delphi


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.


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)


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.

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.

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.

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


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.