/* * Bootloader for a packed executable. * Copyright (C) 2005, Giovanni Bajo * Based on previous work under copyright (c) 2002 McMillan Enterprises, Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * In addition to the permissions in the GNU General Public License, the * authors give you unlimited permission to link or embed the compiled * version of this file into combinations with other programs, and to * distribute those combinations without any restriction coming from the * use of this file. (The General Public License restrictions do apply in * other respects; for example, they cover modification of the file, and * distribution when not linked into a combine executable.) * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #include "launch.h" #include #include // InitCommonControls #include int relaunch(LPWSTR thisfile, char *workpath) { char envvar[_MAX_PATH + 12]; SECURITY_ATTRIBUTES sa; STARTUPINFOW si; PROCESS_INFORMATION pi; int rc = 0; // the parent process should ignore all signals it can signal(SIGABRT, SIG_IGN); signal(SIGINT, SIG_IGN); signal(SIGTERM, SIG_IGN); signal(SIGBREAK, SIG_IGN); VS("Setting up to run child\n"); sa.nLength = sizeof(sa); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = TRUE; GetStartupInfoW(&si); si.lpReserved = NULL; si.lpDesktop = NULL; si.lpTitle = NULL; si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; si.wShowWindow = SW_NORMAL; si.hStdInput = (void*)_get_osfhandle(fileno(stdin)); si.hStdOutput = (void*)_get_osfhandle(fileno(stdout)); si.hStdError = (void*)_get_osfhandle(fileno(stderr)); /* tell pass 2 where we extracted to */ VS("Setting magic environment var\n"); strcpy(envvar, "_MEIPASS2="); strcat(envvar, workpath); _putenv(envvar); VS("Creating child process\n"); // Use wide-string version to make sure that the command line is // passed properly: in fact, the locale-specific version (GetCommandLineA()) // might not be able to decode it fully and thus contain replacement // characters ("?"). // This is actually immaterial right now because Python itself has a bug // and uses only the locale-specific version which is corrupted; but at // least it's not here that we lose information. if (CreateProcessW( thisfile, // pointer to name of executable module GetCommandLineW(), // pointer to command line string &sa, // pointer to process security attributes NULL, // pointer to thread security attributes TRUE, // handle inheritance flag 0, // creation flags NULL, // pointer to new environment block NULL, // pointer to current directory name &si, // pointer to STARTUPINFO &pi // pointer to PROCESS_INFORMATION )) { VS("Waiting for child process to finish...\n"); WaitForSingleObject(pi.hProcess, INFINITE); GetExitCodeProcess(pi.hProcess, (unsigned long *)&rc); } else { FATALERROR("Error creating child process!\n"); rc = -1; } return rc; } #ifdef _CONSOLE int main(int argc, char* argv[]) #else int APIENTRY WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) #endif { char here[_MAX_PATH + 1]; char thisfile[_MAX_PATH + 1]; WCHAR thisfilew[_MAX_PATH + 1]; char pkgfile[_MAX_PATH + 1]; int rc = 0; char *workpath = NULL; char *p; int len; #ifndef _CONSOLE int argc = __argc; char **argv = __argv; #endif // Initialize common controls (needed to link with commctrl32.dll and // obtain native XP look & feel). InitCommonControls(); // fill in thisfile if (!GetModuleFileNameA(NULL, thisfile, _MAX_PATH)) { FATALERROR("System error - unable to load!"); return -1; } if (!GetModuleFileNameW(NULL, thisfilew, _MAX_PATH)) { FATALERROR("System error - unable to load!"); return -1; } p = thisfile+strlen(thisfile) - 4; if (strnicmp(p, ".exe", 4) != 0) strcat(thisfile, ".exe"); // fill in here (directory of thisfile) //GetModuleFileName returns an absolute path strcpy(here, thisfile); for (p=here+strlen(here); *p != '\\' && p >= here+2; --p); *++p = '\0'; len = p - here; strcpy(pkgfile, thisfile); strcpy(pkgfile+strlen(pkgfile)-3, "pkg"); workpath = getenv( "_MEIPASS2" ); rc = init(here, &pkgfile[len], workpath); if (rc) { rc = init(here, &thisfile[len], workpath); } else { VS("Found separate PKG: %s\n", pkgfile); } if (rc) { return rc; } if (workpath) { // we're the "child" process rc = doIt(argc, argv); if (rc) { return rc; } finalizePython(); } else { if (extractBinaries(&workpath)) { VS("Error extracting binaries\n"); return -1; } // if workpath got set to non-NULL, we've extracted stuff if (workpath) { // run the "child" process, then clean up rc = relaunch(thisfilew, workpath); } else { // no "child" process necessary rc = doIt(argc, argv); if (rc) { return rc; } finalizePython(); } cleanUp(); } return rc; }