Index: CHANGES =================================================================== RCS file: /cvs/cygwin-apps/setup/CHANGES,v retrieving revision 1.13 diff -u -p -b -B -r1.13 CHANGES --- CHANGES 13 Jun 2006 14:00:23 -0000 1.13 +++ CHANGES 16 Aug 2006 04:21:08 -0000 @@ -3,6 +3,8 @@ Note: For easier maintenance try to keep Version 2.548 (HEAD) + - Allow interactively retrying to replace open files. + - Fix unreadable chooser page due to bad background colour problem. - Make categories named with an initial "." default to expanded display. Index: install.cc =================================================================== RCS file: /cvs/cygwin-apps/setup/install.cc,v retrieving revision 2.78 diff -u -p -b -B -r2.78 install.cc --- install.cc 16 Apr 2006 15:37:49 -0000 2.78 +++ install.cc 16 Aug 2006 04:21:09 -0000 @@ -178,6 +178,44 @@ Installer::replaceOnRebootSucceeded (con rebootneeded = true; } +#define MB_RETRYCONTINUE 7 +#if !defined(IDCONTINUE) +#define IDCONTINUE IDCANCEL +#endif + +static HHOOK hMsgBoxHook; +LRESULT CALLBACK CBTProc(int nCode, WPARAM wParam, LPARAM lParam) { + HWND hWnd; + switch (nCode) { + case HCBT_ACTIVATE: + hWnd = (HWND)wParam; + if (GetDlgItem(hWnd, IDCANCEL) != NULL) + SetDlgItemText(hWnd, IDCANCEL, "Continue"); + UnhookWindowsHookEx(hMsgBoxHook); + } + return CallNextHookEx(hMsgBoxHook, nCode, wParam, lParam); +} + +int _custom_MessageBox(HWND hWnd, LPCTSTR szText, LPCTSTR szCaption, UINT uType) { + int retval; + bool retry_continue = (uType & MB_TYPEMASK) == MB_RETRYCONTINUE; + if (retry_continue) { + uType &= ~MB_TYPEMASK; uType |= MB_RETRYCANCEL; + // Install a window hook, so we can intercept the message-box + // creation, and customize it + // Only install for THIS thread!!! + hMsgBoxHook = SetWindowsHookEx(WH_CBT, CBTProc, NULL, GetCurrentThreadId()); + } + retval = MessageBox(hWnd, szText, szCaption, uType); + // Intercept the return value for less confusing results + if (retry_continue && retval == IDCANCEL) + return IDCONTINUE; + return retval; +} + +#undef MessageBox +#define MessageBox _custom_MessageBox + /* install one source at a given prefix. */ void Installer::installOne (packagemeta &pkgm, const packageversion &ver, @@ -205,6 +243,7 @@ Installer::installOne (packagemeta &pkgm io_stream *tmp = io_stream::open (source.Cached (), "rb"); io_stream *tmp2 = 0; archive *thefile = 0; + bool ignoreExtractErrors = unattended_mode; if (tmp) { tmp2 = compress::decompress (tmp); @@ -253,8 +292,33 @@ Installer::installOne (packagemeta &pkgm Progress.SetText3 (canonicalfn.c_str()); log (LOG_BABBLE) << "Installing file " << prefixURL << prefixPath << fn << endLog; - if (archive::extract_file (thefile, prefixURL, prefixPath) != 0) + bool firstIteration = true; + while (archive::extract_file (thefile, prefixURL, prefixPath) != 0) + { + if (!ignoreExtractErrors) + { + char msg[fn.size() + 300]; + sprintf (msg, + "%snable to extract /%s -- the file is in use.\r\n" + "Please stop %s Cygwin processes and select \"Retry\", or\r\n" + "select \"Continue\" to go on anyway (you will need to reboot).\r\n", + firstIteration?"U":"Still u", fn.c_str(), firstIteration?"all":"ALL"); + switch (MessageBox + (NULL, msg, "In-use files detected", + MB_RETRYCONTINUE | MB_ICONWARNING | MB_TASKMODAL)) { + case IDRETRY: + // retry + firstIteration = false; + continue; + case IDCONTINUE: + ignoreExtractErrors = true; + break; + default: + break; + } + // fall through to previous functionality + } if (NoReplaceOnReboot) { ++errors; @@ -321,6 +385,8 @@ Installer::installOne (packagemeta &pkgm } } } + // We're done with this file + break; } progress (tmp->tell ()); num_installs++;