/* * BoltClam portable Windows launcher. * * This is a tiny GUI-subsystem bootstrap for the portable package. It finds * the runtime beside itself, starts pythonw.exe with the bundled app, and * exits immediately. It contains no product logic; the Qt application lives * in app/boltclam. * * Build (from the repository root): * zig cc -target x86_64-windows-gnu -O2 -mwindows packaging/launcher.c \ * -o build/portable/BoltClam.exe */ #define UNICODE #define _UNICODE #include #include static void fail(const wchar_t *message) { MessageBoxW(NULL, message, L"BoltClam", MB_OK | MB_ICONERROR); } int WINAPI WinMain(HINSTANCE instance, HINSTANCE previous, LPSTR command_line, int show) { (void)instance; (void)previous; (void)command_line; (void)show; wchar_t exe[MAX_PATH]; DWORD length = GetModuleFileNameW(NULL, exe, MAX_PATH); if (length == 0 || length >= MAX_PATH) { fail(L"BoltClam could not locate its own executable."); return 1; } wchar_t *slash = wcsrchr(exe, L'\\'); if (slash == NULL) { fail(L"BoltClam could not locate its runtime folder."); return 1; } *slash = L'\0'; wchar_t pythonw[MAX_PATH * 2]; _snwprintf(pythonw, MAX_PATH * 2, L"%s\\pythonw.exe", exe); if (GetFileAttributesW(pythonw) == INVALID_FILE_ATTRIBUTES) { fail(L"BoltClam's runtime is incomplete: pythonw.exe is missing.\n\n" L"Extract the whole portable folder, not just BoltClam.exe."); return 1; } wchar_t appdir[MAX_PATH * 2]; _snwprintf(appdir, MAX_PATH * 2, L"%s\\app", exe); if (GetFileAttributesW(appdir) == INVALID_FILE_ATTRIBUTES) { fail(L"BoltClam's runtime is incomplete: the app folder is missing.\n\n" L"Extract the whole portable folder, not just BoltClam.exe."); return 1; } SetCurrentDirectoryW(appdir); wchar_t cmdline[MAX_PATH * 4]; _snwprintf(cmdline, MAX_PATH * 4, L"\"%s\" -m boltclam", pythonw); STARTUPINFOW startup; PROCESS_INFORMATION process; ZeroMemory(&startup, sizeof(startup)); ZeroMemory(&process, sizeof(process)); startup.cb = sizeof(startup); if (!CreateProcessW(pythonw, cmdline, NULL, NULL, FALSE, CREATE_UNICODE_ENVIRONMENT, NULL, appdir, &startup, &process)) { wchar_t error[512]; _snwprintf(error, 512, L"BoltClam could not start its runtime (error %lu).", (unsigned long)GetLastError()); fail(error); return 1; } CloseHandle(process.hThread); CloseHandle(process.hProcess); return 0; }