|
1 /* |
|
2 * Bootloader for a packed executable. |
|
3 * Copyright (C) 2005, Giovanni Bajo |
|
4 * Based on previous work under copyright (c) 2002 McMillan Enterprises, Inc. |
|
5 * |
|
6 * This program is free software; you can redistribute it and/or |
|
7 * modify it under the terms of the GNU General Public License |
|
8 * as published by the Free Software Foundation; either version 2 |
|
9 * of the License, or (at your option) any later version. |
|
10 * |
|
11 * In addition to the permissions in the GNU General Public License, the |
|
12 * authors give you unlimited permission to link or embed the compiled |
|
13 * version of this file into combinations with other programs, and to |
|
14 * distribute those combinations without any restriction coming from the |
|
15 * use of this file. (The General Public License restrictions do apply in |
|
16 * other respects; for example, they cover modification of the file, and |
|
17 * distribution when not linked into a combine executable.) |
|
18 * |
|
19 * This program is distributed in the hope that it will be useful, |
|
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
22 * GNU General Public License for more details. |
|
23 * |
|
24 * You should have received a copy of the GNU General Public License |
|
25 * along with this program; if not, write to the Free Software |
|
26 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
|
27 */ |
|
28 #include "launch.h" |
|
29 #include <windows.h> |
|
30 #include <commctrl.h> // InitCommonControls |
|
31 #include <signal.h> |
|
32 |
|
33 int relaunch(char *thisfile, char *workpath) |
|
34 { |
|
35 char envvar[_MAX_PATH + 12]; |
|
36 SECURITY_ATTRIBUTES sa; |
|
37 STARTUPINFO si; |
|
38 PROCESS_INFORMATION pi; |
|
39 int rc = 0; |
|
40 |
|
41 // the parent process should ignore all signals it can |
|
42 signal(SIGABRT, SIG_IGN); |
|
43 signal(SIGINT, SIG_IGN); |
|
44 signal(SIGTERM, SIG_IGN); |
|
45 signal(SIGBREAK, SIG_IGN); |
|
46 |
|
47 VS("Setting up to run child\n"); |
|
48 sa.nLength = sizeof(sa); |
|
49 sa.lpSecurityDescriptor = NULL; |
|
50 sa.bInheritHandle = TRUE; |
|
51 GetStartupInfo(&si); |
|
52 si.lpReserved = NULL; |
|
53 si.lpDesktop = NULL; |
|
54 si.lpTitle = NULL; |
|
55 si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; |
|
56 si.wShowWindow = SW_NORMAL; |
|
57 si.hStdInput = (void*)_get_osfhandle(fileno(stdin)); |
|
58 si.hStdOutput = (void*)_get_osfhandle(fileno(stdout)); |
|
59 si.hStdError = (void*)_get_osfhandle(fileno(stderr)); |
|
60 /* tell pass 2 where we extracted to */ |
|
61 VS("Setting magic environment var\n"); |
|
62 strcpy(envvar, "_MEIPASS2="); |
|
63 strcat(envvar, workpath); |
|
64 _putenv(envvar); |
|
65 VS("Creating child process\n"); |
|
66 if (CreateProcess( |
|
67 thisfile, // pointer to name of executable module |
|
68 GetCommandLine(), // pointer to command line string |
|
69 &sa, // pointer to process security attributes |
|
70 NULL, // pointer to thread security attributes |
|
71 TRUE, // handle inheritance flag |
|
72 0, // creation flags |
|
73 NULL, // pointer to new environment block |
|
74 NULL, // pointer to current directory name |
|
75 &si, // pointer to STARTUPINFO |
|
76 &pi // pointer to PROCESS_INFORMATION |
|
77 )) { |
|
78 VS("Waiting for child process to finish...\n"); |
|
79 WaitForSingleObject(pi.hProcess, INFINITE); |
|
80 GetExitCodeProcess(pi.hProcess, (unsigned long *)&rc); |
|
81 } |
|
82 else { |
|
83 FATALERROR("Error creating child process!\n"); |
|
84 rc = -1; |
|
85 } |
|
86 return rc; |
|
87 } |
|
88 |
|
89 |
|
90 #ifdef _CONSOLE |
|
91 int main(int argc, char* argv[]) |
|
92 #else |
|
93 int APIENTRY WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, |
|
94 LPSTR lpCmdLine, int nCmdShow ) |
|
95 #endif |
|
96 { |
|
97 char here[_MAX_PATH + 1]; |
|
98 char thisfile[_MAX_PATH + 1]; |
|
99 int rc = 0; |
|
100 char *workpath = NULL; |
|
101 char *p; |
|
102 int len; |
|
103 #ifndef _CONSOLE |
|
104 int argc = __argc; |
|
105 char **argv = __argv; |
|
106 #endif |
|
107 |
|
108 // Initialize common controls (needed to link with commctrl32.dll and |
|
109 // obtain native XP look & feel). |
|
110 InitCommonControls(); |
|
111 |
|
112 // fill in thisfile |
|
113 if (!GetModuleFileNameA(NULL, thisfile, _MAX_PATH)) { |
|
114 FATALERROR("System error - unable to load!"); |
|
115 return -1; |
|
116 } |
|
117 p = thisfile+strlen(thisfile) - 4; |
|
118 if (strnicmp(p, ".exe", 4) != 0) |
|
119 strcat(thisfile, ".exe"); |
|
120 |
|
121 // fill in here (directory of thisfile) |
|
122 //GetModuleFileName returns an absolute path |
|
123 strcpy(here, thisfile); |
|
124 for (p=here+strlen(here); *p != '\\' && p >= here+2; --p); |
|
125 *++p = '\0'; |
|
126 len = p - here; |
|
127 |
|
128 workpath = getenv( "_MEIPASS2" ); |
|
129 rc = init(here, &thisfile[len], workpath); |
|
130 if (rc) |
|
131 return rc; |
|
132 if (workpath) { |
|
133 // we're the "child" process |
|
134 rc = doIt(argc, argv); |
|
135 finalizePython(); |
|
136 } |
|
137 else { |
|
138 if (extractBinaries(&workpath)) { |
|
139 VS("Error extracting binaries"); |
|
140 return -1; |
|
141 } |
|
142 // if workpath got set to non-NULL, we've extracted stuff |
|
143 if (workpath) { |
|
144 // run the "child" process, then clean up |
|
145 rc = relaunch(thisfile, workpath); |
|
146 } |
|
147 else { |
|
148 // no "child" process necessary |
|
149 rc = doIt(argc, argv); |
|
150 finalizePython(); |
|
151 } |
|
152 cleanUp(); |
|
153 } |
|
154 return rc; |
|
155 } |