mirror of
https://github.com/kennethreitz-archive/pyinstaller.git
synced 2026-06-05 23:50:17 +00:00
680572bde4
later look for an external PKG file. This follows PyInstaller's convention of allowing external files (even .py file) if not found within the archive. Moreover, it also allow not to circumvent digital signing too easily. git-svn-id: http://svn.pyinstaller.org/trunk@648 8dd32b29-ccff-0310-8a9a-9233e24343b1
185 lines
5.5 KiB
C
185 lines
5.5 KiB
C
/*
|
|
* 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 <windows.h>
|
|
#include <commctrl.h> // InitCommonControls
|
|
#include <signal.h>
|
|
|
|
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, &thisfile[len], workpath);
|
|
if (rc) {
|
|
rc = init(here, &pkgfile[len], workpath);
|
|
if (rc)
|
|
return rc;
|
|
VS("Found separate PKG: %s\n", pkgfile);
|
|
} else {
|
|
VS("Found embedded PKG: %s\n", thisfile);
|
|
}
|
|
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;
|
|
}
|