System plugin
git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@1130 212acab6-be3b-0410-9dea-997c60f758d6
This commit is contained in:
parent
1fb8b94a22
commit
88956798f1
15 changed files with 1143 additions and 0 deletions
93
Contrib/System/Buffers.c
Normal file
93
Contrib/System/Buffers.c
Normal file
|
@ -0,0 +1,93 @@
|
|||
#include "stdafx.h"
|
||||
#include "Plugin.h"
|
||||
#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)
|
||||
int size;
|
||||
int mem;
|
||||
|
||||
if (popint(&size) == 0)
|
||||
{
|
||||
pushint(0);
|
||||
return;
|
||||
}
|
||||
|
||||
mem = (int) GlobalAlloc(GPTR, size);
|
||||
pushint(mem);
|
||||
PLUGINFUNCTIONEND
|
||||
|
||||
PLUGINFUNCTION(Free)
|
||||
int mem;
|
||||
|
||||
if ((popint(&mem) == 0) || (mem == 0))
|
||||
{
|
||||
pushstring("false");
|
||||
return;
|
||||
}
|
||||
if ((GlobalFree((HANDLE) mem) == NULL)) pushstring("true");
|
||||
else pushstring("false");
|
||||
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
|
||||
{
|
||||
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
|
||||
}
|
||||
|
||||
char buf[1024];
|
||||
wsprintf(buf,"$0=%s\n",getuservariable(INST_0));
|
||||
MessageBox(g_hwndParent,buf,0,MB_OK);
|
||||
PLUGINFUNCTIONEND*/
|
||||
|
||||
HANDLE GlobalCopy(HANDLE Old)
|
||||
{
|
||||
SIZE_T size;
|
||||
HANDLE n;
|
||||
|
||||
size = GlobalSize(Old);
|
||||
n = GlobalAlloc(GPTR, size);
|
||||
CopyMemory(n, Old, size);
|
||||
return n;
|
||||
}
|
3
Contrib/System/Buffers.h
Normal file
3
Contrib/System/Buffers.h
Normal file
|
@ -0,0 +1,3 @@
|
|||
#pragma once
|
||||
|
||||
extern HANDLE GlobalCopy(HANDLE Old);
|
23
Contrib/System/Last Comments.txt
Normal file
23
Contrib/System/Last Comments.txt
Normal file
|
@ -0,0 +1,23 @@
|
|||
I'm just finished and going to sleep, so a few words only.
|
||||
This is alpha release, just for testing. Report bugs please.
|
||||
|
||||
That version limits:
|
||||
|
||||
0. I've not noticed the NSIS team inverted the 'calling convention', arguments
|
||||
are passing to stack from left to right during d::p call, so you should invert
|
||||
system.txt arguments order. See SystemEx.nsi for examples.
|
||||
|
||||
1. PT_VOID and PT_BOOLEAN are unsupported.
|
||||
2. PT_LONG without Pointer specifier is not allowed.
|
||||
3. NSIS->Call PT_LONG converts as 32 bits. Back conversion bit-width is unknown.
|
||||
By the way NSIS doesn't support int64 operations, so you can process received
|
||||
long values as strings only...
|
||||
4. Generaly untested :)
|
||||
5. Requires MSVC++ 7.0 to compile :) Sorry....
|
||||
|
||||
Todo (will be done in a few days):
|
||||
1. Structures work (thru functions).
|
||||
2. Callbacks.
|
||||
3. Arg-lists
|
||||
4. Cdecl convention
|
||||
5. Optimizations and so on...
|
109
Contrib/System/Plugin.c
Normal file
109
Contrib/System/Plugin.c
Normal file
|
@ -0,0 +1,109 @@
|
|||
#include "stdafx.h"
|
||||
#include "Plugin.h"
|
||||
#include "System.h"
|
||||
|
||||
HWND g_hwndParent;
|
||||
int g_stringsize;
|
||||
stack_t **g_stacktop;
|
||||
char *g_variables;
|
||||
|
||||
int popstring(char *str)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
void pushstring(char *str)
|
||||
{
|
||||
stack_t *th;
|
||||
if (!g_stacktop) return;
|
||||
th=(stack_t*)GlobalAlloc(GPTR,sizeof(stack_t)+g_stringsize);
|
||||
lstrcpyn(th->text,str,g_stringsize);
|
||||
th->next=*g_stacktop;
|
||||
*g_stacktop=th;
|
||||
}
|
||||
|
||||
char *getuservariable(int varnum)
|
||||
{
|
||||
if (varnum < 0 || varnum >= __INST_LAST) return NULL;
|
||||
return g_variables+varnum*g_stringsize;
|
||||
}
|
||||
|
||||
void setuservariable(int varnum, char *var)
|
||||
{
|
||||
if (var != NULL && varnum >= 0 && varnum < __INST_LAST) {
|
||||
lstrcpy (g_variables + varnum*g_stringsize, var);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
int myatoi(char *s)
|
||||
{
|
||||
unsigned int v=0;
|
||||
if (*s == '0' && (s[1] == 'x' || s[1] == 'X'))
|
||||
{
|
||||
s+=2;
|
||||
for (;;)
|
||||
{
|
||||
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;
|
||||
else break;
|
||||
v<<=4;
|
||||
v+=c;
|
||||
}
|
||||
}
|
||||
else if (*s == '0' && s[1] <= '7' && s[1] >= '0')
|
||||
{
|
||||
s++;
|
||||
for (;;)
|
||||
{
|
||||
int c=*s++;
|
||||
if (c >= '0' && c <= '7') c-='0';
|
||||
else break;
|
||||
v<<=3;
|
||||
v+=c;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int sign=0;
|
||||
if (*s == '-') { s++; sign++; }
|
||||
for (;;)
|
||||
{
|
||||
int c=*s++ - '0';
|
||||
if (c < 0 || c > 9) break;
|
||||
v*=10;
|
||||
v+=c;
|
||||
}
|
||||
if (sign) return -(int) v;
|
||||
}
|
||||
return (int)v;
|
||||
}
|
||||
|
||||
int popint(int *value)
|
||||
{
|
||||
char buffer[1024];
|
||||
if (popstring(buffer) == 0) return FALSE;
|
||||
*value = myatoi(buffer);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void pushint(int value)
|
||||
{
|
||||
char buffer[1024];
|
||||
wsprintf(buffer, "%d", value);
|
||||
pushstring(buffer);
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
void main()
|
||||
{
|
||||
}
|
||||
#endif
|
56
Contrib/System/Plugin.h
Normal file
56
Contrib/System/Plugin.h
Normal file
|
@ -0,0 +1,56 @@
|
|||
#pragma once
|
||||
|
||||
typedef struct _stack_t {
|
||||
struct _stack_t *next;
|
||||
char text[1]; // this should be the length of string_size
|
||||
} stack_t;
|
||||
|
||||
enum
|
||||
{
|
||||
INST_0, // $0
|
||||
INST_1, // $1
|
||||
INST_2, // $2
|
||||
INST_3, // $3
|
||||
INST_4, // $4
|
||||
INST_5, // $5
|
||||
INST_6, // $6
|
||||
INST_7, // $7
|
||||
INST_8, // $8
|
||||
INST_9, // $9
|
||||
INST_R0, // $R0
|
||||
INST_R1, // $R1
|
||||
INST_R2, // $R2
|
||||
INST_R3, // $R3
|
||||
INST_R4, // $R4
|
||||
INST_R5, // $R5
|
||||
INST_R6, // $R6
|
||||
INST_R7, // $R7
|
||||
INST_R8, // $R8
|
||||
INST_R9, // $R9
|
||||
INST_CMDLINE, // $CMDLINE
|
||||
INST_INSTDIR, // $INSTDIR
|
||||
INST_OUTDIR, // $OUTDIR
|
||||
INST_EXEDIR, // $EXEDIR
|
||||
INST_LANG, // $LANGUAGE
|
||||
__INST_LAST
|
||||
};
|
||||
|
||||
#define PLUGINFUNCTION(name) void __declspec(dllexport) name(HWND hwndParent, int string_size, char *variables, stack_t **stacktop) { \
|
||||
g_hwndParent=hwndParent; \
|
||||
g_stringsize=string_size; \
|
||||
g_stacktop=stacktop; \
|
||||
g_variables=variables; {
|
||||
#define PLUGINFUNCTIONEND }}
|
||||
|
||||
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 void pushint(int value);
|
||||
|
||||
extern HWND g_hwndParent;
|
||||
extern int g_stringsize;
|
||||
extern stack_t **g_stacktop;
|
||||
extern char *g_variables;
|
390
Contrib/System/System.c
Normal file
390
Contrib/System/System.c
Normal file
|
@ -0,0 +1,390 @@
|
|||
// System.cpp : Defines the entry point for the DLL application.
|
||||
//
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "Plugin.h"
|
||||
#include "System.h"
|
||||
|
||||
HINSTANCE g_hInstance;
|
||||
|
||||
#define PT_STRING_SIZE 2048
|
||||
#define PARAMOKCHECK(expr) if (expr) { pushint(0); return; }
|
||||
|
||||
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
|
||||
|
||||
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(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;
|
||||
|
||||
// Extract dllname
|
||||
p1 = ProcID;
|
||||
p2 = dllname;
|
||||
while (*p1 && (*p1 != '?')) *(p2++) = *(p1++);
|
||||
*p2 = 0;
|
||||
if ((lstrlen(dllname) == 0) || (*p1 == 0)) return NULL;
|
||||
|
||||
// Extract procname
|
||||
p1++;
|
||||
p2 = procname;
|
||||
while (*p1 && (*p1 != '?')) *(p2++) = *(p1++);
|
||||
*p2 = 0;
|
||||
if ((lstrlen(procname) == 0) || (*p1 == 0)) return NULL;
|
||||
|
||||
// Ok, check If there is at least 1 param
|
||||
p1++;
|
||||
if (*p1 == 0) return NULL;
|
||||
|
||||
// Allocate memory for new Proc
|
||||
proc = (SystemProc*) GlobalAlloc(GPTR, sizeof(SystemProc));
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
// Move to next character
|
||||
proc->ParamCount++;
|
||||
p1++;
|
||||
}
|
||||
return proc;
|
||||
}
|
||||
|
||||
BOOL ParseParam(SystemProc *proc, char *ParamID)
|
||||
{
|
||||
char *p1;
|
||||
ProcParameter *par;
|
||||
|
||||
par = proc->Params + 1;
|
||||
p1 = ParamID;
|
||||
|
||||
// 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;
|
||||
|
||||
// Move to next param & character
|
||||
par++;
|
||||
p1++;
|
||||
}
|
||||
|
||||
if (*p1++ == 0) return TRUE;
|
||||
par = proc->Params;
|
||||
|
||||
// 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;
|
||||
|
||||
// Move to next param & character
|
||||
par++;
|
||||
p1++;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void ParamsInput(SystemProc *proc)
|
||||
{
|
||||
int i;
|
||||
ProcParameter *par;
|
||||
char buffer[PT_STRING_SIZE], *realbuf;
|
||||
|
||||
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: ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ParamsOutput(SystemProc *proc)
|
||||
{
|
||||
int i;
|
||||
ProcParameter *par;
|
||||
char buffer[PT_STRING_SIZE];
|
||||
|
||||
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: ;
|
||||
}
|
||||
|
||||
// Step 2: place it
|
||||
if (par->Output == IOT_STACK) pushstring(buffer);
|
||||
else if (par->Output > 0) setuservariable(par->Output - 1, buffer);
|
||||
}
|
||||
}
|
||||
|
||||
void SystemCall(SystemProc *proc)
|
||||
{
|
||||
int z;
|
||||
ProcParameter *par;
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
BOOL WINAPI _DllMainCRTStartup(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)
|
||||
{
|
||||
g_hInstance=hInst;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
50
Contrib/System/System.h
Normal file
50
Contrib/System/System.h
Normal file
|
@ -0,0 +1,50 @@
|
|||
// The following ifdef block is the standard way of creating macros which make exporting
|
||||
// from a DLL simpler. All files within this DLL are compiled with the SYSTEM_EXPORTS
|
||||
// symbol defined on the command line. this symbol should not be defined on any project
|
||||
// that uses this DLL. This way any other project whose source files include this file see
|
||||
// SYSTEM_API functions as being imported from a DLL, whereas this DLL sees symbols
|
||||
// defined with this macro as being exported.
|
||||
#pragma once
|
||||
|
||||
#ifdef SYSTEM_EXPORTS
|
||||
#define SYSTEM_API __declspec(dllexport)
|
||||
#else
|
||||
#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
|
||||
|
||||
// Input/Output Source/Destination
|
||||
#define IOT_NONE 0
|
||||
#define IOT_STACK -1
|
||||
#define IOT_REG 1
|
||||
|
||||
// Our single proc parameter
|
||||
typedef struct
|
||||
{
|
||||
int Type;
|
||||
BOOL IsPointer;
|
||||
int Value; // it can hold any value
|
||||
int Input;
|
||||
int Output;
|
||||
} ProcParameter;
|
||||
|
||||
// Our single proc
|
||||
typedef struct
|
||||
{
|
||||
HANDLE dll;
|
||||
HANDLE proc;
|
||||
int ParamCount;
|
||||
ProcParameter Params[20]; // I hope nobody will use more than 20 params
|
||||
} 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);
|
1
Contrib/System/System.ncb
Normal file
1
Contrib/System/System.ncb
Normal file
|
@ -0,0 +1 @@
|
|||
Microsoft C/C++ MSF 7.00
|
21
Contrib/System/System.sln
Normal file
21
Contrib/System/System.sln
Normal file
|
@ -0,0 +1,21 @@
|
|||
Microsoft Visual Studio Solution File, Format Version 7.00
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "System", "System.vcproj", "{2FB013AB-6FD4-4239-9974-C999F4DFD70C}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfiguration) = preSolution
|
||||
ConfigName.0 = Debug
|
||||
ConfigName.1 = Release
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectDependencies) = postSolution
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfiguration) = postSolution
|
||||
{2FB013AB-6FD4-4239-9974-C999F4DFD70C}.Debug.ActiveCfg = Debug|Win32
|
||||
{2FB013AB-6FD4-4239-9974-C999F4DFD70C}.Debug.Build.0 = Debug|Win32
|
||||
{2FB013AB-6FD4-4239-9974-C999F4DFD70C}.Release.ActiveCfg = Release|Win32
|
||||
{2FB013AB-6FD4-4239-9974-C999F4DFD70C}.Release.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityAddIns) = postSolution
|
||||
EndGlobalSection
|
||||
EndGlobal
|
163
Contrib/System/System.txt
Normal file
163
Contrib/System/System.txt
Normal file
|
@ -0,0 +1,163 @@
|
|||
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.
|
166
Contrib/System/System.vcproj
Normal file
166
Contrib/System/System.vcproj
Normal file
|
@ -0,0 +1,166 @@
|
|||
<?xml version="1.0" encoding = "windows-1251"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="7.00"
|
||||
Name="System"
|
||||
ProjectGUID="{2FB013AB-6FD4-4239-9974-C999F4DFD70C}"
|
||||
Keyword="Win32Proj">
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"/>
|
||||
</Platforms>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="Debug"
|
||||
IntermediateDirectory="Debug"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;SYSTEM_EXPORTS"
|
||||
MinimalRebuild="TRUE"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="5"
|
||||
UsePrecompiledHeader="3"
|
||||
AssemblerOutput="2"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="TRUE"
|
||||
DebugInformationFormat="4"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="kernel32.lib user32.lib RunTmChk.lib libcd.lib"
|
||||
OutputFile="$(OutDir)/System.dll"
|
||||
LinkIncremental="2"
|
||||
IgnoreAllDefaultLibraries="TRUE"
|
||||
GenerateDebugInformation="TRUE"
|
||||
ProgramDatabaseFile="$(OutDir)/System.pdb"
|
||||
SubSystem="2"
|
||||
ImportLibrary="$(OutDir)/System.lib"
|
||||
TargetMachine="1"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="Release"
|
||||
IntermediateDirectory="Release"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
InlineFunctionExpansion="1"
|
||||
OmitFramePointers="TRUE"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;SYSTEM_EXPORTS"
|
||||
StringPooling="TRUE"
|
||||
RuntimeLibrary="4"
|
||||
BufferSecurityCheck="FALSE"
|
||||
EnableFunctionLevelLinking="TRUE"
|
||||
UsePrecompiledHeader="3"
|
||||
AssemblerOutput="2"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="TRUE"
|
||||
DebugInformationFormat="3"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="kernel32.lib user32.lib"
|
||||
OutputFile="$(OutDir)/System.dll"
|
||||
LinkIncremental="1"
|
||||
IgnoreAllDefaultLibraries="TRUE"
|
||||
GenerateDebugInformation="TRUE"
|
||||
SubSystem="2"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
OptimizeForWindows98="1"
|
||||
ImportLibrary="$(OutDir)/System.lib"
|
||||
TargetMachine="1"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm">
|
||||
<File
|
||||
RelativePath="Buffers.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="Plugin.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="System.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="stdafx.c">
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="1"/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="1"/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl;inc">
|
||||
<File
|
||||
RelativePath="Buffers.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="Plugin.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="System.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="stdafx.h">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Resource Files"
|
||||
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe">
|
||||
</Filter>
|
||||
<File
|
||||
RelativePath="ReadMe.txt">
|
||||
</File>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
48
Contrib/System/SystemEx.nsi
Normal file
48
Contrib/System/SystemEx.nsi
Normal file
|
@ -0,0 +1,48 @@
|
|||
; This is just an example of System Plugin
|
||||
;
|
||||
; Read LastComments.txt and System.txt (unfinished)
|
||||
;
|
||||
; (c) BSForce, 2002
|
||||
|
||||
Name "System Plugin Example"
|
||||
OutFile "SystemEx.exe"
|
||||
|
||||
Function .onInit
|
||||
|
||||
; First example: Message box, uses PartAddr, ShortAddr, Call
|
||||
|
||||
System::PartAddr "user32.dll?MessageBoxA?iissi"
|
||||
Pop $0
|
||||
System::ShortAddr "ssss?1nssn" $0
|
||||
Pop $0
|
||||
System::Call 33 "Example 1" "Just something" 0 $0
|
||||
Pop $3
|
||||
Pop $2
|
||||
MessageBox MB_OK "Result: $1, strings '$2' and '$3'"
|
||||
System::Free $0
|
||||
Pop $0
|
||||
|
||||
; Second example: uses FullAddr, Call, incorpotates int64, returns to $INSTDIR
|
||||
|
||||
System::FullAddr "snnn?s1al2" "kernel32.dll?GetDiskFreeSpaceExA?isplplpl"
|
||||
Pop $0
|
||||
System::Call "c:\" $0
|
||||
Pop $3
|
||||
MessageBox MB_OK "Path '$1', Free '$R0', Total '$INSTDIR', FreeUser '$2', Result $3"
|
||||
System::Free $0
|
||||
Pop $0
|
||||
|
||||
; Third example: uses FullCall
|
||||
|
||||
System::FullCall "?9" "kernel32.dll?GetVersion?i"
|
||||
; Version aquired, but we wonna built number for example
|
||||
IntOp $8 $9 / 65536
|
||||
MessageBox MB_OK "Aquired windows version: $9 (Build $8)"
|
||||
|
||||
Quit
|
||||
FunctionEnd
|
||||
|
||||
Section "ThisNameIsIgnoredSoWhyBother?"
|
||||
SectionEnd
|
||||
|
||||
; eof
|
8
Contrib/System/stdafx.c
Normal file
8
Contrib/System/stdafx.c
Normal file
|
@ -0,0 +1,8 @@
|
|||
// stdafx.cpp : source file that includes just the standard includes
|
||||
// AnyDLL.pch will be the pre-compiled header
|
||||
// stdafx.obj will contain the pre-compiled type information
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
// TODO: reference any additional headers you need in STDAFX.H
|
||||
// and not in this file
|
12
Contrib/System/stdafx.h
Normal file
12
Contrib/System/stdafx.h
Normal file
|
@ -0,0 +1,12 @@
|
|||
// stdafx.h : include file for standard system include files,
|
||||
// or project specific include files that are used frequently, but
|
||||
// are changed infrequently
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
|
||||
// Windows Header Files:
|
||||
#include <windows.h>
|
||||
|
||||
// TODO: reference additional headers your program requires here
|
BIN
Plugins/System.dll
Normal file
BIN
Plugins/System.dll
Normal file
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue