]> cygwin.com Git - cygwin-apps/setup.git/blob - main.cc
5be956cab25c18521b50f452cd1fcad568949aa6
[cygwin-apps/setup.git] / main.cc
1 /*
2 * Copyright (c) 2000, Red Hat, Inc.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * A copy of the GNU General Public License can be found at
10 * http://www.gnu.org/
11 *
12 * Written by DJ Delorie <dj@cygnus.com>
13 *
14 */
15
16 /* OK, here's how this works. Each of the steps needed for install -
17 dialogs, downloads, installs - are in their own files and have some
18 "do_*" function (prototype in dialog.h) and a resource id (IDD_* or
19 IDD_S_* in resource.h) for that step. Each step is responsible for
20 selecting the next step! See the NEXT macro in dialog.h. Note
21 that the IDD_S_* ids are fake; those are for steps that don't
22 really have a controlling dialog (some have progress dialogs, but
23 those don't count, although they could). Replace the IDD_S_* with
24 IDD_* if you create a real dialog for those steps. */
25
26 #if 0
27 static const char *cvsid =
28 "\n%%% $Id$\n";
29 #endif
30
31 #include "win32.h"
32 #include <commctrl.h>
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include "resource.h"
37 #include "dialog.h"
38 #include "state.h"
39 #include "msg.h"
40 #include "find.h"
41 #include "mount.h"
42 #include "LogFile.h"
43 #include "version.h"
44
45 #include "port.h"
46 #include "proppage.h"
47 #include "propsheet.h"
48
49 // Page class headers
50 #include "splash.h"
51 #include "AntiVirus.h"
52 #include "source.h"
53 #include "root.h"
54 #include "localdir.h"
55 #include "net.h"
56 #include "site.h"
57 #include "choose.h"
58 #include "threebar.h"
59 #include "desktop.h"
60
61 #include "getopt++/GetOption.h"
62 #include "getopt++/BoolOption.h"
63
64 int next_dialog;
65
66 HINSTANCE hinstance;
67
68 static BoolOption UnattendedOption (false, 'q', "quiet-mode", "Unattended setup mode");
69
70 /* Maximum size of a SID on NT/W2K. */
71 #define MAX_SID_LEN 40
72
73 /* Computes the size of an ACL in relation to the number of ACEs it
74 should contain. */
75 #define TOKEN_ACL_SIZE(cnt) (sizeof(ACL) + \
76 (cnt) * (sizeof(ACCESS_ALLOWED_ACE) + MAX_SID_LEN))
77
78 #define iswinnt (GetVersion() < 0x80000000)
79
80 void
81 set_default_sec ()
82 {
83 /* To assure that the created files have a useful ACL, the
84 default DACL in the process token is set to full access to
85 everyone. This applies to files and subdirectories created
86 in directories which don't propagate permissions to child
87 objects.
88 To assure that the files group is meaningful, a token primary
89 group of None is changed to Users or Administrators. */
90
91 /* Create a buffer which has enough room to contain the TOKEN_DEFAULT_DACL
92 structure plus an ACL with one ACE. */
93 char buf[sizeof (TOKEN_DEFAULT_DACL) + TOKEN_ACL_SIZE (1)];
94
95 /* First initialize the TOKEN_DEFAULT_DACL structure. */
96 PTOKEN_DEFAULT_DACL dacl = (PTOKEN_DEFAULT_DACL) buf;
97 dacl->DefaultDacl = (PACL) (buf + sizeof *dacl);
98
99 /* Initialize the ACL for containing one ACE. */
100 if (!InitializeAcl (dacl->DefaultDacl, TOKEN_ACL_SIZE (1), ACL_REVISION))
101 {
102 log (LOG_TIMESTAMP) << "InitializeAcl() failed: " << GetLastError ()
103 << endLog;
104 return;
105 }
106
107 PSID esid = NULL, asid = NULL, usid = NULL;
108 HANDLE token = NULL;
109 struct {
110 PSID psid;
111 char buf[MAX_SID_LEN];
112 } gsid;
113 char lsid[MAX_SID_LEN];
114 char compname[MAX_COMPUTERNAME_LENGTH + 1];
115 char domain[MAX_COMPUTERNAME_LENGTH + 1];
116 DWORD size;
117
118 SID_IDENTIFIER_AUTHORITY sid_auth = { SECURITY_WORLD_SID_AUTHORITY };
119 if (!AllocateAndInitializeSid (&sid_auth, 1, 0, 0, 0, 0, 0, 0, 0, 0, &esid))
120 {
121 log (LOG_TIMESTAMP) << "AllocateAndInitializeSid() failed: " <<
122 GetLastError () << endLog;
123 goto out;
124 }
125
126 /* Create the ACE which grants full access to "Everyone" and store it
127 in dacl->DefaultDacl. */
128 if (!AddAccessAllowedAce
129 (dacl->DefaultDacl, ACL_REVISION, GENERIC_ALL, esid))
130 {
131 log (LOG_TIMESTAMP) << "AddAccessAllowedAce() failed: %lu" <<
132 GetLastError () << endLog;
133 goto out;
134 }
135
136 /* Get the processes access token. */
137 if (!OpenProcessToken (GetCurrentProcess (),
138 TOKEN_READ | TOKEN_ADJUST_DEFAULT, &token))
139 {
140 log (LOG_TIMESTAMP) << "OpenProcessToken() failed: " <<
141 GetLastError () << endLog;
142 goto out;
143 }
144
145 /* Set the default DACL to the above computed ACL. */
146 if (!SetTokenInformation (token, TokenDefaultDacl, dacl, sizeof buf))
147 log (LOG_TIMESTAMP) << "OpenProcessToken() failed: " <<
148 GetLastError () << endLog;
149
150
151 /* Get the default group */
152 if (!GetTokenInformation (token, TokenPrimaryGroup, &gsid, sizeof gsid, &size))
153 {
154 log (LOG_TIMESTAMP) << "GetTokenInformation() failed: " <<
155 GetLastError () << endLog;
156 goto out;
157 }
158
159 /* Get the computer name */
160 if (!GetComputerName (compname, (size = sizeof compname, &size)))
161 {
162 log (LOG_TIMESTAMP) << "GetComputerName() failed: " <<
163 GetLastError () << endLog;
164 goto out;
165 }
166
167 /* Get the local domain SID */
168 SID_NAME_USE use;
169 DWORD sz;
170 if (!LookupAccountName (NULL, compname, lsid, (size = sizeof lsid, &size),
171 domain, (sz = sizeof domain, &sz), &use))
172 {
173 log (LOG_TIMESTAMP) << "LookupAccountName() failed: " <<
174 GetLastError () << endLog;
175 goto out;
176 }
177
178 /* Create the None SID from the domain SID.
179 On NT the last subauthority of a domain is -1 and it is replaced by the RID.
180 On other systems the RID is appended. */
181 sz = *GetSidSubAuthorityCount (lsid);
182 if (*GetSidSubAuthority (lsid, sz -1) != (DWORD) -1)
183 *GetSidSubAuthorityCount (lsid) = ++sz;
184 *GetSidSubAuthority (lsid, sz -1) = DOMAIN_GROUP_RID_USERS;
185
186 /* See if the group is None */
187 if (EqualSid (gsid.psid, lsid))
188 {
189 bool isadmins = false, isusers = false;
190 sid_auth = (SID_IDENTIFIER_AUTHORITY) { SECURITY_NT_AUTHORITY };
191 /* Get the SID for "Administrators" S-1-5-32-544 */
192 if (!AllocateAndInitializeSid (&sid_auth, 2, SECURITY_BUILTIN_DOMAIN_RID,
193 DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &asid))
194 {
195 log (LOG_TIMESTAMP) << "AllocateAndInitializeSid() failed: " <<
196 GetLastError () << endLog;
197 goto out;
198 }
199 /* Get the SID for "Users" S-1-5-32-545 */
200 if (!AllocateAndInitializeSid (&sid_auth, 2, SECURITY_BUILTIN_DOMAIN_RID,
201 DOMAIN_ALIAS_RID_USERS, 0, 0, 0, 0, 0, 0, &usid))
202 {
203 log (LOG_TIMESTAMP) << "AllocateAndInitializeSid() failed: " <<
204 GetLastError () << endLog;
205 goto out;
206 }
207 /* Get the token groups */
208 if (!GetTokenInformation (token, TokenGroups, NULL, 0, &size)
209 && GetLastError () != ERROR_INSUFFICIENT_BUFFER)
210 {
211 log (LOG_TIMESTAMP) << "GetTokenInformation() failed: " <<
212 GetLastError () << endLog;
213 goto out;
214 }
215 else
216 {
217 char buf[size];
218 TOKEN_GROUPS *groups = (TOKEN_GROUPS *) buf;
219
220 if (!GetTokenInformation (token, TokenGroups, buf, size, &size))
221 {
222 log (LOG_TIMESTAMP) << "GetTokenInformation() failed: " <<
223 GetLastError () << endLog;
224 goto out;
225 }
226 else
227 /* See if admins or users is present */
228 for (DWORD pg = 0; pg < groups->GroupCount; ++pg)
229 {
230 isadmins = isadmins || EqualSid(groups->Groups[pg].Sid, asid);
231 isusers = isusers || EqualSid(groups->Groups[pg].Sid, usid);
232 }
233 }
234 /* Set the default group to one of the above computed SID. */
235 PSID nsid = NULL;
236 if (isusers)
237 nsid = usid;
238 else if (isadmins)
239 nsid = asid;
240 if (nsid && !SetTokenInformation (token, TokenPrimaryGroup, &nsid, sizeof nsid))
241 log (LOG_TIMESTAMP) << "SetTokenInformation() failed: " <<
242 GetLastError () << endLog;
243 }
244 out:
245 /* Close token handle. */
246 if (token)
247 CloseHandle (token);
248
249 /* Free memory occupied by the SIDs. */
250 if (esid)
251 FreeSid (esid);
252 if (asid)
253 FreeSid (asid);
254 if (usid)
255 FreeSid (usid);
256 }
257
258 // Other threads talk to this page, so we need to have it externable.
259 ThreeBarProgressPage Progress;
260
261 // This is a little ugly, but the decision about where to log occurs
262 // after the source is set AND the root mount obtained
263 // so we make the actual logger available to the appropriate routine(s).
264 LogFile *theLog;
265
266 #ifndef __CYGWIN__
267 int WINAPI
268 WinMain (HINSTANCE h,
269 HINSTANCE hPrevInstance, LPSTR command_line, int cmd_show)
270 {
271
272 hinstance = h;
273 #else
274 int
275 main (int argc, char **argv)
276 {
277 hinstance = GetModuleHandle (NULL);
278 #endif
279
280 char *cwd=new char[_MAX_PATH];
281 GetCurrentDirectory (_MAX_PATH, cwd);
282 local_dir = String (cwd);
283 delete cwd;
284
285 LogSingleton::SetInstance (*(theLog = LogFile::createLogFile()));
286 theLog->setFile (LOG_BABBLE, local_dir + "/setup.log.full", false);
287 theLog->setFile (0, local_dir + "/setup.log", true);
288
289 next_dialog = IDD_SPLASH;
290
291 log (LOG_PLAIN) << "Starting cygwin install, version " << version << endLog;
292
293 SplashPage Splash;
294 AntiVirusPage AntiVirus;
295 SourcePage Source;
296 RootPage Root;
297 LocalDirPage LocalDir;
298 NetPage Net;
299 SitePage Site;
300 ChooserPage Chooser;
301 DesktopSetupPage Desktop;
302 PropSheet MainWindow;
303
304 log (LOG_TIMESTAMP) << "Current Directory: " << local_dir << endLog;
305
306 // TODO: make an equivalent for __argv under cygwin.
307 char **_argv;
308 #ifndef __CYGWIN__
309 int argc;
310 // char **_argv;
311 #ifndef __CYGWIN__
312 for (argc = 0, _argv = __argv; *_argv; _argv++)++argc;
313 _argv = __argv;
314 #else
315 // for (argc = 0, _argv = argv; *_argv; _argv++)++argc;
316 _argv = argv;
317 #endif
318 #else
319 _argv = argv;
320 #endif
321
322 if (!GetOption::GetInstance().Process (argc,_argv))
323 theLog->exit(1);
324 // #endif
325
326 unattended_mode = UnattendedOption;
327
328 /* Set the default DACL and Group only on NT/W2K. 9x/ME has
329 no idea of access control lists and security at all. */
330 if (iswinnt)
331 set_default_sec ();
332
333 // Initialize common controls
334 InitCommonControls ();
335
336 // Init window class lib
337 Window::SetAppInstance (hinstance);
338
339 // Create pages
340 Splash.Create ();
341 AntiVirus.Create ();
342 Source.Create ();
343 Root.Create ();
344 LocalDir.Create ();
345 Net.Create ();
346 Site.Create ();
347 Chooser.Create ();
348 Progress.Create ();
349 Desktop.Create ();
350
351 // Add pages to sheet
352 MainWindow.AddPage (&Splash);
353 MainWindow.AddPage (&AntiVirus);
354 MainWindow.AddPage (&Source);
355 MainWindow.AddPage (&Root);
356 MainWindow.AddPage (&LocalDir);
357 MainWindow.AddPage (&Net);
358 MainWindow.AddPage (&Site);
359 MainWindow.AddPage (&Chooser);
360 MainWindow.AddPage (&Progress);
361 MainWindow.AddPage (&Desktop);
362
363 // Create the PropSheet main window
364 MainWindow.Create ();
365
366 theLog->exit (0);
367 /* Keep gcc happy :} */
368 return 0;
369 }
This page took 0.051487 seconds and 5 git commands to generate.