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 + -
显示快捷键?