- 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:
kichik 2004-07-23 17:23:34 +00:00
parent f27b869756
commit f43be4183a
4 changed files with 64 additions and 42 deletions

View file

@ -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;

View file

@ -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 &amp; 0xF0F0F0F0
Pop $0
# IntFmt is 32-bit, this is just for the example
IntFmt $0 "0x%X" $0
DetailPrint "0x12345678 &amp; 0xF0F0F0F0 = $0" # 0x10305070
</pre></blockquote>
@ -618,9 +630,9 @@ Pop $0
DetailPrint "1 &amp;&amp; 0 = $0" # 0
</pre></blockquote>
<blockquote><pre>
System::<b>Int64Op</b> 5168 &lt; 89873
System::<b>Int64Op</b> 9302157012375 &lt; 570197509190760
Pop $0
DetailPrint "5168 &lt; 89873 = $0" # 1
DetailPrint "9302157012375 &lt; 570197509190760 = $0" # 1
</pre></blockquote>
<blockquote><pre>
System::<b>Int64Op</b> 5168 &gt; 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>

View file

@ -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.