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:
joostverburg 2002-09-21 20:59:13 +00:00
parent 1fb8b94a22
commit 88956798f1
15 changed files with 1143 additions and 0 deletions

93
Contrib/System/Buffers.c Normal file
View 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
View file

@ -0,0 +1,3 @@
#pragma once
extern HANDLE GlobalCopy(HANDLE Old);

View 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
View 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
View 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
View 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
View 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);

View file

@ -0,0 +1 @@
Microsoft C/C++ MSF 7.00

21
Contrib/System/System.sln Normal file
View 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
View 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.

View 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>

View 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
View 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
View 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

Binary file not shown.