1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
10 #include <registrar.hpp>
16 HRESULT
RegRead(HKEY hRootKey
, const wchar_t* subKey
, const wchar_t* valName
, wchar_t* valData
, size_t cchData
)
19 LSTATUS iRetVal
= RegCreateKeyExW(
24 REG_OPTION_NON_VOLATILE
,
29 if (iRetVal
!= ERROR_SUCCESS
)
30 return HRESULT_FROM_WIN32(iRetVal
);
32 DWORD cbData
= cchData
* sizeof(valData
[0]);
34 iRetVal
= RegQueryValueExW(hKey
, valName
, nullptr, &dwType
, reinterpret_cast<LPBYTE
>(valData
), &cbData
);
36 if ((iRetVal
== ERROR_SUCCESS
) && (dwType
!= REG_SZ
))
40 return HRESULT_FROM_WIN32(iRetVal
);
43 HRESULT
RegWrite(HKEY hRootKey
, const wchar_t* subKey
, const wchar_t* valName
, const wchar_t* valData
, HKEY
*hKeyResult
= nullptr)
46 LSTATUS iRetVal
= RegCreateKeyExW(
51 REG_OPTION_NON_VOLATILE
,
56 if (iRetVal
!= ERROR_SUCCESS
)
57 return HRESULT_FROM_WIN32(iRetVal
);
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
);
65 if (hKeyResult
&& (iRetVal
== ERROR_SUCCESS
))
70 return HRESULT_FROM_WIN32(iRetVal
);
73 HRESULT
RegDel(HKEY hRootKey
, const wchar_t* subKey
)
75 LSTATUS iRetVal
= RegDeleteKeyW(hRootKey
, subKey
);
76 return HRESULT_FROM_WIN32(iRetVal
);
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
85 Registrar::Registrar(REFIID riidCLSID
)
87 m_ConstructionResult
= (StringFromGUID2(riidCLSID
, m_sCLSID
, nGUIDlen
) == 0) ?
91 HRESULT
Registrar::RegisterObject(REFIID riidTypeLib
, const wchar_t* sProgram
,
92 const wchar_t* sComponent
, std::initializer_list
<int> aVersions
,
95 if (!wcslen(sComponent
) || !wcslen(sProgram
))
98 if (FAILED(m_ConstructionResult
))
99 return m_ConstructionResult
;
103 // \{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}
104 // (default) = "MyLibrary MyControl Class"
106 // (default) = "c:\foo\control.dll"
107 // ThreadingModel = "Apartment"
109 // (default) = "MyLibrary.MyControl"
112 // (default) = "{YYYYYYYY-YYYY-YYYY-YYYY-YYYYYYYYYYYY}"
114 wchar_t sBufKey
[MAX_PATH
];
115 wchar_t sBufVal
[MAX_PATH
];
118 swprintf(sBufKey
, MAX_PATH
, L
"CLSID\\%s", m_sCLSID
);
119 swprintf(sBufVal
, MAX_PATH
, L
"%s %s Class", sProgram
, sComponent
);
121 HRESULT hr
= RegWrite(HKEY_CLASSES_ROOT
, sBufKey
, L
"", sBufVal
, &hKeyCLSID
);
127 HKeyGuard(HKEY aKey
) : m_hKey(aKey
) {}
128 ~HKeyGuard() { RegCloseKey(m_hKey
); }
133 HKeyGuard
hKeyCLSIDGuard(hKeyCLSID
);
136 HKEY hKeyInprocServer32
;
137 hr
= RegWrite(hKeyCLSID
, L
"InprocServer32", L
"", Path
, &hKeyInprocServer32
);
141 HKeyGuard
hKeyInProcServer32Guard(hKeyInprocServer32
);
142 hr
= RegWrite(hKeyInprocServer32
, L
"", L
"ThreadingModel", L
"Apartment");
148 swprintf(sBufVal
, MAX_PATH
, L
"%s.%s", sProgram
, sComponent
);
149 hr
= RegWrite(hKeyCLSID
, L
"ProgID", L
"", sBufVal
);
154 hr
= RegWrite(hKeyCLSID
, L
"Programmable", nullptr, nullptr);
159 if (::StringFromGUID2(riidTypeLib
, sBufVal
, nGUIDlen
) == 0)
161 hr
= RegWrite(hKeyCLSID
, L
"TypeLib", L
"", sBufVal
);
167 return RegisterProgIDs(sProgram
, sComponent
, aVersions
);
170 HRESULT
Registrar::UnRegisterObject(const wchar_t* sProgram
, const wchar_t* sComponent
,
171 std::initializer_list
<int> aVersions
)
173 if (FAILED(m_ConstructionResult
))
174 return m_ConstructionResult
;
176 UnRegisterProgIDs(sProgram
, sComponent
, aVersions
);
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
);
192 HRESULT
Registrar::RegisterProgID(const wchar_t* sProgram
, const wchar_t* sComponent
, int nVersion
, bool bSetDefault
)
195 // \MyLibrary.MyControl
196 // (default) = "MyLibrary MyControl Class"
198 // (default) = "MyLibrary.MyControl.1"
199 // \MyLibrary.MyControl.1
200 // (default) = "MyLibrary MyControl Class"
202 // (default) = "{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}"
203 if (FAILED(m_ConstructionResult
))
204 return 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
)
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
);
224 HRESULT
Registrar::RegisterProgIDs(const wchar_t* sProgram
, const wchar_t* sComponent
,
225 std::initializer_list
<int> aVersions
)
228 bool bDefaultRegistered
= false;
229 for (int nVersion
: aVersions
)
233 hr
= RegisterProgID(sProgram
, sComponent
, nVersion
, !bDefaultRegistered
);
234 bDefaultRegistered
= true;
240 HRESULT
Registrar::UnRegisterProgID(const wchar_t* sProgram
, const wchar_t* sComponent
, int nVersion
)
242 if (FAILED(m_ConstructionResult
))
243 return 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
);
250 if (wcsncmp(sCurCLSID
, m_sCLSID
, nGUIDlen
) != 0)
252 // The ProgID points to a different CLSID; most probably it's intercepted
253 // by a different application, so don't remove it
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
);
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))
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
276 HRESULT
Registrar::UnRegisterProgIDs(const wchar_t* sProgram
, const wchar_t* sComponent
,
277 std::initializer_list
<int> aVersions
)
280 // Try all ProgIDs regardless of error, but make sure to return failure result if some failed
281 for (int nVersion
: aVersions
)
283 HRESULT hrLast
= UnRegisterProgID(sProgram
, sComponent
, nVersion
);
290 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */