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.kagan...@collabora.com> AuthorDate: Wed May 22 19:17:44 2019 +0300 Commit: Aron Budea <aron.bu...@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.bu...@collabora.com> Tested-by: Aron Budea <aron.bu...@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", + ¤t_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 _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits