NSIS/Contrib/System/System.c

391 lines
8.4 KiB
C
Raw Normal View History

// 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;
}