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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
38 #include "wine/debug.h"
39 #include "wine/unicode.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
44 * Near the bottom of this file are the exported DllRegisterServer and
45 * DllUnregisterServer, which make all this worthwhile.
48 /***********************************************************************
49 * interface for self-registering
51 struct regsvr_interface
53 IID
const *iid
; /* NULL for end of list */
54 LPCSTR name
; /* can be NULL to omit */
55 IID
const *base_iid
; /* can be NULL to omit */
56 int num_methods
; /* can be <0 to omit */
57 CLSID
const *ps_clsid
; /* can be NULL to omit */
58 CLSID
const *ps_clsid32
; /* can be NULL to omit */
61 static HRESULT
register_interfaces(struct regsvr_interface
const *list
);
62 static HRESULT
unregister_interfaces(struct regsvr_interface
const *list
);
66 CLSID
const *clsid
; /* NULL for end of list */
67 LPCSTR name
; /* can be NULL to omit */
68 LPCSTR ips
; /* can be NULL to omit */
69 LPCSTR ips32
; /* can be NULL to omit */
70 LPCSTR ips32_tmodel
; /* can be NULL to omit */
71 LPCSTR clsid_str
; /* can be NULL to omit */
72 LPCSTR progid
; /* can be NULL to omit */
75 static HRESULT
register_coclasses(struct regsvr_coclass
const *list
);
76 static HRESULT
unregister_coclasses(struct regsvr_coclass
const *list
);
78 /***********************************************************************
79 * static string constants
81 static WCHAR
const interface_keyname
[10] = {
82 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c', 'e', 0 };
83 static WCHAR
const base_ifa_keyname
[14] = {
84 'B', 'a', 's', 'e', 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c',
86 static WCHAR
const num_methods_keyname
[11] = {
87 'N', 'u', 'm', 'M', 'e', 't', 'h', 'o', 'd', 's', 0 };
88 static WCHAR
const ps_clsid_keyname
[15] = {
89 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
91 static WCHAR
const ps_clsid32_keyname
[17] = {
92 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
93 'i', 'd', '3', '2', 0 };
94 static WCHAR
const clsid_keyname
[6] = {
95 'C', 'L', 'S', 'I', 'D', 0 };
96 static WCHAR
const ips_keyname
[13] = {
97 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
99 static WCHAR
const ips32_keyname
[15] = {
100 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
102 static WCHAR
const progid_keyname
[7] = {
103 'P', 'r', 'o', 'g', 'I', 'D', 0 };
104 static char const tmodel_valuename
[] = "ThreadingModel";
106 /***********************************************************************
107 * static helper functions
109 static LONG
register_key_guid(HKEY base
, WCHAR
const *name
, GUID
const *guid
);
110 static LONG
register_key_defvalueW(HKEY base
, WCHAR
const *name
,
112 static LONG
register_key_defvalueA(HKEY base
, WCHAR
const *name
,
115 /***********************************************************************
116 * register_interfaces
118 static HRESULT
register_interfaces(struct regsvr_interface
const *list
)
120 LONG res
= ERROR_SUCCESS
;
123 res
= RegCreateKeyExW(HKEY_CLASSES_ROOT
, interface_keyname
, 0, NULL
, 0,
124 KEY_READ
| KEY_WRITE
, NULL
, &interface_key
, NULL
);
125 if (res
!= ERROR_SUCCESS
) goto error_return
;
127 for (; res
== ERROR_SUCCESS
&& list
->iid
; ++list
) {
131 StringFromGUID2(list
->iid
, buf
, 39);
132 res
= RegCreateKeyExW(interface_key
, buf
, 0, NULL
, 0,
133 KEY_READ
| KEY_WRITE
, NULL
, &iid_key
, NULL
);
134 if (res
!= ERROR_SUCCESS
) goto error_close_interface_key
;
137 res
= RegSetValueExA(iid_key
, NULL
, 0, REG_SZ
,
138 (CONST BYTE
*)(list
->name
),
139 strlen(list
->name
) + 1);
140 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
143 if (list
->base_iid
) {
144 res
= register_key_guid(iid_key
, base_ifa_keyname
, list
->base_iid
);
145 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
148 if (0 <= list
->num_methods
) {
149 static WCHAR
const fmt
[3] = { '%', 'd', 0 };
152 res
= RegCreateKeyExW(iid_key
, num_methods_keyname
, 0, NULL
, 0,
153 KEY_READ
| KEY_WRITE
, NULL
, &key
, NULL
);
154 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
156 sprintfW(buf
, fmt
, list
->num_methods
);
157 res
= RegSetValueExW(key
, NULL
, 0, REG_SZ
,
159 (lstrlenW(buf
) + 1) * sizeof(WCHAR
));
162 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
165 if (list
->ps_clsid
) {
166 res
= register_key_guid(iid_key
, ps_clsid_keyname
, list
->ps_clsid
);
167 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
170 if (list
->ps_clsid32
) {
171 res
= register_key_guid(iid_key
, ps_clsid32_keyname
, list
->ps_clsid32
);
172 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
176 RegCloseKey(iid_key
);
179 error_close_interface_key
:
180 RegCloseKey(interface_key
);
182 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
185 /***********************************************************************
186 * unregister_interfaces
188 static HRESULT
unregister_interfaces(struct regsvr_interface
const *list
)
190 LONG res
= ERROR_SUCCESS
;
193 res
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, interface_keyname
, 0,
194 KEY_READ
| KEY_WRITE
, &interface_key
);
195 if (res
== ERROR_FILE_NOT_FOUND
) return S_OK
;
196 if (res
!= ERROR_SUCCESS
) goto error_return
;
198 for (; res
== ERROR_SUCCESS
&& list
->iid
; ++list
) {
201 StringFromGUID2(list
->iid
, buf
, 39);
202 res
= RegDeleteTreeW(interface_key
, buf
);
203 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
206 RegCloseKey(interface_key
);
208 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
211 /***********************************************************************
214 static HRESULT
register_coclasses(struct regsvr_coclass
const *list
)
216 LONG res
= ERROR_SUCCESS
;
219 res
= RegCreateKeyExW(HKEY_CLASSES_ROOT
, clsid_keyname
, 0, NULL
, 0,
220 KEY_READ
| KEY_WRITE
, NULL
, &coclass_key
, NULL
);
221 if (res
!= ERROR_SUCCESS
) goto error_return
;
223 for (; res
== ERROR_SUCCESS
&& list
->clsid
; ++list
) {
227 StringFromGUID2(list
->clsid
, buf
, 39);
228 res
= RegCreateKeyExW(coclass_key
, buf
, 0, NULL
, 0,
229 KEY_READ
| KEY_WRITE
, NULL
, &clsid_key
, NULL
);
230 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
233 res
= RegSetValueExA(clsid_key
, NULL
, 0, REG_SZ
,
234 (CONST BYTE
*)(list
->name
),
235 strlen(list
->name
) + 1);
236 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
240 res
= register_key_defvalueA(clsid_key
, ips_keyname
, list
->ips
);
241 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
247 res
= RegCreateKeyExW(clsid_key
, ips32_keyname
, 0, NULL
, 0,
248 KEY_READ
| KEY_WRITE
, NULL
,
250 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
252 res
= RegSetValueExA(ips32_key
, NULL
, 0, REG_SZ
,
253 (CONST BYTE
*)list
->ips32
,
254 lstrlenA(list
->ips32
) + 1);
255 if (res
== ERROR_SUCCESS
&& list
->ips32_tmodel
)
256 res
= RegSetValueExA(ips32_key
, tmodel_valuename
, 0, REG_SZ
,
257 (CONST BYTE
*)list
->ips32_tmodel
,
258 strlen(list
->ips32_tmodel
) + 1);
259 RegCloseKey(ips32_key
);
260 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
263 if (list
->clsid_str
) {
264 res
= register_key_defvalueA(clsid_key
, clsid_keyname
,
266 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
272 res
= register_key_defvalueA(clsid_key
, progid_keyname
,
274 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
276 res
= RegCreateKeyExA(HKEY_CLASSES_ROOT
, list
->progid
, 0,
277 NULL
, 0, KEY_READ
| KEY_WRITE
, NULL
,
279 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
281 res
= register_key_defvalueW(progid_key
, clsid_keyname
, buf
);
282 RegCloseKey(progid_key
);
283 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
286 error_close_clsid_key
:
287 RegCloseKey(clsid_key
);
290 error_close_coclass_key
:
291 RegCloseKey(coclass_key
);
293 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
296 /***********************************************************************
297 * unregister_coclasses
299 static HRESULT
unregister_coclasses(struct regsvr_coclass
const *list
)
301 LONG res
= ERROR_SUCCESS
;
304 res
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, clsid_keyname
, 0,
305 KEY_READ
| KEY_WRITE
, &coclass_key
);
306 if (res
== ERROR_FILE_NOT_FOUND
) return S_OK
;
307 if (res
!= ERROR_SUCCESS
) goto error_return
;
309 for (; res
== ERROR_SUCCESS
&& list
->clsid
; ++list
) {
312 StringFromGUID2(list
->clsid
, buf
, 39);
313 res
= RegDeleteTreeW(coclass_key
, buf
);
314 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
315 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
318 res
= RegDeleteTreeA(HKEY_CLASSES_ROOT
, list
->progid
);
319 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
320 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
324 error_close_coclass_key
:
325 RegCloseKey(coclass_key
);
327 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
330 /***********************************************************************
333 static LONG
register_key_guid(HKEY base
, WCHAR
const *name
, GUID
const *guid
)
337 StringFromGUID2(guid
, buf
, 39);
338 return register_key_defvalueW(base
, name
, buf
);
341 /***********************************************************************
342 * regsvr_key_defvalueW
344 static LONG
register_key_defvalueW(
352 res
= RegCreateKeyExW(base
, name
, 0, NULL
, 0,
353 KEY_READ
| KEY_WRITE
, NULL
, &key
, NULL
);
354 if (res
!= ERROR_SUCCESS
) return res
;
355 res
= RegSetValueExW(key
, NULL
, 0, REG_SZ
, (CONST BYTE
*)value
,
356 (lstrlenW(value
) + 1) * sizeof(WCHAR
));
361 /***********************************************************************
362 * regsvr_key_defvalueA
364 static LONG
register_key_defvalueA(
372 res
= RegCreateKeyExW(base
, name
, 0, NULL
, 0,
373 KEY_READ
| KEY_WRITE
, NULL
, &key
, NULL
);
374 if (res
!= ERROR_SUCCESS
) return res
;
375 res
= RegSetValueExA(key
, NULL
, 0, REG_SZ
, (CONST BYTE
*)value
,
376 lstrlenA(value
) + 1);
381 /***********************************************************************
384 static HRESULT
register_typelib( const WCHAR
*name
)
386 static const WCHAR backslash
[] = {'\\',0};
392 len
= GetSystemDirectoryW( NULL
, 0 ) + strlenW( name
) + 1;
393 if (!(path
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) ))) return E_OUTOFMEMORY
;
394 GetSystemDirectoryW( path
, len
);
395 strcatW( path
, backslash
);
396 strcatW( path
, name
);
397 hr
= LoadTypeLib( path
, &typelib
);
400 hr
= RegisterTypeLib( typelib
, path
, NULL
);
401 ITypeLib_Release( typelib
);
403 HeapFree( GetProcessHeap(), 0, path
);
407 /***********************************************************************
410 static GUID
const CLSID_RecordInfo
= {
411 0x0000002F, 0x0000, 0x0000, {0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46} };
413 static GUID
const CLSID_OldFont
= {
414 0x46763EE0, 0xCAB2, 0x11CE, {0x8C,0x20,0x00,0xAA,0x00,0x51,0xE5,0xD4} };
416 static struct regsvr_coclass
const coclass_list
[] = {
445 { &CLSID_PSEnumVariant
,
463 { &CLSID_PSOAInterface
,
483 { &IID_ISupportErrorInfo
,
484 "PSSupportErrorInfo",
489 { NULL
} /* list terminator */
492 /***********************************************************************
495 #define INTERFACE_ENTRY(interface, clsid16, clsid32) { &IID_##interface, #interface, NULL, sizeof(interface##Vtbl)/sizeof(void*), clsid16, clsid32 }
496 #define LCL_INTERFACE_ENTRY(interface) INTERFACE_ENTRY(interface, NULL, NULL)
497 #define CLSID_INTERFACE_ENTRY(interface,clsid) INTERFACE_ENTRY(interface, clsid, clsid)
499 static struct regsvr_interface
const interface_list
[] = {
500 LCL_INTERFACE_ENTRY(ICreateTypeInfo
),
501 LCL_INTERFACE_ENTRY(ICreateTypeLib
),
502 CLSID_INTERFACE_ENTRY(IDispatch
,&CLSID_PSDispatch
),
503 CLSID_INTERFACE_ENTRY(IEnumVARIANT
,&CLSID_PSEnumVariant
),
504 CLSID_INTERFACE_ENTRY(ITypeComp
,&CLSID_PSTypeComp
),
505 CLSID_INTERFACE_ENTRY(ITypeInfo
,&CLSID_PSTypeInfo
),
506 CLSID_INTERFACE_ENTRY(ITypeLib
,&CLSID_PSTypeLib
),
507 INTERFACE_ENTRY(ISupportErrorInfo
,NULL
,&CLSID_PSDispatch
),
508 INTERFACE_ENTRY(ITypeFactory
,NULL
,&CLSID_PSDispatch
),
509 INTERFACE_ENTRY(ITypeInfo2
,NULL
,&CLSID_PSDispatch
),
510 INTERFACE_ENTRY(ITypeLib2
,NULL
,&CLSID_PSDispatch
),
511 { NULL
} /* list terminator */
514 extern HRESULT WINAPI
OLEAUTPS_DllRegisterServer(void) DECLSPEC_HIDDEN
;
515 extern HRESULT WINAPI
OLEAUTPS_DllUnregisterServer(void) DECLSPEC_HIDDEN
;
517 /***********************************************************************
518 * DllRegisterServer (OLEAUT32.@)
520 HRESULT WINAPI
DllRegisterServer(void)
526 hr
= OLEAUTPS_DllRegisterServer();
528 hr
= register_coclasses(coclass_list
);
530 hr
= register_interfaces(interface_list
);
533 const WCHAR stdole32W
[] = {'s','t','d','o','l','e','3','2','.','t','l','b',0};
534 const WCHAR stdole2W
[] = {'s','t','d','o','l','e','2','.','t','l','b',0};
535 hr
= register_typelib( stdole2W
);
536 if (SUCCEEDED(hr
)) hr
= register_typelib( stdole32W
);
541 /***********************************************************************
542 * DllUnregisterServer (OLEAUT32.@)
544 HRESULT WINAPI
DllUnregisterServer(void)
550 hr
= unregister_coclasses(coclass_list
);
552 hr
= unregister_interfaces(interface_list
);
554 hr
= OLEAUTPS_DllUnregisterServer();