Archive: Help with plugin development


Help with plugin development
Hi,

I am making a very simple dialog box in C since I needed certain features that I couldn't get with NSIS.

The program works as a dll, but now I am trying to convert it into a plugin and having all sorts of problems.

Essentially I have a function that calls the dialog box and based on whats returned gets a certain number which the dll function is calling.


void __declspec(dllexport) SHOW(HWND hwndParent, int string_size, char *variables, stack_t **stacktop)
{
g_stacktop=stacktop;
{
popstring(szBuf);
popstring(szError);
nVarError=getvarindex(szError);

wsprintf(szBuf, "%d", RunDialogBox() );
setvar(nVarError, szBuf, string_size, variables);
}
}


This was the original before adding the dll (obviously the below wasnt commented out)


//__declspec(dllexport)
int RunDialogBox() // DemoDialogBoxDll::RunDialogBox
{
int result = FALSE;

result = DialogBoxParam(hModule, MAKEINTRESOURCE(IDD_DIALOG), NULL, DialogProc, (LPARAM)(NULL));

return result;
}



Warning 1 warning C4133: 'function' : incompatible types - from 'char *' to 'LPWSTR' c:\Documents and Settings\jweinraub\Desktop\DemoDialogBoxDll\DemoDialogBoxDll\DemoDialogBoxDll.c 73 DemoDialogBoxDll
Warning 2 warning C4133: 'function' : incompatible types - from 'char [1024]' to 'LPCWSTR' c:\Documents and Settings\jweinraub\Desktop\DemoDialogBoxDll\DemoDialogBoxDll\DemoDialogBoxDll.c 73 DemoDialogBoxDll
Warning 3 warning C4133: 'function' : incompatible types - from 'char *' to 'LPWSTR' c:\Documents and Settings\jweinraub\Desktop\DemoDialogBoxDll\DemoDialogBoxDll\DemoDialogBoxDll.c 83 DemoDialogBoxDll
Warning 4 warning C4133: 'function' : incompatible types - from 'const char *' to 'LPCWSTR' c:\Documents and Settings\jweinraub\Desktop\DemoDialogBoxDll\DemoDialogBoxDll\DemoDialogBoxDll.c 83 DemoDialogBoxDll
Warning 5 warning C4133: 'function' : incompatible types - from 'char *' to 'LPCWSTR' c:\Documents and Settings\jweinraub\Desktop\DemoDialogBoxDll\DemoDialogBoxDll\DemoDialogBoxDll.c 91 DemoDialogBoxDll

......

Warning 46 warning C4133: 'function' : incompatible types - from 'char [3]' to 'LPCWSTR' c:\Documents and Settings\jweinraub\Desktop\DemoDialogBoxDll\DemoDialogBoxDll\DemoDialogBoxDll.c 164 DemoDialogBoxDll

And help is greatly appreciated.

your project settings seem to be set for unicode, if you want to create a ansi plugin for the "normal" nsis, turn off unicode (no UNICODE defines). If you want to compile a unicode plugin for unicode nsis, change char to WCHAR in your code. If you want to compile for both, #include <TCHAR.H> and change char to TCHAR in your code


Thank you. I also found more errors happened because when I changed to Release, I forgot to change exe to dll!

I also changed the code completely.


#define _IBATWARNING_
#include "resource.h"
#include "IBATWarning.h"

/* Defines */
#define NSIS_MAX_STRLEN 1024

/* NSIS stack structure */
typedef struct _stack_t
{
struct _stack_t *next;
char text[NSIS_MAX_STRLEN];
} stack_t;

stack_t **g_stacktop;


HINSTANCE g_hInstance;
HWND g_hwndParent;
int g_stringsize;
char *g_variables;


char *getvar(int varnum);
void setvar(int varnum, char *var);
int runDialogBox();

/* Global variables */
char szBuf[NSIS_MAX_STRLEN]="";
char szError[4]="";
int nVarError;
int res = 0;

enum
{
INST_0, // $0
INST_1, // $1
INST_2, // $2
INST_3, // $3
INST_4, // $4
INST_5, // $5
INST_6, // $6
INST_7, // $7
INST_8, // $8
INST_9, // $9
INST_R0, // $R0
INST_R1, // $R1
INST_R2, // $R2
INST_R3, // $R3
INST_R4, // $R4
INST_R5, // $R5
INST_R6, // $R6
INST_R7, // $R7
INST_R8, // $R8
INST_R9, // $R9
INST_CMDLINE, // $CMDLINE
INST_INSTDIR, // $INSTDIR
INST_OUTDIR, // $OUTDIR
INST_EXEDIR, // $EXEDIR
__INST_LAST
};

