(A-compU+26612): New abstract node.
[chise/xemacs-chise.git.1] / 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 int CALLBACK
141 browse_cb (HWND h, UINT m, LPARAM lp, LPARAM data)
142 {
143   switch (m)
144     {
145     case BFFM_INITIALIZED:
146       if (root_dir)
147         SendMessage (h, BFFM_SETSELECTION, TRUE, (LPARAM)root_dir);
148       break;
149     }
150   return 0;
151 }
152
153 static void
154 browse (HWND h)
155 {
156   BROWSEINFO bi;
157   CHAR name[MAX_PATH];
158   LPITEMIDLIST pidl;
159   memset (&bi, 0, sizeof (bi));
160   bi.hwndOwner = h;
161   bi.pszDisplayName = name;
162   bi.lpszTitle = "Select an installation root directory";
163   bi.ulFlags = BIF_RETURNONLYFSDIRS;
164   bi.lpfn = browse_cb;
165   pidl = SHBrowseForFolder (&bi);
166   if (pidl)
167     {
168       if (SHGetPathFromIDList (pidl, name))
169         eset (h, IDC_ROOT_DIR, name);
170     }
171 }
172
173 #define isslash(c) ((c) == '\\' || (c) == '/')
174
175 static int
176 directory_is_absolute ()
177 {
178   if (isalpha (root_dir[0])
179       && root_dir[1] == ':'
180       && (root_dir[2] == '\\' || root_dir[2] == '/'))
181     return 1;
182   return 0;
183 }
184
185 static int
186 directory_is_rootdir ()
187 {
188   char *c;
189   for (c = root_dir; *c; c++)
190     if (isslash (c[0]) && c[1] && !isslash (c[1]))
191       return 0;
192   return 1;
193 }
194
195 static int
196 cygwin_without_cygwin ()
197 {
198   int issystem;
199   if (install_type == IDC_INSTALL_CYGWIN
200       && !find_cygwin_root (&issystem))
201     return 1;
202   return 0;
203 }
204
205 static BOOL
206 dialog_cmd (HWND h, int id, HWND hwndctl, UINT code)
207 {
208   switch (id)
209     {
210
211     case IDC_ROOT_DIR:
212     case IDC_ROOT_SYSTEM:
213     case IDC_ROOT_USER:
214       save_dialog (h);
215       check_if_enable_next (h);
216       break;
217
218     case IDC_INSTALL_NATIVE:
219     case IDC_INSTALL_CYGWIN:
220       if (root_dir_default)
221         {
222           change_default_root (id);
223           eset (h, IDC_ROOT_DIR, root_dir);
224         }
225       save_dialog (h);
226       check_if_enable_next (h);
227       break;
228
229     case IDC_ROOT_BROWSE:
230       browse (h);
231       break;
232
233     case IDOK:
234       save_dialog (h);
235
236       if (! directory_is_absolute ())
237         {
238           note (IDS_ROOT_ABSOLUTE);
239           break;
240         }
241
242       if (directory_is_rootdir ())
243         if (IDNO == yesno (IDS_ROOT_SLASH))
244           break;
245
246       if (cygwin_without_cygwin ())
247         if (IDNO == yesno (IDS_ROOT_NOCYGWIN))
248           break;
249
250       create_xemacs_root (backslash (root_dir),
251                           root_scope == IDC_ROOT_SYSTEM ? 1 : 0,
252                           install_type == IDC_INSTALL_NATIVE ? 1 : 0);
253
254       switch (source)
255         {
256         case IDC_SOURCE_NETINST:
257           NEXT (IDD_NET);
258           break;
259         case IDC_SOURCE_CWD:
260           NEXT (IDD_S_FROM_CWD);
261           break;
262         default:
263           msg ("source is default? %d\n", source);
264           NEXT (0);
265         }
266       break;
267
268     case IDC_BACK:
269       save_dialog (h);
270       NEXT (IDD_LOCAL_DIR);
271       break;
272
273     case IDCANCEL:
274       NEXT (0);
275       break;
276     }
277   return FALSE;
278 }
279
280 static BOOL CALLBACK
281 dialog_proc (HWND h, UINT message, WPARAM wParam, LPARAM lParam)
282 {
283   switch (message)
284     {
285     case WM_INITDIALOG:
286       load_dialog (h);
287       return FALSE;
288     case WM_COMMAND:
289       return HANDLE_WM_COMMAND (h, wParam, lParam, dialog_cmd);
290     }
291   return FALSE;
292 }
293
294 static void
295 set_default_root ()
296 {
297   change_default_root (IDC_INSTALL_NATIVE);
298   root_scope = (is_admin()) ? IDC_ROOT_SYSTEM : IDC_ROOT_USER;
299   root_dir_default = 1;
300 }
301
302 void
303 do_root (HINSTANCE h)
304 {
305   int rv = 0;
306   // init will have read a previous root
307   if (!root_dir)
308     set_default_root ();
309
310   rv = DialogBox (h, MAKEINTRESOURCE (IDD_ROOT), 0, dialog_proc);
311   if (rv == -1)
312     fatal (IDS_DIALOG_FAILED);
313
314   log (0, "root: %s %s %s", root_dir,
315        (install_type == IDC_INSTALL_NATIVE) ? "native" : "cygwin",
316        (root_scope == IDC_ROOT_USER) ? "user" : "system");
317 }
318