summaryrefslogtreecommitdiff
path: root/shell
diff options
context:
space:
mode:
authorMike Kaganski <mike.kaganski@collabora.com>2016-10-08 23:38:05 +1000
committerTor Lillqvist <tml@collabora.com>2017-03-10 11:05:54 +0000
commit3de2e8a32bead23229b263f21d4dff13dc695e4d (patch)
treee48dec154ab7996ed2956a6d85afd5f4549fd093 /shell
parent75f118da50b217956ee7a735e921524d0c2935ff (diff)
tdf#103058: Implement OpenDocuments ActiveX control
Change-Id: I97489090476cd884a122a4b36d3ac62ca86fd886 Reviewed-on: https://gerrit.libreoffice.org/29608 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Tor Lillqvist <tml@collabora.com>
Diffstat (limited to 'shell')
-rw-r--r--shell/CustomTarget_spsupp_idl.mk31
-rw-r--r--shell/CustomTarget_x64.mk8
-rw-r--r--shell/Library_spsupp.mk47
-rw-r--r--shell/Library_spsupp_x64.mk50
-rw-r--r--shell/Module_shell.mk4
-rw-r--r--shell/WinResTarget_spsupp.mk22
-rw-r--r--shell/inc/spsupp/COMOpenDocuments.hpp215
-rw-r--r--shell/inc/spsupp/COMRefCounted.hpp43
-rw-r--r--shell/inc/spsupp/registrar.hpp26
-rw-r--r--shell/inc/spsupp/spsuppClassFactory.hpp50
-rw-r--r--shell/inc/spsupp/spsuppServ.hpp20
-rw-r--r--shell/source/win32/spsupp/COMOpenDocuments.cxx448
-rw-r--r--shell/source/win32/spsupp/registrar.cxx173
-rw-r--r--shell/source/win32/spsupp/res/spsupp.rc1
-rw-r--r--shell/source/win32/spsupp/spsupp.def7
-rw-r--r--shell/source/win32/spsupp/spsupp.idl147
-rw-r--r--shell/source/win32/spsupp/spsuppClassFactory.cxx83
-rw-r--r--shell/source/win32/spsupp/spsuppServ.cxx140
18 files changed, 1514 insertions, 1 deletions
diff --git a/shell/CustomTarget_spsupp_idl.mk b/shell/CustomTarget_spsupp_idl.mk
new file mode 100644
index 000000000000..89f83cbd213d
--- /dev/null
+++ b/shell/CustomTarget_spsupp_idl.mk
@@ -0,0 +1,31 @@
+# -*- 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_CustomTarget_CustomTarget,shell/source/win32/spsupp/idl))
+
+spsupp_IDLDIR := $(call gb_CustomTarget_get_workdir,shell/source/win32/spsupp/idl)
+
+$(call gb_CustomTarget_get_target,shell/source/win32/spsupp/idl) : \
+ $(spsupp_IDLDIR)/spsupp.tlb
+
+$(spsupp_IDLDIR)/spsupp.tlb : \
+ $(SRCDIR)/shell/source/win32/spsupp/spsupp.idl \
+ | $(spsupp_IDLDIR)/.dir
+ $(call gb_Output_announce,$(subst $(WORKDIR)/,,$@),$(true),IDL,1)
+ $(call gb_Helper_abbreviate_dirs, \
+ midl.exe \
+ -tlb $@ \
+ -h $(spsupp_IDLDIR)/spsupp_h.h \
+ -iid $(spsupp_IDLDIR)/spsupp_i.c \
+ $(INCLUDE) \
+ $(SOLARINC) \
+ -Oicf \
+ $<)
+
+# vim:set shiftwidth=4 tabstop=4 noexpandtab:
diff --git a/shell/CustomTarget_x64.mk b/shell/CustomTarget_x64.mk
index 79dcde80d0e3..42dd36c03edb 100644
--- a/shell/CustomTarget_x64.mk
+++ b/shell/CustomTarget_x64.mk
@@ -44,6 +44,12 @@ SHELL_PROPERTYHDL_FILES := \
SHELL_XMLPARSER_FILES := \
all/xml_parser
+SHELL_SPSUPP_FILES := \
+ win32/spsupp/COMOpenDocuments \
+ win32/spsupp/registrar \
+ win32/spsupp/spsuppClassFactory \
+ win32/spsupp/spsuppServ
+
SHELL_HEADERS := \
win32/ooofilereader/autostyletag \
win32/ooofilereader/dummytag \
@@ -58,7 +64,7 @@ SHELL_HEADERS := \
win32/zipfile/zipexcptn
$(call gb_CustomTarget_get_target,shell/source) : \
- $(foreach source,$(SHELL_SHLXTHANDLER_COMMON_FILES) $(SHELL_SHLXTHDL_FILES) $(SHELL_OOOFILT_FILES) $(SHELL_PROPERTYHDL_FILES) $(SHELL_XMLPARSER_FILES),\
+ $(foreach source,$(SHELL_SHLXTHANDLER_COMMON_FILES) $(SHELL_SHLXTHDL_FILES) $(SHELL_OOOFILT_FILES) $(SHELL_PROPERTYHDL_FILES) $(SHELL_XMLPARSER_FILES) $(SHELL_SPSUPP_FILES),\
$(call gb_CustomTarget_get_workdir,shell/source)/$(source).cxx) \
$(foreach header,$(SHELL_HEADERS),\
$(call gb_CustomTarget_get_workdir,shell/source)/$(header).hxx)
diff --git a/shell/Library_spsupp.mk b/shell/Library_spsupp.mk
new file mode 100644
index 000000000000..fd9bdba84351
--- /dev/null
+++ b/shell/Library_spsupp.mk
@@ -0,0 +1,47 @@
+# -*- 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,spsupp))
+
+$(eval $(call gb_Library_use_custom_headers,spsupp,\
+ shell/source/win32/spsupp/idl \
+))
+
+$(eval $(call gb_Library_set_include,spsupp,\
+ -I$(SRCDIR)/shell/inc/spsupp \
+ $$(INCLUDE) \
+))
+
+$(eval $(call gb_Library_add_defs,spsupp,\
+ -DUNICODE \
+ -D_UNICODE \
+))
+
+$(eval $(call gb_Library_use_system_win32_libs,spsupp,\
+ advapi32 \
+ kernel32 \
+ ole32 \
+ oleaut32 \
+ user32 \
+))
+
+$(eval $(call gb_Library_add_nativeres,spsupp,spsupp))
+
+$(eval $(call gb_Library_add_ldflags,spsupp,\
+ /DEF:$(SRCDIR)/shell/source/win32/spsupp/spsupp.def \
+))
+
+$(eval $(call gb_Library_add_exception_objects,spsupp,\
+ shell/source/win32/spsupp/COMOpenDocuments \
+ shell/source/win32/spsupp/registrar \
+ shell/source/win32/spsupp/spsuppClassFactory \
+ shell/source/win32/spsupp/spsuppServ \
+))
+
+# vim: set shiftwidth=4 tabstop=4 noexpandtab:
diff --git a/shell/Library_spsupp_x64.mk b/shell/Library_spsupp_x64.mk
new file mode 100644
index 000000000000..4b29f27e31d2
--- /dev/null
+++ b/shell/Library_spsupp_x64.mk
@@ -0,0 +1,50 @@
+# -*- 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,spsupp_x64))
+
+$(eval $(call gb_Library_set_x64,spsupp_x64,YES))
+
+$(eval $(call gb_Library_use_custom_headers,spsupp_x64,\
+ shell/source \
+ shell/source/win32/spsupp/idl \
+))
+
+$(eval $(call gb_Library_set_include,spsupp_x64,\
+ -I$(SRCDIR)/shell/inc/spsupp \
+ $$(INCLUDE) \
+))
+
+$(eval $(call gb_Library_add_defs,spsupp_x64,\
+ -DUNICODE \
+ -D_UNICODE \
+))
+
+$(eval $(call gb_Library_use_system_win32_libs,spsupp_x64,\
+ advapi32 \
+ kernel32 \
+ ole32 \
+ oleaut32 \
+ user32 \
+))
+
+$(eval $(call gb_Library_add_nativeres,spsupp_x64,spsupp))
+
+$(eval $(call gb_Library_add_ldflags,spsupp_x64,\
+ /DEF:$(SRCDIR)/shell/source/win32/spsupp/spsupp.def \
+))
+
+$(eval $(call gb_Library_add_x64_generated_exception_objects,spsupp_x64,\
+ CustomTarget/shell/source/win32/spsupp/COMOpenDocuments \
+ CustomTarget/shell/source/win32/spsupp/registrar \
+ CustomTarget/shell/source/win32/spsupp/spsuppClassFactory \
+ CustomTarget/shell/source/win32/spsupp/spsuppServ \
+))
+
+# vim: set shiftwidth=4 tabstop=4 noexpandtab:
diff --git a/shell/Module_shell.mk b/shell/Module_shell.mk
index 53fda24734b6..cfe7aa061cef 100644
--- a/shell/Module_shell.mk
+++ b/shell/Module_shell.mk
@@ -61,6 +61,9 @@ $(eval $(call gb_Module_add_targets,shell,\
StaticLibrary_shlxthandler_common \
StaticLibrary_xmlparser \
WinResTarget_shlxthdl \
+ CustomTarget_spsupp_idl \
+ Library_spsupp \
+ WinResTarget_spsupp \
))
$(eval $(call gb_Module_add_check_targets,shell,\
@@ -76,6 +79,7 @@ $(eval $(call gb_Module_add_targets,shell,\
Library_shlxthdl_x64 \
StaticLibrary_shlxthandler_common_x64 \
StaticLibrary_xmlparser_x64 \
+ Library_spsupp_x64 \
))
endif
diff --git a/shell/WinResTarget_spsupp.mk b/shell/WinResTarget_spsupp.mk
new file mode 100644
index 000000000000..77d9a41342a8
--- /dev/null
+++ b/shell/WinResTarget_spsupp.mk
@@ -0,0 +1,22 @@
+# -*- 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_WinResTarget_WinResTarget,spsupp))
+
+$(eval $(call gb_WinResTarget_use_custom_headers,spsupp,\
+ shell/source/win32/spsupp/idl \
+))
+
+$(eval $(call gb_WinResTarget_add_defs,spsupp,\
+ -DTLB_FILE=\"$(call gb_CustomTarget_get_workdir,shell/source/win32/spsupp/idl)/spsupp.tlb\" \
+))
+
+$(eval $(call gb_WinResTarget_set_rcfile,spsupp,shell/source/win32/spsupp/res/spsupp))
+
+# vim: set shiftwidth=4 tabstop=4 noexpandtab:
diff --git a/shell/inc/spsupp/COMOpenDocuments.hpp b/shell/inc/spsupp/COMOpenDocuments.hpp
new file mode 100644
index 000000000000..1b2a52999ead
--- /dev/null
+++ b/shell/inc/spsupp/COMOpenDocuments.hpp
@@ -0,0 +1,215 @@
+/* -*- 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/.
+*/
+
+#ifndef _COMOPENDOCUMENTS_HPP_
+#define _COMOPENDOCUMENTS_HPP_
+
+#include "spsupp_h.h"
+#include "COMRefCounted.hpp"
+#include "Objsafe.h"
+#include "assert.h"
+
+class COMOpenDocuments : public COMRefCounted<IOWSNewDocument3>
+{
+public:
+
+ class Error {
+ public:
+ Error(HRESULT syserr) : m_nErr(syserr) {}
+ HRESULT val() const { return m_nErr; }
+ private:
+ HRESULT m_nErr;
+ };
+
+ COMOpenDocuments();
+ virtual ~COMOpenDocuments();
+
+ // IUnknown methods
+
+ HRESULT STDMETHODCALLTYPE QueryInterface(
+ REFIID riid,
+ void **ppvObject) override;
+
+ // IDispatch methods
+
+ HRESULT STDMETHODCALLTYPE GetTypeInfoCount(
+ UINT *pctinfo) override;
+
+ HRESULT STDMETHODCALLTYPE GetTypeInfo(
+ UINT iTInfo,
+ LCID lcid,
+ ITypeInfo **ppTInfo) override;
+
+ HRESULT STDMETHODCALLTYPE GetIDsOfNames(
+ REFIID riid,
+ LPOLESTR *rgszNames,
+ UINT cNames,
+ LCID lcid,
+ DISPID *rgDispId) override;
+
+ HRESULT STDMETHODCALLTYPE Invoke(
+ DISPID dispIdMember,
+ REFIID riid,
+ LCID lcid,
+ WORD wFlags,
+ DISPPARAMS *pDispParams,
+ VARIANT *pVarResult,
+ EXCEPINFO *pExcepInfo,
+ UINT *puArgErr) override;
+
+ // IOWSNewDocument methods https://msdn.microsoft.com/en-us/library/cc264316
+
+ HRESULT STDMETHODCALLTYPE CreateNewDocument(
+ BSTR bstrTemplateLocation,
+ BSTR bstrDefaultSaveLocation,
+ VARIANT_BOOL *pbResult) override;
+
+ HRESULT STDMETHODCALLTYPE EditDocument(
+ BSTR bstrDocumentLocation,
+ VARIANT varProgID,
+ VARIANT_BOOL *pbResult) override;
+
+ // IOWSNewDocument2 methods
+
+ HRESULT STDMETHODCALLTYPE ViewDocument(
+ BSTR bstrDocumentLocation,
+ VARIANT varProgID,
+ VARIANT_BOOL *pbResult) override;
+
+ HRESULT STDMETHODCALLTYPE ViewDocument2(
+ IDispatch *pdisp,
+ BSTR bstrDocumentLocation,
+ VARIANT varProgID,
+ VARIANT_BOOL *pbResult) override;
+
+ HRESULT STDMETHODCALLTYPE EditDocument2(
+ IDispatch *pdisp,
+ BSTR bstrDocumentLocation,
+ VARIANT varProgID,
+ VARIANT_BOOL *pbResult) override;
+
+ HRESULT STDMETHODCALLTYPE CreateNewDocument2(
+ IDispatch *pdisp,
+ BSTR bstrTemplateLocation,
+ BSTR bstrDefaultSaveLocation,
+ VARIANT_BOOL *pbResult) override;
+
+ HRESULT STDMETHODCALLTYPE PromptedOnLastOpen(
+ VARIANT_BOOL *pbResult) override;
+
+ // IOWSNewDocument3 methods
+
+ HRESULT STDMETHODCALLTYPE ViewDocument3(
+ IDispatch *pdisp,
+ BSTR bstrDocumentLocation,
+ int OpenType,
+ VARIANT varProgID,
+ VARIANT_BOOL *pbResult) override;
+
+ HRESULT STDMETHODCALLTYPE CheckinDocument(
+ BSTR bstrDocumentLocation,
+ int CheckinType,
+ BSTR CheckinComment,
+ VARIANT_BOOL bKeepCheckout,
+ VARIANT_BOOL *pbResult) override;
+
+ HRESULT STDMETHODCALLTYPE DiscardLocalCheckout(
+ BSTR bstrDocumentLocationRaw,
+ VARIANT_BOOL *pbResult) override;
+
+ HRESULT STDMETHODCALLTYPE ViewInExcel(
+ BSTR SiteUrl,
+ BSTR FileName,
+ BSTR SessionId,
+ BSTR Cmd,
+ BSTR Sheet,
+ int Row,
+ int Column,
+ VARIANT varProgID) override;
+
+ HRESULT STDMETHODCALLTYPE CheckoutDocumentPrompt(
+ BSTR bstrDocumentLocationRaw,
+ VARIANT_BOOL fEditAfterCheckout,
+ VARIANT varProgID,
+ VARIANT_BOOL *pbResult) override;
+
+ HRESULT STDMETHODCALLTYPE EditDocument3(
+ IDispatch *pdisp,
+ BSTR bstrDocumentLocation,
+ VARIANT_BOOL fUseLocalCopy,
+ VARIANT varProgID,
+ VARIANT_BOOL *pbResult) override;
+
+ HRESULT STDMETHODCALLTYPE NewBlogPost(
+ BSTR bstrProviderId,
+ BSTR bstrBlogUrl,
+ BSTR bstrBlogName) override;
+
+ // Non-COM methods
+
+ static long GetObjectCount();
+
+private:
+ //Aggregated object
+ class COMObjectSafety : public IObjectSafety
+ {
+ public:
+ COMObjectSafety(IUnknown* pOwner) : m_pOwner(pOwner) { assert(m_pOwner); }
+ virtual ~COMObjectSafety() {}
+
+ // IUnknown members delegate to the outer unknown
+ // IUnknown members do not control lifetime of object
+
+ HRESULT STDMETHODCALLTYPE QueryInterface(
+ REFIID riid,
+ void **ppvObject) override
+ {
+ return m_pOwner->QueryInterface(riid, ppvObject);
+ }
+
+ ULONG STDMETHODCALLTYPE AddRef() override { return m_pOwner->AddRef(); }
+
+ ULONG STDMETHODCALLTYPE Release() override { return m_pOwner->Release(); }
+
+ // IObjectSafety methods
+
+ HRESULT STDMETHODCALLTYPE GetInterfaceSafetyOptions(
+ REFIID riid,
+ DWORD *pdwSupportedOptions,
+ DWORD *pdwEnabledOptions) override;
+
+ HRESULT STDMETHODCALLTYPE SetInterfaceSafetyOptions(
+ REFIID riid,
+ DWORD dwOptionSetMask,
+ DWORD dwEnabledOptions) override;
+
+ // Non-COM methods
+
+ bool GetSafe_forUntrustedCaller() { return (m_iEnabledOptions & INTERFACESAFE_FOR_UNTRUSTED_CALLER) != 0; }
+ bool GetSafe_forUntrustedData() { return (m_iEnabledOptions & INTERFACESAFE_FOR_UNTRUSTED_DATA) != 0; }
+
+ private:
+ IUnknown* m_pOwner;
+ DWORD m_iEnabledOptions = 0;
+ enum : DWORD { iSupportedOptionsMask = INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA };
+
+ void SetMaskedOptions(DWORD iMask, DWORD iOptions);
+ void SetSafe_forUntrustedCaller(bool bSafe);
+ void SetSafe_forUntrustedData(bool bSafe);
+ };
+
+ static long m_nObjCount;
+ static ITypeInfo* m_pTypeInfo;
+ static wchar_t m_szLOPath[MAX_PATH];
+ COMObjectSafety m_aObjectSafety;
+};
+
+#endif // _COMOPENDOCUMENTS_HPP_
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/shell/inc/spsupp/COMRefCounted.hpp b/shell/inc/spsupp/COMRefCounted.hpp
new file mode 100644
index 000000000000..1a60ed372300
--- /dev/null
+++ b/shell/inc/spsupp/COMRefCounted.hpp
@@ -0,0 +1,43 @@
+/* -*- 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/.
+*/
+
+#ifndef _COMREFCOUNTED_HPP_
+#define _COMREFCOUNTED_HPP_
+
+#include "objbase.h"
+
+template <class Interface>
+class COMRefCounted : public Interface
+{
+public:
+ COMRefCounted() {}
+ virtual ~COMRefCounted() {}
+
+ // IUnknown methods
+
+ ULONG STDMETHODCALLTYPE AddRef() override
+ {
+ return static_cast<ULONG>(::InterlockedIncrement(&m_nRef));
+ }
+
+ ULONG STDMETHODCALLTYPE Release() override
+ {
+ if (::InterlockedDecrement(&m_nRef) == 0)
+ delete this;
+ return (m_nRef > 0) ? static_cast<ULONG>(m_nRef) : 0;
+ }
+
+private:
+
+ long m_nRef = 1; // Created referenced
+};
+
+#endif // _COMREFCOUNTED_HPP_
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/shell/inc/spsupp/registrar.hpp b/shell/inc/spsupp/registrar.hpp
new file mode 100644
index 000000000000..00b230e5c624
--- /dev/null
+++ b/shell/inc/spsupp/registrar.hpp
@@ -0,0 +1,26 @@
+/* -*- 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/.
+*/
+
+#ifndef _REGISTRAR_H
+#define _REGISTRAR_H
+
+#include "windows.h"
+
+namespace Registrar {
+ HRESULT RegisterObject(REFIID riidCLSID,
+ REFIID riidTypeLib,
+ const wchar_t* sProgram,
+ const wchar_t* sComponent,
+ const wchar_t* Path);
+ HRESULT UnRegisterObject(REFIID riidCLSID, const wchar_t* LibId, const wchar_t* ClassId);
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/shell/inc/spsupp/spsuppClassFactory.hpp b/shell/inc/spsupp/spsuppClassFactory.hpp
new file mode 100644
index 000000000000..9bb879f70393
--- /dev/null
+++ b/shell/inc/spsupp/spsuppClassFactory.hpp
@@ -0,0 +1,50 @@
+/* -*- 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/.
+*/
+
+#ifndef _SPSUPPCLASSFACTORY_H_
+#define _SPSUPPCLASSFACTORY_H_
+
+#include "COMRefCounted.hpp"
+
+class ClassFactory : public COMRefCounted<IClassFactory>
+{
+public:
+ ClassFactory();
+ virtual ~ClassFactory();
+
+ // IUnknown methods
+
+ HRESULT STDMETHODCALLTYPE QueryInterface(
+ REFIID riid,
+ void **ppvObject) override;
+
+ // IClassFactory methods
+
+ HRESULT STDMETHODCALLTYPE CreateInstance(
+ IUnknown *pUnkOuter,
+ REFIID riid,
+ void **ppvObject) override;
+
+ HRESULT STDMETHODCALLTYPE LockServer(
+ BOOL fLock) override;
+
+ // Non-COM methods
+
+ static long GetObjectCount() { return m_nObjCount; }
+ static long GetLockCount() { return m_nLockCount; }
+
+private:
+
+ static long m_nObjCount;
+ static long m_nLockCount;
+};
+
+#endif // _SPSUPPCLASSFACTORY_H_
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/shell/inc/spsupp/spsuppServ.hpp b/shell/inc/spsupp/spsuppServ.hpp
new file mode 100644
index 000000000000..971e6bcda9b8
--- /dev/null
+++ b/shell/inc/spsupp/spsuppServ.hpp
@@ -0,0 +1,20 @@
+/* -*- 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/.
+*/
+
+#ifndef _SPSUPPSERV_HPP_
+#define _SPSUPPSERV_HPP_
+
+#include <objbase.h>
+
+ITypeLib* GetTypeLib();
+const wchar_t* GetLOPath();
+
+#endif // _SPSUPPSERV_HPP_
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/shell/source/win32/spsupp/COMOpenDocuments.cxx b/shell/source/win32/spsupp/COMOpenDocuments.cxx
new file mode 100644
index 000000000000..b9d24405aa4f
--- /dev/null
+++ b/shell/source/win32/spsupp/COMOpenDocuments.cxx
@@ -0,0 +1,448 @@
+/* -*- 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 "COMOpenDocuments.hpp"
+#include "spsuppServ.hpp"
+#include "stdio.h"
+
+// Display confirmation dialog, return false on negative answer
+bool SecurityWarning(const wchar_t* sProgram, const wchar_t* sDocument)
+{
+ // TODO: change wording (currently taken from MS Office), use LO localization
+ wchar_t sBuf[65536];
+ swprintf(sBuf, sizeof(sBuf) / sizeof(sBuf[0]),
+ L"Some files contain viruses that can be harmful to your computer. It is important to be certain that this file is from a trustworthy source.\n\n"
+ L"Do you want to open this file ?\n\n"
+ L"Program : %s\n\n"
+ L"Address : %s", sProgram, sDocument);
+ return (MessageBoxW(nullptr, sBuf, L"LibreOffice SharePoint integration", MB_YESNO | MB_ICONWARNING) == IDYES);
+}
+
+// Returns S_OK if successful
+HRESULT LOStart(wchar_t* sCommandLine)
+{
+ STARTUPINFOW si = { sizeof(si) };
+ si.dwFlags = STARTF_USESHOWWINDOW;
+ si.wShowWindow = SW_SHOW;
+ PROCESS_INFORMATION pi = {};
+ if (CreateProcessW(nullptr, sCommandLine, nullptr, nullptr, FALSE, 0, nullptr, nullptr, &si, &pi) == FALSE)
+ {
+ DWORD dwError = GetLastError();
+ wchar_t* sMsgBuf;
+ FormatMessageW(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ nullptr,
+ dwError,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPWSTR)&sMsgBuf,
+ 0, nullptr);
+
+ size_t nBufSize = wcslen(sMsgBuf) + 100;
+ wchar_t* sDisplayBuf = new wchar_t[nBufSize];
+ swprintf(sDisplayBuf, nBufSize, L"Could not start LibreOffice. Error is 0x%08X:\n\n%s", dwError, sMsgBuf);
+ LocalFree(sMsgBuf);
+
+ // Report the error to user and return error
+ MessageBoxW(nullptr, sDisplayBuf, nullptr, MB_ICONERROR);
+ delete[](sDisplayBuf);
+ return HRESULT_FROM_WIN32(dwError);
+ }
+ CloseHandle(pi.hProcess);
+ CloseHandle(pi.hThread);
+ return S_OK;
+}
+
+// IObjectSafety methods
+
+void COMOpenDocuments::COMObjectSafety::SetMaskedOptions(DWORD iMask, DWORD iOptions)
+{
+ m_iEnabledOptions &= ~iMask;
+ m_iEnabledOptions |= (iOptions & iMask);
+}
+
+void COMOpenDocuments::COMObjectSafety::SetSafe_forUntrustedCaller(bool bSafe)
+{
+ if (GetSafe_forUntrustedCaller() != bSafe)
+ {
+ SetMaskedOptions(INTERFACESAFE_FOR_UNTRUSTED_CALLER, bSafe ? 0xFFFFFFFF : 0);
+ }
+}
+
+void COMOpenDocuments::COMObjectSafety::SetSafe_forUntrustedData(bool bSafe)
+{
+ if (GetSafe_forUntrustedData() != bSafe)
+ {
+ SetMaskedOptions(INTERFACESAFE_FOR_UNTRUSTED_DATA, bSafe ? 0xFFFFFFFF : 0);
+ }
+}
+
+HRESULT STDMETHODCALLTYPE COMOpenDocuments::COMObjectSafety::GetInterfaceSafetyOptions(
+ REFIID riid,
+ DWORD *pdwSupportedOptions,
+ DWORD *pdwEnabledOptions)
+{
+ void* ppvo;
+ HRESULT hr = m_pOwner->QueryInterface(riid, &ppvo);
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+
+ // We know about it; release reference and return required information
+ reinterpret_cast<IUnknown*>(ppvo)->Release();
+ *pdwSupportedOptions = iSupportedOptionsMask;
+ *pdwEnabledOptions = m_iEnabledOptions;
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE COMOpenDocuments::COMObjectSafety::SetInterfaceSafetyOptions(
+ REFIID /*riid*/,
+ DWORD dwOptionSetMask,
+ DWORD dwEnabledOptions)
+{
+ // Are there unsupported options in mask?
+ if (dwOptionSetMask & ~iSupportedOptionsMask)
+ return E_FAIL;
+
+ if (dwOptionSetMask & INTERFACESAFE_FOR_UNTRUSTED_CALLER)
+ {
+ SetSafe_forUntrustedCaller(dwEnabledOptions & INTERFACESAFE_FOR_UNTRUSTED_CALLER);
+ }
+
+ if (dwOptionSetMask & INTERFACESAFE_FOR_UNTRUSTED_DATA)
+ {
+ SetSafe_forUntrustedData((dwEnabledOptions & INTERFACESAFE_FOR_UNTRUSTED_DATA) != 0);
+ }
+
+ return S_OK;
+}
+
+long COMOpenDocuments::m_nObjCount = 0;
+ITypeInfo* COMOpenDocuments::m_pTypeInfo = nullptr;
+wchar_t COMOpenDocuments::m_szLOPath[MAX_PATH] = {0};
+
+COMOpenDocuments::COMOpenDocuments()
+ : m_aObjectSafety(this)
+{
+ ::InterlockedIncrement(&m_nObjCount);
+ if (m_pTypeInfo == nullptr)
+ {
+ ITypeLib* pITypeLib = GetTypeLib();
+ HRESULT hr = pITypeLib->GetTypeInfoOfGuid(__uuidof(IOWSNewDocument3), &m_pTypeInfo);
+ if (FAILED(hr))
+ throw Error(hr);
+ }
+}
+
+COMOpenDocuments::~COMOpenDocuments()
+{
+ if (::InterlockedDecrement(&m_nObjCount) == 0 && m_pTypeInfo)
+ {
+ m_pTypeInfo->Release();
+ m_pTypeInfo = nullptr;
+ }
+}
+
+// IUnknown methods
+
+STDMETHODIMP COMOpenDocuments::QueryInterface(REFIID riid, void **ppvObject)
+{
+ *ppvObject = nullptr;
+ if (IsEqualIID(riid, __uuidof(IUnknown)) ||
+ IsEqualIID(riid, __uuidof(IDispatch)) ||
+ IsEqualIID(riid, __uuidof(IOWSNewDocument)) ||
+ IsEqualIID(riid, __uuidof(IOWSNewDocument2)) ||
+ IsEqualIID(riid, __uuidof(IOWSNewDocument3)))
+ {
+ *ppvObject = this;
+ }
+ else if (IsEqualIID(riid, __uuidof(IObjectSafety)))
+ {
+ *ppvObject = &m_aObjectSafety;
+ }
+ else
+ {
+ return E_NOINTERFACE;
+ }
+
+ reinterpret_cast<IUnknown*>(*ppvObject)->AddRef();
+ return S_OK;
+}
+
+// IDispatch methods
+
+STDMETHODIMP COMOpenDocuments::GetTypeInfoCount(UINT *pctinfo)
+{
+ if (pctinfo == nullptr)
+ return E_INVALIDARG;
+
+ *pctinfo = 1;
+ return S_OK;
+}
+
+STDMETHODIMP COMOpenDocuments::GetTypeInfo(UINT iTInfo, LCID /*lcid*/, ITypeInfo **ppTInfo)
+{
+ if (ppTInfo == nullptr)
+ return E_INVALIDARG;
+ *ppTInfo = nullptr;
+
+ if (iTInfo != 0)
+ return DISP_E_BADINDEX;
+
+ (*ppTInfo = m_pTypeInfo)->AddRef();
+ return S_OK;
+}
+
+STDMETHODIMP COMOpenDocuments::GetIDsOfNames(
+ REFIID /*riid*/,
+ LPOLESTR *rgszNames,
+ UINT cNames,
+ LCID /*lcid*/,
+ DISPID *rgDispId)
+{
+ return m_pTypeInfo->GetIDsOfNames(rgszNames, cNames, rgDispId);
+}
+
+STDMETHODIMP COMOpenDocuments::Invoke(
+ DISPID dispIdMember,
+ REFIID /*riid*/, // IID_NULL (see https://msdn.microsoft.com/en-us/library/windows/desktop/ms221479)
+ LCID /*lcid*/,
+ WORD wFlags,
+ DISPPARAMS *pDispParams,
+ VARIANT *pVarResult,
+ EXCEPINFO *pExcepInfo,
+ UINT *puArgErr)
+{
+// ReportInvoke(m_pTypeInfo, dispIdMember, pDispParams);
+ return DispInvoke(this, m_pTypeInfo, dispIdMember, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
+}
+
+// IOWSNewDocument methods
+
+// Creates a document based on the specified document template
+STDMETHODIMP COMOpenDocuments::CreateNewDocument(
+ BSTR bstrTemplateLocation, // A string that contains the URL of the document template from which the document is created, or the programmatic identifier (progID) of the application to invoke when creating the document
+ BSTR bstrDefaultSaveLocation, // A string that contains the path that specifies a suggested default location for saving the new document
+ VARIANT_BOOL *pbResult) // true if the document creation succeeds; otherwise false
+{
+ return CreateNewDocument2(nullptr, bstrTemplateLocation, bstrDefaultSaveLocation, pbResult);
+}
+
+// Opens the specified document for editing with its associated application
+// or with the specified editor
+STDMETHODIMP COMOpenDocuments::EditDocument(
+ BSTR bstrDocumentLocation, // A string that contains the URL of the document to open for editing
+ VARIANT varProgID, // An optional string that contains the ProgID of the application with which to edit the document. If this argument is omitted, the default editor for the document is used
+ VARIANT_BOOL *pbResult) // true if the document was successfully opened; otherwise false
+{
+ return EditDocument3(nullptr, bstrDocumentLocation, FALSE, varProgID, pbResult);
+}
+
+// IOWSNewDocument2 methods
+
+// Opens the document for reading instead of editing, so that the document is not locked on the server
+//
+// Use the ViewDocument method to open a document in its appropriate application,
+// instead of inside of an application instance embedded within the browser
+STDMETHODIMP COMOpenDocuments::ViewDocument(
+ BSTR bstrDocumentLocation, // A string that contains the URL of the document to open for reading
+ VARIANT varProgID, // An optional string that contains the ProgID of the application with which to open the document. If this argument is omitted, the default viewer for the document is used
+ VARIANT_BOOL *pbResult) // true if the document was successfully opened; otherwise false
+{
+ return ViewDocument3(nullptr, bstrDocumentLocation, 0, varProgID, pbResult);
+}
+
+// Opens the document for reading instead of editing, so that the document
+// is not locked on the server and in a specified window
+//
+// Use the ViewDocument method to open a document in its appropriate application,
+// instead of inside of an application instance embedded within the browser
+STDMETHODIMP COMOpenDocuments::ViewDocument2(
+ IDispatch *pdisp, // An Object that represents the window from which the ViewDocument2 method is being activated
+ BSTR bstrDocumentLocation, // A string that contains the URL of the document to open for reading
+ VARIANT varProgID, // An optional string that contains the ProgID of the application with which to open the document. If this argument is omitted, the default viewer for the document is used
+ VARIANT_BOOL *pbResult) // true if the document was successfully opened; otherwise false
+{
+ return ViewDocument3(pdisp, bstrDocumentLocation, 0, varProgID, pbResult);
+}
+
+// Opens the specified document for editing with its associated application
+// or with the specified editor based on the specified window object
+STDMETHODIMP COMOpenDocuments::EditDocument2(
+ IDispatch *pdisp, // An Object that represents the window from which the EditDocument2 method is being activated
+ BSTR bstrDocumentLocation, // A string that contains the URL of the document to open for editing
+ VARIANT varProgID, // An optional string that contains the ProgID of the application with which to edit the document. If this argument is omitted, the default editor for the document is used
+ VARIANT_BOOL *pbResult) // true if the document was successfully opened; otherwise false
+{
+ return EditDocument3(pdisp, bstrDocumentLocation, FALSE, varProgID, pbResult);
+}
+
+// Creates a document based on the specified document template and window object
+STDMETHODIMP COMOpenDocuments::CreateNewDocument2(
+ IDispatch* /*pdisp*/, // An Object that represents the window from which the CreateNewDocument2 method is being activated
+ BSTR bstrTemplateLocation, // A string that contains the URL of the document template from which the document is created, or the programmatic identifier (progID) of the application to invoke when creating the document
+ BSTR /*bstrDefaultSaveLocation*/, // A string that contains the path that specifies a suggested default location for saving the new document
+ VARIANT_BOOL* pbResult) // true if the document creation succeeds; otherwise false
+{
+ // TODO: resolve the program from varProgID (nullptr -> default?)
+ const wchar_t* sProgram = GetLOPath();
+ if (m_aObjectSafety.GetSafe_forUntrustedCaller() || m_aObjectSafety.GetSafe_forUntrustedData())
+ {
+ if (!SecurityWarning(sProgram, bstrTemplateLocation))
+ {
+ // Set result to true and return success to avoid downloading in browser
+ *pbResult = TRUE;
+ return S_OK;
+ }
+ }
+ wchar_t sCommandLine[32768];
+ swprintf(sCommandLine, sizeof(sCommandLine) / sizeof(*sCommandLine), L"\"%s\" -n \"%s\"", sProgram, bstrTemplateLocation);
+ HRESULT hr = LOStart(sCommandLine);
+ *pbResult = SUCCEEDED(hr);
+ return hr;
+}
+
+// Used with the OpenDocuments.CreateNewDocument2 Method method to determine
+// whether the security dialog box that appears when a document is opened has already appeared
+//
+// If the PromptedOnLastOpen method returns true, the window containing the document library view
+// refreshes itself the next time it receives focus. One refresh can occur after the new document
+// is saved to the server
+STDMETHODIMP COMOpenDocuments::PromptedOnLastOpen(
+ VARIANT_BOOL* /*pbResult*/) // true if the security dialog box that appears when a document is opened has already appeared; otherwise false
+{
+ // TODO
+ return E_NOTIMPL;
+}
+
+// IOWSNewDocument3 methods
+
+// Opens the document for reading instead of editing, so that the document
+// is not locked on the server in a specified window, and with a specified type
+//
+// The following table shows possible values for OpenType
+//
+// 0 When checked out, or when the document library does not require check out, the user can read or edit the document
+// 1 When another user has checked it out, the user can only read the document
+// 2 When the current user has checked it out, the user can only edit the document
+// 3 When the document is not checked out and the document library requires that documents be checked out to be edited, the user can only read the document, or check it out and edit it
+// 4 When the current user has checked it out, the user can only edit the local copy of the document
+STDMETHODIMP COMOpenDocuments::ViewDocument3(
+ IDispatch* /*pdisp*/, // An Object that represents the window from which the ViewDocmument3 method is being activated
+ BSTR bstrDocumentLocation, // A string that contains the URL of the document to open for reading
+ int /*OpenType*/, // A Long integer that specifies the rights for opening the document
+ VARIANT /*varProgID*/, // An optional string that contains the ProgID of the application with which to open the document. If this argument is omitted, the default viewer for the document is used
+ VARIANT_BOOL *pbResult) // true if the document was successfully opened; otherwise false
+{
+ // TODO: resolve the program from varProgID (nullptr -> default?)
+ const wchar_t* sProgram = GetLOPath();
+ if (m_aObjectSafety.GetSafe_forUntrustedCaller() || m_aObjectSafety.GetSafe_forUntrustedData())
+ {
+ if (!SecurityWarning(sProgram, bstrDocumentLocation))
+ {
+ // Set result to true and return success to avoid downloading in browser
+ *pbResult = TRUE;
+ return S_OK;
+ }
+ }
+ wchar_t sCommandLine[32768];
+ swprintf(sCommandLine, sizeof(sCommandLine) / sizeof(*sCommandLine), L"\"%s\" --view \"%s\"", sProgram, bstrDocumentLocation);
+ HRESULT hr = LOStart(sCommandLine);
+ *pbResult = SUCCEEDED(hr);
+ return hr;
+}
+
+// Checks in the specified document to a library
+STDMETHODIMP COMOpenDocuments::CheckinDocument(
+ BSTR /*bstrDocumentLocation*/, // A string that contains the URL of the document to check in
+ int /*CheckinType*/, // A Long that specifies the type of check-in, where 0 = minor check-in, 1 = major check-in, and 2 = overwrite check-in
+ BSTR /*CheckinComment*/, // A string that contains a comment for checking in the document
+ VARIANT_BOOL /*bKeepCheckout*/, // Optional. true to check in changes that have been made to the document yet keep the document checked out; otherwise, false. The default value is false
+ VARIANT_BOOL* /*pbResult*/) // true if the document is successfully checked in; otherwise, false
+{
+ // TODO
+ return E_NOTIMPL;
+}
+
+// Discards the check out of a document to the client computer and deletes the local draft
+STDMETHODIMP COMOpenDocuments::DiscardLocalCheckout(
+ BSTR /*bstrDocumentLocationRaw*/, // A string that contains the URL of the document
+ VARIANT_BOOL* /*pbResult*/) // true if the operation to discard the local checkout of the document is successful; otherwise, false
+{
+ // TODO
+ return E_NOTIMPL;
+}
+
+// Deprecated. Returns E_NOTIMPL
+STDMETHODIMP COMOpenDocuments::ViewInExcel(
+ BSTR /*SiteUrl*/,
+ BSTR /*FileName*/,
+ BSTR /*SessionId*/,
+ BSTR /*Cmd*/,
+ BSTR /*Sheet*/,
+ int /*Row*/,
+ int /*Column*/,
+ VARIANT /*varProgID*/)
+{
+ return E_NOTIMPL;
+}
+
+// Checks out a document from a library
+STDMETHODIMP COMOpenDocuments::CheckoutDocumentPrompt(
+ BSTR /*bstrDocumentLocationRaw*/, // A string that contains the URL of the document to check out
+ VARIANT_BOOL /*fEditAfterCheckout*/, // true to open the document in an editing application; otherwise, false
+ VARIANT /*varProgID*/, // An optional string that contains the ProgID of the application that is used to work with the document. If this argument is omitted, the default application for the document is used
+ VARIANT_BOOL* /*pbResult*/) // true if the document is successfully checked out; otherwise, false
+{
+ // TODO
+ return E_NOTIMPL;
+}
+
+// Opens the specified document for editing with its associated application
+// or with the specified editor based on the specified window object,
+// and specifies whether to use a local copy
+STDMETHODIMP COMOpenDocuments::EditDocument3(
+ IDispatch* /*pdisp*/, // An Object that represents the window from which the EditDocument3 method is being activated
+ BSTR bstrDocumentLocation, // A string that contains the URL of the document to open for editing
+ VARIANT_BOOL /*fUseLocalCopy*/, // true to use a local copy; otherwise false
+ VARIANT /*varProgID*/, // An optional string that contains the ProgID of the application with which to edit the document. If this argument is omitted, the default editor for the document is used
+ VARIANT_BOOL *pbResult) // true if the document was successfully opened; otherwise false
+{
+ // TODO: resolve the program from varProgID (nullptr -> default?)
+ const wchar_t* sProgram = GetLOPath();
+ if (m_aObjectSafety.GetSafe_forUntrustedCaller() || m_aObjectSafety.GetSafe_forUntrustedData())
+ {
+ if (!SecurityWarning(sProgram, bstrDocumentLocation))
+ {
+ // Set result to true and return success to avoid downloading in browser
+ *pbResult = TRUE;
+ return S_OK;
+ }
+ }
+ wchar_t sCommandLine[32768];
+ swprintf(sCommandLine, sizeof(sCommandLine) / sizeof(*sCommandLine), L"\"%s\" -o \"%s\"", sProgram, bstrDocumentLocation);
+ HRESULT hr = LOStart(sCommandLine);
+ *pbResult = SUCCEEDED(hr);
+ return hr;
+}
+
+// Creates a new blog post in the editing application
+STDMETHODIMP COMOpenDocuments::NewBlogPost(
+ BSTR /*bstrProviderId*/, // A string that contains the GUID of the blog provider
+ BSTR /*bstrBlogUrl*/, // A string that contains the absolute URL of the blog site
+ BSTR /*bstrBlogName*/) // A string that contains the GUID of the blog site and the GUID of the post list separated by the pound sign (#)
+{
+ return E_NOTIMPL;
+}
+
+long COMOpenDocuments::GetObjectCount() { return m_nObjCount; }
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/shell/source/win32/spsupp/registrar.cxx b/shell/source/win32/spsupp/registrar.cxx
new file mode 100644
index 000000000000..2d182cb7b85f
--- /dev/null
+++ b/shell/source/win32/spsupp/registrar.cxx
@@ -0,0 +1,173 @@
+/* -*- 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 "registrar.hpp"
+#include "stdio.h"
+
+namespace {
+
+ HRESULT RegWrite(HKEY hRootKey, const wchar_t* subKey, const wchar_t* keyName, const wchar_t* keyValue, HKEY *hKeyResult = nullptr)
+ {
+ HKEY hKey;
+ long iRetVal = RegCreateKeyExW(
+ hRootKey,
+ subKey,
+ 0,
+ nullptr,
+ REG_OPTION_NON_VOLATILE,
+ KEY_WRITE,
+ nullptr,
+ &hKey,
+ nullptr);
+ if (iRetVal != ERROR_SUCCESS)
+ return HRESULT_FROM_WIN32(iRetVal);
+
+ if (keyValue)
+ {
+ DWORD cbData = static_cast<DWORD>(wcslen(keyValue)*sizeof(keyValue[0]));
+ iRetVal = RegSetValueExW(hKey, keyName, 0, REG_SZ, reinterpret_cast<const BYTE *>(keyValue), cbData);
+ }
+
+ if (hKeyResult && (iRetVal == ERROR_SUCCESS))
+ *hKeyResult = hKey;
+ else
+ RegCloseKey(hKey);
+
+ return HRESULT_FROM_WIN32(iRetVal);
+ }
+
+ HRESULT RegDel(HKEY hRootKey, const wchar_t* subKey)
+ {
+ long iRetVal = RegDeleteKeyW(hRootKey, subKey);
+ return HRESULT_FROM_WIN32(iRetVal);
+ }
+
+ const int nGUIDlen = 40;
+
+}
+
+namespace Registrar {
+
+ // see http://stackoverflow.com/questions/284619
+ // see https://msdn.microsoft.com/en-us/library/ms691424
+ // see https://msdn.microsoft.com/en-us/library/ms694514
+
+ HRESULT RegisterObject(REFIID riidCLSID,
+ REFIID riidTypeLib,
+ const wchar_t* sProgram,
+ const wchar_t* sComponent,
+ const wchar_t* Path)
+ {
+ if (!wcslen(sComponent) || !wcslen(sProgram))
+ return E_INVALIDARG;
+
+ wchar_t sCLSID[nGUIDlen];
+ if (::StringFromGUID2(riidCLSID, sCLSID, nGUIDlen) == 0)
+ return E_UNEXPECTED;
+
+ // HKEY_CLASSES_ROOT
+ // \CLSID
+ // \{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}
+ // (default) = "MyLibrary MyControl Class"
+ // \InprocServer32
+ // (default) = "c:\foo\control.dll"
+ // ThreadingModel = "Apartment"
+ // \ProgID
+ // (default) = "MyLibrary.MyControl"
+ // \Programmable
+ // \TypeLib
+ // (default) = "{YYYYYYYY-YYYY-YYYY-YYYY-YYYYYYYYYYYY}"
+ // \MyLibrary.MyControl
+ // \CLSID
+ // (default) = "{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}"
+
+ wchar_t sBufKey[MAX_PATH];
+ wchar_t sBufVal[MAX_PATH];
+
+ // CLSID
+ swprintf(sBufKey, MAX_PATH, L"CLSID\\%s", sCLSID);
+ swprintf(sBufVal, MAX_PATH, L"%s %s Class", sProgram, sComponent);
+ HKEY hKeyCLSID;
+ HRESULT hr = RegWrite(HKEY_CLASSES_ROOT, sBufKey, L"", sBufVal, &hKeyCLSID);
+ if (FAILED(hr))
+ return hr;
+ {
+ class HKeyGuard {
+ public:
+ HKeyGuard(HKEY aKey) : m_hKey(aKey) {}
+ ~HKeyGuard() { RegCloseKey(m_hKey); }
+ private:
+ HKEY m_hKey;
+ };
+
+ HKeyGuard hKeyCLSIDGuard(hKeyCLSID);
+
+ // InprocServer32
+ HKEY hKeyInprocServer32;
+ hr = RegWrite(hKeyCLSID, L"InprocServer32", L"", Path, &hKeyInprocServer32);
+ if (FAILED(hr))
+ return hr;
+ {
+ HKeyGuard hKeyInProcServer32Guard(hKeyInprocServer32);
+ hr = RegWrite(hKeyInprocServer32, L"", L"ThreadingModel", L"Apartment");
+ if (FAILED(hr))
+ return hr;
+ }
+
+ // ProgID
+ swprintf(sBufVal, MAX_PATH, L"%s.%s", sProgram, sComponent);
+ hr = RegWrite(hKeyCLSID, L"ProgID", L"", sBufVal);
+ if (FAILED(hr))
+ return hr;
+
+ // Programmable
+ hr = RegWrite(hKeyCLSID, L"Programmable", nullptr, nullptr);
+ if (FAILED(hr))
+ return hr;
+
+ // TypeLib
+ if (::StringFromGUID2(riidTypeLib, sBufVal, nGUIDlen) == 0)
+ return E_UNEXPECTED;
+ hr = RegWrite(hKeyCLSID, L"TypeLib", L"", sBufVal);
+ if (FAILED(hr))
+ return hr;
+ }
+
+ // ProgID
+ swprintf(sBufKey, MAX_PATH, L"%s.%s\\CLSID", sProgram, sComponent);
+ return RegWrite(HKEY_CLASSES_ROOT, sBufKey, L"", sCLSID);
+ }
+
+ HRESULT UnRegisterObject(REFIID riidCLSID, const wchar_t* LibId, const wchar_t* ClassId)
+ {
+ wchar_t sCLSID[nGUIDlen];
+ wchar_t sBuf[MAX_PATH];
+ if (::StringFromGUID2(riidCLSID, sCLSID, nGUIDlen) == 0)
+ return E_UNEXPECTED;
+ // ProgID
+ swprintf(sBuf, MAX_PATH, L"%s.%s\\CLSID", LibId, ClassId);
+ RegDel(HKEY_CLASSES_ROOT, sBuf);
+ swprintf(sBuf, MAX_PATH, L"%s.%s", LibId, ClassId);
+ RegDel(HKEY_CLASSES_ROOT, sBuf);
+ // CLSID
+ swprintf(sBuf, MAX_PATH, L"CLSID\\%s\\InProcServer32", sCLSID);
+ RegDel(HKEY_CLASSES_ROOT, sBuf);
+ swprintf(sBuf, MAX_PATH, L"CLSID\\%s\\ProgId", sCLSID);
+ RegDel(HKEY_CLASSES_ROOT, sBuf);
+ swprintf(sBuf, MAX_PATH, L"CLSID\\%s\\Programmable", sCLSID);
+ RegDel(HKEY_CLASSES_ROOT, sBuf);
+ swprintf(sBuf, MAX_PATH, L"CLSID\\%s\\TypeLib", sCLSID);
+ RegDel(HKEY_CLASSES_ROOT, sBuf);
+ swprintf(sBuf, MAX_PATH, L"CLSID\\%s", sCLSID);
+ return RegDel(HKEY_CLASSES_ROOT, sBuf);
+ }
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/shell/source/win32/spsupp/res/spsupp.rc b/shell/source/win32/spsupp/res/spsupp.rc
new file mode 100644
index 000000000000..c7f62aeb24e3
--- /dev/null
+++ b/shell/source/win32/spsupp/res/spsupp.rc
@@ -0,0 +1 @@
+1 TYPELIB TLB_FILE \ No newline at end of file
diff --git a/shell/source/win32/spsupp/spsupp.def b/shell/source/win32/spsupp/spsupp.def
new file mode 100644
index 000000000000..2977aa21d125
--- /dev/null
+++ b/shell/source/win32/spsupp/spsupp.def
@@ -0,0 +1,7 @@
+LIBRARY
+
+EXPORTS
+ DllRegisterServer PRIVATE
+ DllUnregisterServer PRIVATE
+ DllCanUnloadNow PRIVATE
+ DllGetClassObject PRIVATE
diff --git a/shell/source/win32/spsupp/spsupp.idl b/shell/source/win32/spsupp/spsupp.idl
new file mode 100644
index 000000000000..45d5f47b13a1
--- /dev/null
+++ b/shell/source/win32/spsupp/spsupp.idl
@@ -0,0 +1,147 @@
+/* -*- 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/.
+*/
+
+[
+ uuid(580411ED-80EC-4834-BA1F-2EB07A49C80B),
+ version(0.1),
+ helpstring("LibreOffice SharePoint Client Support Type Library v.0.1")
+]
+library spsupp
+{
+ // TLib : OLE Automation : {00020430-0000-0000-C000-000000000046}
+ importlib("stdole2.tlb");
+
+ // Forward declare all types defined in this typelib
+ interface IOWSNewDocument;
+ interface IOWSNewDocument2;
+ interface IOWSNewDocument3;
+
+ [
+ odl,
+ uuid(7B678CDE-D71C-4954-ACC7-A92A96BF70DB),
+ helpstring("IOWSNewDocument Interface"),
+ dual,
+ oleautomation
+ ]
+ interface IOWSNewDocument : IDispatch {
+ [id(0x60020000)]
+ HRESULT CreateNewDocument(
+ [in] BSTR bstrTemplateLocation,
+ [in] BSTR bstrDefaultSaveLocation,
+ [out, retval] VARIANT_BOOL* pbResult);
+ [id(0x60020001)]
+ HRESULT EditDocument(
+ [in] BSTR bstrDocumentLocation,
+ [in, optional] VARIANT varProgID,
+ [out, retval] VARIANT_BOOL* pbResult);
+ };
+
+ [
+ odl,
+ uuid(470D72F8-C6E2-40D1-B844-4FF73DB69EC5),
+ helpstring("IOWSNewDocument2 Interface"),
+ dual,
+ oleautomation
+ ]
+ interface IOWSNewDocument2 : IOWSNewDocument {
+ [id(0x60030000)]
+ HRESULT ViewDocument(
+ [in] BSTR bstrDocumentLocation,
+ [in, optional] VARIANT varProgID,
+ [out, retval] VARIANT_BOOL* pbResult);
+ [id(0x60030001)]
+ HRESULT ViewDocument2(
+ [in] IDispatch* pdisp,
+ [in] BSTR bstrDocumentLocation,
+ [in, optional] VARIANT varProgID,
+ [out, retval] VARIANT_BOOL* pbResult);
+ [id(0x60030002)]
+ HRESULT EditDocument2(
+ [in] IDispatch* pdisp,
+ [in] BSTR bstrDocumentLocation,
+ [in, optional] VARIANT varProgID,
+ [out, retval] VARIANT_BOOL* pbResult);
+ [id(0x60030003)]
+ HRESULT CreateNewDocument2(
+ [in] IDispatch* pdisp,
+ [in] BSTR bstrTemplateLocation,
+ [in] BSTR bstrDefaultSaveLocation,
+ [out, retval] VARIANT_BOOL* pbResult);
+ [id(0x60030004)]
+ HRESULT PromptedOnLastOpen([out, retval] VARIANT_BOOL* pbResult);
+ };
+
+ [
+ odl,
+ uuid(4D144CA3-2336-4E15-A7D1-A4B151D07CC7),
+ helpstring("IOWSNewDocument3 Interface"),
+ dual,
+ oleautomation
+ ]
+ interface IOWSNewDocument3 : IOWSNewDocument2 {
+ [id(0x60040000)]
+ HRESULT ViewDocument3(
+ [in] IDispatch* pdisp,
+ [in] BSTR bstrDocumentLocation,
+ [in] int OpenType,
+ [in, optional] VARIANT varProgID,
+ [out, retval] VARIANT_BOOL* pbResult);
+ [id(0x60040001)]
+ HRESULT CheckinDocument(
+ [in] BSTR bstrDocumentLocation,
+ [in] int CheckinType,
+ [in] BSTR CheckinComment,
+ [in, defaultvalue(FALSE)] VARIANT_BOOL bKeepCheckout,
+ [out, retval] VARIANT_BOOL* pbResult);
+ [id(0x60040002)]
+ HRESULT DiscardLocalCheckout(
+ [in] BSTR bstrDocumentLocationRaw,
+ [out, retval] VARIANT_BOOL* pbResult);
+ [id(0x60040003)]
+ HRESULT ViewInExcel(
+ [in] BSTR SiteUrl,
+ [in] BSTR FileName,
+ [in] BSTR SessionId,
+ [in] BSTR Cmd,
+ [in] BSTR Sheet,
+ [in] int Row,
+ [in] int Column,
+ [in, optional] VARIANT varProgID);
+ [id(0x60040004)]
+ HRESULT CheckoutDocumentPrompt(
+ [in] BSTR bstrDocumentLocationRaw,
+ [in] VARIANT_BOOL fEditAfterCheckout,
+ [in, optional] VARIANT varProgID,
+ [out, retval] VARIANT_BOOL* pbResult);
+ [id(0x60040005)]
+ HRESULT EditDocument3(
+ [in] IDispatch* pdisp,
+ [in] BSTR bstrDocumentLocation,
+ [in] VARIANT_BOOL fUseLocalCopy,
+ [in, optional] VARIANT varProgID,
+ [out, retval] VARIANT_BOOL* pbResult);
+ [id(0x60040006)]
+ HRESULT NewBlogPost(
+ [in] BSTR bstrProviderId,
+ [in] BSTR bstrBlogUrl,
+ [in] BSTR bstrBlogName);
+ };
+
+ [
+ uuid(4AD14812-2807-48B1-A27F-BA836D874E45),
+ helpstring("COMOpenDocuments Class")
+ ]
+ coclass COMOpenDocuments {
+ [default] interface IOWSNewDocument;
+ interface IOWSNewDocument2;
+ interface IOWSNewDocument3;
+ };
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/shell/source/win32/spsupp/spsuppClassFactory.cxx b/shell/source/win32/spsupp/spsuppClassFactory.cxx
new file mode 100644
index 000000000000..a86b8a16beaa
--- /dev/null
+++ b/shell/source/win32/spsupp/spsuppClassFactory.cxx
@@ -0,0 +1,83 @@
+/* -*- 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 "spsuppClassFactory.hpp"
+#include "COMOpenDocuments.hpp"
+
+long ClassFactory::m_nObjCount = 0;
+long ClassFactory::m_nLockCount = 0;
+
+ClassFactory::ClassFactory()
+{
+ ::InterlockedIncrement(&m_nObjCount);
+};
+
+ClassFactory::~ClassFactory()
+{
+ ::InterlockedDecrement(&m_nObjCount);
+};
+
+// IUnknown methods
+
+const wchar_t* GUID2Str(REFGUID rGUID);
+
+STDMETHODIMP ClassFactory::QueryInterface(
+ REFIID riid,
+ void **ppvObject)
+{
+ *ppvObject = nullptr;
+ if (IsEqualIID(riid, __uuidof(IUnknown)) ||
+ IsEqualIID(riid, __uuidof(IClassFactory)))
+ {
+ *ppvObject = static_cast<IClassFactory*>(this);
+ AddRef();
+ return S_OK;
+ }
+ return E_NOINTERFACE;
+}
+
+// IClassFactory methods
+
+STDMETHODIMP ClassFactory::CreateInstance(
+ IUnknown *pUnkOuter,
+ REFIID riid,
+ void **ppvObject)
+{
+ *ppvObject = nullptr;
+ if (pUnkOuter)
+ {
+ return CLASS_E_NOAGGREGATION;
+ }
+
+ COMOpenDocuments* pObj;
+ try {
+ pObj = new COMOpenDocuments;
+ }
+ catch (const COMOpenDocuments::Error& e) {
+ return e.val();
+ }
+ catch (...) {
+ return E_OUTOFMEMORY;
+ }
+
+ HRESULT hr = pObj->QueryInterface(riid, ppvObject);
+ pObj->Release();
+ return hr;
+}
+
+STDMETHODIMP ClassFactory::LockServer(BOOL fLock)
+{
+ if (fLock)
+ ::InterlockedIncrement(&m_nLockCount);
+ else
+ ::InterlockedDecrement(&m_nLockCount);
+ return S_OK;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/shell/source/win32/spsupp/spsuppServ.cxx b/shell/source/win32/spsupp/spsuppServ.cxx
new file mode 100644
index 000000000000..c71ba10b9d78
--- /dev/null
+++ b/shell/source/win32/spsupp/spsuppServ.cxx
@@ -0,0 +1,140 @@
+/* -*- 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
+#include "spsupp_i.c"
+
+#include <memory>
+#include "olectl.h"
+#include "spsuppServ.hpp"
+#include "spsuppClassFactory.hpp"
+#include "COMOpenDocuments.hpp"
+#include "registrar.hpp"
+
+HANDLE g_hModule;
+
+ITypeLib* GetTypeLib()
+{
+ typedef std::unique_ptr<ITypeLib, void(*)(IUnknown* p)> ITypeLibGuard;
+ static ITypeLibGuard aITypeLibGuard(nullptr, [](IUnknown* p) { if (p) p->Release(); });
+ if (!aITypeLibGuard.get())
+ {
+ wchar_t szFile[MAX_PATH];
+ if (GetModuleFileNameW((HMODULE)g_hModule, szFile, MAX_PATH) == 0)
+ return nullptr;
+ ITypeLib* pTypeLib;
+ HRESULT hr = LoadTypeLib(szFile, &pTypeLib);
+ if (FAILED(hr))
+ return nullptr;
+ aITypeLibGuard.reset(pTypeLib);
+ }
+ return aITypeLibGuard.get();
+}
+
+const wchar_t* GetLOPath()
+{
+ static wchar_t sPath[MAX_PATH] = { 0 };
+ if (*sPath == 0)
+ {
+ // Initialization
+ if (GetModuleFileNameW((HMODULE)g_hModule, sPath, MAX_PATH) == 0)
+ return nullptr;
+ wchar_t* pSlashPos = wcsrchr(sPath, L'\\');
+ if (pSlashPos == nullptr)
+ return nullptr;
+ wcscpy(pSlashPos+1, L"soffice.exe");
+ }
+ return 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((HMODULE)g_hModule, szFile, MAX_PATH) == 0)
+ return HRESULT_FROM_WIN32(GetLastError());
+
+ HRESULT hr = RegisterTypeLib(pTypeLib, szFile, nullptr);
+ if (FAILED(hr))
+ return hr;
+
+ return Registrar::RegisterObject(CLSID_spsupp, LIBID_spsupp, L"LOSPSupport", L"OpenDocuments", szFile);
+}
+
+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::UnRegisterObject(CLSID_spsupp, L"LOSPSupport", L"OpenDocuments");
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */