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