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?
|
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] = {
|
static const int ByteSizeByType[8] = {
|
||||||
1, // PAT_VOID
|
1, // PAT_VOID
|
||||||
1, // PAT_INT
|
1, // PAT_INT
|
||||||
|
@ -66,15 +66,29 @@ HINSTANCE g_hInstance;
|
||||||
char retexpr[4]; //BUGBUG64?
|
char retexpr[4]; //BUGBUG64?
|
||||||
HANDLE retaddr;
|
HANDLE retaddr;
|
||||||
|
|
||||||
TCHAR *GetResultStr(SystemProc *proc)
|
static TCHAR *MakeResultStr(SystemProc *proc, TCHAR *buf)
|
||||||
{
|
{
|
||||||
TCHAR *buf = AllocString();
|
if (proc->ProcResult == PR_OK)
|
||||||
if (proc->ProcResult == PR_OK) lstrcpy(buf, _T("ok"));
|
lstrcpy(buf, _T("ok"));
|
||||||
else if (proc->ProcResult == PR_ERROR) lstrcpy(buf, _T("error"));
|
else if (proc->ProcResult == PR_ERROR)
|
||||||
else if (proc->ProcResult == PR_CALLBACK) wsprintf(buf, _T("callback%d"), proc->CallbackIndex);
|
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;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TCHAR *AllocResultStr(SystemProc *proc)
|
||||||
|
{
|
||||||
|
return MakeResultStr(proc, AllocString());
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef SYSTEM_LOG_DEBUG
|
#ifdef SYSTEM_LOG_DEBUG
|
||||||
|
|
||||||
#ifndef COUNTOF
|
#ifndef COUNTOF
|
||||||
|
@ -253,19 +267,20 @@ PLUGINFUNCTION(Get)
|
||||||
SYSTEM_LOG_ADD(proc->ProcName);
|
SYSTEM_LOG_ADD(proc->ProcName);
|
||||||
//SYSTEM_LOG_ADD(_T("\n"));
|
//SYSTEM_LOG_ADD(_T("\n"));
|
||||||
SYSTEM_LOG_POST;
|
SYSTEM_LOG_POST;
|
||||||
if ((proc->Options & POPT_ALWRETURN) != 0)
|
if (proc->Options & POPT_ALWRETURN)
|
||||||
{
|
{
|
||||||
// Always return flag set -> return separate proc and result
|
// Always return flag set -> return separate proc and result
|
||||||
system_pushintptr((INT_PTR) proc);
|
system_pushintptr((INT_PTR) proc);
|
||||||
GlobalFree(system_pushstring(GetResultStr(proc)));
|
GlobalFree(system_pushstring(AllocResultStr(proc)));
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
if (proc->ProcResult != PR_OK)
|
if (proc->ProcResult != PR_OK)
|
||||||
{
|
{
|
||||||
// No always return flag and error result - return result
|
// 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 is permanent?
|
||||||
if ((proc->Options & POPT_PERMANENT) == 0)
|
if (!(proc->Options & POPT_PERMANENT))
|
||||||
GlobalFree((HGLOBAL) proc); // No, free it
|
GlobalFree((HGLOBAL) proc); // No, free it
|
||||||
}
|
}
|
||||||
else // Ok result, return proc
|
else // Ok result, return proc
|
||||||
|
@ -319,11 +334,11 @@ PLUGINFUNCTION(Call)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process output
|
// Process output
|
||||||
if ((proc->Options & POPT_ALWRETURN) != 0)
|
if (proc->Options & POPT_ALWRETURN)
|
||||||
{
|
{
|
||||||
// Always return flag set - return separate return and result
|
// Always return flag set - return separate return and result
|
||||||
ParamsOut(proc);
|
ParamsOut(proc);
|
||||||
GlobalFree(system_pushstring(GetResultStr(proc)));
|
GlobalFree(system_pushstring(AllocResultStr(proc)));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -332,8 +347,10 @@ PLUGINFUNCTION(Call)
|
||||||
ProcParameter pp = proc->Params[0]; // Save old return param
|
ProcParameter pp = proc->Params[0]; // Save old return param
|
||||||
|
|
||||||
// Return result instead of return value
|
// 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].Type = PAT_TSTRING;
|
||||||
|
proc->Params[0].allocatedBlock = NULL;
|
||||||
|
|
||||||
ParamsOut(proc); // Return all params
|
ParamsOut(proc); // Return all params
|
||||||
proc->Params[0] = pp; // Restore old return param
|
proc->Params[0] = pp; // Restore old return param
|
||||||
|
@ -355,7 +372,7 @@ PLUGINFUNCTION(Call)
|
||||||
}
|
}
|
||||||
|
|
||||||
// If proc is permanent?
|
// 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
|
} PLUGINFUNCTIONEND
|
||||||
|
|
||||||
PLUGINFUNCTIONSHORT(Int64Op)
|
PLUGINFUNCTIONSHORT(Int64Op)
|
||||||
|
@ -436,7 +453,12 @@ SystemProc *PrepareProc(BOOL NeedForCall)
|
||||||
BOOL param_defined = FALSE;
|
BOOL param_defined = FALSE;
|
||||||
SystemProc *proc = NULL;
|
SystemProc *proc = NULL;
|
||||||
TCHAR *ibuf, *ib, *sbuf, *cbuf, *cb;
|
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__
|
#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
|
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('('):
|
case _T('('):
|
||||||
SectionType = PST_PARAMS;
|
SectionType = PST_PARAMS;
|
||||||
// fake-real parameter: for COM interfaces first param is Interface Pointer
|
// 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;
|
temp3 = temp = 0;
|
||||||
param_defined = FALSE;
|
param_defined = FALSE;
|
||||||
break;
|
break;
|
||||||
|
@ -526,13 +548,13 @@ SystemProc *PrepareProc(BOOL NeedForCall)
|
||||||
if (pr != NULL) pr->Clone = NULL;
|
if (pr != NULL) pr->Clone = NULL;
|
||||||
|
|
||||||
// Never Redefine?
|
// Never Redefine?
|
||||||
if ((proc->Options & POPT_NEVERREDEF) != 0)
|
if (proc->Options & POPT_NEVERREDEF)
|
||||||
{
|
{
|
||||||
// Create new proc as copy
|
proc = GlobalCopy(proc); // Create new proc as copy
|
||||||
proc = GlobalCopy(proc);
|
proc->Options &= ~(POPT_NEVERREDEF|POPT_PERMANENT); // NeverRedef options is never inherited
|
||||||
// NeverRedef options is never inherited
|
}
|
||||||
proc->Options &= (~POPT_NEVERREDEF) & (~POPT_PERMANENT);
|
else
|
||||||
} else proc->Options |= POPT_PERMANENT; // Proc is old -> permanent
|
proc->Options |= POPT_PERMANENT; // Proc is old -> permanent
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case PT_PROC:
|
case PT_PROC:
|
||||||
|
@ -601,6 +623,7 @@ SystemProc *PrepareProc(BOOL NeedForCall)
|
||||||
ParamIndex = 0; // Uses the same logic as PST_PARAMS section
|
ParamIndex = 0; // Uses the same logic as PST_PARAMS section
|
||||||
case PST_PARAMS:
|
case PST_PARAMS:
|
||||||
temp2 = -1; temp4 = 0; // Our type placeholder
|
temp2 = -1; temp4 = 0; // Our type placeholder
|
||||||
|
aligntype = FALSE;
|
||||||
switch (*ib)
|
switch (*ib)
|
||||||
{
|
{
|
||||||
case _T(' '):
|
case _T(' '):
|
||||||
|
@ -623,41 +646,44 @@ SystemProc *PrepareProc(BOOL NeedForCall)
|
||||||
param_defined = TRUE;
|
param_defined = TRUE;
|
||||||
break;
|
break;
|
||||||
case _T('&'):
|
case _T('&'):
|
||||||
temp = 1; break; // Special parameter option
|
temp = PAO_ARRBASE; break; // Special parameter option
|
||||||
case _T('*'):
|
case _T('*'):
|
||||||
temp = -1; break; // Pointer parameter option
|
temp = PAO_PTRFLAG; break; // Pointer parameter option
|
||||||
|
|
||||||
// Types
|
// Types
|
||||||
case _T('@'): temp2 = PAT_REGMEM; break;
|
case _T('@'): temp2 = PAT_REGMEM; break;
|
||||||
case _T('v'):
|
case _T('V'): // No extra alignment for void padding
|
||||||
case _T('V'): temp2 = PAT_VOID; break;
|
case _T('v'): temp2 = PAT_VOID; break;
|
||||||
case 'B': // INT8/BYTE/BOOLEAN
|
case 'B': aligntype += alignflag ? 1 : 0;
|
||||||
case 'b': temp2 = PAT_INT, temp = sizeof(BYTE) + 1; break;
|
case 'b': temp2 = PAT_INT, temp = sizeof(BYTE) + 1; break; // INT8/BYTE/BOOLEAN alias for &1
|
||||||
case 'H': // INT16/WORD/SHORT: 'h' AKA printf type length specifier
|
case 'H': aligntype += alignflag ? 1 : 0;
|
||||||
case 'h': temp2 = PAT_INT, temp = sizeof(WORD) + 1; break;
|
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
|
#ifndef _WIN64
|
||||||
case _T('p'):
|
case _T('p'):
|
||||||
#endif
|
#endif
|
||||||
case _T('i'):
|
case _T('i'): temp2 = PAT_INT; break; // INT32
|
||||||
case _T('I'): temp2 = PAT_INT; break;
|
#ifdef _WIN64
|
||||||
|
case _T('P'):
|
||||||
|
#endif
|
||||||
|
case _T('L'): aligntype += alignflag ? 1 : 0;
|
||||||
#ifdef _WIN64
|
#ifdef _WIN64
|
||||||
case _T('p'):
|
case _T('p'):
|
||||||
#endif
|
#endif
|
||||||
case _T('l'):
|
case _T('l'): temp2 = PAT_LONG; break; // INT64
|
||||||
case _T('L'): temp2 = PAT_LONG; break;
|
case _T('M'): // 1 byte, no extra alignment
|
||||||
case _T('m'):
|
case _T('m'): temp2 = PAT_STRING; break;
|
||||||
case _T('M'): temp2 = PAT_STRING; break;
|
case _T('T'): aligntype += (alignflag && sizeof(TCHAR) > 1) ? 1 : 0;
|
||||||
case _T('t'):
|
case _T('t'): temp2 = PAT_TSTRING, ++UsedTString; break;
|
||||||
case _T('T'):
|
case _T('G'): aligntype += alignflag ? 1 : 0;
|
||||||
temp2 = PAT_TSTRING;
|
case _T('g'): temp2 = PAT_GUID; break;
|
||||||
++UsedTString;
|
case _T('W'): aligntype += alignflag ? 1 : 0;
|
||||||
break;
|
case _T('w'): temp2 = PAT_WSTRING; break;
|
||||||
case _T('g'):
|
case _T('K'): aligntype += alignflag ? 1 : 0;
|
||||||
case _T('G'): temp2 = PAT_GUID; break;
|
case _T('k'): temp2 = PAT_CALLBACK; break;
|
||||||
case _T('w'):
|
|
||||||
case _T('W'): temp2 = PAT_WSTRING; break;
|
|
||||||
case _T('k'):
|
|
||||||
case _T('K'): temp2 = PAT_CALLBACK; break;
|
|
||||||
|
|
||||||
// Input output specifiers
|
// Input output specifiers
|
||||||
case _T('.'): temp3++; break; // skip specifier
|
case _T('.'): temp3++; break; // skip specifier
|
||||||
|
@ -716,11 +742,11 @@ SystemProc *PrepareProc(BOOL NeedForCall)
|
||||||
{
|
{
|
||||||
const int psbt = ParamSizeByType[temp2];
|
const int psbt = ParamSizeByType[temp2];
|
||||||
param_defined = TRUE;
|
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
|
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?
|
ParamOptionIsPointer(temp) ? (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
|
if (temp == PAO_ARRBASE) temp =
|
||||||
((int) GetIntFromString(&ib)) + 1; // Read '&' type size specification
|
PAO_ARRBASE + ((int) GetIntFromString(&ib)); // Read '&' array count specification
|
||||||
proc->Params[ParamIndex].Option = temp;
|
proc->Params[ParamIndex].Option = temp;
|
||||||
proc->Params[ParamIndex].Value = 0;
|
proc->Params[ParamIndex].Value = 0;
|
||||||
proc->Params[ParamIndex].Input = IOT_NONE;
|
proc->Params[ParamIndex].Input = IOT_NONE;
|
||||||
|
@ -752,36 +778,27 @@ SystemProc *PrepareProc(BOOL NeedForCall)
|
||||||
temp2 = 0;
|
temp2 = 0;
|
||||||
switch (*ib)
|
switch (*ib)
|
||||||
{
|
{
|
||||||
case _T(' '):
|
case _T(' '): break;
|
||||||
break;
|
|
||||||
case _T('!'): temp = -temp; break;
|
case _T('!'): temp = -temp; break;
|
||||||
case _T('c'):
|
case _T('c'):
|
||||||
#ifndef _WIN64
|
#ifndef _WIN64
|
||||||
temp2 = POPT_CDECL;
|
temp2 = POPT_CDECL; // Only x86 cares, just eat the option for everything else
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
case _T('r'):
|
case _T('r'): temp2 = POPT_ALWRETURN; break;
|
||||||
temp2 = POPT_ALWRETURN;
|
case _T('n'): temp2 = POPT_NEVERREDEF; break;
|
||||||
break;
|
case _T('s'): temp2 = POPT_GENSTACK; break;
|
||||||
case _T('n'):
|
case _T('e'): temp2 = POPT_ERROR; break;
|
||||||
temp2 = POPT_NEVERREDEF;
|
case _T('u'): temp2 = POPT_UNLOAD; break;
|
||||||
break;
|
#ifdef POPT_SYNTAX2
|
||||||
case _T('s'):
|
case _T('2'): temp2 = POPT_SYNTAX2; break;
|
||||||
temp2 = POPT_GENSTACK;
|
#endif
|
||||||
break;
|
|
||||||
case _T('e'):
|
|
||||||
temp2 = POPT_ERROR;
|
|
||||||
break;
|
|
||||||
case _T('u'):
|
|
||||||
temp2 = POPT_UNLOAD;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// New Options
|
// New Options
|
||||||
if (temp2 != 0)
|
if (temp2 != 0)
|
||||||
{
|
{
|
||||||
if (temp == 1) proc->Options |= temp2;
|
if (temp == 1) proc->Options |= temp2; else proc->Options &= ~temp2;
|
||||||
else proc->Options &= ~temp2;
|
|
||||||
// Back to default (turn on nothing) state
|
// Back to default (turn on nothing) state
|
||||||
temp = 1; temp2 = 0;
|
temp = 1; temp2 = 0;
|
||||||
}
|
}
|
||||||
|
@ -892,10 +909,10 @@ SystemProc *PrepareProc(BOOL NeedForCall)
|
||||||
|
|
||||||
void ParamAllocate(SystemProc *proc)
|
void ParamAllocate(SystemProc *proc)
|
||||||
{
|
{
|
||||||
int i;
|
UINT i, c;
|
||||||
for (i = 0; i <= proc->ParamCount; i++)
|
for (i = 0, c = proc->ParamCount; i <= c; i++)
|
||||||
if (!proc->Params[i].Value && proc->Params[i].Option == -1)
|
if (!proc->Params[i].Value && ParamIsPointer(proc->Params[i]))
|
||||||
proc->Params[i].Value = (INT_PTR) GlobalAlloc(GPTR, 4*ParamSizeByType[proc->Params[i].Type]);
|
proc->Params[i].Value = (INT_PTR) GlobalAlloc(GPTR, ParamSizeByType[GetParamType(proc->Params[i])] * 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ParamsIn(SystemProc *proc)
|
void ParamsIn(SystemProc *proc)
|
||||||
|
@ -913,6 +930,7 @@ void ParamsIn(SystemProc *proc)
|
||||||
while (TRUE)
|
while (TRUE)
|
||||||
{
|
{
|
||||||
ProcParameter *par = &proc->Params[i];
|
ProcParameter *par = &proc->Params[i];
|
||||||
|
UINT partype;
|
||||||
// Step 1: retrive value
|
// Step 1: retrive value
|
||||||
if ((par->Input == IOT_NONE) || (par->Input == IOT_INLINE))
|
if ((par->Input == IOT_NONE) || (par->Input == IOT_INLINE))
|
||||||
realbuf = AllocStr(_T(""));
|
realbuf = AllocStr(_T(""));
|
||||||
|
@ -927,14 +945,13 @@ void ParamsIn(SystemProc *proc)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retreive pointer to place
|
// Retreive pointer to place
|
||||||
if (par->Option == -1) place = (HGLOBAL*) par->Value;
|
place = ParamIsPointer(*par) ? (HGLOBAL*) par->Value : (HGLOBAL*) &(par->Value);
|
||||||
else place = (HGLOBAL*) &(par->Value);
|
|
||||||
|
|
||||||
// by default no blocks are allocated
|
// by default no blocks are allocated
|
||||||
par->allocatedBlock = NULL;
|
par->allocatedBlock = NULL;
|
||||||
|
|
||||||
// Step 2: place it
|
// Step 2: place it
|
||||||
switch (par->Type)
|
switch (partype = GetParamType(*par))
|
||||||
{
|
{
|
||||||
case PAT_VOID:
|
case PAT_VOID:
|
||||||
par->Value = 0;
|
par->Value = 0;
|
||||||
|
@ -965,7 +982,7 @@ void ParamsIn(SystemProc *proc)
|
||||||
case PAT_GUID:
|
case PAT_GUID:
|
||||||
wstr = (LPWSTR) GlobalAlloc(GPTR, g_stringsize*sizeof(WCHAR));
|
wstr = (LPWSTR) GlobalAlloc(GPTR, g_stringsize*sizeof(WCHAR));
|
||||||
MultiByteToWideChar(CP_ACP, 0, realbuf, g_stringsize, wstr, g_stringsize);
|
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);
|
*place = par->allocatedBlock = GlobalAlloc(GPTR, 16);
|
||||||
CLSIDFromString(wstr, *(LPCLSID*)place);
|
CLSIDFromString(wstr, *(LPCLSID*)place);
|
||||||
|
@ -997,7 +1014,7 @@ void ParamsIn(SystemProc *proc)
|
||||||
#ifndef _WIN64
|
#ifndef _WIN64
|
||||||
hi32 = par->_value;
|
hi32 = par->_value;
|
||||||
#endif
|
#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);
|
par->Type, par->Value, hi32);
|
||||||
SYSTEM_LOG_ADD(buf);
|
SYSTEM_LOG_ADD(buf);
|
||||||
SYSTEM_LOG_POST;
|
SYSTEM_LOG_POST;
|
||||||
|
@ -1013,36 +1030,36 @@ void ParamsDeAllocate(SystemProc *proc)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
for (i = proc->ParamCount; i >= 0; 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));
|
GlobalFree((HGLOBAL) (proc->Params[i].Value));
|
||||||
proc->Params[i].Value = 0;
|
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 };
|
static const int g_intmask[4] = { 0xFFFFFFFF, 0x000000FF, 0x0000FFFF, 0x00FFFFFF };
|
||||||
#define GetMaskedInt32Value(val, size) ( (val) & g_intmask[(((size) >= 0) && ((size) < 4))?((size)):(0)] )
|
#define GetMaskedInt32Value(val, size) ( (val) & g_intmask[((UINT)(size) < 4) ? (size) : (0)] )
|
||||||
#define GetSpecialParamInt32Value(pPP, size) GetMaskedInt32Value((pPP)->Value, (size))
|
#define GetSpecialParamInt32Value(par, size) GetMaskedInt32Value((par).Value, (size))
|
||||||
|
|
||||||
void ParamsOut(SystemProc *proc)
|
void ParamsOut(SystemProc *proc)
|
||||||
{
|
{
|
||||||
INT_PTR *place;
|
INT_PTR *place;
|
||||||
LPWSTR wstr;
|
LPWSTR wstr;
|
||||||
int i, intval, typsiz;
|
int i, partype, intval, typsiz;
|
||||||
TCHAR *realbuf = AllocString();
|
TCHAR *realbuf = AllocString();
|
||||||
|
|
||||||
i = proc->ParamCount;
|
i = proc->ParamCount;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
// Retreive pointer to place
|
// Retreive pointer to place
|
||||||
if (proc->Params[i].Option == -1)
|
if (ParamIsPointer(proc->Params[i]))
|
||||||
place = (INT_PTR*) proc->Params[i].Value;
|
place = (INT_PTR*) proc->Params[i].Value;
|
||||||
else
|
else
|
||||||
place = (INT_PTR*) &(proc->Params[i].Value);
|
place = (INT_PTR*) &(proc->Params[i].Value);
|
||||||
|
|
||||||
// Step 1: retrive value
|
// Step 1: retrive value
|
||||||
switch (proc->Params[i].Type)
|
switch (partype = GetParamType(proc->Params[i]))
|
||||||
{
|
{
|
||||||
case PAT_VOID:
|
case PAT_VOID:
|
||||||
*realbuf = _T('\0');
|
*realbuf = _T('\0');
|
||||||
|
@ -1054,7 +1071,7 @@ void ParamsOut(SystemProc *proc)
|
||||||
intval = (int)(*((INT_PTR*) place));
|
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
|
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);
|
intval = GetMaskedInt32Value(intval, typsiz);
|
||||||
}
|
}
|
||||||
wsprintf(realbuf, _T("%d"), intval);
|
wsprintf(realbuf, _T("%d"), intval);
|
||||||
|
@ -1099,8 +1116,9 @@ void ParamsOut(SystemProc *proc)
|
||||||
}
|
}
|
||||||
|
|
||||||
// memory cleanup
|
// memory cleanup
|
||||||
if ((proc->Params[i].allocatedBlock != NULL) && ((proc->ProcType != PT_STRUCT)
|
if ((proc->Params[i].allocatedBlock != NULL)
|
||||||
|| (proc->Params[i].Option > 0)))
|
&& ((partype != PT_STRUCT) || ParamIsArray(proc->Params[i]))
|
||||||
|
)
|
||||||
GlobalFree(proc->Params[i].allocatedBlock);
|
GlobalFree(proc->Params[i].allocatedBlock);
|
||||||
|
|
||||||
SYSTEM_LOG_ADD(_T("\t\t\tParam Out("));
|
SYSTEM_LOG_ADD(_T("\t\t\tParam Out("));
|
||||||
|
@ -1123,7 +1141,7 @@ void ParamsOut(SystemProc *proc)
|
||||||
#ifdef SYSTEM_LOG_DEBUG
|
#ifdef SYSTEM_LOG_DEBUG
|
||||||
{
|
{
|
||||||
TCHAR dbgbuf[99];
|
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);
|
i, proc->Params[i].Type, proc->Params[i].Option, proc->Params[i].Size);
|
||||||
SYSTEM_LOG_ADD(dbgbuf);
|
SYSTEM_LOG_ADD(dbgbuf);
|
||||||
SYSTEM_LOG_ADD(realbuf);
|
SYSTEM_LOG_ADD(realbuf);
|
||||||
|
@ -1174,36 +1192,61 @@ HANDLE CreateCallback(SystemProc *cbproc)
|
||||||
#endif
|
#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)
|
void CallStruct(SystemProc *proc)
|
||||||
{
|
{
|
||||||
BOOL ssflag; // "&l" struct size syntax
|
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;
|
char *st, *ptr;
|
||||||
|
#ifdef POPT_SYNTAX2
|
||||||
|
BOOL tryalign = proc->Options & POPT_SYNTAX2;
|
||||||
|
#endif
|
||||||
|
|
||||||
SYSTEM_LOG_ADD(_T("\t\tStruct..."));
|
SYSTEM_LOG_ADD(_T("\t\tStruct..."));
|
||||||
|
|
||||||
// Calculate the structure size
|
// 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
|
// Emulate g as &g16
|
||||||
// (Changing ByteSizeByType would break compatibility with '*(&g16,i)i.s')
|
// (Changing ByteSizeByType would break compatibility with '*(&g16,i)i.s')
|
||||||
if (PAT_GUID==proc->Params[i].Type && 0==proc->Params[i].Option)
|
if (PAT_GUID==partype && ParamIsSimple(proc->Params[i]))
|
||||||
{
|
proc->Params[i].Option = PAO_ARRBASE + 16;
|
||||||
proc->Params[i].Option = 1 + 16;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (proc->Params[i].Option < 1)
|
if (!ParamIsArray(proc->Params[i]))
|
||||||
structsize += proc->Params[i].Size * 4;
|
size = proc->Params[i].Size * 4;
|
||||||
else
|
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?
|
// Struct exists?
|
||||||
if (proc->Proc == NULL)
|
if (proc->Proc == NULL) // No. Allocate struct memory
|
||||||
// No. Allocate struct memory
|
|
||||||
proc->Proc = (HANDLE) GlobalAlloc(GPTR, structsize);
|
proc->Proc = (HANDLE) GlobalAlloc(GPTR, structsize);
|
||||||
else // In case of zero size defined structure use mapped size
|
else if (structsize == 0) // In case of zero size defined structure use mapped size
|
||||||
if (structsize == 0) structsize = (int) GlobalSize((HGLOBAL) proc->Proc);
|
structsize = (int) GlobalSize((HGLOBAL) proc->Proc);
|
||||||
|
|
||||||
#ifdef SYSTEM_LOG_DEBUG
|
#ifdef SYSTEM_LOG_DEBUG
|
||||||
{
|
{
|
||||||
|
@ -1216,49 +1259,58 @@ void CallStruct(SystemProc *proc)
|
||||||
// Pointer to current data
|
// Pointer to current data
|
||||||
st = (char*) proc->Proc;
|
st = (char*) proc->Proc;
|
||||||
|
|
||||||
for (i = 1; i <= proc->ParamCount; i++)
|
for (i = 1; i <= paramcount; i++)
|
||||||
{
|
{
|
||||||
ssflag = FALSE;
|
ssflag = FALSE;
|
||||||
|
partype = GetParamType(proc->Params[i]);
|
||||||
|
|
||||||
// Normal or special block?
|
// Normal or special block?
|
||||||
if (proc->Params[i].Option < 1)
|
if (!ParamIsArray(proc->Params[i]))
|
||||||
{
|
{
|
||||||
// Normal
|
// Normal
|
||||||
size = proc->Params[i].Size*4;
|
size = proc->Params[i].Size * 4;
|
||||||
ptr = (char*) &(proc->Params[i].Value);
|
ptr = (char*) &(proc->Params[i].Value);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Special
|
// Special
|
||||||
size = GetSpecialParamTypeSize(&proc->Params[i]);
|
size = GetParamArrayTypeSize(proc->Params[i]);
|
||||||
ptr = NULL;
|
ptr = NULL;
|
||||||
switch (proc->Params[i].Type)
|
switch (partype)
|
||||||
{
|
{
|
||||||
case PAT_VOID: break;
|
case PAT_VOID:
|
||||||
case PAT_LONG:
|
break;
|
||||||
|
case PAT_LONG:
|
||||||
// real structure size
|
// real structure size
|
||||||
proc->Params[i].Value = structsize;
|
proc->Params[i].Value = structsize;
|
||||||
#ifndef _WIN64
|
#ifndef _WIN64
|
||||||
proc->Params[i]._value = 0;
|
proc->Params[i]._value = 0;
|
||||||
#endif
|
#endif
|
||||||
ssflag = TRUE; // System::Call '*(...,&l.r0)'
|
ssflag = TRUE; // System::Call '*(...,&l.r0)'
|
||||||
|
// [[fallthrough]]
|
||||||
case PAT_INT:
|
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
|
// pointer
|
||||||
ptr = (char*) &(proc->Params[i].Value);
|
ptr = (char*) &(proc->Params[i].Value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PAT_STRING:
|
case PAT_STRING:
|
||||||
case PAT_WSTRING:
|
case PAT_WSTRING:
|
||||||
case PAT_GUID:
|
case PAT_GUID:
|
||||||
// Jim Park: Pointer for memcopy, so keep as char*
|
// 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!
|
// Process them!
|
||||||
if (ptr != NULL)
|
if (ptr != NULL)
|
||||||
{
|
{
|
||||||
|
#ifdef POPT_SYNTAX2
|
||||||
|
if (tryalign)
|
||||||
|
st = (char*) SYS_ALIGNON((INT_PTR) st, GetStructParamAlignment(&proc->Params[i]));
|
||||||
|
#endif
|
||||||
|
|
||||||
// Input
|
// Input
|
||||||
if ((proc->Params[i].Input != IOT_NONE) || (ssflag))
|
if ((proc->Params[i].Input != IOT_NONE) || (ssflag))
|
||||||
copymem(st, ptr, size);
|
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?
|
# define SYSTEM_API __declspec(dllimport) // BUGBUG: This is a plugin, who is going to import the functions directly?
|
||||||
#endif
|
#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
|
#define NEW_STACK_SIZE 256*256
|
||||||
|
|
||||||
// Proc types:
|
// Proc types:
|
||||||
|
@ -59,6 +63,7 @@
|
||||||
#define PAT_TSTRING PAT_STRING
|
#define PAT_TSTRING PAT_STRING
|
||||||
#endif
|
#endif
|
||||||
#define PAT_PTR ( (4==sizeof(void*)) ? PAT_INT : PAT_LONG )
|
#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
|
// Input/Output Source/Destination
|
||||||
#define IOT_NONE 0
|
#define IOT_NONE 0
|
||||||
|
@ -75,13 +80,18 @@
|
||||||
#define POPT_GENSTACK 0x10 // Use general stack (non temporary for callback)
|
#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_ERROR 0x20 // Call GetLastError after proc and push it to stack
|
||||||
#define POPT_UNLOAD 0x40 // unload dll after call
|
#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
|
typedef struct
|
||||||
{
|
{
|
||||||
int Type;
|
int Type; // Can be ORed with PAT_ALIGNFLAG to request alignment in structs
|
||||||
int Option; // -1 -> Pointer, 1-... -> Special+1
|
int Option; // PAO_PTRFLAG -> Pointer, PAO_ARRBASE-... -> Special+PAO_ARRBASE
|
||||||
INT_PTR Value; // it can hold any pointer sized value
|
INT_PTR Value; // it can hold any pointer sized value
|
||||||
#ifndef _WIN64
|
#ifndef _WIN64
|
||||||
int _value; // Upper 32 bits of Value when type is 64 bit (2 pushes)
|
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
|
HGLOBAL allocatedBlock; // block allocated for passing string, wstring or guid param
|
||||||
} ProcParameter;
|
} 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,
|
// Our single proc (Since the user will free proc with GlobalFree,
|
||||||
// I've declared all variables as statics)
|
// I've declared all variables as statics)
|
||||||
typedef struct tag_SystemProc SystemProc;
|
typedef struct tag_SystemProc SystemProc;
|
||||||
|
|
|
@ -472,9 +472,20 @@ System::Free $0
|
||||||
<th>u</th>
|
<th>u</th>
|
||||||
<td>Unload DLL after call (using FreeLibrary, so you'll be able to delete it for example).</td>
|
<td>Unload DLL after call (using FreeLibrary, so you'll be able to delete it for example).</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>2</th>
|
||||||
|
<td>Experimental v2 syntax</td>
|
||||||
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</blockquote>
|
</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>
|
<h4>Usage Examples</h4>
|
||||||
|
|
||||||
<blockquote><pre>
|
<blockquote><pre>
|
||||||
|
@ -516,6 +527,19 @@ System::<b>Call</b> "*$0(i .r1)"
|
||||||
System::Free $0
|
System::Free $0
|
||||||
DetailPrint $1
|
DetailPrint $1
|
||||||
</pre></blockquote>
|
</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>
|
<blockquote><pre>
|
||||||
<a name="directvarmemparam"></a>System::<b>Call</b> "user32::GetClientRect(p $hwndparent, @ r0)"
|
<a name="directvarmemparam"></a>System::<b>Call</b> "user32::GetClientRect(p $hwndparent, @ r0)"
|
||||||
System::<b>Call</b> "*$0(i,i,i.r1,i.r2)"
|
System::<b>Call</b> "*$0(i,i,i.r1,i.r2)"
|
||||||
|
@ -564,6 +588,29 @@ loop:
|
||||||
done:
|
done:
|
||||||
System::Free $R0
|
System::Free $R0
|
||||||
</pre></blockquote>
|
</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>
|
<blockquote><pre>
|
||||||
<a name="repeat"></a>!define MB "user32::MessageBox(p$HWNDPARENT,t,t'NSIS System Plug-in',i0)"
|
<a name="repeat"></a>!define MB "user32::MessageBox(p$HWNDPARENT,t,t'NSIS System Plug-in',i0)"
|
||||||
System::<b>Call</b> "${MB}(,'my message',,)"
|
System::<b>Call</b> "${MB}(,'my message',,)"
|
||||||
|
|
|
@ -20,6 +20,8 @@ Released on ??? ??rd, 20??
|
||||||
|
|
||||||
\S2{} Minor Changes
|
\S2{} Minor Changes
|
||||||
|
|
||||||
|
\b Added System plug-in v2 syntax option
|
||||||
|
|
||||||
\b Added System plug-in B and H types
|
\b Added System plug-in B and H types
|
||||||
|
|
||||||
\b Added \R{intptrcmp}{IntPtrCmp}, IntPtrCmpU, and \R{intptrop}{IntPtrOp}
|
\b Added \R{intptrcmp}{IntPtrCmp}, IntPtrCmpU, and \R{intptrop}{IntPtrOp}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue