[Libreoffice-commits] core.git: Branch 'distro/collabora/cp-6.0' - Repository.mk scp2/source setup_native/Library_reg_dlls.mk setup_native/Module_setup_native.mk setup_native/source

Mike Kaganski (via logerrit) logerrit at kemper.freedesktop.org
Tue Jun 4 19:59:09 UTC 2019


 Repository.mk                                                 |    1 
 scp2/source/calc/module_calc.scp                              |    2 
 scp2/source/draw/module_draw.scp                              |    2 
 scp2/source/impress/module_impress.scp                        |    2 
 scp2/source/ooo/windowscustomaction_ooo.scp                   |   41 +
 scp2/source/writer/module_writer.scp                          |    2 
 setup_native/Library_reg_dlls.mk                              |   40 +
 setup_native/Module_setup_native.mk                           |    1 
 setup_native/source/win32/customactions/reg_dlls/reg_dlls.cxx |  281 ++++++++++
 setup_native/source/win32/customactions/reg_dlls/reg_dlls.def |    5 
 10 files changed, 373 insertions(+), 4 deletions(-)

New commits:
commit 7f0ef81cec7e4f64c7fbfce04372d84871244b11
Author:     Mike Kaganski <mike.kaganski at collabora.com>
AuthorDate: Wed May 22 19:17:44 2019 +0300
Commit:     Aron Budea <aron.budea at collabora.com>
CommitDate: Tue Jun 4 21:58:30 2019 +0200

    Register spsupp*.dll during installation
    
    This registers SharePoint integration libraries using regsvr.exe.
    Both 32-bit and 64-bit libraries are registered; registration of
    SharePoint.OpenDocuments is unconditional (subject to ActiveX
    feature install state), substituting respective MSO component.
    
    This only works for 32-bit MSI, because in case of 64-bit MSI, only
    64-bit SharePoint DLL is included; this makes the library ~useless
    in case of 64-bit MSI, because IE needs 32-bit component absent there.
    Proper solution will be created for master branch.
    
    Change-Id: Ic5bf9e7090acfaa17d47cb72b9ebfd483242f656
    Reviewed-on: https://gerrit.libreoffice.org/72801
    Reviewed-by: Aron Budea <aron.budea at collabora.com>
    Tested-by: Aron Budea <aron.budea at collabora.com>

diff --git a/Repository.mk b/Repository.mk
index ca4b1031131c..889643183942 100644
--- a/Repository.mk
+++ b/Repository.mk
@@ -668,6 +668,7 @@ $(eval $(call gb_Helper_register_libraries_for_install,PLAINLIBS_OOO,ooobinaryta
 		instooofiltmsi \
 		inst_msu_msi \
 		qslnkmsi \
+		reg_dlls \
 		reg4allmsdoc \
 		sdqsmsi \
 		sellangmsi \
diff --git a/scp2/source/calc/module_calc.scp b/scp2/source/calc/module_calc.scp
index dd31007bb5ca..0f83dec54352 100644
--- a/scp2/source/calc/module_calc.scp
+++ b/scp2/source/calc/module_calc.scp
@@ -74,7 +74,7 @@ Module gid_Module_Prg_Calc_MSO_Reg
     Name = "gid_Module_Prg_Calc_MSO_Reg";
     Description = "gid_Module_Prg_Calc_MSO_Reg";
     Styles = (HIDDEN_ROOT);
-    Default = YES;
+    Default = NO;
 End
 
 Module gid_Module_Prg_Calc_Other_Reg
diff --git a/scp2/source/draw/module_draw.scp b/scp2/source/draw/module_draw.scp
index 87375797e1c6..c4c835b4ccc1 100644
--- a/scp2/source/draw/module_draw.scp
+++ b/scp2/source/draw/module_draw.scp
@@ -64,7 +64,7 @@ Module gid_Module_Prg_Draw_MSO_Reg
     Name = "gid_Module_Prg_Draw_MSO_Reg";
     Description = "gid_Module_Prg_Draw_MSO_Reg";
     Styles = (HIDDEN_ROOT);
-    Default = YES;
+    Default = NO;
 End
 
 Module gid_Module_Prg_Draw_Other_Reg
diff --git a/scp2/source/impress/module_impress.scp b/scp2/source/impress/module_impress.scp
index ca335d6973d9..42d62dd9e7c6 100644
--- a/scp2/source/impress/module_impress.scp
+++ b/scp2/source/impress/module_impress.scp
@@ -66,7 +66,7 @@ Module gid_Module_Prg_Impress_MSO_Reg
     Name = "gid_Module_Prg_Impress_MSO_Reg";
     Description = "gid_Module_Prg_Impress_MSO_Reg";
     Styles = (HIDDEN_ROOT);
-    Default = YES;
+    Default = NO;
 End
 
 Module gid_Module_Prg_Impress_Other_Reg
diff --git a/scp2/source/ooo/windowscustomaction_ooo.scp b/scp2/source/ooo/windowscustomaction_ooo.scp
index bc7201b9b2b4..f98296ca48dc 100644
--- a/scp2/source/ooo/windowscustomaction_ooo.scp
+++ b/scp2/source/ooo/windowscustomaction_ooo.scp
@@ -221,3 +221,44 @@ WindowsCustomAction gid_Customaction_RegisterSomeExtensions
 End
 
 #endif /* HAVE_WINDOWS_SDK */
+
+/* Deferred not-impersonated actions that will call regsvr32 to (un)register DLLs.
+   Custom action type 1 (msidbCustomActionTypeDll + msidbCustomActionTypeBinaryData)
+   + 64 (msidbCustomActionTypeContinue) + 1024 (msidbCustomActionTypeInScript)
+   + 2048 (msidbCustomActionTypeNoImpersonate).
+   Since deferred actions don't have access to current DB, the actions depend on
+   immediate-executed action prep_reg_unreg_dlls (see below) that precedes it, and
+   sets this action's CustomActionData property.
+*/
+
+WindowsCustomAction gid_Customaction_reg_dlls
+	Name = "reg_dlls";
+	Typ = "3137";
+	Source = "reg_dlls.dll";
+	Target = "RegDLLs";
+	Inbinarytable = 1;
+	Assignment1 = ("InstallExecuteSequence", "reg_dlls", "InstallFinalize");
+End
+
+WindowsCustomAction gid_Customaction_unreg_dlls
+	Name = "unreg_dlls";
+	Typ = "3137";
+	Source = "reg_dlls.dll";
+	Target = "UnregDLLs";
+	Inbinarytable = 1;
+	Assignment1 = ("InstallExecuteSequence", "unreg_dlls", "UnpublishComponents");
+End
+
+/* Immediately-executed action that adds registration command lines for spsupp[_x64].dll
+   to "[un]reg_dlls" properties.
+   Custom action type 1 (msidbCustomActionTypeDll + msidbCustomActionTypeBinaryData)
+   + 64 (msidbCustomActionTypeContinue).
+*/
+WindowsCustomAction gid_Customaction_prep_reg_dlls
+	Name = "prep_reg_unreg_dlls";
+	Typ = "65";
+	Source = "reg_dlls.dll";
+	Target = "PrepRegUnregDLLs";
+	Inbinarytable = 1;
+	Assignment1 = ("InstallExecuteSequence", "", "behind_CostFinalize");
+End
diff --git a/scp2/source/writer/module_writer.scp b/scp2/source/writer/module_writer.scp
index 9a0ed77ac4b8..ded807099d63 100644
--- a/scp2/source/writer/module_writer.scp
+++ b/scp2/source/writer/module_writer.scp
@@ -65,7 +65,7 @@ Module gid_Module_Prg_Wrt_MSO_Reg
     Name = "gid_Module_Prg_Wrt_MSO_Reg";
     Description = "gid_Module_Prg_Wrt_MSO_Reg";
     Styles = (HIDDEN_ROOT);
-    Default = YES;
+    Default = NO;
 End
 
 Module gid_Module_Prg_Wrt_Other_Reg
diff --git a/setup_native/Library_reg_dlls.mk b/setup_native/Library_reg_dlls.mk
new file mode 100644
index 000000000000..f0ac9a875c60
--- /dev/null
+++ b/setup_native/Library_reg_dlls.mk
@@ -0,0 +1,40 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_Library_Library,reg_dlls))
+
+$(eval $(call gb_Library_add_defs,reg_dlls,\
+	-U_DLL \
+))
+
+$(eval $(call gb_Library_add_cxxflags,reg_dlls,\
+	$(if $(MSVC_USE_DEBUG_RUNTIME),/MTd,/MT) \
+))
+
+$(eval $(call gb_Library_add_ldflags,reg_dlls,\
+	/DEF:$(SRCDIR)/setup_native/source/win32/customactions/reg_dlls/reg_dlls.def \
+	/NODEFAULTLIB \
+))
+
+$(eval $(call gb_Library_add_exception_objects,reg_dlls,\
+	setup_native/source/win32/customactions/reg_dlls/reg_dlls \
+))
+
+$(eval $(call gb_Library_use_system_win32_libs,reg_dlls,\
+	libcmt \
+	libcpmt \
+	libucrt \
+	libvcruntime \
+	kernel32 \
+	Ole32 \
+	Shell32 \
+	Msi \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/setup_native/Module_setup_native.mk b/setup_native/Module_setup_native.mk
index abf37aff6c86..aa4025a9a7bb 100644
--- a/setup_native/Module_setup_native.mk
+++ b/setup_native/Module_setup_native.mk
@@ -26,6 +26,7 @@ $(eval $(call gb_Module_add_targets,setup_native,\
 	Library_instooofiltmsi \
 	Library_inst_msu_msi \
 	Library_qslnkmsi \
+	Library_reg_dlls \
 	Library_reg4allmsdoc \
 	Library_regactivex \
 	Library_sdqsmsi \
diff --git a/setup_native/source/win32/customactions/reg_dlls/reg_dlls.cxx b/setup_native/source/win32/customactions/reg_dlls/reg_dlls.cxx
new file mode 100644
index 000000000000..e0d3ee3b2cc8
--- /dev/null
+++ b/setup_native/source/win32/customactions/reg_dlls/reg_dlls.cxx
@@ -0,0 +1,281 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <iomanip>
+#include <memory>
+#include <string>
+#include <sstream>
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <Shlobj.h>
+#include <msiquery.h>
+
+namespace
+{
+template <typename IntType> std::string Num2Hex(IntType n)
+{
+    std::stringstream sMsg;
+    sMsg << "0x" << std::uppercase << std::setfill('0') << std::setw(sizeof(n) * 2) << std::hex
+         << n;
+    return sMsg.str();
+}
+
+template <typename IntType> std::string Num2Dec(IntType n)
+{
+    std::stringstream sMsg;
+    sMsg << n;
+    return sMsg.str();
+}
+
+std::string Win32ErrorMessage(const char* sFunc, DWORD nWin32Error)
+{
+    std::stringstream sMsg;
+    sMsg << sFunc << " failed with Win32 error code " << Num2Hex(nWin32Error) << "!";
+
+    return sMsg.str();
+}
+
+void ThrowHResult(const char* sFunc, HRESULT hr)
+{
+    std::stringstream sMsg;
+    sMsg << sFunc << " failed (HRESULT = " << Num2Hex(hr) << ")!";
+
+    throw std::exception(sMsg.str().c_str());
+}
+
+void CheckHResult(const char* sFunc, HRESULT hr)
+{
+    if (FAILED(hr))
+        ThrowHResult(sFunc, hr);
+}
+
+void ThrowWin32Error(const char* sFunc, DWORD nWin32Error)
+{
+    throw std::exception(Win32ErrorMessage(sFunc, nWin32Error).c_str());
+}
+
+void ThrowLastError(const char* sFunc) { ThrowWin32Error(sFunc, GetLastError()); }
+
+void CheckWin32Error(const char* sFunc, DWORD nWin32Error)
+{
+    if (nWin32Error != ERROR_SUCCESS)
+        ThrowWin32Error(sFunc, nWin32Error);
+}
+
+std::wstring GetKnownFolder(const KNOWNFOLDERID& rfid)
+{
+    PWSTR sPath = nullptr;
+    HRESULT hr = SHGetKnownFolderPath(rfid, KF_FLAG_DEFAULT, nullptr, &sPath);
+    CheckHResult("SHGetKnownFolderPath", hr);
+    std::wstring sResult(sPath);
+    CoTaskMemFree(sPath);
+    return sResult;
+}
+
+void WriteLogElem(MSIHANDLE hInst, MSIHANDLE hRecord, std::ostringstream& sTmpl, UINT)
+{
+    MsiRecordSetStringA(hRecord, 0, sTmpl.str().c_str());
+    MsiProcessMessage(hInst, INSTALLMESSAGE_INFO, hRecord);
+}
+
+void RecSetString(MSIHANDLE hRec, UINT nField, LPCSTR sVal)
+{
+    MsiRecordSetStringA(hRec, nField, sVal);
+}
+
+void RecSetString(MSIHANDLE hRec, UINT nField, LPCWSTR sVal)
+{
+    MsiRecordSetStringW(hRec, nField, sVal);
+}
+
+template <class Ch, class... SOther>
+void WriteLogElem(MSIHANDLE hInst, MSIHANDLE hRec, std::ostringstream& sTmpl, UINT nField,
+                  const Ch* elem, const SOther&... others)
+{
+    sTmpl << " [" << nField << "]";
+    RecSetString(hRec, nField, elem);
+    WriteLogElem(hInst, hRec, sTmpl, nField + 1, others...);
+}
+
+template <class S1, class... SOther>
+void WriteLogElem(MSIHANDLE hInst, MSIHANDLE hRec, std::ostringstream& sTmpl, UINT nField,
+                  const S1& elem, const SOther&... others)
+{
+    WriteLogElem(hInst, hRec, sTmpl, nField, elem.c_str(), others...);
+}
+
+static std::string sLogPrefix;
+
+template <class... StrType> void WriteLog(MSIHANDLE hInst, const StrType&... elements)
+{
+    PMSIHANDLE hRec = MsiCreateRecord(sizeof...(elements));
+    if (!hRec)
+        return;
+
+    std::ostringstream sTemplate;
+    sTemplate << sLogPrefix;
+    WriteLogElem(hInst, hRec, sTemplate, 1, elements...);
+}
+
+std::wstring MsiGetPropertyW(MSIHANDLE hInst, LPCWSTR szName)
+{
+    std::wstring sResult;
+    DWORD nSz = 0;
+    UINT nRet = ::MsiGetPropertyW(hInst, szName, L"", &nSz);
+    if (nRet == ERROR_MORE_DATA)
+    {
+        ++nSz;
+        auto buf = std::make_unique<wchar_t[]>(nSz);
+        CheckWin32Error("MsiGetPropertyW", ::MsiGetPropertyW(hInst, szName, buf.get(), &nSz));
+        sResult = buf.get();
+        WriteLog(hInst, "Property", szName, "=", sResult);
+    }
+    else
+        CheckWin32Error("MsiGetPropertyW", nRet);
+
+    return sResult;
+}
+
+typedef std::unique_ptr<void, decltype(&CloseHandle)> CloseHandleGuard;
+CloseHandleGuard Guard(HANDLE h) { return CloseHandleGuard(h, CloseHandle); }
+
+void RegDLL(MSIHANDLE hInst, const std::wstring& sArgs, bool bUnreg)
+{
+    static std::wstring sRegSvr32 = GetKnownFolder(FOLDERID_System) + L"\\regsvr32.exe";
+
+    try
+    {
+        std::wstring sCmd = L"\"" + sRegSvr32 + L"\" /s ";
+        if (bUnreg)
+            sCmd += L"/u ";
+        sCmd += sArgs;
+        WriteLog(hInst, "Prepared regsvr32 command:", sCmd);
+
+        STARTUPINFOW si{ sizeof(si) };
+        PROCESS_INFORMATION pi{};
+        if (!CreateProcessW(sRegSvr32.c_str(), const_cast<LPWSTR>(sCmd.c_str()), nullptr, nullptr,
+                            FALSE, CREATE_NO_WINDOW, nullptr, nullptr, &si, &pi))
+            ThrowLastError("CreateProcessW");
+        auto aCloseProcHandleGuard(Guard(pi.hProcess));
+        WriteLog(hInst, "CreateProcessW succeeded");
+
+        DWORD nWaitResult = WaitForSingleObject(pi.hProcess, INFINITE);
+        if (nWaitResult != WAIT_OBJECT_0)
+            ThrowWin32Error("WaitForSingleObject", nWaitResult);
+
+        DWORD nExitCode = 0;
+        if (!GetExitCodeProcess(pi.hProcess, &nExitCode))
+            ThrowLastError("GetExitCodeProcess");
+
+        WriteLog(hInst, "regsvr32 returned:", Num2Dec(nExitCode));
+    }
+    catch (std::exception& e)
+    {
+        WriteLog(hInst, e.what());
+    }
+}
+
+void ProcessCustomActionData(MSIHANDLE hInst, bool bUnreg)
+{
+    WriteLog(hInst, "Checking value of CustomActionData");
+    std::wstring sCustomActionData = MsiGetPropertyW(hInst, L"CustomActionData");
+    WriteLog(hInst, "Got CustomActionData value:", sCustomActionData);
+    std::wstringstream ss(sCustomActionData);
+    std::wstring sToken;
+    while (std::getline(ss, sToken, L'|'))
+    {
+        if (!sToken.empty())
+        {
+            RegDLL(hInst, sToken, bUnreg);
+        }
+    }
+}
+} // namespace
+
+// Deferred action "reg_dlls" that must be run from system account. Receives a list of regsvr32
+// arguments: DLLs which need registering, and possibly /i argument with its parameter.
+extern "C" __declspec(dllexport) UINT __stdcall RegDLLs(MSIHANDLE hInstall)
+{
+    sLogPrefix = "RegDLLs:";
+    WriteLog(hInstall, "started");
+
+    ProcessCustomActionData(hInstall, false);
+    return ERROR_SUCCESS;
+}
+
+// Deferred action "unreg_dlls" that must be run from system account. Receives a list of regsvr32
+// arguments: DLLs which need registering, and possibly /i argument with its parameter.
+extern "C" __declspec(dllexport) UINT __stdcall UnregDLLs(MSIHANDLE hInstall)
+{
+    sLogPrefix = "UnregDLLs:";
+    WriteLog(hInstall, "started");
+
+    ProcessCustomActionData(hInstall, true);
+    return ERROR_SUCCESS;
+}
+
+// Immediate action "prep_reg_unreg_dlls". Checks states of the features to prepare custom action data
+// for reg_dlls and unreg_dlls deferred actions.
+extern "C" __declspec(dllexport) UINT __stdcall PrepRegUnregDLLs(MSIHANDLE hInstall)
+{
+    sLogPrefix = "PrepRegUnregDLLs:";
+    WriteLog(hInstall, "started");
+
+    try
+    {
+        INSTALLSTATE current_state;
+        INSTALLSTATE future_state;
+        CheckWin32Error("MsiGetFeatureStateW", MsiGetFeatureStateW(hInstall, L"gm_o_Activexcontrol",
+                                                                   &current_state, &future_state));
+        const bool bRegActiveX
+            = future_state == INSTALLSTATE_LOCAL
+              || (current_state == INSTALLSTATE_LOCAL && (future_state == INSTALLSTATE_UNKNOWN
+                                                         || future_state == INSTALLSTATE_DEFAULT));
+        const bool bUnregActiveX = current_state == INSTALLSTATE_LOCAL
+                                   && future_state != INSTALLSTATE_UNKNOWN
+                                   && future_state != INSTALLSTATE_LOCAL
+                                   && future_state != INSTALLSTATE_DEFAULT;
+
+        if (!bRegActiveX && !bUnregActiveX)
+            return ERROR_SUCCESS;
+
+        // For now, do that unconditionally; TODO: move the component to own feature
+        std::wstring sRegData = L"/i:Substitute_OWSSUPP \"[#spsupp.dll]\"|/i:Substitute_OWSSUPP "
+                                L"\"[#spsupp_x64.dll]\"";
+
+        auto SetFormattedPropW = [&](LPCWSTR sProp, LPCWSTR sVal) {
+            PMSIHANDLE hRec = MsiCreateRecord(0);
+            if (!hRec)
+                throw std::exception("MsiCreateRecord failed!");
+            MsiRecordSetStringW(hRec, 0, sVal);
+            DWORD nSz = 0;
+            if (MsiFormatRecordW(hInstall, hRec, L"", &nSz) == ERROR_MORE_DATA)
+            {
+                ++nSz;
+                auto buf = std::make_unique<wchar_t[]>(nSz);
+                CheckWin32Error("MsiFormatRecordW",
+                                MsiFormatRecordW(hInstall, hRec, buf.get(), &nSz));
+                CheckWin32Error("MsiSetPropertyW", MsiSetPropertyW(hInstall, sProp, buf.get()));
+            }
+        };
+        if (bRegActiveX)
+            SetFormattedPropW(L"reg_dlls", sRegData.c_str());
+        if (bUnregActiveX)
+            SetFormattedPropW(L"unreg_dlls", sRegData.c_str());
+    }
+    catch (std::exception& e)
+    {
+        WriteLog(hInstall, e.what());
+    }
+
+    return ERROR_SUCCESS;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/setup_native/source/win32/customactions/reg_dlls/reg_dlls.def b/setup_native/source/win32/customactions/reg_dlls/reg_dlls.def
new file mode 100644
index 000000000000..ed0d1685dea1
--- /dev/null
+++ b/setup_native/source/win32/customactions/reg_dlls/reg_dlls.def
@@ -0,0 +1,5 @@
+LIBRARY		"r.dll"
+EXPORTS
+			RegDLLs
+			UnregDLLs
+			PrepRegUnregDLLs
\ No newline at end of file


More information about the Libreoffice-commits mailing list