diff options
-rw-r--r-- | shell/inc/spsupp/COMOpenDocuments.hpp | 1 | ||||
-rw-r--r-- | shell/inc/spsupp/COMRefCounted.hpp | 7 | ||||
-rw-r--r-- | shell/inc/spsupp/registrar.hpp | 21 | ||||
-rw-r--r-- | shell/source/win32/spsupp/COMOpenDocuments.cxx | 55 | ||||
-rw-r--r-- | shell/source/win32/spsupp/registrar.cxx | 281 | ||||
-rw-r--r-- | shell/source/win32/spsupp/spsupp.def | 1 | ||||
-rw-r--r-- | shell/source/win32/spsupp/spsuppServ.cxx | 35 |
7 files changed, 243 insertions, 158 deletions
diff --git a/shell/inc/spsupp/COMOpenDocuments.hpp b/shell/inc/spsupp/COMOpenDocuments.hpp index a0f733e16f6d..e6c1f22c59e4 100644 --- a/shell/inc/spsupp/COMOpenDocuments.hpp +++ b/shell/inc/spsupp/COMOpenDocuments.hpp @@ -213,7 +213,6 @@ private: static long m_nObjCount; static ITypeInfo* m_pTypeInfo; - static wchar_t m_szLOPath[MAX_PATH]; COMObjectSafety m_aObjectSafety; }; diff --git a/shell/inc/spsupp/COMRefCounted.hpp b/shell/inc/spsupp/COMRefCounted.hpp index 230f6c8da517..9647db2fb0aa 100644 --- a/shell/inc/spsupp/COMRefCounted.hpp +++ b/shell/inc/spsupp/COMRefCounted.hpp @@ -11,6 +11,7 @@ #define INCLUDED_SHELL_INC_SPSUPP_COMREFCOUNTED_HPP #include "objbase.h" +#include "assert.h" template <class Interface> class COMRefCounted : public Interface @@ -28,9 +29,13 @@ public: ULONG STDMETHODCALLTYPE Release() override { + assert(m_nRef > 0); if (::InterlockedDecrement(&m_nRef) == 0) + { delete this; - return (m_nRef > 0) ? static_cast<ULONG>(m_nRef) : 0; + return 0; + } + return static_cast<ULONG>(m_nRef); } private: diff --git a/shell/inc/spsupp/registrar.hpp b/shell/inc/spsupp/registrar.hpp index ed41c4d04003..21f0c22d9688 100644 --- a/shell/inc/spsupp/registrar.hpp +++ b/shell/inc/spsupp/registrar.hpp @@ -12,14 +12,23 @@ #include "windows.h" -namespace Registrar { - HRESULT RegisterObject(REFIID riidCLSID, - REFIID riidTypeLib, +class Registrar { +public: + explicit Registrar(REFIID riidCLSID); + HRESULT RegisterObject(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); -} + int nVersion, + 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 diff --git a/shell/source/win32/spsupp/COMOpenDocuments.cxx b/shell/source/win32/spsupp/COMOpenDocuments.cxx index f9e5a4bd0340..ece3ba82f2ad 100644 --- a/shell/source/win32/spsupp/COMOpenDocuments.cxx +++ b/shell/source/win32/spsupp/COMOpenDocuments.cxx @@ -29,14 +29,24 @@ bool SecurityWarning(const wchar_t* sProgram, const wchar_t* sDocument) } // 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; std::memset(&si, 0, sizeof si); si.cb = sizeof si; si.dwFlags = STARTF_USESHOWWINDOW; si.wShowWindow = SW_SHOW; 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) { DWORD dwError = GetLastError(); @@ -133,7 +143,6 @@ HRESULT STDMETHODCALLTYPE COMOpenDocuments::COMObjectSafety::SetInterfaceSafetyO long COMOpenDocuments::m_nObjCount = 0; ITypeInfo* COMOpenDocuments::m_pTypeInfo = nullptr; -wchar_t COMOpenDocuments::m_szLOPath[MAX_PATH] = {0}; COMOpenDocuments::COMOpenDocuments() : m_aObjectSafety(this) @@ -299,19 +308,7 @@ STDMETHODIMP COMOpenDocuments::CreateNewDocument2( 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); + HRESULT hr = LOStart(L"-n", bstrTemplateLocation, m_aObjectSafety.GetSafe_forUntrustedCaller() || m_aObjectSafety.GetSafe_forUntrustedData()); *pbResult = VARIANT_BOOL(SUCCEEDED(hr)); return hr; } @@ -349,19 +346,7 @@ STDMETHODIMP COMOpenDocuments::ViewDocument3( 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); + HRESULT hr = LOStart(L"--view", bstrDocumentLocation, m_aObjectSafety.GetSafe_forUntrustedCaller() || m_aObjectSafety.GetSafe_forUntrustedData()); *pbResult = VARIANT_BOOL(SUCCEEDED(hr)); return hr; } @@ -423,19 +408,7 @@ STDMETHODIMP COMOpenDocuments::EditDocument3( 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); + HRESULT hr = LOStart(L"-o", bstrDocumentLocation, m_aObjectSafety.GetSafe_forUntrustedCaller() || m_aObjectSafety.GetSafe_forUntrustedData()); *pbResult = VARIANT_BOOL(SUCCEEDED(hr)); return hr; } diff --git a/shell/source/win32/spsupp/registrar.cxx b/shell/source/win32/spsupp/registrar.cxx index 2d182cb7b85f..5ece3fcdd2d8 100644 --- a/shell/source/win32/spsupp/registrar.cxx +++ b/shell/source/win32/spsupp/registrar.cxx @@ -8,11 +8,18 @@ */ #include "registrar.hpp" -#include "stdio.h" +#include "wchar.h" 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; long iRetVal = RegCreateKeyExW( @@ -28,10 +35,10 @@ namespace { if (iRetVal != ERROR_SUCCESS) return HRESULT_FROM_WIN32(iRetVal); - if (keyValue) + if (valData) { - DWORD cbData = static_cast<DWORD>(wcslen(keyValue)*sizeof(keyValue[0])); - iRetVal = RegSetValueExW(hKey, keyName, 0, REG_SZ, reinterpret_cast<const BYTE *>(keyValue), cbData); + DWORD cbData = static_cast<DWORD>(wcslen(valData)*sizeof(valData[0])); + iRetVal = RegSetValueExW(hKey, valName, 0, REG_SZ, reinterpret_cast<const BYTE *>(valData), cbData); } if (hKeyResult && (iRetVal == ERROR_SUCCESS)) @@ -48,126 +55,186 @@ namespace { 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 - // see https://msdn.microsoft.com/en-us/library/ms691424 - // see https://msdn.microsoft.com/en-us/library/ms694514 +Registrar::Registrar(REFIID riidCLSID) +{ + m_ConstructionResult = (StringFromGUID2(riidCLSID, m_sCLSID, nGUIDlen) == 0) ? + E_UNEXPECTED: S_OK; +} - HRESULT RegisterObject(REFIID riidCLSID, - REFIID riidTypeLib, - const wchar_t* sProgram, - const wchar_t* sComponent, - const wchar_t* Path) +HRESULT Registrar::RegisterObject(REFIID riidTypeLib, + const wchar_t* sProgram, + const wchar_t* sComponent, + int nVersion, + const wchar_t* Path, + bool bSetDefault) +{ + if (!wcslen(sComponent) || !wcslen(sProgram)) + return E_INVALIDARG; + + if (FAILED(m_ConstructionResult)) + return m_ConstructionResult; + + // 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}" + + wchar_t sBufKey[MAX_PATH]; + wchar_t sBufVal[MAX_PATH]; + + // CLSID + swprintf(sBufKey, MAX_PATH, L"CLSID\\%s", m_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; { - 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); + 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; { - 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); + HKeyGuard hKeyInProcServer32Guard(hKeyInprocServer32); + hr = RegWrite(hKeyInprocServer32, L"", L"ThreadingModel", L"Apartment"); if (FAILED(hr)) return hr; } // ProgID - swprintf(sBufKey, MAX_PATH, L"%s.%s\\CLSID", sProgram, sComponent); - return RegWrite(HKEY_CLASSES_ROOT, sBufKey, L"", sCLSID); + 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; } - HRESULT UnRegisterObject(REFIID riidCLSID, const wchar_t* LibId, const wchar_t* ClassId) + // ProgID + return RegisterProgID(sProgram, sComponent, nVersion, bSetDefault); +} + +HRESULT Registrar::UnRegisterObject(const wchar_t* sProgram, const wchar_t* sComponent, int nVersion) +{ + if (FAILED(m_ConstructionResult)) + return m_ConstructionResult; + // ProgID + UnRegisterProgID(sProgram, sComponent, nVersion); + // CLSID + wchar_t sBuf[MAX_PATH]; + swprintf(sBuf, MAX_PATH, L"CLSID\\%s\\InProcServer32", m_sCLSID); + RegDel(HKEY_CLASSES_ROOT, sBuf); + swprintf(sBuf, MAX_PATH, L"CLSID\\%s\\ProgId", m_sCLSID); + RegDel(HKEY_CLASSES_ROOT, sBuf); + swprintf(sBuf, MAX_PATH, L"CLSID\\%s\\Programmable", m_sCLSID); + RegDel(HKEY_CLASSES_ROOT, sBuf); + swprintf(sBuf, MAX_PATH, L"CLSID\\%s\\TypeLib", m_sCLSID); + RegDel(HKEY_CLASSES_ROOT, sBuf); + swprintf(sBuf, MAX_PATH, L"CLSID\\%s", m_sCLSID); + 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) { - 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); + 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: */ diff --git a/shell/source/win32/spsupp/spsupp.def b/shell/source/win32/spsupp/spsupp.def index 2977aa21d125..f6828a3e8d43 100644 --- a/shell/source/win32/spsupp/spsupp.def +++ b/shell/source/win32/spsupp/spsupp.def @@ -5,3 +5,4 @@ EXPORTS DllUnregisterServer PRIVATE DllCanUnloadNow PRIVATE DllGetClassObject PRIVATE + DllInstall PRIVATE diff --git a/shell/source/win32/spsupp/spsuppServ.cxx b/shell/source/win32/spsupp/spsuppServ.cxx index e5d1f432b2eb..bfa5710b46b8 100644 --- a/shell/source/win32/spsupp/spsuppServ.cxx +++ b/shell/source/win32/spsupp/spsuppServ.cxx @@ -20,6 +20,7 @@ #include <memory> #include "olectl.h" +#include "wchar.h" #include "spsuppServ.hpp" #include "spsuppClassFactory.hpp" #include "COMOpenDocuments.hpp" @@ -126,7 +127,7 @@ STDAPI DllRegisterServer(void) if (FAILED(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) @@ -146,7 +147,37 @@ STDAPI DllUnregisterServer(void) if (FAILED(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: */ |