diff options
4 files changed, 69 insertions, 64 deletions
diff --git a/instsetoo_native/inc_openoffice/windows/msi_languages/Error.ulf b/instsetoo_native/inc_openoffice/windows/msi_languages/Error.ulf index a14f45e0cd54..315e35fe0b33 100644 --- a/instsetoo_native/inc_openoffice/windows/msi_languages/Error.ulf +++ b/instsetoo_native/inc_openoffice/windows/msi_languages/Error.ulf @@ -406,4 +406,7 @@ en-US = "This setup requires Internet Information Server 4.0 or higher for confi [OOO_ERROR_130] en-US = "This setup requires Administrator privileges for configuring IIS Virtual Roots." +[OOO_ERROR_131] +en-US = "Installing a pre-requisite KB2999226 failed. You might need to manually install it from Microsoft site to be able to run the product. [2]" + diff --git a/instsetoo_native/inc_openoffice/windows/msi_templates/Error.idt b/instsetoo_native/inc_openoffice/windows/msi_templates/Error.idt index 2f3a5912817d..52cc797c643e 100644 --- a/instsetoo_native/inc_openoffice/windows/msi_templates/Error.idt +++ b/instsetoo_native/inc_openoffice/windows/msi_templates/Error.idt @@ -131,3 +131,4 @@ i2 L0 1932 OOO_ERROR_128 1933 OOO_ERROR_129 1934 OOO_ERROR_130 +25000 OOO_ERROR_131 diff --git a/scp2/source/ooo/ucrt.scp b/scp2/source/ooo/ucrt.scp index ae2eb27a4dbe..8cba6cfc3cd0 100644 --- a/scp2/source/ooo/ucrt.scp +++ b/scp2/source/ooo/ucrt.scp @@ -85,11 +85,14 @@ WindowsCustomAction gid_Customaction_cleanup_msu Assignment1 = ("InstallExecuteSequence", "Not Installed And cleanup_msu", "inst_msu"); End +/* The "InstMSUBinary" property contains an error message number and a binary name, separated by "|". + The former is used when installing the MSU fails. +*/ WindowsCustomAction gid_Customaction_check_win7x64_ucrt Name = "check_win7x64_ucrt"; Typ = "51"; Source = "InstMSUBinary"; - Target = "Windows61-KB2999226-x64msu"; + Target = "25000|Windows61-KB2999226-x64msu"; Inbinarytable = 0; Assignment1 = ("InstallExecuteSequence", "Not Installed And VersionNT = 601 And VersionNT64", "FileCost"); Styles = "NO_FILE"; @@ -99,7 +102,7 @@ WindowsCustomAction gid_Customaction_check_win8x64_ucrt Name = "check_win8x64_ucrt"; Typ = "51"; Source = "InstMSUBinary"; - Target = "Windows8-RT-KB2999226-x64msu"; + Target = "25000|Windows8-RT-KB2999226-x64msu"; Inbinarytable = 0; Assignment1 = ("InstallExecuteSequence", "Not Installed And VersionNT = 602 And VersionNT64", "check_win7x64_ucrt"); Styles = "NO_FILE"; @@ -109,7 +112,7 @@ WindowsCustomAction gid_Customaction_check_win81x64_ucrt Name = "check_win81x64_ucrt"; Typ = "51"; Source = "InstMSUBinary"; - Target = "Windows81-KB2999226-x64msu"; + Target = "25000|Windows81-KB2999226-x64msu"; Inbinarytable = 0; Assignment1 = ("InstallExecuteSequence", "Not Installed And VersionNT = 603 And VersionNT64", "check_win8x64_ucrt"); Styles = "NO_FILE"; @@ -125,7 +128,7 @@ WindowsCustomAction gid_Customaction_check_win7x32_ucrt Name = "check_win7x32_ucrt"; Typ = "51"; Source = "InstMSUBinary"; - Target = "Windows61-KB2999226-x86msu"; + Target = "25000|Windows61-KB2999226-x86msu"; Inbinarytable = 0; Assignment1 = ("InstallExecuteSequence", "Not Installed And VersionNT = 601 And Not VersionNT64", "check_win81x64_ucrt"); Styles = "NO_FILE"; @@ -135,7 +138,7 @@ WindowsCustomAction gid_Customaction_check_win8x32_ucrt Name = "check_win8x32_ucrt"; Typ = "51"; Source = "InstMSUBinary"; - Target = "Windows8-RT-KB2999226-x86msu"; + Target = "25000|Windows8-RT-KB2999226-x86msu"; Inbinarytable = 0; Assignment1 = ("InstallExecuteSequence", "Not Installed And VersionNT = 602 And Not VersionNT64", "check_win7x32_ucrt"); Styles = "NO_FILE"; @@ -145,7 +148,7 @@ WindowsCustomAction gid_Customaction_check_win81x32_ucrt Name = "check_win81x32_ucrt"; Typ = "51"; Source = "InstMSUBinary"; - Target = "Windows81-KB2999226-x86msu"; + Target = "25000|Windows81-KB2999226-x86msu"; Inbinarytable = 0; Assignment1 = ("InstallExecuteSequence", "Not Installed And VersionNT = 603 And Not VersionNT64", "check_win8x32_ucrt"); Styles = "NO_FILE"; diff --git a/setup_native/source/win32/customactions/inst_msu/inst_msu.cxx b/setup_native/source/win32/customactions/inst_msu/inst_msu.cxx index 96fb88f4b889..5df2b26431d7 100644 --- a/setup_native/source/win32/customactions/inst_msu/inst_msu.cxx +++ b/setup_native/source/win32/customactions/inst_msu/inst_msu.cxx @@ -120,6 +120,17 @@ template <class... StrType> void WriteLog(MSIHANDLE hInst, const StrType&... ele WriteLogElem(hInst, hRec, sTemplate, 1, elements...); } +void ShowWarning(MSIHANDLE hInst, const std::wstring& sErrNo, const char* sMessage) +{ + PMSIHANDLE hRec = MsiCreateRecord(2); + // To show a message from Error table, record's Field 0 must be null + MsiRecordSetStringW(hRec, 1, sErrNo.c_str()); + std::string s("\n"); + s += sMessage; + MsiRecordSetStringA(hRec, 2, s.c_str()); + MsiProcessMessage(hInst, INSTALLMESSAGE_WARNING, hRec); +} + typedef std::unique_ptr<void, decltype(&CloseHandle)> CloseHandleGuard; CloseHandleGuard Guard(HANDLE h) { return CloseHandleGuard(h, CloseHandle); } @@ -166,16 +177,6 @@ bool IsWow64Process() #endif } -// An exception class to differentiate a non-fatal exception -class nonfatal_exception : public std::exception -{ -public: - nonfatal_exception(const std::exception& e) - : std::exception(e) - { - } -}; - // Checks if Windows Update service is disabled, and if it is, enables it temporarily. class WUServiceEnabler { @@ -205,37 +206,27 @@ public: private: static CloseServiceHandleGuard EnableWUService(MSIHANDLE hInstall) { - try - { - auto hSCM = Guard(OpenSCManagerW(nullptr, nullptr, SC_MANAGER_ALL_ACCESS)); - if (!hSCM) - ThrowLastError("OpenSCManagerW"); - WriteLog(hInstall, "Opened service control manager"); - - auto hService = Guard(OpenServiceW(hSCM.get(), L"wuauserv", - SERVICE_QUERY_CONFIG | SERVICE_CHANGE_CONFIG - | SERVICE_QUERY_STATUS | SERVICE_STOP)); - if (!hService) - ThrowLastError("OpenServiceW"); - WriteLog(hInstall, "Obtained WU service handle"); - - if (ServiceStatus(hInstall, hService.get()) == SERVICE_RUNNING - || !EnsureServiceEnabled(hInstall, hService.get(), true)) - { - // No need to restore anything back, since we didn't change config - hService.reset(); - WriteLog(hInstall, "Service configuration is unchanged"); - } - - return hService; - } - catch (const std::exception& e) + auto hSCM = Guard(OpenSCManagerW(nullptr, nullptr, SC_MANAGER_ALL_ACCESS)); + if (!hSCM) + ThrowLastError("OpenSCManagerW"); + WriteLog(hInstall, "Opened service control manager"); + + auto hService = Guard(OpenServiceW(hSCM.get(), L"wuauserv", + SERVICE_QUERY_CONFIG | SERVICE_CHANGE_CONFIG + | SERVICE_QUERY_STATUS | SERVICE_STOP)); + if (!hService) + ThrowLastError("OpenServiceW"); + WriteLog(hInstall, "Obtained WU service handle"); + + if (ServiceStatus(hInstall, hService.get()) == SERVICE_RUNNING + || !EnsureServiceEnabled(hInstall, hService.get(), true)) { - // Allow errors opening service to be logged, but not interrupt installation. - // They are likely to happen in situations where people hard-disable WU service, - // and for these cases, let people deal with install logs instead of failing. - throw nonfatal_exception(e); + // No need to restore anything back, since we didn't change config + hService.reset(); + WriteLog(hInstall, "Service configuration is unchanged"); } + + return hService; } // Returns if the service configuration was actually changed @@ -354,11 +345,18 @@ extern "C" __declspec(dllexport) UINT __stdcall UnpackMSUForInstall(MSIHANDLE hI WriteLog(hInstall, "started"); WriteLog(hInstall, "Checking value of InstMSUBinary"); - wchar_t sBinaryName[MAX_PATH + 1]; - DWORD nCCh = sizeof(sBinaryName) / sizeof(*sBinaryName); + wchar_t sInstMSUBinary[MAX_PATH + 10]; + DWORD nCCh = sizeof(sInstMSUBinary) / sizeof(*sInstMSUBinary); CheckWin32Error("MsiGetPropertyW", - MsiGetPropertyW(hInstall, L"InstMSUBinary", sBinaryName, &nCCh)); - WriteLog(hInstall, "Got InstMSUBinary value:", sBinaryName); + MsiGetPropertyW(hInstall, L"InstMSUBinary", sInstMSUBinary, &nCCh)); + WriteLog(hInstall, + "Got InstMSUBinary value:", sInstMSUBinary); // 123|Windows61-KB2999226-x64msu + const wchar_t* sBinaryName = wcschr(sInstMSUBinary, L'|'); + if (!sBinaryName) + throw std::exception("No error code in InstMSUBinary!"); + // "123" - # of the message in Error table to be shown on failure + const std::wstring sErrNo(sInstMSUBinary, sBinaryName - sInstMSUBinary); + ++sBinaryName; PMSIHANDLE hDatabase = MsiGetActiveDatabase(hInstall); if (!hDatabase) @@ -415,8 +413,9 @@ extern "C" __declspec(dllexport) UINT __stdcall UnpackMSUForInstall(MSIHANDLE hI WriteLog(hInstall, "Successfully wrote", Num2Dec(nTotal), "bytes"); } - - CheckWin32Error("MsiSetPropertyW", MsiSetPropertyW(hInstall, L"inst_msu", sBinary.c_str())); + const std::wstring s_inst_msu = sErrNo + L"|" + sBinary; + CheckWin32Error("MsiSetPropertyW", + MsiSetPropertyW(hInstall, L"inst_msu", s_inst_msu.c_str())); // Don't delete the file: it will be done by following actions (inst_msu or cleanup_msu) (void)aDeleteFileGuard.release(); @@ -433,17 +432,23 @@ extern "C" __declspec(dllexport) UINT __stdcall UnpackMSUForInstall(MSIHANDLE hI // "CustomActionData" property, and runs wusa.exe to install it. Waits for it and checks exit code. extern "C" __declspec(dllexport) UINT __stdcall InstallMSU(MSIHANDLE hInstall) { + std::wstring sErrNo; // "123" - # of the message in Error table to be shown on failure try { sLogPrefix = "InstallMSU:"; WriteLog(hInstall, "started"); WriteLog(hInstall, "Checking value of CustomActionData"); - wchar_t sBinaryName[MAX_PATH + 1]; - DWORD nCCh = sizeof(sBinaryName) / sizeof(*sBinaryName); + wchar_t sCustomActionData[MAX_PATH + 10]; // "123|C:\Temp\binary.tmp" + DWORD nCCh = sizeof(sCustomActionData) / sizeof(*sCustomActionData); CheckWin32Error("MsiGetPropertyW", - MsiGetPropertyW(hInstall, L"CustomActionData", sBinaryName, &nCCh)); - WriteLog(hInstall, "Got CustomActionData value:", sBinaryName); + MsiGetPropertyW(hInstall, L"CustomActionData", sCustomActionData, &nCCh)); + WriteLog(hInstall, "Got CustomActionData value:", sCustomActionData); + const wchar_t* sBinaryName = wcschr(sCustomActionData, L'|'); + if (!sBinaryName) + throw std::exception("No error code in CustomActionData!"); + sErrNo = std::wstring(sCustomActionData, sBinaryName - sCustomActionData); + ++sBinaryName; auto aDeleteFileGuard(Guard(sBinaryName)); // In case the Windows Update service is disabled, we temporarily enable it here @@ -496,19 +501,12 @@ extern "C" __declspec(dllexport) UINT __stdcall InstallMSU(MSIHANDLE hInstall) ThrowWin32Error("Execution of wusa.exe", nExitCode); } } - catch (nonfatal_exception& e) - { - // An error that should not interrupt installation - WriteLog(hInstall, e.what()); - WriteLog(hInstall, "Installation of MSU package failed, but installation of product will " - "continue. You may need to install the required update manually"); - return ERROR_SUCCESS; - } catch (std::exception& e) { WriteLog(hInstall, e.what()); + ShowWarning(hInstall, sErrNo, e.what()); } - return ERROR_INSTALL_FAILURE; + return ERROR_SUCCESS; // Do not break on MSU installation errors } // Rollback deferred action "cleanup_msu" that is executed on error or cancel. |