system.c
来自「NullSofts criptable install system2.28源代」· C语言 代码 · 共 1,412 行 · 第 1/3 页
C
1,412 行
// System.cpp : Defines the entry point for the DLL application.
//
#include "stdafx.h"
#include "Plugin.h"
#include "Buffers.h"
#include "System.h"
#ifndef __GNUC__
#include <crtdbg.h>
#endif /* __GNUC__ */
#include <objbase.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
const int ParamSizeByType[7] = {0, // PAT_VOID (Size will be equal to 1)
1, // PAT_INT
2, // PAT_LONG
1, // PAT_STRING
1, // PAT_WSTRING
1, // PAT_GUID
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;
int LastStackReal;
DWORD LastError;
volatile SystemProc *LastProc;
int CallbackIndex;
HINSTANCE g_hInstance;
// Return to callback caller with stack restore
char retexpr[4];
HANDLE retaddr;
#ifndef __GNUC__
/*
FIXME:
GCC cannot compile the inline assembly used by System::Call and
System::Get, so those functions and their supporting functions
are disabled when using GCC.
*/
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;
}
#ifdef SYSTEM_LOG_DEBUG
// System log debuggin turned on
#define SYSTEM_EVENT(a) { _asm { mov logespsave, esp }; LogEvent(a); }
#define SYSTEM_LOG_ADD(a) { lstrcat(syslogbuf, a); }
#define SYSTEM_LOG_POST { lstrcat(syslogbuf, "\n"); WriteToLog(syslogbuf); *syslogbuf = 0; }
HANDLE logfile = NULL;
char syslogbuf[4096] = "";
int logop = 0, logespsave;
void WriteToLog(char *buffer)
{
DWORD written;
char timebuffer[128];
GetTickCount();
if (logfile == NULL) return;
SetFilePointer(logfile, 0, 0, FILE_END);
wsprintf(timebuffer, "%04d %04d.%03d ", (++logop)%10000, (GetTickCount() / 1000) % 10000,
GetTickCount() % 1000);
_RPT0(_CRT_WARN, timebuffer);
_RPT0(_CRT_WARN, buffer);
WriteFile(logfile, timebuffer, lstrlen(timebuffer), &written, NULL);
WriteFile(logfile, buffer, lstrlen(buffer), &written, NULL);
// FlushFileBuffers(logfile);
}
void LogEvent(char *a)
{
char buffer[1024];
wsprintf(buffer, "%s ESP = 0x%08X Stack = 0x%08X Real = 0x%08X", a,
logespsave, LastStackPlace, LastStackReal);
SYSTEM_LOG_ADD(buffer);
}
PLUGINFUNCTION(Debug)
{
char *o1;
o1 = popstring();
if (logfile == NULL)
if (lstrlen(o1) > 0)
{
SYSTEMTIME t;
char buffer[1024], buftime[1024], bufdate[1024];
// Init debugging
logfile = CreateFile(o1, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
SetFilePointer(logfile, 0, 0, FILE_END);
logop = 0;
GetLocalTime(&t);
GetTimeFormat(LOCALE_SYSTEM_DEFAULT, LOCALE_NOUSEROVERRIDE, &t, NULL, buftime, 1024);
GetDateFormat(LOCALE_SYSTEM_DEFAULT, LOCALE_NOUSEROVERRIDE, &t, NULL, bufdate, 1024);
wsprintf(buffer, "System, %s %s [build "__TIME__" "__DATE__"]\n", buftime, bufdate);
WriteToLog(buffer);
} else ;
else
if (lstrlen(o1) > 0)
{
// Log in to log file
WriteToLog(o1);
} else
{
// Stop debugging
WriteToLog("Debug stopped.\n\n\n");
CloseHandle(logfile);
logfile = NULL;
}
} PLUGINFUNCTIONEND
#else
// System log debugging turned off
#define SYSTEM_EVENT(a)
#define SYSTEM_LOG_ADD(a)
#define SYSTEM_LOG_POST
#endif
PLUGINFUNCTION(Get)
{
SystemProc *proc = PrepareProc(FALSE);
if (proc == NULL)
{
pushstring("error");
return;
}
SYSTEM_LOG_ADD("Get ");
SYSTEM_LOG_ADD(proc->DllName);
SYSTEM_LOG_ADD("::");
SYSTEM_LOG_ADD(proc->ProcName);
SYSTEM_LOG_ADD("\n");
SYSTEM_LOG_POST;
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)
{
// Prepare input
SystemProc *proc = PrepareProc(TRUE);
if (proc == NULL)
return;
SYSTEM_LOG_ADD("Call ");
SYSTEM_LOG_ADD(proc->DllName);
SYSTEM_LOG_ADD("::");
SYSTEM_LOG_ADD(proc->ProcName);
SYSTEM_LOG_ADD("\n");
if (proc->ProcResult != PR_CALLBACK)
ParamAllocate(proc);
ParamsIn(proc);
// 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:
case PT_VTABLEPROC:
proc = CallProc(proc); break;
case PT_STRUCT:
CallStruct(proc); break;
}
}
// 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];
// Return result instead of return value
proc->Params[0].Value = (int) GetResultStr(proc);
proc->Params[0].Type = PAT_STRING;
// Return all params
ParamsOut(proc);
// Restore old return param
proc->Params[0] = pp;
} else
ParamsOut(proc);
}
if (proc->ProcResult != PR_CALLBACK)
{
// Deallocate params if not callback
ParamsDeAllocate(proc);
// if not callback - check for unload library option
if ((proc->Options & POPT_UNLOAD)
&& (proc->ProcType == PT_PROC)
&& (proc->Dll != NULL))
FreeLibrary(proc->Dll); // and unload it :)
// In case of POPT_ERROR - first pop will be proc error
if ((proc->Options & POPT_ERROR) != 0) pushint(LastError);
}
// If proc is permanent?
if ((proc->Options & POPT_PERMANENT) == 0)
GlobalFree((HANDLE) proc); // No, free it
} PLUGINFUNCTIONEND
#endif /* __GNUC__ */
PLUGINFUNCTIONSHORT(Int64Op)
{
__int64 i1, i2 = 0, i3, i4;
char *op, *o1, *o2;
char buf[128];
// 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);
}
// 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.
if (i2 == 0) { i3 = 0; i4 = i1; }
else {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);
}
#ifndef __GNUC__
SystemProc *PrepareProc(BOOL NeedForCall)
{
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;
BOOL param_defined = FALSE;
SystemProc *proc = NULL;
char *ibuf, *ib, *sbuf, *cbuf, *cb;
// Retrieve proc specs
cb = (cbuf = AllocString()); // Current String buffer
sbuf = AllocString(); // Safe String buffer
ib = ibuf = popstring(); // Input string
// Parse the string
while (SectionType != -1)
{
// Check for Section Change
BOOL changed = TRUE;
ChangesDone = SectionType;
if (SectionType != PST_PROC && proc == NULL)
// no proc after PST_PROC is done means something is wrong with
// the call syntax and we'll get a crash because everything needs
// proc from here on.
break;
switch (*ib)
{
case 0x0: SectionType = -1; break;
case '#': SectionType = PST_PROC; ProcType = PT_NOTHING; break;
case '(':
SectionType = PST_PARAMS;
// fake-real parameter: for COM interfaces first param is Interface Pointer
ParamIndex = ((ProcType == PT_VTABLEPROC)?(2):(1));
temp3 = temp = 0;
param_defined = FALSE;
break;
case ')': SectionType = PST_RETURN; temp3 = temp = 0; break;
case '?': SectionType = PST_OPTIONS; temp = 1; break;
default:
changed = FALSE;
}
// Check for changes
if (changed)
{
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)
{
// Previous proc (for clear up)
SystemProc *pr = NULL;
if (proc != NULL) GlobalFree(proc);
// Get already defined proc
proc = (SystemProc *) myatoi(cbuf);
if (!proc) break;
// Find the last clone at proc queue
while (proc && (proc->Clone != NULL)) proc = (pr = proc)->Clone;
// Clear parents record for child callback proc
if (pr != NULL) pr->Clone = NULL;
// 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:
case PT_VTABLEPROC:
lstrcpy(proc->DllName, sbuf);
case PT_STRUCT:
lstrcpy(proc->ProcName, cbuf);
break;
}
break;
case PST_PARAMS:
if (param_defined)
proc->ParamCount = ParamIndex;
else
// not simply zero because of vtable calls
proc->ParamCount = ParamIndex - 1;
case PST_RETURN:
case PST_OPTIONS:
break;
}
ib++;
cb = cbuf;
continue;
}
// Parse the section
ChangesDone = PCD_NONE;
switch (SectionType)
{
// Proc sections parser
case PST_PROC:
switch (*ib)
{
case ':':
case '-':
// Is it '::'
if ((*(ib) == '-') && (*(ib+1) == '>'))
{
ProcType = PT_VTABLEPROC;
} else
{
if ((*(ib+1) != ':') || (*(ib) == '-')) break;
ProcType = PT_PROC;
}
ib++; // Skip next ':'
if (cb > cbuf)
{
*cb = 0;
lstrcpy(sbuf, cbuf);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?