Files
odfstudio/shell/source/win32/spsupp/spsuppServ.cxx
T
Mike Kaganski f60cc89ec3 SharePoint: Add dialog to choose opening in read-only or edit mode.
ViewDocument3 method takes OpenType parameter, which allows to decide
if user can choose opening the document read-only or to edit.

Since we need to show localizable strings, we need to bootstrap part
of LO (l10n), which is impossible when e.g. 64-bit ActiveX DLL tries
to load installed 32-bit sal DLLs. Thus, we need a separate helper
.exe, which architecture matches the rest of installed LO, and which
handles user interaction.

Change-Id: I0ad53ba64272fb84728d2221e3dc85d3eefdda68
Reviewed-on: https://gerrit.libreoffice.org/72355
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
Tested-by: Mike Kaganski <mike.kaganski@collabora.com>
2019-05-17 19:15:02 +02:00

185 lines
5.6 KiB
C++

/* -*- 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 MIDL-generated file
#if defined __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wextra-tokens"
// "#endif !_MIDL_USE_GUIDDEF_" in midl-generated code
#endif
#include <spsupp_i.c>
#if defined __clang__
#pragma clang diagnostic pop
#endif
#include <memory>
#include <olectl.h>
#include <wchar.h>
#include <spsuppServ.hpp>
#include <spsuppClassFactory.hpp>
#include <COMOpenDocuments.hpp>
#include <registrar.hpp>
#include <shlwapi.h> // declaration of DllInstall
namespace
{
HANDLE g_hModule;
HMODULE GetHModule() { return static_cast<HMODULE>(g_hModule); }
} // namespace
ITypeLib* GetTypeLib()
{
typedef std::unique_ptr<ITypeLib, void(*)(IUnknown* p)> ITypeLibGuard;
static ITypeLibGuard s_aITypeLibGuard = [] {
ITypeLibGuard aITypeLibGuard(nullptr, [](IUnknown* p) { if (p) p->Release(); });
wchar_t szFile[MAX_PATH];
if (GetModuleFileNameW(GetHModule(), szFile, MAX_PATH) == 0)
return aITypeLibGuard;
ITypeLib* pTypeLib;
if (FAILED(LoadTypeLib(szFile, &pTypeLib)))
return aITypeLibGuard;
aITypeLibGuard.reset(pTypeLib);
return aITypeLibGuard;
}();
return s_aITypeLibGuard.get();
}
const wchar_t* GetHelperExe()
{
static wchar_t* s_sPath = []() -> wchar_t* {
static wchar_t sPath[MAX_PATH];
if (GetModuleFileNameW(GetHModule(), sPath, MAX_PATH) == 0)
return nullptr;
wchar_t* pSlashPos = wcsrchr(sPath, L'\\');
if (pSlashPos == nullptr)
return nullptr;
wcscpy(pSlashPos + 1, L"spsupp_helper.exe");
return sPath;
}();
return s_sPath;
}
BOOL APIENTRY DllMain( HANDLE hinstDLL,
DWORD fdwReason,
LPVOID /*lpvReserved*/ )
{
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
g_hModule = hinstDLL;
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
namespace {
// {F1924D0C-9B35-4A46-BCDE-CFEF2CE67A17}
static const IID CLSID_spsupp =
{ 0xf1924d0c, 0x9b35, 0x4a46, { 0xbc, 0xde, 0xcf, 0xef, 0x2c, 0xe6, 0x7a, 0x17 } };
}
STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppvOut)
{
*ppvOut = nullptr;
if (IsEqualIID(rclsid, CLSID_spsupp))
{
ClassFactory *pCf = new ClassFactory;
HRESULT hr = pCf->QueryInterface(riid, ppvOut);
pCf->Release();
return hr;
}
return CLASS_E_CLASSNOTAVAILABLE;
}
STDAPI DllCanUnloadNow(void)
{
if (ClassFactory::GetLockCount() == 0 &&
ClassFactory::GetObjectCount() == 0 &&
COMOpenDocuments::GetObjectCount() == 0)
return S_OK;
else
return S_FALSE;
}
STDAPI DllRegisterServer(void)
{
ITypeLib* pTypeLib = GetTypeLib();
if (!pTypeLib)
return ResultFromScode(SELFREG_E_TYPELIB);
wchar_t szFile[MAX_PATH];
if (GetModuleFileNameW(GetHModule(), szFile, MAX_PATH) == 0)
return HRESULT_FROM_WIN32(GetLastError());
HRESULT hr = RegisterTypeLib(pTypeLib, szFile, nullptr);
if (FAILED(hr))
return hr;
return Registrar(CLSID_spsupp).RegisterObject(LIBID_spsupp, L"LOSPSupport", L"OpenDocuments", 1, szFile, true);
}
STDAPI DllUnregisterServer(void)
{
ITypeLib* pTypeLib = GetTypeLib();
if (!pTypeLib)
return ResultFromScode(SELFREG_E_TYPELIB);
TLIBATTR* pLibAttr;
HRESULT hr = pTypeLib->GetLibAttr(&pLibAttr);
if (FAILED(hr))
return hr;
auto ReleaseFunc = [pTypeLib](TLIBATTR* p) { if (p) pTypeLib->ReleaseTLibAttr(p); };
typedef std::unique_ptr<TLIBATTR, decltype(ReleaseFunc)> TLIBATTRGuard;
static TLIBATTRGuard aTLIBATTRGuard(nullptr, ReleaseFunc);
hr = UnRegisterTypeLib(pLibAttr->guid, pLibAttr->wMajorVerNum, pLibAttr->wMinorVerNum, pLibAttr->lcid, pLibAttr->syskind);
if (FAILED(hr))
return hr;
return Registrar(CLSID_spsupp).UnRegisterObject(L"LOSPSupport", L"OpenDocuments", 1);
}
// This is called when regsvr32.exe is called with "/i" flag
// pszCmdLine is the string passed to "/i:<string>"
// See https://msdn.microsoft.com/library/windows/desktop/bb759846
STDAPI DllInstall(BOOL bInstall, _In_opt_ PCWSTR pszCmdLine)
{
if (wcscmp(pszCmdLine, L"Substitute_OWSSUPP") == 0)
{
HRESULT hr;
Registrar registrar(CLSID_spsupp);
if (bInstall)
{
hr = registrar.RegisterProgID(L"SharePoint", L"OpenDocuments", 3, true);
if (SUCCEEDED(hr))
hr = registrar.RegisterProgID(L"SharePoint", L"OpenDocuments", 2, false);
if (SUCCEEDED(hr))
hr = registrar.RegisterProgID(L"SharePoint", L"OpenDocuments", 1, false);
}
else
{
// Try all ProgIDs regardless of error, but make sure to return failure result if at least one failed
hr = registrar.UnRegisterProgID(L"SharePoint", L"OpenDocuments", 1);
HRESULT hrLast;
hr = SUCCEEDED(hrLast = registrar.UnRegisterProgID(L"SharePoint", L"OpenDocuments", 2)) ? hr : hrLast;
hr = SUCCEEDED(hrLast = registrar.UnRegisterProgID(L"SharePoint", L"OpenDocuments", 3)) ? hr : hrLast;
}
return hr;
}
return E_INVALIDARG;
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */