]>
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" | |
23c9e63c | 67 | |
6908b7d7 | 68 | #include "getopt++/GetOption.h" |
f2ff9838 | 69 | #include "getopt++/BoolOption.h" |
1be8f8fd | 70 | |
072fb49a MB |
71 | #include "Exception.h" |
72 | #include <stdexcept> | |
73 | ||
f26f525f CF |
74 | #include "UserSettings.h" |
75 | #include "SourceSetting.h" | |
76 | #include "ConnectionSetting.h" | |
77 | #include "KeysSetting.h" | |
78 | ||
c8356810 CF |
79 | #include <wincon.h> |
80 | #include <fstream> | |
81 | ||
072fb49a | 82 | using namespace std; |
0df9be37 | 83 | |
23c9e63c | 84 | HINSTANCE hinstance; |
4ea94dbb | 85 | bool is_legacy; |
23c9e63c | 86 | |
f2ff9838 | 87 | static BoolOption UnattendedOption (false, 'q', "quiet-mode", "Unattended setup mode"); |
7a4e611a | 88 | static BoolOption PackageManagerOption (false, 'M', "package-manager", "Semi-attended chooser-only mode"); |
c9feb168 | 89 | static BoolOption HelpOption (false, 'h', "help", "print help"); |
89216328 CF |
90 | static BOOL WINAPI (*dyn_AttachConsole) (DWORD); |
91 | static BOOL WINAPI (*dyn_GetLongPathName) (LPCTSTR, LPTSTR, DWORD); | |
92 | ||
93 | ||
94 | static void inline | |
95 | set_dynaddr () | |
96 | { | |
97 | HMODULE hm = LoadLibrary ("kernel32.dll"); | |
98 | if (!hm) | |
99 | return; | |
100 | ||
101 | dyn_AttachConsole = (BOOL WINAPI (*)(DWORD)) GetProcAddress (hm, "AttachConsole"); | |
102 | dyn_GetLongPathName = (BOOL WINAPI (*)(LPCTSTR, LPTSTR, DWORD)) GetProcAddress (hm, "GetLongPathNameA"); | |
103 | } | |
f2ff9838 | 104 | |
c8356810 CF |
105 | static void inline |
106 | set_cout () | |
107 | { | |
0188fce5 CF |
108 | HANDLE my_stdout = GetStdHandle (STD_OUTPUT_HANDLE); |
109 | if (my_stdout != INVALID_HANDLE_VALUE && GetFileType (my_stdout) != FILE_TYPE_UNKNOWN) | |
0cbac692 | 110 | return; |
0188fce5 | 111 | |
0188fce5 | 112 | if (dyn_AttachConsole && dyn_AttachConsole ((DWORD) -1)) |
e0fd9bd3 | 113 | { |
0188fce5 CF |
114 | ofstream *conout = new ofstream ("conout$"); |
115 | cout.rdbuf (conout->rdbuf ()); | |
116 | cout.flush (); | |
e0fd9bd3 | 117 | } |
c8356810 CF |
118 | } |
119 | ||
ab57ceaa RC |
120 | // Other threads talk to this page, so we need to have it externable. |
121 | ThreeBarProgressPage Progress; | |
122 | ||
9f4a0c62 RC |
123 | // This is a little ugly, but the decision about where to log occurs |
124 | // after the source is set AND the root mount obtained | |
125 | // so we make the actual logger available to the appropriate routine(s). | |
a55c8f45 | 126 | LogFile *theLog; |
9f4a0c62 | 127 | |
f26f525f CF |
128 | static inline void |
129 | main_display () | |
130 | { | |
131 | /* nondisplay classes */ | |
132 | LocalDirSetting localDir; | |
133 | SourceSetting SourceSettings; | |
134 | ConnectionSetting ConnectionSettings; | |
135 | SiteSetting ChosenSites; | |
136 | ExtraKeysSetting ExtraKeys; | |
137 | ||
138 | SplashPage Splash; | |
139 | AntiVirusPage AntiVirus; | |
140 | SourcePage Source; | |
141 | RootPage Root; | |
142 | LocalDirPage LocalDir; | |
143 | NetPage Net; | |
144 | SitePage Site; | |
145 | ChooserPage Chooser; | |
146 | PrereqPage Prereq; | |
147 | DesktopSetupPage Desktop; | |
148 | PropSheet MainWindow; | |
149 | ||
150 | log (LOG_TIMESTAMP) << "Current Directory: " << local_dir << endLog; | |
151 | ||
152 | if (HelpOption) | |
153 | { | |
154 | GetOption::GetInstance ().ParameterUsage (log (LOG_PLAIN) | |
155 | << "\nCommand Line Options:\n"); | |
156 | theLog->exit (0); | |
157 | } | |
158 | ||
159 | /* Set the default DACL and Group only on NT/W2K. 9x/ME has | |
160 | no idea of access control lists and security at all. */ | |
161 | if (IsWindowsNT ()) | |
162 | nt_sec.setDefaultSecurity (); | |
163 | ||
164 | // Initialize common controls | |
e36b0f1e CV |
165 | INITCOMMONCONTROLSEX icce = { sizeof (INITCOMMONCONTROLSEX), |
166 | ICC_WIN95_CLASSES }; | |
167 | InitCommonControlsEx (&icce); | |
168 | ||
169 | // Initialize COM and ShellLink instance here. For some reason | |
170 | // Windows 7 fails to create the ShellLink instance if this is | |
171 | // done later, in the thread which actually creates the shortcuts. | |
172 | extern IShellLink *sl; | |
9e11837b | 173 | CoInitializeEx (NULL, COINIT_APARTMENTTHREADED); |
e36b0f1e CV |
174 | HRESULT res = CoCreateInstance (&CLSID_ShellLink, NULL, |
175 | CLSCTX_INPROC_SERVER, &IID_IShellLink, | |
176 | (LPVOID *) & sl); | |
177 | if (res) | |
178 | { | |
179 | char buf[256]; | |
180 | sprintf (buf, "CoCreateInstance failed with error %p.\n" | |
181 | "Setup will not be able to create Cygwin Icons\n" | |
182 | "in the Start Menu or on the Desktop.", (void *) res); | |
3e805913 | 183 | MessageBox (NULL, buf, "Cygwin Setup", MB_OK); |
e36b0f1e | 184 | } |
f26f525f CF |
185 | |
186 | // Init window class lib | |
187 | Window::SetAppInstance (hinstance); | |
188 | ||
189 | // Create pages | |
190 | Splash.Create (); | |
191 | AntiVirus.Create (); | |
192 | Source.Create (); | |
193 | Root.Create (); | |
194 | LocalDir.Create (); | |
195 | Net.Create (); | |
196 | Site.Create (); | |
197 | Chooser.Create (); | |
198 | Prereq.Create (); | |
199 | Progress.Create (); | |
200 | Desktop.Create (); | |
201 | ||
202 | // Add pages to sheet | |
203 | MainWindow.AddPage (&Splash); | |
204 | MainWindow.AddPage (&AntiVirus); | |
205 | MainWindow.AddPage (&Source); | |
206 | MainWindow.AddPage (&Root); | |
207 | MainWindow.AddPage (&LocalDir); | |
208 | MainWindow.AddPage (&Net); | |
209 | MainWindow.AddPage (&Site); | |
210 | MainWindow.AddPage (&Chooser); | |
211 | MainWindow.AddPage (&Prereq); | |
212 | MainWindow.AddPage (&Progress); | |
213 | MainWindow.AddPage (&Desktop); | |
214 | ||
215 | // Create the PropSheet main window | |
216 | MainWindow.Create (); | |
e36b0f1e CV |
217 | |
218 | // Uninitalize COM | |
219 | if (sl) | |
220 | sl->lpVtbl->Release (sl); | |
221 | CoUninitialize (); | |
f26f525f CF |
222 | } |
223 | ||
4ea94dbb CF |
224 | static void |
225 | set_legacy (const char *command) | |
226 | { | |
89216328 CF |
227 | char buf[MAX_PATH + 1]; |
228 | if (strchr (command, '~') == NULL || !dyn_GetLongPathName | |
229 | || !dyn_GetLongPathName (command, buf, MAX_PATH)) | |
230 | { | |
231 | strncpy (buf, command, MAX_PATH); | |
232 | buf[MAX_PATH] = '\0'; | |
233 | } | |
4ea94dbb CF |
234 | strlwr (buf); |
235 | is_legacy = strstr (buf, "setup-legacy"); | |
236 | } | |
237 | ||
45e01f23 | 238 | #ifndef __CYGWIN__ |
23c9e63c | 239 | int WINAPI |
1fd6d0a2 | 240 | WinMain (HINSTANCE h, |
b24c88b3 | 241 | HINSTANCE hPrevInstance, LPSTR command_line, int cmd_show) |
23c9e63c | 242 | { |
8bb9dad9 | 243 | |
23c9e63c | 244 | hinstance = h; |
45e01f23 RC |
245 | #else |
246 | int | |
247 | main (int argc, char **argv) | |
248 | { | |
249 | hinstance = GetModuleHandle (NULL); | |
250 | #endif | |
23c9e63c | 251 | |
89216328 | 252 | set_dynaddr (); |
3e805913 CV |
253 | // Make sure the C runtime functions use the same codepage as the GUI |
254 | char locale[12]; | |
255 | snprintf(locale, sizeof locale, ".%u", GetACP()); | |
256 | setlocale(LC_ALL, locale); | |
257 | ||
4ea94dbb CF |
258 | set_legacy (_argv[0]); |
259 | ||
260 | if (is_legacy && IsWindowsNT ()) | |
261 | { | |
262 | if (MessageBox (NULL, | |
263 | "You are attempting to install a legacy version of Cygwin\n" | |
264 | "on a modern version of Windows. Press \"OK\" if this is\n" | |
265 | "really want you want to do. Otherwise press \"Cancel\".\n" | |
266 | "See http://cygwin.com/ for more information.", | |
267 | "Attempt to install legacy version of Cygwin", | |
268 | MB_OKCANCEL | MB_ICONSTOP | MB_SETFOREGROUND | MB_TOPMOST) | |
269 | == IDCANCEL) | |
270 | return 1; | |
271 | } | |
272 | else if (!is_legacy && !IsWindowsNT ()) | |
a5405502 CV |
273 | { |
274 | MessageBox (NULL, | |
275 | "Cygwin 1.7 and later does not run on Windows 95,\n" | |
276 | "Windows 98, or Windows Me. If you want to install Cygwin\n" | |
277 | "on one of these systems, please install an older version.\n" | |
278 | "See http://cygwin.com/ for more information.", | |
4ea94dbb | 279 | "Unsupported version of Windows detected", |
a5405502 CV |
280 | MB_OK | MB_ICONSTOP | MB_SETFOREGROUND | MB_TOPMOST); |
281 | return 1; | |
282 | } | |
283 | ||
072fb49a | 284 | try { |
5072c0bb | 285 | char cwd[MAX_PATH]; |
4875ac88 | 286 | GetCurrentDirectory (MAX_PATH, cwd); |
08678720 | 287 | local_dir = std::string (cwd); |
072fb49a | 288 | |
c66b9174 MB |
289 | // TODO: make an equivalent for __argv under cygwin. |
290 | char **_argv; | |
291 | #ifndef __CYGWIN__ | |
292 | int argc; | |
5072c0bb BD |
293 | for (argc = 0, _argv = __argv; *_argv; _argv++) |
294 | ++argc; | |
c66b9174 MB |
295 | _argv = __argv; |
296 | #else | |
297 | _argv = argv; | |
298 | #endif | |
299 | ||
5072c0bb BD |
300 | if (!GetOption::GetInstance ().Process (argc,_argv, NULL)) |
301 | exit (1); | |
c66b9174 | 302 | |
7a4e611a DK |
303 | unattended_mode = PackageManagerOption ? chooseronly |
304 | : (UnattendedOption ? unattended : attended); | |
305 | ||
c8356810 CF |
306 | if (unattended_mode || HelpOption) |
307 | set_cout (); | |
308 | ||
5072c0bb | 309 | LogSingleton::SetInstance (*(theLog = LogFile::createLogFile ())); |
4d10ec8c CV |
310 | const char *sep = isdirsep (local_dir[local_dir.size () - 1]) ? "" : "\\"; |
311 | theLog->setFile (LOG_BABBLE, local_dir + sep + "setup.log.full", false); | |
312 | theLog->setFile (0, local_dir + sep + "setup.log", true); | |
072fb49a | 313 | |
5072c0bb BD |
314 | log (LOG_PLAIN) << "Starting cygwin install, version " |
315 | << setup_version << endLog; | |
072fb49a | 316 | |
f26f525f | 317 | UserSettings Settings (local_dir); |
072fb49a | 318 | |
f26f525f | 319 | main_display (); |
072fb49a | 320 | |
f26f525f | 321 | Settings.save (); // Clean exit.. save user options. |
b24c88b3 | 322 | |
0407753c DK |
323 | if (rebootneeded) |
324 | { | |
325 | theLog->exit (IDS_REBOOT_REQUIRED); | |
326 | } | |
327 | else | |
328 | { | |
329 | theLog->exit (0); | |
330 | } | |
c9feb168 | 331 | } |
072fb49a | 332 | TOPLEVEL_CATCH("main"); |
c9feb168 | 333 | |
072fb49a | 334 | // Never reached |
b24c88b3 | 335 | return 0; |
23c9e63c | 336 | } |