2 * self-registerable dll functions for ole32.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
36 #include "compobj_private.h"
39 #include "wine/debug.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 */
73 static HRESULT
register_coclasses(struct regsvr_coclass
const *list
);
74 static HRESULT
unregister_coclasses(struct regsvr_coclass
const *list
);
76 /***********************************************************************
77 * static string constants
79 static WCHAR
const interface_keyname
[10] = {
80 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c', 'e', 0 };
81 static WCHAR
const base_ifa_keyname
[14] = {
82 'B', 'a', 's', 'e', 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c',
84 static WCHAR
const num_methods_keyname
[11] = {
85 'N', 'u', 'm', 'M', 'e', 't', 'h', 'o', 'd', 's', 0 };
86 static WCHAR
const ps_clsid_keyname
[15] = {
87 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
89 static WCHAR
const ps_clsid32_keyname
[17] = {
90 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
91 'i', 'd', '3', '2', 0 };
92 static WCHAR
const clsid_keyname
[6] = {
93 'C', 'L', 'S', 'I', 'D', 0 };
94 static WCHAR
const ips_keyname
[13] = {
95 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
97 static WCHAR
const ips32_keyname
[15] = {
98 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
100 static char const tmodel_valuename
[] = "ThreadingModel";
102 /***********************************************************************
103 * static helper functions
105 static LONG
register_key_guid(HKEY base
, WCHAR
const *name
, GUID
const *guid
);
106 static LONG
register_key_defvalueW(HKEY base
, WCHAR
const *name
,
108 static LONG
register_key_defvalueA(HKEY base
, WCHAR
const *name
,
110 static LONG
recursive_delete_key(HKEY key
);
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 res
= 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 res
= 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 res
= 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
) {
200 StringFromGUID2(list
->iid
, buf
, 39);
201 res
= RegOpenKeyExW(interface_key
, buf
, 0,
202 KEY_READ
| KEY_WRITE
, &iid_key
);
203 if (res
== ERROR_FILE_NOT_FOUND
) {
207 if (res
!= ERROR_SUCCESS
) goto error_close_interface_key
;
208 res
= recursive_delete_key(iid_key
);
209 RegCloseKey(iid_key
);
210 if (res
!= ERROR_SUCCESS
) goto error_close_interface_key
;
213 error_close_interface_key
:
214 RegCloseKey(interface_key
);
216 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
219 /***********************************************************************
222 static HRESULT
register_coclasses(struct regsvr_coclass
const *list
)
224 LONG res
= ERROR_SUCCESS
;
227 res
= RegCreateKeyExW(HKEY_CLASSES_ROOT
, clsid_keyname
, 0, NULL
, 0,
228 KEY_READ
| KEY_WRITE
, NULL
, &coclass_key
, NULL
);
229 if (res
!= ERROR_SUCCESS
) goto error_return
;
231 for (; res
== ERROR_SUCCESS
&& list
->clsid
; ++list
) {
235 StringFromGUID2(list
->clsid
, buf
, 39);
236 res
= RegCreateKeyExW(coclass_key
, buf
, 0, NULL
, 0,
237 KEY_READ
| KEY_WRITE
, NULL
, &clsid_key
, NULL
);
238 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
241 res
= RegSetValueExA(clsid_key
, NULL
, 0, REG_SZ
,
242 (CONST BYTE
*)(list
->name
),
243 strlen(list
->name
) + 1);
244 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
248 res
= register_key_defvalueA(clsid_key
, ips_keyname
, list
->ips
);
249 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
255 res
= RegCreateKeyExW(clsid_key
, ips32_keyname
, 0, NULL
, 0,
256 KEY_READ
| KEY_WRITE
, NULL
,
258 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
260 res
= RegSetValueExA(ips32_key
, NULL
, 0, REG_SZ
,
261 (CONST BYTE
*)list
->ips32
,
262 lstrlenA(list
->ips32
) + 1);
263 if (res
== ERROR_SUCCESS
&& list
->ips32_tmodel
)
264 res
= RegSetValueExA(ips32_key
, tmodel_valuename
, 0, REG_SZ
,
265 (CONST BYTE
*)list
->ips32_tmodel
,
266 strlen(list
->ips32_tmodel
) + 1);
267 RegCloseKey(ips32_key
);
268 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
271 error_close_clsid_key
:
272 RegCloseKey(clsid_key
);
275 error_close_coclass_key
:
276 RegCloseKey(coclass_key
);
278 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
281 /***********************************************************************
282 * unregister_coclasses
284 static HRESULT
unregister_coclasses(struct regsvr_coclass
const *list
)
286 LONG res
= ERROR_SUCCESS
;
289 res
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, clsid_keyname
, 0,
290 KEY_READ
| KEY_WRITE
, &coclass_key
);
291 if (res
== ERROR_FILE_NOT_FOUND
) return S_OK
;
292 if (res
!= ERROR_SUCCESS
) goto error_return
;
294 for (; res
== ERROR_SUCCESS
&& list
->clsid
; ++list
) {
298 StringFromGUID2(list
->clsid
, buf
, 39);
299 res
= RegOpenKeyExW(coclass_key
, buf
, 0,
300 KEY_READ
| KEY_WRITE
, &clsid_key
);
301 if (res
== ERROR_FILE_NOT_FOUND
) {
305 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
306 res
= recursive_delete_key(clsid_key
);
307 RegCloseKey(clsid_key
);
308 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
311 error_close_coclass_key
:
312 RegCloseKey(coclass_key
);
314 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
317 /***********************************************************************
320 static LONG
register_key_guid(HKEY base
, WCHAR
const *name
, GUID
const *guid
)
324 StringFromGUID2(guid
, buf
, 39);
325 return register_key_defvalueW(base
, name
, buf
);
328 /***********************************************************************
329 * regsvr_key_defvalueW
331 static LONG
register_key_defvalueW(
339 res
= RegCreateKeyExW(base
, name
, 0, NULL
, 0,
340 KEY_READ
| KEY_WRITE
, NULL
, &key
, NULL
);
341 if (res
!= ERROR_SUCCESS
) return res
;
342 res
= RegSetValueExW(key
, NULL
, 0, REG_SZ
, (CONST BYTE
*)value
,
343 (lstrlenW(value
) + 1) * sizeof(WCHAR
));
348 /***********************************************************************
349 * regsvr_key_defvalueA
351 static LONG
register_key_defvalueA(
359 res
= RegCreateKeyExW(base
, name
, 0, NULL
, 0,
360 KEY_READ
| KEY_WRITE
, NULL
, &key
, NULL
);
361 if (res
!= ERROR_SUCCESS
) return res
;
362 res
= RegSetValueExA(key
, NULL
, 0, REG_SZ
, (CONST BYTE
*)value
,
363 lstrlenA(value
) + 1);
368 /***********************************************************************
369 * recursive_delete_key
371 static LONG
recursive_delete_key(HKEY key
)
374 WCHAR subkey_name
[MAX_PATH
];
379 cName
= sizeof(subkey_name
) / sizeof(WCHAR
);
380 res
= RegEnumKeyExW(key
, 0, subkey_name
, &cName
,
381 NULL
, NULL
, NULL
, NULL
);
382 if (res
!= ERROR_SUCCESS
&& res
!= ERROR_MORE_DATA
) {
383 res
= ERROR_SUCCESS
; /* presumably we're done enumerating */
386 res
= RegOpenKeyExW(key
, subkey_name
, 0,
387 KEY_READ
| KEY_WRITE
, &subkey
);
388 if (res
== ERROR_FILE_NOT_FOUND
) continue;
389 if (res
!= ERROR_SUCCESS
) break;
391 res
= recursive_delete_key(subkey
);
393 if (res
!= ERROR_SUCCESS
) break;
396 if (res
== ERROR_SUCCESS
) res
= RegDeleteKeyW(key
, 0);
400 /***********************************************************************
403 static GUID
const CLSID_PointerMoniker
= {
404 0x00000306, 0x0000, 0x0000, {0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46} };
406 static GUID
const CLSID_PackagerMoniker
= {
407 0x00000308, 0x0000, 0x0000, {0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46} };
409 static struct regsvr_coclass
const coclass_list
[] = {
410 { &CLSID_FileMoniker
,
416 { &CLSID_ItemMoniker
,
422 { &CLSID_AntiMoniker
,
428 { &CLSID_PointerMoniker
,
434 { &CLSID_PackagerMoniker
,
440 { &CLSID_CompositeMoniker
,
452 { &CLSID_ClassMoniker
,
458 { &CLSID_PSFactoryBuffer
,
464 { &CLSID_StdGlobalInterfaceTable
,
465 "StdGlobalInterfaceTable",
470 { NULL
} /* list terminator */
473 /***********************************************************************
477 #define INTERFACE_ENTRY(interface, base, clsid32, clsid16) { &IID_##interface, #interface, base, sizeof(interface##Vtbl)/sizeof(void*), clsid16, clsid32 }
478 #define STD_INTERFACE_ENTRY(interface) INTERFACE_ENTRY(interface, NULL, &CLSID_PSFactoryBuffer, NULL)
479 #define LCL_INTERFACE_ENTRY(interface) INTERFACE_ENTRY(interface, NULL, NULL, NULL)
481 static const struct regsvr_interface interface_list
[] = {
482 LCL_INTERFACE_ENTRY(IUnknown
),
483 STD_INTERFACE_ENTRY(IClassFactory
),
484 LCL_INTERFACE_ENTRY(IMalloc
),
485 LCL_INTERFACE_ENTRY(IMarshal
),
486 STD_INTERFACE_ENTRY(IStorage
),
487 LCL_INTERFACE_ENTRY(IMessageFilter
),
488 LCL_INTERFACE_ENTRY(IStdMarshalInfo
),
489 LCL_INTERFACE_ENTRY(IExternalConnection
),
490 LCL_INTERFACE_ENTRY(IMallocSpy
),
491 LCL_INTERFACE_ENTRY(IMultiQI
),
492 STD_INTERFACE_ENTRY(IStream
),
493 STD_INTERFACE_ENTRY(IPersistStorage
),
494 STD_INTERFACE_ENTRY(IDataObject
),
495 STD_INTERFACE_ENTRY(IAdviseSink
),
496 LCL_INTERFACE_ENTRY(IDataAdviseHolder
),
497 LCL_INTERFACE_ENTRY(IOleAdviseHolder
),
498 STD_INTERFACE_ENTRY(IOleObject
),
499 STD_INTERFACE_ENTRY(IOleClientSite
),
500 LCL_INTERFACE_ENTRY(IDropSource
),
501 STD_INTERFACE_ENTRY(IRemUnknown
),
502 LCL_INTERFACE_ENTRY(IClientSecurity
),
503 LCL_INTERFACE_ENTRY(IServerSecurity
),
504 STD_INTERFACE_ENTRY(ISequentialStream
),
505 { NULL
} /* list terminator */
508 /***********************************************************************
509 * DllRegisterServer (OLE32.@)
511 HRESULT WINAPI
DllRegisterServer()
517 hr
= register_coclasses(coclass_list
);
519 hr
= register_interfaces(interface_list
);
523 /***********************************************************************
524 * DllUnregisterServer (OLE32.@)
526 HRESULT WINAPI
DllUnregisterServer()
532 hr
= unregister_coclasses(coclass_list
);
534 hr
= unregister_interfaces(interface_list
);