
git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@7289 212acab6-be3b-0410-9dea-997c60f758d6
197 lines
6.7 KiB
C
197 lines
6.7 KiB
C
#ifndef ___SYSTEM__H___
|
|
#define ___SYSTEM__H___
|
|
|
|
// This should probably be moved to platform.h at some point
|
|
|
|
#if defined(_M_X64) || defined(_M_AMD64) || defined(__amd64__)
|
|
# define SYSTEM_AMD64
|
|
#elif defined(_M_IX86) || defined(__i386__) || defined(_X86_)
|
|
# define SYSTEM_X86
|
|
#elif defined(_M_ARM64)
|
|
# define SYSTEM_ARM64
|
|
#else
|
|
# error "Unknown architecture!"
|
|
#endif
|
|
|
|
#ifdef _WIN64
|
|
# define SYSFMT_HEXPTR _T("0x%016IX")
|
|
#else
|
|
# define SYSFMT_HEXPTR _T("0x%08X")
|
|
#endif
|
|
|
|
|
|
// 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.
|
|
|
|
#ifdef SYSTEM_EXPORTS
|
|
# define SYSTEM_API __declspec(dllexport)
|
|
#else
|
|
# define SYSTEM_API __declspec(dllimport) // BUGBUG: This is a plugin, who is going to import the functions directly?
|
|
#endif
|
|
|
|
#define SYS_ALIGNUP(num, al) ( ((num)+((al)-1)) & ~((al)-1) )
|
|
#define SYS_UNSAFEALIGNON(num, al) ( (num) % (al) == 0 ? (num) : SYS_ALIGNUP((num), (al)) ) // al CANNOT be 0!
|
|
#define SYS_ALIGNON(num, al) ( (al) ? SYS_UNSAFEALIGNON((num), (al)) : (num) )
|
|
|
|
#define NEW_STACK_SIZE 256*256
|
|
|
|
// Proc types:
|
|
#define PT_NOTHING 0
|
|
#define PT_PROC 1
|
|
#define PT_STRUCT 2
|
|
#define PT_VTABLEPROC 3
|
|
|
|
// Proc results:
|
|
#define PR_OK 0
|
|
#define PR_ERROR -1
|
|
#define PR_CALLBACK 1
|
|
|
|
// Real world argument types
|
|
#define PAT_VOID 0
|
|
#define PAT_INT 1
|
|
#define PAT_LONG 2
|
|
#define PAT_STRING 3
|
|
#define PAT_WSTRING 4
|
|
#define PAT_GUID 5
|
|
#define PAT_CALLBACK 6
|
|
#define PAT_REGMEM 7
|
|
#ifdef _UNICODE
|
|
#define PAT_TSTRING PAT_WSTRING
|
|
#else
|
|
#define PAT_TSTRING PAT_STRING
|
|
#endif
|
|
#define PAT_PTR ( (4==sizeof(void*)) ? PAT_INT : PAT_LONG )
|
|
#define PAT_ALIGNFLAG 0x8000 // Type is aligned to its natural alignment
|
|
|
|
// Input/Output Source/Destination
|
|
#define IOT_NONE 0
|
|
#define IOT_STACK -1
|
|
#define IOT_REG 1
|
|
#define IOT_INLINE (__INST_LAST+1) // should replace pointer to inline input
|
|
// #define INLINE_INPUT -> any other value, will contain pointer to input string
|
|
|
|
// Options
|
|
#define POPT_CDECL 0x1 // (Option & 0x1) == 0x1 -> cdecl, otherwise stdcall
|
|
#define POPT_PERMANENT 0x2 // Permanent proc, will not be destroyed after calling
|
|
#define POPT_ALWRETURN 0x4 // Always return
|
|
#define POPT_NEVERREDEF 0x8 // Never redefine
|
|
#define POPT_GENSTACK 0x10 // Use general stack (non temporary for callback)
|
|
#define POPT_ERROR 0x20 // Call GetLastError after proc and push it to stack
|
|
#define POPT_UNLOAD 0x40 // unload dll after call
|
|
#define POPT_CLONE 0x80 // Callback clone
|
|
#define POPT_SYNTAX2 0x100 // "?2" syntax mode (direct callback ids and aligned uppercased types)
|
|
|
|
// Proc argument (ProcParameter) options
|
|
#define PAO_PTRFLAG -1 // Could be changed to 0x80000000 if we need to support "*&iN"
|
|
#define PAO_ARRBASE 1
|
|
#define ParamOptionIsPointer(opt) ( (opt) < 0 )
|
|
|
|
typedef struct
|
|
{
|
|
int Type; // Can be ORed with PAT_ALIGNFLAG to request alignment in structs
|
|
int Option; // PAO_PTRFLAG -> Pointer, PAO_ARRBASE-... -> Special+PAO_ARRBASE
|
|
INT_PTR Value; // it can hold any pointer sized value
|
|
#ifndef _WIN64
|
|
int _value; // Upper 32 bits of Value when type is 64 bit (2 pushes)
|
|
#endif
|
|
int Size; // Value real size (should be either 1 or 2 (the number of pushes))
|
|
int Output;
|
|
INT_PTR Input;
|
|
HGLOBAL allocatedBlock; // block allocated for passing string, wstring or guid param
|
|
} ProcParameter;
|
|
|
|
#define ParamIsSimple(par) ( (par).Option == 0 )
|
|
#define ParamIsPointer(par) ParamOptionIsPointer((par).Option)
|
|
#define ParamIsArray(par) ( (par).Option > 0 ) // AKA special
|
|
#define GetParamArrayTypeSize GetSpecialParamTypeSize
|
|
#ifdef POPT_SYNTAX2
|
|
#define GetParamType(par) ( (BYTE) (par).Type )
|
|
#else
|
|
#define GetParamType(par) ( (par).Type )
|
|
#endif
|
|
|
|
// Our single proc (Since the user will free proc with GlobalFree,
|
|
// I've declared all variables as statics)
|
|
typedef struct tag_SystemProc SystemProc;
|
|
struct tag_SystemProc
|
|
{
|
|
int ProcType;
|
|
int ProcResult;
|
|
TCHAR DllName[1024];
|
|
TCHAR ProcName[1024];
|
|
HMODULE Dll;
|
|
HANDLE Proc;
|
|
int Options;
|
|
int ParamCount;
|
|
ProcParameter Params[100]; // I hope nobody will use more than 100 params
|
|
|
|
// Callback specific
|
|
int CallbackIndex;
|
|
int ArgsSize;
|
|
// Clone of current element (used for multi-level callbacks)
|
|
SystemProc *Clone;
|
|
};
|
|
|
|
typedef struct tag_CallbackThunk CallbackThunk;
|
|
struct tag_CallbackThunk
|
|
{
|
|
#ifdef SYSTEM_X86
|
|
/*
|
|
#pragma pack(push,1)
|
|
char mov_eax_imm;
|
|
int sysprocptr;
|
|
char reljmp_imm;
|
|
int realprocaddr;
|
|
#pragma pack(pop)
|
|
*/
|
|
char asm_code[10];
|
|
#elif defined(SYSTEM_AMD64) || defined(SYSTEM_ARM64)
|
|
char asm_code[BUGBUG64(1)]; // TODO: BUGBUG64
|
|
#else
|
|
#error "Asm thunk not implemeted for this architecture!"
|
|
#endif
|
|
|
|
CallbackThunk* pNext;
|
|
};
|
|
|
|
// Free() only knows about pNext in CallbackThunk, it does not know anything about the assembly, that is where this helper comes in...
|
|
#ifdef SYSTEM_X86
|
|
# define GetAssociatedSysProcFromCallbackThunkPtr(pCbT) ( (SystemProc*) *(unsigned int*) (((char*)(pCbT))+1) )
|
|
#elif defined(SYSTEM_AMD64) || defined(SYSTEM_ARM64)
|
|
# define GetAssociatedSysProcFromCallbackThunkPtr(pCbT) BUGBUG64(NULL)
|
|
#else
|
|
# error "GetAssociatedSysProcFromCallbackThunkPtr not defined for the current architecture!"
|
|
#endif
|
|
|
|
|
|
extern const int ParamSizeByType[]; // Size of every parameter type (*4 bytes)
|
|
|
|
extern HANDLE CreateCallback(SystemProc *cbproc);
|
|
extern SystemProc* PrepareProc(BOOL NeedForCall);
|
|
extern void ParamAllocate(SystemProc *proc);
|
|
extern void ParamsDeAllocate(SystemProc *proc);
|
|
extern void ParamsIn(SystemProc *proc);
|
|
extern void ParamsOut(SystemProc *proc);
|
|
#ifdef SYSTEM_AMD64
|
|
extern SystemProc* CallProc2(SystemProc *proc, UINT_PTR ParamCount);
|
|
#define CallProc(p) CallProc2((p), (p)->ParamCount) // ParamCount is passed as a parameter so CallProc2 can determine the required stack size without a function call
|
|
#else //! SYSTEM_AMD64
|
|
extern SystemProc* CallProc(SystemProc *proc);
|
|
#endif //~ SYSTEM_AMD64
|
|
#ifndef SYSTEM_NOCALLBACKS
|
|
extern SystemProc* CallBack(SystemProc *proc);
|
|
extern SystemProc* RealCallBack();
|
|
#endif
|
|
extern void CallStruct(SystemProc *proc);
|
|
|
|
#ifdef _UNICODE
|
|
# define STRSET2CH(str, c1, c2) ( *(DWORD*)(str) = ((c1)|(c2)<<16) )
|
|
#else
|
|
# define STRSET2CH(str, c1, c2) ( *(WORD*)(str) = ((c1)|(c2)<<8) )
|
|
#endif
|
|
|
|
#endif
|