mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-08 03:28:20 +02:00
518 lines
No EOL
14 KiB
C++
518 lines
No EOL
14 KiB
C++
#define SUPPORT_TLS
|
|
|
|
#ifdef _WIN64
|
|
typedef unsigned __int64 size_t;
|
|
typedef __int64 ptrdiff_t;
|
|
typedef __int64 intptr_t;
|
|
#else
|
|
typedef unsigned int size_t;
|
|
typedef int ptrdiff_t;
|
|
typedef int intptr_t;
|
|
#endif
|
|
typedef unsigned int DWORD;
|
|
typedef unsigned short WORD;
|
|
typedef char* LPSTR;
|
|
typedef char* LPBYTE;
|
|
|
|
typedef void* HINSTANCE;
|
|
typedef void* HANDLE;
|
|
typedef void* HMODULE;
|
|
|
|
#define WINAPI __stdcall
|
|
#define NTAPI __stdcall
|
|
typedef int BOOL;
|
|
#define FALSE 0
|
|
#define TRUE 1
|
|
|
|
#define NULL 0
|
|
#define _CONSOLE_APP 1
|
|
#define _GUI_APP 2
|
|
#define _O_RDONLY 0x0000 // open for reading only
|
|
#define _O_WRONLY 0x0001 // open for writing only
|
|
#define STD_INPUT_HANDLE -10
|
|
#define STD_OUTPUT_HANDLE -11
|
|
#define STD_ERROR_HANDLE -12
|
|
#define SW_SHOWDEFAULT 10
|
|
#define STARTF_USESHOWWINDOW 0x00000001
|
|
#define DLL_THREAD_ATTACH 2
|
|
|
|
#define _MCW_PC 0x00030000 // Precision Control
|
|
#define _PC_53 0x00010000 // 53 bits
|
|
|
|
struct FILE;
|
|
typedef char* va_list;
|
|
typedef int errno_t;
|
|
struct _startupinfo
|
|
{
|
|
int newmode;
|
|
};
|
|
|
|
struct STARTUPINFOA
|
|
{
|
|
DWORD cb;
|
|
LPSTR lpReserved;
|
|
LPSTR lpDesktop;
|
|
LPSTR lpTitle;
|
|
DWORD dwX;
|
|
DWORD dwY;
|
|
DWORD dwXSize;
|
|
DWORD dwYSize;
|
|
DWORD dwXCountChars;
|
|
DWORD dwYCountChars;
|
|
DWORD dwFillAttribute;
|
|
DWORD dwFlags;
|
|
WORD wShowWindow;
|
|
WORD cbReserved2;
|
|
LPBYTE lpReserved2;
|
|
HANDLE hStdInput;
|
|
HANDLE hStdOutput;
|
|
HANDLE hStdError;
|
|
};
|
|
|
|
typedef void(__cdecl* VoidFunc)();
|
|
typedef int(__cdecl* IntFunc)();
|
|
|
|
char** gArgV = NULL;
|
|
char** gEnv = NULL;
|
|
int gArgC = 0;
|
|
bool gIsGUIApp = false;
|
|
_startupinfo gStartupInfo = { 0 };
|
|
extern "C" int _fltused = 0;
|
|
extern "C" int _tls_index = 0;
|
|
extern "C"
|
|
{
|
|
extern char* _acmdln;
|
|
extern wchar_t* _wcmdln;
|
|
}
|
|
//extern "C" extern void* _image_base;
|
|
extern "C" extern void* __ImageBase;
|
|
|
|
extern "C" int main(int argc, char** argv, char** env);
|
|
extern "C" int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, char* lpCmdLine, int nCmdShow);
|
|
extern "C" int __getmainargs(int* _Argc, char*** _Argv, char *** _Env, int _DoWildCard, _startupinfo* _StartInfo);
|
|
extern "C" void __set_app_type(int at);
|
|
extern "C" void exit(int exitCode);
|
|
extern "C" void _exit(int exitCode);
|
|
extern "C" void _cexit();
|
|
extern "C" char* _strdup(const char* str);
|
|
extern "C" int _open_osfhandle(intptr_t osfhandle, int flags);
|
|
extern "C" intptr_t __stdcall GetStdHandle(int nStdHandle);
|
|
extern "C" FILE* _fdopen(int fd, const char *mode);
|
|
extern "C" void setbuf(FILE *stream, char *buffer);
|
|
extern "C" int printf_s(const char* str, va_list arglist);
|
|
extern "C" int fprintf_s(FILE* fp, const char* str, va_list arglist);
|
|
extern "C" void free(void* ptr);
|
|
extern "C" void _clearfp();
|
|
void __cdecl terminate();
|
|
extern "C" float floorf(float val);
|
|
extern "C" double floor(double val);
|
|
extern "C" int _finite(double val);
|
|
extern "C" int _finitef(float val);
|
|
|
|
extern "C" void _initterm(VoidFunc* begin, VoidFunc* end);
|
|
extern "C" int _initterm_e(IntFunc* begin, IntFunc * end);
|
|
extern "C" errno_t _controlfp_s(unsigned int *currentControl, unsigned int newControl, unsigned int mask);
|
|
|
|
extern "C" char* __stdcall GetCommandLineA();
|
|
extern "C" wchar_t* __stdcall GetCommandLineW();
|
|
extern "C" void __stdcall GetStartupInfoA(STARTUPINFOA* lpStartupInfo);
|
|
extern "C" HMODULE LoadLibraryA(char* lpFileName);
|
|
extern "C" void* GetProcAddress(HMODULE mod, const char* name);
|
|
|
|
//extern "C" void __stdcall OutputDebugStringA(char* ptr);
|
|
|
|
#pragma section(".CRT$XCA", long, read) // First C++ Initializer
|
|
#pragma section(".CRT$XCAA", long, read) // Startup C++ Initializer
|
|
#pragma section(".CRT$XCZ", long, read) // Last C++ Initializer
|
|
|
|
#pragma section(".CRT$XDA", long, read) // First Dynamic TLS Initializer
|
|
#pragma section(".CRT$XDZ", long, read) // Last Dynamic TLS Initializer
|
|
|
|
#pragma section(".CRT$XIA", long, read) // First C Initializer
|
|
#pragma section(".CRT$XIAA", long, read) // Startup C Initializer
|
|
#pragma section(".CRT$XIAB", long, read) // PGO C Initializer
|
|
#pragma section(".CRT$XIAC", long, read) // Post-PGO C Initializer
|
|
#pragma section(".CRT$XIC", long, read) // CRT C Initializers
|
|
#pragma section(".CRT$XIYA", long, read) // VCCorLib Threading Model Initializer
|
|
#pragma section(".CRT$XIYAA", long, read) // XAML Designer Threading Model Override Initializer
|
|
#pragma section(".CRT$XIYB", long, read) // VCCorLib Main Initializer
|
|
#pragma section(".CRT$XIZ", long, read) // Last C Initializer
|
|
|
|
#pragma section(".CRT$XLA", long, read) // First Loader TLS Callback
|
|
#pragma section(".CRT$XLC", long, read) // CRT TLS Constructor
|
|
#pragma section(".CRT$XLD", long, read) // CRT TLS Terminator
|
|
#pragma section(".CRT$XLZ", long, read) // Last Loader TLS Callback
|
|
|
|
#pragma section(".CRT$XPA", long, read) // First Pre-Terminator
|
|
#pragma section(".CRT$XPB", long, read) // CRT ConcRT Pre-Terminator
|
|
#pragma section(".CRT$XPX", long, read) // CRT Pre-Terminators
|
|
#pragma section(".CRT$XPXA", long, read) // CRT stdio Pre-Terminator
|
|
#pragma section(".CRT$XPZ", long, read) // Last Pre-Terminator
|
|
|
|
#pragma section(".CRT$XTA", long, read) // First Terminator
|
|
#pragma section(".CRT$XTZ", long, read) // Last Terminator
|
|
|
|
#pragma section(".CRTMA$XCA", long, read) // First Managed C++ Initializer
|
|
#pragma section(".CRTMA$XCZ", long, read) // Last Managed C++ Initializer
|
|
|
|
#pragma section(".CRTVT$XCA", long, read) // First Managed VTable Initializer
|
|
#pragma section(".CRTVT$XCZ", long, read) // Last Managed VTable Initializer
|
|
|
|
#pragma section(".rdata$T", long, read)
|
|
|
|
#pragma section(".rtc$IAA", long, read) // First RTC Initializer
|
|
#pragma section(".rtc$IZZ", long, read) // Last RTC Initializer
|
|
|
|
#pragma section(".rtc$TAA", long, read) // First RTC Terminator
|
|
#pragma section(".rtc$TZZ", long, read) // Last RTC Terminator
|
|
|
|
#ifdef SUPPORT_TLS
|
|
#pragma section(".tls",long,read,write)
|
|
#pragma section(".tls$",long,read,write)
|
|
#pragma section(".tls$ZZZ",long,read,write)
|
|
#endif
|
|
|
|
static int __cdecl pre_c_initialization()
|
|
{
|
|
#ifdef MINRT_CONSOLE
|
|
__set_app_type(_CONSOLE_APP);
|
|
#else
|
|
__set_app_type(_GUI_APP);
|
|
#endif
|
|
|
|
#ifdef _M_IX86
|
|
_clearfp();
|
|
#endif
|
|
//__setusermatherr
|
|
|
|
#ifdef _M_IX86
|
|
_controlfp_s(nullptr, _PC_53, _MCW_PC); // _initialize_default_precision()
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
typedef void (NTAPI* PIMAGE_TLS_CALLBACK)(void* DllHandle, DWORD Reason, void* Reserved);
|
|
|
|
#define _CRTALLOC(x) __declspec(allocate(x))
|
|
_CRTALLOC(".CRT$XIAA") static IntFunc pre_c_initializer = pre_c_initialization;
|
|
|
|
extern "C" _CRTALLOC(".CRT$XIA") IntFunc __xi_a[] = { nullptr }; // C initializers (first)
|
|
extern "C" _CRTALLOC(".CRT$XIZ") IntFunc __xi_z[] = { nullptr }; // C initializers (last)
|
|
extern "C" _CRTALLOC(".CRT$XCA") VoidFunc __xc_a[] = { nullptr }; // C++ initializers (first)
|
|
extern "C" _CRTALLOC(".CRT$XCZ") VoidFunc __xc_z[] = { nullptr }; // C++ initializers (last)
|
|
extern "C" _CRTALLOC(".CRT$XPA") VoidFunc __xp_a[] = { nullptr }; // C pre-terminators (first)
|
|
extern "C" _CRTALLOC(".CRT$XPZ") VoidFunc __xp_z[] = { nullptr }; // C pre-terminators (last)
|
|
extern "C" _CRTALLOC(".CRT$XTA") VoidFunc __xt_a[] = { nullptr }; // C terminators (first)
|
|
extern "C" _CRTALLOC(".CRT$XTZ") VoidFunc __xt_z[] = { nullptr }; // C terminators (last)
|
|
|
|
extern "C" _CRTALLOC(".CRT$XDA") VoidFunc __xd_a = { nullptr };
|
|
extern "C" _CRTALLOC(".CRT$XDZ") VoidFunc __xd_z = { nullptr };
|
|
/* TLS raw template data start and end.
|
|
We use here pointer-types for start/end so that tls-data remains
|
|
aligned on pointer-size-width. This seems to be required for
|
|
pe-loader. */
|
|
|
|
#ifdef SUPPORT_TLS
|
|
extern "C" _CRTALLOC(".tls$") char* _tls_start = NULL;
|
|
extern "C" _CRTALLOC(".tls$ZZZ") char* _tls_end = NULL;
|
|
#endif
|
|
|
|
struct IMAGE_TLS_DIRECTORY
|
|
{
|
|
void* StartAddressOfRawData;
|
|
void* EndAddressOfRawData;
|
|
void* AddressOfIndex; // PDWORD
|
|
void* AddressOfCallBacks; // PIMAGE_TLS_CALLBACK *;
|
|
DWORD SizeOfZeroFill;
|
|
union {
|
|
DWORD Characteristics;
|
|
struct {
|
|
DWORD Reserved0 : 20;
|
|
DWORD Alignment : 4;
|
|
DWORD Reserved1 : 8;
|
|
} DUMMYSTRUCTNAME;
|
|
} DUMMYUNIONNAME;
|
|
};
|
|
|
|
#ifdef SUPPORT_TLS
|
|
BOOL WINAPI __dyn_tls_init(HANDLE hDllHandle, DWORD dwReason, void* lpreserved)
|
|
{
|
|
VoidFunc* ps = &__xd_a;
|
|
ps++;
|
|
for (; ps != &__xd_z; ps++)
|
|
{
|
|
if (*ps != NULL)
|
|
(*ps)();
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
const PIMAGE_TLS_CALLBACK __dyn_tls_init_callback = (const PIMAGE_TLS_CALLBACK)__dyn_tls_init;
|
|
extern "C" _CRTALLOC(".CRT$XLC") PIMAGE_TLS_CALLBACK __xl_c = (PIMAGE_TLS_CALLBACK)__dyn_tls_init;
|
|
extern "C" _CRTALLOC(".CRT$XLA") PIMAGE_TLS_CALLBACK __xl_a = 0;
|
|
extern "C" _CRTALLOC(".CRT$XLZ") PIMAGE_TLS_CALLBACK __xl_z = 0;
|
|
|
|
//extern "C" _CRTALLOC(".tls") IMAGE_TLS_DIRECTORY _tls_used = {
|
|
|
|
extern "C" IMAGE_TLS_DIRECTORY _tls_used = {
|
|
&_tls_start, &_tls_end,
|
|
&_tls_index, (&__xl_a + 1),
|
|
0, 0
|
|
};
|
|
#endif
|
|
|
|
|
|
#pragma comment(linker, "/merge:.CRT=.rdata")
|
|
|
|
FILE* gStdFiles[3];
|
|
FILE* GetStdFile(int stdHandleId, bool isIn)
|
|
{
|
|
// int fd = _open_osfhandle(GetStdHandle(stdHandleId), 0);
|
|
// if (fd == -1)
|
|
// return NULL;
|
|
// FILE* fp = _fdopen(fd, isIn ? "r" : "w");
|
|
|
|
FILE* fp = _fdopen(stdHandleId, isIn ? "r" : "w");
|
|
|
|
setbuf(fp, NULL);
|
|
return fp;
|
|
}
|
|
|
|
int Init()
|
|
{
|
|
/*gStdFiles[0] = GetStdFile(STD_INPUT_HANDLE, true);
|
|
gStdFiles[1] = GetStdFile(STD_OUTPUT_HANDLE, false);
|
|
gStdFiles[2] = GetStdFile(STD_ERROR_HANDLE, false);*/
|
|
|
|
gStdFiles[0] = GetStdFile(0, true);
|
|
gStdFiles[1] = GetStdFile(1, false);
|
|
gStdFiles[2] = GetStdFile(2, false);
|
|
|
|
int result = _initterm_e(__xi_a, __xi_z);
|
|
if (result != 0)
|
|
return result;
|
|
_initterm(__xc_a, __xc_z);
|
|
|
|
#ifdef __dyn_tls_init
|
|
if (__dyn_tls_init_callback != NULL)
|
|
__dyn_tls_init(NULL, DLL_THREAD_ATTACH, NULL);
|
|
#endif
|
|
|
|
|
|
return 0;
|
|
}
|
|
|
|
void Finish(int result)
|
|
{
|
|
_initterm(__xp_a, __xp_z);
|
|
_initterm(__xt_a, __xt_z);
|
|
|
|
exit(result);
|
|
_cexit();
|
|
}
|
|
|
|
#ifdef MINRT_CONSOLE
|
|
extern "C" int mainCRTStartup()
|
|
{
|
|
gIsGUIApp = false;
|
|
|
|
int result = Init();
|
|
if (result != 0)
|
|
return result;
|
|
|
|
__getmainargs(&gArgC, &gArgV, &gEnv, 0, &gStartupInfo);
|
|
result = main(gArgC, gArgV, gEnv);
|
|
|
|
Finish(result);
|
|
return result;
|
|
}
|
|
#else
|
|
extern "C" int WinMainCRTStartup()
|
|
{
|
|
STARTUPINFOA startupInfo;
|
|
GetStartupInfoA(&startupInfo);
|
|
|
|
int result = Init();
|
|
if (result != 0)
|
|
return result;
|
|
|
|
HINSTANCE hInstance = (HINSTANCE)&__ImageBase;
|
|
char* cmdLine = GetCommandLineA();
|
|
|
|
if (cmdLine)
|
|
{
|
|
bool inDoubleQuote = false;
|
|
while (*cmdLine > ' ' || (*cmdLine && inDoubleQuote))
|
|
{
|
|
if (*cmdLine == '"')
|
|
inDoubleQuote = !inDoubleQuote;
|
|
++cmdLine;
|
|
}
|
|
while (*cmdLine && (*cmdLine <= ' '))
|
|
cmdLine++;
|
|
}
|
|
|
|
result = WinMain(hInstance, NULL, cmdLine, startupInfo.dwFlags & STARTF_USESHOWWINDOW ?
|
|
startupInfo.wShowWindow : SW_SHOWDEFAULT);
|
|
|
|
Finish(result);
|
|
return result;
|
|
}
|
|
#endif
|
|
|
|
void __cdecl operator delete(void* val, unsigned __int64 size)
|
|
{
|
|
free(val);
|
|
}
|
|
|
|
void __cdecl operator delete(void* val, int a, const char* name, int line)
|
|
{
|
|
free(val);
|
|
}
|
|
|
|
extern "C" __declspec(dllexport) void* __cdecl _set_purecall_handler(void* _Handler)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
extern "C" __declspec(dllexport) void* __cdecl _set_invalid_parameter_handler(void* _Handler)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
extern "C" __declspec(dllexport) unsigned int __cdecl _set_abort_behavior(unsigned int _Flags, unsigned int _Mask)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
extern "C" int _vsnprintf_s_l(
|
|
char *buffer,
|
|
size_t sizeOfBuffer,
|
|
size_t count,
|
|
const char *format,
|
|
void* locale,
|
|
va_list argptr
|
|
);
|
|
|
|
typedef int (PROC_vsnprintf_s_l)(
|
|
char *buffer,
|
|
size_t sizeOfBuffer,
|
|
size_t count,
|
|
const char *format,
|
|
void* locale,
|
|
va_list argptr
|
|
);
|
|
|
|
typedef int (PROC_vfprintf_l)(
|
|
FILE *stream,
|
|
const char *format,
|
|
void* locale,
|
|
va_list argptr
|
|
);
|
|
|
|
static HMODULE gCrtLib = NULL;
|
|
void* GetCrtProc(const char* name)
|
|
{
|
|
if (gCrtLib == NULL)
|
|
gCrtLib = ::LoadLibraryA("msvcrt.dll");
|
|
return ::GetProcAddress(gCrtLib, name);
|
|
}
|
|
|
|
extern "C" __declspec(dllexport) int __cdecl __stdio_common_vsprintf(
|
|
unsigned __int64 const options,
|
|
char* const buffer,
|
|
size_t const buffer_count,
|
|
char const* const format,
|
|
void* const locale,
|
|
va_list const arglist
|
|
)
|
|
{
|
|
static PROC_vsnprintf_s_l* p_vsnprintf_s_l = (PROC_vsnprintf_s_l*)GetCrtProc("_vsnprintf_s_l");
|
|
return p_vsnprintf_s_l(buffer, buffer_count, -1, format, locale, arglist);
|
|
}
|
|
|
|
extern "C" __declspec(dllexport) int __cdecl __stdio_common_vfprintf(
|
|
unsigned __int64 const options,
|
|
FILE* const stream,
|
|
char const* const format,
|
|
void* const locale,
|
|
va_list const arglist
|
|
)
|
|
{
|
|
static PROC_vfprintf_l* p_vfprintf_l = (PROC_vfprintf_l*)GetCrtProc("_vfprintf_l");
|
|
return p_vfprintf_l(stream, format, locale, arglist);
|
|
}
|
|
|
|
extern "C" __declspec(dllexport) FILE* __cdecl __acrt_iob_func(unsigned const id)
|
|
{
|
|
return gStdFiles[id];
|
|
}
|
|
|
|
extern "C" __declspec(noreturn) void __cdecl __std_terminate()
|
|
{
|
|
terminate();
|
|
}
|
|
|
|
extern "C" __declspec(dllexport) float roundf(float val)
|
|
{
|
|
if (!_finitef(val))
|
|
{
|
|
return val;
|
|
}
|
|
else if (val >= 0)
|
|
{
|
|
float result = floorf(val);
|
|
if (result - val <= -0.5f)
|
|
result += 1.0f;
|
|
return result;
|
|
}
|
|
else
|
|
{
|
|
float result = floorf(-val);
|
|
if (result + val <= -0.5f)
|
|
result += 1.0f;
|
|
return -result;
|
|
}
|
|
}
|
|
|
|
extern "C" __declspec(dllexport) double round(double val)
|
|
{
|
|
if (!_finite(val))
|
|
{
|
|
return val;
|
|
}
|
|
else if (val >= 0)
|
|
{
|
|
double result = floor(val);
|
|
if (result - val <= -0.5)
|
|
result += 1.0;
|
|
return result;
|
|
}
|
|
else
|
|
{
|
|
double result = floor(-val);
|
|
if (result + val <= -0.5)
|
|
result += 1.0;
|
|
return -result;
|
|
}
|
|
}
|
|
|
|
extern "C" __declspec(dllexport) char* strdup(const char* str)
|
|
{
|
|
return _strdup(str);
|
|
}
|
|
|
|
extern "C" __declspec(dllexport) void __CxxFrameHandler4()
|
|
{
|
|
}
|
|
|
|
// if (TSS > _Init_thread_epoch) {
|
|
// _Init_thread_header(&TSS);
|
|
// Test our bit from the guard variable.
|
|
// if (TSS == -1) {
|
|
// ... initialize the object ...;
|
|
// _Init_thread_footer(&TSS);
|
|
// }
|
|
// }
|