2019-09-13 09:12:35 +05:30

125 lines
3.8 KiB
C

/*
* Copyright 2009 Kovid Goyal
*/
#ifndef UNICODE
#define UNICODE
#endif
#define WINDOWS_LEAN_AND_MEAN
#include<windows.h>
#include<strsafe.h>
static size_t mystrlen(const wchar_t *buf) {
size_t ans = 0;
if (FAILED(StringCbLengthW(buf, 500, &ans))) return 0;
return ans;
}
static int show_error(const wchar_t *preamble, const wchar_t *msg, const int code) {
wchar_t *buf;
buf = (wchar_t*)LocalAlloc(LMEM_ZEROINIT, sizeof(wchar_t)*
(mystrlen(msg) + mystrlen(preamble) + 80));
if (!buf) {
MessageBox(NULL, preamble, NULL, MB_OK|MB_ICONERROR);
return code;
}
MessageBeep(MB_ICONERROR);
wsprintf(buf, L"%s\r\n %s (Error Code: %d)\r\n", preamble, msg, code);
MessageBox(NULL, buf, NULL, MB_OK|MB_ICONERROR);
LocalFree(buf);
return code;
}
static int show_last_error(wchar_t *preamble) {
wchar_t *msg = NULL;
DWORD dw = GetLastError();
int ret;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dw,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPWSTR)&msg,
0,
NULL );
ret = show_error(preamble, msg, (int)dw);
if (msg != NULL) LocalFree(msg);
return ret;
}
typedef int (__cdecl *ENTRYPROC)(const char*, const char*, const char*, int);
typedef void (__cdecl *SIMPLEPRINT)(const wchar_t*);
typedef BOOL (*SETDEFAULTDIRS)(DWORD);
static ENTRYPROC entrypoint = NULL;
static SIMPLEPRINT simple_print = NULL;
static HMODULE dll = 0;
static void
load_launcher_dll() {
static wchar_t buf[MAX_PATH]; // Cannot use a zero initializer for the array as it generates an implicit call to memset()
wchar_t *dll_point = NULL;
int i = 0;
DWORD sz = 0;
if ((sz = GetModuleFileNameW(NULL, buf, MAX_PATH)) >= MAX_PATH - 30) {
show_error(L"Installation directory path too long", L"", 1);
return;
}
while (sz > 0) {
if (buf[sz] == L'\\' || buf[sz] == L'/') { dll_point = buf + sz + 1; break; }
sz--;
}
if (dll_point == NULL) {
show_error(L"Executable path has no path separators", L"", 1);
return;
}
wsprintf(dll_point, L"%s\0\0", L"app\\bin");
// Restrict the directories from which DLLs can be loaded
SETDEFAULTDIRS SetDefaultDllDirectories = (SETDEFAULTDIRS)GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "SetDefaultDllDirectories");
if (SetDefaultDllDirectories) SetDefaultDllDirectories(LOAD_LIBRARY_SEARCH_DEFAULT_DIRS);
if (SetDllDirectoryW(buf) == 0) {
show_last_error(L"Failed to set DLL directory");
return;
}
// Have to load ucrtbase manually first, otherwise loading fails on systems where the
// Universal CRT is not installed.
if (!LoadLibraryW(L"ucrtbase.dll")) {
show_last_error(L"Unable to find ucrtbase.dll. You should install all Windows updates on your computer to get this file.");
return;
}
if (!(dll = LoadLibraryW(L"calibre-launcher.dll"))) {
show_last_error(L"Failed to load: calibre-launcher.dll");
return;
}
if (!(entrypoint = (ENTRYPROC) GetProcAddress(dll, "execute_python_entrypoint"))) {
show_last_error(L"Failed to get the calibre-launcher dll entry point");
return;
}
simple_print = (SIMPLEPRINT) GetProcAddress(dll, "simple_print");
}
int __stdcall start_here() {
int ret = 0;
load_launcher_dll();
if (entrypoint) {
#ifdef GUI_APP
// This should really be returning the value set in the WM_QUIT message, but I cannot be bothered figuring out how to get that.
entrypoint(BASENAME, MODULE, FUNCTION, 1);
#else
ret = entrypoint(BASENAME, MODULE, FUNCTION, 0);
#endif
} else ret = 1;
if (dll != 0) {
FreeLibrary(dll);
dll = 0;
}
ExitProcess(ret);
return ret;
}