mirror of
https://github.com/nextcloud/desktop.git
synced 2025-10-26 11:17:43 +00:00
This also ensures a clear separation in the system registry. SelfReg is not recommended by Microsoft and will be handled by the MSI package to allow proper Repair and Uninstall. However, we keep it for backward compatibility with the NSIS installer. For details see: https://stackoverflow.com/questions/364187/how-do-you-register-a-win32-com-dll-file-in-wix-3#364210 https://docs.microsoft.com/en-us/windows/win32/msi/selfreg-table#remarks Another fix by this commit: The "Version" registry value in the NCOverlays self reg should be a key and not a value. Details: https://wixtoolset.org/documentation/manual/v3/xsd/wix/class.html Example: [HKCR\CLSID\{01234567-89AB-CDEF-0123-456789ABCDEF}\Version] @="1.0.0.0" Signed-off-by: Michael Schuster <michael@schuster.ms>
217 lines
6.3 KiB
C++
217 lines
6.3 KiB
C++
/**
|
|
* Copyright (c) 2015 Daniel Molkentin <danimo@owncloud.com>. All rights reserved.
|
|
*
|
|
* This library is free software; you can redistribute it and/or modify it under
|
|
* the terms of the GNU Lesser General Public License as published by the Free
|
|
* Software Foundation; either version 2.1 of the License, or (at your option)
|
|
* any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
|
* details.
|
|
*/
|
|
|
|
#include "NCContextMenuRegHandler.h"
|
|
#include "RegDelnode.h"
|
|
#include <strsafe.h>
|
|
#include <objbase.h>
|
|
|
|
namespace {
|
|
|
|
HRESULT SetHKCRRegistryKeyAndValue(PCWSTR pszSubKey, PCWSTR pszValueName, PCWSTR pszData)
|
|
{
|
|
HRESULT hr;
|
|
HKEY hKey = nullptr;
|
|
|
|
// Creates the specified registry key. If the key already exists, the
|
|
// function opens it.
|
|
hr = HRESULT_FROM_WIN32(RegCreateKeyEx(HKEY_CLASSES_ROOT, pszSubKey, 0,
|
|
nullptr, REG_OPTION_NON_VOLATILE, KEY_WRITE, nullptr, &hKey, nullptr));
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (pszData)
|
|
{
|
|
// Set the specified value of the key.
|
|
DWORD cbData = lstrlen(pszData) * sizeof(*pszData);
|
|
hr = HRESULT_FROM_WIN32(RegSetValueEx(hKey, pszValueName, 0,
|
|
REG_SZ, reinterpret_cast<const BYTE *>(pszData), cbData));
|
|
}
|
|
|
|
RegCloseKey(hKey);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT GetHKCRRegistryKeyAndValue(PCWSTR pszSubKey, PCWSTR pszValueName, PWSTR pszData, DWORD cbData)
|
|
{
|
|
HRESULT hr;
|
|
HKEY hKey = nullptr;
|
|
|
|
// Try to open the specified registry key.
|
|
hr = HRESULT_FROM_WIN32(RegOpenKeyEx(HKEY_CLASSES_ROOT, pszSubKey, 0,
|
|
KEY_READ, &hKey));
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Get the data for the specified value name.
|
|
hr = HRESULT_FROM_WIN32(RegQueryValueEx(hKey, pszValueName, nullptr,
|
|
nullptr, reinterpret_cast<LPBYTE>(pszData), &cbData));
|
|
|
|
RegCloseKey(hKey);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
}
|
|
|
|
HRESULT NCContextMenuRegHandler::RegisterInprocServer(PCWSTR pszModule, const CLSID& clsid, PCWSTR pszFriendlyName, PCWSTR pszThreadModel)
|
|
{
|
|
if (!pszModule || !pszThreadModel)
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
HRESULT hr;
|
|
|
|
wchar_t szCLSID[MAX_PATH];
|
|
StringFromGUID2(clsid, szCLSID, ARRAYSIZE(szCLSID));
|
|
|
|
wchar_t szSubkey[MAX_PATH];
|
|
|
|
// Create the HKCR\CLSID\{<CLSID>} key.
|
|
hr = StringCchPrintf(szSubkey, ARRAYSIZE(szSubkey), LR"(CLSID\%s)", szCLSID);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = SetHKCRRegistryKeyAndValue(szSubkey, nullptr, pszFriendlyName);
|
|
|
|
// Create the HKCR\CLSID\{<CLSID>}\InprocServer32 key.
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = StringCchPrintf(szSubkey, ARRAYSIZE(szSubkey),
|
|
LR"(CLSID\%s\InprocServer32)", szCLSID);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Set the default value of the InprocServer32 key to the
|
|
// path of the COM module.
|
|
hr = SetHKCRRegistryKeyAndValue(szSubkey, nullptr, pszModule);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Set the threading model of the component.
|
|
hr = SetHKCRRegistryKeyAndValue(szSubkey,
|
|
L"ThreadingModel", pszThreadModel);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT NCContextMenuRegHandler::UnregisterInprocServer(const CLSID& clsid)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
wchar_t szCLSID[MAX_PATH];
|
|
StringFromGUID2(clsid, szCLSID, ARRAYSIZE(szCLSID));
|
|
|
|
wchar_t szSubkey[MAX_PATH];
|
|
|
|
// Delete the HKCR\CLSID\{<CLSID>} key.
|
|
hr = StringCchPrintf(szSubkey, ARRAYSIZE(szSubkey), LR"(CLSID\%s)", szCLSID);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(RegDelnode(HKEY_CLASSES_ROOT, szSubkey));
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT NCContextMenuRegHandler::RegisterShellExtContextMenuHandler(
|
|
PCWSTR pszFileType, const CLSID& clsid, PCWSTR pszFriendlyName)
|
|
{
|
|
if (!pszFileType)
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
HRESULT hr;
|
|
|
|
wchar_t szCLSID[MAX_PATH];
|
|
StringFromGUID2(clsid, szCLSID, ARRAYSIZE(szCLSID));
|
|
|
|
wchar_t szSubkey[MAX_PATH];
|
|
|
|
// If pszFileType starts with '.', try to read the default value of the
|
|
// HKCR\<File Type> key which contains the ProgID to which the file type
|
|
// is linked.
|
|
if (*pszFileType == L'.')
|
|
{
|
|
wchar_t szDefaultVal[260];
|
|
hr = GetHKCRRegistryKeyAndValue(pszFileType, nullptr, szDefaultVal,
|
|
sizeof(szDefaultVal));
|
|
|
|
// If the key exists and its default value is not empty, use the
|
|
// ProgID as the file type.
|
|
if (SUCCEEDED(hr) && szDefaultVal[0] != L'\0')
|
|
{
|
|
pszFileType = szDefaultVal;
|
|
}
|
|
}
|
|
|
|
// Create the key HKCR\<File Type>\shellex\ContextMenuHandlers\{friendlyName>}
|
|
hr = StringCchPrintf(szSubkey, ARRAYSIZE(szSubkey),
|
|
LR"(%s\shellex\ContextMenuHandlers\%s)", pszFileType, pszFriendlyName);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Set the default value of the key.
|
|
hr = SetHKCRRegistryKeyAndValue(szSubkey, nullptr, szCLSID);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT NCContextMenuRegHandler::UnregisterShellExtContextMenuHandler(
|
|
PCWSTR pszFileType, PCWSTR pszFriendlyName)
|
|
{
|
|
if (!pszFileType)
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
HRESULT hr;
|
|
|
|
wchar_t szSubkey[MAX_PATH];
|
|
|
|
// If pszFileType starts with '.', try to read the default value of the
|
|
// HKCR\<File Type> key which contains the ProgID to which the file type
|
|
// is linked.
|
|
if (*pszFileType == L'.')
|
|
{
|
|
wchar_t szDefaultVal[260];
|
|
hr = GetHKCRRegistryKeyAndValue(pszFileType, nullptr, szDefaultVal,
|
|
sizeof(szDefaultVal));
|
|
|
|
// If the key exists and its default value is not empty, use the
|
|
// ProgID as the file type.
|
|
if (SUCCEEDED(hr) && szDefaultVal[0] != L'\0')
|
|
{
|
|
pszFileType = szDefaultVal;
|
|
}
|
|
}
|
|
|
|
// Remove the HKCR\<File Type>\shellex\ContextMenuHandlers\{friendlyName} key.
|
|
hr = StringCchPrintf(szSubkey, ARRAYSIZE(szSubkey),
|
|
LR"(%s\shellex\ContextMenuHandlers\%s)", pszFileType, pszFriendlyName);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(RegDelnode(HKEY_CLASSES_ROOT, szSubkey));
|
|
}
|
|
|
|
return hr;
|
|
}
|