Added experimental System plug-in v2 syntax option

git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@6955 212acab6-be3b-0410-9dea-997c60f758d6
This commit is contained in:
anders_k 2017-12-03 18:04:02 +00:00
parent ebfe3bf6d2
commit 9229c5df18
4 changed files with 243 additions and 122 deletions

View file

@ -42,7 +42,7 @@ const int ParamSizeByType[8] = {
0 // PAT_REGMEM //BUGBUG64?
};
// Thomas needs to look at this.
// The size of the base type when used in a struct with the '&' syntax (multiply by (Option - PAO_ARRBASE) to get the real size)
static const int ByteSizeByType[8] = {
1, // PAT_VOID
1, // PAT_INT
@ -66,15 +66,29 @@ HINSTANCE g_hInstance;
char retexpr[4]; //BUGBUG64?
HANDLE retaddr;
TCHAR *GetResultStr(SystemProc *proc)
static TCHAR *MakeResultStr(SystemProc *proc, TCHAR *buf)
{
TCHAR *buf = AllocString();
if (proc->ProcResult == PR_OK) lstrcpy(buf, _T("ok"));
else if (proc->ProcResult == PR_ERROR) lstrcpy(buf, _T("error"));
else if (proc->ProcResult == PR_CALLBACK) wsprintf(buf, _T("callback%d"), proc->CallbackIndex);
if (proc->ProcResult == PR_OK)
lstrcpy(buf, _T("ok"));
else if (proc->ProcResult == PR_ERROR)
lstrcpy(buf, _T("error"));
else if (proc->ProcResult == PR_CALLBACK)
{
INT_PTR id = proc->CallbackIndex;
#ifdef POPT_SYNTAX2
if (proc->Options & POPT_SYNTAX2)
id = (INT_PTR) GetAssociatedSysProcFromCallbackThunkPtr(proc->Proc);
#endif
wsprintf(buf, sizeof(void*) > 4 ? _T("callback%Id") : _T("callback%d"), id); // "%d" must match format used by system_pushintptr() in Get() because script will StrCmp!
}
return buf;
}
TCHAR *AllocResultStr(SystemProc *proc)
{
return MakeResultStr(proc, AllocString());
}
#ifdef SYSTEM_LOG_DEBUG
#ifndef COUNTOF
@ -253,19 +267,20 @@ PLUGINFUNCTION(Get)
SYSTEM_LOG_ADD(proc->ProcName);
//SYSTEM_LOG_ADD(_T("\n"));
SYSTEM_LOG_POST;
if ((proc->Options & POPT_ALWRETURN) != 0)
if (proc->Options & POPT_ALWRETURN)
{
// Always return flag set -> return separate proc and result
system_pushintptr((INT_PTR) proc);
GlobalFree(system_pushstring(GetResultStr(proc)));
} else
GlobalFree(system_pushstring(AllocResultStr(proc)));
}
else
{
if (proc->ProcResult != PR_OK)
{
// No always return flag and error result - return result
GlobalFree(system_pushstring(GetResultStr(proc)));
GlobalFree(system_pushstring(AllocResultStr(proc)));
// If proc is permanent?
if ((proc->Options & POPT_PERMANENT) == 0)
if (!(proc->Options & POPT_PERMANENT))
GlobalFree((HGLOBAL) proc); // No, free it
}
else // Ok result, return proc
@ -319,11 +334,11 @@ PLUGINFUNCTION(Call)
}
// Process output
if ((proc->Options & POPT_ALWRETURN) != 0)
if (proc->Options & POPT_ALWRETURN)
{
// Always return flag set - return separate return and result
ParamsOut(proc);
GlobalFree(system_pushstring(GetResultStr(proc)));
GlobalFree(system_pushstring(AllocResultStr(proc)));
}
else
{
@ -332,8 +347,10 @@ PLUGINFUNCTION(Call)
ProcParameter pp = proc->Params[0]; // Save old return param
// Return result instead of return value
proc->Params[0].Value = (INT_PTR) GetResultStr(proc);
TCHAR resstr[50];
proc->Params[0].Value = (INT_PTR) MakeResultStr(proc, resstr);
proc->Params[0].Type = PAT_TSTRING;
proc->Params[0].allocatedBlock = NULL;
ParamsOut(proc); // Return all params
proc->Params[0] = pp; // Restore old return param
@ -355,7 +372,7 @@ PLUGINFUNCTION(Call)
}
// If proc is permanent?
if ((proc->Options & POPT_PERMANENT) == 0) GlobalFree((HGLOBAL) proc); // No, free it
if (!(proc->Options & POPT_PERMANENT)) GlobalFree((HGLOBAL) proc); // No, free it
} PLUGINFUNCTIONEND
PLUGINFUNCTIONSHORT(Int64Op)
@ -436,7 +453,12 @@ SystemProc *PrepareProc(BOOL NeedForCall)
BOOL param_defined = FALSE;
SystemProc *proc = NULL;
TCHAR *ibuf, *ib, *sbuf, *cbuf, *cb;
unsigned int UsedTString = 0;
unsigned int UsedTString = 0, aligntype;
#ifdef POPT_SYNTAX2
const UINT alignflag = PAT_ALIGNFLAG;
#else
const UINT alignflag = 0;
#endif
#ifdef __GNUC__
temp3 = 0; // "warning: 'temp3' may be used uninitialized in this function": temp3 is set to 0 when we start parsing a new parameter
@ -472,7 +494,7 @@ SystemProc *PrepareProc(BOOL NeedForCall)
case _T('('):
SectionType = PST_PARAMS;
// fake-real parameter: for COM interfaces first param is Interface Pointer
ParamIndex = ((ProcType == PT_VTABLEPROC)?(2):(1));
ParamIndex = ((ProcType == PT_VTABLEPROC)?(2):(1));
temp3 = temp = 0;
param_defined = FALSE;
break;
@ -526,13 +548,13 @@ SystemProc *PrepareProc(BOOL NeedForCall)
if (pr != NULL) pr->Clone = NULL;
// Never Redefine?
if ((proc->Options & POPT_NEVERREDEF) != 0)
if (proc->Options & POPT_NEVERREDEF)
{
// Create new proc as copy
proc = GlobalCopy(proc);
// NeverRedef options is never inherited
proc->Options &= (~POPT_NEVERREDEF) & (~POPT_PERMANENT);
} else proc->Options |= POPT_PERMANENT; // Proc is old -> permanent
proc = GlobalCopy(proc); // Create new proc as copy
proc->Options &= ~(POPT_NEVERREDEF|POPT_PERMANENT); // NeverRedef options is never inherited
}
else
proc->Options |= POPT_PERMANENT; // Proc is old -> permanent
}
break;
case PT_PROC:
@ -601,6 +623,7 @@ SystemProc *PrepareProc(BOOL NeedForCall)
ParamIndex = 0; // Uses the same logic as PST_PARAMS section
case PST_PARAMS:
temp2 = -1; temp4 = 0; // Our type placeholder
aligntype = FALSE;
switch (*ib)
{
case _T(' '):
@ -623,41 +646,44 @@ SystemProc *PrepareProc(BOOL NeedForCall)
param_defined = TRUE;
break;
case _T('&'):
temp = 1; break; // Special parameter option
temp = PAO_ARRBASE; break; // Special parameter option
case _T('*'):
temp = -1; break; // Pointer parameter option
temp = PAO_PTRFLAG; break; // Pointer parameter option
// Types
case _T('@'): temp2 = PAT_REGMEM; break;
case _T('v'):
case _T('V'): temp2 = PAT_VOID; break;
case 'B': // INT8/BYTE/BOOLEAN
case 'b': temp2 = PAT_INT, temp = sizeof(BYTE) + 1; break;
case 'H': // INT16/WORD/SHORT: 'h' AKA printf type length specifier
case 'h': temp2 = PAT_INT, temp = sizeof(WORD) + 1; break;
case _T('V'): // No extra alignment for void padding
case _T('v'): temp2 = PAT_VOID; break;
case 'B': aligntype += alignflag ? 1 : 0;
case 'b': temp2 = PAT_INT, temp = sizeof(BYTE) + 1; break; // INT8/BYTE/BOOLEAN alias for &1
case 'H': aligntype += alignflag ? 1 : 0;
case 'h': temp2 = PAT_INT, temp = sizeof(WORD) + 1; break; // INT16/WORD/SHORT alias for &2 with 'h' AKA printf type length specifier
#ifndef _WIN64
case _T('P'):
#endif
case _T('I'): aligntype += alignflag ? 1 : 0;
#ifndef _WIN64
case _T('p'):
#endif
case _T('i'):
case _T('I'): temp2 = PAT_INT; break;
case _T('i'): temp2 = PAT_INT; break; // INT32
#ifdef _WIN64
case _T('P'):
#endif
case _T('L'): aligntype += alignflag ? 1 : 0;
#ifdef _WIN64
case _T('p'):
#endif
case _T('l'):
case _T('L'): temp2 = PAT_LONG; break;
case _T('m'):
case _T('M'): temp2 = PAT_STRING; break;
case _T('t'):
case _T('T'):
temp2 = PAT_TSTRING;
++UsedTString;
break;
case _T('g'):
case _T('G'): temp2 = PAT_GUID; break;
case _T('w'):
case _T('W'): temp2 = PAT_WSTRING; break;
case _T('k'):
case _T('K'): temp2 = PAT_CALLBACK; break;
case _T('l'): temp2 = PAT_LONG; break; // INT64
case _T('M'): // 1 byte, no extra alignment
case _T('m'): temp2 = PAT_STRING; break;
case _T('T'): aligntype += (alignflag && sizeof(TCHAR) > 1) ? 1 : 0;
case _T('t'): temp2 = PAT_TSTRING, ++UsedTString; break;
case _T('G'): aligntype += alignflag ? 1 : 0;
case _T('g'): temp2 = PAT_GUID; break;
case _T('W'): aligntype += alignflag ? 1 : 0;
case _T('w'): temp2 = PAT_WSTRING; break;
case _T('K'): aligntype += alignflag ? 1 : 0;
case _T('k'): temp2 = PAT_CALLBACK; break;
// Input output specifiers
case _T('.'): temp3++; break; // skip specifier
@ -716,11 +742,11 @@ SystemProc *PrepareProc(BOOL NeedForCall)
{
const int psbt = ParamSizeByType[temp2];
param_defined = TRUE;
proc->Params[ParamIndex].Type = temp2;
proc->Params[ParamIndex].Type = temp2 | (alignflag && aligntype ? alignflag : 0);
proc->Params[ParamIndex].Size = // Pointer sized or from type
(temp == -1)?(PARAMSIZEBYTYPE_PTR):((psbt>0)?(psbt):(1)); //BUGBUG64: Is it safe to fallback to 1 for CALLBACK?
if (temp == 1) temp = // Get the parameter real special option value
((int) GetIntFromString(&ib)) + 1; // Read '&' type size specification
ParamOptionIsPointer(temp) ? (PARAMSIZEBYTYPE_PTR) : ((psbt>0) ? (psbt) : (1)); //BUGBUG64: Is it safe to fallback to 1 for CALLBACK?
if (temp == PAO_ARRBASE) temp =
PAO_ARRBASE + ((int) GetIntFromString(&ib)); // Read '&' array count specification
proc->Params[ParamIndex].Option = temp;
proc->Params[ParamIndex].Value = 0;
proc->Params[ParamIndex].Input = IOT_NONE;
@ -752,36 +778,27 @@ SystemProc *PrepareProc(BOOL NeedForCall)
temp2 = 0;
switch (*ib)
{
case _T(' '):
break;
case _T(' '): break;
case _T('!'): temp = -temp; break;
case _T('c'):
#ifndef _WIN64
temp2 = POPT_CDECL;
temp2 = POPT_CDECL; // Only x86 cares, just eat the option for everything else
#endif
break;
case _T('r'):
temp2 = POPT_ALWRETURN;
break;
case _T('n'):
temp2 = POPT_NEVERREDEF;
break;
case _T('s'):
temp2 = POPT_GENSTACK;
break;
case _T('e'):
temp2 = POPT_ERROR;
break;
case _T('u'):
temp2 = POPT_UNLOAD;
break;
case _T('r'): temp2 = POPT_ALWRETURN; break;
case _T('n'): temp2 = POPT_NEVERREDEF; break;
case _T('s'): temp2 = POPT_GENSTACK; break;
case _T('e'): temp2 = POPT_ERROR; break;
case _T('u'): temp2 = POPT_UNLOAD; break;
#ifdef POPT_SYNTAX2
case _T('2'): temp2 = POPT_SYNTAX2; break;
#endif
}
// New Options
if (temp2 != 0)
{
if (temp == 1) proc->Options |= temp2;
else proc->Options &= ~temp2;
if (temp == 1) proc->Options |= temp2; else proc->Options &= ~temp2;
// Back to default (turn on nothing) state
temp = 1; temp2 = 0;
}
@ -892,10 +909,10 @@ SystemProc *PrepareProc(BOOL NeedForCall)
void ParamAllocate(SystemProc *proc)
{
int i;
for (i = 0; i <= proc->ParamCount; i++)
if (!proc->Params[i].Value && proc->Params[i].Option == -1)
proc->Params[i].Value = (INT_PTR) GlobalAlloc(GPTR, 4*ParamSizeByType[proc->Params[i].Type]);
UINT i, c;
for (i = 0, c = proc->ParamCount; i <= c; i++)
if (!proc->Params[i].Value && ParamIsPointer(proc->Params[i]))
proc->Params[i].Value = (INT_PTR) GlobalAlloc(GPTR, ParamSizeByType[GetParamType(proc->Params[i])] * 4);
}
void ParamsIn(SystemProc *proc)
@ -913,6 +930,7 @@ void ParamsIn(SystemProc *proc)
while (TRUE)
{
ProcParameter *par = &proc->Params[i];
UINT partype;
// Step 1: retrive value
if ((par->Input == IOT_NONE) || (par->Input == IOT_INLINE))
realbuf = AllocStr(_T(""));
@ -927,14 +945,13 @@ void ParamsIn(SystemProc *proc)
}
// Retreive pointer to place
if (par->Option == -1) place = (HGLOBAL*) par->Value;
else place = (HGLOBAL*) &(par->Value);
place = ParamIsPointer(*par) ? (HGLOBAL*) par->Value : (HGLOBAL*) &(par->Value);
// by default no blocks are allocated
par->allocatedBlock = NULL;
// Step 2: place it
switch (par->Type)
switch (partype = GetParamType(*par))
{
case PAT_VOID:
par->Value = 0;
@ -965,7 +982,7 @@ void ParamsIn(SystemProc *proc)
case PAT_GUID:
wstr = (LPWSTR) GlobalAlloc(GPTR, g_stringsize*sizeof(WCHAR));
MultiByteToWideChar(CP_ACP, 0, realbuf, g_stringsize, wstr, g_stringsize);
if (par->Type == PAT_GUID)
if (partype == PAT_GUID)
{
*place = par->allocatedBlock = GlobalAlloc(GPTR, 16);
CLSIDFromString(wstr, *(LPCLSID*)place);
@ -997,7 +1014,7 @@ void ParamsIn(SystemProc *proc)
#ifndef _WIN64
hi32 = par->_value;
#endif
wsprintf(buf, _T("\t\t\tParam In %d:\tType=%d Value=")SYSFMT_HEXPTR _T(" hi32=0x%08X"), i,
wsprintf(buf, _T("\t\t\tParam In %d:\tType=%#x Value=") SYSFMT_HEXPTR _T(" hi32=0x%08X"), i,
par->Type, par->Value, hi32);
SYSTEM_LOG_ADD(buf);
SYSTEM_LOG_POST;
@ -1013,36 +1030,36 @@ void ParamsDeAllocate(SystemProc *proc)
{
int i;
for (i = proc->ParamCount; i >= 0; i--)
if (proc->Params[i].Value && proc->Params[i].Option == -1)
if (proc->Params[i].Value && ParamIsPointer(proc->Params[i]))
{
GlobalFree((HGLOBAL) (proc->Params[i].Value));
proc->Params[i].Value = 0;
}
}
#define GetSpecialParamTypeSize(pPP) ( (((pPP)->Option)-1) * ByteSizeByType[(pPP)->Type] )
#define GetSpecialParamTypeSize(par) ( (((par).Option)-PAO_ARRBASE) * ByteSizeByType[GetParamType(par)] ) // Option must be > PAO_ARRBASE!
static const int g_intmask[4] = { 0xFFFFFFFF, 0x000000FF, 0x0000FFFF, 0x00FFFFFF };
#define GetMaskedInt32Value(val, size) ( (val) & g_intmask[(((size) >= 0) && ((size) < 4))?((size)):(0)] )
#define GetSpecialParamInt32Value(pPP, size) GetMaskedInt32Value((pPP)->Value, (size))
#define GetMaskedInt32Value(val, size) ( (val) & g_intmask[((UINT)(size) < 4) ? (size) : (0)] )
#define GetSpecialParamInt32Value(par, size) GetMaskedInt32Value((par).Value, (size))
void ParamsOut(SystemProc *proc)
{
INT_PTR *place;
LPWSTR wstr;
int i, intval, typsiz;
int i, partype, intval, typsiz;
TCHAR *realbuf = AllocString();
i = proc->ParamCount;
do
{
// Retreive pointer to place
if (proc->Params[i].Option == -1)
if (ParamIsPointer(proc->Params[i]))
place = (INT_PTR*) proc->Params[i].Value;
else
place = (INT_PTR*) &(proc->Params[i].Value);
// Step 1: retrive value
switch (proc->Params[i].Type)
switch (partype = GetParamType(proc->Params[i]))
{
case PAT_VOID:
*realbuf = _T('\0');
@ -1054,7 +1071,7 @@ void ParamsOut(SystemProc *proc)
intval = (int)(*((INT_PTR*) place));
if (proc->Params[i].Option > 0) // Note: We don't handle '*' pointers, "*h" and "*b" are not supported, use "*i" even on smaller types
{
typsiz = GetSpecialParamTypeSize(&proc->Params[i]);
typsiz = GetSpecialParamTypeSize(proc->Params[i]);
intval = GetMaskedInt32Value(intval, typsiz);
}
wsprintf(realbuf, _T("%d"), intval);
@ -1099,8 +1116,9 @@ void ParamsOut(SystemProc *proc)
}
// memory cleanup
if ((proc->Params[i].allocatedBlock != NULL) && ((proc->ProcType != PT_STRUCT)
|| (proc->Params[i].Option > 0)))
if ((proc->Params[i].allocatedBlock != NULL)
&& ((partype != PT_STRUCT) || ParamIsArray(proc->Params[i]))
)
GlobalFree(proc->Params[i].allocatedBlock);
SYSTEM_LOG_ADD(_T("\t\t\tParam Out("));
@ -1123,7 +1141,7 @@ void ParamsOut(SystemProc *proc)
#ifdef SYSTEM_LOG_DEBUG
{
TCHAR dbgbuf[99];
wsprintf(dbgbuf, _T(")\t%d:\tType=%d Optn=%d Size=%d Data="),
wsprintf(dbgbuf, _T(")\t%d:\tType=%#x Optn=%d Size=%d Data="),
i, proc->Params[i].Type, proc->Params[i].Option, proc->Params[i].Size);
SYSTEM_LOG_ADD(dbgbuf);
SYSTEM_LOG_ADD(realbuf);
@ -1174,36 +1192,61 @@ HANDLE CreateCallback(SystemProc *cbproc)
#endif
}
#ifdef POPT_SYNTAX2
static UINT GetStructParamAlignment(const ProcParameter *par)
{
int partype = GetParamType(*par);
int isarr = ParamIsArray(*par);
// &l is used to get the final struct size "*(p, &l.r0)"
// but it also allows you to write the struct size to the struct as a int<8|16|32|64> "*(p, &l4)"
// so we can't stop that with: if ((par->Type & PAT_ALIGNFLAG) && (!isarr || partype != PAT_LONG))
if (par->Type & PAT_ALIGNFLAG)
{
if ((partype == PAT_STRING) | (partype == PAT_WSTRING)) return ByteSizeByType[partype];
if (partype == PAT_GUID) return 16;
return !isarr ? (par->Size * 4) : GetSpecialParamTypeSize(*par);
}
return 0;
}
#endif
void CallStruct(SystemProc *proc)
{
BOOL ssflag; // "&l" struct size syntax
int i, structsize = 0, size = 0;
UINT i, paramcount = proc->ParamCount, structsize = 0, size = 0, partype;
char *st, *ptr;
#ifdef POPT_SYNTAX2
BOOL tryalign = proc->Options & POPT_SYNTAX2;
#endif
SYSTEM_LOG_ADD(_T("\t\tStruct..."));
// Calculate the structure size
for (i = 1; i <= proc->ParamCount; i++)
for (i = 1; i <= paramcount; i++)
{
partype = GetParamType(proc->Params[i]);
// Emulate g as &g16
// (Changing ByteSizeByType would break compatibility with '*(&g16,i)i.s')
if (PAT_GUID==proc->Params[i].Type && 0==proc->Params[i].Option)
{
proc->Params[i].Option = 1 + 16;
}
if (PAT_GUID==partype && ParamIsSimple(proc->Params[i]))
proc->Params[i].Option = PAO_ARRBASE + 16;
if (proc->Params[i].Option < 1)
structsize += proc->Params[i].Size * 4;
if (!ParamIsArray(proc->Params[i]))
size = proc->Params[i].Size * 4;
else
structsize += GetSpecialParamTypeSize(&proc->Params[i]);
size = GetParamArrayTypeSize(proc->Params[i]);
#ifdef POPT_SYNTAX2
if (tryalign)
structsize = SYS_ALIGNON(structsize, GetStructParamAlignment(&proc->Params[i]));
#endif
structsize += size;
}
// Struct exists?
if (proc->Proc == NULL)
// No. Allocate struct memory
if (proc->Proc == NULL) // No. Allocate struct memory
proc->Proc = (HANDLE) GlobalAlloc(GPTR, structsize);
else // In case of zero size defined structure use mapped size
if (structsize == 0) structsize = (int) GlobalSize((HGLOBAL) proc->Proc);
else if (structsize == 0) // In case of zero size defined structure use mapped size
structsize = (int) GlobalSize((HGLOBAL) proc->Proc);
#ifdef SYSTEM_LOG_DEBUG
{
@ -1216,49 +1259,58 @@ void CallStruct(SystemProc *proc)
// Pointer to current data
st = (char*) proc->Proc;
for (i = 1; i <= proc->ParamCount; i++)
for (i = 1; i <= paramcount; i++)
{
ssflag = FALSE;
partype = GetParamType(proc->Params[i]);
// Normal or special block?
if (proc->Params[i].Option < 1)
if (!ParamIsArray(proc->Params[i]))
{
// Normal
size = proc->Params[i].Size*4;
size = proc->Params[i].Size * 4;
ptr = (char*) &(proc->Params[i].Value);
}
else
{
// Special
size = GetSpecialParamTypeSize(&proc->Params[i]);
size = GetParamArrayTypeSize(proc->Params[i]);
ptr = NULL;
switch (proc->Params[i].Type)
switch (partype)
{
case PAT_VOID: break;
case PAT_LONG:
case PAT_VOID:
break;
case PAT_LONG:
// real structure size
proc->Params[i].Value = structsize;
#ifndef _WIN64
proc->Params[i]._value = 0;
#endif
ssflag = TRUE; // System::Call '*(...,&l.r0)'
// [[fallthrough]]
case PAT_INT:
proc->Params[i].Value = GetSpecialParamInt32Value(&proc->Params[i], size); // clears unused value bits
proc->Params[i].Value = GetSpecialParamInt32Value(proc->Params[i], size); // clears unused value bits
// pointer
ptr = (char*) &(proc->Params[i].Value);
break;
case PAT_STRING:
case PAT_WSTRING:
case PAT_GUID:
case PAT_STRING:
case PAT_WSTRING:
case PAT_GUID:
// Jim Park: Pointer for memcopy, so keep as char*
ptr = (char*) proc->Params[i].Value; break;
ptr = (char*) proc->Params[i].Value;
break;
}
}
// Process them!
if (ptr != NULL)
{
#ifdef POPT_SYNTAX2
if (tryalign)
st = (char*) SYS_ALIGNON((INT_PTR) st, GetStructParamAlignment(&proc->Params[i]));
#endif
// Input
if ((proc->Params[i].Input != IOT_NONE) || (ssflag))
copymem(st, ptr, size);

View file

@ -31,6 +31,10 @@
# define SYSTEM_API __declspec(dllimport) // BUGBUG: This is a plugin, who is going to import the functions directly?
#endif
#define SYS_ALIGNUP(num, al) ( ((num)+((al)-1)) & ~((al)-1) )
#define SYS_UNSAFEALIGNON(num, al) ( (num) % (al) == 0 ? (num) : SYS_ALIGNUP((num), (al)) ) // al CANNOT be 0!
#define SYS_ALIGNON(num, al) ( (al) ? SYS_UNSAFEALIGNON((num), (al)) : (num) )
#define NEW_STACK_SIZE 256*256
// Proc types:
@ -59,6 +63,7 @@
#define PAT_TSTRING PAT_STRING
#endif
#define PAT_PTR ( (4==sizeof(void*)) ? PAT_INT : PAT_LONG )
#define PAT_ALIGNFLAG 0x8000 // Type is aligned to its natural alignment
// Input/Output Source/Destination
#define IOT_NONE 0
@ -75,13 +80,18 @@
#define POPT_GENSTACK 0x10 // Use general stack (non temporary for callback)
#define POPT_ERROR 0x20 // Call GetLastError after proc and push it to stack
#define POPT_UNLOAD 0x40 // unload dll after call
#define POPT_CLONE 0x80 // This is clone callback
#define POPT_CLONE 0x80 // Callback clone
#define POPT_SYNTAX2 0x100 // "?2" syntax mode (direct callback ids and aligned uppercased types)
// Proc argument (ProcParameter) options
#define PAO_PTRFLAG -1 // Could be changed to 0x80000000 if we need to support "*&iN"
#define PAO_ARRBASE 1
#define ParamOptionIsPointer(opt) ( (opt) < 0 )
// Our single proc parameter
typedef struct
{
int Type;
int Option; // -1 -> Pointer, 1-... -> Special+1
int Type; // Can be ORed with PAT_ALIGNFLAG to request alignment in structs
int Option; // PAO_PTRFLAG -> Pointer, PAO_ARRBASE-... -> Special+PAO_ARRBASE
INT_PTR Value; // it can hold any pointer sized value
#ifndef _WIN64
int _value; // Upper 32 bits of Value when type is 64 bit (2 pushes)
@ -92,6 +102,16 @@ typedef struct
HGLOBAL allocatedBlock; // block allocated for passing string, wstring or guid param
} ProcParameter;
#define ParamIsSimple(par) ( (par).Option == 0 )
#define ParamIsPointer(par) ParamOptionIsPointer((par).Option)
#define ParamIsArray(par) ( (par).Option > 0 ) // AKA special
#define GetParamArrayTypeSize GetSpecialParamTypeSize
#ifdef POPT_SYNTAX2
#define GetParamType(par) ( (BYTE) (par).Type )
#else
#define GetParamType(par) ( (par).Type )
#endif
// Our single proc (Since the user will free proc with GlobalFree,
// I've declared all variables as statics)
typedef struct tag_SystemProc SystemProc;

View file

@ -472,9 +472,20 @@ System::Free $0
<th>u</th>
<td>Unload DLL after call (using FreeLibrary, so you'll be able to delete it for example).</td>
</tr>
<tr>
<th>2</th>
<td>Experimental v2 syntax</td>
</tr>
</table>
</blockquote>
<h4>Experimental v2 syntax</h4>
<ul>
<li>Struct types in <a href="#v2typealign">uppercase are aligned</a> to their natural alignment. Lowercased types are packed without alignment.
<li><a href="#v2callback">Callback id</a> based on the allocated callback
</ul>
<h4>Usage Examples</h4>
<blockquote><pre>
@ -516,6 +527,19 @@ System::<b>Call</b> "*$0(i .r1)"
System::Free $0
DetailPrint $1
</pre></blockquote>
<a name="structsize"></a><blockquote><pre>
System::Call '*0(p, <b>&l.r2,</b> &t2)' ; &l. is not part of the struct
DetailPrint "Struct size=$2"
</pre></blockquote>
<a name="structsizemember"></a><blockquote><pre>
System::Call '*(<b>&l4</b>,i,i,i,i,&t128)p.r1' ; Fills dwOSVersionInfoSize with the struct size as a int32
${If} $1 Z<> 0
System::Call 'kernel32::GetVersionEx(pr1)i.r0'
System::Call '*$1(i,i.R1,i.R2,i.R3)'
System::Free $1
${IfThen} $0 <> 0 ${|} DetailPrint "v$R1.$R2.$R3" ${|}
${EndIf}
</pre></blockquote>
<blockquote><pre>
<a name="directvarmemparam"></a>System::<b>Call</b> "user32::GetClientRect(p $hwndparent, @ r0)"
System::<b>Call</b> "*$0(i,i,i.r1,i.r2)"
@ -564,6 +588,29 @@ loop:
done:
System::Free $R0
</pre></blockquote>
<a name="v2callback"></a><blockquote><pre>
System::Get '(m.r1)ir2r0 <b>?2</b>' ; v2 syntax
Pop $9
System::Call 'kernel32::EnumSystemLocalesA(k r9, i 0)'
loop:
StrCmp <b>$0 "callback$9"</b> 0 done
DetailPrint "Locale: $1"
StrCpy $2 1 ; EnumLocalesProc return value
System::Call $9 ; return from EnumLocalesProc
Goto loop
done:
System::Free $9
</pre></blockquote>
<a name="v2typealign"></a><blockquote><pre>
System::Call '*(&t50 "!")p.r2' ; DecimalSep
System::Call '*(&t50 "`")p.r3' ; ThousandSep
System::Call '*(i 2, i 0, i 3, <b>P r2, P r3</b>, i 1)p.r1 <b>?2</b>'
System::Call 'kernel32::GetNumberFormat(i 0, i 0, t "1337.666" r4, p r1, t.r5, i ${NSIS_MAX_STRLEN})'
DetailPrint "Custom formated $4: $5"
System::Free $3
System::Free $2
System::Free $1
</pre></blockquote>
<blockquote><pre>
<a name="repeat"></a>!define MB "user32::MessageBox(p$HWNDPARENT,t,t'NSIS System Plug-in',i0)"
System::<b>Call</b> "${MB}(,'my message',,)"

View file

@ -20,6 +20,8 @@ Released on ??? ??rd, 20??
\S2{} Minor Changes
\b Added System plug-in v2 syntax option
\b Added System plug-in B and H types
\b Added \R{intptrcmp}{IntPtrCmp}, IntPtrCmpU, and \R{intptrop}{IntPtrOp}