/* -*- 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 <wchar.h>
#include <objbase.h>
namespace {
HRESULT RegRead(HKEY hRootKey,
const wchar_t * subKey,
const wchar_t * valName,
wchar_t * val
Data, size_t cchData)
{
HKEY hKey;
LSTATUS iRetVal = RegCreateKeyExW(
hRootKey,
subKey,
0 ,
nullptr,
REG_OPTION_NON_VOLATILE,
KEY_READ,
nullptr,
&hKey,
nullptr);
if (iRetVal != ERROR_SUCCESS)
return HRESULT_FROM_WIN32(iRetVal);
DWORD cbData = cchData * sizeof (valData[0 ]);
DWORD dwType;
iRetVal = RegQueryValueExW(hKey, valName, nullptr, &dwType, reinterpret_cast <LPBYTE>(valData), &cbData);
RegCloseKey(hKey);
if ((iRetVal == ERROR_SUCCESS) && (dwType != REG_SZ))
{
return E_FAIL;
}
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;
LSTATUS 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 (valData)
{
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))
*hKeyResult = hKey;
else
RegCloseKey(hKey);
return HRESULT_FROM_WIN32(iRetVal);
}
HRESULT RegDel(HKEY hRootKey, const wchar_t * subKey)
{
LSTATUS iRetVal = RegDeleteKeyW(hRootKey, subKey);
return HRESULT_FROM_WIN32(iRetVal);
}
} // namespace
// 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 Registrar::RegisterObject(REFIID riidTypeLib, const wchar_t * sProgram,
const wchar_t * sComponent, std::initializer_list<int > aVersions,
const wchar_t * Path)
{
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;
{
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
return RegisterProgIDs(sProgram, sComponent, aVersions);
}
HRESULT Registrar::UnRegisterObject(const wchar_t * sProgram, const wchar_t * sComponent,
std::initializer_list<int > aVersions)
{
if (FAILED(m_ConstructionResult))
return m_ConstructionResult;
// ProgID
UnRegisterProgIDs(sProgram, sComponent, aVersions);
// 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);
RegDel(HKEY_CLASSES_ROOT, sBuf);
return S_OK;
}
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::RegisterProgIDs(const wchar_t * sProgram, const wchar_t * sComponent,
std::initializer_list<int > aVersions)
{
HRESULT hr = S_OK;
bool bDefaultRegistered = false ;
for (int nVersion : aVersions)
{
if (SUCCEEDED(hr))
{
hr = RegisterProgID(sProgram, sComponent, nVersion, !bDefaultRegistered);
bDefaultRegistered = true ;
}
}
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;
}
HRESULT Registrar::UnRegisterProgIDs(const wchar_t * sProgram, const wchar_t * sComponent,
std::initializer_list<int > aVersions)
{
HRESULT hr = S_OK;
// Try all ProgIDs regardless of error, but make sure to return failure result if some failed
for (int nVersion : aVersions)
{
HRESULT hrLast = UnRegisterProgID(sProgram, sComponent, nVersion);
if (SUCCEEDED(hr))
hr = hrLast;
}
return hr;
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Messung V0.5 in Prozent C=96 H=92 G=93
¤ Dauer der Verarbeitung: 0.17 Sekunden
(vorverarbeitet am 2026-10-11)
¤
*© Formatika GbR, Deutschland