2 * Copyright (c) 2000, Red Hat, Inc.
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.
9 * A copy of the GNU General Public License can be found at
12 * Written by DJ Delorie <dj@cygnus.com>
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. */
27 static const char *cvsid
=
47 #include "propsheet.h"
51 #include "AntiVirus.h"
61 #include "getopt++/GetOption.h"
62 #include "getopt++/BoolOption.h"
68 static BoolOption
UnattendedOption (false, 'q', "quiet-mode", "Unattended setup mode");
70 /* Maximum size of a SID on NT/W2K. */
71 #define MAX_SID_LEN 40
73 /* Computes the size of an ACL in relation to the number of ACEs it
75 #define TOKEN_ACL_SIZE(cnt) (sizeof(ACL) + \
76 (cnt) * (sizeof(ACCESS_ALLOWED_ACE) + MAX_SID_LEN))
78 #define iswinnt (GetVersion() < 0x80000000)
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
88 To assure that the files group is meaningful, a token primary
89 group of None is changed to Users or Administrators. */
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)];
95 /* First initialize the TOKEN_DEFAULT_DACL structure. */
96 PTOKEN_DEFAULT_DACL dacl
= (PTOKEN_DEFAULT_DACL
) buf
;
97 dacl
->DefaultDacl
= (PACL
) (buf
+ sizeof *dacl
);
99 /* Initialize the ACL for containing one ACE. */
100 if (!InitializeAcl (dacl
->DefaultDacl
, TOKEN_ACL_SIZE (1), ACL_REVISION
))
102 log (LOG_TIMESTAMP
) << "InitializeAcl() failed: " << GetLastError ()
107 PSID esid
= NULL
, asid
= NULL
, usid
= NULL
;
111 char buf
[MAX_SID_LEN
];
113 char lsid
[MAX_SID_LEN
];
114 char compname
[MAX_COMPUTERNAME_LENGTH
+ 1];
115 char domain
[MAX_COMPUTERNAME_LENGTH
+ 1];
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
))
121 log (LOG_TIMESTAMP
) << "AllocateAndInitializeSid() failed: " <<
122 GetLastError () << endLog
;
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
))
131 log (LOG_TIMESTAMP
) << "AddAccessAllowedAce() failed: %lu" <<
132 GetLastError () << endLog
;
136 /* Get the processes access token. */
137 if (!OpenProcessToken (GetCurrentProcess (),
138 TOKEN_READ
| TOKEN_ADJUST_DEFAULT
, &token
))
140 log (LOG_TIMESTAMP
) << "OpenProcessToken() failed: " <<
141 GetLastError () << endLog
;
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
;
151 /* Get the default group */
152 if (!GetTokenInformation (token
, TokenPrimaryGroup
, &gsid
, sizeof gsid
, &size
))
154 log (LOG_TIMESTAMP
) << "GetTokenInformation() failed: " <<
155 GetLastError () << endLog
;
159 /* Get the computer name */
160 if (!GetComputerName (compname
, (size
= sizeof compname
, &size
)))
162 log (LOG_TIMESTAMP
) << "GetComputerName() failed: " <<
163 GetLastError () << endLog
;
167 /* Get the local domain SID */
170 if (!LookupAccountName (NULL
, compname
, lsid
, (size
= sizeof lsid
, &size
),
171 domain
, (sz
= sizeof domain
, &sz
), &use
))
173 log (LOG_TIMESTAMP
) << "LookupAccountName() failed: " <<
174 GetLastError () << endLog
;
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
;
186 /* See if the group is None */
187 if (EqualSid (gsid
.psid
, lsid
))
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
))
195 log (LOG_TIMESTAMP
) << "AllocateAndInitializeSid() failed: " <<
196 GetLastError () << endLog
;
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
))
203 log (LOG_TIMESTAMP
) << "AllocateAndInitializeSid() failed: " <<
204 GetLastError () << endLog
;
207 /* Get the token groups */
208 if (!GetTokenInformation (token
, TokenGroups
, NULL
, 0, &size
)
209 && GetLastError () != ERROR_INSUFFICIENT_BUFFER
)
211 log (LOG_TIMESTAMP
) << "GetTokenInformation() failed: " <<
212 GetLastError () << endLog
;
218 TOKEN_GROUPS
*groups
= (TOKEN_GROUPS
*) buf
;
220 if (!GetTokenInformation (token
, TokenGroups
, buf
, size
, &size
))
222 log (LOG_TIMESTAMP
) << "GetTokenInformation() failed: " <<
223 GetLastError () << endLog
;
227 /* See if admins or users is present */
228 for (DWORD pg
= 0; pg
< groups
->GroupCount
; ++pg
)
230 isadmins
= isadmins
|| EqualSid(groups
->Groups
[pg
].Sid
, asid
);
231 isusers
= isusers
|| EqualSid(groups
->Groups
[pg
].Sid
, usid
);
234 /* Set the default group to one of the above computed SID. */
240 if (nsid
&& !SetTokenInformation (token
, TokenPrimaryGroup
, &nsid
, sizeof nsid
))
241 log (LOG_TIMESTAMP
) << "SetTokenInformation() failed: " <<
242 GetLastError () << endLog
;
245 /* Close token handle. */
249 /* Free memory occupied by the SIDs. */
258 // Other threads talk to this page, so we need to have it externable.
259 ThreeBarProgressPage Progress
;
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).
268 WinMain (HINSTANCE h
,
269 HINSTANCE hPrevInstance
, LPSTR command_line
, int cmd_show
)
275 main (int argc
, char **argv
)
277 hinstance
= GetModuleHandle (NULL
);
280 char *cwd
=new char[_MAX_PATH
];
281 GetCurrentDirectory (_MAX_PATH
, cwd
);
282 local_dir
= String (cwd
);
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);
289 next_dialog
= IDD_SPLASH
;
291 log (LOG_PLAIN
) << "Starting cygwin install, version " << version
<< endLog
;
294 AntiVirusPage AntiVirus
;
297 LocalDirPage LocalDir
;
301 DesktopSetupPage Desktop
;
302 PropSheet MainWindow
;
304 log (LOG_TIMESTAMP
) << "Current Directory: " << local_dir
<< endLog
;
306 // TODO: make an equivalent for __argv under cygwin.
312 for (argc
= 0, _argv
= __argv
; *_argv
; _argv
++)++argc
;
315 // for (argc = 0, _argv = argv; *_argv; _argv++)++argc;
322 if (!GetOption::GetInstance().Process (argc
,_argv
))
326 unattended_mode
= UnattendedOption
;
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. */
333 // Initialize common controls
334 InitCommonControls ();
336 // Init window class lib
337 Window::SetAppInstance (hinstance
);
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
);
363 // Create the PropSheet main window
364 MainWindow
.Create ();
367 /* Keep gcc happy :} */