2 * self-registerable dll functions for oleaut32.dll
4 * Copyright (C) 2003 John K. Hohm
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
34 #include "wine/debug.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
39 * Near the bottom of this file are the exported DllRegisterServer and
40 * DllUnregisterServer, which make all this worthwhile.
43 /***********************************************************************
44 * interface for self-registering
46 struct regsvr_interface
48 IID
const *iid
; /* NULL for end of list */
49 LPCSTR name
; /* can be NULL to omit */
50 IID
const *base_iid
; /* can be NULL to omit */
51 int num_methods
; /* can be <0 to omit */
52 CLSID
const *ps_clsid
; /* can be NULL to omit */
53 CLSID
const *ps_clsid32
; /* can be NULL to omit */
56 static HRESULT
register_interfaces(struct regsvr_interface
const *list
);
57 static HRESULT
unregister_interfaces(struct regsvr_interface
const *list
);
61 CLSID
const *clsid
; /* NULL for end of list */
62 LPCSTR name
; /* can be NULL to omit */
63 LPCSTR ips
; /* can be NULL to omit */
64 LPCSTR ips32
; /* can be NULL to omit */
65 LPCSTR ips32_tmodel
; /* can be NULL to omit */
66 LPCSTR clsid_str
; /* can be NULL to omit */
67 LPCSTR progid
; /* can be NULL to omit */
70 static HRESULT
register_coclasses(struct regsvr_coclass
const *list
);
71 static HRESULT
unregister_coclasses(struct regsvr_coclass
const *list
);
73 /***********************************************************************
74 * static string constants
76 static WCHAR
const interface_keyname
[10] = {
77 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c', 'e', 0 };
78 static WCHAR
const base_ifa_keyname
[14] = {
79 'B', 'a', 's', 'e', 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c',
81 static WCHAR
const num_methods_keyname
[11] = {
82 'N', 'u', 'm', 'M', 'e', 't', 'h', 'o', 'd', 's', 0 };
83 static WCHAR
const ps_clsid_keyname
[15] = {
84 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
86 static WCHAR
const ps_clsid32_keyname
[17] = {
87 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
88 'i', 'd', '3', '2', 0 };
89 static WCHAR
const clsid_keyname
[6] = {
90 'C', 'L', 'S', 'I', 'D', 0 };
91 static WCHAR
const ips_keyname
[13] = {
92 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
94 static WCHAR
const ips32_keyname
[15] = {
95 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
97 static WCHAR
const progid_keyname
[7] = {
98 'P', 'r', 'o', 'g', 'I', 'D', 0 };
99 static char const tmodel_valuename
[] = "ThreadingModel";
101 /***********************************************************************
102 * static helper functions
104 static LONG
register_key_guid(HKEY base
, WCHAR
const *name
, GUID
const *guid
);
105 static LONG
register_key_defvalueW(HKEY base
, WCHAR
const *name
,
107 static LONG
register_key_defvalueA(HKEY base
, WCHAR
const *name
,
109 static LONG
recursive_delete_key(HKEY key
);
110 static LONG
recursive_delete_keyA(HKEY base
, char const *name
);
111 static LONG
recursive_delete_keyW(HKEY base
, WCHAR
const *name
);
113 /***********************************************************************
114 * register_interfaces
116 static HRESULT
register_interfaces(struct regsvr_interface
const *list
)
118 LONG res
= ERROR_SUCCESS
;
121 res
= RegCreateKeyExW(HKEY_CLASSES_ROOT
, interface_keyname
, 0, NULL
, 0,
122 KEY_READ
| KEY_WRITE
, NULL
, &interface_key
, NULL
);
123 if (res
!= ERROR_SUCCESS
) goto error_return
;
125 for (; res
== ERROR_SUCCESS
&& list
->iid
; ++list
) {
129 StringFromGUID2(list
->iid
, buf
, 39);
130 res
= RegCreateKeyExW(interface_key
, buf
, 0, NULL
, 0,
131 KEY_READ
| KEY_WRITE
, NULL
, &iid_key
, NULL
);
132 if (res
!= ERROR_SUCCESS
) goto error_close_interface_key
;
135 res
= RegSetValueExA(iid_key
, NULL
, 0, REG_SZ
,
136 (CONST BYTE
*)(list
->name
),
137 strlen(list
->name
) + 1);
138 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
141 if (list
->base_iid
) {
142 register_key_guid(iid_key
, base_ifa_keyname
, list
->base_iid
);
143 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
146 if (0 <= list
->num_methods
) {
147 static WCHAR
const fmt
[3] = { '%', 'd', 0 };
150 res
= RegCreateKeyExW(iid_key
, num_methods_keyname
, 0, NULL
, 0,
151 KEY_READ
| KEY_WRITE
, NULL
, &key
, NULL
);
152 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
154 wsprintfW(buf
, fmt
, list
->num_methods
);
155 res
= RegSetValueExW(key
, NULL
, 0, REG_SZ
,
157 (lstrlenW(buf
) + 1) * sizeof(WCHAR
));
160 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
163 if (list
->ps_clsid
) {
164 register_key_guid(iid_key
, ps_clsid_keyname
, list
->ps_clsid
);
165 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
168 if (list
->ps_clsid32
) {
169 register_key_guid(iid_key
, ps_clsid32_keyname
, list
->ps_clsid32
);
170 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
174 RegCloseKey(iid_key
);
177 error_close_interface_key
:
178 RegCloseKey(interface_key
);
180 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
183 /***********************************************************************
184 * unregister_interfaces
186 static HRESULT
unregister_interfaces(struct regsvr_interface
const *list
)
188 LONG res
= ERROR_SUCCESS
;
191 res
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, interface_keyname
, 0,
192 KEY_READ
| KEY_WRITE
, &interface_key
);
193 if (res
== ERROR_FILE_NOT_FOUND
) return S_OK
;
194 if (res
!= ERROR_SUCCESS
) goto error_return
;
196 for (; res
== ERROR_SUCCESS
&& list
->iid
; ++list
) {
199 StringFromGUID2(list
->iid
, buf
, 39);
200 res
= recursive_delete_keyW(interface_key
, buf
);
203 RegCloseKey(interface_key
);
205 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
208 /***********************************************************************
211 static HRESULT
register_coclasses(struct regsvr_coclass
const *list
)
213 LONG res
= ERROR_SUCCESS
;
216 res
= RegCreateKeyExW(HKEY_CLASSES_ROOT
, clsid_keyname
, 0, NULL
, 0,
217 KEY_READ
| KEY_WRITE
, NULL
, &coclass_key
, NULL
);
218 if (res
!= ERROR_SUCCESS
) goto error_return
;
220 for (; res
== ERROR_SUCCESS
&& list
->clsid
; ++list
) {
224 StringFromGUID2(list
->clsid
, buf
, 39);
225 res
= RegCreateKeyExW(coclass_key
, buf
, 0, NULL
, 0,
226 KEY_READ
| KEY_WRITE
, NULL
, &clsid_key
, NULL
);
227 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
230 res
= RegSetValueExA(clsid_key
, NULL
, 0, REG_SZ
,
231 (CONST BYTE
*)(list
->name
),
232 strlen(list
->name
) + 1);
233 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
237 res
= register_key_defvalueA(clsid_key
, ips_keyname
, list
->ips
);
238 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
244 res
= RegCreateKeyExW(clsid_key
, ips32_keyname
, 0, NULL
, 0,
245 KEY_READ
| KEY_WRITE
, NULL
,
247 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
249 res
= RegSetValueExA(ips32_key
, NULL
, 0, REG_SZ
,
250 (CONST BYTE
*)list
->ips32
,
251 lstrlenA(list
->ips32
) + 1);
252 if (res
== ERROR_SUCCESS
&& list
->ips32_tmodel
)
253 res
= RegSetValueExA(ips32_key
, tmodel_valuename
, 0, REG_SZ
,
254 (CONST BYTE
*)list
->ips32_tmodel
,
255 strlen(list
->ips32_tmodel
) + 1);
256 RegCloseKey(ips32_key
);
257 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
260 if (list
->clsid_str
) {
261 res
= register_key_defvalueA(clsid_key
, clsid_keyname
,
263 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
269 res
= register_key_defvalueA(clsid_key
, progid_keyname
,
271 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
273 res
= RegCreateKeyExA(HKEY_CLASSES_ROOT
, list
->progid
, 0,
274 NULL
, 0, KEY_READ
| KEY_WRITE
, NULL
,
276 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
278 res
= register_key_defvalueW(progid_key
, clsid_keyname
, buf
);
279 RegCloseKey(progid_key
);
280 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
283 error_close_clsid_key
:
284 RegCloseKey(clsid_key
);
287 error_close_coclass_key
:
288 RegCloseKey(coclass_key
);
290 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
293 /***********************************************************************
294 * unregister_coclasses
296 static HRESULT
unregister_coclasses(struct regsvr_coclass
const *list
)
298 LONG res
= ERROR_SUCCESS
;
301 res
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, clsid_keyname
, 0,
302 KEY_READ
| KEY_WRITE
, &coclass_key
);
303 if (res
== ERROR_FILE_NOT_FOUND
) return S_OK
;
304 if (res
!= ERROR_SUCCESS
) goto error_return
;
306 for (; res
== ERROR_SUCCESS
&& list
->clsid
; ++list
) {
309 StringFromGUID2(list
->clsid
, buf
, 39);
310 res
= recursive_delete_keyW(coclass_key
, buf
);
311 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
314 res
= recursive_delete_keyA(HKEY_CLASSES_ROOT
, list
->progid
);
315 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
319 error_close_coclass_key
:
320 RegCloseKey(coclass_key
);
322 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
325 /***********************************************************************
328 static LONG
register_key_guid(HKEY base
, WCHAR
const *name
, GUID
const *guid
)
332 StringFromGUID2(guid
, buf
, 39);
333 return register_key_defvalueW(base
, name
, buf
);
336 /***********************************************************************
337 * regsvr_key_defvalueW
339 static LONG
register_key_defvalueW(
347 res
= RegCreateKeyExW(base
, name
, 0, NULL
, 0,
348 KEY_READ
| KEY_WRITE
, NULL
, &key
, NULL
);
349 if (res
!= ERROR_SUCCESS
) return res
;
350 res
= RegSetValueExW(key
, NULL
, 0, REG_SZ
, (CONST BYTE
*)value
,
351 (lstrlenW(value
) + 1) * sizeof(WCHAR
));
356 /***********************************************************************
357 * regsvr_key_defvalueA
359 static LONG
register_key_defvalueA(
367 res
= RegCreateKeyExW(base
, name
, 0, NULL
, 0,
368 KEY_READ
| KEY_WRITE
, NULL
, &key
, NULL
);
369 if (res
!= ERROR_SUCCESS
) return res
;
370 res
= RegSetValueExA(key
, NULL
, 0, REG_SZ
, (CONST BYTE
*)value
,
371 lstrlenA(value
) + 1);
376 /***********************************************************************
377 * recursive_delete_key
379 static LONG
recursive_delete_key(HKEY key
)
382 WCHAR subkey_name
[MAX_PATH
];
387 cName
= sizeof(subkey_name
) / sizeof(WCHAR
);
388 res
= RegEnumKeyExW(key
, 0, subkey_name
, &cName
,
389 NULL
, NULL
, NULL
, NULL
);
390 if (res
!= ERROR_SUCCESS
&& res
!= ERROR_MORE_DATA
) {
391 res
= ERROR_SUCCESS
; /* presumably we're done enumerating */
394 res
= RegOpenKeyExW(key
, subkey_name
, 0,
395 KEY_READ
| KEY_WRITE
, &subkey
);
396 if (res
== ERROR_FILE_NOT_FOUND
) continue;
397 if (res
!= ERROR_SUCCESS
) break;
399 res
= recursive_delete_key(subkey
);
401 if (res
!= ERROR_SUCCESS
) break;
404 if (res
== ERROR_SUCCESS
) res
= RegDeleteKeyW(key
, 0);
408 /***********************************************************************
409 * recursive_delete_keyA
411 static LONG
recursive_delete_keyA(HKEY base
, char const *name
)
416 res
= RegOpenKeyExA(base
, name
, 0, KEY_READ
| KEY_WRITE
, &key
);
417 if (res
== ERROR_FILE_NOT_FOUND
) return ERROR_SUCCESS
;
418 if (res
!= ERROR_SUCCESS
) return res
;
419 res
= recursive_delete_key(key
);
424 /***********************************************************************
425 * recursive_delete_keyW
427 static LONG
recursive_delete_keyW(HKEY base
, WCHAR
const *name
)
432 res
= RegOpenKeyExW(base
, name
, 0, KEY_READ
| KEY_WRITE
, &key
);
433 if (res
== ERROR_FILE_NOT_FOUND
) return ERROR_SUCCESS
;
434 if (res
!= ERROR_SUCCESS
) return res
;
435 res
= recursive_delete_key(key
);
440 /***********************************************************************
443 static GUID
const CLSID_RecordInfo
= {
444 0x0000002F, 0x0000, 0x0000, {0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46} };
446 extern GUID
const CLSID_PSDispatch
;
448 static GUID
const CLSID_PSEnumVariant
= {
449 0x00020421, 0x0000, 0x0000, {0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46} };
451 static GUID
const CLSID_PSTypeInfo
= {
452 0x00020422, 0x0000, 0x0000, {0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46} };
454 static GUID
const CLSID_PSTypeLib
= {
455 0x00020423, 0x0000, 0x0000, {0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46} };
457 extern GUID
const CLSID_PSOAInterface
;
459 static GUID
const CLSID_PSTypeComp
= {
460 0x00020425, 0x0000, 0x0000, {0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46} };
462 static GUID
const CLSID_OldFont
= {
463 0x46763EE0, 0xCAB2, 0x11CE, {0x8C,0x20,0x00,0xAA,0x00,0x51,0xE5,0xD4} };
465 static GUID
const CLSID_PSFactoryBuffer
= {
466 0xB196B286, 0xBAB4, 0x101A, {0xB6,0x9C,0x00,0xAA,0x00,0x34,0x1D,0x07} };
468 static struct regsvr_coclass
const coclass_list
[] = {
497 { &CLSID_PSEnumVariant
,
515 { &CLSID_PSOAInterface
,
535 { &CLSID_PSFactoryBuffer
,
541 { NULL
} /* list terminator */
544 /***********************************************************************
548 static struct regsvr_interface
const interface_list
[] = {
549 { NULL
} /* list terminator */
552 /***********************************************************************
553 * DllRegisterServer (OLEAUT32.320)
555 HRESULT WINAPI
OLEAUT32_DllRegisterServer()
561 hr
= register_coclasses(coclass_list
);
563 hr
= register_interfaces(interface_list
);
567 /***********************************************************************
568 * DllUnregisterServer (OLEAUT32.321)
570 HRESULT WINAPI
OLEAUT32_DllUnregisterServer()
576 hr
= unregister_coclasses(coclass_list
);
578 hr
= unregister_interfaces(interface_list
);