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:
parent
ebfe3bf6d2
commit
9229c5df18
4 changed files with 243 additions and 122 deletions
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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',,)"
|
||||
|
|
|
@ -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}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue