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
37 #include "compobj_private.h"
40 #include "wine/debug.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
45 * Near the bottom of this file are the exported DllRegisterServer and
46 * DllUnregisterServer, which make all this worthwhile.
49 /***********************************************************************
50 * interface for self-registering
52 struct regsvr_interface
54 IID
const *iid
; /* NULL for end of list */
55 LPCSTR name
; /* can be NULL to omit */
56 IID
const *base_iid
; /* can be NULL to omit */
57 int num_methods
; /* can be <0 to omit */
58 CLSID
const *ps_clsid
; /* can be NULL to omit */
59 CLSID
const *ps_clsid32
; /* can be NULL to omit */
62 static HRESULT
register_interfaces(struct regsvr_interface
const *list
);
63 static HRESULT
unregister_interfaces(struct regsvr_interface
const *list
);
67 CLSID
const *clsid
; /* NULL for end of list */
68 LPCSTR name
; /* can be NULL to omit */
69 LPCSTR ips
; /* can be NULL to omit */
70 LPCSTR ips32
; /* can be NULL to omit */
71 LPCSTR ips32_tmodel
; /* 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
,
114 static LONG
register_progid(WCHAR
const *clsid
, char const *progid
,
117 /***********************************************************************
118 * register_interfaces
120 static HRESULT
register_interfaces(struct regsvr_interface
const *list
)
122 LONG res
= ERROR_SUCCESS
;
125 res
= RegCreateKeyExW(HKEY_CLASSES_ROOT
, interface_keyname
, 0, NULL
, 0,
126 KEY_READ
| KEY_WRITE
, NULL
, &interface_key
, NULL
);
127 if (res
!= ERROR_SUCCESS
) goto error_return
;
129 for (; res
== ERROR_SUCCESS
&& list
->iid
; ++list
) {
133 StringFromGUID2(list
->iid
, buf
, 39);
134 res
= RegCreateKeyExW(interface_key
, buf
, 0, NULL
, 0,
135 KEY_READ
| KEY_WRITE
, NULL
, &iid_key
, NULL
);
136 if (res
!= ERROR_SUCCESS
) goto error_close_interface_key
;
139 res
= RegSetValueExA(iid_key
, NULL
, 0, REG_SZ
,
140 (CONST BYTE
*)(list
->name
),
141 strlen(list
->name
) + 1);
142 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
145 if (list
->base_iid
) {
146 res
= register_key_guid(iid_key
, base_ifa_keyname
, list
->base_iid
);
147 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
150 if (0 <= list
->num_methods
) {
151 static WCHAR
const fmt
[3] = { '%', 'd', 0 };
154 res
= RegCreateKeyExW(iid_key
, num_methods_keyname
, 0, NULL
, 0,
155 KEY_READ
| KEY_WRITE
, NULL
, &key
, NULL
);
156 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
158 wsprintfW(buf
, fmt
, list
->num_methods
);
159 res
= RegSetValueExW(key
, NULL
, 0, REG_SZ
,
161 (lstrlenW(buf
) + 1) * sizeof(WCHAR
));
164 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
167 if (list
->ps_clsid
) {
168 res
= register_key_guid(iid_key
, ps_clsid_keyname
, list
->ps_clsid
);
169 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
172 if (list
->ps_clsid32
) {
173 res
= register_key_guid(iid_key
, ps_clsid32_keyname
, list
->ps_clsid32
);
174 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
178 RegCloseKey(iid_key
);
181 error_close_interface_key
:
182 RegCloseKey(interface_key
);
184 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
187 /***********************************************************************
188 * unregister_interfaces
190 static HRESULT
unregister_interfaces(struct regsvr_interface
const *list
)
192 LONG res
= ERROR_SUCCESS
;
195 res
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, interface_keyname
, 0,
196 KEY_READ
| KEY_WRITE
, &interface_key
);
197 if (res
== ERROR_FILE_NOT_FOUND
) return S_OK
;
198 if (res
!= ERROR_SUCCESS
) goto error_return
;
200 for (; res
== ERROR_SUCCESS
&& list
->iid
; ++list
) {
203 StringFromGUID2(list
->iid
, buf
, 39);
204 res
= RegDeleteTreeW(interface_key
, buf
);
205 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
208 RegCloseKey(interface_key
);
210 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
213 /***********************************************************************
216 static HRESULT
register_coclasses(struct regsvr_coclass
const *list
)
218 LONG res
= ERROR_SUCCESS
;
221 res
= RegCreateKeyExW(HKEY_CLASSES_ROOT
, clsid_keyname
, 0, NULL
, 0,
222 KEY_READ
| KEY_WRITE
, NULL
, &coclass_key
, NULL
);
223 if (res
!= ERROR_SUCCESS
) goto error_return
;
225 for (; res
== ERROR_SUCCESS
&& list
->clsid
; ++list
) {
229 StringFromGUID2(list
->clsid
, buf
, 39);
230 res
= RegCreateKeyExW(coclass_key
, buf
, 0, NULL
, 0,
231 KEY_READ
| KEY_WRITE
, NULL
, &clsid_key
, NULL
);
232 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
235 res
= RegSetValueExA(clsid_key
, NULL
, 0, REG_SZ
,
236 (CONST BYTE
*)(list
->name
),
237 strlen(list
->name
) + 1);
238 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
242 res
= register_key_defvalueA(clsid_key
, ips_keyname
, list
->ips
);
243 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
249 res
= RegCreateKeyExW(clsid_key
, ips32_keyname
, 0, NULL
, 0,
250 KEY_READ
| KEY_WRITE
, NULL
,
252 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
254 res
= RegSetValueExA(ips32_key
, NULL
, 0, REG_SZ
,
255 (CONST BYTE
*)list
->ips32
,
256 lstrlenA(list
->ips32
) + 1);
257 if (res
== ERROR_SUCCESS
&& list
->ips32_tmodel
)
258 res
= RegSetValueExA(ips32_key
, tmodel_valuename
, 0, REG_SZ
,
259 (CONST BYTE
*)list
->ips32_tmodel
,
260 strlen(list
->ips32_tmodel
) + 1);
261 RegCloseKey(ips32_key
);
262 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
266 res
= register_key_defvalueA(clsid_key
, progid_keyname
,
268 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
270 res
= register_progid(buf
, list
->progid
, list
->name
);
271 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
274 error_close_clsid_key
:
275 RegCloseKey(clsid_key
);
278 error_close_coclass_key
:
279 RegCloseKey(coclass_key
);
281 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
284 /***********************************************************************
285 * unregister_coclasses
287 static HRESULT
unregister_coclasses(struct regsvr_coclass
const *list
)
289 LONG res
= ERROR_SUCCESS
;
292 res
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, clsid_keyname
, 0,
293 KEY_READ
| KEY_WRITE
, &coclass_key
);
294 if (res
== ERROR_FILE_NOT_FOUND
) return S_OK
;
295 if (res
!= ERROR_SUCCESS
) goto error_return
;
297 for (; res
== ERROR_SUCCESS
&& list
->clsid
; ++list
) {
300 StringFromGUID2(list
->clsid
, buf
, 39);
301 res
= RegDeleteTreeW(coclass_key
, buf
);
302 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
303 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
306 res
= RegDeleteTreeA(HKEY_CLASSES_ROOT
, list
->progid
);
307 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
308 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
312 error_close_coclass_key
:
313 RegCloseKey(coclass_key
);
315 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
318 /***********************************************************************
321 static LONG
register_key_guid(HKEY base
, WCHAR
const *name
, GUID
const *guid
)
325 StringFromGUID2(guid
, buf
, 39);
326 return register_key_defvalueW(base
, name
, buf
);
329 /***********************************************************************
330 * regsvr_key_defvalueW
332 static LONG
register_key_defvalueW(
340 res
= RegCreateKeyExW(base
, name
, 0, NULL
, 0,
341 KEY_READ
| KEY_WRITE
, NULL
, &key
, NULL
);
342 if (res
!= ERROR_SUCCESS
) return res
;
343 res
= RegSetValueExW(key
, NULL
, 0, REG_SZ
, (CONST BYTE
*)value
,
344 (lstrlenW(value
) + 1) * sizeof(WCHAR
));
349 /***********************************************************************
350 * regsvr_key_defvalueA
352 static LONG
register_key_defvalueA(
360 res
= RegCreateKeyExW(base
, name
, 0, NULL
, 0,
361 KEY_READ
| KEY_WRITE
, NULL
, &key
, NULL
);
362 if (res
!= ERROR_SUCCESS
) return res
;
363 res
= RegSetValueExA(key
, NULL
, 0, REG_SZ
, (CONST BYTE
*)value
,
364 lstrlenA(value
) + 1);
369 /***********************************************************************
372 static LONG
register_progid(
380 res
= RegCreateKeyExA(HKEY_CLASSES_ROOT
, progid
, 0,
381 NULL
, 0, KEY_READ
| KEY_WRITE
, NULL
,
383 if (res
!= ERROR_SUCCESS
) return res
;
386 res
= RegSetValueExA(progid_key
, NULL
, 0, REG_SZ
,
387 (CONST BYTE
*)name
, strlen(name
) + 1);
388 if (res
!= ERROR_SUCCESS
) goto error_close_progid_key
;
392 res
= register_key_defvalueW(progid_key
, clsid_keyname
, clsid
);
393 if (res
!= ERROR_SUCCESS
) goto error_close_progid_key
;
396 error_close_progid_key
:
397 RegCloseKey(progid_key
);
401 /***********************************************************************
404 static GUID
const CLSID_StdOleLink
= {
405 0x00000300, 0x0000, 0x0000, {0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46} };
407 static GUID
const CLSID_PackagerMoniker
= {
408 0x00000308, 0x0000, 0x0000, {0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46} };
410 static GUID
const CLSID_PSFactoryBuffer_actxprxy
= {
411 0xB8DA6310, 0xE19B, 0x11D0, {0x93,0x3C,0x00,0xA0,0xC9,0x0D,0xCA,0xA9} };
413 extern GUID
const CLSID_Picture_Metafile
;
414 extern GUID
const CLSID_Picture_Dib
;
416 static struct regsvr_coclass
const coclass_list
[] = {
423 { &CLSID_FileMoniker
,
430 { &CLSID_ItemMoniker
,
436 { &CLSID_AntiMoniker
,
442 { &CLSID_PointerMoniker
,
448 { &CLSID_PackagerMoniker
,
454 { &CLSID_CompositeMoniker
,
466 { &CLSID_Picture_Metafile
,
467 "Picture (Metafile)",
473 { &CLSID_Picture_Dib
,
474 "Picture (Device Independent Bitmap)",
480 { &CLSID_ClassMoniker
,
487 { &CLSID_PSFactoryBuffer
,
493 { &CLSID_StdGlobalInterfaceTable
,
494 "StdGlobalInterfaceTable",
499 { &CLSID_StdComponentCategoriesMgr
,
500 "Component Categories Manager",
505 { NULL
} /* list terminator */
508 /***********************************************************************
512 #define INTERFACE_ENTRY(interface, base, clsid32, clsid16) { &IID_##interface, #interface, base, sizeof(interface##Vtbl)/sizeof(void*), clsid16, clsid32 }
513 #define BAS_INTERFACE_ENTRY(interface, base) INTERFACE_ENTRY(interface, &IID_##base, &CLSID_PSFactoryBuffer, NULL)
514 #define STD_INTERFACE_ENTRY(interface) INTERFACE_ENTRY(interface, NULL, &CLSID_PSFactoryBuffer, NULL)
515 #define ACTX_INTERFACE_ENTRY(interface) INTERFACE_ENTRY(interface, NULL, &CLSID_PSFactoryBuffer_actxprxy, NULL)
516 #define LCL_INTERFACE_ENTRY(interface) INTERFACE_ENTRY(interface, NULL, NULL, NULL)
518 static const struct regsvr_interface interface_list
[] = {
519 LCL_INTERFACE_ENTRY(IUnknown
),
520 STD_INTERFACE_ENTRY(IClassFactory
),
521 LCL_INTERFACE_ENTRY(IMalloc
),
522 LCL_INTERFACE_ENTRY(IMarshal
),
523 STD_INTERFACE_ENTRY(ILockBytes
),
524 STD_INTERFACE_ENTRY(IStorage
),
525 STD_INTERFACE_ENTRY(IStream
),
526 STD_INTERFACE_ENTRY(IEnumSTATSTG
),
527 STD_INTERFACE_ENTRY(IBindCtx
),
528 BAS_INTERFACE_ENTRY(IMoniker
, IPersistStream
),
529 STD_INTERFACE_ENTRY(IRunningObjectTable
),
530 STD_INTERFACE_ENTRY(IRootStorage
),
531 LCL_INTERFACE_ENTRY(IMessageFilter
),
532 LCL_INTERFACE_ENTRY(IStdMarshalInfo
),
533 LCL_INTERFACE_ENTRY(IExternalConnection
),
534 LCL_INTERFACE_ENTRY(IMallocSpy
),
535 LCL_INTERFACE_ENTRY(IMultiQI
),
536 STD_INTERFACE_ENTRY(IEnumUnknown
),
537 STD_INTERFACE_ENTRY(IEnumString
),
538 STD_INTERFACE_ENTRY(IEnumMoniker
),
539 STD_INTERFACE_ENTRY(IEnumFORMATETC
),
540 STD_INTERFACE_ENTRY(IEnumOLEVERB
),
541 STD_INTERFACE_ENTRY(IEnumSTATDATA
),
542 BAS_INTERFACE_ENTRY(IPersistStream
, IPersist
),
543 BAS_INTERFACE_ENTRY(IPersistStorage
, IPersist
),
544 BAS_INTERFACE_ENTRY(IPersistFile
, IPersist
),
545 STD_INTERFACE_ENTRY(IPersist
),
546 STD_INTERFACE_ENTRY(IViewObject
),
547 STD_INTERFACE_ENTRY(IDataObject
),
548 STD_INTERFACE_ENTRY(IAdviseSink
),
549 LCL_INTERFACE_ENTRY(IDataAdviseHolder
),
550 LCL_INTERFACE_ENTRY(IOleAdviseHolder
),
551 STD_INTERFACE_ENTRY(IOleObject
),
552 BAS_INTERFACE_ENTRY(IOleInPlaceObject
, IOleWindow
),
553 STD_INTERFACE_ENTRY(IOleWindow
),
554 BAS_INTERFACE_ENTRY(IOleInPlaceUIWindow
, IOleWindow
),
555 STD_INTERFACE_ENTRY(IOleInPlaceFrame
),
556 BAS_INTERFACE_ENTRY(IOleInPlaceActiveObject
, IOleWindow
),
557 STD_INTERFACE_ENTRY(IOleClientSite
),
558 BAS_INTERFACE_ENTRY(IOleInPlaceSite
, IOleWindow
),
559 STD_INTERFACE_ENTRY(IParseDisplayName
),
560 BAS_INTERFACE_ENTRY(IOleContainer
, IParseDisplayName
),
561 BAS_INTERFACE_ENTRY(IOleItemContainer
, IOleContainer
),
562 STD_INTERFACE_ENTRY(IOleLink
),
563 STD_INTERFACE_ENTRY(IOleCache
),
564 LCL_INTERFACE_ENTRY(IDropSource
),
565 STD_INTERFACE_ENTRY(IDropTarget
),
566 BAS_INTERFACE_ENTRY(IAdviseSink2
, IAdviseSink
),
567 STD_INTERFACE_ENTRY(IRunnableObject
),
568 BAS_INTERFACE_ENTRY(IViewObject2
, IViewObject
),
569 BAS_INTERFACE_ENTRY(IOleCache2
, IOleCache
),
570 STD_INTERFACE_ENTRY(IOleCacheControl
),
571 STD_INTERFACE_ENTRY(IRemUnknown
),
572 LCL_INTERFACE_ENTRY(IClientSecurity
),
573 LCL_INTERFACE_ENTRY(IServerSecurity
),
574 STD_INTERFACE_ENTRY(ISequentialStream
),
575 ACTX_INTERFACE_ENTRY(IEnumGUID
),
576 ACTX_INTERFACE_ENTRY(IEnumCATEGORYINFO
),
577 ACTX_INTERFACE_ENTRY(ICatRegister
),
578 ACTX_INTERFACE_ENTRY(ICatInformation
),
579 { NULL
} /* list terminator */
582 /***********************************************************************
583 * DllRegisterServer (OLE32.@)
585 HRESULT WINAPI
DllRegisterServer(void)
591 hr
= register_coclasses(coclass_list
);
593 hr
= register_interfaces(interface_list
);
597 /***********************************************************************
598 * DllUnregisterServer (OLE32.@)
600 HRESULT WINAPI
DllUnregisterServer(void)
606 hr
= unregister_coclasses(coclass_list
);
608 hr
= unregister_interfaces(interface_list
);