
git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@1130 212acab6-be3b-0410-9dea-997c60f758d6
163 lines
No EOL
6.7 KiB
Text
163 lines
No EOL
6.7 KiB
Text
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. |