2 * self-registerable dll functions for msdaps.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
39 #include "row_server.h"
41 #include "wine/debug.h"
42 #include "wine/unicode.h"
44 WINE_DEFAULT_DEBUG_CHANNEL(oledb
);
46 extern HRESULT WINAPI
msdaps_DllRegisterServer(void) DECLSPEC_HIDDEN
;
47 extern HRESULT WINAPI
msdaps_DllUnregisterServer(void) DECLSPEC_HIDDEN
;
50 /***********************************************************************
51 * interface for self-registering
53 struct regsvr_interface
55 IID
const *iid
; /* NULL for end of list */
56 LPCSTR name
; /* can be NULL to omit */
57 IID
const *base_iid
; /* can be NULL to omit */
58 int num_methods
; /* can be <0 to omit */
59 CLSID
const *ps_clsid
; /* can be NULL to omit */
60 CLSID
const *ps_clsid32
; /* can be NULL to omit */
63 static HRESULT
register_interfaces(struct regsvr_interface
const *list
);
64 static HRESULT
unregister_interfaces(struct regsvr_interface
const *list
);
68 CLSID
const *clsid
; /* NULL for end of list */
69 LPCSTR name
; /* can be NULL to omit */
70 LPCSTR iph32
; /* can be NULL to omit */
71 LPCSTR ips
; /* can be NULL to omit */
72 LPCSTR ips32
; /* can be NULL to omit */
73 LPCSTR ips32_tmodel
; /* can be NULL to omit, if apartment, iph32 must be set */
74 DWORD flags
; /* set defines below */
75 LPCSTR progid
; /* can be NULL to omit */
76 LPCSTR viprogid
; /* can be NULL to omit */
77 LPCSTR progid_extra
; /* can be NULL to omit */
78 LPCSTR dllversion
; /* can be NULL to omit */
81 /* flags for regsvr_coclass.flags */
82 #define PROGID_CLSID 0x00000010 /* add a clsid key to the progid */
84 static HRESULT
register_coclasses(struct regsvr_coclass
const *list
);
85 static HRESULT
unregister_coclasses(struct regsvr_coclass
const *list
);
87 /***********************************************************************
88 * static string constants
90 static WCHAR
const interface_keyname
[10] = {
91 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c', 'e', 0 };
92 static WCHAR
const base_ifa_keyname
[14] = {
93 'B', 'a', 's', 'e', 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c',
95 static WCHAR
const num_methods_keyname
[11] = {
96 'N', 'u', 'm', 'M', 'e', 't', 'h', 'o', 'd', 's', 0 };
97 static WCHAR
const ps_clsid_keyname
[15] = {
98 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
100 static WCHAR
const ps_clsid32_keyname
[17] = {
101 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
102 'i', 'd', '3', '2', 0 };
103 static WCHAR
const clsid_keyname
[6] = {
104 'C', 'L', 'S', 'I', 'D', 0 };
105 static WCHAR
const curver_keyname
[7] = {
106 'C', 'u', 'r', 'V', 'e', 'r', 0 };
107 static WCHAR
const iph32_keyname
[] = {
108 'I', 'n', 'P', 'r', 'o', 'c', 'H', 'a', 'n', 'd', 'l', 'e', 'r',
110 static WCHAR
const ips_keyname
[13] = {
111 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
113 static WCHAR
const ips32_keyname
[15] = {
114 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
116 static WCHAR
const progid_keyname
[7] = {
117 'P', 'r', 'o', 'g', 'I', 'D', 0 };
118 static WCHAR
const viprogid_keyname
[25] = {
119 'V', 'e', 'r', 's', 'i', 'o', 'n', 'I', 'n', 'd', 'e', 'p',
120 'e', 'n', 'd', 'e', 'n', 't', 'P', 'r', 'o', 'g', 'I', 'D',
122 static WCHAR
const dllversion_keyname
[11] = {
123 'D', 'l', 'l', 'V', 'e', 'r', 's', 'i', 'o', 'n', 0 };
124 static char const tmodel_valuename
[] = "ThreadingModel";
126 /***********************************************************************
127 * static helper functions
129 static LONG
register_key_guid(HKEY base
, WCHAR
const *name
, GUID
const *guid
);
130 static LONG
register_key_defvalueW(HKEY base
, WCHAR
const *name
,
132 static LONG
register_key_defvalueA(HKEY base
, WCHAR
const *name
,
134 static LONG
register_progid(WCHAR
const *clsid
,
135 char const *progid
, char const *curver_progid
,
136 char const *name
, char const *extra
);
138 /***********************************************************************
139 * register_interfaces
141 static HRESULT
register_interfaces(struct regsvr_interface
const *list
)
143 LONG res
= ERROR_SUCCESS
;
146 res
= RegCreateKeyExW(HKEY_CLASSES_ROOT
, interface_keyname
, 0, NULL
, 0,
147 KEY_READ
| KEY_WRITE
, NULL
, &interface_key
, NULL
);
148 if (res
!= ERROR_SUCCESS
) goto error_return
;
150 for (; res
== ERROR_SUCCESS
&& list
->iid
; ++list
)
155 StringFromGUID2(list
->iid
, buf
, 39);
156 res
= RegCreateKeyExW(interface_key
, buf
, 0, NULL
, 0,
157 KEY_READ
| KEY_WRITE
, NULL
, &iid_key
, NULL
);
158 if (res
!= ERROR_SUCCESS
) goto error_close_interface_key
;
162 res
= RegSetValueExA(iid_key
, NULL
, 0, REG_SZ
,
163 (CONST BYTE
*)(list
->name
),
164 strlen(list
->name
) + 1);
165 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
170 res
= register_key_guid(iid_key
, base_ifa_keyname
, list
->base_iid
);
171 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
174 if (0 <= list
->num_methods
)
176 static WCHAR
const fmt
[3] = { '%', 'd', 0 };
179 res
= RegCreateKeyExW(iid_key
, num_methods_keyname
, 0, NULL
, 0,
180 KEY_READ
| KEY_WRITE
, NULL
, &key
, NULL
);
181 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
183 sprintfW(buf
, fmt
, list
->num_methods
);
184 res
= RegSetValueExW(key
, NULL
, 0, REG_SZ
,
186 (lstrlenW(buf
) + 1) * sizeof(WCHAR
));
189 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
194 res
= register_key_guid(iid_key
, ps_clsid_keyname
, list
->ps_clsid
);
195 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
198 if (list
->ps_clsid32
)
200 res
= register_key_guid(iid_key
, ps_clsid32_keyname
, list
->ps_clsid32
);
201 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
205 RegCloseKey(iid_key
);
208 error_close_interface_key
:
209 RegCloseKey(interface_key
);
211 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
214 /***********************************************************************
215 * unregister_interfaces
217 static HRESULT
unregister_interfaces(struct regsvr_interface
const *list
)
219 LONG res
= ERROR_SUCCESS
;
222 res
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, interface_keyname
, 0,
223 KEY_READ
| KEY_WRITE
, &interface_key
);
224 if (res
== ERROR_FILE_NOT_FOUND
) return S_OK
;
225 if (res
!= ERROR_SUCCESS
) goto error_return
;
227 for (; res
== ERROR_SUCCESS
&& list
->iid
; ++list
)
231 StringFromGUID2(list
->iid
, buf
, 39);
232 res
= RegDeleteTreeW(interface_key
, buf
);
233 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
236 RegCloseKey(interface_key
);
238 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
241 /***********************************************************************
244 static HRESULT
register_coclasses(struct regsvr_coclass
const *list
)
246 LONG res
= ERROR_SUCCESS
;
249 res
= RegCreateKeyExW(HKEY_CLASSES_ROOT
, clsid_keyname
, 0, NULL
, 0,
250 KEY_READ
| KEY_WRITE
, NULL
, &coclass_key
, NULL
);
251 if (res
!= ERROR_SUCCESS
) goto error_return
;
253 for (; res
== ERROR_SUCCESS
&& list
->clsid
; ++list
)
258 StringFromGUID2(list
->clsid
, buf
, 39);
259 res
= RegCreateKeyExW(coclass_key
, buf
, 0, NULL
, 0,
260 KEY_READ
| KEY_WRITE
, NULL
, &clsid_key
, NULL
);
261 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
265 res
= RegSetValueExA(clsid_key
, NULL
, 0, REG_SZ
,
266 (CONST BYTE
*)(list
->name
),
267 strlen(list
->name
) + 1);
268 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
275 res
= RegCreateKeyExW(clsid_key
, iph32_keyname
, 0, NULL
, 0,
276 KEY_READ
| KEY_WRITE
, NULL
,
278 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
280 res
= RegSetValueExA(iph32_key
, NULL
, 0, REG_SZ
,
281 (CONST BYTE
*)list
->iph32
,
282 lstrlenA(list
->iph32
) + 1);
283 RegCloseKey(iph32_key
);
284 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
289 res
= register_key_defvalueA(clsid_key
, ips_keyname
, list
->ips
);
290 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
297 res
= RegCreateKeyExW(clsid_key
, ips32_keyname
, 0, NULL
, 0,
298 KEY_READ
| KEY_WRITE
, NULL
,
300 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
302 res
= RegSetValueExA(ips32_key
, NULL
, 0, REG_SZ
,
303 (CONST BYTE
*)list
->ips32
,
304 lstrlenA(list
->ips32
) + 1);
305 if (res
== ERROR_SUCCESS
&& list
->ips32_tmodel
)
306 res
= RegSetValueExA(ips32_key
, tmodel_valuename
, 0, REG_SZ
,
307 (CONST BYTE
*)list
->ips32_tmodel
,
308 strlen(list
->ips32_tmodel
) + 1);
309 RegCloseKey(ips32_key
);
310 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
315 res
= register_key_defvalueA(clsid_key
, progid_keyname
,
317 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
319 res
= register_progid(list
->flags
& PROGID_CLSID
? buf
: NULL
,
321 list
->name
, list
->progid_extra
);
322 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
327 res
= register_key_defvalueA(clsid_key
, viprogid_keyname
,
329 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
331 res
= register_progid(list
->flags
& PROGID_CLSID
? buf
: NULL
,
332 list
->viprogid
, list
->progid
,
333 list
->name
, list
->progid_extra
);
334 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
337 if (list
->dllversion
)
341 res
= RegCreateKeyExW(clsid_key
, dllversion_keyname
, 0, NULL
, 0,
342 KEY_READ
| KEY_WRITE
, NULL
,
344 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
346 res
= RegSetValueExA(dllver_key
, NULL
, 0, REG_SZ
,
347 (CONST BYTE
*)list
->dllversion
,
348 lstrlenA(list
->dllversion
) + 1);
349 RegCloseKey(dllver_key
);
350 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
354 error_close_clsid_key
:
355 RegCloseKey(clsid_key
);
358 error_close_coclass_key
:
359 RegCloseKey(coclass_key
);
361 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
364 /***********************************************************************
365 * unregister_coclasses
367 static HRESULT
unregister_coclasses(struct regsvr_coclass
const *list
)
369 LONG res
= ERROR_SUCCESS
;
372 res
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, clsid_keyname
, 0,
373 KEY_READ
| KEY_WRITE
, &coclass_key
);
374 if (res
== ERROR_FILE_NOT_FOUND
) return S_OK
;
375 if (res
!= ERROR_SUCCESS
) goto error_return
;
377 for (; res
== ERROR_SUCCESS
&& list
->clsid
; ++list
)
381 StringFromGUID2(list
->clsid
, buf
, 39);
382 res
= RegDeleteTreeW(coclass_key
, buf
);
383 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
384 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
388 res
= RegDeleteTreeA(HKEY_CLASSES_ROOT
, list
->progid
);
389 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
390 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
395 res
= RegDeleteTreeA(HKEY_CLASSES_ROOT
, list
->viprogid
);
396 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
397 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
401 error_close_coclass_key
:
402 RegCloseKey(coclass_key
);
404 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
407 /***********************************************************************
410 static LONG
register_key_guid(HKEY base
, WCHAR
const *name
, GUID
const *guid
)
414 StringFromGUID2(guid
, buf
, 39);
415 return register_key_defvalueW(base
, name
, buf
);
418 /***********************************************************************
419 * register_key_defvalueW
421 static LONG
register_key_defvalueW(HKEY base
, WCHAR
const *name
, WCHAR
const *value
)
426 res
= RegCreateKeyExW(base
, name
, 0, NULL
, 0,
427 KEY_READ
| KEY_WRITE
, NULL
, &key
, NULL
);
428 if (res
!= ERROR_SUCCESS
) return res
;
429 res
= RegSetValueExW(key
, NULL
, 0, REG_SZ
, (CONST BYTE
*)value
,
430 (lstrlenW(value
) + 1) * sizeof(WCHAR
));
435 /***********************************************************************
436 * register_key_defvalueA
438 static LONG
register_key_defvalueA(HKEY base
, WCHAR
const *name
, char const *value
)
443 res
= RegCreateKeyExW(base
, name
, 0, NULL
, 0,
444 KEY_READ
| KEY_WRITE
, NULL
, &key
, NULL
);
445 if (res
!= ERROR_SUCCESS
) return res
;
446 res
= RegSetValueExA(key
, NULL
, 0, REG_SZ
, (CONST BYTE
*)value
,
447 lstrlenA(value
) + 1);
452 /***********************************************************************
455 static LONG
register_progid(WCHAR
const *clsid
, char const *progid
,
456 char const *curver_progid
, char const *name
,
462 res
= RegCreateKeyExA(HKEY_CLASSES_ROOT
, progid
, 0,
463 NULL
, 0, KEY_READ
| KEY_WRITE
, NULL
,
465 if (res
!= ERROR_SUCCESS
) return res
;
469 res
= RegSetValueExA(progid_key
, NULL
, 0, REG_SZ
,
470 (CONST BYTE
*)name
, strlen(name
) + 1);
471 if (res
!= ERROR_SUCCESS
) goto error_close_progid_key
;
476 res
= register_key_defvalueW(progid_key
, clsid_keyname
, clsid
);
477 if (res
!= ERROR_SUCCESS
) goto error_close_progid_key
;
482 res
= register_key_defvalueA(progid_key
, curver_keyname
, curver_progid
);
483 if (res
!= ERROR_SUCCESS
) goto error_close_progid_key
;
490 res
= RegCreateKeyExA(progid_key
, extra
, 0,
491 NULL
, 0, KEY_READ
| KEY_WRITE
, NULL
,
493 if (res
== ERROR_SUCCESS
)
494 RegCloseKey(extra_key
);
497 error_close_progid_key
:
498 RegCloseKey(progid_key
);
502 /***********************************************************************
505 static struct regsvr_coclass
const coclass_list
[] =
508 &CLSID_wine_row_proxy
,
509 "Wine OLE DB Row Proxy",
515 "WINEDBROWPRX.AsProxy.1",
516 "WINEDBROWPRX.AsProxy",
521 &CLSID_wine_row_server
,
522 "Wine OLE DB Row Server",
528 "WINEDBROWPRX.AsServer.1",
529 "WINEDBROWPRX.AsServer",
534 &CLSID_wine_rowset_proxy
,
535 "Wine OLE DB Rowset Proxy",
541 "WINEDBRSTPRX.AsProxy.1",
542 "WINEDBRSTPRX.AsProxy",
547 &CLSID_wine_rowset_server
,
548 "Wine OLE DB Rowset Server",
554 "WINEDBRSTPRX.AsServer.1",
555 "WINEDBRSTPRX.AsServer",
559 { NULL
} /* list terminator */
562 /***********************************************************************
565 static struct regsvr_interface
const interface_list
[] =
567 { NULL
} /* list terminator */
570 /***********************************************************************
573 HRESULT WINAPI
DllRegisterServer(void)
579 hr
= register_coclasses(coclass_list
);
582 hr
= register_interfaces(interface_list
);
585 hr
= msdaps_DllRegisterServer();
590 /***********************************************************************
591 * DllUnregisterServer
593 HRESULT WINAPI
DllUnregisterServer(void)
599 hr
= unregister_coclasses(coclass_list
);
602 hr
= unregister_interfaces(interface_list
);
605 hr
= msdaps_DllUnregisterServer();