- fixes by brainsucker:
* Bug with proc call parts redefinition, # for example * Bug with memory protection during callback processing (XP SP2) - updated documentation: * all examples now work, thanks to brainsucker's fixes * visual improvements * pointer information git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@3590 212acab6-be3b-0410-9dea-997c60f758d6
This commit is contained in:
parent
f27b869756
commit
f43be4183a
4 changed files with 64 additions and 42 deletions
|
@ -316,6 +316,7 @@ SystemProc *PrepareProc(BOOL NeedForCall)
|
|||
while (SectionType != -1)
|
||||
{
|
||||
// Check for Section Change
|
||||
BOOL changed = TRUE;
|
||||
ChangesDone = SectionType;
|
||||
switch (*ib)
|
||||
{
|
||||
|
@ -329,10 +330,12 @@ SystemProc *PrepareProc(BOOL NeedForCall)
|
|||
break;
|
||||
case ')': SectionType = PST_RETURN; temp3 = temp = 0; break;
|
||||
case '?': SectionType = PST_OPTIONS; temp = 1; break;
|
||||
default:
|
||||
changed = FALSE;
|
||||
}
|
||||
|
||||
// Check for changes
|
||||
if (ChangesDone != SectionType)
|
||||
if (changed)
|
||||
{
|
||||
switch (ChangesDone)
|
||||
{
|
||||
|
@ -366,9 +369,10 @@ SystemProc *PrepareProc(BOOL NeedForCall)
|
|||
if (proc != NULL) GlobalFree(proc);
|
||||
// Get already defined proc
|
||||
proc = (SystemProc *) myatoi(cbuf);
|
||||
if (!proc) break;
|
||||
|
||||
// Find the last clone at proc queue
|
||||
while (proc->Clone != NULL) proc = (pr = proc)->Clone;
|
||||
while (proc && (proc->Clone != NULL)) proc = (pr = proc)->Clone;
|
||||
|
||||
// Clear parents record for child callback proc
|
||||
if (pr != NULL) pr->Clone = NULL;
|
||||
|
@ -385,20 +389,21 @@ SystemProc *PrepareProc(BOOL NeedForCall)
|
|||
break;
|
||||
case PT_PROC:
|
||||
case PT_VTABLEPROC:
|
||||
lstrcpy(proc->ProcName, cbuf);
|
||||
lstrcpy(proc->DllName, sbuf);
|
||||
break;
|
||||
case PT_STRUCT:
|
||||
lstrcpy(proc->ProcName, cbuf);
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
break;
|
||||
case PST_PARAMS:
|
||||
proc->ParamCount = ParamIndex;
|
||||
case PST_RETURN:
|
||||
case PST_OPTIONS:
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
ib++;
|
||||
cb = cbuf;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Parse the section
|
||||
|
@ -703,31 +708,32 @@ void ParamsIn(SystemProc *proc)
|
|||
i = (proc->ParamCount > 0)?(1):(0);
|
||||
while (TRUE)
|
||||
{
|
||||
ProcParameter *par = &proc->Params[i];
|
||||
// Step 1: retrive value
|
||||
if ((proc->Params[i].Input == IOT_NONE) || (proc->Params[i].Input == IOT_INLINE))
|
||||
if ((par->Input == IOT_NONE) || (par->Input == IOT_INLINE))
|
||||
realbuf = AllocStr("");
|
||||
else if (proc->Params[i].Input == IOT_STACK) realbuf = popstring();
|
||||
else if ((proc->Params[i].Input > 0) && (proc->Params[i].Input <= __INST_LAST))
|
||||
realbuf = getuservariable(proc->Params[i].Input - 1);
|
||||
else if (par->Input == IOT_STACK) realbuf = popstring();
|
||||
else if ((par->Input > 0) && (par->Input <= __INST_LAST))
|
||||
realbuf = getuservariable(par->Input - 1);
|
||||
else
|
||||
{
|
||||
// Inline input, will be freed as realbuf
|
||||
realbuf = (char*) proc->Params[i].Input;
|
||||
proc->Params[i].Input = IOT_INLINE;
|
||||
realbuf = (char*) par->Input;
|
||||
par->Input = IOT_INLINE;
|
||||
}
|
||||
|
||||
// Retreive pointer to place
|
||||
if (proc->Params[i].Option == -1) place = (int*) proc->Params[i].Value;
|
||||
else place = (int*) &(proc->Params[i].Value);
|
||||
if (par->Option == -1) place = (int*) par->Value;
|
||||
else place = (int*) &(par->Value);
|
||||
|
||||
// by default no blocks are allocated
|
||||
proc->Params[i].allocatedBlock = NULL;
|
||||
par->allocatedBlock = NULL;
|
||||
|
||||
// Step 2: place it
|
||||
switch (proc->Params[i].Type)
|
||||
switch (par->Type)
|
||||
{
|
||||
case PAT_VOID:
|
||||
proc->Params[i].Value = 0;
|
||||
par->Value = 0;
|
||||
break;
|
||||
case PAT_INT:
|
||||
*((int*) place) = (int) myatoi(realbuf);
|
||||
|
@ -736,18 +742,18 @@ void ParamsIn(SystemProc *proc)
|
|||
*((__int64*) place) = myatoi(realbuf);
|
||||
break;
|
||||
case PAT_STRING:
|
||||
/* if (proc->Params[i].Input == IOT_NONE)
|
||||
/* if (par->Input == IOT_NONE)
|
||||
*((int*) place) = (int) NULL;
|
||||
else*/
|
||||
*((int*) place) = (int) (proc->Params[i].allocatedBlock = AllocStr(realbuf));
|
||||
*((int*) place) = (int) (par->allocatedBlock = AllocStr(realbuf));
|
||||
break;
|
||||
case PAT_WSTRING:
|
||||
case PAT_GUID:
|
||||
wstr = (LPWSTR) (proc->Params[i].allocatedBlock = GlobalAlloc(GPTR, g_stringsize*2));
|
||||
wstr = (LPWSTR) (par->allocatedBlock = GlobalAlloc(GPTR, g_stringsize*2));
|
||||
MultiByteToWideChar(CP_ACP, 0, realbuf, g_stringsize, wstr, g_stringsize);
|
||||
if (proc->Params[i].Type == PAT_GUID)
|
||||
if (par->Type == PAT_GUID)
|
||||
{
|
||||
*((HGLOBAL*)place) = (proc->Params[i].allocatedBlock = GlobalAlloc(GPTR, 16));
|
||||
*((HGLOBAL*)place) = (par->allocatedBlock = GlobalAlloc(GPTR, 16));
|
||||
CLSIDFromString(wstr, *((LPCLSID*)place));
|
||||
GlobalFree((HGLOBAL) wstr);
|
||||
} else
|
||||
|
@ -756,7 +762,7 @@ void ParamsIn(SystemProc *proc)
|
|||
case PAT_CALLBACK:
|
||||
// Generate new or use old callback
|
||||
if (lstrlen(realbuf) > 0)
|
||||
proc->Params[i].Value = (int) CreateCallback((SystemProc*) myatoi(realbuf));
|
||||
par->Value = (int) CreateCallback((SystemProc*) myatoi(realbuf));
|
||||
break;
|
||||
}
|
||||
GlobalFree(realbuf);
|
||||
|
@ -765,7 +771,7 @@ void ParamsIn(SystemProc *proc)
|
|||
{
|
||||
char buf[1024];
|
||||
wsprintf(buf, "\t\t\tParam In %d: type %d value 0x%08X value2 0x%08X\n", i,
|
||||
proc->Params[i].Type, proc->Params[i].Value, proc->Params[i]._value);
|
||||
par->Type, par->Value, par->_value);
|
||||
SYSTEM_LOG_ADD(buf);
|
||||
}
|
||||
#endif
|
||||
|
@ -1218,7 +1224,7 @@ HANDLE CreateCallback(SystemProc *cbproc)
|
|||
cbproc->CallbackIndex = ++(CallbackIndex);
|
||||
cbproc->Options |= POPT_PERMANENT;
|
||||
|
||||
mem = (char *) (cbproc->Proc = GlobalAlloc(GPTR, 10));
|
||||
mem = (char *) (cbproc->Proc = VirtualAlloc(NULL, 10, MEM_COMMIT, PAGE_EXECUTE_READWRITE));
|
||||
*(mem++) = 0xB8; // Mov eax, const
|
||||
*(((int *)mem)++) = (int) cbproc;
|
||||
*(mem++) = 0xe9; // Jmp relative
|
||||
|
@ -1323,6 +1329,9 @@ BOOL WINAPI _DllMainCRTStartup(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lp
|
|||
|
||||
if (ul_reason_for_call == DLL_PROCESS_ATTACH)
|
||||
{
|
||||
// change the protection of return command
|
||||
VirtualProtect(&retexpr, sizeof(retexpr), PAGE_EXECUTE_READWRITE, &LastStackPlace);
|
||||
|
||||
// initialize some variables
|
||||
LastStackPlace = 0;
|
||||
LastStackReal = 0;
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
|
||||
<p>The System plug-in also allows the developer to allocate, free and copy memory; interact with COM objects and perform mathematical operations on 64-bit integers.</p>
|
||||
|
||||
<p>Programming knowledge is highly recommended in order to understand the System plug-in.</p>
|
||||
<p>Programming knowledge is highly recommended for good understanding of the System plug-in.</p>
|
||||
|
||||
<h4>Usage Examples From The Archive</h4>
|
||||
|
||||
|
@ -173,9 +173,9 @@ DetailPrint $4
|
|||
|
||||
<p><i>PARAMS</i>, <i>RETURN</i> and <i>OPTIONS</i> can be repeated many times in one Get/Call line. When repeating, a lot can be omitted, and only what you wish to change can be used. <i>Type</i>, <i>source</i> and/or <i>destination</i> can be omitted for each parameter, even the return value. Options can be added or removed. This allows you to define function prototypes and save on some typing. The <a href="#repeat">last two examples</a> show this.</p>
|
||||
|
||||
<p><b>(can't get a working example)</b> <i>PROC</i> can also be repeated but must be prefixed with a hash sign (`#').</p>
|
||||
<p><i>PROC</i> can also be repeated but must be prefixed with a hash sign (`#').</p>
|
||||
|
||||
<h4>Possible <i>PROC</i> values and Meanings</h4>
|
||||
<h4>Possible <i>PROC</i> Values and Meanings</h4>
|
||||
|
||||
<blockquote>
|
||||
<table>
|
||||
|
@ -284,6 +284,7 @@ DetailPrint $4
|
|||
<td><i>N</i> bytes of GUID (structures only)</td>
|
||||
</tr>
|
||||
</table>
|
||||
<p>Additionally, each type can be prefixed with an asterisk to denote a pointer. When using an asterisk, the System plug-in still expects the value of the parameter, rather than the pointer's address. To pass a direct address, use `i' with no asterisk. A <a href="#pointer">usage example</a> is available. <a href="#memfuncs">Alloc</a> returns addresses and its return value should therefore be used with `i', without an asterisk.</p>
|
||||
</blockquote>
|
||||
|
||||
<h4>Available Sources and Destinations</h4>
|
||||
|
@ -370,9 +371,10 @@ StrCmp $R0 "callback1" 0 +2
|
|||
DetailPrint "UseCallback passed ($0, $1) to the callback"
|
||||
</pre></blockquote>
|
||||
|
||||
<p>After you've processed the callback call, you should use <a href="#callfuncs">Call</a>, passing it the value returned by <a href="#callfuncs">Get</a> - the callback. This tells System to return from the callback. If you've specified a source for the return "parameter" when the callback was created, you should fill that source with the appropriate return value.</p>
|
||||
<p>After you've processed the callback call, you should use <a href="#callfuncs">Call</a>, passing it the value returned by <a href="#callfuncs">Get</a> - the callback. This tells System to return from the callback. If you've specified a source for the return "parameter" when the callback was created, you should fill that source with the appropriate return value. Callbacks are not automatically freed, don't forget to free it after you've finished using it.</p>
|
||||
|
||||
<blockquote><pre>System::Call "(i .r0, i .r1) isR0"
|
||||
<blockquote><pre>SetPluginUnload alwaysoff
|
||||
System::Call "(i .r0, i .r1) isR0"
|
||||
Pop $0
|
||||
System::Call "dll::UseCallback(k r0)"
|
||||
loop:
|
||||
|
@ -382,6 +384,8 @@ loop:
|
|||
System::Call $0 # tell system to return from the callback
|
||||
Goto loop
|
||||
done:
|
||||
SetPluginUnload manual
|
||||
System::Free $0
|
||||
</pre></blockquote>
|
||||
|
||||
<p>A complete working <a href="#callback">example</a> is available in the usage examples section.</p>
|
||||
|
@ -456,6 +460,12 @@ Pop $0
|
|||
System::<b>Call</b> "$0(, 'This is a System::Get test', 'NSIS System Plug-in',)"
|
||||
</pre></blockquote>
|
||||
<blockquote><pre>
|
||||
<a name="pointer"></a>System::<b>Call</b> "advapi32::GetUserName(t .r0, *i ${NSIS_MAX_STRLEN} r1) i.r2"
|
||||
DetailPrint "User name - $0"
|
||||
DetailPrint "String length - $1"
|
||||
DetailPrint "Return value - $2"
|
||||
</pre></blockquote>
|
||||
<blockquote><pre>
|
||||
<a name="structaddr"></a>System::Alloc 4
|
||||
Pop $0
|
||||
System::<b>Call</b> "*$0(i 5)"
|
||||
|
@ -519,8 +529,8 @@ System::<b>Call</b> "${MB}(,'another message',,) i.r0"
|
|||
MessageBox MB_OK "last call returned $0"
|
||||
</pre></blockquote>
|
||||
<blockquote><pre>
|
||||
System::<b>Call</b> "user32::MessageBox(i $HWNDPARENT, t 'test', t 'test', i 0) i.s ? \
|
||||
e (,t'test replacement',,) i.r0 ? !e"
|
||||
System::<b>Call</b> "user32::SendMessage(i $HWNDPARENT, t 'test', t 'test', i 0) i.s ? \
|
||||
e (,t'test replacement',,) i.r0 ? !e #user32::MessageBox"
|
||||
DetailPrint $0
|
||||
ClearErrors
|
||||
Pop $0
|
||||
|
@ -593,12 +603,14 @@ DetailPrint "0x89498A198E4566C % 157 = $0" # 118
|
|||
<blockquote><pre>
|
||||
System::<b>Int64Op</b> 0xF0F0F0F | 0xF0F0FFF
|
||||
Pop $0
|
||||
# IntFmt is 32-bit, this is just for the example
|
||||
IntFmt $0 "0x%X" $0
|
||||
DetailPrint "0xF0F0F0F | 0xF0F0FFF = $0" # 0xF0F0FFF
|
||||
</pre></blockquote>
|
||||
<blockquote><pre>
|
||||
System::<b>Int64Op</b> 0x12345678 & 0xF0F0F0F0
|
||||
Pop $0
|
||||
# IntFmt is 32-bit, this is just for the example
|
||||
IntFmt $0 "0x%X" $0
|
||||
DetailPrint "0x12345678 & 0xF0F0F0F0 = $0" # 0x10305070
|
||||
</pre></blockquote>
|
||||
|
@ -618,9 +630,9 @@ Pop $0
|
|||
DetailPrint "1 && 0 = $0" # 0
|
||||
</pre></blockquote>
|
||||
<blockquote><pre>
|
||||
System::<b>Int64Op</b> 5168 < 89873
|
||||
System::<b>Int64Op</b> 9302157012375 < 570197509190760
|
||||
Pop $0
|
||||
DetailPrint "5168 < 89873 = $0" # 1
|
||||
DetailPrint "9302157012375 < 570197509190760 = $0" # 1
|
||||
</pre></blockquote>
|
||||
<blockquote><pre>
|
||||
System::<b>Int64Op</b> 5168 > 89873
|
||||
|
@ -633,10 +645,9 @@ Pop $0
|
|||
DetailPrint "189189 = 189189 = $0" # 1
|
||||
</pre></blockquote>
|
||||
<blockquote><pre>
|
||||
System::<b>Int64Op</b> 1 ~
|
||||
System::<b>Int64Op</b> 156545668489 ~
|
||||
Pop $0
|
||||
IntFmt $0 "0x%X" $0
|
||||
DetailPrint "1 ~ = $0" # 0xFFFFFFFE
|
||||
DetailPrint "1 ~ = $0" # -156545668490
|
||||
</pre></blockquote>
|
||||
<blockquote><pre>
|
||||
System::<b>Int64Op</b> 1 !
|
||||
|
@ -670,7 +681,7 @@ System::Alloc 16
|
|||
</pre></blockquote>
|
||||
|
||||
<blockquote><pre>
|
||||
System::Call "*(i, i, i, t).s"
|
||||
System::Call "*(i, i, i, t)i.s"
|
||||
</pre></blockquote>
|
||||
|
||||
</blockquote>
|
||||
|
@ -680,7 +691,7 @@ System::Call "*(i, i, i, t).s"
|
|||
<blockquote><p>Setting data can be done using <a href="#callfuncs">Call</a>. It can be done in the allocation stage, or in another stage using the struct handling syntax.</p>
|
||||
|
||||
<blockquote><pre>
|
||||
System::Call "*(i 5, i 2, i 513, t 'test')"
|
||||
System::Call "*(i 5, i 2, i 513, t 'test')i.s"
|
||||
</pre></blockquote>
|
||||
|
||||
<blockquote><pre>
|
||||
|
|
|
@ -39,6 +39,8 @@ release 5, 11 september 2003.
|
|||
|
||||
bug-fix-release, 4.06.2004
|
||||
1. System::Copy /SIZE fixed (Kichik).
|
||||
2. System::Alloc with destination auto-allocation now pushes destination
|
||||
2. System::Copy with destination auto-allocation now pushes destination
|
||||
address on stack.
|
||||
3. Callbacks fixed (Kichik's kick is awesome).
|
||||
3. Callbacks fixed (Kichik's kick is awesome).
|
||||
4. Bug with proc call parts redefinition, # for example (pointed by Kichik).
|
||||
5. Bug with memory protection during callback processing (Kichik).
|
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue