2005-04-16 17:09:19 +00:00
# ifndef ___SYSTEM__H___
# define ___SYSTEM__H___
2009-12-21 15:04:22 +00:00
// This should probably be moved to platform.h at some point
2014-02-08 00:13:52 +00:00
# if defined(_M_X64) || defined(_M_AMD64) || defined(__amd64__)
2014-03-03 18:10:53 +00:00
# define SYSTEM_AMD64
2009-12-21 15:04:22 +00:00
# elif defined(_M_IX86) || defined(__i386__) || defined(_X86_)
2014-03-03 18:10:53 +00:00
# define SYSTEM_X86
2018-06-03 21:00:53 +00:00
# elif defined(_M_ARM64)
# define SYSTEM_ARM64
2009-12-21 15:04:22 +00:00
# else
2014-03-03 18:10:53 +00:00
# error "Unknown architecture!"
2009-12-21 15:04:22 +00:00
# endif
2014-03-03 18:10:53 +00:00
2013-09-06 23:48:59 +00:00
# ifdef _WIN64
2014-03-03 18:10:53 +00:00
# define SYSFMT_HEXPTR _T("0x%016IX")
2013-09-06 23:48:59 +00:00
# else
2014-03-03 18:10:53 +00:00
# define SYSFMT_HEXPTR _T("0x%08X")
2013-09-06 23:48:59 +00:00
# endif
2009-12-21 15:04:22 +00:00
2002-09-21 20:59:13 +00:00
// 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
2014-03-03 18:10:53 +00:00
# define SYSTEM_API __declspec(dllexport)
2002-09-21 20:59:13 +00:00
# else
2014-03-03 18:10:53 +00:00
# define SYSTEM_API __declspec(dllimport) // BUGBUG: This is a plugin, who is going to import the functions directly?
2002-09-21 20:59:13 +00:00
# endif
2017-12-03 18:04:02 +00:00
# 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) )
2003-03-22 11:15:53 +00:00
# define NEW_STACK_SIZE 256*256
2002-10-23 17:53:09 +00:00
// Proc types:
# define PT_NOTHING 0
# define PT_PROC 1
# define PT_STRUCT 2
2003-09-04 18:25:57 +00:00
# define PT_VTABLEPROC 3
2002-10-23 17:53:09 +00:00
// Proc results:
# define PR_OK 0
# define PR_ERROR -1
# define PR_CALLBACK 1
// Real world argument types
2008-11-21 09:34:24 +00:00
# define PAT_VOID 0
# define PAT_INT 1
# define PAT_LONG 2
# define PAT_STRING 3
# define PAT_WSTRING 4
# define PAT_GUID 5
2003-09-04 18:25:57 +00:00
# define PAT_CALLBACK 6
2014-06-27 14:27:32 +00:00
# define PAT_REGMEM 7
2021-08-04 17:10:36 +00:00
# ifdef _UNICODE
2010-04-13 15:25:33 +00:00
# define PAT_TSTRING PAT_WSTRING
2012-03-06 23:09:23 +00:00
# else
2010-04-13 15:25:33 +00:00
# define PAT_TSTRING PAT_STRING
2012-03-06 23:09:23 +00:00
# endif
2012-09-10 22:56:41 +00:00
# define PAT_PTR ( (4==sizeof(void*)) ? PAT_INT : PAT_LONG )
2017-12-03 18:04:02 +00:00
# define PAT_ALIGNFLAG 0x8000 // Type is aligned to its natural alignment
2002-09-21 20:59:13 +00:00
// Input/Output Source/Destination
2008-11-21 09:34:24 +00:00
# define IOT_NONE 0
# define IOT_STACK -1
# define IOT_REG 1
2002-10-31 14:41:46 +00:00
# define IOT_INLINE (__INST_LAST+1) // should replace pointer to inline input
2002-10-23 17:53:09 +00:00
// #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)
2003-04-18 11:21:06 +00:00
# define POPT_ERROR 0x20 // Call GetLastError after proc and push it to stack
2003-09-11 20:31:04 +00:00
# define POPT_UNLOAD 0x40 // unload dll after call
2017-12-03 18:04:02 +00:00
# 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 )
2002-09-21 20:59:13 +00:00
typedef struct
{
2017-12-03 18:04:02 +00:00
int Type ; // Can be ORed with PAT_ALIGNFLAG to request alignment in structs
int Option ; // PAO_PTRFLAG -> Pointer, PAO_ARRBASE-... -> Special+PAO_ARRBASE
2013-09-06 23:48:59 +00:00
INT_PTR Value ; // it can hold any pointer sized value
2014-07-01 22:09:38 +00:00
# ifndef _WIN64
int _value ; // Upper 32 bits of Value when type is 64 bit (2 pushes)
# endif
2002-10-23 17:53:09 +00:00
int Size ; // Value real size (should be either 1 or 2 (the number of pushes))
2008-11-21 09:34:24 +00:00
int Output ;
2014-07-01 22:09:38 +00:00
INT_PTR Input ;
2003-09-04 18:25:57 +00:00
HGLOBAL allocatedBlock ; // block allocated for passing string, wstring or guid param
2002-09-21 20:59:13 +00:00
} ProcParameter ;
2017-12-03 18:04:02 +00:00
# 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
2002-10-23 17:53:09 +00:00
// Our single proc (Since the user will free proc with GlobalFree,
// I've declared all variables as statics)
typedef struct tag_SystemProc SystemProc ;
2005-05-06 10:23:32 +00:00
struct tag_SystemProc
2002-09-21 20:59:13 +00:00
{
2008-11-21 09:34:24 +00:00
int ProcType ;
2002-10-23 17:53:09 +00:00
int ProcResult ;
2010-03-24 17:22:56 +00:00
TCHAR DllName [ 1024 ] ;
TCHAR ProcName [ 1024 ] ;
2010-03-29 14:24:47 +00:00
HMODULE Dll ;
HANDLE Proc ;
2002-10-23 17:53:09 +00:00
int Options ;
2008-11-21 09:34:24 +00:00
int ParamCount ;
ProcParameter Params [ 100 ] ; // I hope nobody will use more than 100 params
2002-10-23 17:53:09 +00:00
// Callback specific
int CallbackIndex ;
int ArgsSize ;
// Clone of current element (used for multi-level callbacks)
SystemProc * Clone ;
2005-05-06 10:23:32 +00:00
} ;
2002-09-21 20:59:13 +00:00
2009-12-21 21:25:45 +00:00
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)
*/
2010-02-06 15:51:55 +00:00
char asm_code [ 10 ] ;
2018-06-03 21:00:53 +00:00
# elif defined(SYSTEM_AMD64) || defined(SYSTEM_ARM64)
2013-09-06 23:48:59 +00:00
char asm_code [ BUGBUG64 ( 1 ) ] ; // TODO: BUGBUG64
2009-12-21 21:25:45 +00:00
# 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) )
2018-06-03 21:00:53 +00:00
# elif defined(SYSTEM_AMD64) || defined(SYSTEM_ARM64)
2013-09-06 23:48:59 +00:00
# define GetAssociatedSysProcFromCallbackThunkPtr(pCbT) BUGBUG64(NULL)
2009-12-21 21:25:45 +00:00
# else
# error "GetAssociatedSysProcFromCallbackThunkPtr not defined for the current architecture!"
# endif
2003-09-11 20:31:04 +00:00
extern const int ParamSizeByType [ ] ; // Size of every parameter type (*4 bytes)
2002-10-23 17:53:09 +00:00
extern HANDLE CreateCallback ( SystemProc * cbproc ) ;
2014-03-03 18:10:53 +00:00
extern SystemProc * PrepareProc ( BOOL NeedForCall ) ;
2002-10-23 17:53:09 +00:00
extern void ParamAllocate ( SystemProc * proc ) ;
extern void ParamsDeAllocate ( SystemProc * proc ) ;
extern void ParamsIn ( SystemProc * proc ) ;
extern void ParamsOut ( SystemProc * proc ) ;
2014-03-03 18:10:53 +00:00
# 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
2017-11-30 21:38:49 +00:00
# else //! SYSTEM_AMD64
2014-03-03 18:10:53 +00:00
extern SystemProc * CallProc ( SystemProc * proc ) ;
2017-11-30 21:38:49 +00:00
# endif //~ SYSTEM_AMD64
2014-03-03 18:10:53 +00:00
# ifndef SYSTEM_NOCALLBACKS
extern SystemProc * CallBack ( SystemProc * proc ) ;
extern SystemProc * RealCallBack ( ) ;
# endif
2002-10-23 17:53:09 +00:00
extern void CallStruct ( SystemProc * proc ) ;
2005-04-16 17:09:19 +00:00
2012-03-06 00:26:12 +00:00
# ifdef _UNICODE
# define STRSET2CH(str, c1, c2) ( *(DWORD*)(str) = ((c1)|(c2)<<16) )
# else
# define STRSET2CH(str, c1, c2) ( *(WORD*)(str) = ((c1)|(c2)<<8) )
# endif
2005-04-16 17:09:19 +00:00
# endif