[Libreoffice-commits] core.git: instsetoo_native/inc_openoffice scp2/source setup_native/source

Libreoffice Gerrit user logerrit at kemper.freedesktop.org
Sun Dec 16 14:11:07 UTC 2018


 instsetoo_native/inc_openoffice/windows/msi_languages/Error.ulf |    3 
 instsetoo_native/inc_openoffice/windows/msi_templates/Error.idt |    1 
 scp2/source/ooo/ucrt.scp                                        |   15 -
 setup_native/source/win32/customactions/inst_msu/inst_msu.cxx   |  114 ++++------
 4 files changed, 69 insertions(+), 64 deletions(-)

New commits:
commit 0b6884b9f1f60db48983de6c5bd53e25e1f68eeb
Author:     Mike Kaganski <mike.kaganski at collabora.com>
AuthorDate: Mon Dec 10 16:20:42 2018 +0300
Commit:     Mike Kaganski <mike.kaganski at collabora.com>
CommitDate: Sun Dec 16 15:10:47 2018 +0100

    tdf#121987 follow-up: never fail MSU install; warn instead.
    
    This replaces commit 53058090beede6a399e2f408f62c28a2921ff8ab. Now
    not only failure to start WU service, but also other errors during
    MSU installation won't break installation. E.g., running WU service
    as Guest does not prevent the service from starting; but installing
    updates fail, which makes previous solution incomplete.
    
    Instead, show a warning in those rare cases when an error happens,
    and continue. It will allow users to see the reason if they see
    "api-ms-win-*.dll missing" message later after installation. Of
    course, some small percentage of these warnings will be false, e.g.
    those on Windows 10. But those false messages must be really small
    minority, because only when (1) the installation fails (2) on a
    system with the component already present, such a message would be
    false. And it will not prevent the installation.
    
    This will not block unattended installations, since in those cases,
    MsiProcessMessage() will do nothing.
    
    Change-Id: I3a9e681e9d6701d092bd5c18bb4b68b4f77170f3
    Reviewed-on: https://gerrit.libreoffice.org/64874
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kaganski at collabora.com>

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.


More information about the Libreoffice-commits mailing list