Initial revision
[chise/xemacs-chise.git] / netinstall / root.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 /* The purpose of this file is to ask the user where they want the
17    root of the installation to be, and to ask whether the user prefers
18    text or binary mounts. */
19
20 #include "win32.h"
21 #include <shlobj.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <ctype.h>
25
26 #include "dialog.h"
27 #include "resource.h"
28 #include "state.h"
29 #include "msg.h"
30 #include "regedit.h"
31 #include "reginfo.h"
32 #include "concat.h"
33 #include "log.h"
34
35 static int rb[] = { IDC_INSTALL_CYGWIN, IDC_INSTALL_NATIVE, 0 };
36 static int su[] = { IDC_ROOT_SYSTEM, IDC_ROOT_USER, 0 };
37
38 static void
39 check_if_enable_next (HWND h)
40 {
41   EnableWindow (GetDlgItem (h, IDOK), install_type && root_dir && root_scope);
42 }
43
44 static void
45 load_dialog (HWND h)
46 {
47   rbset (h, rb, install_type);
48   rbset (h, su, root_scope);
49   eset (h, IDC_ROOT_DIR, root_dir);
50   check_if_enable_next (h);
51 }
52
53 static void
54 save_dialog (HWND h)
55 {
56   install_type = rbget (h, rb);
57   root_scope = rbget (h, su);
58   char* new_root_dir = eget (h, IDC_ROOT_DIR, root_dir);
59
60   if (!root_dir || strcmp (new_root_dir, root_dir) != 0)
61     root_dir_default = 0;
62
63   root_dir = new_root_dir;
64 }
65
66 /*
67  * is_admin () determines whether or not the current user is a member of the
68  * Administrators group.  On Windows 9X, the current user is considered an
69  * Administrator by definition.
70  */
71
72 static int
73 is_admin ()
74 {
75   // Windows 9X users are considered Administrators by definition
76   OSVERSIONINFO verinfo;
77   verinfo.dwOSVersionInfoSize = sizeof (verinfo);
78   GetVersionEx (&verinfo);
79   if (verinfo.dwPlatformId != VER_PLATFORM_WIN32_NT)
80     return 1;
81
82   // Get the process token for the current process
83   HANDLE token;
84   BOOL status = OpenProcessToken (GetCurrentProcess(), TOKEN_QUERY, &token);
85   if (!status)
86     return 0;
87
88   // Get the group token information
89   UCHAR token_info[1024];
90   PTOKEN_GROUPS groups = (PTOKEN_GROUPS) token_info;
91   DWORD token_info_len = sizeof (token_info);
92   status = GetTokenInformation (token, TokenGroups, token_info, token_info_len, &token_info_len);
93   CloseHandle(token);
94   if (!status)
95     return 0;
96
97   // Create the Administrators group SID
98   PSID admin_sid;
99   SID_IDENTIFIER_AUTHORITY authority = SECURITY_NT_AUTHORITY;
100   status = AllocateAndInitializeSid (&authority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &admin_sid);
101   if (!status)
102     return 0;
103
104   // Check to see if the user is a member of the Administrators group
105   status = 0;
106   for (UINT i=0; i<groups->GroupCount; i++) {
107     if (EqualSid(groups->Groups[i].Sid, admin_sid)) {
108       status = 1;
109       break;
110     }
111   }
112
113   // Destroy the Administrators group SID
114   FreeSid (admin_sid);
115
116   // Return whether or not the user is a member of the Administrators group
117   return status;
118 }
119
120 static void
121 change_default_root (int id)
122 {
123   int issystem;
124   char* cygroot = find_cygwin_root (&issystem);
125   if (id == IDC_INSTALL_CYGWIN && cygroot)
126     {
127       root_dir = concat (cygroot, XEMACS_CYGWIN_DEFAULT_ROOT, 0);
128       install_type = IDC_INSTALL_CYGWIN;
129     }
130   else if (id == IDC_INSTALL_NATIVE)
131     {
132       char windir[_MAX_PATH];
133       GetWindowsDirectory (windir, sizeof (windir));
134       windir[2] = 0;
135       root_dir = concat (windir, XEMACS_DEFAULT_ROOT, 0);
136       install_type = IDC_INSTALL_NATIVE;
137     }
138 }
139
140 static void
141 read_mount_table ()
142 {
143   int isnative, issystem;
144   root_dir = find_root_location (&issystem, &isnative);
145   if (root_dir)
146     {
147       if (isnative)
148         install_type = IDC_INSTALL_NATIVE;
149       else
150         install_type = IDC_INSTALL_CYGWIN;
151
152       if (issystem)
153         root_scope = IDC_ROOT_SYSTEM;
154       else
155         root_scope = IDC_ROOT_USER;
156       root_dir_default = 0;
157     }
158   else
159     {
160       change_default_root (IDC_INSTALL_NATIVE);
161       root_scope = (is_admin()) ? IDC_ROOT_SYSTEM : IDC_ROOT_USER;
162       root_dir_default = 1;
163     }
164 }
165
166 static int CALLBACK
167 browse_cb (HWND h, UINT m, LPARAM lp, LPARAM data)
168 {
169   switch (m)
170     {
171     case BFFM_INITIALIZED:
172       if (root_dir)
173         SendMessage (h, BFFM_SETSELECTION, TRUE, (LPARAM)root_dir);
174       break;
175     }
176   return 0;
177 }
178
179 static void
180 browse (HWND h)
181 {
182   BROWSEINFO bi;
183   CHAR name[MAX_PATH];
184   LPITEMIDLIST pidl;
185   memset (&bi, 0, sizeof (bi));
186   bi.hwndOwner = h;
187   bi.pszDisplayName = name;
188   bi.lpszTitle = "Select an installation root directory";
189   bi.ulFlags = BIF_RETURNONLYFSDIRS;
190   bi.lpfn = browse_cb;
191   pidl = SHBrowseForFolder (&bi);
192   if (pidl)
193     {
194       if (SHGetPathFromIDList (pidl, name))
195         eset (h, IDC_ROOT_DIR, name);
196     }
197 }
198
199 #define isslash(c) ((c) == '\\' || (c) == '/')
200
201 static int
202 directory_is_absolute ()
203 {
204   if (isalpha (root_dir[0])
205       && root_dir[1] == ':'
206       && (root_dir[2] == '\\' || root_dir[2] == '/'))
207     return 1;
208   return 0;
209 }
210
211 static int
212 directory_is_rootdir ()
213 {
214   char *c;
215   for (c = root_dir; *c; c++)
216     if (isslash (c[0]) && c[1] && !isslash (c[1]))
217       return 0;
218   return 1;
219 }
220
221 static int
222 cygwin_without_cygwin ()
223 {
224   int issystem;
225   if (install_type == IDC_INSTALL_CYGWIN
226       && !find_cygwin_root (&issystem))
227     return 1;
228   return 0;
229 }
230
231 static BOOL
232 dialog_cmd (HWND h, int id, HWND hwndctl, UINT code)
233 {
234   switch (id)
235     {
236
237     case IDC_ROOT_DIR:
238     case IDC_ROOT_SYSTEM:
239     case IDC_ROOT_USER:
240       save_dialog (h);
241       check_if_enable_next (h);
242       break;
243
244     case IDC_INSTALL_NATIVE:
245     case IDC_INSTALL_CYGWIN:
246       if (root_dir_default)
247         {
248           change_default_root (id);
249           eset (h, IDC_ROOT_DIR, root_dir);
250         }
251       save_dialog (h);
252       check_if_enable_next (h);
253       break;
254
255     case IDC_ROOT_BROWSE:
256       browse (h);
257       break;
258
259     case IDOK:
260       save_dialog (h);
261
262       if (! directory_is_absolute ())
263         {
264           note (IDS_ROOT_ABSOLUTE);
265           break;
266         }
267
268       if (directory_is_rootdir ())
269         if (IDNO == yesno (IDS_ROOT_SLASH))
270           break;
271
272       if (cygwin_without_cygwin ())
273         if (IDNO == yesno (IDS_ROOT_NOCYGWIN))
274           break;
275
276       create_xemacs_root (root_dir,
277                           root_scope == IDC_ROOT_SYSTEM ? 1 : 0,
278                           install_type == IDC_INSTALL_NATIVE ? 1 : 0);
279
280       switch (source)
281         {
282         case IDC_SOURCE_NETINST:
283           NEXT (IDD_NET);
284           break;
285         case IDC_SOURCE_CWD:
286           NEXT (IDD_S_FROM_CWD);
287           break;
288         default:
289           msg ("source is default? %d\n", source);
290           NEXT (0);
291         }
292       break;
293
294     case IDC_BACK:
295       save_dialog (h);
296       NEXT (IDD_LOCAL_DIR);
297       break;
298
299     case IDCANCEL:
300       NEXT (0);
301       break;
302     }
303   return FALSE;
304 }
305
306 static BOOL CALLBACK
307 dialog_proc (HWND h, UINT message, WPARAM wParam, LPARAM lParam)
308 {
309   switch (message)
310     {
311     case WM_INITDIALOG:
312       load_dialog (h);
313       return FALSE;
314     case WM_COMMAND:
315       return HANDLE_WM_COMMAND (h, wParam, lParam, dialog_cmd);
316     }
317   return FALSE;
318 }
319
320 void
321 do_root (HINSTANCE h)
322 {
323   int rv = 0;
324   read_mount_table ();
325
326   rv = DialogBox (h, MAKEINTRESOURCE (IDD_ROOT), 0, dialog_proc);
327   if (rv == -1)
328     fatal (IDS_DIALOG_FAILED);
329
330   log (0, "root: %s %s %s", root_dir,
331        (install_type == IDC_INSTALL_NATIVE) ? "native" : "cygwin",
332        (root_scope == IDC_ROOT_USER) ? "user" : "system");
333 }
334