BOOL APIENTRY DllMain( HANDLE hModulePar,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
hModule = hModulePar;
break;

case DLL_PROCESS_DETACH:
break;
}

return TRUE;
}

LRESULT CALLBACK DialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_INITDIALOG:
CheckDlgButton(hDlg, IDC_CHECK, FALSE);
EnableWindow(GetDlgItem(hDlg, IDOK), FALSE);
return TRUE;

case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDC_CHECK:
if (IsDlgButtonChecked(hDlg, IDC_CHECK))
{
EnableWindow(GetDlgItem(hDlg, IDOK), TRUE);
EnableWindow(GetDlgItem(hDlg, IDCANCEL), FALSE);
}
else
{
EnableWindow(GetDlgItem(hDlg, IDOK), FALSE);
EnableWindow(GetDlgItem(hDlg, IDCANCEL), TRUE);
}
break;
case IDOK:
{
EndDialog(hDlg, TRUE);
return FALSE;
}
case IDCANCEL:
{
EndDialog(hDlg, FALSE);
return FALSE;
}
}
}
return FALSE;
}
// Sets user variable
void setvar( int varnum, char * var )
{
if (var != NULL && varnum >= 0 && varnum < __INST_LAST)
{
lstrcpy (g_variables + varnum*g_stringsize, var);
}
}

// Gets user variable
char *getvar(int varnum)
{
if (varnum < 0 || varnum >= __INST_LAST)
return NULL;
return g_variables + varnum*g_stringsize;
}


void __declspec(dllexport) Show(HWND hwndParent, int string_size, char *variables, stack_t **stacktop)
{
g_hwndParent=hwndParent;
g_stringsize=string_size;
g_variables=variables;
res = runDialogBox();
if ( res == 0 )
setvar(INST_0,"abort" );
else
setvar(INST_0,"agree" );
}


//__declspec(dllexport)
int runDialogBox()
{
int result = FALSE;
result = DialogBoxParam(hModule, MAKEINTRESOURCE(IDD_DIALOG), NULL, DialogProc, (LPARAM)(NULL));

return result;
}

you can't use NSIS_MAX_STRLEN, you need to allocate memory at runtime with string_size size


Anders,

I am still very new at this, can you tell me how I exactly do that?


well, your current code is not using the stack or the szBuf global. But if you need to code that uses them, allocate and free the memory with GlobalAlloc/Free ( http://nsis.svn.sourceforge.net/view...56&view=markup has sample code for stack usage )


If I use it as is, is it a memory leak?

I pretty much did the dll project first, then I adapted it to nsis plugin by following some other sample code I found.

Essentially, this just plops up a dialogue box with several options in it, and it just returns 0 or 1 based on the box outcome.

So, $0 just gets the "agree" or "abort" and the nsis uses that and goes from there.


no, you can use it as is, setvar() does not have that problem (As long as the string is somewhat short like the ones you are using, if it is closer to 1024 or more, you probably need to use lstrcpyn in setvar and limit to string_size)

You should probably remove the NSIS_MAX_STRLEN define so you don't use it by accident in the future


Since I am more used to C++, I guess I should of done something like strSz = new strSz or somehting to allocate it to the pointer? Should I do that now?

How would you change that so it is better code?


do something like this....?


#define _IBATWARNING_
#include "resource.h"
#include "IBATWarning.h"

/* NSIS stack structure */
typedef struct _stack_t
{
struct _stack_t *next;
char text[256];
} stack_t;

stack_t **g_stacktop;


HINSTANCE g_hInstance;
HWND g_hwndParent;
int g_stringsize;
char *g_variables;


char *getvar(int varnum);
void setvar(int varnum, char *var);
int runDialogBox();

/* Global variables */
char szBuf[256]="";
char szError[4]="";
int nVarError;
int res = 0;

no, I already told you, you need to allocate memory with GlobalAlloc, you can't use fixed size arrays ( foo[...] )


void __declspec(dllexport) MyFunction(HWND h,int stringsize)
{
char*mystringbuffer;
mystringbuffer=(char*)GlobalAlloc(GPTR,stringsize);
//call popstring() from sample code I linked to to get string from stack
//do something with mystringbuffer...
GlobalFree(mystringbuffer);
}