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", "Root installation directory", 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());
102 /* SHGetPathFromIDList doesn't handle path length > MAX_PATH. */
105 memset (&bi
, 0, sizeof (bi
));
107 bi
.pszDisplayName
= name
;
108 bi
.lpszTitle
= "Select an installation root directory";
109 bi
.ulFlags
= BIF_RETURNONLYFSDIRS
;
111 pidl
= SHBrowseForFolder (&bi
);
114 if (SHGetPathFromIDList (pidl
, name
))
115 eset (h
, IDC_ROOT_DIR
, name
);
120 directory_is_absolute ()
122 const std::string
&r
= get_root_dir ();
123 if (isalpha (r
[0]) && r
[1] == ':' && isdirsep (r
[2]))
129 directory_is_rootdir ()
131 const std::string
&r
= get_root_dir ();
132 size_t pos
= r
.find_first_of ("/\\");
133 if (pos
!= std::string::npos
)
135 while (isdirsep (r
[++pos
]))
144 directory_has_spaces ()
146 if (std::string(get_root_dir()).find(' ') != std::string::npos
)
152 directory_contains_wrong_version (HWND h
)
155 std::string cygwin_dll
= get_root_dir() + "\\bin\\cygwin1.dll";
157 /* Check if we have a cygwin1.dll. If not, this is a new install.
158 If yes, check if the target machine type of this setup version is the
159 same as the machine type of the install Cygwin DLL. If yes, just go
160 ahead. If not, show a message and indicate this to the caller.
162 If anything goes wrong reading the header of cygwin1.dll, we check
163 cygcheck.exe's binary type. This also covers the situation that the
164 installed cygwin1.dll is broken for some reason. */
165 fh
= CreateFileA (cygwin_dll
.c_str (), GENERIC_READ
, FILE_SHARE_VALID_FLAGS
,
166 NULL
, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, NULL
);
167 if (fh
!= INVALID_HANDLE_VALUE
)
172 IMAGE_NT_HEADERS32 nt_header
;
175 ReadFile (fh
, &hdr
, sizeof hdr
, &read
, NULL
);
177 if (read
!= sizeof hdr
)
178 fh
= INVALID_HANDLE_VALUE
;
181 /* 32 bit setup and 32 bit inst? */
182 if (hdr
.nt_header
.FileHeader
.Machine
== IMAGE_FILE_MACHINE_I386
185 /* 64 bit setup and 64 bit inst? */
186 if (hdr
.nt_header
.FileHeader
.Machine
== IMAGE_FILE_MACHINE_AMD64
191 if (fh
== INVALID_HANDLE_VALUE
)
194 std::string cygcheck_exe
= get_root_dir() + "\\bin\\cygcheck.exe";
196 /* Probably new installation */
197 if (!GetBinaryType (cygcheck_exe
.c_str (), &type
))
199 is_new_install
= true;
202 /* 64 bit setup and 64 bit inst? */
203 if (type
== SCS_32BIT_BINARY
&& !is_64bit
)
205 /* 32 bit setup and 32 bit inst? */
206 if (type
== SCS_64BIT_BINARY
&& is_64bit
)
210 /* Forestall mixing. */
211 const char *setup_ver
= is_64bit
? "64" : "32";
212 const char *inst_ver
= is_64bit
? "32" : "64";
213 mbox (h
, IDS_MIXED_BITNESS_ERROR
, MB_OK
,
214 setup_ver
, inst_ver
, is_64bit
? "x86" : "x86_64", inst_ver
, setup_ver
);
219 RootPage::OnMessageCmd (int id
, HWND hwndctl
, UINT code
)
225 case IDC_ROOT_SYSTEM
:
227 check_if_enable_next (GetHWND ());
230 case IDC_ROOT_BROWSE
:
239 RootPage::RootPage ()
241 sizeProcessor
.AddControlInfo (RootControlsInfo
);
247 return PropertyPage::Create (IDD_ROOT
);
253 if (((std::string
)RootOption
).size())
254 set_root_dir((std::string
)RootOption
);
255 if (!get_root_dir ().size())
256 read_mounts (std::string ());
257 orig_root_dir
= get_root_dir();
258 load_dialog (GetHWND ());
262 RootPage::OnActivate ()
264 check_if_enable_next (GetHWND ());
268 RootPage::wantsActivation() const
270 return (source
!= IDC_SOURCE_DOWNLOAD
);
280 if (!directory_is_absolute ())
282 note (h
, IDS_ROOT_ABSOLUTE
);
285 else if (get_root_dir() != orig_root_dir
&&
286 directory_is_rootdir () && (IDNO
== yesno (h
, IDS_ROOT_SLASH
)))
288 else if (directory_has_spaces () && (IDNO
== yesno (h
, IDS_ROOT_SPACE
)))
290 else if (directory_contains_wrong_version (h
))
293 Log (LOG_PLAIN
) << "root: " << get_root_dir ()
294 << (root_scope
== IDC_ROOT_USER
? " user" : " system") << endLog
;
309 RootPage::OnUnattended ()