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. */
21 static const char *cvsid
=
27 #include "LogSingleton.h"
40 #include "package_db.h"
43 #include "getopt++/StringOption.h"
47 StringOption
RootOption ("", 'R', "root", "Root installation directory", false);
49 static ControlAdjuster::ControlInfo RootControlsInfo
[] = {
50 { IDC_ROOTDIR_GRP
, CP_STRETCH
, CP_TOP
},
51 { IDC_ROOT_DIR
, CP_STRETCH
, CP_TOP
},
52 { IDC_ROOT_BROWSE
, CP_RIGHT
, CP_TOP
},
54 { IDC_INSTALLFOR_GRP
, CP_STRETCH
, CP_STRETCH
},
55 { IDC_ROOT_SYSTEM
, CP_LEFT
, CP_TOP
},
56 { IDC_ALLUSERS_TEXT
, CP_STRETCH
, CP_TOP
},
57 { IDC_ROOT_USER
, CP_LEFT
, CP_BOTTOM
},
58 { IDC_JUSTME_TEXT
, CP_STRETCH
, CP_BOTTOM
},
63 static int su
[] = { IDC_ROOT_SYSTEM
, IDC_ROOT_USER
, 0 };
65 static string orig_root_dir
;
68 check_if_enable_next (HWND h
)
70 EnableWindow (GetDlgItem (h
, IDOK
),
71 egetString (h
, IDC_ROOT_DIR
).size() && root_scope
);
77 rbset (h
, su
, root_scope
);
78 eset (h
, IDC_ROOT_DIR
, get_root_dir ());
79 check_if_enable_next (h
);
85 root_scope
= rbget (h
, su
);
86 set_root_dir (egetString (h
, IDC_ROOT_DIR
));
90 browse_cb (HWND h
, UINT msg
, LPARAM lp
, LPARAM data
)
94 case BFFM_INITIALIZED
:
95 if (get_root_dir ().size())
96 SendMessage (h
, BFFM_SETSELECTION
, TRUE
, (LPARAM
) get_root_dir ().c_str());
106 /* SHGetPathFromIDList doesn't handle path length > MAX_PATH. */
109 memset (&bi
, 0, sizeof (bi
));
111 bi
.pszDisplayName
= name
;
112 bi
.lpszTitle
= "Select an installation root directory";
113 bi
.ulFlags
= BIF_RETURNONLYFSDIRS
;
115 pidl
= SHBrowseForFolder (&bi
);
118 if (SHGetPathFromIDList (pidl
, name
))
119 eset (h
, IDC_ROOT_DIR
, name
);
124 directory_is_absolute ()
127 const char *r
= get_root_dir ().c_str();
128 if (isalpha (r
[0]) && r
[1] == ':' && (r
[2] == '\\' || r
[2] == '/'))
136 directory_is_rootdir ()
139 for (const char *c
= get_root_dir().c_str(); *c
; c
++)
140 if (isdirsep (c
[0]) && c
[1] && !isdirsep (c
[1]))
146 directory_has_spaces ()
148 if (std::string(get_root_dir()).find(' ') != std::string::npos
)
154 directory_contains_wrong_version (HWND h
)
158 std::string cygwin_dll
= get_root_dir() + "\\bin\\cygwin1.dll";
160 /* Check if we have a cygwin1.dll. If not, this is a new install.
161 If yes, check if the target machine type of this setup version is the
162 same as the machine type of the install Cygwin DLL. If yes, just go
163 ahead. If not, show a message and indicate this to the caller.
165 If anything goes wrong reading the header of cygwin1.dll, we check
166 cygcheck.exe's binary type. This also covers the situation that the
167 installed cygwin1.dll is broken for some reason. */
168 fh
= CreateFileA (cygwin_dll
.c_str (), GENERIC_READ
, FILE_SHARE_VALID_FLAGS
,
169 NULL
, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, NULL
);
170 if (fh
!= INVALID_HANDLE_VALUE
)
175 IMAGE_NT_HEADERS32 nt_header
;
178 ReadFile (fh
, &hdr
, sizeof hdr
, &read
, NULL
);
180 if (read
!= sizeof hdr
)
181 fh
= INVALID_HANDLE_VALUE
;
184 /* 32 bit setup and 32 bit inst? */
185 if (hdr
.nt_header
.FileHeader
.Machine
== IMAGE_FILE_MACHINE_I386
188 /* 64 bit setup and 64 bit inst? */
189 if (hdr
.nt_header
.FileHeader
.Machine
== IMAGE_FILE_MACHINE_AMD64
194 if (fh
== INVALID_HANDLE_VALUE
)
197 std::string cygcheck_exe
= get_root_dir() + "\\bin\\cygcheck.exe";
199 /* Probably new installation */
200 if (!GetBinaryType (cygcheck_exe
.c_str (), &type
))
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 snprintf (text
, sizeof text
,
214 "You're trying to install a %s bit version of Cygwin into a directory\n"
215 "containing a %s bit version of Cygwin. Continuing to do so would\n"
216 "break the existing installation.\n\n"
217 "Either run http://cygwin.com/setup-%s.exe to update your\n"
218 "existing %s bit installation of Cygwin, or choose another directory\n"
219 "for your %s bit installation.",
221 is_64bit
? "x86" : "x86_64",
222 inst_ver
, setup_ver
);
223 MessageBox (h
, text
, "Target CPU mismatch", MB_OK
);
228 RootPage::OnMessageCmd (int id
, HWND hwndctl
, UINT code
)
234 case IDC_ROOT_SYSTEM
:
236 check_if_enable_next (GetHWND ());
239 case IDC_ROOT_BROWSE
:
248 RootPage::RootPage ()
250 sizeProcessor
.AddControlInfo (RootControlsInfo
);
256 return PropertyPage::Create (IDD_ROOT
);
262 if (((string
)RootOption
).size())
263 set_root_dir((string
)RootOption
);
264 if (!get_root_dir ().size())
265 read_mounts (std::string ());
266 orig_root_dir
= get_root_dir();
267 load_dialog (GetHWND ());
271 RootPage::wantsActivation() const
273 return (source
!= IDC_SOURCE_DOWNLOAD
);
283 if (!directory_is_absolute ())
285 note (h
, IDS_ROOT_ABSOLUTE
);
288 else if (get_root_dir() != orig_root_dir
&&
289 directory_is_rootdir () && (IDNO
== yesno (h
, IDS_ROOT_SLASH
)))
291 else if (directory_has_spaces () && (IDNO
== yesno (h
, IDS_ROOT_SPACE
)))
293 else if (directory_contains_wrong_version (h
))
296 Log (LOG_PLAIN
) << "root: " << get_root_dir ()
297 << (root_scope
== IDC_ROOT_USER
? " user" : " system") << endLog
;
312 RootPage::OnUnattended ()