2 * Copyright (c) 2000, Red Hat, Inc.
3 * Copyright (c) 2003, Robert Collins <rbtcollins@hotmail.com>
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.
10 * A copy of the GNU General Public License can be found at
13 * Written by DJ Delorie <dj@cygnus.com>
14 * Robert Collins <rbtcollins@hotmail.com>
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. */
30 static const char *cvsid
=
35 #define _WIN32_WINNT 0x0501
50 #include "setup_version.h"
53 #include "propsheet.h"
57 #include "AntiVirus.h"
67 #include "postinstallresults.h"
69 #include "getopt++/GetOption.h"
70 #include "getopt++/BoolOption.h"
71 #include "getopt++/StringOption.h"
73 #include "Exception.h"
76 #include "UserSettings.h"
77 #include "SourceSetting.h"
78 #include "ConnectionSetting.h"
79 #include "KeysSetting.h"
84 #ifdef __MINGW64_VERSION_MAJOR
94 static StringOption
Arch ("", 'a', "arch", "architecture to install (x86_64 or x86)", false);
95 static BoolOption
UnattendedOption (false, 'q', "quiet-mode", "Unattended setup mode");
96 static BoolOption
PackageManagerOption (false, 'M', "package-manager", "Semi-attended chooser-only mode");
97 static BoolOption
NoAdminOption (false, 'B', "no-admin", "Do not check for and enforce running as Administrator");
98 static BoolOption
WaitOption (false, 'W', "wait", "When elevating, wait for elevated child process");
99 static BoolOption
HelpOption (false, 'h', "help", "print help");
104 HANDLE my_stdout
= GetStdHandle (STD_OUTPUT_HANDLE
);
105 if (my_stdout
!= INVALID_HANDLE_VALUE
&& GetFileType (my_stdout
) != FILE_TYPE_UNKNOWN
)
108 if (AttachConsole ((DWORD
) -1))
110 ofstream
*conout
= new ofstream ("conout$");
111 cout
.rdbuf (conout
->rdbuf ());
116 // Other threads talk to these pages, so we need to have it externable.
117 ThreeBarProgressPage Progress
;
118 PostInstallResultsPage PostInstallResults
;
123 /* nondisplay classes */
124 LocalDirSetting localDir
;
125 SourceSetting SourceSettings
;
126 ConnectionSetting ConnectionSettings
;
127 SiteSetting ChosenSites
;
128 ExtraKeysSetting ExtraKeys
;
131 AntiVirusPage AntiVirus
;
134 LocalDirPage LocalDir
;
139 DesktopSetupPage Desktop
;
140 PropSheet MainWindow
;
142 Log (LOG_TIMESTAMP
) << "Current Directory: " << local_dir
<< endLog
;
144 // Initialize common controls
145 INITCOMMONCONTROLSEX icce
= { sizeof (INITCOMMONCONTROLSEX
),
147 InitCommonControlsEx (&icce
);
149 // Initialize COM and ShellLink instance here. For some reason
150 // Windows 7 fails to create the ShellLink instance if this is
151 // done later, in the thread which actually creates the shortcuts.
152 extern IShellLink
*sl
;
153 CoInitializeEx (NULL
, COINIT_APARTMENTTHREADED
);
154 HRESULT res
= CoCreateInstance (CLSID_ShellLink
, NULL
,
155 CLSCTX_INPROC_SERVER
, IID_IShellLink
,
160 sprintf (buf
, "CoCreateInstance failed with error 0x%x.\n"
161 "Setup will not be able to create Cygwin Icons\n"
162 "in the Start Menu or on the Desktop.", (int) res
);
163 MessageBox (NULL
, buf
, "Cygwin Setup", MB_OK
);
166 // Init window class lib
167 Window::SetAppInstance (hinstance
);
180 PostInstallResults
.Create ();
183 // Add pages to sheet
184 MainWindow
.AddPage (&Splash
);
185 MainWindow
.AddPage (&AntiVirus
);
186 MainWindow
.AddPage (&Source
);
187 MainWindow
.AddPage (&Root
);
188 MainWindow
.AddPage (&LocalDir
);
189 MainWindow
.AddPage (&Net
);
190 MainWindow
.AddPage (&Site
);
191 MainWindow
.AddPage (&Chooser
);
192 MainWindow
.AddPage (&Prereq
);
193 MainWindow
.AddPage (&Progress
);
194 MainWindow
.AddPage (&PostInstallResults
);
195 MainWindow
.AddPage (&Desktop
);
197 // Create the PropSheet main window
198 MainWindow
.Create ();
207 WinMain (HINSTANCE h
,
208 HINSTANCE hPrevInstance
, LPSTR command_line
, int cmd_show
)
213 // Make sure the C runtime functions use the same codepage as the GUI
215 snprintf(locale
, sizeof locale
, ".%u", GetACP());
216 setlocale(LC_ALL
, locale
);
220 for (argc
= 0, _argv
= __argv
; *_argv
; _argv
++)
225 bool help_option
= false;
226 bool invalid_option
= false;
228 GetCurrentDirectory (MAX_PATH
, cwd
);
229 local_dir
= std::string (cwd
);
231 if (!GetOption::GetInstance ().Process (argc
,_argv
, NULL
))
232 help_option
= invalid_option
= true;
236 if (!((string
) Arch
).size ())
244 else if (((string
) Arch
).find ("64") != string::npos
)
246 else if (((string
) Arch
).find ("32") != string::npos
247 || ((string
) Arch
).find ("x86") != string::npos
)
251 char buff
[80 + ((string
) Arch
).size ()];
252 sprintf (buff
, "Invalid option for --arch: \"%s\"",
253 ((string
) Arch
).c_str ());
254 fprintf (stderr
, "*** %s\n", buff
);
255 MessageBox (NULL
, buff
, "Invalid option", MB_ICONEXCLAMATION
| MB_OK
);
259 unattended_mode
= PackageManagerOption
? chooseronly
260 : (UnattendedOption
? unattended
: attended
);
262 if (unattended_mode
|| help_option
)
265 /* Get System info */
266 OSVERSIONINFO version
;
267 version
.dwOSVersionInfoSize
= sizeof version
;
268 GetVersionEx (&version
);
269 /* Initialize well known SIDs. We need the admin SID to test if we're
270 supposed to elevate. */
271 nt_sec
.initialiseWellKnownSIDs ();
272 /* Check if we have to elevate. */
273 bool elevate
= !help_option
&& version
.dwMajorVersion
>= 6
274 && !NoAdminOption
&& !nt_sec
.isRunAsAdmin ();
276 /* Start logging only if we don't elevate. Same for setting default
277 security settings. */
278 LogSingleton::SetInstance (*LogFile::createLogFile ());
279 const char *sep
= isdirsep (local_dir
[local_dir
.size () - 1])
281 /* Don't create log files for help output only. */
282 if (!elevate
&& !help_option
)
284 Logger ().setFile (LOG_BABBLE
, local_dir
+ sep
+ "setup.log.full",
286 Logger ().setFile (0, local_dir
+ sep
+ "setup.log", true);
287 Log (LOG_PLAIN
) << "Starting cygwin install, version "
288 << setup_version
<< endLog
;
294 Log (LOG_PLAIN
) << "\nError during option processing." << endLog
;
295 Log (LOG_PLAIN
) << "\nCommand Line Options:\n" << endLog
;
296 GetOption::GetInstance ().ParameterUsage (Log (LOG_PLAIN
));
297 Log (LOG_PLAIN
) << endLog
;
298 Logger ().exit (invalid_option
? 1 : 0, false);
302 char exe_path
[MAX_PATH
];
303 if (!GetModuleFileName(NULL
, exe_path
, ARRAYSIZE(exe_path
)))
306 SHELLEXECUTEINFO sei
= { sizeof(sei
) };
307 sei
.lpVerb
= "runas";
308 sei
.lpFile
= exe_path
;
309 sei
.nShow
= SW_NORMAL
;
311 sei
.fMask
|= SEE_MASK_NOCLOSEPROCESS
;
313 // Avoid another isRunAsAdmin check in the child.
314 std::string
command_line_cs (command_line
);
315 command_line_cs
+= " -";
316 command_line_cs
+= NoAdminOption
.shortOption();
317 sei
.lpParameters
= command_line_cs
.c_str ();
319 if (ShellExecuteEx(&sei
))
321 /* Wait until child process is finished. */
322 if (WaitOption
&& sei
.hProcess
!= NULL
)
323 WaitForSingleObject (sei
.hProcess
, INFINITE
);
325 Logger ().setExitMsg (IDS_ELEVATED
);
326 Logger ().exit (0, false);
330 /* Set default DACL and Group. */
331 nt_sec
.setDefaultSecurity ();
333 UserSettings
Settings (local_dir
);
335 Settings
.save (); // Clean exit.. save user options.
337 Logger ().setExitMsg (IDS_REBOOT_REQUIRED
);
338 Logger ().exit (rebootneeded
? IDS_REBOOT_REQUIRED
: 0);
343 TOPLEVEL_CATCH("main");