Kaydet (Commit) 88829fd9 authored tarafından Mike Kaganski's avatar Mike Kaganski

tdf#103058: allow optional registration for MS ProgIDs

To allow in-place replacement of OWSSUPP.dll, we need to be able
to handle the same ProgIDs that it handles, namely:
SharePoint.OpenDocuments and its versions. This allows to use
the SharePoint integration capabilities of LO without the need to
reconfigure SharePoint server's DOCICON.xml (the system would
start the component with same name as MS Office uses).

But this cannot be the default mode, since if MS Office is installed
on the same system, we would hijack the registration, that could be
undesirable.

So, this commit adds an option to use
regsvr32 [/u] /i:Substitute_OWSSUPP path\to\spsupp.dll
to also [un]register SharePoint.OpenDocuments in addition to normal
LOSPSupport.OpenDocuments.

Change-Id: Icc284f9aa8f97ecf04594dd55b99bc1e3d20740d
Reviewed-on: https://gerrit.libreoffice.org/36389Tested-by: 's avatarJenkins <ci@libreoffice.org>
Reviewed-by: 's avatarMike Kaganski <mike.kaganski@collabora.com>
üst 5fb961ad
...@@ -213,7 +213,6 @@ private: ...@@ -213,7 +213,6 @@ private:
static long m_nObjCount; static long m_nObjCount;
static ITypeInfo* m_pTypeInfo; static ITypeInfo* m_pTypeInfo;
static wchar_t m_szLOPath[MAX_PATH];
COMObjectSafety m_aObjectSafety; COMObjectSafety m_aObjectSafety;
}; };
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#define INCLUDED_SHELL_INC_SPSUPP_COMREFCOUNTED_HPP #define INCLUDED_SHELL_INC_SPSUPP_COMREFCOUNTED_HPP
#include "objbase.h" #include "objbase.h"
#include "assert.h"
template <class Interface> template <class Interface>
class COMRefCounted : public Interface class COMRefCounted : public Interface
...@@ -28,9 +29,13 @@ public: ...@@ -28,9 +29,13 @@ public:
ULONG STDMETHODCALLTYPE Release() override ULONG STDMETHODCALLTYPE Release() override
{ {
assert(m_nRef > 0);
if (::InterlockedDecrement(&m_nRef) == 0) if (::InterlockedDecrement(&m_nRef) == 0)
{
delete this; delete this;
return (m_nRef > 0) ? static_cast<ULONG>(m_nRef) : 0; return 0;
}
return static_cast<ULONG>(m_nRef);
} }
private: private:
......
...@@ -12,14 +12,23 @@ ...@@ -12,14 +12,23 @@
#include "windows.h" #include "windows.h"
namespace Registrar { class Registrar {
HRESULT RegisterObject(REFIID riidCLSID, public:
REFIID riidTypeLib, explicit Registrar(REFIID riidCLSID);
HRESULT RegisterObject(REFIID riidTypeLib,
const wchar_t* sProgram, const wchar_t* sProgram,
const wchar_t* sComponent, const wchar_t* sComponent,
const wchar_t* Path); int nVersion,
HRESULT UnRegisterObject(REFIID riidCLSID, const wchar_t* LibId, const wchar_t* ClassId); const wchar_t* Path,
} bool bSetDefault);
HRESULT UnRegisterObject(const wchar_t* sProgram, const wchar_t* sComponent, int nVersion);
HRESULT RegisterProgID(const wchar_t* sProgram, const wchar_t* sComponent, int nVersion, bool bSetDefault);
HRESULT UnRegisterProgID(const wchar_t* sProgram, const wchar_t* sComponent, int nVersion);
private:
static const size_t nGUIDlen = 40;
wchar_t m_sCLSID[nGUIDlen];
HRESULT m_ConstructionResult;
};
#endif #endif
......
...@@ -29,14 +29,24 @@ bool SecurityWarning(const wchar_t* sProgram, const wchar_t* sDocument) ...@@ -29,14 +29,24 @@ bool SecurityWarning(const wchar_t* sProgram, const wchar_t* sDocument)
} }
// Returns S_OK if successful // Returns S_OK if successful
HRESULT LOStart(wchar_t* sCommandLine) HRESULT LOStart(const wchar_t* sModeArg, const wchar_t* sFilePath, bool bDoSecurityWarning)
{ {
const wchar_t* sProgram = GetLOPath();
if (bDoSecurityWarning && !SecurityWarning(sProgram, sFilePath))
{
// Return success to avoid downloading in browser
return S_OK;
}
STARTUPINFOW si; STARTUPINFOW si;
std::memset(&si, 0, sizeof si); std::memset(&si, 0, sizeof si);
si.cb = sizeof si; si.cb = sizeof si;
si.dwFlags = STARTF_USESHOWWINDOW; si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_SHOW; si.wShowWindow = SW_SHOW;
PROCESS_INFORMATION pi = {}; PROCESS_INFORMATION pi = {};
const size_t cchCommandLine = 32768;
wchar_t sCommandLine[cchCommandLine];
swprintf(sCommandLine, cchCommandLine, L"\"%s\" %s \"%s\"", sProgram, sModeArg, sFilePath);
if (CreateProcessW(nullptr, sCommandLine, nullptr, nullptr, FALSE, 0, nullptr, nullptr, &si, &pi) == FALSE) if (CreateProcessW(nullptr, sCommandLine, nullptr, nullptr, FALSE, 0, nullptr, nullptr, &si, &pi) == FALSE)
{ {
DWORD dwError = GetLastError(); DWORD dwError = GetLastError();
...@@ -133,7 +143,6 @@ HRESULT STDMETHODCALLTYPE COMOpenDocuments::COMObjectSafety::SetInterfaceSafetyO ...@@ -133,7 +143,6 @@ HRESULT STDMETHODCALLTYPE COMOpenDocuments::COMObjectSafety::SetInterfaceSafetyO
long COMOpenDocuments::m_nObjCount = 0; long COMOpenDocuments::m_nObjCount = 0;
ITypeInfo* COMOpenDocuments::m_pTypeInfo = nullptr; ITypeInfo* COMOpenDocuments::m_pTypeInfo = nullptr;
wchar_t COMOpenDocuments::m_szLOPath[MAX_PATH] = {0};
COMOpenDocuments::COMOpenDocuments() COMOpenDocuments::COMOpenDocuments()
: m_aObjectSafety(this) : m_aObjectSafety(this)
...@@ -299,19 +308,7 @@ STDMETHODIMP COMOpenDocuments::CreateNewDocument2( ...@@ -299,19 +308,7 @@ STDMETHODIMP COMOpenDocuments::CreateNewDocument2(
VARIANT_BOOL* pbResult) // true if the document creation succeeds; otherwise false VARIANT_BOOL* pbResult) // true if the document creation succeeds; otherwise false
{ {
// TODO: resolve the program from varProgID (nullptr -> default?) // TODO: resolve the program from varProgID (nullptr -> default?)
const wchar_t* sProgram = GetLOPath(); HRESULT hr = LOStart(L"-n", bstrTemplateLocation, m_aObjectSafety.GetSafe_forUntrustedCaller() || m_aObjectSafety.GetSafe_forUntrustedData());
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 = VARIANT_BOOL(SUCCEEDED(hr)); *pbResult = VARIANT_BOOL(SUCCEEDED(hr));
return hr; return hr;
} }
...@@ -349,19 +346,7 @@ STDMETHODIMP COMOpenDocuments::ViewDocument3( ...@@ -349,19 +346,7 @@ STDMETHODIMP COMOpenDocuments::ViewDocument3(
VARIANT_BOOL *pbResult) // true if the document was successfully opened; otherwise false VARIANT_BOOL *pbResult) // true if the document was successfully opened; otherwise false
{ {
// TODO: resolve the program from varProgID (nullptr -> default?) // TODO: resolve the program from varProgID (nullptr -> default?)
const wchar_t* sProgram = GetLOPath(); HRESULT hr = LOStart(L"--view", bstrDocumentLocation, m_aObjectSafety.GetSafe_forUntrustedCaller() || m_aObjectSafety.GetSafe_forUntrustedData());
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 = VARIANT_BOOL(SUCCEEDED(hr)); *pbResult = VARIANT_BOOL(SUCCEEDED(hr));
return hr; return hr;
} }
...@@ -423,19 +408,7 @@ STDMETHODIMP COMOpenDocuments::EditDocument3( ...@@ -423,19 +408,7 @@ STDMETHODIMP COMOpenDocuments::EditDocument3(
VARIANT_BOOL *pbResult) // true if the document was successfully opened; otherwise false VARIANT_BOOL *pbResult) // true if the document was successfully opened; otherwise false
{ {
// TODO: resolve the program from varProgID (nullptr -> default?) // TODO: resolve the program from varProgID (nullptr -> default?)
const wchar_t* sProgram = GetLOPath(); HRESULT hr = LOStart(L"-o", bstrDocumentLocation, m_aObjectSafety.GetSafe_forUntrustedCaller() || m_aObjectSafety.GetSafe_forUntrustedData());
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 = VARIANT_BOOL(SUCCEEDED(hr)); *pbResult = VARIANT_BOOL(SUCCEEDED(hr));
return hr; return hr;
} }
......
...@@ -8,11 +8,18 @@ ...@@ -8,11 +8,18 @@
*/ */
#include "registrar.hpp" #include "registrar.hpp"
#include "stdio.h" #include "wchar.h"
namespace { namespace {
HRESULT RegWrite(HKEY hRootKey, const wchar_t* subKey, const wchar_t* keyName, const wchar_t* keyValue, HKEY *hKeyResult = nullptr) HRESULT RegRead(HKEY hRootKey, const wchar_t* subKey, const wchar_t* valName, wchar_t* valData, size_t cchData)
{
DWORD cbData = cchData * sizeof(valData[0]);
long iRetVal = RegGetValue(hRootKey, subKey, valName, RRF_RT_REG_SZ, nullptr, valData, &cbData);
return HRESULT_FROM_WIN32(iRetVal);
}
HRESULT RegWrite(HKEY hRootKey, const wchar_t* subKey, const wchar_t* valName, const wchar_t* valData, HKEY *hKeyResult = nullptr)
{ {
HKEY hKey; HKEY hKey;
long iRetVal = RegCreateKeyExW( long iRetVal = RegCreateKeyExW(
...@@ -28,10 +35,10 @@ namespace { ...@@ -28,10 +35,10 @@ namespace {
if (iRetVal != ERROR_SUCCESS) if (iRetVal != ERROR_SUCCESS)
return HRESULT_FROM_WIN32(iRetVal); return HRESULT_FROM_WIN32(iRetVal);
if (keyValue) if (valData)
{ {
DWORD cbData = static_cast<DWORD>(wcslen(keyValue)*sizeof(keyValue[0])); DWORD cbData = static_cast<DWORD>(wcslen(valData)*sizeof(valData[0]));
iRetVal = RegSetValueExW(hKey, keyName, 0, REG_SZ, reinterpret_cast<const BYTE *>(keyValue), cbData); iRetVal = RegSetValueExW(hKey, valName, 0, REG_SZ, reinterpret_cast<const BYTE *>(valData), cbData);
} }
if (hKeyResult && (iRetVal == ERROR_SUCCESS)) if (hKeyResult && (iRetVal == ERROR_SUCCESS))
...@@ -48,28 +55,30 @@ namespace { ...@@ -48,28 +55,30 @@ namespace {
return HRESULT_FROM_WIN32(iRetVal); 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
// see http://stackoverflow.com/questions/284619 Registrar::Registrar(REFIID riidCLSID)
// see https://msdn.microsoft.com/en-us/library/ms691424 {
// see https://msdn.microsoft.com/en-us/library/ms694514 m_ConstructionResult = (StringFromGUID2(riidCLSID, m_sCLSID, nGUIDlen) == 0) ?
E_UNEXPECTED: S_OK;
}
HRESULT RegisterObject(REFIID riidCLSID, HRESULT Registrar::RegisterObject(REFIID riidTypeLib,
REFIID riidTypeLib,
const wchar_t* sProgram, const wchar_t* sProgram,
const wchar_t* sComponent, const wchar_t* sComponent,
const wchar_t* Path) int nVersion,
{ const wchar_t* Path,
bool bSetDefault)
{
if (!wcslen(sComponent) || !wcslen(sProgram)) if (!wcslen(sComponent) || !wcslen(sProgram))
return E_INVALIDARG; return E_INVALIDARG;
wchar_t sCLSID[nGUIDlen]; if (FAILED(m_ConstructionResult))
if (::StringFromGUID2(riidCLSID, sCLSID, nGUIDlen) == 0) return m_ConstructionResult;
return E_UNEXPECTED;
// HKEY_CLASSES_ROOT // HKEY_CLASSES_ROOT
// \CLSID // \CLSID
...@@ -83,15 +92,12 @@ namespace Registrar { ...@@ -83,15 +92,12 @@ namespace Registrar {
// \Programmable // \Programmable
// \TypeLib // \TypeLib
// (default) = "{YYYYYYYY-YYYY-YYYY-YYYY-YYYYYYYYYYYY}" // (default) = "{YYYYYYYY-YYYY-YYYY-YYYY-YYYYYYYYYYYY}"
// \MyLibrary.MyControl
// \CLSID
// (default) = "{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}"
wchar_t sBufKey[MAX_PATH]; wchar_t sBufKey[MAX_PATH];
wchar_t sBufVal[MAX_PATH]; wchar_t sBufVal[MAX_PATH];
// CLSID // CLSID
swprintf(sBufKey, MAX_PATH, L"CLSID\\%s", sCLSID); swprintf(sBufKey, MAX_PATH, L"CLSID\\%s", m_sCLSID);
swprintf(sBufVal, MAX_PATH, L"%s %s Class", sProgram, sComponent); swprintf(sBufVal, MAX_PATH, L"%s %s Class", sProgram, sComponent);
HKEY hKeyCLSID; HKEY hKeyCLSID;
HRESULT hr = RegWrite(HKEY_CLASSES_ROOT, sBufKey, L"", sBufVal, &hKeyCLSID); HRESULT hr = RegWrite(HKEY_CLASSES_ROOT, sBufKey, L"", sBufVal, &hKeyCLSID);
...@@ -140,34 +146,95 @@ namespace Registrar { ...@@ -140,34 +146,95 @@ namespace Registrar {
} }
// ProgID // ProgID
swprintf(sBufKey, MAX_PATH, L"%s.%s\\CLSID", sProgram, sComponent); return RegisterProgID(sProgram, sComponent, nVersion, bSetDefault);
return RegWrite(HKEY_CLASSES_ROOT, sBufKey, L"", sCLSID); }
}
HRESULT UnRegisterObject(REFIID riidCLSID, const wchar_t* LibId, const wchar_t* ClassId) HRESULT Registrar::UnRegisterObject(const wchar_t* sProgram, const wchar_t* sComponent, int nVersion)
{ {
wchar_t sCLSID[nGUIDlen]; if (FAILED(m_ConstructionResult))
wchar_t sBuf[MAX_PATH]; return m_ConstructionResult;
if (::StringFromGUID2(riidCLSID, sCLSID, nGUIDlen) == 0)
return E_UNEXPECTED;
// ProgID // ProgID
swprintf(sBuf, MAX_PATH, L"%s.%s\\CLSID", LibId, ClassId); UnRegisterProgID(sProgram, sComponent, nVersion);
RegDel(HKEY_CLASSES_ROOT, sBuf);
swprintf(sBuf, MAX_PATH, L"%s.%s", LibId, ClassId);
RegDel(HKEY_CLASSES_ROOT, sBuf);
// CLSID // CLSID
swprintf(sBuf, MAX_PATH, L"CLSID\\%s\\InProcServer32", sCLSID); wchar_t sBuf[MAX_PATH];
swprintf(sBuf, MAX_PATH, L"CLSID\\%s\\InProcServer32", m_sCLSID);
RegDel(HKEY_CLASSES_ROOT, sBuf); RegDel(HKEY_CLASSES_ROOT, sBuf);
swprintf(sBuf, MAX_PATH, L"CLSID\\%s\\ProgId", sCLSID); swprintf(sBuf, MAX_PATH, L"CLSID\\%s\\ProgId", m_sCLSID);
RegDel(HKEY_CLASSES_ROOT, sBuf); RegDel(HKEY_CLASSES_ROOT, sBuf);
swprintf(sBuf, MAX_PATH, L"CLSID\\%s\\Programmable", sCLSID); swprintf(sBuf, MAX_PATH, L"CLSID\\%s\\Programmable", m_sCLSID);
RegDel(HKEY_CLASSES_ROOT, sBuf); RegDel(HKEY_CLASSES_ROOT, sBuf);
swprintf(sBuf, MAX_PATH, L"CLSID\\%s\\TypeLib", sCLSID); swprintf(sBuf, MAX_PATH, L"CLSID\\%s\\TypeLib", m_sCLSID);
RegDel(HKEY_CLASSES_ROOT, sBuf); RegDel(HKEY_CLASSES_ROOT, sBuf);
swprintf(sBuf, MAX_PATH, L"CLSID\\%s", sCLSID); swprintf(sBuf, MAX_PATH, L"CLSID\\%s", m_sCLSID);
return RegDel(HKEY_CLASSES_ROOT, sBuf); return RegDel(HKEY_CLASSES_ROOT, sBuf);
}
HRESULT Registrar::RegisterProgID(const wchar_t* sProgram, const wchar_t* sComponent, int nVersion, bool bSetDefault)
{
// HKEY_CLASSES_ROOT
// \MyLibrary.MyControl
// (default) = "MyLibrary MyControl Class"
// \CurVer
// (default) = "MyLibrary.MyControl.1"
// \MyLibrary.MyControl.1
// (default) = "MyLibrary MyControl Class"
// \CLSID
// (default) = "{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}"
if (FAILED(m_ConstructionResult))
return m_ConstructionResult;
wchar_t sBufKey[MAX_PATH];
swprintf(sBufKey, MAX_PATH, L"%s.%s.%d", sProgram, sComponent, nVersion);
wchar_t sBufVal[MAX_PATH];
swprintf(sBufVal, MAX_PATH, L"%s %s Class", sProgram, sComponent);
RegWrite(HKEY_CLASSES_ROOT, sBufKey, L"", sBufVal);
swprintf(sBufKey, MAX_PATH, L"%s.%s.%d\\CLSID", sProgram, sComponent, nVersion);
HRESULT hr = RegWrite(HKEY_CLASSES_ROOT, sBufKey, L"", m_sCLSID);
if (SUCCEEDED(hr) && bSetDefault)
{
swprintf(sBufKey, MAX_PATH, L"%s.%s", sProgram, sComponent);
swprintf(sBufVal, MAX_PATH, L"%s %s Class", sProgram, sComponent);
hr = RegWrite(HKEY_CLASSES_ROOT, sBufKey, L"", sBufVal);
swprintf(sBufKey, MAX_PATH, L"%s.%s\\CurVer", sProgram, sComponent);
swprintf(sBufVal, MAX_PATH, L"%s.%s.%d", sProgram, sComponent, nVersion);
hr = RegWrite(HKEY_CLASSES_ROOT, sBufKey, L"", sBufVal);
} }
return hr;
}
HRESULT Registrar::UnRegisterProgID(const wchar_t* sProgram, const wchar_t* sComponent, int nVersion)
{
if (FAILED(m_ConstructionResult))
return m_ConstructionResult;
wchar_t sBuf[MAX_PATH];
swprintf(sBuf, MAX_PATH, L"%s.%s.%d\\CLSID", sProgram, sComponent, nVersion);
wchar_t sCurCLSID[nGUIDlen];
HRESULT hr = RegRead(HKEY_CLASSES_ROOT, sBuf, L"", sCurCLSID, nGUIDlen);
if (FAILED(hr))
return hr;
if (wcsncmp(sCurCLSID, m_sCLSID, nGUIDlen) != 0)
{
// The ProgID points to a different CLSID; most probably it's intercepted
// by a different application, so don't remove it
return S_FALSE;
}
RegDel(HKEY_CLASSES_ROOT, sBuf);
swprintf(sBuf, MAX_PATH, L"%s.%s.%d", sProgram, sComponent, nVersion);
hr = RegDel(HKEY_CLASSES_ROOT, sBuf);
wchar_t sBufKey[MAX_PATH];
swprintf(sBufKey, MAX_PATH, L"%s.%s\\CurVer", sProgram, sComponent);
wchar_t sBufVal[MAX_PATH];
if (SUCCEEDED(RegRead(HKEY_CLASSES_ROOT, sBufKey, L"", sBufVal, MAX_PATH)) && (wcsncmp(sBufVal, sBuf, MAX_PATH) == 0))
{
// Only unreg default if this version is current default
RegDel(HKEY_CLASSES_ROOT, sBufKey);
swprintf(sBuf, MAX_PATH, L"%s.%s", sProgram, sComponent);
HRESULT hr1 = RegDel(HKEY_CLASSES_ROOT, sBuf);
// Always return a failure result if we failed somewhere
if (FAILED(hr1))
hr = hr1;
}
return hr;
} }
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
...@@ -5,3 +5,4 @@ EXPORTS ...@@ -5,3 +5,4 @@ EXPORTS
DllUnregisterServer PRIVATE DllUnregisterServer PRIVATE
DllCanUnloadNow PRIVATE DllCanUnloadNow PRIVATE
DllGetClassObject PRIVATE DllGetClassObject PRIVATE
DllInstall PRIVATE
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include <memory> #include <memory>
#include "olectl.h" #include "olectl.h"
#include "wchar.h"
#include "spsuppServ.hpp" #include "spsuppServ.hpp"
#include "spsuppClassFactory.hpp" #include "spsuppClassFactory.hpp"
#include "COMOpenDocuments.hpp" #include "COMOpenDocuments.hpp"
...@@ -126,7 +127,7 @@ STDAPI DllRegisterServer(void) ...@@ -126,7 +127,7 @@ STDAPI DllRegisterServer(void)
if (FAILED(hr)) if (FAILED(hr))
return hr; return hr;
return Registrar::RegisterObject(CLSID_spsupp, LIBID_spsupp, L"LOSPSupport", L"OpenDocuments", szFile); return Registrar(CLSID_spsupp).RegisterObject(LIBID_spsupp, L"LOSPSupport", L"OpenDocuments", 1, szFile, true);
} }
STDAPI DllUnregisterServer(void) STDAPI DllUnregisterServer(void)
...@@ -146,7 +147,37 @@ STDAPI DllUnregisterServer(void) ...@@ -146,7 +147,37 @@ STDAPI DllUnregisterServer(void)
if (FAILED(hr)) if (FAILED(hr))
return hr; return hr;
return Registrar::UnRegisterObject(CLSID_spsupp, L"LOSPSupport", L"OpenDocuments"); 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: */ /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment