LibreOffice Module shell (master) 1
registrar.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
9
10#include <registrar.hpp>
11#include <wchar.h>
12#include <objbase.h>
13
14namespace {
15
16 HRESULT RegRead(HKEY hRootKey, const wchar_t* subKey, const wchar_t* valName, wchar_t* valData, size_t cchData)
17 {
18 HKEY hKey;
19 LSTATUS iRetVal = RegCreateKeyExW(
20 hRootKey,
21 subKey,
22 0,
23 nullptr,
24 REG_OPTION_NON_VOLATILE,
25 KEY_READ,
26 nullptr,
27 &hKey,
28 nullptr);
29 if (iRetVal != ERROR_SUCCESS)
30 return HRESULT_FROM_WIN32(iRetVal);
31
32 DWORD cbData = cchData * sizeof(valData[0]);
33 DWORD dwType;
34 iRetVal = RegQueryValueExW(hKey, valName, nullptr, &dwType, reinterpret_cast<LPBYTE>(valData), &cbData);
35 RegCloseKey(hKey);
36 if ((iRetVal == ERROR_SUCCESS) && (dwType != REG_SZ))
37 {
38 return E_FAIL;
39 }
40 return HRESULT_FROM_WIN32(iRetVal);
41 }
42
43 HRESULT RegWrite(HKEY hRootKey, const wchar_t* subKey, const wchar_t* valName, const wchar_t* valData, HKEY *hKeyResult = nullptr)
44 {
45 HKEY hKey;
46 LSTATUS iRetVal = RegCreateKeyExW(
47 hRootKey,
48 subKey,
49 0,
50 nullptr,
51 REG_OPTION_NON_VOLATILE,
52 KEY_WRITE,
53 nullptr,
54 &hKey,
55 nullptr);
56 if (iRetVal != ERROR_SUCCESS)
57 return HRESULT_FROM_WIN32(iRetVal);
58
59 if (valData)
60 {
61 DWORD cbData = static_cast<DWORD>(wcslen(valData)*sizeof(valData[0]));
62 iRetVal = RegSetValueExW(hKey, valName, 0, REG_SZ, reinterpret_cast<const BYTE *>(valData), cbData);
63 }
64
65 if (hKeyResult && (iRetVal == ERROR_SUCCESS))
66 *hKeyResult = hKey;
67 else
68 RegCloseKey(hKey);
69
70 return HRESULT_FROM_WIN32(iRetVal);
71 }
72
73 HRESULT RegDel(HKEY hRootKey, const wchar_t* subKey)
74 {
75 LSTATUS iRetVal = RegDeleteKeyW(hRootKey, subKey);
76 return HRESULT_FROM_WIN32(iRetVal);
77 }
78
79} // namespace
80
81// see http://stackoverflow.com/questions/284619
82// see https://msdn.microsoft.com/en-us/library/ms691424
83// see https://msdn.microsoft.com/en-us/library/ms694514
84
85Registrar::Registrar(REFIID riidCLSID)
86{
87 m_ConstructionResult = (StringFromGUID2(riidCLSID, m_sCLSID, nGUIDlen) == 0) ?
88 E_UNEXPECTED: S_OK;
89}
90
91HRESULT Registrar::RegisterObject(REFIID riidTypeLib, const wchar_t* sProgram,
92 const wchar_t* sComponent, std::initializer_list<int> aVersions,
93 const wchar_t* Path)
94{
95 if (!wcslen(sComponent) || !wcslen(sProgram))
96 return E_INVALIDARG;
97
98 if (FAILED(m_ConstructionResult))
100
101 // HKEY_CLASSES_ROOT
102 // \CLSID
103 // \{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}
104 // (default) = "MyLibrary MyControl Class"
105 // \InprocServer32
106 // (default) = "c:\foo\control.dll"
107 // ThreadingModel = "Apartment"
108 // \ProgID
109 // (default) = "MyLibrary.MyControl"
110 // \Programmable
111 // \TypeLib
112 // (default) = "{YYYYYYYY-YYYY-YYYY-YYYY-YYYYYYYYYYYY}"
113
114 wchar_t sBufKey[MAX_PATH];
115 wchar_t sBufVal[MAX_PATH];
116
117 // CLSID
118 swprintf(sBufKey, MAX_PATH, L"CLSID\\%s", m_sCLSID);
119 swprintf(sBufVal, MAX_PATH, L"%s %s Class", sProgram, sComponent);
120 HKEY hKeyCLSID;
121 HRESULT hr = RegWrite(HKEY_CLASSES_ROOT, sBufKey, L"", sBufVal, &hKeyCLSID);
122 if (FAILED(hr))
123 return hr;
124 {
125 class HKeyGuard {
126 public:
127 HKeyGuard(HKEY aKey) : m_hKey(aKey) {}
128 ~HKeyGuard() { RegCloseKey(m_hKey); }
129 private:
130 HKEY m_hKey;
131 };
132
133 HKeyGuard hKeyCLSIDGuard(hKeyCLSID);
134
135 // InprocServer32
136 HKEY hKeyInprocServer32;
137 hr = RegWrite(hKeyCLSID, L"InprocServer32", L"", Path, &hKeyInprocServer32);
138 if (FAILED(hr))
139 return hr;
140 {
141 HKeyGuard hKeyInProcServer32Guard(hKeyInprocServer32);
142 hr = RegWrite(hKeyInprocServer32, L"", L"ThreadingModel", L"Apartment");
143 if (FAILED(hr))
144 return hr;
145 }
146
147 // ProgID
148 swprintf(sBufVal, MAX_PATH, L"%s.%s", sProgram, sComponent);
149 hr = RegWrite(hKeyCLSID, L"ProgID", L"", sBufVal);
150 if (FAILED(hr))
151 return hr;
152
153 // Programmable
154 hr = RegWrite(hKeyCLSID, L"Programmable", nullptr, nullptr);
155 if (FAILED(hr))
156 return hr;
157
158 // TypeLib
159 if (::StringFromGUID2(riidTypeLib, sBufVal, nGUIDlen) == 0)
160 return E_UNEXPECTED;
161 hr = RegWrite(hKeyCLSID, L"TypeLib", L"", sBufVal);
162 if (FAILED(hr))
163 return hr;
164 }
165
166 // ProgID
167 return RegisterProgIDs(sProgram, sComponent, aVersions);
168}
169
170HRESULT Registrar::UnRegisterObject(const wchar_t* sProgram, const wchar_t* sComponent,
171 std::initializer_list<int> aVersions)
172{
173 if (FAILED(m_ConstructionResult))
175 // ProgID
176 UnRegisterProgIDs(sProgram, sComponent, aVersions);
177 // CLSID
178 wchar_t sBuf[MAX_PATH];
179 swprintf(sBuf, MAX_PATH, L"CLSID\\%s\\InProcServer32", m_sCLSID);
180 RegDel(HKEY_CLASSES_ROOT, sBuf);
181 swprintf(sBuf, MAX_PATH, L"CLSID\\%s\\ProgId", m_sCLSID);
182 RegDel(HKEY_CLASSES_ROOT, sBuf);
183 swprintf(sBuf, MAX_PATH, L"CLSID\\%s\\Programmable", m_sCLSID);
184 RegDel(HKEY_CLASSES_ROOT, sBuf);
185 swprintf(sBuf, MAX_PATH, L"CLSID\\%s\\TypeLib", m_sCLSID);
186 RegDel(HKEY_CLASSES_ROOT, sBuf);
187 swprintf(sBuf, MAX_PATH, L"CLSID\\%s", m_sCLSID);
188 RegDel(HKEY_CLASSES_ROOT, sBuf);
189 return S_OK;
190}
191
192HRESULT Registrar::RegisterProgID(const wchar_t* sProgram, const wchar_t* sComponent, int nVersion, bool bSetDefault)
193{
194 // HKEY_CLASSES_ROOT
195 // \MyLibrary.MyControl
196 // (default) = "MyLibrary MyControl Class"
197 // \CurVer
198 // (default) = "MyLibrary.MyControl.1"
199 // \MyLibrary.MyControl.1
200 // (default) = "MyLibrary MyControl Class"
201 // \CLSID
202 // (default) = "{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}"
203 if (FAILED(m_ConstructionResult))
205 wchar_t sBufKey[MAX_PATH];
206 swprintf(sBufKey, MAX_PATH, L"%s.%s.%d", sProgram, sComponent, nVersion);
207 wchar_t sBufVal[MAX_PATH];
208 swprintf(sBufVal, MAX_PATH, L"%s %s Class", sProgram, sComponent);
209 RegWrite(HKEY_CLASSES_ROOT, sBufKey, L"", sBufVal);
210 swprintf(sBufKey, MAX_PATH, L"%s.%s.%d\\CLSID", sProgram, sComponent, nVersion);
211 HRESULT hr = RegWrite(HKEY_CLASSES_ROOT, sBufKey, L"", m_sCLSID);
212 if (SUCCEEDED(hr) && bSetDefault)
213 {
214 swprintf(sBufKey, MAX_PATH, L"%s.%s", sProgram, sComponent);
215 swprintf(sBufVal, MAX_PATH, L"%s %s Class", sProgram, sComponent);
216 hr = RegWrite(HKEY_CLASSES_ROOT, sBufKey, L"", sBufVal);
217 swprintf(sBufKey, MAX_PATH, L"%s.%s\\CurVer", sProgram, sComponent);
218 swprintf(sBufVal, MAX_PATH, L"%s.%s.%d", sProgram, sComponent, nVersion);
219 hr = RegWrite(HKEY_CLASSES_ROOT, sBufKey, L"", sBufVal);
220 }
221 return hr;
222}
223
224HRESULT Registrar::RegisterProgIDs(const wchar_t* sProgram, const wchar_t* sComponent,
225 std::initializer_list<int> aVersions)
226{
227 HRESULT hr = S_OK;
228 bool bDefaultRegistered = false;
229 for (int nVersion : aVersions)
230 {
231 if (SUCCEEDED(hr))
232 {
233 hr = RegisterProgID(sProgram, sComponent, nVersion, !bDefaultRegistered);
234 bDefaultRegistered = true;
235 }
236 }
237 return hr;
238}
239
240HRESULT Registrar::UnRegisterProgID(const wchar_t* sProgram, const wchar_t* sComponent, int nVersion)
241{
242 if (FAILED(m_ConstructionResult))
244 wchar_t sBuf[MAX_PATH];
245 swprintf(sBuf, MAX_PATH, L"%s.%s.%d\\CLSID", sProgram, sComponent, nVersion);
246 wchar_t sCurCLSID[nGUIDlen];
247 HRESULT hr = RegRead(HKEY_CLASSES_ROOT, sBuf, L"", sCurCLSID, nGUIDlen);
248 if (FAILED(hr))
249 return hr;
250 if (wcsncmp(sCurCLSID, m_sCLSID, nGUIDlen) != 0)
251 {
252 // The ProgID points to a different CLSID; most probably it's intercepted
253 // by a different application, so don't remove it
254 return S_FALSE;
255 }
256 RegDel(HKEY_CLASSES_ROOT, sBuf);
257 swprintf(sBuf, MAX_PATH, L"%s.%s.%d", sProgram, sComponent, nVersion);
258 hr = RegDel(HKEY_CLASSES_ROOT, sBuf);
259
260 wchar_t sBufKey[MAX_PATH];
261 swprintf(sBufKey, MAX_PATH, L"%s.%s\\CurVer", sProgram, sComponent);
262 wchar_t sBufVal[MAX_PATH];
263 if (SUCCEEDED(RegRead(HKEY_CLASSES_ROOT, sBufKey, L"", sBufVal, MAX_PATH)) && (wcsncmp(sBufVal, sBuf, MAX_PATH) == 0))
264 {
265 // Only unreg default if this version is current default
266 RegDel(HKEY_CLASSES_ROOT, sBufKey);
267 swprintf(sBuf, MAX_PATH, L"%s.%s", sProgram, sComponent);
268 HRESULT hr1 = RegDel(HKEY_CLASSES_ROOT, sBuf);
269 // Always return a failure result if we failed somewhere
270 if (FAILED(hr1))
271 hr = hr1;
272 }
273 return hr;
274}
275
276HRESULT Registrar::UnRegisterProgIDs(const wchar_t* sProgram, const wchar_t* sComponent,
277 std::initializer_list<int> aVersions)
278{
279 HRESULT hr = S_OK;
280 // Try all ProgIDs regardless of error, but make sure to return failure result if some failed
281 for (int nVersion : aVersions)
282 {
283 HRESULT hrLast = UnRegisterProgID(sProgram, sComponent, nVersion);
284 if (SUCCEEDED(hr))
285 hr = hrLast;
286 }
287 return hr;
288}
289
290/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
HRESULT RegisterProgIDs(const wchar_t *sProgram, const wchar_t *sComponent, std::initializer_list< int > aVersions)
Definition: registrar.cxx:224
static const size_t nGUIDlen
Definition: registrar.hpp:42
HRESULT m_ConstructionResult
Definition: registrar.hpp:44
HRESULT RegisterProgID(const wchar_t *sProgram, const wchar_t *sComponent, int nVersion, bool bSetDefault)
Definition: registrar.cxx:192
HRESULT UnRegisterProgID(const wchar_t *sProgram, const wchar_t *sComponent, int nVersion)
Definition: registrar.cxx:240
HRESULT RegisterObject(REFIID riidTypeLib, const wchar_t *sProgram, const wchar_t *sComponent, std::initializer_list< int > aVersions, const wchar_t *Path)
Definition: registrar.cxx:91
HRESULT UnRegisterObject(const wchar_t *sProgram, const wchar_t *sComponent, std::initializer_list< int > aVersions)
Definition: registrar.cxx:170
Registrar(REFIID riidCLSID)
Definition: registrar.cxx:85
HRESULT UnRegisterProgIDs(const wchar_t *sProgram, const wchar_t *sComponent, std::initializer_list< int > aVersions)
Definition: registrar.cxx:276
wchar_t m_sCLSID[nGUIDlen]
Definition: registrar.hpp:43
sal_Int16 nVersion
#define MAX_PATH
return hr
unsigned char BYTE