I am attempting to prepare multiple callbacks from an NSIS script. I can get one callback to work - but two or more fails - and actually call the original callback. THe following is what I have in place
---- SCRIPT
GetFunctionAddress $2 FinalizeNotification
OfferSDK.Packaging::NSISCallbackRegistration /NOUNLOAD $2
GetFunctionAddress $2 CancelNotification
OfferSDK.Packaging::NSISCancelCallbackRegistration /NOUNLOAD $2
Function CancelNotification
MessageBox MB_OK "Cancel Requested"
FunctionEnd
Function FinalizeNotification
MessageBox MB_OK "got here"
StrCpy $R9 1
Call RelGotoPage
FunctionEnd
--- C++
__declspec(dllexport) void NSISCallbackRegistration(HWND hWndParent, int this_string_size, char* thisvariables, stack_t** thisstacktop, extra_parameters* extra)
{}
__declspec(dllexport) void NSISCancelCallbackRegistration(HWND hWndParent, int this_string_size, char* thisvariables, stack_t** thisstacktop, extra_parameters* extra)
{}
unclear why it does not work. There is no infomration in NSIS documentatrion and examples are limited and incomplete - so I've had to guess what is required. If somone can provide a complete example showing multiple callback regsitrations - would be greatly appreciated.
Peter
Callback
4 posts
Check that the two $2s are different numbers. The number is basically an instruction count offset into the code.
In C++ you have to add or subtract 1 from the number when calling IIRC.
In C++ you have to add or subtract 1 from the number when calling IIRC.
I changed the second registration to use $3 - and I have the C++ subtracting 1 when calling. It works on original - but does not work on second callback.Originally Posted by Anders View PostCheck that the two $2s are different numbers. The number is basically an instruction count offset into the code.
In C++ you have to add or subtract 1 from the number when calling IIRC.
Is there a complete example of multiple callback registration?
Perhaps your plugin is unloaded between each call so it forgets the address? Are you using RegisterPluginCallback, /NoUnload or SetPluginsUnload?
There is nothing special about having multiple callbacks:
There is nothing special about having multiple callbacks:
/* Note: This is both the NSIS and C++ code in one file. */
#if 0 // NSIS:
Unicode False
!addplugindir "."
RequestExecutionLevel User
Function F1
MessageBox MB_OK "F1 called"
FunctionEnd
Function F2
MessageBox MB_OK "F2 called"
FunctionEnd
Section
GetFunctionAddress $0 F1
CallbackTest::SetCallback1 /NoUnload ; /NoUnload or SetPluginsUnload required
GetFunctionAddress $0 F2
CallbackTest::SetCallback2 ; Requires the plug-in to call RegisterPluginCallback
CallbackTest::Trigger ; Just a simple way to start calling back
SectionEnd
!if 0
#else // C++:
#include <windows.h>
#include <stdlib.h>
#include <tchar.h>
typedef struct {
int*sloppy_hack; // Not using this
int (WINAPI*ExecuteCodeSegment)(int, HWND);
void (WINAPI*validate_filename)(LPTSTR);
int (WINAPI*RegisterPluginCallback)(HINSTANCE, UINT_PTR(__cdecl*f)(int));
} extra_parameters;
typedef struct _stack_t { struct _stack_t *next; TCHAR text[1]; } stack_t;
#define NPPUBEXPORT EXTERN_C __declspec(dllexport) void __cdecl
static char remember_to_fix_unicode_in_nsi_if_you_remove_this[sizeof(OSVERSIONINFO) == sizeof(OSVERSIONINFOA)];
HINSTANCE g_hInst;
int g_CallbackAddr1 = 0;
int g_CallbackAddr2 = 0;
UINT_PTR __cdecl NsisPluginCallback(int Reason)
{
return 0;
}
NPPUBEXPORT SetCallback1(HWND hWndNsis, UINT cchNsis, PTSTR Vars, stack_t **ppST, extra_parameters*pXP, ...)
{
LPTSTR r0 = Vars;
g_CallbackAddr1 = _ttoi(r0);
// Note: Not calling RegisterPluginCallback. The script must use /NoUnload!
}
NPPUBEXPORT SetCallback2(HWND hWndNsis, UINT cchNsis, PTSTR Vars, stack_t **ppST, extra_parameters*pXP, ...)
{
LPTSTR r0 = Vars;
g_CallbackAddr2 = _ttoi(r0);
pXP->RegisterPluginCallback(g_hInst, NsisPluginCallback); // Prevent FreeLibrary
}
NPPUBEXPORT Trigger(HWND hWndNsis, UINT cchNsis, PTSTR Vars, stack_t **ppST, extra_parameters*pXP, ...)
{
for (;;)
{
switch(MessageBox(hWndNsis, TEXT("\"Try Again\" for callback 1\n\n\"Continue\" for callback 2"), TEXT("?"), MB_ICONQUESTION|MB_CANCELTRYCONTINUE))
{
case IDCANCEL:
return;
case IDTRYAGAIN:
if (g_CallbackAddr1) pXP->ExecuteCodeSegment(g_CallbackAddr1 - 1, NULL);
break;
case IDCONTINUE:
if (g_CallbackAddr2) pXP->ExecuteCodeSegment(g_CallbackAddr2 - 1, NULL);
break;
}
}
}
EXTERN_C BOOL WINAPI _DllMainCRTStartup(HINSTANCE hInst, DWORD, void*)
{
g_hInst = hInst;
return TRUE;
}
#if 0
!endif
#endif
#endif