2 * self-registerable dll functions for oledb32.dll
4 * Copyright (C) 2004 Raphael Junqueira
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
41 #include "wine/debug.h"
42 #include "wine/unicode.h"
44 WINE_DEFAULT_DEBUG_CHANNEL(oledb);
47 * Near the bottom of this file are the exported DllRegisterServer and
48 * DllUnregisterServer, which make all this worthwhile.
51 /***********************************************************************
52 * interface for self-registering
54 struct regsvr_interface
56 IID const *iid; /* NULL for end of list */
57 LPCSTR name; /* can be NULL to omit */
58 IID const *base_iid; /* can be NULL to omit */
59 int num_methods; /* can be <0 to omit */
60 CLSID const *ps_clsid; /* can be NULL to omit */
61 CLSID const *ps_clsid32; /* can be NULL to omit */
64 static HRESULT register_interfaces(struct regsvr_interface const *list);
65 static HRESULT unregister_interfaces(struct regsvr_interface const *list);
69 CLSID const *clsid; /* NULL for end of list */
70 LPCSTR name; /* can be NULL to omit */
71 LPCSTR iph32; /* can be NULL to omit */
72 LPCSTR ips; /* can be NULL to omit */
73 LPCSTR ips32; /* can be NULL to omit */
74 LPCSTR ips32_tmodel; /* can be NULL to omit, if apartment, iph32 must be set */
75 DWORD flags; /* set defines below */
76 LPCSTR progid; /* can be NULL to omit */
77 LPCSTR viprogid; /* can be NULL to omit */
78 LPCSTR progid_extra; /* can be NULL to omit */
79 LPCSTR dllversion; /* can be NULL to omit */
82 /* flags for regsvr_coclass.flags */
83 #define PROGID_CLSID 0x00000010 /* add a clsid key to the progid */
85 static HRESULT register_coclasses(struct regsvr_coclass const *list);
86 static HRESULT unregister_coclasses(struct regsvr_coclass const *list);
88 /***********************************************************************
89 * static string constants
91 static WCHAR const interface_keyname[10] = {
92 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c', 'e', 0 };
93 static WCHAR const base_ifa_keyname[14] = {
94 'B', 'a', 's', 'e', 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c',
96 static WCHAR const num_methods_keyname[11] = {
97 'N', 'u', 'm', 'M', 'e', 't', 'h', 'o', 'd', 's', 0 };
98 static WCHAR const ps_clsid_keyname[15] = {
99 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
101 static WCHAR const ps_clsid32_keyname[17] = {
102 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
103 'i', 'd', '3', '2', 0 };
104 static WCHAR const clsid_keyname[6] = {
105 'C', 'L', 'S', 'I', 'D', 0 };
106 static WCHAR const curver_keyname[7] = {
107 'C', 'u', 'r', 'V', 'e', 'r', 0 };
108 static WCHAR const iph32_keyname[] = {
109 'I', 'n', 'P', 'r', 'o', 'c', 'H', 'a', 'n', 'd', 'l', 'e', 'r',
111 static WCHAR const ips_keyname[13] = {
112 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
114 static WCHAR const ips32_keyname[15] = {
115 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
117 static WCHAR const progid_keyname[7] = {
118 'P', 'r', 'o', 'g', 'I', 'D', 0 };
119 static WCHAR const viprogid_keyname[25] = {
120 'V', 'e', 'r', 's', 'i', 'o', 'n', 'I', 'n', 'd', 'e', 'p',
121 'e', 'n', 'd', 'e', 'n', 't', 'P', 'r', 'o', 'g', 'I', 'D',
123 static WCHAR const dllversion_keyname[11] = {
124 'D', 'l', 'l', 'V', 'e', 'r', 's', 'i', 'o', 'n', 0 };
125 static char const tmodel_valuename[] = "ThreadingModel";
127 /***********************************************************************
128 * static helper functions
130 static LONG register_key_guid(HKEY base, WCHAR const *name, GUID const *guid);
131 static LONG register_key_defvalueW(HKEY base, WCHAR const *name,
133 static LONG register_key_defvalueA(HKEY base, WCHAR const *name,
135 static LONG register_progid(WCHAR const *clsid,
136 char const *progid, char const *curver_progid,
137 char const *name, char const *extra);
139 /***********************************************************************
140 * register_interfaces
142 static HRESULT register_interfaces(struct regsvr_interface const *list)
144 LONG res = ERROR_SUCCESS;
147 res = RegCreateKeyExW(HKEY_CLASSES_ROOT, interface_keyname, 0, NULL, 0,
148 KEY_READ | KEY_WRITE, NULL, &interface_key, NULL);
149 if (res != ERROR_SUCCESS) goto error_return;
151 for (; res == ERROR_SUCCESS && list->iid; ++list)
156 StringFromGUID2(list->iid, buf, 39);
157 res = RegCreateKeyExW(interface_key, buf, 0, NULL, 0,
158 KEY_READ | KEY_WRITE, NULL, &iid_key, NULL);
159 if (res != ERROR_SUCCESS) goto error_close_interface_key;
163 res = RegSetValueExA(iid_key, NULL, 0, REG_SZ,
164 (CONST BYTE*)(list->name),
165 strlen(list->name) + 1);
166 if (res != ERROR_SUCCESS) goto error_close_iid_key;
171 res = register_key_guid(iid_key, base_ifa_keyname, list->base_iid);
172 if (res != ERROR_SUCCESS) goto error_close_iid_key;
175 if (0 <= list->num_methods)
177 static WCHAR const fmt[3] = { '%', 'd', 0 };
180 res = RegCreateKeyExW(iid_key, num_methods_keyname, 0, NULL, 0,
181 KEY_READ | KEY_WRITE, NULL, &key, NULL);
182 if (res != ERROR_SUCCESS) goto error_close_iid_key;
184 sprintfW(buf, fmt, list->num_methods);
185 res = RegSetValueExW(key, NULL, 0, REG_SZ,
187 (lstrlenW(buf) + 1) * sizeof(WCHAR));
190 if (res != ERROR_SUCCESS) goto error_close_iid_key;
195 res = register_key_guid(iid_key, ps_clsid_keyname, list->ps_clsid);
196 if (res != ERROR_SUCCESS) goto error_close_iid_key;
199 if (list->ps_clsid32)
201 res = register_key_guid(iid_key, ps_clsid32_keyname, list->ps_clsid32);
202 if (res != ERROR_SUCCESS) goto error_close_iid_key;
206 RegCloseKey(iid_key);
209 error_close_interface_key:
210 RegCloseKey(interface_key);
212 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
215 /***********************************************************************
216 * unregister_interfaces
218 static HRESULT unregister_interfaces(struct regsvr_interface const *list)
220 LONG res = ERROR_SUCCESS;
223 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, interface_keyname, 0,
224 KEY_READ | KEY_WRITE, &interface_key);
225 if (res == ERROR_FILE_NOT_FOUND) return S_OK;
226 if (res != ERROR_SUCCESS) goto error_return;
228 for (; res == ERROR_SUCCESS && list->iid; ++list)
232 StringFromGUID2(list->iid, buf, 39);
233 res = RegDeleteTreeW(interface_key, buf);
234 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
237 RegCloseKey(interface_key);
239 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
242 /***********************************************************************
245 static HRESULT register_coclasses(struct regsvr_coclass const *list)
247 LONG res = ERROR_SUCCESS;
250 res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0,
251 KEY_READ | KEY_WRITE, NULL, &coclass_key, NULL);
252 if (res != ERROR_SUCCESS) goto error_return;
254 for (; res == ERROR_SUCCESS && list->clsid; ++list)
259 StringFromGUID2(list->clsid, buf, 39);
260 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
261 KEY_READ | KEY_WRITE, NULL, &clsid_key, NULL);
262 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
266 res = RegSetValueExA(clsid_key, NULL, 0, REG_SZ,
267 (CONST BYTE*)(list->name),
268 strlen(list->name) + 1);
269 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
276 res = RegCreateKeyExW(clsid_key, iph32_keyname, 0, NULL, 0,
277 KEY_READ | KEY_WRITE, NULL,
279 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
281 res = RegSetValueExA(iph32_key, NULL, 0, REG_SZ,
282 (CONST BYTE*)list->iph32,
283 lstrlenA(list->iph32) + 1);
284 RegCloseKey(iph32_key);
285 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
290 res = register_key_defvalueA(clsid_key, ips_keyname, list->ips);
291 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
298 res = RegCreateKeyExW(clsid_key, ips32_keyname, 0, NULL, 0,
299 KEY_READ | KEY_WRITE, NULL,
301 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
303 res = RegSetValueExA(ips32_key, NULL, 0, REG_SZ,
304 (CONST BYTE*)list->ips32,
305 lstrlenA(list->ips32) + 1);
306 if (res == ERROR_SUCCESS && list->ips32_tmodel)
307 res = RegSetValueExA(ips32_key, tmodel_valuename, 0, REG_SZ,
308 (CONST BYTE*)list->ips32_tmodel,
309 strlen(list->ips32_tmodel) + 1);
310 RegCloseKey(ips32_key);
311 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
316 res = register_key_defvalueA(clsid_key, progid_keyname,
318 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
320 res = register_progid(list->flags & PROGID_CLSID ? buf : NULL,
322 list->name, list->progid_extra);
323 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
328 res = register_key_defvalueA(clsid_key, viprogid_keyname,
330 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
332 res = register_progid(list->flags & PROGID_CLSID ? buf : NULL,
333 list->viprogid, list->progid,
334 list->name, list->progid_extra);
335 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
338 if (list->dllversion)
342 res = RegCreateKeyExW(clsid_key, dllversion_keyname, 0, NULL, 0,
343 KEY_READ | KEY_WRITE, NULL,
345 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
347 res = RegSetValueExA(dllver_key, NULL, 0, REG_SZ,
348 (CONST BYTE*)list->dllversion,
349 lstrlenA(list->dllversion) + 1);
350 RegCloseKey(dllver_key);
351 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
355 error_close_clsid_key:
356 RegCloseKey(clsid_key);
359 error_close_coclass_key:
360 RegCloseKey(coclass_key);
362 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
365 /***********************************************************************
366 * unregister_coclasses
368 static HRESULT unregister_coclasses(struct regsvr_coclass const *list)
370 LONG res = ERROR_SUCCESS;
373 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0,
374 KEY_READ | KEY_WRITE, &coclass_key);
375 if (res == ERROR_FILE_NOT_FOUND) return S_OK;
376 if (res != ERROR_SUCCESS) goto error_return;
378 for (; res == ERROR_SUCCESS && list->clsid; ++list)
382 StringFromGUID2(list->clsid, buf, 39);
383 res = RegDeleteTreeW(coclass_key, buf);
384 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
385 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
389 res = RegDeleteTreeA(HKEY_CLASSES_ROOT, list->progid);
390 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
391 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
396 res = RegDeleteTreeA(HKEY_CLASSES_ROOT, list->viprogid);
397 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
398 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
402 error_close_coclass_key:
403 RegCloseKey(coclass_key);
405 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
408 /***********************************************************************
411 static LONG register_key_guid(HKEY base, WCHAR const *name, GUID const *guid)
415 StringFromGUID2(guid, buf, 39);
416 return register_key_defvalueW(base, name, buf);
419 /***********************************************************************
420 * register_key_defvalueW
422 static LONG register_key_defvalueW(HKEY base, WCHAR const *name, WCHAR const *value)
427 res = RegCreateKeyExW(base, name, 0, NULL, 0,
428 KEY_READ | KEY_WRITE, NULL, &key, NULL);
429 if (res != ERROR_SUCCESS) return res;
430 res = RegSetValueExW(key, NULL, 0, REG_SZ, (CONST BYTE*)value,
431 (lstrlenW(value) + 1) * sizeof(WCHAR));
436 /***********************************************************************
437 * register_key_defvalueA
439 static LONG register_key_defvalueA(HKEY base, WCHAR const *name, char const *value)
444 res = RegCreateKeyExW(base, name, 0, NULL, 0,
445 KEY_READ | KEY_WRITE, NULL, &key, NULL);
446 if (res != ERROR_SUCCESS) return res;
447 res = RegSetValueExA(key, NULL, 0, REG_SZ, (CONST BYTE*)value,
448 lstrlenA(value) + 1);
453 /***********************************************************************
456 static LONG register_progid(WCHAR const *clsid, char const *progid,
457 char const *curver_progid, char const *name,
463 res = RegCreateKeyExA(HKEY_CLASSES_ROOT, progid, 0,
464 NULL, 0, KEY_READ | KEY_WRITE, NULL,
466 if (res != ERROR_SUCCESS) return res;
470 res = RegSetValueExA(progid_key, NULL, 0, REG_SZ,
471 (CONST BYTE*)name, strlen(name) + 1);
472 if (res != ERROR_SUCCESS) goto error_close_progid_key;
477 res = register_key_defvalueW(progid_key, clsid_keyname, clsid);
478 if (res != ERROR_SUCCESS) goto error_close_progid_key;
483 res = register_key_defvalueA(progid_key, curver_keyname, curver_progid);
484 if (res != ERROR_SUCCESS) goto error_close_progid_key;
491 res = RegCreateKeyExA(progid_key, extra, 0,
492 NULL, 0, KEY_READ | KEY_WRITE, NULL,
494 if (res == ERROR_SUCCESS)
495 RegCloseKey(extra_key);
498 error_close_progid_key:
499 RegCloseKey(progid_key);
503 /***********************************************************************
506 static struct regsvr_coclass const coclass_list[] =
509 &CLSID_OLEDB_CONVERSIONLIBRARY,
510 "OLE DB Data Conversion Library",
521 { NULL } /* list terminator */
524 /***********************************************************************
527 static struct regsvr_interface const interface_list[] =
529 { NULL } /* list terminator */
532 /***********************************************************************
535 HRESULT WINAPI DllRegisterServer(void)
541 hr = register_coclasses(coclass_list);
543 hr = register_interfaces(interface_list);
547 /***********************************************************************
548 * DllUnregisterServer
550 HRESULT WINAPI DllUnregisterServer(void)
556 hr = unregister_coclasses(coclass_list);
558 hr = unregister_interfaces(interface_list);