]>
Commit | Line | Data |
---|---|---|
23c9e63c DD |
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 | ||
8e9aa511 | 16 | /* The purpose of this file is to install all the packages selected in |
23c9e63c DD |
17 | the install list (in ini.h). Note that we use a separate thread to |
18 | maintain the progress dialog, so we avoid the complexity of | |
19 | handling two tasks in one thread. We also create or update all the | |
b24c88b3 | 20 | files in /etc/setup/\* and create the mount points. */ |
23c9e63c | 21 | |
b24c88b3 | 22 | #if 0 |
ad3c7385 | 23 | static const char *cvsid = "\n%%% $Id$\n"; |
b24c88b3 | 24 | #endif |
8507f105 | 25 | |
23c9e63c DD |
26 | #include "win32.h" |
27 | #include "commctrl.h" | |
28 | ||
29 | #include <stdio.h> | |
904d24fe | 30 | #include <stdlib.h> |
4a83b7b0 | 31 | #include <unistd.h> |
23c9e63c DD |
32 | #include <sys/types.h> |
33 | #include <sys/stat.h> | |
34 | #include <errno.h> | |
ab57ceaa RC |
35 | #include <process.h> |
36 | ||
87c42361 | 37 | #include "zlib/zlib.h" |
23c9e63c DD |
38 | |
39 | #include "resource.h" | |
40 | #include "ini.h" | |
41 | #include "dialog.h" | |
23c9e63c | 42 | #include "geturl.h" |
23c9e63c | 43 | #include "state.h" |
23c9e63c DD |
44 | #include "diskfull.h" |
45 | #include "msg.h" | |
46 | #include "mount.h" | |
89b1a15b | 47 | #include "log.h" |
a351e48c | 48 | #include "mount.h" |
c46a33a9 | 49 | #include "filemanip.h" |
b24c88b3 RC |
50 | #include "io_stream.h" |
51 | #include "compress.h" | |
52 | #include "compress_gz.h" | |
53 | #include "archive.h" | |
54 | #include "archive_tar.h" | |
8e9aa511 | 55 | #include "script.h" |
4a83b7b0 | 56 | |
fa0c0d10 RC |
57 | #include "package_db.h" |
58 | #include "package_meta.h" | |
bb849dbd RC |
59 | #include "package_version.h" |
60 | #include "package_source.h" | |
fa0c0d10 | 61 | |
4a83b7b0 | 62 | #include "port.h" |
23c9e63c | 63 | |
ab57ceaa RC |
64 | #include "threebar.h" |
65 | extern ThreeBarProgressPage Progress; | |
23c9e63c DD |
66 | |
67 | static int total_bytes = 0; | |
68 | static int total_bytes_sofar = 0; | |
69 | static int package_bytes = 0; | |
70 | ||
23c9e63c DD |
71 | static void |
72 | init_dialog () | |
73 | { | |
ab57ceaa RC |
74 | Progress.SetText2 (""); |
75 | Progress.SetText3 (""); | |
23c9e63c DD |
76 | } |
77 | ||
78 | static void | |
79 | progress (int bytes) | |
80 | { | |
ab57ceaa | 81 | if (package_bytes > 0) |
23c9e63c | 82 | { |
ab57ceaa | 83 | Progress.SetBar1 (bytes, package_bytes); |
23c9e63c DD |
84 | } |
85 | ||
ab57ceaa | 86 | if (total_bytes > 0) |
23c9e63c | 87 | { |
ab57ceaa | 88 | Progress.SetBar2 (total_bytes_sofar + bytes, total_bytes); |
23c9e63c | 89 | } |
23c9e63c DD |
90 | } |
91 | ||
b24c88b3 | 92 | static const char *standard_dirs[] = { |
1a18aed7 | 93 | "/bin", |
904d24fe | 94 | "/etc", |
1a18aed7 | 95 | "/lib", |
904d24fe | 96 | "/tmp", |
4a83b7b0 | 97 | "/usr", |
1a18aed7 DD |
98 | "/usr/bin", |
99 | "/usr/lib", | |
ef45c299 | 100 | "/usr/src", |
4a83b7b0 | 101 | "/usr/local", |
1a18aed7 DD |
102 | "/usr/local/bin", |
103 | "/usr/local/etc", | |
104 | "/usr/local/lib", | |
904d24fe | 105 | "/usr/tmp", |
1a18aed7 | 106 | "/var/run", |
904d24fe DD |
107 | "/var/tmp", |
108 | 0 | |
109 | }; | |
110 | ||
ad3c7385 RC |
111 | static int num_installs, num_replacements, num_uninstalls; |
112 | static void uninstall_one (packagemeta &); | |
113 | static int replace_one (packagemeta &); | |
3c054baf RC |
114 | static int install_one_source (packagemeta &, packagesource &, String const &, |
115 | String const &, package_type_t); | |
ad3c7385 | 116 | static bool rebootneeded; |
3b9077d4 | 117 | |
fa0c0d10 | 118 | /* FIXME: upgrades should be a method too */ |
3b9077d4 | 119 | static void |
cbfc4215 | 120 | uninstall_one (packagemeta & pkgm) |
3b9077d4 | 121 | { |
ab57ceaa | 122 | Progress.SetText1 ("Uninstalling..."); |
3c054baf | 123 | Progress.SetText2 (pkgm.name.cstr_oneuse()); |
1ac649ed | 124 | log (LOG_PLAIN, String("Uninstalling ") + pkgm.name); |
ab57ceaa RC |
125 | pkgm.uninstall (); |
126 | num_uninstalls++; | |
3b9077d4 DD |
127 | } |
128 | ||
ad3c7385 RC |
129 | /* uninstall and install a package, preserving configuration |
130 | * files and the like. | |
131 | * This method should also know about replacing in-use file. | |
132 | * ASSUMPTIONS: pkgm is installed. | |
133 | * pkgm has a desired package. | |
134 | */ | |
135 | static int | |
136 | replace_one (packagemeta & pkg) | |
137 | { | |
138 | int errors = 0; | |
139 | Progress.SetText1 ("Replacing..."); | |
3c054baf | 140 | Progress.SetText2 (pkg.name.cstr_oneuse()); |
1ac649ed | 141 | log (LOG_PLAIN, String( "Replacing ") + pkg.name); |
ad3c7385 RC |
142 | pkg.uninstall (); |
143 | ||
144 | errors += | |
6dc75764 | 145 | install_one_source (pkg, pkg.desired->bin, "cygfile://","/", package_binary); |
ad3c7385 RC |
146 | if (!errors) |
147 | pkg.installed = pkg.desired; | |
148 | num_replacements++; | |
149 | return errors; | |
150 | } | |
42bf5b92 | 151 | |
bb849dbd RC |
152 | |
153 | /* install one source at a given prefix. */ | |
3b9077d4 | 154 | static int |
bb849dbd | 155 | install_one_source (packagemeta & pkgm, packagesource & source, |
3c054baf | 156 | String const &prefixURL, String const &prefixPath, package_type_t type) |
3b9077d4 DD |
157 | { |
158 | int errors = 0; | |
ab57ceaa | 159 | Progress.SetText2 (source.Base ()); |
7c6ef2c3 | 160 | if (!source.Cached () || !io_stream::exists (source.Cached ())) |
c46a33a9 | 161 | { |
ab57ceaa | 162 | note (NULL, IDS_ERR_OPEN_READ, source.Cached (), "No such file"); |
bb849dbd | 163 | return 1; |
c46a33a9 | 164 | } |
bb849dbd RC |
165 | io_stream *lst = 0; |
166 | if (type == package_binary) | |
c46a33a9 | 167 | { |
bb849dbd RC |
168 | io_stream *tmp = |
169 | io_stream:: | |
3c054baf | 170 | open (String ("cygfile:///etc/setup/") + pkgm.name + ".lst.gz", |
bb849dbd RC |
171 | "wb"); |
172 | lst = new compress_gz (tmp, "w9"); | |
173 | if (lst->error ()) | |
174 | { | |
175 | delete lst; | |
176 | lst = NULL; | |
177 | } | |
c46a33a9 | 178 | } |
b24c88b3 | 179 | |
bb849dbd | 180 | package_bytes = source.size; |
3b9077d4 | 181 | |
bb849dbd RC |
182 | char msg[64]; |
183 | strcpy (msg, "Installing"); | |
ab57ceaa | 184 | Progress.SetText1 (msg); |
1ac649ed | 185 | log (LOG_PLAIN, String (msg) + " " + source.Cached ()); |
bb849dbd RC |
186 | io_stream *tmp = io_stream::open (source.Cached (), "rb"); |
187 | archive *thefile = 0; | |
188 | if (tmp) | |
d4a4527d | 189 | { |
bb849dbd RC |
190 | io_stream *tmp2 = compress::decompress (tmp); |
191 | if (tmp2) | |
192 | thefile = archive::extract (tmp2); | |
193 | else | |
194 | thefile = archive::extract (tmp); | |
3b9077d4 | 195 | } |
bb849dbd RC |
196 | /* FIXME: potential leak of either *tmp or *tmp2 */ |
197 | if (thefile) | |
d4a4527d | 198 | { |
3c054baf RC |
199 | String fn; |
200 | while ((fn = thefile->next_file_name ()).size()) | |
bb849dbd RC |
201 | { |
202 | if (lst) | |
3c054baf RC |
203 | { |
204 | String tmp=fn + "\n"; | |
2fa7c5a4 | 205 | lst->write (tmp.cstr_oneuse(), tmp.size()); |
3c054baf RC |
206 | } |
207 | ||
208 | String canonicalfn = prefixPath + fn; | |
bb849dbd | 209 | |
3c054baf RC |
210 | Progress.SetText3 (canonicalfn.cstr_oneuse()); |
211 | log (LOG_BABBLE, String("Installing file ") + prefixURL + prefixPath + fn); | |
6dc75764 | 212 | if (archive::extract_file (thefile, prefixURL, prefixPath) != 0) |
bb849dbd | 213 | { |
ad3c7385 | 214 | //extract to temp location |
6dc75764 | 215 | if (archive::extract_file (thefile, prefixURL, prefixPath, ".new") != 0) |
ad3c7385 | 216 | { |
1ac649ed RC |
217 | log (LOG_PLAIN, |
218 | String("Unable to install file ") + | |
219 | prefixURL + prefixPath + fn); | |
ad3c7385 RC |
220 | errors++; |
221 | } | |
222 | else | |
223 | //switch Win32::OS | |
224 | { | |
225 | switch (Win32::OS ()) | |
226 | { | |
227 | case Win32::Win9x:{ | |
228 | /* Get the short file names */ | |
229 | char source[MAX_PATH]; | |
230 | unsigned int len = | |
1ac649ed RC |
231 | GetShortPathName (cygpath (String ("/") + fn + |
232 | ".new").cstr_oneuse(), | |
ad3c7385 RC |
233 | source, MAX_PATH); |
234 | if (!len || len > MAX_PATH) | |
235 | { | |
3c054baf | 236 | log (LOG_TIMESTAMP, |
ad3c7385 | 237 | "Unable to schedule reboot replacement of file %s with %s (Win32 Error %ld)", |
1ac649ed RC |
238 | cygpath (String ("/") + fn).cstr_oneuse(), |
239 | cygpath (String ("/") + fn + | |
240 | ".new").cstr_oneuse(), | |
ad3c7385 RC |
241 | GetLastError ()); |
242 | ++errors; | |
243 | } | |
244 | else | |
245 | { | |
246 | char dest[MAX_PATH]; | |
247 | len = | |
1ac649ed RC |
248 | GetShortPathName (cygpath (String ("/") + |
249 | fn).cstr_oneuse(), | |
250 | dest, MAX_PATH); | |
ad3c7385 RC |
251 | if (!len || len > MAX_PATH) |
252 | { | |
3c054baf | 253 | log (LOG_TIMESTAMP, |
ad3c7385 | 254 | "Unable to schedule reboot replacement of file %s with %s (Win32 Error %ld)", |
1ac649ed RC |
255 | cygpath (String ("/") + fn).cstr_oneuse(), |
256 | cygpath (String ("/") + fn + | |
257 | ".new").cstr_oneuse(), | |
ad3c7385 RC |
258 | GetLastError ()); |
259 | ++errors; | |
260 | ||
261 | } | |
262 | else | |
263 | /* trigger a replacement on reboot */ | |
264 | if (!WritePrivateProfileString | |
265 | ("rename", dest, source, "WININIT.INI")) | |
266 | { | |
3c054baf | 267 | log (LOG_TIMESTAMP, |
ad3c7385 | 268 | "Unable to schedule reboot replacement of file %s with %s (Win32 Error %ld)", |
1ac649ed RC |
269 | cygpath (String ("/") + fn).cstr_oneuse(), |
270 | cygpath (String ("/") + fn + | |
271 | ".new").cstr_oneuse(), | |
ad3c7385 RC |
272 | GetLastError ()); |
273 | ++errors; | |
274 | } | |
275 | ||
276 | } | |
277 | } | |
278 | break; | |
279 | case Win32::WinNT: | |
280 | /* XXX FIXME: prefix may not be / for in use files - | |
281 | * although it most likely is | |
282 | * - we need a io method to get win32 paths | |
283 | * or to wrap this system call | |
284 | */ | |
1ac649ed RC |
285 | if (!MoveFileEx (cygpath (String ("/") + fn + |
286 | ".new").cstr_oneuse(), | |
287 | cygpath (String ("/") + fn).cstr_oneuse(), | |
ad3c7385 RC |
288 | MOVEFILE_DELAY_UNTIL_REBOOT | |
289 | MOVEFILE_REPLACE_EXISTING)) | |
290 | { | |
3c054baf | 291 | log (LOG_TIMESTAMP, |
ad3c7385 | 292 | "Unable to schedule reboot replacement of file %s with %s (Win32 Error %ld)", |
1ac649ed RC |
293 | cygpath (String ("/") + fn).cstr_oneuse(), |
294 | cygpath (String ("/") + fn + ".new").cstr_oneuse(), | |
ad3c7385 RC |
295 | GetLastError ()); |
296 | ++errors; | |
297 | } | |
298 | else | |
299 | rebootneeded = true; | |
300 | break; | |
301 | } | |
302 | } | |
bb849dbd RC |
303 | } |
304 | ||
305 | progress (tmp->tell ()); | |
306 | num_installs++; | |
307 | } | |
308 | delete thefile; | |
309 | ||
310 | total_bytes_sofar += package_bytes; | |
d4a4527d | 311 | } |
3b9077d4 | 312 | |
90d14922 | 313 | |
bb849dbd RC |
314 | progress (0); |
315 | ||
3c054baf | 316 | int df = diskfull (get_root_dir ().cstr_oneuse()); |
ab57ceaa | 317 | Progress.SetBar3 (df); |
bb849dbd RC |
318 | |
319 | if (lst) | |
320 | delete lst; | |
321 | ||
322 | return errors; | |
323 | } | |
324 | ||
325 | /* install a package, install both the binary and source aspects if needed */ | |
326 | static int | |
327 | install_one (packagemeta & pkg) | |
328 | { | |
329 | int errors = 0; | |
330 | ||
ad3c7385 | 331 | if (pkg.installed != pkg.desired && pkg.desired->binpicked) |
ab57ceaa | 332 | { |
bb849dbd | 333 | errors += |
6dc75764 | 334 | install_one_source (pkg, pkg.desired->bin, "cygfile://","/", |
ab57ceaa RC |
335 | package_binary); |
336 | if (!errors) | |
337 | pkg.installed = pkg.desired; | |
338 | } | |
339 | if (pkg.desired->srcpicked) | |
340 | errors += | |
490717ef | 341 | install_one_source (pkg, pkg.desired->src, "cygfile://","/usr/src/", |
ab57ceaa | 342 | package_source); |
bb849dbd RC |
343 | |
344 | /* FIXME: make a upgrade method and reinstate this */ | |
345 | #if 0 | |
1ac649ed | 346 | String msg; |
c46a33a9 | 347 | if (!pkg->installed) |
1ac649ed | 348 | msg = "Installing"; |
c46a33a9 CF |
349 | else |
350 | { | |
351 | int n = strcmp (pi->version, pkg->installed->version); | |
352 | if (n < 0) | |
1ac649ed | 353 | msg = "Reverting"; |
c46a33a9 | 354 | else if (n == 0) |
1ac649ed | 355 | msg = "Reinstalling"; |
c46a33a9 | 356 | else |
1ac649ed | 357 | msg = "Upgrading"; |
c46a33a9 CF |
358 | } |
359 | ||
360 | switch (pkg->action) | |
3b9077d4 | 361 | { |
c46a33a9 | 362 | case ACTION_PREV: |
1ac649ed | 363 | msg += " previous version..."; |
3b9077d4 | 364 | break; |
c46a33a9 | 365 | case ACTION_CURR: |
1ac649ed | 366 | msg += "..."; |
3b9077d4 | 367 | break; |
c46a33a9 | 368 | case ACTION_TEST: |
1ac649ed | 369 | msg += " test version..."; |
42bf5b92 | 370 | break; |
b24c88b3 RC |
371 | default: |
372 | /* FIXME: log this somehow */ | |
373 | break; | |
3b9077d4 | 374 | } |
1ac649ed RC |
375 | SetWindowText (ins_action, msg.cstr_oneuse()); |
376 | log (LOG_PLAIN, msg + " " + file); | |
bb849dbd | 377 | #endif |
c46a33a9 | 378 | |
3b9077d4 DD |
379 | return errors; |
380 | } | |
381 | ||
72fd1d1e CF |
382 | static void |
383 | check_for_old_cygwin () | |
384 | { | |
385 | char buf[_MAX_PATH + sizeof ("\\cygwin1.dll")]; | |
386 | if (!GetSystemDirectory (buf, sizeof (buf))) | |
387 | return; | |
388 | strcat (buf, "\\cygwin1.dll"); | |
389 | if (_access (buf, 0) != 0) | |
390 | return; | |
391 | ||
392 | char msg[sizeof (buf) + 132]; | |
b24c88b3 RC |
393 | sprintf (msg, |
394 | "An old version of cygwin1.dll was found here:\r\n%s\r\nDelete?", | |
395 | buf); | |
396 | switch (MessageBox | |
397 | (NULL, msg, "What's that doing there?", | |
398 | MB_YESNO | MB_ICONQUESTION | MB_TASKMODAL)) | |
72fd1d1e CF |
399 | { |
400 | case IDYES: | |
401 | if (!DeleteFile (buf)) | |
402 | { | |
403 | sprintf (msg, "Couldn't delete file %s.\r\n" | |
b24c88b3 | 404 | "Is the DLL in use by another application?\r\n" |
7c7034e8 RC |
405 | "You should delete the old version of cygwin1.dll\r\n" |
406 | "at your earliest convenience.", buf); | |
b24c88b3 RC |
407 | MessageBox (NULL, buf, "Couldn't delete file", |
408 | MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL); | |
72fd1d1e CF |
409 | } |
410 | break; | |
411 | default: | |
b24c88b3 | 412 | break; |
72fd1d1e CF |
413 | } |
414 | ||
415 | return; | |
416 | } | |
417 | ||
ab57ceaa RC |
418 | static void |
419 | do_install_thread (HINSTANCE h, HWND owner) | |
23c9e63c | 420 | { |
3b9077d4 | 421 | int i; |
2a1a01e0 DD |
422 | int errors = 0; |
423 | ||
ad3c7385 RC |
424 | num_installs = 0, num_uninstalls = 0, num_replacements = 0; |
425 | rebootneeded = false; | |
3b9077d4 | 426 | |
50225eae | 427 | next_dialog = IDD_DESKTOP; |
23c9e63c | 428 | |
490717ef | 429 | io_stream::mkpath_p (PATH_TO_DIR, String ("file://") + get_root_dir ()); |
904d24fe | 430 | |
b24c88b3 | 431 | for (i = 0; standard_dirs[i]; i++) |
904d24fe | 432 | { |
1ac649ed | 433 | String p = cygpath (standard_dirs[i]); |
3c054baf | 434 | if (p.size()) |
490717ef | 435 | io_stream::mkpath_p (PATH_TO_DIR, String ("file://") + p); |
904d24fe DD |
436 | } |
437 | ||
1a18aed7 | 438 | /* Create /var/run/utmp */ |
b24c88b3 RC |
439 | io_stream *utmp = io_stream::open ("cygfile:///var/run/utmp", "wb"); |
440 | delete utmp; | |
1a18aed7 | 441 | |
23c9e63c DD |
442 | init_dialog (); |
443 | ||
444 | total_bytes = 0; | |
445 | total_bytes_sofar = 0; | |
446 | ||
3c054baf | 447 | int df = diskfull (get_root_dir ().cstr_oneuse()); |
ab57ceaa | 448 | Progress.SetBar3 (df); |
d07591a3 | 449 | |
0af2d779 CF |
450 | int istext = (root_text == IDC_ROOT_TEXT) ? 1 : 0; |
451 | int issystem = (root_scope == IDC_ROOT_SYSTEM) ? 1 : 0; | |
452 | ||
1ac649ed RC |
453 | create_mount ("/", get_root_dir (), istext, issystem); |
454 | create_mount ("/usr/bin", cygpath ("/bin"), istext, issystem); | |
455 | create_mount ("/usr/lib", cygpath ("/lib"), istext, issystem); | |
0af2d779 CF |
456 | set_cygdrive_flags (istext, issystem); |
457 | ||
8e9aa511 RC |
458 | /* Let's hope people won't uninstall packages before installing [b]ash */ |
459 | init_run_script (); | |
460 | ||
bb849dbd | 461 | packagedb db; |
bc78a6d5 | 462 | for (size_t n = 1; n <= db.packages.number (); n++) |
cbfc4215 | 463 | { |
ab57ceaa RC |
464 | packagemeta & pkg = *db.packages[n]; |
465 | ||
466 | if (pkg.desired && (pkg.desired->srcpicked || pkg.desired->binpicked)) | |
467 | { | |
468 | if (pkg.desired->srcpicked) | |
469 | total_bytes += pkg.desired->src.size; | |
470 | if (pkg.desired->binpicked) | |
471 | total_bytes += pkg.desired->bin.size; | |
472 | } | |
cbfc4215 | 473 | } |
bb849dbd | 474 | |
ad3c7385 | 475 | /* start with uninstalls - remove files that new packages may replace */ |
bc78a6d5 | 476 | for (size_t n = 1; n <= db.packages.number (); n++) |
23c9e63c | 477 | { |
ab57ceaa | 478 | packagemeta & pkg = *db.packages[n]; |
cbfc4215 | 479 | if (pkg.installed && (!pkg.desired || pkg.desired != pkg.installed)) |
ad3c7385 RC |
480 | uninstall_one (pkg); |
481 | } | |
482 | ||
483 | /* now in-place binary upgrades/reinstalls, as these may remove fils | |
484 | * that have been moved into new packages | |
485 | */ | |
486 | ||
487 | for (size_t n = 1; n <= db.packages.number (); n++) | |
488 | { | |
489 | packagemeta & pkg = *db.packages[n]; | |
490 | if (pkg.installed && pkg.desired && pkg.desired->binpicked) | |
4a83b7b0 | 491 | { |
ad3c7385 RC |
492 | int e = 0; |
493 | e += replace_one (pkg); | |
494 | if (e) | |
495 | errors++; | |
4a83b7b0 | 496 | } |
ad3c7385 RC |
497 | } |
498 | ||
499 | for (size_t n = 1; n <= db.packages.number (); n++) | |
500 | { | |
501 | packagemeta & pkg = *db.packages[n]; | |
23c9e63c | 502 | |
ab57ceaa | 503 | if (pkg.desired && (pkg.desired->srcpicked || pkg.desired->binpicked)) |
23c9e63c | 504 | { |
c46a33a9 | 505 | int e = 0; |
cbfc4215 | 506 | e += install_one (pkg); |
3b9077d4 | 507 | if (e) |
40aef45e | 508 | { |
3b9077d4 | 509 | errors++; |
40aef45e | 510 | } |
4a83b7b0 | 511 | } |
b24c88b3 | 512 | } // end of big package loop |
4a83b7b0 | 513 | |
ad3c7385 RC |
514 | if (rebootneeded) |
515 | note (owner, IDS_REBOOT_REQUIRED); | |
516 | ||
7c7034e8 RC |
517 | int temperr; |
518 | if ((temperr = db.flush ())) | |
23c9e63c | 519 | { |
7c7034e8 | 520 | const char *err = strerror (temperr); |
23c9e63c DD |
521 | if (!err) |
522 | err = "(unknown error)"; | |
3c054baf RC |
523 | fatal (owner, IDS_ERR_OPEN_WRITE, "Package Database", |
524 | err); | |
23c9e63c DD |
525 | } |
526 | ||
72fd1d1e CF |
527 | if (!errors) |
528 | check_for_old_cygwin (); | |
4a83b7b0 DD |
529 | if (num_installs == 0 && num_uninstalls == 0) |
530 | { | |
531 | exit_msg = IDS_NOTHING_INSTALLED; | |
532 | return; | |
533 | } | |
534 | if (num_installs == 0) | |
535 | { | |
536 | exit_msg = IDS_UNINSTALL_COMPLETE; | |
537 | return; | |
538 | } | |
539 | ||
2a1a01e0 DD |
540 | if (errors) |
541 | exit_msg = IDS_INSTALL_INCOMPLETE; | |
542 | else | |
543 | exit_msg = IDS_INSTALL_COMPLETE; | |
23c9e63c | 544 | } |
ab57ceaa RC |
545 | |
546 | static void | |
547 | do_install_reflector (void *p) | |
548 | { | |
549 | HANDLE *context; | |
550 | context = (HANDLE *) p; | |
551 | ||
552 | do_install_thread ((HINSTANCE) context[0], (HWND) context[1]); | |
553 | ||
554 | // Tell the progress page that we're done downloading | |
555 | Progress.PostMessage (WM_APP_INSTALL_THREAD_COMPLETE); | |
556 | ||
557 | _endthread (); | |
558 | } | |
559 | ||
560 | static HANDLE context[2]; | |
561 | ||
562 | void | |
563 | do_install (HINSTANCE h, HWND owner) | |
564 | { | |
565 | context[0] = h; | |
566 | context[1] = owner; | |
567 | ||
568 | _beginthread (do_install_reflector, 0, context); | |
569 | } |