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 /* 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. */
22 #include "LogSingleton.h"
35 #include "package_db.h"
37 #include "propsheet.h"
39 #include "getopt++/StringOption.h"
41 StringOption
RootOption ("", 'R', "root", IDS_HELPTEXT_ROOT
, false);
43 static 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
},
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
},
57 static int su
[] = { IDC_ROOT_SYSTEM
, IDC_ROOT_USER
, 0 };
59 static std::string orig_root_dir
;
62 RootPage::check_if_enable_next (HWND h
)
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
);
74 rbset (h
, su
, root_scope
);
75 eset (h
, IDC_ROOT_DIR
, get_root_dir ());
81 root_scope
= rbget (h
, su
);
82 set_root_dir (egetString (h
, IDC_ROOT_DIR
));
86 browse_cb (HWND h
, UINT msg
, LPARAM lp
, LPARAM data
)
90 case BFFM_INITIALIZED
:
91 if (get_root_dir ().size())
92 SendMessage (h
, BFFM_SETSELECTION
, TRUE
, (LPARAM
) get_root_dir ().c_str());
101 std::wstring title
= LoadStringW(IDS_ROOT_BROWSE_TITLE
);
103 wchar_t wname
[MAX_PATH
];
105 memset (&bi
, 0, sizeof (bi
));
107 bi
.pszDisplayName
= wname
;
108 bi
.lpszTitle
= title
.c_str();
109 bi
.ulFlags
= BIF_RETURNONLYFSDIRS
;
112 /* SHGetPathFromIDList doesn't handle path length > MAX_PATH. */
114 pidl
= SHBrowseForFolderW (&bi
);
118 if (SHGetPathFromIDList (pidl
, name
))
119 eset (h
, IDC_ROOT_DIR
, name
);
124 directory_is_absolute ()
126 const std::string
&r
= get_root_dir ();
127 if (isalpha (r
[0]) && r
[1] == ':' && isdirsep (r
[2]))
133 directory_is_rootdir ()
135 const std::string
&r
= get_root_dir ();
136 size_t pos
= r
.find_first_of ("/\\");
137 if (pos
!= std::string::npos
)
139 while (isdirsep (r
[++pos
]))
148 directory_has_spaces ()
150 if (std::string(get_root_dir()).find(' ') != std::string::npos
)
156 directory_contains_wrong_version (HWND h
)
159 std::string cygwin_dll
= get_root_dir() + "\\bin\\cygwin1.dll";
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.
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
)
176 IMAGE_NT_HEADERS32 nt_header
;
179 ReadFile (fh
, &hdr
, sizeof hdr
, &read
, NULL
);
181 if (read
!= sizeof hdr
)
182 fh
= INVALID_HANDLE_VALUE
;
185 /* 32 bit setup and 32 bit inst? */
186 if (hdr
.nt_header
.FileHeader
.Machine
== IMAGE_FILE_MACHINE_I386
189 /* 64 bit setup and 64 bit inst? */
190 if (hdr
.nt_header
.FileHeader
.Machine
== IMAGE_FILE_MACHINE_AMD64
195 if (fh
== INVALID_HANDLE_VALUE
)
198 std::string cygcheck_exe
= get_root_dir() + "\\bin\\cygcheck.exe";
200 /* Probably new installation */
201 if (!GetBinaryType (cygcheck_exe
.c_str (), &type
))
203 is_new_install
= true;
206 /* 64 bit setup and 64 bit inst? */
207 if (type
== SCS_32BIT_BINARY
&& !is_64bit
)
209 /* 32 bit setup and 32 bit inst? */
210 if (type
== SCS_64BIT_BINARY
&& is_64bit
)
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
);
223 RootPage::OnMessageCmd (int id
, HWND hwndctl
, UINT code
)
229 case IDC_ROOT_SYSTEM
:
231 check_if_enable_next (GetHWND ());
234 case IDC_ROOT_BROWSE
:
243 RootPage::RootPage ()
245 sizeProcessor
.AddControlInfo (RootControlsInfo
);
251 return PropertyPage::Create (IDD_ROOT
);
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();
263 if (!nt_sec
.isRunAsAdmin())
265 // disable IDC_ROOT_SYSTEM if not running as admin
266 EnableWindow(GetDlgItem(IDC_ROOT_SYSTEM
), FALSE
);
267 root_scope
= IDC_ROOT_USER
;
271 set_default_root_scope();
274 load_dialog (GetHWND ());
278 RootPage::OnActivate ()
280 check_if_enable_next (GetHWND ());
284 RootPage::wantsActivation() const
286 return (source
!= IDC_SOURCE_DOWNLOAD
);
296 if (!directory_is_absolute ())
298 note (h
, IDS_ROOT_ABSOLUTE
);
301 else if (get_root_dir() != orig_root_dir
&&
302 directory_is_rootdir () && (IDNO
== yesno (h
, IDS_ROOT_SLASH
)))
304 else if (directory_has_spaces () && (IDNO
== yesno (h
, IDS_ROOT_SPACE
)))
306 else if (directory_contains_wrong_version (h
))
309 Log (LOG_PLAIN
) << "root: " << get_root_dir ()
310 << (root_scope
== IDC_ROOT_USER
? " user" : " system") << endLog
;
312 if (root_scope
== IDC_ROOT_SYSTEM
)
313 nt_sec
.setAdminGroup ();
315 nt_sec
.resetPrimaryGroup ();
330 RootPage::OnUnattended ()