diff --git a/Contrib/System/Buffers.c b/Contrib/System/Buffers.c
index d373d8e9..6ae37d0f 100644
--- a/Contrib/System/Buffers.c
+++ b/Contrib/System/Buffers.c
@@ -3,91 +3,79 @@
#include "System.h"
#include "Buffers.h"
-PLUGINFUNCTION(AllocCopy)
- int mem;
-
- if (popint(&mem) == 0)
- {
- pushint(0);
- return;
- }
-
- mem = (int) GlobalCopy((HANDLE) mem);
- pushint(mem);
-PLUGINFUNCTIONEND
-
-PLUGINFUNCTION(Alloc)
+PLUGINFUNCTIONSHORT(Alloc)
+{
int size;
- int mem;
-
- if (popint(&size) == 0)
+ if ((size = popint()) == 0)
{
pushint(0);
return;
}
-
- mem = (int) GlobalAlloc(GPTR, size);
- pushint(mem);
+ pushint((int) GlobalAlloc(GPTR, size));
+}
PLUGINFUNCTIONEND
-PLUGINFUNCTION(Free)
- int mem;
+PLUGINFUNCTIONSHORT(Copy)
+{
+ int size = 0;
+ HANDLE source, dest;
+ char *str;
+ // Get the string
+ if ((str = popstring()) == NULL) return;
- if ((popint(&mem) == 0) || (mem == 0))
- {
- pushstring("false");
- return;
- }
- if ((GlobalFree((HANDLE) mem) == NULL)) pushstring("true");
- else pushstring("false");
+ // Check for size option
+ if (str[0] == '/')
+ {
+ size = (int) myatoi(str+1);
+ dest = popint();
+ }
+ else dest = (HANDLE) myatoi(str+1);
+ source = popint();
+
+ // Ok, check the size
+ if (size == 0) size = (int) GlobalSize(source);
+ // and the destinantion
+ if ((int) dest == 0) dest = GlobalAlloc((GPTR), size);
+
+ // COPY!
+ copymem(dest, source, size);
+
+ GlobalFree(str);
+}
PLUGINFUNCTIONEND
-/*typedef BOOL (__stdcall *GetDiskSpace)
-(
- LPCTSTR lpDirectoryName, // directory name
- PULARGE_INTEGER lpFreeBytesAvailable, // bytes available to caller
- PULARGE_INTEGER lpTotalNumberOfBytes, // bytes on disk
- PULARGE_INTEGER lpTotalNumberOfFreeBytes // free bytes on disk
-);*/
-
-/*PLUGINFUNCTION(MyFunction)
- GetDiskSpace proc;
- ULARGE_INTEGER i1, i2, i3;
- BOOL check;
-
- proc = (GetDiskSpace) GetProcAddress(GetModuleHandle("kernel32.dll"), "GetDiskFreeSpaceExA");
- check = proc(NULL, &i1, &i2, &i3);
-
- _asm
+PLUGINFUNCTIONSHORT(Free)
+{
+ char *str;
+ // Get the string
+ if ((str = popstring()) == NULL) return;
+ // Check for callback clear
+ if (lstrcmpi(str,"/callback") == 0)
+ {
+ SystemProc *proc, *next;
+ next = (SystemProc*) popint();
+ // Clear all the clone queue of callback
+ while ((proc = next) != NULL)
{
- push ecx
- lea ecx, i3
- push ecx
- lea ecx, i2
- push ecx
- lea ecx, i1
- push ecx
- push 0
-
- call proc
-
- mov check, eax
-// add esp, 16
- pop ecx
+ next = proc->Clone;
+ GlobalFree((HANDLE)proc);
}
+ }
+ else
+ GlobalFree((HANDLE) myatoi(str));
+ GlobalFree(str);
+}
+PLUGINFUNCTIONEND
- char buf[1024];
- wsprintf(buf,"$0=%s\n",getuservariable(INST_0));
- MessageBox(g_hwndParent,buf,0,MB_OK);
-PLUGINFUNCTIONEND*/
+char *copymem(char *output, char *input, int size)
+{
+ char *out = output;
+ while (size-- > 0) *(out++) = *(input++);
+ return output;
+}
HANDLE GlobalCopy(HANDLE Old)
{
- SIZE_T size;
- HANDLE n;
-
- size = GlobalSize(Old);
- n = GlobalAlloc(GPTR, size);
- CopyMemory(n, Old, size);
- return n;
+ SIZE_T size = GlobalSize(Old);
+ return copymem(GlobalAlloc(GPTR, size), Old, (int) size);
}
\ No newline at end of file
diff --git a/Contrib/System/Buffers.h b/Contrib/System/Buffers.h
index 538c481b..ae12263f 100644
--- a/Contrib/System/Buffers.h
+++ b/Contrib/System/Buffers.h
@@ -1,3 +1,4 @@
#pragma once
-extern HANDLE GlobalCopy(HANDLE Old);
\ No newline at end of file
+extern HANDLE GlobalCopy(HANDLE Old);
+extern char *copymem(char *output, char *input, int size);
\ No newline at end of file
diff --git a/Contrib/System/Example.txt b/Contrib/System/Example.txt
new file mode 100644
index 00000000..f51ed62d
--- /dev/null
+++ b/Contrib/System/Example.txt
@@ -0,0 +1,35 @@
+; Memory for paths
+System::Alloc 1024
+Pop $1
+; Get drives
+System::Call 'kernel32::GetLogicalDriveStringsA(i 1024, i r1) i'
+enumok:
+; One more drive?
+System::Call 'kernel32::lstrlenA(i r1) i.r2'
+IntCmp $2 0 enumex
+
+; Drive space
+System::Call 'kernel32::GetDiskFreeSpaceExA(i r1, *l .r3, *l .r4, *l .r5) i'
+
+; Pretty KBs
+System::Int64Op $3 / 1024
+Pop $3
+System::Int64Op $4 / 1024
+Pop $4
+System::Int64Op $5 / 1024
+Pop $5
+
+; Get pretty drive path string
+System::Call '*$1(&t1024 .r6)'
+; Message box
+System::Call 'user32::MessageBoxA(i $HWNDPARENT, t "Path: `$6`, Free for Caller: $3 kb, Free for All: $5 kb, Disk Size: $4 kb", t "Disk spaces example", i 33) i.r0'
+; User cancel?
+IntCmp $0 2 enumex
+
+; Next drive path
+IntOp $1 $1 + $2
+IntOp $1 $1 + 1
+goto enumok
+enumex: ; End of drives or user cancel
+; Free memory for paths
+System::Free $1
\ No newline at end of file
diff --git a/Contrib/System/New System.txt b/Contrib/System/New System.txt
new file mode 100644
index 00000000..a24ac620
--- /dev/null
+++ b/Contrib/System/New System.txt
@@ -0,0 +1,120 @@
+Additional notes:
+1. if you are using callbacks you should set SetPluginUnload
+to alwaysoff.
+2. If you are using inline input syntax, you shouldn't use the same quotes for
+quoting inlines and the whole defenition. Use \ as escape character (for ex.:
+\" will be replaced with ").
+
+----------- Main functions -----------
+
+RESULT/PROC System::Get "Proc"
+RESULT/RETURN System::Call "Proc" StackArgs...
+
+These functions return error RESULTs or PROC/RETURN in OK case.
+Error result is "error" and callback results are "callbackN", where N is
+callback index.
+
+----------- Additional functions -----------
+
+System::Int64Op ARG1 OP1
+System::Int64Op ARG1 OP2 ARG2
+ Performs operation on ARG1 and ARG2 (or on ARG1 only at single argument
+operator cases) and returns result on stack. Here are the OP2s: +, -, *, / DIV,
+% MOD, | OR, & AND, ^ XOR, || LOGIC-OR, && LOGIC-AND, < BELOW, > ABOVE, = EQUAL.
+There are only 2 OP1s: ~ (BITWISE-NOT) and ! (LOGIC-NOT).
+
+System::Alloc SIZE
+ Allocates SIZE bytes and returns the pointer on stack.
+
+System::Copy 0 SOURCE
+System::Copy DESTINATION SOURCE
+System::Copy /SIZE 0 SOURCE
+System::Copy /SIZE DESTINATION SOURCE
+ Copys data from source to destination, if /SIZE option and SIZE itself
+are undefined uses GlobalSize to determine source size. If destination is equal
+to 0, allocates the new memory block.
+
+System::Free ADDR
+System::Free /callback ADDR
+ Frees memory used by object at ADDR. If /callback option is specified,
+then ADDR is considered to be the addr of CALLBACK proc, and will be cleared
+accordingly (must be used!).
+
+----------- Get/Call syntaxis -----------
+
+Syntax:
+ "Proc(Params)Return?Options#Proc(Params)Return?Options..."
+
+Proc:
+ dll::proc -> Proc from DLL
+ ::addr -> Handle to system proc (memory address)
+ *addr -> Structure
+ * -> New structure
+ nothing -> Dup proc, usually callback or for future defenition
+
+ proc -> Ready proc specification for use or redefinition
+
+
+ If in System::Call proc specification points to already existing proc,
+the existing proc will be adapted and executed, otherwise the new proc will be
+created, executed and deleted.
+
+Params syntax: (Param1, Param2, Param3...), the number of params of proc is set
+to number of params at last Params section (so params cutting may ocur). If you
+need to save previous Param defenition use '_' after last param at Params
+section - no param cutting will ocur for it (section).
+Syntax of single param: "Type Source Destination", type can be omitted (previous
+or void will be used), each of Source and Destination can be replaced with
+'.' placeholder. Any parameter can be omitted at all - previous or default
+values will be used (example: "(i1,,i2)", 2nd arg omitted).
+
+ Return section is like single param defenition, but the Source defenition is
+never used, beside callback cases.
+
+Params & Return - Type:
+ v - void (generaly for return)
+ i - int (includes char, byte, short, handles, pointers and so on)
+ l - long & large integer (know as int64)
+ t - text, string (LPCSTR, pointer to first character)
+ b - boolean (needs/returns 'true':'false') - by the fact this type is
+ senseless -> usual integer can be used ('0':'1')
+ k - callback. See Callback section.
+
+ * - pointer specifier -> the proc needs the pointer to type, affects
+ next char (parameter) [ex: '*i' - pointer to int]
+
+For structures: & - additional meaning specificator.
+ &v - padding, &vN - pad for N bytes
+ &i - smaller types: &i4, &i2 (short), &i1 (byte)
+ &t - structure contains plain text, &tN - lenght == N bytes.
+
+Params & Return - Source / Destination:
+ . - makes no change to source
+ 0..9 - starts numeric inline input (accepts 0..9, x, |)
+ " / ' / ` - starts / ends string inline input, use \ to escape chars
+ Registers $0-$9 -> r(0..9)
+ Registers $R0-$R9 -> 'r(10..19)' or 'R(0..9)'
+ Additional regs -> c(Cmdline) d(instDir) o(Outdir) e(Exedir) a(lAng)
+ Stack -> s (you could pass arguments from Call line, see examples)
+ None -> n (0 (null) for input / specifies no output is required)
+
+Options (any option can be turned off (returned to default value) by specifing
+'!' where needed, for example _stdcall cc can be turned on by '!c'):
+ c - _cdecl calling convention (the stack restored by caller). By default
+stdcall calling convention is used (the stack restored by callee).
+ r - always return (for GET means you should pop result and proc,
+for CALL means you should pop result (at least)). By default result is returned
+for errors only (for GET you will pop either error result or right
+proc, and for CALL you will get either your return or result at defined
+return place.
+ n - no redefine. Whenever this proc will be used it will never be
+redefined either by GET or CALL. This options is never inherited to childs.
+ s - use general Stack. Whenever the first callback defined the system
+starts using the temporary stacks for function calls.
+
+Callback: you should check for callbacked return after every function call
+which can use your callback. Genereal scheme is:
+ 1. Check result for callback or normal return
+ 2. Input arguments defined for callback are at places.
+ 3. Place output and return arguments
+ 4. Call System::Call using callback proc handle
\ No newline at end of file
diff --git a/Contrib/System/Plugin.c b/Contrib/System/Plugin.c
index 1e0d2174..c18631b8 100644
--- a/Contrib/System/Plugin.c
+++ b/Contrib/System/Plugin.c
@@ -7,31 +7,47 @@ int g_stringsize;
stack_t **g_stacktop;
char *g_variables;
-int popstring(char *str)
+char *AllocString()
{
- stack_t *th;
- if (!g_stacktop || !*g_stacktop) return 0;
- th=(*g_stacktop);
- lstrcpy(str,th->text);
- *g_stacktop = th->next;
- GlobalFree((HGLOBAL)th);
- return 1;
+ return (char*) GlobalAlloc(GPTR,g_stringsize);
}
-void pushstring(char *str)
+char *AllocStr(char *str)
+{
+ return lstrcpy(AllocString(), str);
+}
+
+char* popstring()
+{
+ char *str;
+ stack_t *th;
+
+ if (!g_stacktop || !*g_stacktop) return NULL;
+ th=(*g_stacktop);
+
+ str = AllocString();
+ lstrcpy(str,th->text);
+
+ *g_stacktop = th->next;
+ GlobalFree((HGLOBAL)th);
+ return str;
+}
+
+char *pushstring(char *str)
{
stack_t *th;
- if (!g_stacktop) return;
+ if (!g_stacktop) return str;
th=(stack_t*)GlobalAlloc(GPTR,sizeof(stack_t)+g_stringsize);
lstrcpyn(th->text,str,g_stringsize);
th->next=*g_stacktop;
*g_stacktop=th;
+ return str;
}
char *getuservariable(int varnum)
{
- if (varnum < 0 || varnum >= __INST_LAST) return NULL;
- return g_variables+varnum*g_stringsize;
+ if (varnum < 0 || varnum >= __INST_LAST) return AllocString();
+ return AllocStr(g_variables+varnum*g_stringsize);
}
void setuservariable(int varnum, char *var)
@@ -42,15 +58,18 @@ void setuservariable(int varnum, char *var)
}
}
-int myatoi(char *s)
+// Updated for int64 and simple bitwise operations
+__int64 myatoi(char *s)
{
- unsigned int v=0;
+ __int64 v=0;
+ // Check for right input
+ if (!s) return 0;
if (*s == '0' && (s[1] == 'x' || s[1] == 'X'))
{
- s+=2;
+ s++;
for (;;)
{
- int c=*s++;
+ int c=*(++s);
if (c >= '0' && c <= '9') c-='0';
else if (c >= 'a' && c <= 'f') c-='a'-10;
else if (c >= 'A' && c <= 'F') c-='A'-10;
@@ -61,10 +80,9 @@ int myatoi(char *s)
}
else if (*s == '0' && s[1] <= '7' && s[1] >= '0')
{
- s++;
for (;;)
{
- int c=*s++;
+ int c=*(++s);
if (c >= '0' && c <= '7') c-='0';
else break;
v<<=3;
@@ -74,25 +92,52 @@ int myatoi(char *s)
else
{
int sign=0;
- if (*s == '-') { s++; sign++; }
+ if (*s == '-') sign++; else s--;
for (;;)
{
- int c=*s++ - '0';
+ int c=*(++s) - '0';
if (c < 0 || c > 9) break;
v*=10;
v+=c;
}
- if (sign) return -(int) v;
+ if (sign) v = -v;
}
- return (int)v;
+
+ // Support for simple ORed expressions
+ if (*s == '|')
+ {
+ v |= myatoi(s+1);
+ }
+
+ return v;
}
-int popint(int *value)
+void myitoa64(__int64 i, char *buffer)
{
- char buffer[1024];
- if (popstring(buffer) == 0) return FALSE;
- *value = myatoi(buffer);
- return TRUE;
+ char buf[128], *b = buf;
+
+ if (i < 0)
+ {
+ *(buffer++) = '-';
+ i = -i;
+ }
+ while (i > 0)
+ {
+ *(b++) = '0' + ((char) (i%10));
+ i /= 10;
+ }
+ while (b > buf) *(buffer++) = *(--b);
+ *buffer = 0;
+}
+
+int popint()
+{
+ int value;
+ char *str;
+ if ((str = popstring()) == NULL) return -1;
+ value = (int) myatoi(str);
+ GlobalFree(str);
+ return value;
}
void pushint(int value)
diff --git a/Contrib/System/Plugin.h b/Contrib/System/Plugin.h
index d8e84626..956302cd 100644
--- a/Contrib/System/Plugin.h
+++ b/Contrib/System/Plugin.h
@@ -36,18 +36,26 @@ __INST_LAST
};
#define PLUGINFUNCTION(name) void __declspec(dllexport) name(HWND hwndParent, int string_size, char *variables, stack_t **stacktop) { \
- g_hwndParent=hwndParent; \
+/* g_hwndParent=hwndParent; */\
g_stringsize=string_size; \
g_stacktop=stacktop; \
- g_variables=variables; {
-#define PLUGINFUNCTIONEND }}
+ g_variables=variables;
+#define PLUGINFUNCTIONEND }
+#define PLUGINFUNCTIONSHORT(name) void __declspec(dllexport) name(HWND hwndParent, int string_size, char *variables, stack_t **stacktop) { \
+ g_stringsize=string_size; \
+ g_stacktop=stacktop;
+#define PLUGINFUNCTIONEND }
+
+extern char *AllocStr(char *str);
+extern void myitoa64(__int64 i, char *buffer);
+extern char *AllocString();
extern char *getuservariable(int varnum);
extern void setuservariable(int varnum, char *var);
-extern int popstring(char *str); // 0 on empty stack
-extern void pushstring(char *str);
-extern int myatoi(char *s);
-extern int popint(int *value); // 0 on empty stack
+extern char* popstring(); // NULL - stack empty
+extern char* pushstring(char *str);
+extern __int64 myatoi(char *s);
+extern int popint(); // -1 -> stack empty
extern void pushint(int value);
extern HWND g_hwndParent;
diff --git a/Contrib/System/SysFunc.nsh b/Contrib/System/SysFunc.nsh
new file mode 100644
index 00000000..f3590eca
--- /dev/null
+++ b/Contrib/System/SysFunc.nsh
@@ -0,0 +1,283 @@
+; Some useful functions based on System plugin
+;
+; (c) brainsucker, 2002
+; (r) BSForce
+
+!include "${NSISDIR}\Contrib\System\System.nsh"
+!include "${NSISDIR}\Examples\WinMessages.nsh"
+
+!define ssName $9
+!define ssDelay $8
+!define ssInstance $7
+!define ssImage $6
+!define ssWnd $5
+!define ssResult $4
+!define ssCallback $3
+
+Function _systemSplashWndCB
+ ; Callback receives 4 values (
+ Pop $R2 ; hwnd
+ Pop $R5 ; umsg
+ Pop $R0 ; wparam
+ Pop $R1 ; lparam
+
+ ; Save globals and use them
+ Push $R6
+ Push $R7
+ Push $R8
+ Push $R9
+ Push $2
+ Push $5
+ Push $7
+ Push $9
+ StrCpy $2 $R2
+ StrCpy $5 $R5
+ StrCpy $7 $R0
+ StrCpy $9 $R1
+
+; MessageBox MB_OK "Got: $2 $5 $7 $9"
+
+ ; Message branching
+ IntCmp $5 ${WM_CLOSE} m_Close
+ IntCmp $5 ${WM_TIMER} m_Timer
+ IntCmp $5 ${WM_LBUTTONDOWN} m_Lbtn
+ IntCmp $5 ${WM_CREATE} m_Create
+ IntCmp $5 ${WM_PAINT} m_Paint
+ goto default
+
+m_Create:
+
+ ; Create structures
+ System::Call "*${sysRECT} (_) .R8"
+ System::Call "*${sysBITMAP} (_) .R9"
+
+ ; Get bitmap info
+ System::Call "${sysGetObject} (r6, ${sysBITMAP_SIZE}, R9)"
+
+ ; Get desktop info
+ System::Call "${sysSystemParametersInfo} (${SPI_GETWORKAREA}, 0, R8, 0)"
+
+ ; Style (callbacked)
+ System::Call "${sysSetWindowLong} (r2, ${GWL_STYLE}, 0) .s"
+ !insertmacro SINGLE_CALLBACK 5 $R7 1 _systemSplashWndCB
+
+ ; Calculate and set window pos
+
+ ; Get bmWidth(R2) and bmHeight(R3)
+ System::Call "*$R9${sysBITMAP} (,.R2,.R3)"
+ ; Get left(R4), top(R5), right(R6), bottom(R7)
+ System::Call "*$R8${sysRECT} (.R4,.R5,.R6,.R7)"
+
+ ; Left pos
+ IntOp $R0 $R6 - $R4
+ IntOp $R0 $R0 - $R2
+ IntOp $R0 $R0 / 2
+ IntOp $R0 $R0 + $R4
+
+ ; Top pos
+ IntOp $R1 $R7 - $R5
+ IntOp $R1 $R1 - $R3
+ IntOp $R1 $R1 / 2
+ IntOp $R1 $R1 + $R5
+
+ System::Call "${sysSetWindowPos} (r2, 0, R0, R1, R2, R3, ${SWP_NOZORDER}) .s"
+ !insertmacro SINGLE_CALLBACK 6 $R7 1 _systemSplashWndCB
+
+ ; Show window
+ System::Call "${sysShowWindow} (r2, ${SW_SHOW}) .s"
+ !insertmacro SINGLE_CALLBACK 7 $R7 1 _systemSplashWndCB
+
+ ; Set Timer
+ System::Call "${sysSetTimer} (r2, 1, r8,)"
+
+ ; Free used memory
+ System::Free $R8
+ System::Free $R9
+
+ StrCpy $R0 0
+ goto exit
+
+m_Paint:
+
+ ; Create structures
+ System::Call "*${sysRECT} (_) .R8"
+ System::Call "*${sysPAINTSTRUCT} (_) .R9"
+
+ ; Begin Paint
+ System::Call "${sysBeginPaint} (r2, R9) .R7"
+
+ ; CreateCompatibleDC
+ System::Call "${sysCreateCompatibleDC} (R7) .R6"
+
+ ; GetClientRect
+ System::Call "${sysGetClientRect} (r2, R8)"
+
+ ; Select new bitmap
+ System::Call "${sysSelectObject} (R6, r6) .R5"
+
+ ; Get left(R0), top(R1), right(R2), bottom(R3)
+ System::Call "*$R8${sysRECT} (.R0,.R1,.R2,.R3)"
+
+ ; width=right-left
+ IntOp $R2 $R2 - $R0
+ ; height=bottom-top
+ IntOp $R3 $R3 - $R1
+
+ System::Call "${sysBitBlt} (R7, R0, R1, R2, R3, R6, 0, 0, ${SRCCOPY})"
+
+ ; Select old bitmap
+ System::Call "${sysSelectObject} (R6, R5)"
+
+ ; Delete compatible DC
+ System::Call "${sysDeleteDC} (R6)"
+
+ ; End Paint
+ System::Call "${sysEndPaint} (r2, R9)"
+
+ ; Free used memory
+ System::Free $R8
+ System::Free $R9
+
+ StrCpy $R0 0
+ goto exit
+
+m_Timer:
+m_Lbtn:
+ StrCpy ${ssResult} 0
+ IntCmp $5 ${WM_TIMER} destroy
+ StrCpy ${ssResult} 1
+
+destroy:
+ System::Call "${sysDestroyWindow} (r2) .s"
+ !insertmacro SINGLE_CALLBACK 12 $R4 1 _systemSplashWndCB
+
+default:
+ ; Default
+ System::Call "${sysDefWindowProc} (r2, r5, r7, r9) .s"
+ !insertmacro SINGLE_CALLBACK 14 $R0 1 _systemSplashWndCB
+ goto exit
+
+m_Close:
+ StrCpy $R0 0
+ goto exit
+
+exit:
+ ; Restore globals
+ Pop $9
+ Pop $7
+ Pop $5
+ Pop $2
+ Pop $R9
+ Pop $R8
+ Pop $R7
+ Pop $R6
+
+ ; Return from callback
+ System::Call "${ssCallback}" $R0
+FunctionEnd
+
+Function systemSplash
+ Pop $R8
+ Pop $R9
+
+ ; Save global register
+ Push $9
+ Push $8
+ Push $7
+ Push $6
+ Push $5
+ Push $4
+ Push $3
+
+ StrCpy ${ssName} $R9
+ StrCpy ${ssDelay} $R8
+
+ ; Get module instance
+ System::Call "${sysGetModuleHandle} (i) .r7"
+ ; Pop ${ssInstance}
+
+ ; Get arrow cursor
+ System::Call "${sysLoadCursor} (0, i ${IDC_ARROW}) .R9"
+ ; Pop $R9
+
+ ; Get callback
+ System::Get "${sysWNDPROC}"
+ Pop ${ssCallback}
+
+ ; Create window class
+ System::Call "*${sysWNDCLASS} (,r3,,,r7,,R9,,,s) .R9" "_sp"
+ ; Pop $R9
+
+ ; Register window class
+ System::Call "${sysRegisterClass} (R9) .R9"
+ IntCmp $R9 0 errorexit ; Class registered ok?
+
+ ; Load Image (LR_CREATEDIBSECTION|LR_LOADFROMFILE = 0x2010)
+ System::Call '${sysLoadImage} (, s, ${IMAGE_BITMAP}, 0, 0, ${LR_CREATEDIBSECTION}|${LR_LOADFROMFILE}) .r6' "${ssName}.bmp"
+ ; Pop ${ssImage}
+ IntCmp ${ssImage} 0 errorexit ; Image loaded ok?
+
+ ; Start the sound (SND_ASYNC|SND_FILENAME|SND_NODEFAULT = 0x20003)
+ System::Call "${sysPlaySound} (s,,${SND_ASYNC}|${SND_FILENAME}|${SND_NODEFAULT})" "${ssName}.wav"
+
+ ; Create window
+ System::Call "${sysCreateWindowEx} (${WS_EX_TOOLWINDOW}, s, s,,,,,, $HWNDPARENT,,r7,) .s" "_sp" "_sp"
+ ; Pop ${ssWnd} -> SINGLE_CALLBACK will do that
+ !insertmacro SINGLE_CALLBACK 1 ${ssWnd} 1 _systemSplashWndCB
+
+ ; Create MSG struct
+ System::Call "*${sysMSG} (_) i.R9"
+ ; Pop $R9
+
+ ; -------------------------
+repeat:
+ ; Check for window
+ System::Call "${sysIsWindow} (r5) .s"
+ !insertmacro SINGLE_CALLBACK 2 $R8 1 _systemSplashWndCB
+ IntCmp $R8 0 finish
+
+ ; Get message
+ System::Call "${sysGetMessage} (R9, r5,_) .s"
+ !insertmacro SINGLE_CALLBACK 3 $R8 1 _systemSplashWndCB
+ IntCmp $R8 0 finish
+
+ ; Dispatch message
+ System::Call "${sysDispatchMessage} (R9) .s"
+ !insertmacro SINGLE_CALLBACK 4 $R8 1 _systemSplashWndCB
+
+ ; Repeat dispatch cycle
+ goto repeat
+ ; -------------------------
+
+finish:
+ ; Stop the sound
+ System::Call "${sysPlaySound}"
+
+ ; Delete bitmap object
+ System::Call "${sysDeleteObject} (r6)"
+
+ ; Delete the callback queue
+ System::Free /CALLBACK ${ssCallback}
+
+ ; Dialog return
+ StrCpy $R0 ${ssResult}
+ goto exit
+
+; Exit in case of error
+errorexit:
+ StrCpy $R0 -1
+ goto exit
+
+exit:
+ ; Restore globals
+ Pop $3
+ Pop $4
+ Pop $5
+ Pop $6
+ Pop $7
+ Pop $8
+ Pop $9
+
+ ; Return
+ Push $R0
+FunctionEnd
\ No newline at end of file
diff --git a/Contrib/System/System.c b/Contrib/System/System.c
index 56efb3c4..fbe9a9cc 100644
--- a/Contrib/System/System.c
+++ b/Contrib/System/System.c
@@ -3,384 +3,997 @@
#include "stdafx.h"
#include "Plugin.h"
+#include "Buffers.h"
#include "System.h"
+// Parse Section Type
+#define PST_PROC 0
+#define PST_PARAMS 1
+#define PST_RETURN 2
+#define PST_OPTIONS 3
+
+#define PCD_NONE 0
+#define PCD_PROC 1
+#define PCD_PARAMS 2
+#define PCD_DONE 3 // Just Continue
+
+int ParamSizeByType[6] = {0, // PAT_VOID (Size will be equal to 1)
+ 1, // PAT_INT
+ 2, // PAT_LONG
+ 1, // PAT_STRING
+ 1, // PAT_BOOLEAN
+ 0}; // PAT_CALLBACK (Size will be equal to 1)
+
+int z1, z2; // I've made them static for easier use at callback procs
+int LastStackPlace = 0;
+int LastStackReal = 0;
+SystemProc *LastProc = NULL;
+int CallbackIndex = 0;
HINSTANCE g_hInstance;
-#define PT_STRING_SIZE 2048
-#define PARAMOKCHECK(expr) if (expr) { pushint(0); return; }
+// Return to callback caller with stack restore
+char retexpr[3] = {0xC2, 0x00, 0x00};
+HANDLE retaddr;
-PLUGINFUNCTION(PartAddr)
- char buffer[1024];
- SystemProc *proc;
- // Retrieve ProcID
- PARAMOKCHECK(popstring(buffer) == 0);
- // Try to initialize proc ...
- proc = ParseProc(buffer);
- // ... and return it to nsis!
- pushint((int) proc);
-PLUGINFUNCTIONEND
+char *GetResultStr(SystemProc *proc)
+{
+ char *buf = AllocString();
+ if (proc->ProcResult == PR_OK) lstrcpy(buf, "ok");
+ else if (proc->ProcResult == PR_ERROR) lstrcpy(buf, "error");
+ else if (proc->ProcResult == PR_CALLBACK) wsprintf(buf, "callback%d", proc->CallbackIndex);
+ return buf;
+}
-PLUGINFUNCTION(FullAddr)
- char procid[1024], paramid[1024];
- SystemProc *proc;
- // Retrieve ProcID and ParamId
- PARAMOKCHECK((popstring(procid) == 0) || (popstring(paramid) == 0))
- // Try to initialize proc ...
- proc = ParseProc(procid);
- PARAMOKCHECK(proc == NULL)
- // Try to initialize params ...
- PARAMOKCHECK(ParseParam(proc, paramid) == FALSE)
- // ... and return it to nsis!
- pushint((int) proc);
-PLUGINFUNCTIONEND
-
-PLUGINFUNCTION(ShortAddr)
- char paramid[1024];
- SystemProc *proc;
-
- // Retrieve Proc and ParamId
- PARAMOKCHECK((popint(&((int)proc)) == 0) || (popstring(paramid) == 0))
- // Try to initialize params ...
- PARAMOKCHECK(ParseParam(proc, paramid) == FALSE)
- // ... and return it to nsis!
- pushint((int) proc);
-PLUGINFUNCTIONEND
+PLUGINFUNCTION(Get)
+{
+ SystemProc *proc = PrepareProc();
+ if ((proc->Options & POPT_ALWRETURN) != 0)
+ {
+ // Always return flag set -> return separate proc and result
+ pushint((int) proc);
+ GlobalFree(pushstring(GetResultStr(proc)));
+ } else
+ {
+ if (proc->ProcResult != PR_OK)
+ {
+ // No always return flag and error result - return result
+ GlobalFree(pushstring(GetResultStr(proc)));
+ // If proc is permanent?
+ if ((proc->Options & POPT_PERMANENT) == 0)
+ GlobalFree((HANDLE) proc); // No, free it
+ }
+ else // Ok result, return proc
+ pushint((int) proc);
+ }
+} PLUGINFUNCTIONEND
PLUGINFUNCTION(Call)
- SystemProc *proc;
-
- // Retrieve Proc
- PARAMOKCHECK(popint(&((int)proc)) == 0)
-
- // Run the proc
- SystemCall(proc);
-PLUGINFUNCTIONEND
-
-PLUGINFUNCTION(ShortCall)
- char paramid[1024];
- SystemProc *proc;
-
- // Retrieve Proc and ParamId
- PARAMOKCHECK((popint(&((int)proc)) == 0) || (popstring(paramid) == 0))
- // Try to initialize params ...
- PARAMOKCHECK(ParseParam(proc, paramid) == FALSE)
-
- // Run the proc
- SystemCall(proc);
-PLUGINFUNCTIONEND
-
-PLUGINFUNCTION(FullCall)
- char procid[1024], paramid[1024];
- SystemProc *proc;
-
- // Retrieve ProcID and ParamId
- PARAMOKCHECK((popstring(procid) == 0) || (popstring(paramid) == 0))
- // Try to initialize proc ...
- proc = ParseProc(procid);
- PARAMOKCHECK(proc == NULL)
- // Try to initialize params ...
- PARAMOKCHECK(ParseParam(proc, paramid) == FALSE)
- // ... and return it to nsis!
-
- // Run the proc
- SystemCall(proc);
-
- // We've created it, we've to destroyit
- GlobalFree(proc);
-PLUGINFUNCTIONEND
-
-SystemProc *ParseProc(char *ProcID)
{
- SystemProc *proc;
- char dllname[1024], procname[256], *p1, *p2;
+ // Prepare input
+ SystemProc *proc = PrepareProc();
+ if (proc->ProcResult != PR_CALLBACK)
+ ParamAllocate(proc);
+ ParamsIn(proc);
- // Extract dllname
- p1 = ProcID;
- p2 = dllname;
- while (*p1 && (*p1 != '?')) *(p2++) = *(p1++);
- *p2 = 0;
- if ((lstrlen(dllname) == 0) || (*p1 == 0)) return NULL;
+ // Make the call
+ if (proc->ProcResult != PR_ERROR)
+ {
+ switch (proc->ProcType)
+ {
+ case PT_NOTHING:
+ if (proc->ProcResult == PR_CALLBACK)
+ proc = CallBack(proc);
+ break;
+ case PT_PROC:
+ proc = CallProc(proc); break;
+ case PT_STRUCT:
+ CallStruct(proc); break;
+ }
+ }
- // Extract procname
- p1++;
- p2 = procname;
- while (*p1 && (*p1 != '?')) *(p2++) = *(p1++);
- *p2 = 0;
- if ((lstrlen(procname) == 0) || (*p1 == 0)) return NULL;
+ // Process output
+ if ((proc->Options & POPT_ALWRETURN) != 0)
+ {
+ // Always return flag set - return separate return and result
+ ParamsOut(proc);
+ GlobalFree(pushstring(GetResultStr(proc)));
+ } else
+ {
+ if (proc->ProcResult != PR_OK)
+ {
+ ProcParameter pp;
+ // Save old return param
+ pp = proc->Params[0];
- // Ok, check If there is at least 1 param
- p1++;
- if (*p1 == 0) return NULL;
+ // Return result instead of return value
+ proc->Params[0].Value = (int) GetResultStr(proc);
+ proc->Params[0].Type = PAT_STRING;
+ // Return all params
+ ParamsOut(proc);
- // Allocate memory for new Proc
- proc = (SystemProc*) GlobalAlloc(GPTR, sizeof(SystemProc));
+ // Restore old return param
+ proc->Params[0] = pp;
+ } else
+ ParamsOut(proc);
+ }
- // Ok, retrieve dll handle
- proc->dll = GetModuleHandle(dllname);
- if (proc->dll == NULL)
- {
- // Dll is not loaded already
- proc->dll = LoadLibrary(dllname);
- if (proc->dll == NULL)
- {
- // Dll not found
- GlobalFree(proc);
- return NULL;
- }
- }
+ // Deallocate params if not callback
+ if (proc->ProcResult != PR_CALLBACK)
+ ParamsDeAllocate(proc);
- // Dll succesfully loaded, now we should Get Proc Address
- proc->proc = GetProcAddress(proc->dll, procname);
- if (proc->proc == NULL)
- {
- // Proc is not loaded succesfully
- GlobalFree(proc);
- return NULL;
- }
+ // If proc is permanent?
+ if ((proc->Options & POPT_PERMANENT) == 0)
+ GlobalFree((HANDLE) proc); // No, free it
+} PLUGINFUNCTIONEND
- // Allright, lets parse parameters
- proc->ParamCount = 0;
- while (*p1 && (*p1 != '?'))
- {
- // Memory is initialized to zeros with GlobalAlloc, so we don't need
- // to set defaults for Parameters
-
- // We should check for pointer
- if ((*p1 == 'p') || (*p1 == 'P'))
- {
- proc->Params[proc->ParamCount].IsPointer = TRUE;
- // Check for next character to be valid
- p1++;
- if ((*p1 == 0) || (*p1 == '?')) break;
- }
+PLUGINFUNCTIONSHORT(Int64Op)
+{
+ __int64 i1, i2 = 0, i3, i4;
+ char *op, *o1, *o2;
+ char buf[128];
- switch(*p1)
- {
- case 'v':
- case 'V':
- proc->Params[proc->ParamCount].Type = PT_VOID;
- break;
- case 'i':
- case 'I':
- proc->Params[proc->ParamCount].Type = PT_INT;
- break;
- case 'l':
- case 'L':
- proc->Params[proc->ParamCount].Type = PT_LONG;
- break;
- case 's':
- case 'S':
- proc->Params[proc->ParamCount].Type = PT_STRING;
- break;
- case 'b':
- case 'B':
- proc->Params[proc->ParamCount].Type = PT_BOOLEAN;
- break;
- };
+ // Get strings
+ o1 = popstring(); op = popstring();
+ i1 = myatoi(o1); // convert first arg to int64
+ if ((*op != '~') && (*op != '!'))
+ {
+ // get second arg, convert it, free it
+ o2 = popstring();
+ i2 = myatoi(o2);
+ GlobalFree(o2);
+ }
- // Move to next character
- proc->ParamCount++;
- p1++;
- }
- return proc;
+ // operation
+ switch (*op)
+ {
+ case '+': i1 += i2; break;
+ case '-': i1 -= i2; break;
+ case '*': i1 *= i2; break;
+ case '/':
+ case '%':
+ // It's unclear, but in this case compiler will use DivMod rountine
+ // instead of two separate Div and Mod rountines.
+ i3 = i1 / i2; i4 = i1 % i2;
+ if (*op == '/') i1 = i3; else i1 = i4;
+ break;
+ case '|': if (op[1] == '|') i1 = i1 || i2; else i1 |= i2; break;
+ case '&': if (op[1] == '&') i1 = i1 && i2; else i1 &= i2; break;
+ case '^': i1 ^= i2; break;
+ case '~': i1 = ~i1; break;
+ case '!': i1 = !i1; break;
+ case '<': if (op[1] == '<') i1 = i1 << i2; else i1 = i1 < i2; break;
+ case '>': if (op[1] == '>') i1 = i1 >> i2; else i1 = i1 > i2; break;
+ case '=': i1 = (i1 == i2); break;
+ }
+
+ // Output and freedom
+ myitoa64(i1, buf);
+ pushstring(buf);
+ GlobalFree(o1); GlobalFree(op);
+} PLUGINFUNCTIONEND
+
+__int64 GetIntFromString(char **p)
+{
+ char buffer[128], *b = buffer;
+ (*p)++; // First character should be skipped
+ while (((**p >= 'a') && (**p <= 'f')) || ((**p >= 'A') && (**p <= 'F')) || ((**p >= '0') && (**p <= '9')) || (**p == 'X') || (**p == '-') || (**p == 'x') || (**p == '|')) *(b++) = *((*p)++);
+ *b = 0;
+ (*p)--; // We should point at last digit
+ return myatoi(buffer);
}
-BOOL ParseParam(SystemProc *proc, char *ParamID)
+SystemProc *PrepareProc()
{
- char *p1;
- ProcParameter *par;
-
- par = proc->Params + 1;
- p1 = ParamID;
+ int SectionType = PST_PROC, // First section is always proc spec
+ ProcType = PT_NOTHING, // Default proc spec
+ ChangesDone = 0,
+ ParamIndex = 0,
+ temp = 0, temp2, temp3, temp4;
+ SystemProc *proc = NULL;
+ char *ibuf, *ib, *sbuf, *cbuf, *cb;
- // Allright, lets parse input parameters
- while (*p1 && (*p1 != '?'))
- {
- if ((*p1 == 's') || (*p1 == 'S')) par->Input = IOT_STACK;
- else if ((*p1 == 'n') || (*p1 == 'N')) par->Input = IOT_NONE;
- else if ((*p1 >= '0') && (*p1 <= '9')) par->Input = (*p1-'0')+1;
- else if ((*p1 >= 'a') && (*p1 <= 'o')) par->Input = (*p1-'a')+11;
- else if ((*p1 >= 'A') && (*p1 <= 'O')) par->Input = (*p1-'A')+11;
+ // Retrieve proc specs
+ cb = (cbuf = AllocString()); // Current String buffer
+ sbuf = AllocString(); // Safe String buffer
+ ib = ibuf = popstring(); // Input string
- // Move to next param & character
- par++;
- p1++;
- }
+ // Parse the string
+ while (SectionType != -1)
+ {
+ // Check for Section Change
+ ChangesDone = SectionType;
+ switch (*ib)
+ {
+ case 0x0: SectionType = -1; break;
+ case '#': SectionType = PST_PROC; ProcType = PT_NOTHING; break;
+ case '(': SectionType = PST_PARAMS; ParamIndex = 1; temp3 = temp = 0; break;
+ case ')': SectionType = PST_RETURN; temp3 = temp = 0; break;
+ case '?': SectionType = PST_OPTIONS; temp = 1; break;
+ }
- if (*p1++ == 0) return TRUE;
- par = proc->Params;
+ // Check for changes
+ if (ChangesDone != SectionType)
+ {
+ switch (ChangesDone)
+ {
+ case PST_PROC:
+ *cb = 0;
+ // Adopt proc
+ if (proc == NULL)
+ {
+ proc = (SystemProc *) GlobalAlloc(GPTR, sizeof(SystemProc));
+ proc->Options = 0;
+ proc->ParamCount = 0;
+ }
+ // Default parameters
+ *proc->DllName = 0;
+ *proc->ProcName = 0;
+ proc->Dll = NULL;
+ proc->Proc = NULL;
+ proc->ProcType = ProcType;
+ proc->ProcResult = PR_OK;
+
+ // Section changed and previos section was Proc
+ switch (ProcType)
+ {
+ case PT_NOTHING:
+ // Is it previous proc or just unknown proc?
+ if (cb != cbuf)
+ {
+ if (proc != NULL) GlobalFree(proc);
+ // Get already defined proc
+ proc = (SystemProc *) myatoi(cbuf);
- // Allright, lets parse output parameters
- while (*p1)
- {
- if ((*p1 == 's') || (*p1 == 'S')) par->Output = IOT_STACK;
- else if ((*p1 == 'n') || (*p1 == 'N')) par->Output = IOT_NONE;
- else if ((*p1 >= '0') && (*p1 <= '9')) par->Output = (*p1-'0')+1;
- else if ((*p1 >= 'a') && (*p1 <= 'o')) par->Output = (*p1-'a')+11;
- else if ((*p1 >= 'A') && (*p1 <= 'O')) par->Output = (*p1-'A')+11;
+ // Find the last clone at proc queue
+ while (proc->Clone != NULL) proc = proc->Clone;
- // Move to next param & character
- par++;
- p1++;
- }
+ // Never Redefine?
+ if ((proc->Options & POPT_NEVERREDEF) != 0)
+ {
+ // 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
+ }
+ break;
+ case PT_PROC:
+ lstrcpy(proc->ProcName, cbuf);
+ lstrcpy(proc->DllName, sbuf);
+ break;
+ case PT_STRUCT:
+ lstrcpy(proc->ProcName, cbuf);
+ break;
+ }
+ continue;
+ case PST_PARAMS:
+ proc->ParamCount = ParamIndex;
+ case PST_RETURN:
+ case PST_OPTIONS:
+ continue;
+ }
+ }
- return TRUE;
+ // Parse the section
+ ChangesDone = PCD_NONE;
+ switch (SectionType)
+ {
+ // Proc sections parser
+ case PST_PROC:
+ switch (*ib)
+ {
+ case ':':
+ // Is it '::'
+ if (*(ib+1) != ':') break;
+ ib++; // Skip next ':'
+
+ if (cb > cbuf)
+ {
+ *cb = 0;
+ lstrcpy(sbuf, cbuf);
+ } else *sbuf = 0; // No dll - system proc
+
+ // Ok
+ ProcType = PT_PROC;
+ ChangesDone = PCD_DONE;
+ break;
+ case '*':
+ // Structure defenition
+ ProcType = PT_STRUCT;
+ ChangesDone = PCD_DONE;
+ break;
+ }
+ break;
+
+ // Params and return sections parser
+ case PST_RETURN:
+ ParamIndex = 0; // Uses the same logic as PST_PARAMS section
+ case PST_PARAMS:
+ temp2 = -1; temp4 = 0; // Our type placeholder
+ switch (*ib)
+ {
+ case ' ':
+ break;
+ case '_': // No param cutting specifier
+ if (proc->ParamCount > ParamIndex) ParamIndex = proc->ParamCount;
+ temp3 = temp = 0; // Clear parameter options
+ break;
+ case ',': // Next param
+ temp3 = temp = 0; // Clear parameter options
+ ParamIndex++;
+ break;
+ case '&':
+ temp = 1; break; // Special parameter option
+ case '*':
+ temp = -1; break; // Pointer parameter option
+
+ // Types
+ case 'v':
+ case 'V': temp2 = PAT_VOID; break;
+ case 'i':
+ case 'I': temp2 = PAT_INT; break;
+ case 'l':
+ case 'L': temp2 = PAT_LONG; break;
+ case 't':
+ case 'T': temp2 = PAT_STRING; break;
+ case 'b':
+ case 'B': temp2 = PAT_BOOLEAN; break;
+ case 'k':
+ case 'K': temp2 = PAT_CALLBACK; break;
+
+ // Input output specifiers
+ case '.': temp3++; break; // skip specifier
+
+ case 'R':
+ temp4 = ((int) GetIntFromString(&ib))+1;
+ if (temp4 < 11) temp4 += 10;
+ break;
+ case 'r': temp4 = ((int) GetIntFromString(&ib))+1; break; // Register
+
+ case '-':
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ // Numeric inline
+ if (temp3 == 0)
+ {
+ ib--;
+ // It's stupid, I know, but I'm too laze to do another thing
+ myitoa64(GetIntFromString(&(ib)),(char *)(temp4 = (int) AllocString()));
+ }
+ break;
+
+ case '\"': case '\'': case '\`':
+ // Character inline
+ {
+ char start = *ib;
+ cb = cbuf;
+ // copy inline
+ while ((*(++ib) != start) && (*ib))
+ if (*ib == '\\') *(cb++) = *(++ib);
+ else *(cb++) = *(ib);
+ // finish and save
+ *cb = 0;
+ temp4 = (int) AllocStr(cbuf);
+ }
+ break;
+
+ case 's':
+ case 'S': temp4 = -1; break; // Stack
+ case 'c':
+ case 'C': temp4 = INST_CMDLINE+1; break;
+ case 'd':
+ case 'D': temp4 = INST_INSTDIR+1; break;
+ case 'o':
+ case 'O': temp4 = INST_OUTDIR+1; break;
+ case 'e':
+ case 'E': temp4 = INST_EXEDIR+1; break;
+ case 'a':
+ case 'A': temp4 = INST_LANG+1; break;
+ }
+
+ // Param type changed?
+ if (temp2 != -1)
+ {
+ proc->Params[ParamIndex].Type = temp2;
+ proc->Params[ParamIndex].Size = // If pointer, then 1, else by type
+ (temp == -1)?(1):((ParamSizeByType[temp2]>0)?(ParamSizeByType[temp2]):(1));
+ // Get the parameter real special option value
+ if (temp == 1) temp = (int) GetIntFromString(&ib);
+ proc->Params[ParamIndex].Option = temp;
+ proc->Params[ParamIndex].Value = 0;
+ proc->Params[ParamIndex].Input = IOT_NONE;
+ proc->Params[ParamIndex].Output = IOT_NONE;
+ }
+
+ // Param source/dest changed?
+ if (temp4 != 0)
+ {
+ if (temp3 == 0)
+ {
+ // it may contain previous inline input
+ if (!((proc->Params[ParamIndex].Input > -1) && (proc->Params[ParamIndex].Input <= __INST_LAST)))
+ GlobalFree((HANDLE) proc->Params[ParamIndex].Input);
+ proc->Params[ParamIndex].Input = temp4;
+ }
+ if (temp3 == 1)
+ proc->Params[ParamIndex].Output = temp4;
+ // Next parameter is output or something else
+ temp3++;
+ }
+
+ ChangesDone = PCD_DONE;
+ break;
+
+ // Options sections parser
+ case PST_OPTIONS:
+ temp2 = 0;
+ switch (*ib)
+ {
+ case ' ':
+ break;
+ case '!': temp = -temp; break;
+ case 'c':
+ temp2 = POPT_CDECL;
+ break;
+ case 'r':
+ temp2 = POPT_ALWRETURN;
+ break;
+ case 'n':
+ temp2 = POPT_NEVERREDEF;
+ break;
+ case 's':
+ temp2 = POPT_GENSTACK;
+ break;
+ }
+
+ // New Options
+ if (temp2 != 0)
+ {
+ if (temp == 1) proc->Options |= temp2;
+ else proc->Options &= ~temp2;
+ // Back to default (turn on nothing) state
+ temp = 1; temp2 = 0;
+ }
+
+ ChangesDone = PCD_DONE;
+ break;
+ }
+
+ // Nothing done, just copy char to buffer
+ if (ChangesDone == PCD_NONE) *(cb++) = *(ib);
+ // Something done, buffer = ""
+ else cb = cbuf;
+
+ // Increase input pointer
+ ib++;
+ }
+
+ GlobalFree(ibuf);
+ GlobalFree(cbuf);
+ GlobalFree(sbuf);
+
+ // Ok, the final step: check proc for existance
+ if (proc->Proc == NULL)
+ {
+ switch (proc->ProcType)
+ {
+ case PT_NOTHING: break;
+ case PT_PROC:
+ if (*proc->DllName == 0)
+ {
+ // Use direct system proc address
+ if ((proc->Proc = (HANDLE) myatoi(proc->ProcName)) == 0)
+ proc->ProcResult = PR_ERROR;
+ } else
+ {
+ // Get DLL address
+ if ((proc->Dll = GetModuleHandle(proc->DllName)) == NULL)
+ if ((proc->Dll = LoadLibrary(proc->DllName)) == NULL)
+ {
+ proc->ProcResult = PR_ERROR;
+ break;
+ }
+
+ // Get proc address
+ if ((proc->Proc = GetProcAddress(proc->Dll, proc->ProcName)) == NULL)
+ proc->ProcResult = PR_ERROR;
+ }
+ break;
+ case PT_STRUCT:
+ if (*(proc->ProcName) != 0) proc->Proc = (HANDLE) myatoi(proc->ProcName);
+ break;
+ }
+ }
+
+ return proc;
}
-void ParamsInput(SystemProc *proc)
+void ParamAllocate(SystemProc *proc)
{
- int i;
- ProcParameter *par;
- char buffer[PT_STRING_SIZE], *realbuf;
+ int i;
- par = proc->Params + 1;
- for (i = 1; i < proc->ParamCount; i++, par++)
- {
- // Step 1: retrive value
- if (par->Input == IOT_STACK) popstring(realbuf = buffer);
- else if (par->Input > 0) realbuf = getuservariable(par->Input - 1);
- else *(realbuf = buffer) = 0;
-
- // Step 2: place it
- switch (par->Type)
- {
- // TODO: PT_VOID input????
- //case PT_VOID:
- case PT_INT:
- {
- if (par->IsPointer)
- {
- par->Value = (int) GlobalAlloc(GPTR, sizeof(int));
- *((int*) par->Value) = myatoi(realbuf);
- } else par->Value = myatoi(realbuf);
- }
- break;
- case PT_LONG:
- {
- if (par->IsPointer)
- {
- par->Value = (int) GlobalAlloc(GPTR, sizeof(ULARGE_INTEGER));
- ((ULARGE_INTEGER*) par->Value)->LowPart = myatoi(realbuf);
- ((ULARGE_INTEGER*) par->Value)->HighPart = 0; // TODO: 64 bit atoi conversion
- } else; // TODO: PT_LONG direct input????
- }
- break;
- case PT_STRING:
- {
- if (par->IsPointer)
- {
- par->Value = (int) GlobalAlloc(GPTR, sizeof(int));
- *((int*)par->Value) = GlobalAlloc(GPTR, PT_STRING_SIZE);
- lstrcpy(*((LPCSTR*) par->Value), realbuf);
- } else
- {
- par->Value = (int) GlobalAlloc(GPTR, PT_STRING_SIZE);
- lstrcpy(par->Value, realbuf);
- }
- }
- break;
- // TODO: PT_BOOLEAN support ???
- //case PT_BOLEAN: ;
- }
- }
+ for (i = 0; i <= proc->ParamCount; i++)
+ if (((HANDLE) proc->Params[i].Value == NULL) && (proc->Params[i].Option == -1))
+ proc->Params[i].Value = (int) GlobalAlloc(GPTR, ParamSizeByType[proc->Params[i].Type]);
}
-void ParamsOutput(SystemProc *proc)
+void ParamsIn(SystemProc *proc)
{
- int i;
- ProcParameter *par;
- char buffer[PT_STRING_SIZE];
+ int i, *place;
+ char *realbuf;
- par = proc->Params;
- for (i = 0; i < proc->ParamCount; i++, par++)
- {
- // Step 1: retrieve value
- switch (par->Type)
- {
- case PT_VOID:
- {
- if (par->IsPointer); // TODO: Pointer To Void Output
- else *buffer = 0;
- }
- break;
- case PT_INT:
- {
- if (par->IsPointer)
- {
- wsprintf(buffer, "%d", *((int*) par->Value));
- GlobalFree(par->Value);
- } else wsprintf(buffer, "%d", par->Value);
- }
- break;
- case PT_LONG:
- {
- if (par->IsPointer)
- {
- wsprintf(buffer, "%ld", *((ULARGE_INTEGER*) par->Value));
- GlobalFree(par->Value);
- } else; // TODO: PT_LONG direct output????
- }
- break;
- case PT_STRING:
- {
- if (par->IsPointer)
- {
- lstrcpy(buffer, *((LPCSTR*) par->Value));
- GlobalFree(*((int*)par->Value));
- GlobalFree(par->Value);
- } else
- {
- lstrcpy(buffer, par->Value);
- GlobalFree((HANDLE) par->Value);
- }
- }
- break;
- // TODO: PT_BOOLEAN support ???
- //case PT_BOLEAN: ;
- }
+ i = 1;
+ do
+ {
+ // Step 1: retrive value
+ if (proc->Params[i].Input == IOT_NONE) 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
+ {
+ // Inline input, will be freed as realbuf
+ realbuf = (char*) proc->Params[i].Input;
+ proc->Params[i].Input = 0;
+ }
- // Step 2: place it
- if (par->Output == IOT_STACK) pushstring(buffer);
- else if (par->Output > 0) setuservariable(par->Output - 1, buffer);
- }
+ // Retreive pointer to place
+ if (proc->Params[i].Option == -1) place = (int*) proc->Params[i].Value;
+ else place = (int*) &(proc->Params[i].Value);
+
+ // Step 2: place it
+ switch (proc->Params[i].Type)
+ {
+ case PAT_VOID:
+ proc->Params[i].Value = 0;
+ break;
+ case PAT_INT:
+ *((int*) place) = (int) myatoi(realbuf);
+ break;
+ case PAT_LONG:
+ *((__int64*) place) = myatoi(realbuf);
+ break;
+ case PAT_STRING:
+ *((int*) place) = (int) AllocStr(realbuf);
+ break;
+ case PAT_BOOLEAN:
+ *((int*) place) = lstrcmpi(realbuf, "true");
+ break;
+ case PAT_CALLBACK:
+ // Generate new or use old callback
+ if (lstrlen(realbuf) > 0)
+ proc->Params[i].Value = (int) CreateCallback((SystemProc*) myatoi(realbuf));
+ break;
+ }
+ GlobalFree(realbuf);
+
+ if (i == proc->ParamCount) i = 0;
+ else i++;
+ }
+ while (i != 1);
}
-void SystemCall(SystemProc *proc)
+void ParamsDeAllocate(SystemProc *proc)
{
- int z;
- ProcParameter *par;
+ int i;
- // Prepare input arguments
- ParamsInput(proc);
-
- // Push arguments to stack
- par = proc->Params+proc->ParamCount-1;
- while (par > proc->Params)
- {
- z = par->Value;
- _asm
- {
- push z
- }
- par--;
- }
-
- // Call the proc and save return
- z = proc->proc;
- _asm
- {
- call z
- mov z, eax
- }
- proc->Params[0].Value = z;
-
- // Prepare output parameters
- ParamsOutput(proc);
+ for (i = proc->ParamCount; i >= 0; i--)
+ if (((HANDLE) proc->Params[i].Value != NULL) && (proc->Params[i].Option == -1))
+ GlobalFree((HANDLE) proc->Params[i].Value);
}
+void ParamsOut(SystemProc *proc)
+{
+ int i, *place;
+ char *realbuf;
+
+ i = proc->ParamCount;
+ do
+ {
+ // Retreive pointer to place
+ if (proc->Params[i].Option == -1) place = (int*) proc->Params[i].Value;
+ else place = (int*) &(proc->Params[i].Value);
+
+ realbuf = AllocString();
+
+ // Step 1: retrive value
+ switch (proc->Params[i].Type)
+ {
+ case PAT_VOID:
+ lstrcpy(realbuf,"");
+ break;
+ case PAT_INT:
+ wsprintf(realbuf, "%d", *((int*) place));
+ break;
+ case PAT_LONG:
+ myitoa64(*((__int64*) place), realbuf);
+ break;
+ case PAT_STRING:
+ lstrcpy(realbuf,*((char**) place));
+ break;
+ case PAT_BOOLEAN:
+ lstrcpy(realbuf,(*((int*) place))?("true"):("false"));
+ break;
+ case PAT_CALLBACK:
+ wsprintf(realbuf, "%d", proc->Params[i].Value);
+ break;
+ }
+
+ // Step 2: place it
+ if (proc->Params[i].Output == IOT_NONE);
+ else if (proc->Params[i].Output == IOT_STACK) pushstring(realbuf);
+ else if (proc->Params[i].Output > 0) setuservariable(proc->Params[i].Output - 1, realbuf);
+
+ GlobalFree(realbuf);
+
+ i--;
+ }
+ while (i >= 0);
+}
+
+SystemProc __declspec(naked) *CallProc(SystemProc *proc)
+{
+ int z3;
+
+ _asm
+ {
+ // Save stack
+ push ebp
+ mov ebp, esp
+ // Stack space for local variables
+ sub esp, __LOCAL_SIZE
+ // Save all usable registers to free our hands
+ push ebx
+ push edi
+ push esi
+ }
+
+ if ((CallbackIndex > 0) && ((proc->Options & POPT_GENSTACK) == 0))
+ {
+ if (LastStackPlace == 0)
+ {
+ // Create new stack
+ LastStackPlace = (int) GlobalAlloc(GPTR, NEW_STACK_SIZE);
+ // Point to stack end
+ LastStackPlace += NEW_STACK_SIZE;
+ }
+
+ _asm
+ {
+ // Save previous stack location
+ push ebp
+ mov LastStackReal, esp
+ // Move stack pointer
+ mov esp, LastStackPlace
+ }
+ }
+
+ // Push arguments to stack
+ for (z1 = proc->ParamCount; z1 > 0; z1--)
+ {
+ // Long types
+ if (proc->Params[z1].Size == 2)
+ {
+ z2 = proc->Params[z1]._value;
+ _asm push z2;
+ }
+ // Default
+ z2 = proc->Params[z1].Value;
+ _asm push z2;
+ }
+
+ // Call the proc and save return
+ z1 = (int) proc->Proc;
+
+ // Save proc
+ proc->Clone = LastProc;
+ LastProc = proc;
+
+ _asm
+ {
+ // Call
+ call z1
+ // Return
+ mov z1, eax
+ mov z2, edx
+ }
+
+ if ((CallbackIndex > 0) && ((LastProc->Options & POPT_GENSTACK) == 0))
+ {
+ _asm
+ {
+ // Restore real stack location
+ mov LastStackPlace, esp
+ mov esp, LastStackReal
+ pop ebp
+ }
+ }
+
+ // Restore proc
+ proc = LastProc;
+ LastProc = proc->Clone;
+
+ // In case of cdecl convention we should clear stack
+ if ((proc->Options & POPT_CDECL) != 0)
+ {
+ if ((CallbackIndex > 0) && ((LastProc->Options & POPT_GENSTACK) == 0))
+ {
+ // In case of temporary stack
+ for (z3 = 1; z3 <= proc->ParamCount; z3++)
+ LastStackPlace += 4*proc->Params[z3].Size;
+ } else
+ {
+ // in case of real stack
+ for (z3 = 1; z3 <= proc->ParamCount; z3++)
+ {
+ if (proc->Params[z3].Size == 2)
+ _asm pop edx;
+ _asm pop edx;
+ }
+ }
+ }
+
+ // Save return
+ proc->Params[0].Value = z1;
+ if (proc->Params[0].Size == 2)
+ proc->Params[0]._value = z2;
+ // Proc result: OK
+ proc->ProcResult = PR_OK;
+
+ _asm
+ {
+ // Return
+ mov eax, proc
+ // Restore registers
+ pop esi
+ pop edi
+ pop ebx
+ // Restore stack pointer
+ mov esp, ebp
+ pop ebp
+ // Return
+ ret
+ }
+}
+
+SystemProc __declspec(naked) *RealCallBack()
+{
+ SystemProc *proc;
+
+ _asm
+ {
+ // Save stack
+ push ebp
+ mov ebp, esp
+ // Stack space for local variables
+ sub esp, __LOCAL_SIZE
+ // Save all usable registers to free our hands
+ push ebx
+ push edi
+ push esi
+
+ // Arguments pointer
+ mov z2, esp // 1-st arg - 4*4 (pushes) - 4 (return) - __LOCAL_SIZE
+ add z2, __LOCAL_SIZE
+ add z2, 5*4
+ // Our callback proc
+ mov proc, eax
+ }
+
+ // Find last unused clone
+ while ((proc->ProcResult != PR_OK) && (proc->Clone != NULL)) proc = proc->Clone;
+ // Unused?
+ if (proc->ProcResult != PR_OK)
+ {
+ // Callback already used, create new
+ // 2. Create new clone
+ proc = (proc->Clone = GlobalCopy(proc));
+ // 3. Set clone option
+ proc->Options |= POPT_CLONE;
+ }
+
+ // Read arguments
+ proc->ArgsSize = 0;
+ for (z1 = 1; z1 <= proc->ParamCount; z1++)
+ {
+ // Default
+ proc->Params[z1].Value = *(((int*)z2)++);
+ proc->ArgsSize += 4;
+ // Long only
+ if (proc->Params[z1].Size == 2)
+ {
+ proc->Params[z1]._value = *(((int*)z2)++);
+ proc->ArgsSize += 4;
+ }
+ }
+ proc->ProcResult = PR_CALLBACK;
+
+ _asm
+ {
+ // Return
+ mov eax, proc
+
+ // Save temporary stack info
+ push ebp
+// push LastStackPlace
+ mov LastStackPlace, esp
+ // Restore real stack
+ mov esp, LastStackReal
+ pop ebp
+// pop LastStackReal
+
+ // Fake return from System::Call
+
+ // Restore registers
+ pop esi
+ pop edi
+ pop ebx
+ // Restore stack pointer
+ mov esp, ebp
+ pop ebp
+ // Return
+ ret
+ }
+}
+
+
+SystemProc __declspec(naked) *CallBack(SystemProc *proc)
+{
+ _asm
+ {
+ // Save stack
+ push ebp
+ mov ebp, esp
+ // Stack space for local variables
+ sub esp, __LOCAL_SIZE
+ // Save all usable registers to free our hands
+ push ebx
+ push edi
+ push esi
+ }
+
+ z1 = proc->Params[0].Value;
+ z2 = proc->Params[0]._value;
+
+ // Adjust return statement
+ if ((proc->Options & POPT_CDECL) == 0) retexpr[1] = proc->ArgsSize;
+ else retexpr[1] = 0x0;
+
+ // Right return statement address
+ retaddr = (HANDLE) retexpr;
+
+ _asm
+ {
+ // Prepare return
+ mov eax, z1
+ mov edx, z2
+
+ // Restore temporary stack and return
+
+ // Save real stack info
+ // Save previous stack location
+// push LastStackReal
+ push ebp
+ mov LastStackReal, esp
+ // Move stack pointer
+ mov esp, LastStackPlace
+// pop LastStackPlace
+ pop ebp
+
+ // Fake return from Callback
+
+ // Restore registers
+ pop esi
+ pop edi
+ pop ebx
+ // Restore stack pointer
+ mov esp, ebp
+ pop ebp
+ // Return
+ jmp retaddr
+ }
+}
+
+HANDLE CreateCallback(SystemProc *cbproc)
+{
+ char *mem;
+
+ if (cbproc->Proc == NULL)
+ {
+ // Set callback index
+ cbproc->CallbackIndex = ++(CallbackIndex);
+ cbproc->Options |= POPT_PERMANENT;
+
+ mem = (char *) (cbproc->Proc = GlobalAlloc(GPTR, 10));
+ *(mem++) = 0xB8; // Mov eax, const
+ *(((int *)mem)++) = (int) cbproc;
+ *(mem++) = 0xe9; // Jmp relative
+ *((int *)mem) = (int) RealCallBack;
+ *((int *)mem) -= ((int) mem) + 4;
+ }
+
+ // Return proc address
+ return cbproc->Proc;
+}
+
+void CallStruct(SystemProc *proc)
+{
+ int i, size = 0;
+ char *st, *ptr;
+
+ // Struct exists?
+ if (proc->Proc == NULL)
+ {
+ // No. Calculate the size and create
+ for (i = 1; i <= proc->ParamCount; i++)
+ if (proc->Params[i].Option < 1)
+ size += proc->Params[i].Size * 4;
+ else
+ size += proc->Params[i].Option;
+
+ // Allocate struct memory
+ proc->Proc = (HANDLE) GlobalAlloc(GPTR, size);
+ }
+
+ // Pointer to current data
+ st = (char*) proc->Proc;
+
+ for (i = 1; i <= proc->ParamCount; i++)
+ {
+ // Normal or special block?
+ if (proc->Params[i].Option < 1)
+ {
+ // Normal
+ size = proc->Params[i].Size*4;
+ ptr = (char*) &(proc->Params[i].Value);
+ }
+ else
+ {
+ // Special
+ size = proc->Params[i].Option;
+ switch (proc->Params[i].Type)
+ {
+ case PAT_VOID: ptr = NULL; break;
+ case PAT_INT: ptr = (char*) &(proc->Params[i].Value); break;
+ case PAT_STRING: ptr = (char*) proc->Params[i].Value; break;
+ }
+ }
+
+ // Process them!
+ if (ptr != NULL)
+ {
+ // Input
+ if (proc->Params[i].Input != IOT_NONE)
+ copymem(st, ptr, size);
+
+ // Output
+ if (proc->Params[i].Output != IOT_NONE)
+ copymem(ptr, st, size);
+ }
+
+ // Skip to next data block
+ st += size;
+ }
+
+ // Proc virtual return - pointer to memory struct
+ proc->Params[0].Value = (int) proc->Proc;
+}
+
+
+/*__int64 __declspec(dllexport) just(__int64 a, __int64 b, __int64 *c)
+{
+ *c += a*b + 8402934020348;
+ return a*b+(*c);
+}*/
+
+/*typedef int (__stdcall *func)(int a, int b);
+
+int __declspec(dllexport) cbtest(func f)
+{
+ return f(5, 10);
+}*/
+
BOOL WINAPI _DllMainCRTStartup(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)
{
g_hInstance=hInst;
diff --git a/Contrib/System/System.h b/Contrib/System/System.h
index 55db95be..7d3c6634 100644
--- a/Contrib/System/System.h
+++ b/Contrib/System/System.h
@@ -12,39 +12,83 @@
#define SYSTEM_API __declspec(dllimport)
#endif
-// Real world types
-#define PT_VOID 0
-#define PT_INT 1
-#define PT_LONG 2
-#define PT_STRING 3
-#define PT_BOOLEAN 4
+#define NEW_STACK_SIZE 65536
+
+// Proc types:
+#define PT_NOTHING 0
+#define PT_PROC 1
+#define PT_STRUCT 2
+
+// Proc results:
+#define PR_OK 0
+#define PR_ERROR -1
+#define PR_CALLBACK 1
+
+// Real world argument types
+#define PAT_VOID 0
+#define PAT_INT 1
+#define PAT_LONG 2
+#define PAT_STRING 3
+#define PAT_BOOLEAN 4
+#define PAT_CALLBACK 5
// Input/Output Source/Destination
#define IOT_NONE 0
#define IOT_STACK -1
#define IOT_REG 1
+// #define INLINE_INPUT -> any other value, will contain pointer to input string
+
+// Options
+#define POPT_CDECL 0x1 // (Option & 0x1) == 0x1 -> cdecl, otherwise stdcall
+#define POPT_PERMANENT 0x2 // Permanent proc, will not be destroyed after calling
+#define POPT_ALWRETURN 0x4 // Always return
+#define POPT_NEVERREDEF 0x8 // Never redefine
+#define POPT_GENSTACK 0x10 // Use general stack (non temporary for callback)
+#define POPT_CLONE 0x20 // This is clone callback
// Our single proc parameter
typedef struct
{
int Type;
- BOOL IsPointer;
- int Value; // it can hold any value
+ int Option; // -1 -> Pointer, 1-... -> Special
+ int Value; // it can hold any 4 byte value
+ int _value; // value buffer for structures > 4 bytes (I hope 8 bytes will be enough)
+ int Size; // Value real size (should be either 1 or 2 (the number of pushes))
int Input;
int Output;
} ProcParameter;
-// Our single proc
-typedef struct
+// Our single proc (Since the user will free proc with GlobalFree,
+// I've declared all variables as statics)
+typedef struct tag_SystemProc SystemProc;
+typedef struct tag_SystemProc
{
- HANDLE dll;
- HANDLE proc;
+ int ProcType;
+ int ProcResult;
+ char DllName[1024];
+ char ProcName[1024];
+ HANDLE Dll;
+ HANDLE Proc;
+ int Options;
int ParamCount;
- ProcParameter Params[20]; // I hope nobody will use more than 20 params
+ ProcParameter Params[100]; // I hope nobody will use more than 100 params
+
+ // Callback specific
+ int CallbackIndex;
+ int ArgsSize;
+ // Clone of current element (used for multi-level callbacks)
+ SystemProc *Clone;
} SystemProc;
-extern SystemProc *ParseProc(char *ProcID);
-extern BOOL ParseParam(SystemProc *proc, char *ParamID);
-extern void ParamsInput(SystemProc *proc);
-extern void ParamsOutput(SystemProc *proc);
-extern void SystemCall(SystemProc *proc);
+extern int ParamSizeByType[]; // Size of every parameter type (*4 bytes)
+
+extern HANDLE CreateCallback(SystemProc *cbproc);
+extern SystemProc *PrepareProc();
+extern void ParamAllocate(SystemProc *proc);
+extern void ParamsDeAllocate(SystemProc *proc);
+extern void ParamsIn(SystemProc *proc);
+extern void ParamsOut(SystemProc *proc);
+extern SystemProc *CallProc(SystemProc *proc);
+extern SystemProc *CallBack(SystemProc *proc);
+extern SystemProc *RealCallBack();
+extern void CallStruct(SystemProc *proc);
diff --git a/Contrib/System/System.ncb b/Contrib/System/System.ncb
deleted file mode 100644
index 9057ebac..00000000
--- a/Contrib/System/System.ncb
+++ /dev/null
@@ -1 +0,0 @@
-Microsoft C/C++ MSF 7.00
diff --git a/Contrib/System/System.nsh b/Contrib/System/System.nsh
new file mode 100644
index 00000000..b4eae5b0
--- /dev/null
+++ b/Contrib/System/System.nsh
@@ -0,0 +1,353 @@
+; Some useful functions, structures, constants
+;
+; (c) brainsucker, 2002
+; (r) BSForce
+
+; Check for double includes
+!ifndef System.NSH.Included
+
+!define System.NSH.Included
+
+; ------------- Functions --------------
+
+; LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+!define sysWNDPROC "(i.s, i.s, i.s, i.s) iss"
+
+; LRESULT DefWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
+!define sysDefWindowProc "user32::DefWindowProcA(i, i, i, i) i"
+
+!define sysMessageBox "user32::MessageBoxA(i, t, t, i) i"
+
+; int wsprintf(LPTSTR lpOut, LPCTSTR lpFmt, ...);
+!define syswsprintf "user32::wsprintfA(t, t) i ? c"
+
+; HMODULE GetModuleHandle(LPCTSTR lpModuleName);
+!define sysGetModuleHandle "kernel32::GetModuleHandleA(t) i"
+
+; HCURSOR LoadCursor(HINSTANCE hInstance, LPCTSTR lpCursorName);
+!define sysLoadCursor "user32::LoadCursorA(i, t) i"
+
+; ATOM RegisterClass(CONST WNDCLASS *lpWndClass);
+!define sysRegisterClass "user32::RegisterClassA(i) i"
+
+; HANDLE LoadImage(HINSTANCE hinst, LPCTSTR lpszName, UINT uType,
+; int cxDesired, int cyDesired, UINT fuLoad);
+!define sysLoadImage "user32::LoadImageA(i, t, i, i, i, i) i"
+
+; BOOL PlaySound(LPCSTR pszSound, HMODULE hmod, DWORD fdwSound);
+!define sysPlaySound "winmm.dll::PlaySoundA(t, i, i) i"
+
+; HWND CreateWindowEx(DWORD dwExStyle, LPCTSTR lpClassName, LPCTSTR lpWindowName,
+; DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hWndParent,
+; HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam);
+!define sysCreateWindowEx "user32::CreateWindowExA(i, t, t, i, i, i, i, i, i, i, i, i) i"
+
+; BOOL IsWindow(HWND hWnd);
+!define sysIsWindow "user32::IsWindow(i) i"
+
+; LONG SetWindowLong(HWND hWnd, int nIndex, LONG dwNewLong);
+!define sysSetWindowLong "user32::SetWindowLongA(i, i, i) i"
+
+; BOOL SetWindowPos(HWND hWnd, HWND hWndInsertAfter, int X, int Y, int cx, int cy, UINT uFlags);
+!define sysSetWindowPos "user32::SetWindowPos(i, i, i, i, i, i, i) i"
+
+; BOOL ShowWindow(HWND hWnd, int nCmdShow);
+!define sysShowWindow "user32::ShowWindow(i, i) i"
+
+; BOOL DestroyWindow(HWND hWnd);
+!define sysDestroyWindow "user32::DestroyWindow(i) i"
+
+; BOOL GetClientRect(HWND hWnd, LPRECT lpRect);
+!define sysGetClientRect "user32::GetClientRect(i, i) i"
+
+; BOOL GetMessage(LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax);
+!define sysGetMessage "user32::GetMessageA(i, i, i, i) i"
+
+; LRESULT DispatchMessage(CONST MSG *lpmsg);
+!define sysDispatchMessage "user32::DispatchMessageA(i) i"
+
+; BOOL DeleteObject(HGDIOBJ hObject);
+!define sysDeleteObject "gdi32::DeleteObject(i) i"
+
+; int GetObject(HGDIOBJ hgdiobj, int cbBuffer, LPVOID lpvObject);
+!define sysGetObject "gdi32::GetObjectA(i, i, i) i"
+
+; HGDIOBJ SelectObject(HDC hdc, HGDIOBJ hgdiobj);
+!define sysSelectObject "gdi32::SelectObject(i, i) i"
+
+; HDC CreateCompatibleDC(HDC hdc);
+!define sysCreateCompatibleDC "gdi32::CreateCompatibleDC(i) i"
+
+; BOOL DeleteDC(HDC hdc);
+!define sysDeleteDC "gdi32::DeleteDC(i) i"
+
+; BOOL BitBlt(HDC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight,
+; HDC hdcSrc, int nXSrc, int nYSrc, DWORD dwRop);
+!define sysBitBlt "gdi32::BitBlt(i, i, i, i, i, i, i, i, i) i"
+
+; HDC BeginPaint(HWND hwnd, LPPAINTSTRUCT lpPaint);
+!define sysBeginPaint "user32::BeginPaint(i, i) i"
+
+; BOOL EndPaint(HWND hWnd, CONST PAINTSTRUCT *lpPaint);
+!define sysEndPaint "user32::EndPaint(i, i) i"
+
+; BOOL SystemParametersInfo(UINT uiAction, UINT uiParam, PVOID pvParam, UINT fWinIni);
+!define sysSystemParametersInfo "user32::SystemParametersInfoA(i, i, i, i) i"
+
+; UINT_PTR SetTimer(HWND hWnd, UINT_PTR nIDEvent, UINT uElapse, TIMERPROC lpTimerFunc);
+!define sysSetTimer "user32::SetTimer(i, i, i, k) i"
+
+
+; ------------- Structures --------------
+
+; typedef struct _WNDCLASS {
+; UINT style;
+; WNDPROC lpfnWndProc;
+; int cbClsExtra;
+; int cbWndExtra;
+; HINSTANCE hInstance;
+; HICON hIcon;
+; HCURSOR hCursor;
+; HBRUSH hbrBackground;
+; LPCTSTR lpszMenuName;
+; LPCTSTR lpszClassName;
+; } WNDCLASS, *PWNDCLASS;
+!define sysWNDCLASS "(i, k, i, i, i, i, i, i, t, t) i"
+
+; typedef struct tagMSG {
+; HWND hwnd;
+; UINT message;
+; WPARAM wParam;
+; LPARAM lParam;
+; DWORD time;
+; POINT pt; -> will be presented as two separate px and py
+; } MSG, *PMSG;
+!define sysMSG "(i, i, i, i, i, i, i) i"
+
+; typedef struct tagBITMAP {
+; LONG bmType;
+; LONG bmWidth;
+; LONG bmHeight;
+; LONG bmWidthBytes;
+; WORD bmPlanes;
+; WORD bmBitsPixel;
+; LPVOID bmBits;
+; } BITMAP, *PBITMAP;
+!define sysBITMAP "(i, i, i, i, i, i, i) i"
+!define sysBITMAP_SIZE 28
+
+; typedef struct _RECT {
+; LONG left;
+; LONG top;
+; LONG right;
+; LONG bottom;
+; } RECT, *PRECT;
+!define sysRECT "(i, i, i, i) i"
+
+; typedef struct tagPAINTSTRUCT {
+; HDC hdc;
+; BOOL fErase;
+; RECT rcPaint; (rcl, rct, rcr, rcb)
+; BOOL fRestore;
+; BOOL fIncUpdate;
+; BYTE rgbReserved[32];
+; } PAINTSTRUCT, *PPAINTSTRUCT;
+!define sysPAINTSTRUCT "(i, i, i, i, i, i, i, i, &v32) i"
+
+; ------------- Constants --------------
+
+; == Cursors ==
+
+!define IDC_ARROW 32512
+!define IDC_IBEAM 32513
+!define IDC_WAIT 32514
+!define IDC_CROSS 32515
+!define IDC_UPARROW 32516
+!define IDC_SIZE 32640
+!define IDC_ICON 32641
+!define IDC_SIZENWSE 32642
+!define IDC_SIZENESW 32643
+!define IDC_SIZEWE 32644
+!define IDC_SIZENS 32645
+!define IDC_SIZEALL 32646
+!define IDC_NO 32648
+!define IDC_HAND 32649
+!define IDC_APPSTARTING 32650
+!define IDC_HELP 32651
+
+; == Images ==
+
+!define IMAGE_BITMAP 0
+!define IMAGE_ICON 1
+!define IMAGE_CURSOR 2
+!define IMAGE_ENHMETAFILE 3
+
+!define LR_DEFAULTCOLOR 0x0000
+!define LR_MONOCHROME 0x0001
+!define LR_COLOR 0x0002
+!define LR_COPYRETURNORG 0x0004
+!define LR_COPYDELETEORG 0x0008
+!define LR_LOADFROMFILE 0x0010
+!define LR_LOADTRANSPARENT 0x0020
+!define LR_DEFAULTSIZE 0x0040
+!define LR_VGACOLOR 0x0080
+!define LR_LOADMAP3DCOLORS 0x1000
+!define LR_CREATEDIBSECTION 0x2000
+!define LR_COPYFROMRESOURCE 0x4000
+!define LR_SHARED 0x8000
+
+; == Sounds ==
+
+!define SND_SYNC 0x0000
+!define SND_ASYNC 0x0001
+!define SND_NODEFAULT 0x0002
+!define SND_MEMORY 0x0004
+!define SND_LOOP 0x0008
+!define SND_NOSTOP 0x0010
+
+!define SND_NOWAIT 0x00002000
+!define SND_ALIAS 0x00010000
+!define SND_ALIAS_ID 0x00110000
+!define SND_FILENAME 0x00020000
+!define SND_RESOURCE 0x00040004
+!define SND_PURGE 0x0040
+!define SND_APPLICATION 0x0080
+
+; == Windows ==
+
+!define WS_OVERLAPPED 0x00000000
+!define WS_POPUP 0x80000000
+!define WS_CHILD 0x40000000
+!define WS_MINIMIZE 0x20000000
+!define WS_VISIBLE 0x10000000
+!define WS_DISABLED 0x08000000
+!define WS_CLIPSIBLINGS 0x04000000
+!define WS_CLIPCHILDREN 0x02000000
+!define WS_MAXIMIZE 0x01000000
+!define WS_CAPTION 0x00C00000
+!define WS_BORDER 0x00800000
+!define WS_DLGFRAME 0x00400000
+!define WS_VSCROLL 0x00200000
+!define WS_HSCROLL 0x00100000
+!define WS_SYSMENU 0x00080000
+!define WS_THICKFRAME 0x00040000
+!define WS_GROUP 0x00020000
+!define WS_TABSTOP 0x00010000
+!define WS_MINIMIZEBOX 0x00020000
+!define WS_MAXIMIZEBOX 0x00010000
+!define WS_TILED ${WS_OVERLAPPED}
+!define WS_ICONIC ${WS_MINIMIZE}
+!define WS_SIZEBOX ${WS_THICKFRAME}
+!define WS_OVERLAPPEDWINDOW 0x00CF0000
+!define WS_TILEDWINDOW ${WS_OVERLAPPEDWINDOW}
+!define WS_POPUPWINDOW 0x80880000
+!define WS_CHILDWINDOW ${WS_CHILD}
+!define WS_EX_DLGMODALFRAME 0x00000001
+!define WS_EX_NOPARENTNOTIFY 0x00000004
+!define WS_EX_TOPMOST 0x00000008
+!define WS_EX_ACCEPTFILES 0x00000010
+!define WS_EX_TRANSPARENT 0x00000020
+!define WS_EX_MDICHILD 0x00000040
+!define WS_EX_TOOLWINDOW 0x00000080
+!define WS_EX_WINDOWEDGE 0x00000100
+!define WS_EX_CLIENTEDGE 0x00000200
+!define WS_EX_CONTEXTHELP 0x00000400
+!define WS_EX_RIGHT 0x00001000
+!define WS_EX_LEFT 0x00000000
+!define WS_EX_RTLREADING 0x00002000
+!define WS_EX_LTRREADING 0x00000000
+!define WS_EX_LEFTSCROLLBAR 0x00004000
+!define WS_EX_RIGHTSCROLLBAR 0x00000000
+!define WS_EX_CONTROLPARENT 0x00010000
+!define WS_EX_STATICEDGE 0x00020000
+!define WS_EX_APPWINDOW 0x00040000
+!define WS_EX_OVERLAPPEDWINDOW 0x00000300
+!define WS_EX_PALETTEWINDOW 0x00000188
+!define WS_EX_LAYERED 0x00080000
+!define WS_EX_NOINHERITLAYOUT 0x00100000
+!define WS_EX_LAYOUTRTL 0x00400000
+!define WS_EX_COMPOSITED 0x02000000
+!define WS_EX_NOACTIVATE 0x08000000
+
+
+; == System Parameters Info ==
+
+!define SPI_GETWORKAREA 0x0030
+
+; == Window Long Offsets ==
+
+!define GWL_WNDPROC -4
+!define GWL_HINSTANCE -6
+!define GWL_HWNDPARENT -8
+!define GWL_STYLE -16
+!define GWL_EXSTYLE -20
+!define GWL_USERDATA -21
+!define GWL_ID -12
+
+; == Show Window ==
+
+!define SW_HIDE 0
+!define SW_SHOWNORMAL 1
+!define SW_NORMAL 1
+!define SW_SHOWMINIMIZED 2
+!define SW_SHOWMAXIMIZED 3
+!define SW_MAXIMIZE 3
+!define SW_SHOWNOACTIVATE 4
+!define SW_SHOW 5
+!define SW_MINIMIZE 6
+!define SW_SHOWMINNOACTIVE 7
+!define SW_SHOWNA 8
+!define SW_RESTORE 9
+!define SW_SHOWDEFAULT 10
+!define SW_FORCEMINIMIZE 11
+!define SW_MAX 11
+
+; == Window swap ==
+
+!define SWP_NOSIZE 0x0001
+!define SWP_NOMOVE 0x0002
+!define SWP_NOZORDER 0x0004
+!define SWP_NOREDRAW 0x0008
+!define SWP_NOACTIVATE 0x0010
+!define SWP_FRAMECHANGED 0x0020
+!define SWP_SHOWWINDOW 0x0040
+!define SWP_HIDEWINDOW 0x0080
+!define SWP_NOCOPYBITS 0x0100
+!define SWP_NOOWNERZORDER 0x0200
+!define SWP_NOSENDCHANGING 0x0400
+
+!define SWP_DRAWFRAME ${SWP_FRAMECHANGED}
+!define SWP_NOREPOSITION ${SWP_NOOWNERZORDER}
+!define SWP_DEFERERASE 0x2000
+!define SWP_ASYNCWINDOWPOS 0x4000
+
+; == Bit Copy ==
+
+!define SRCCOPY 0x00CC0020
+!define SRCPAINT 0x00EE0086
+!define SRCAND 0x008800C6
+!define SRCINVERT 0x00660046
+!define SRCERASE 0x00440328
+!define NOTSRCCOPY 0x00330008
+!define NOTSRCERASE 0x001100A6
+!define MERGECOPY 0x00C000CA
+!define MERGEPAINT 0x00BB0226
+!define PATCOPY 0x00F00021
+!define PATPAINT 0x00FB0A09
+!define PATINVERT 0x005A0049
+!define DSTINVERT 0x00550009
+!define BLACKNESS 0x00000042
+!define WHITENESS 0x00FF0062
+
+; == Callbacks ==
+
+!macro SINGLE_CALLBACK CHKN RES INDEX FUNC
+CheckCB_${CHKN}:
+ Pop ${RES}
+ StrCmp ${RES} "callback${INDEX}" 0 ExitCB_${CHKN}
+ Call ${FUNC}
+ Goto CheckCB_${CHKN}
+ExitCB_${CHKN}:
+!macroend
+
+!endif
\ No newline at end of file
diff --git a/Contrib/System/System.txt b/Contrib/System/System.txt
deleted file mode 100644
index f6e7d037..00000000
--- a/Contrib/System/System.txt
+++ /dev/null
@@ -1,163 +0,0 @@
- System: NSIS Plugin
-
-* - I'm a lazy bitch, for *(N) - see comment N at the end of the file.
-
-I. Introduction.
-----------------
-
- That plugin will make you virtually unstopable. Now you could call any
-DLL procedure or function, i.e. you gain full control over the system.
-
- If you want to call some proc, you should prepare two proc IDs: the
-ProcId and ParamID. Since the System plugin couldn't know the dll proc
-parameters and return type, you should find the proc description somewhere (the
-best will be .h files, for example from Platform SDK in case of system dlls).
-After that you should specify the ProcID: it contains the DLL and proc name,
-proc parameters, and proc calling options.
- Since the parameters format of proc in DLL never changes (in general),
-that ProcID can be defined ones for all times (in include file for example, and
-I'm thinking about automatic conversion of some windows headers (winbase.h,
-winuser.h ...) to ProcID defines).
-
- When you want to call the proc, you should prepare the second id,
-ParamID. It specifies where the System plugin should find your input values
-(registers, stack, etc) and where it should place proc output values. You can
-define this id once for installation, or you can use separate declaration at
-each call.
-
-II. ProcID.
------------
-
- Ok. Let's learn how to convert function declaration to ProcID. Below
-the ProcID format is specified (You can read here *(1) why I'm using '?' as
-delimeter):
-
-"dll?proc?params?options", where:
-
- - dll - the path (or name) of DLL containing proc (for ex: "kernel32",
-"c:\test\super.dll", etc.).
- - proc - the proc name itself (warning: the proc name must be specified
-in the way it mentioned at dll, for example it may look like "_MyFunction@16".
-Other examples: "GetDiskFreeSpaceExA", "GetProcAddress", etc.).
- - params - the proc parameters, described below.
- - options - the proc options *(2) (for those, who don't want to read my
-comments - Currently Unavailable). At least two will be defined later: 'c' & 's'
--> CDECL and STDCALL calling conventions. Should be completly (including
-question mark) ommited now.
-
- Ok, each proc parameter (and return) is presented by single chararacter
-(there is only one exception - p character), these character are:
-
- v - void (generaly for return)
- i - int (includes char, byte, short, handles, pointers and so on)
- l - long & large integer (know as int64)
- s - string (LPCSTR, pointer to first character)
- b - boolean (needs/returns 'true':'false') - by the fact this type is
- senseless -> usual integer can be used ('0':'1')
-
- p - pointer specifier -> the proc needs the pointer to type, affects
- next char (parameter) [ex: 'pi' - pointer to int]
-
- Huh, I think that is easily understandable, but there is one IMPORTANT
-HINT: the first parameter is RETURN type!
- And at last: the pointers. You should remember that if you specify
-pointer parameter with 'p' specifier, the System Plugin waits from you and will
-return to you BASE TYPE, i.e. for 'pi' it will wait for and return to you
-INTEGER.
- As I wrote above the options (including calling conventions are
-unsupported now), the System Plugin will always call DLL function with STDCALL
-(this convention is default for windows procs, for example for procs specified
-with WINAPI. CDECL is usually used with WINAPIV declared procs. This V char
-stands for variable, or arguments-list -> with CDECL convention the stack after
-the function call is cleared by caller, and with STDCALL it is cleared by called
-proc ('calee') -> all procs with arguments-lists (such as wsprintf) must use
-CDECL).
-
-IIa. ProcID examples.
----------------------
-
- Let's transform some real procs defenitions to ProcIDs:
-
-1) WINBASEAPI FARPROC WINAPI GetProcAddress(IN HMODULE hModule,
- IN LPCSTR lpProcName);
- For the start: proc defined with WINAPI - stdcall and thats allright.
-Proc return type FARPROC is just another name for proc handle (or address), so
-we could use integer type. This proc defined at kernel32.dll, but '.dll' could
-be ommited. So...
-
-"kernel32?GetProcAddress?iis"
-
- Params: i - return, i - hModule, s - lpProcName.
- Simple, huh?
-
-2) WINBASEAPI BOOL WINAPI GetDiskFreeSpaceExA( IN LPCSTR lpDirectoryName,
- OUT PULARGE_INTEGER lpFreeBytesAvailableToCaller,
- OUT PULARGE_INTEGER lpTotalNumberOfBytes,
- OUT PULARGE_INTEGER lpTotalNumberOfFreeBytes
- );
-
- At first, If you'll look at MSDN, you will find GetDiskFreeSpaceEx
-function, but not with trailing 'A'. This is default Microsoft behaviour for
-functions, which have two variants: for ANSI (trailing 'A') and UNICODE
-(trailing 'W') respectively. You can meet such functions sometimes, and since
-neither NSIS or System Plugin support unicode you should always use version with
-trailing 'A'. PULARGE_INTEGER can be represented as (int64*) [pointer to long],
-so we will code this ProcID as:
-
-"kernel32.dll?GetDiskFreeSpaceExA?bsplplpl"
-
- Params: b - return (boolean); pl, pl, pl - three pointer to long.
-
- See other examples at System.nsh.
-
-III. ParamID.
--------------
-
- Ok, here is ParamID format:
-
-"input?output"
-
-Input/Output -> describes places (from where to take and where to put), encoded
-by single character too. The first character of output describes the place for
-function return.
-
-Input sources / Output destinations:
- Registers $0-$9 -> 0..9
- Registers $R0-$R9 -> a(0) b(1) c(2) d(3) e(4) f(5) g(6) h(7) i(8) j(9)
- Additional regs -> k(CmdLine) l(InstDir) m(OutDir) n(ExeDir) o(Lang)
- Stack -> s (parameters are poped/pushed in default, right-to-left order)
- None -> n (0 (null) for input / specifies no output is required)
-
-VI. Functions.
---------------
-
-Default return - on stack.
-
-handle = Alloc(bytes)
-ok? = Free(handle)
-handle = AllocCopy(handle) -> creates a copy
-
-----------
-
-addr = FullAddr(ProcID, ParamID) -> retrieve address for use with Call
-Call = FullCall(ProcID, ParamID) -> Direct call
-
-addr = PartAddr(ProcID)
-Call = Call(addr)
-
-----------
-
-Hint: These two change the passed proc, so if you want to preserve original
-proc use AllocCopy...
-
-addr = ShortAddr(addr, ParamID) -> For use if you half defined the proc
-Call = ShortCall(addr, ParamID) -> by PartAddr
-
-----------
-
-Comments (don't forget the * meaning :):
- 1. I'm using '?' as delimiter just because I need some character to use
-as :). The other reason: '?' can't be spotted at dll paths and proc names.
- 2. Currently unsupported. Some features, like buffers/structures,
-callbacks, different calling conventions, arg-lists, etc should become available
-at future releases.
\ No newline at end of file
diff --git a/Contrib/System/System.vcproj b/Contrib/System/System.vcproj
index 37af6d34..2ce19646 100644
--- a/Contrib/System/System.vcproj
+++ b/Contrib/System/System.vcproj
@@ -64,8 +64,10 @@
CharacterSet="2">
+
+
+
diff --git a/Contrib/System/WhatsNew.txt b/Contrib/System/WhatsNew.txt
new file mode 100644
index 00000000..cd6cf00d
--- /dev/null
+++ b/Contrib/System/WhatsNew.txt
@@ -0,0 +1,6 @@
+1. Syntax, with inline input
+2. Int64 full support (conversion/operations/comparison)
+3. Structures support
+4. Callbacks support, including multilevel callbacks
+5. Some useful rountines (Alloc, Free, Copy)
+6. CDecl and StdCall calling conventions
diff --git a/Contrib/System/vc7ldvrm.obj b/Contrib/System/vc7ldvrm.obj
new file mode 100644
index 00000000..23650a15
Binary files /dev/null and b/Contrib/System/vc7ldvrm.obj differ
diff --git a/Contrib/System/vc7lmul.obj b/Contrib/System/vc7lmul.obj
new file mode 100644
index 00000000..ef7005c8
Binary files /dev/null and b/Contrib/System/vc7lmul.obj differ
diff --git a/Contrib/System/vc7lshl.obj b/Contrib/System/vc7lshl.obj
new file mode 100644
index 00000000..d97bc26b
Binary files /dev/null and b/Contrib/System/vc7lshl.obj differ
diff --git a/Contrib/System/vc7lshr.obj b/Contrib/System/vc7lshr.obj
new file mode 100644
index 00000000..e2f2b1a8
Binary files /dev/null and b/Contrib/System/vc7lshr.obj differ
diff --git a/Plugins/System.dll b/Plugins/System.dll
index 230a9c35..ffc4c7ee 100644
Binary files a/Plugins/System.dll and b/Plugins/System.dll differ