]> cygwin.com Git - cygwin-apps/setup.git/blame_incremental - root.cc
Added dpiAwareness element to manifest
[cygwin-apps/setup.git] / root.cc
... / ...
CommitLineData
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 "root.h"
21
22#include "LogSingleton.h"
23
24#include "win32.h"
25#include <shlobj.h>
26#include <stdio.h>
27#include <stdlib.h>
28#include <ctype.h>
29
30#include "ini.h"
31#include "dialog.h"
32#include "resource.h"
33#include "state.h"
34#include "msg.h"
35#include "package_db.h"
36#include "mount.h"
37#include "propsheet.h"
38
39#include "getopt++/StringOption.h"
40
41StringOption RootOption ("", 'R', "root", IDS_HELPTEXT_ROOT, false);
42
43static ControlAdjuster::ControlInfo RootControlsInfo[] = {
44 { IDC_ROOTDIR_GRP, CP_STRETCH, CP_TOP },
45 { IDC_ROOT_DIR, CP_STRETCH, CP_TOP },
46 { IDC_ROOT_BROWSE, CP_RIGHT, CP_TOP },
47
48 { IDC_INSTALLFOR_GRP, CP_STRETCH, CP_STRETCH },
49 { IDC_ROOT_SYSTEM, CP_LEFT, CP_TOP },
50 { IDC_ALLUSERS_TEXT, CP_STRETCH, CP_TOP },
51 { IDC_ROOT_USER, CP_LEFT, CP_BOTTOM },
52 { IDC_JUSTME_TEXT, CP_STRETCH, CP_BOTTOM },
53
54 {0, CP_LEFT, CP_TOP}
55};
56
57static int su[] = { IDC_ROOT_SYSTEM, IDC_ROOT_USER, 0 };
58
59static std::string orig_root_dir;
60
61void
62RootPage::check_if_enable_next (HWND h)
63{
64 DWORD ButtonFlags = PSWIZB_BACK;
65 // if there's something in the root dir box, and we have a scope, enable next
66 if (egetString (h, IDC_ROOT_DIR).size() && root_scope)
67 ButtonFlags |= PSWIZB_NEXT;
68 GetOwner ()->SetButtons (ButtonFlags);
69}
70
71static void
72load_dialog (HWND h)
73{
74 rbset (h, su, root_scope);
75 eset (h, IDC_ROOT_DIR, get_root_dir ());
76}
77
78static void
79save_dialog (HWND h)
80{
81 root_scope = rbget (h, su);
82 set_root_dir (egetString (h, IDC_ROOT_DIR));
83}
84
85static int CALLBACK
86browse_cb (HWND h, UINT msg, LPARAM lp, LPARAM data)
87{
88 switch (msg)
89 {
90 case BFFM_INITIALIZED:
91 if (get_root_dir ().size())
92 SendMessage (h, BFFM_SETSELECTION, TRUE, (LPARAM) get_root_dir ().c_str());
93 break;
94 }
95 return 0;
96}
97
98static void
99browse (HWND h)
100{
101 std::wstring title = LoadStringW(IDS_ROOT_BROWSE_TITLE);
102
103 wchar_t wname[MAX_PATH];
104 BROWSEINFOW bi;
105 memset (&bi, 0, sizeof (bi));
106 bi.hwndOwner = h;
107 bi.pszDisplayName = wname;
108 bi.lpszTitle = title.c_str();
109 bi.ulFlags = BIF_RETURNONLYFSDIRS;
110 bi.lpfn = browse_cb;
111
112 /* SHGetPathFromIDList doesn't handle path length > MAX_PATH. */
113 LPITEMIDLIST pidl;
114 pidl = SHBrowseForFolderW (&bi);
115 if (pidl)
116 {
117 CHAR name[MAX_PATH];
118 if (SHGetPathFromIDList (pidl, name))
119 eset (h, IDC_ROOT_DIR, name);
120 }
121}
122
123static int
124directory_is_absolute ()
125{
126 const std::string &r = get_root_dir ();
127 if (isalpha (r[0]) && r[1] == ':' && isdirsep (r[2]))
128 return 1;
129 return 0;
130}
131
132static int
133directory_is_rootdir ()
134{
135 const std::string &r = get_root_dir ();
136 size_t pos = r.find_first_of ("/\\");
137 if (pos != std::string::npos)
138 {
139 while (isdirsep (r[++pos]))
140 ;
141 if (r[pos])
142 return 0;
143 }
144 return 1;
145}
146
147static int
148directory_has_spaces ()
149{
150 if (std::string(get_root_dir()).find(' ') != std::string::npos)
151 return 1;
152 return 0;
153}
154
155static int
156directory_contains_wrong_version (HWND h)
157{
158 HANDLE fh;
159 std::string cygwin_dll = get_root_dir() + "\\bin\\cygwin1.dll";
160
161 /* Check if we have a cygwin1.dll. If not, this is a new install.
162 If yes, check if the target machine type of this setup version is the
163 same as the machine type of the install Cygwin DLL. If yes, just go
164 ahead. If not, show a message and indicate this to the caller.
165
166 If anything goes wrong reading the header of cygwin1.dll, we check
167 cygcheck.exe's binary type. This also covers the situation that the
168 installed cygwin1.dll is broken for some reason. */
169 fh = CreateFileA (cygwin_dll.c_str (), GENERIC_READ, FILE_SHARE_VALID_FLAGS,
170 NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
171 if (fh != INVALID_HANDLE_VALUE)
172 {
173 DWORD read = 0;
174 struct {
175 LONG dos_header[32];
176 IMAGE_NT_HEADERS32 nt_header;
177 } hdr;
178
179 ReadFile (fh, &hdr, sizeof hdr, &read, NULL);
180 CloseHandle (fh);
181 if (read != sizeof hdr)
182 fh = INVALID_HANDLE_VALUE;
183 else
184 {
185 /* 32 bit setup and 32 bit inst? */
186 if (hdr.nt_header.FileHeader.Machine == IMAGE_FILE_MACHINE_I386
187 && !is_64bit)
188 return 0;
189 /* 64 bit setup and 64 bit inst? */
190 if (hdr.nt_header.FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64
191 && is_64bit)
192 return 0;
193 }
194 }
195 if (fh == INVALID_HANDLE_VALUE)
196 {
197 DWORD type;
198 std::string cygcheck_exe = get_root_dir() + "\\bin\\cygcheck.exe";
199
200 /* Probably new installation */
201 if (!GetBinaryType (cygcheck_exe.c_str (), &type))
202 {
203 is_new_install = true;
204 return 0;
205 }
206 /* 64 bit setup and 64 bit inst? */
207 if (type == SCS_32BIT_BINARY && !is_64bit)
208 return 0;
209 /* 32 bit setup and 32 bit inst? */
210 if (type == SCS_64BIT_BINARY && is_64bit)
211 return 0;
212 }
213
214 /* Forestall mixing. */
215 const char *setup_ver = is_64bit ? "64" : "32";
216 const char *inst_ver = is_64bit ? "32" : "64";
217 mbox (h, IDS_MIXED_BITNESS_ERROR, MB_OK,
218 setup_ver, inst_ver, is_64bit ? "x86" : "x86_64", inst_ver, setup_ver);
219 return 1;
220}
221
222bool
223RootPage::OnMessageCmd (int id, HWND hwndctl, UINT code)
224{
225 switch (id)
226 {
227
228 case IDC_ROOT_DIR:
229 case IDC_ROOT_SYSTEM:
230 case IDC_ROOT_USER:
231 check_if_enable_next (GetHWND ());
232 break;
233
234 case IDC_ROOT_BROWSE:
235 browse (GetHWND ());
236 break;
237 default:
238 return false;
239 }
240 return true;
241}
242
243RootPage::RootPage ()
244{
245 sizeProcessor.AddControlInfo (RootControlsInfo);
246}
247
248bool
249RootPage::Create ()
250{
251 return PropertyPage::Create (IDD_ROOT);
252}
253
254void
255RootPage::OnInit ()
256{
257 if (((std::string)RootOption).size())
258 set_root_dir((std::string)RootOption);
259 if (!get_root_dir ().size())
260 read_mounts (std::string ());
261 orig_root_dir = get_root_dir();
262
263 if (!nt_sec.isRunAsAdmin())
264 {
265 // disable IDC_ROOT_SYSTEM if not running as admin
266 EnableWindow(GetDlgItem(IDC_ROOT_SYSTEM), FALSE);
267 root_scope = IDC_ROOT_USER;
268 }
269 else
270 {
271 set_default_root_scope();
272 }
273
274 load_dialog (GetHWND ());
275}
276
277void
278RootPage::OnActivate ()
279{
280 check_if_enable_next (GetHWND ());
281}
282
283bool
284RootPage::wantsActivation() const
285{
286 return (source != IDC_SOURCE_DOWNLOAD);
287}
288
289long
290RootPage::OnNext ()
291{
292 HWND h = GetHWND ();
293
294 save_dialog (h);
295
296 if (!directory_is_absolute ())
297 {
298 note (h, IDS_ROOT_ABSOLUTE);
299 return -1;
300 }
301 else if (get_root_dir() != orig_root_dir &&
302 directory_is_rootdir () && (IDNO == yesno (h, IDS_ROOT_SLASH)))
303 return -1;
304 else if (directory_has_spaces () && (IDNO == yesno (h, IDS_ROOT_SPACE)))
305 return -1;
306 else if (directory_contains_wrong_version (h))
307 return -1;
308
309 Log (LOG_PLAIN) << "root: " << get_root_dir ()
310 << (root_scope == IDC_ROOT_USER ? " user" : " system") << endLog;
311
312 if (root_scope == IDC_ROOT_SYSTEM)
313 nt_sec.setAdminGroup ();
314 else
315 nt_sec.resetPrimaryGroup ();
316
317 return 0;
318}
319
320long
321RootPage::OnBack ()
322{
323 HWND h = GetHWND ();
324
325 save_dialog (h);
326 return 0;
327}
328
329long
330RootPage::OnUnattended ()
331{
332 return OnNext();
333}
This page took 0.024468 seconds and 6 git commands to generate.