]>
Commit | Line | Data |
---|---|---|
2b734ec7 | 1 | /* |
23c9e63c | 2 | * Copyright (c) 2000, Red Hat, Inc. |
e46e15bf | 3 | * Copyright (c) 2003, Robert Collins <rbtcollins@hotmail.com> |
23c9e63c DD |
4 | * |
5 | * This program is free software; you can redistribute it and/or modify | |
6 | * it under the terms of the GNU General Public License as published by | |
7 | * the Free Software Foundation; either version 2 of the License, or | |
8 | * (at your option) any later version. | |
9 | * | |
10 | * A copy of the GNU General Public License can be found at | |
11 | * http://www.gnu.org/ | |
12 | * | |
13 | * Written by DJ Delorie <dj@cygnus.com> | |
e46e15bf RC |
14 | * Robert Collins <rbtcollins@hotmail.com> |
15 | * | |
23c9e63c DD |
16 | * |
17 | */ | |
18 | ||
19 | /* OK, here's how this works. Each of the steps needed for install - | |
20 | dialogs, downloads, installs - are in their own files and have some | |
21 | "do_*" function (prototype in dialog.h) and a resource id (IDD_* or | |
22 | IDD_S_* in resource.h) for that step. Each step is responsible for | |
23 | selecting the next step! See the NEXT macro in dialog.h. Note | |
24 | that the IDD_S_* ids are fake; those are for steps that don't | |
25 | really have a controlling dialog (some have progress dialogs, but | |
26 | those don't count, although they could). Replace the IDD_S_* with | |
27 | IDD_* if you create a real dialog for those steps. */ | |
28 | ||
b24c88b3 RC |
29 | #if 0 |
30 | static const char *cvsid = | |
31 | "\n%%% $Id$\n"; | |
32 | #endif | |
8507f105 | 33 | |
c8356810 CF |
34 | #undef _WIN32_WINNT |
35 | #define _WIN32_WINNT 0x0501 | |
e36b0f1e | 36 | #define CINTERFACE |
23c9e63c | 37 | #include "win32.h" |
ab57ceaa | 38 | #include <commctrl.h> |
e36b0f1e | 39 | #include "shlobj.h" |
23c9e63c DD |
40 | |
41 | #include <stdio.h> | |
89b1a15b | 42 | #include <stdlib.h> |
23c9e63c DD |
43 | #include "resource.h" |
44 | #include "dialog.h" | |
45 | #include "state.h" | |
46 | #include "msg.h" | |
23c9e63c DD |
47 | #include "find.h" |
48 | #include "mount.h" | |
9f4a0c62 | 49 | #include "LogFile.h" |
2b734ec7 | 50 | #include "setup_version.h" |
89b1a15b | 51 | |
ab57ceaa RC |
52 | #include "proppage.h" |
53 | #include "propsheet.h" | |
54 | ||
55 | // Page class headers | |
56 | #include "splash.h" | |
f9e903a3 | 57 | #include "AntiVirus.h" |
ab57ceaa RC |
58 | #include "source.h" |
59 | #include "root.h" | |
60 | #include "localdir.h" | |
61 | #include "net.h" | |
62 | #include "site.h" | |
63 | #include "choose.h" | |
82306ac2 | 64 | #include "prereq.h" |
ab57ceaa RC |
65 | #include "threebar.h" |
66 | #include "desktop.h" | |
1f24c3e4 | 67 | #include "postinstallresults.h" |
23c9e63c | 68 | |
6908b7d7 | 69 | #include "getopt++/GetOption.h" |
f2ff9838 | 70 | #include "getopt++/BoolOption.h" |
1be8f8fd | 71 | |
072fb49a MB |
72 | #include "Exception.h" |
73 | #include <stdexcept> | |
74 | ||
f26f525f CF |
75 | #include "UserSettings.h" |
76 | #include "SourceSetting.h" | |
77 | #include "ConnectionSetting.h" | |
78 | #include "KeysSetting.h" | |
79 | ||
c8356810 CF |
80 | #include <wincon.h> |
81 | #include <fstream> | |
82 | ||
072fb49a | 83 | using namespace std; |
0df9be37 | 84 | |
23c9e63c | 85 | HINSTANCE hinstance; |
4ea94dbb | 86 | bool is_legacy; |
23c9e63c | 87 | |
f2ff9838 | 88 | static BoolOption UnattendedOption (false, 'q', "quiet-mode", "Unattended setup mode"); |
7a4e611a | 89 | static BoolOption PackageManagerOption (false, 'M', "package-manager", "Semi-attended chooser-only mode"); |
c9feb168 | 90 | static BoolOption HelpOption (false, 'h', "help", "print help"); |
89216328 CF |
91 | static BOOL WINAPI (*dyn_AttachConsole) (DWORD); |
92 | static BOOL WINAPI (*dyn_GetLongPathName) (LPCTSTR, LPTSTR, DWORD); | |
93 | ||
94 | ||
95 | static void inline | |
96 | set_dynaddr () | |
97 | { | |
98 | HMODULE hm = LoadLibrary ("kernel32.dll"); | |
99 | if (!hm) | |
100 | return; | |
101 | ||
102 | dyn_AttachConsole = (BOOL WINAPI (*)(DWORD)) GetProcAddress (hm, "AttachConsole"); | |
103 | dyn_GetLongPathName = (BOOL WINAPI (*)(LPCTSTR, LPTSTR, DWORD)) GetProcAddress (hm, "GetLongPathNameA"); | |
104 | } | |
f2ff9838 | 105 | |
c8356810 CF |
106 | static void inline |
107 | set_cout () | |
108 | { | |
0188fce5 CF |
109 | HANDLE my_stdout = GetStdHandle (STD_OUTPUT_HANDLE); |
110 | if (my_stdout != INVALID_HANDLE_VALUE && GetFileType (my_stdout) != FILE_TYPE_UNKNOWN) | |
0cbac692 | 111 | return; |
0188fce5 | 112 | |
0188fce5 | 113 | if (dyn_AttachConsole && dyn_AttachConsole ((DWORD) -1)) |
e0fd9bd3 | 114 | { |
0188fce5 CF |
115 | ofstream *conout = new ofstream ("conout$"); |
116 | cout.rdbuf (conout->rdbuf ()); | |
117 | cout.flush (); | |
e0fd9bd3 | 118 | } |
c8356810 CF |
119 | } |
120 | ||
1f24c3e4 | 121 | // Other threads talk to these pages, so we need to have it externable. |
ab57ceaa | 122 | ThreeBarProgressPage Progress; |
1f24c3e4 | 123 | PostInstallResultsPage PostInstallResults; |
ab57ceaa | 124 | |
9f4a0c62 RC |
125 | // This is a little ugly, but the decision about where to log occurs |
126 | // after the source is set AND the root mount obtained | |
127 | // so we make the actual logger available to the appropriate routine(s). | |
a55c8f45 | 128 | LogFile *theLog; |
9f4a0c62 | 129 | |
f26f525f CF |
130 | static inline void |
131 | main_display () | |
132 | { | |
133 | /* nondisplay classes */ | |
134 | LocalDirSetting localDir; | |
135 | SourceSetting SourceSettings; | |
136 | ConnectionSetting ConnectionSettings; | |
137 | SiteSetting ChosenSites; | |
138 | ExtraKeysSetting ExtraKeys; | |
139 | ||
140 | SplashPage Splash; | |
141 | AntiVirusPage AntiVirus; | |
142 | SourcePage Source; | |
143 | RootPage Root; | |
144 | LocalDirPage LocalDir; | |
145 | NetPage Net; | |
146 | SitePage Site; | |
147 | ChooserPage Chooser; | |
148 | PrereqPage Prereq; | |
149 | DesktopSetupPage Desktop; | |
150 | PropSheet MainWindow; | |
151 | ||
152 | log (LOG_TIMESTAMP) << "Current Directory: " << local_dir << endLog; | |
153 | ||
154 | if (HelpOption) | |
155 | { | |
156 | GetOption::GetInstance ().ParameterUsage (log (LOG_PLAIN) | |
157 | << "\nCommand Line Options:\n"); | |
158 | theLog->exit (0); | |
159 | } | |
160 | ||
161 | /* Set the default DACL and Group only on NT/W2K. 9x/ME has | |
162 | no idea of access control lists and security at all. */ | |
163 | if (IsWindowsNT ()) | |
164 | nt_sec.setDefaultSecurity (); | |
165 | ||
166 | // Initialize common controls | |
e36b0f1e CV |
167 | INITCOMMONCONTROLSEX icce = { sizeof (INITCOMMONCONTROLSEX), |
168 | ICC_WIN95_CLASSES }; | |
169 | InitCommonControlsEx (&icce); | |
170 | ||
171 | // Initialize COM and ShellLink instance here. For some reason | |
172 | // Windows 7 fails to create the ShellLink instance if this is | |
173 | // done later, in the thread which actually creates the shortcuts. | |
174 | extern IShellLink *sl; | |
9e11837b | 175 | CoInitializeEx (NULL, COINIT_APARTMENTTHREADED); |
e36b0f1e CV |
176 | HRESULT res = CoCreateInstance (&CLSID_ShellLink, NULL, |
177 | CLSCTX_INPROC_SERVER, &IID_IShellLink, | |
178 | (LPVOID *) & sl); | |
179 | if (res) | |
180 | { | |
181 | char buf[256]; | |
182 | sprintf (buf, "CoCreateInstance failed with error %p.\n" | |
183 | "Setup will not be able to create Cygwin Icons\n" | |
184 | "in the Start Menu or on the Desktop.", (void *) res); | |
3e805913 | 185 | MessageBox (NULL, buf, "Cygwin Setup", MB_OK); |
e36b0f1e | 186 | } |
f26f525f CF |
187 | |
188 | // Init window class lib | |
189 | Window::SetAppInstance (hinstance); | |
190 | ||
191 | // Create pages | |
192 | Splash.Create (); | |
193 | AntiVirus.Create (); | |
194 | Source.Create (); | |
195 | Root.Create (); | |
196 | LocalDir.Create (); | |
197 | Net.Create (); | |
198 | Site.Create (); | |
199 | Chooser.Create (); | |
200 | Prereq.Create (); | |
201 | Progress.Create (); | |
1f24c3e4 | 202 | PostInstallResults.Create (); |
f26f525f CF |
203 | Desktop.Create (); |
204 | ||
205 | // Add pages to sheet | |
206 | MainWindow.AddPage (&Splash); | |
207 | MainWindow.AddPage (&AntiVirus); | |
208 | MainWindow.AddPage (&Source); | |
209 | MainWindow.AddPage (&Root); | |
210 | MainWindow.AddPage (&LocalDir); | |
211 | MainWindow.AddPage (&Net); | |
212 | MainWindow.AddPage (&Site); | |
213 | MainWindow.AddPage (&Chooser); | |
214 | MainWindow.AddPage (&Prereq); | |
215 | MainWindow.AddPage (&Progress); | |
1f24c3e4 | 216 | MainWindow.AddPage (&PostInstallResults); |
f26f525f CF |
217 | MainWindow.AddPage (&Desktop); |
218 | ||
219 | // Create the PropSheet main window | |
220 | MainWindow.Create (); | |
e36b0f1e CV |
221 | |
222 | // Uninitalize COM | |
223 | if (sl) | |
224 | sl->lpVtbl->Release (sl); | |
225 | CoUninitialize (); | |
f26f525f CF |
226 | } |
227 | ||
4ea94dbb CF |
228 | static void |
229 | set_legacy (const char *command) | |
230 | { | |
89216328 CF |
231 | char buf[MAX_PATH + 1]; |
232 | if (strchr (command, '~') == NULL || !dyn_GetLongPathName | |
233 | || !dyn_GetLongPathName (command, buf, MAX_PATH)) | |
234 | { | |
235 | strncpy (buf, command, MAX_PATH); | |
236 | buf[MAX_PATH] = '\0'; | |
237 | } | |
4ea94dbb CF |
238 | strlwr (buf); |
239 | is_legacy = strstr (buf, "setup-legacy"); | |
240 | } | |
241 | ||
45e01f23 | 242 | #ifndef __CYGWIN__ |
23c9e63c | 243 | int WINAPI |
1fd6d0a2 | 244 | WinMain (HINSTANCE h, |
b24c88b3 | 245 | HINSTANCE hPrevInstance, LPSTR command_line, int cmd_show) |
23c9e63c | 246 | { |
8bb9dad9 | 247 | |
23c9e63c | 248 | hinstance = h; |
45e01f23 RC |
249 | #else |
250 | int | |
251 | main (int argc, char **argv) | |
252 | { | |
253 | hinstance = GetModuleHandle (NULL); | |
254 | #endif | |
23c9e63c | 255 | |
89216328 | 256 | set_dynaddr (); |
3e805913 CV |
257 | // Make sure the C runtime functions use the same codepage as the GUI |
258 | char locale[12]; | |
259 | snprintf(locale, sizeof locale, ".%u", GetACP()); | |
260 | setlocale(LC_ALL, locale); | |
261 | ||
4ea94dbb CF |
262 | set_legacy (_argv[0]); |
263 | ||
264 | if (is_legacy && IsWindowsNT ()) | |
265 | { | |
266 | if (MessageBox (NULL, | |
267 | "You are attempting to install a legacy version of Cygwin\n" | |
268 | "on a modern version of Windows. Press \"OK\" if this is\n" | |
269 | "really want you want to do. Otherwise press \"Cancel\".\n" | |
270 | "See http://cygwin.com/ for more information.", | |
271 | "Attempt to install legacy version of Cygwin", | |
272 | MB_OKCANCEL | MB_ICONSTOP | MB_SETFOREGROUND | MB_TOPMOST) | |
273 | == IDCANCEL) | |
274 | return 1; | |
275 | } | |
276 | else if (!is_legacy && !IsWindowsNT ()) | |
a5405502 CV |
277 | { |
278 | MessageBox (NULL, | |
279 | "Cygwin 1.7 and later does not run on Windows 95,\n" | |
280 | "Windows 98, or Windows Me. If you want to install Cygwin\n" | |
281 | "on one of these systems, please install an older version.\n" | |
282 | "See http://cygwin.com/ for more information.", | |
4ea94dbb | 283 | "Unsupported version of Windows detected", |
a5405502 CV |
284 | MB_OK | MB_ICONSTOP | MB_SETFOREGROUND | MB_TOPMOST); |
285 | return 1; | |
286 | } | |
287 | ||
072fb49a | 288 | try { |
5072c0bb | 289 | char cwd[MAX_PATH]; |
4875ac88 | 290 | GetCurrentDirectory (MAX_PATH, cwd); |
08678720 | 291 | local_dir = std::string (cwd); |
072fb49a | 292 | |
c66b9174 MB |
293 | // TODO: make an equivalent for __argv under cygwin. |
294 | char **_argv; | |
295 | #ifndef __CYGWIN__ | |
296 | int argc; | |
5072c0bb BD |
297 | for (argc = 0, _argv = __argv; *_argv; _argv++) |
298 | ++argc; | |
c66b9174 MB |
299 | _argv = __argv; |
300 | #else | |
301 | _argv = argv; | |
302 | #endif | |
303 | ||
5072c0bb BD |
304 | if (!GetOption::GetInstance ().Process (argc,_argv, NULL)) |
305 | exit (1); | |
c66b9174 | 306 | |
7a4e611a DK |
307 | unattended_mode = PackageManagerOption ? chooseronly |
308 | : (UnattendedOption ? unattended : attended); | |
309 | ||
c8356810 CF |
310 | if (unattended_mode || HelpOption) |
311 | set_cout (); | |
312 | ||
5072c0bb | 313 | LogSingleton::SetInstance (*(theLog = LogFile::createLogFile ())); |
4d10ec8c CV |
314 | const char *sep = isdirsep (local_dir[local_dir.size () - 1]) ? "" : "\\"; |
315 | theLog->setFile (LOG_BABBLE, local_dir + sep + "setup.log.full", false); | |
316 | theLog->setFile (0, local_dir + sep + "setup.log", true); | |
072fb49a | 317 | |
5072c0bb BD |
318 | log (LOG_PLAIN) << "Starting cygwin install, version " |
319 | << setup_version << endLog; | |
072fb49a | 320 | |
f26f525f | 321 | UserSettings Settings (local_dir); |
072fb49a | 322 | |
f26f525f | 323 | main_display (); |
072fb49a | 324 | |
f26f525f | 325 | Settings.save (); // Clean exit.. save user options. |
b24c88b3 | 326 | |
0407753c DK |
327 | if (rebootneeded) |
328 | { | |
329 | theLog->exit (IDS_REBOOT_REQUIRED); | |
330 | } | |
331 | else | |
332 | { | |
333 | theLog->exit (0); | |
334 | } | |
c9feb168 | 335 | } |
072fb49a | 336 | TOPLEVEL_CATCH("main"); |
c9feb168 | 337 | |
072fb49a | 338 | // Never reached |
b24c88b3 | 339 | return 0; |
23c9e63c | 340 | } |