ole32: Use helper function to duplicate global memory.
[wine] / dlls / ole32 / regsvr.c
1 /*
2  *      self-registerable dll functions for ole32.dll
3  *
4  * Copyright (C) 2003 John K. Hohm
5  *
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.
10  *
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.
15  *
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
19  */
20
21 #include "config.h"
22
23 #include <stdarg.h>
24 #include <string.h>
25
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winuser.h"
29 #include "winreg.h"
30 #include "winerror.h"
31 #include "objbase.h"
32
33 #include "ole2.h"
34 #include "olectl.h"
35 #include "comcat.h"
36 #include "initguid.h"
37 #include "compobj_private.h"
38 #include "moniker.h"
39
40 #include "wine/debug.h"
41 #include "wine/unicode.h"
42
43 WINE_DEFAULT_DEBUG_CHANNEL(ole);
44
45 /*
46  * Near the bottom of this file are the exported DllRegisterServer and
47  * DllUnregisterServer, which make all this worthwhile.
48  */
49
50 /***********************************************************************
51  *              interface for self-registering
52  */
53 struct regsvr_interface
54 {
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 */
61 };
62
63 static HRESULT register_interfaces(struct regsvr_interface const *list);
64 static HRESULT unregister_interfaces(struct regsvr_interface const *list);
65
66 struct regsvr_coclass
67 {
68     CLSID const *clsid;         /* NULL for end of list */
69     LPCSTR name;                /* can be NULL to omit */
70     LPCSTR ips;                 /* can be NULL to omit */
71     LPCSTR ips32;               /* can be NULL to omit */
72     LPCSTR ips32_tmodel;        /* can be NULL to omit */
73     LPCSTR progid;              /* can be NULL to omit */
74 };
75
76 static HRESULT register_coclasses(struct regsvr_coclass const *list);
77 static HRESULT unregister_coclasses(struct regsvr_coclass const *list);
78
79 /***********************************************************************
80  *              static string constants
81  */
82 static WCHAR const interface_keyname[10] = {
83     'I', 'n', 't', 'e', 'r', 'f', 'a', 'c', 'e', 0 };
84 static WCHAR const base_ifa_keyname[14] = {
85     'B', 'a', 's', 'e', 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c',
86     'e', 0 };
87 static WCHAR const num_methods_keyname[11] = {
88     'N', 'u', 'm', 'M', 'e', 't', 'h', 'o', 'd', 's', 0 };
89 static WCHAR const ps_clsid_keyname[15] = {
90     'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
91     'i', 'd', 0 };
92 static WCHAR const ps_clsid32_keyname[17] = {
93     'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
94     'i', 'd', '3', '2', 0 };
95 static WCHAR const clsid_keyname[6] = {
96     'C', 'L', 'S', 'I', 'D', 0 };
97 static WCHAR const ips_keyname[13] = {
98     'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
99     0 };
100 static WCHAR const ips32_keyname[15] = {
101     'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
102     '3', '2', 0 };
103 static WCHAR const progid_keyname[7] = {
104     'P', 'r', 'o', 'g', 'I', 'D', 0 };
105 static char const tmodel_valuename[] = "ThreadingModel";
106
107 /***********************************************************************
108  *              static helper functions
109  */
110 static LONG register_key_guid(HKEY base, WCHAR const *name, GUID const *guid);
111 static LONG register_key_defvalueW(HKEY base, WCHAR const *name,
112                                    WCHAR const *value);
113 static LONG register_key_defvalueA(HKEY base, WCHAR const *name,
114                                    char const *value);
115 static LONG register_progid(WCHAR const *clsid, char const *progid,
116                             char const *name);
117
118 /***********************************************************************
119  *              register_interfaces
120  */
121 static HRESULT register_interfaces(struct regsvr_interface const *list)
122 {
123     LONG res = ERROR_SUCCESS;
124     HKEY interface_key;
125
126     res = RegCreateKeyExW(HKEY_CLASSES_ROOT, interface_keyname, 0, NULL, 0,
127                           KEY_READ | KEY_WRITE, NULL, &interface_key, NULL);
128     if (res != ERROR_SUCCESS) goto error_return;
129
130     for (; res == ERROR_SUCCESS && list->iid; ++list) {
131         WCHAR buf[39];
132         HKEY iid_key;
133
134         StringFromGUID2(list->iid, buf, 39);
135         res = RegCreateKeyExW(interface_key, buf, 0, NULL, 0,
136                               KEY_READ | KEY_WRITE, NULL, &iid_key, NULL);
137         if (res != ERROR_SUCCESS) goto error_close_interface_key;
138
139         if (list->name) {
140             res = RegSetValueExA(iid_key, NULL, 0, REG_SZ,
141                                  (CONST BYTE*)(list->name),
142                                  strlen(list->name) + 1);
143             if (res != ERROR_SUCCESS) goto error_close_iid_key;
144         }
145
146         if (list->base_iid) {
147             res = register_key_guid(iid_key, base_ifa_keyname, list->base_iid);
148             if (res != ERROR_SUCCESS) goto error_close_iid_key;
149         }
150
151         if (0 <= list->num_methods) {
152             static WCHAR const fmt[3] = { '%', 'd', 0 };
153             HKEY key;
154
155             res = RegCreateKeyExW(iid_key, num_methods_keyname, 0, NULL, 0,
156                                   KEY_READ | KEY_WRITE, NULL, &key, NULL);
157             if (res != ERROR_SUCCESS) goto error_close_iid_key;
158
159             sprintfW(buf, fmt, list->num_methods);
160             res = RegSetValueExW(key, NULL, 0, REG_SZ,
161                                  (CONST BYTE*)buf,
162                                  (lstrlenW(buf) + 1) * sizeof(WCHAR));
163             RegCloseKey(key);
164
165             if (res != ERROR_SUCCESS) goto error_close_iid_key;
166         }
167
168         if (list->ps_clsid) {
169             res = register_key_guid(iid_key, ps_clsid_keyname, list->ps_clsid);
170             if (res != ERROR_SUCCESS) goto error_close_iid_key;
171         }
172
173         if (list->ps_clsid32) {
174             res = register_key_guid(iid_key, ps_clsid32_keyname, list->ps_clsid32);
175             if (res != ERROR_SUCCESS) goto error_close_iid_key;
176         }
177
178     error_close_iid_key:
179         RegCloseKey(iid_key);
180     }
181
182 error_close_interface_key:
183     RegCloseKey(interface_key);
184 error_return:
185     return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
186 }
187
188 /***********************************************************************
189  *              unregister_interfaces
190  */
191 static HRESULT unregister_interfaces(struct regsvr_interface const *list)
192 {
193     LONG res = ERROR_SUCCESS;
194     HKEY interface_key;
195
196     res = RegOpenKeyExW(HKEY_CLASSES_ROOT, interface_keyname, 0,
197                         KEY_READ | KEY_WRITE, &interface_key);
198     if (res == ERROR_FILE_NOT_FOUND) return S_OK;
199     if (res != ERROR_SUCCESS) goto error_return;
200
201     for (; res == ERROR_SUCCESS && list->iid; ++list) {
202         WCHAR buf[39];
203
204         StringFromGUID2(list->iid, buf, 39);
205         res = RegDeleteTreeW(interface_key, buf);
206         if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
207     }
208
209     RegCloseKey(interface_key);
210 error_return:
211     return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
212 }
213
214 /***********************************************************************
215  *              register_coclasses
216  */
217 static HRESULT register_coclasses(struct regsvr_coclass const *list)
218 {
219     LONG res = ERROR_SUCCESS;
220     HKEY coclass_key;
221
222     res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0,
223                           KEY_READ | KEY_WRITE, NULL, &coclass_key, NULL);
224     if (res != ERROR_SUCCESS) goto error_return;
225
226     for (; res == ERROR_SUCCESS && list->clsid; ++list) {
227         WCHAR buf[39];
228         HKEY clsid_key;
229
230         StringFromGUID2(list->clsid, buf, 39);
231         res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
232                               KEY_READ | KEY_WRITE, NULL, &clsid_key, NULL);
233         if (res != ERROR_SUCCESS) goto error_close_coclass_key;
234
235         if (list->name) {
236             res = RegSetValueExA(clsid_key, NULL, 0, REG_SZ,
237                                  (CONST BYTE*)(list->name),
238                                  strlen(list->name) + 1);
239             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
240         }
241
242         if (list->ips) {
243             res = register_key_defvalueA(clsid_key, ips_keyname, list->ips);
244             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
245         }
246
247         if (list->ips32) {
248             HKEY ips32_key;
249
250             res = RegCreateKeyExW(clsid_key, ips32_keyname, 0, NULL, 0,
251                                   KEY_READ | KEY_WRITE, NULL,
252                                   &ips32_key, NULL);
253             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
254
255             res = RegSetValueExA(ips32_key, NULL, 0, REG_SZ,
256                                  (CONST BYTE*)list->ips32,
257                                  lstrlenA(list->ips32) + 1);
258             if (res == ERROR_SUCCESS && list->ips32_tmodel)
259                 res = RegSetValueExA(ips32_key, tmodel_valuename, 0, REG_SZ,
260                                      (CONST BYTE*)list->ips32_tmodel,
261                                      strlen(list->ips32_tmodel) + 1);
262             RegCloseKey(ips32_key);
263             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
264         }
265
266         if (list->progid) {
267             res = register_key_defvalueA(clsid_key, progid_keyname,
268                                          list->progid);
269             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
270
271             res = register_progid(buf, list->progid, list->name);
272             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
273         }
274
275     error_close_clsid_key:
276         RegCloseKey(clsid_key);
277     }
278
279 error_close_coclass_key:
280     RegCloseKey(coclass_key);
281 error_return:
282     return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
283 }
284
285 /***********************************************************************
286  *              unregister_coclasses
287  */
288 static HRESULT unregister_coclasses(struct regsvr_coclass const *list)
289 {
290     LONG res = ERROR_SUCCESS;
291     HKEY coclass_key;
292
293     res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0,
294                         KEY_READ | KEY_WRITE, &coclass_key);
295     if (res == ERROR_FILE_NOT_FOUND) return S_OK;
296     if (res != ERROR_SUCCESS) goto error_return;
297
298     for (; res == ERROR_SUCCESS && list->clsid; ++list) {
299         WCHAR buf[39];
300
301         StringFromGUID2(list->clsid, buf, 39);
302         res = RegDeleteTreeW(coclass_key, buf);
303         if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
304         if (res != ERROR_SUCCESS) goto error_close_coclass_key;
305
306         if (list->progid) {
307             res = RegDeleteTreeA(HKEY_CLASSES_ROOT, list->progid);
308             if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
309             if (res != ERROR_SUCCESS) goto error_close_coclass_key;
310         }
311     }
312
313 error_close_coclass_key:
314     RegCloseKey(coclass_key);
315 error_return:
316     return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
317 }
318
319 /***********************************************************************
320  *              regsvr_key_guid
321  */
322 static LONG register_key_guid(HKEY base, WCHAR const *name, GUID const *guid)
323 {
324     WCHAR buf[39];
325
326     StringFromGUID2(guid, buf, 39);
327     return register_key_defvalueW(base, name, buf);
328 }
329
330 /***********************************************************************
331  *              regsvr_key_defvalueW
332  */
333 static LONG register_key_defvalueW(
334     HKEY base,
335     WCHAR const *name,
336     WCHAR const *value)
337 {
338     LONG res;
339     HKEY key;
340
341     res = RegCreateKeyExW(base, name, 0, NULL, 0,
342                           KEY_READ | KEY_WRITE, NULL, &key, NULL);
343     if (res != ERROR_SUCCESS) return res;
344     res = RegSetValueExW(key, NULL, 0, REG_SZ, (CONST BYTE*)value,
345                          (lstrlenW(value) + 1) * sizeof(WCHAR));
346     RegCloseKey(key);
347     return res;
348 }
349
350 /***********************************************************************
351  *              regsvr_key_defvalueA
352  */
353 static LONG register_key_defvalueA(
354     HKEY base,
355     WCHAR const *name,
356     char const *value)
357 {
358     LONG res;
359     HKEY key;
360
361     res = RegCreateKeyExW(base, name, 0, NULL, 0,
362                           KEY_READ | KEY_WRITE, NULL, &key, NULL);
363     if (res != ERROR_SUCCESS) return res;
364     res = RegSetValueExA(key, NULL, 0, REG_SZ, (CONST BYTE*)value,
365                          lstrlenA(value) + 1);
366     RegCloseKey(key);
367     return res;
368 }
369
370 /***********************************************************************
371  *              regsvr_progid
372  */
373 static LONG register_progid(
374     WCHAR const *clsid,
375     char const *progid,
376     char const *name)
377 {
378     LONG res;
379     HKEY progid_key;
380
381     res = RegCreateKeyExA(HKEY_CLASSES_ROOT, progid, 0,
382                           NULL, 0, KEY_READ | KEY_WRITE, NULL,
383                           &progid_key, NULL);
384     if (res != ERROR_SUCCESS) return res;
385
386     if (name) {
387         res = RegSetValueExA(progid_key, NULL, 0, REG_SZ,
388                              (CONST BYTE*)name, strlen(name) + 1);
389         if (res != ERROR_SUCCESS) goto error_close_progid_key;
390     }
391
392     if (clsid) {
393         res = register_key_defvalueW(progid_key, clsid_keyname, clsid);
394         if (res != ERROR_SUCCESS) goto error_close_progid_key;
395     }
396
397 error_close_progid_key:
398     RegCloseKey(progid_key);
399     return res;
400 }
401
402 /***********************************************************************
403  *              coclass list
404  */
405 static GUID const CLSID_StdOleLink = {
406     0x00000300, 0x0000, 0x0000, {0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46} };
407
408 static GUID const CLSID_PackagerMoniker = {
409     0x00000308, 0x0000, 0x0000, {0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46} };
410
411 static GUID const CLSID_PSFactoryBuffer_actxprxy = {
412     0xB8DA6310, 0xE19B, 0x11D0, {0x93,0x3C,0x00,0xA0,0xC9,0x0D,0xCA,0xA9} };
413
414 extern GUID const CLSID_Picture_Metafile;
415 extern GUID const CLSID_Picture_Dib;
416
417 static struct regsvr_coclass const coclass_list[] = {
418     {   &CLSID_StdOleLink,
419         "StdOleLink",
420         NULL,
421         "ole32.dll",
422         NULL
423     },
424     {   &CLSID_FileMoniker,
425         "FileMoniker",
426         NULL,
427         "ole32.dll",
428         "Both",
429         "file"
430     },
431     {   &CLSID_ItemMoniker,
432         "ItemMoniker",
433         NULL,
434         "ole32.dll",
435         "Both"
436     },
437     {   &CLSID_AntiMoniker,
438         "AntiMoniker",
439         NULL,
440         "ole32.dll",
441         "Both"
442     },
443     {   &CLSID_PointerMoniker,
444         "PointerMoniker",
445         NULL,
446         "ole32.dll",
447         "Both"
448     },
449     {   &CLSID_PackagerMoniker,
450         "PackagerMoniker",
451         NULL,
452         "ole32.dll",
453         "Both"
454     },
455     {   &CLSID_CompositeMoniker,
456         "CompositeMoniker",
457         NULL,
458         "ole32.dll",
459         "Both"
460     },
461     {   &CLSID_DfMarshal,
462         "DfMarshal",
463         NULL,
464         "ole32.dll",
465         "Both"
466     },
467     {   &CLSID_Picture_Metafile,
468         "Picture (Metafile)",
469         NULL,
470         "ole32.dll",
471         NULL,
472         "StaticMetafile"
473     },
474     {   &CLSID_Picture_Dib,
475         "Picture (Device Independent Bitmap)",
476         NULL,
477         "ole32.dll",
478         NULL,
479         "StaticDib"
480     },
481     {   &CLSID_ClassMoniker,
482         "ClassMoniker",
483         NULL,
484         "ole32.dll",
485         "Both",
486         "CLSID"
487     },
488     {   &CLSID_PSFactoryBuffer,
489         "PSFactoryBuffer",
490         NULL,
491         "ole32.dll",
492         "Both"
493     },
494     {   &CLSID_StdGlobalInterfaceTable,
495         "StdGlobalInterfaceTable",
496         NULL,
497         "ole32.dll",
498         "Apartment"
499     },
500     {   &CLSID_StdComponentCategoriesMgr,
501         "Component Categories Manager",
502         NULL,
503         "ole32.dll",
504         "Both"
505     },
506     { NULL }                    /* list terminator */
507 };
508
509 /***********************************************************************
510  *              interface list
511  */
512
513 #define INTERFACE_ENTRY(interface, base, clsid32) { &IID_##interface, #interface, base, sizeof(interface##Vtbl)/sizeof(void*), NULL, clsid32 }
514 #define BAS_INTERFACE_ENTRY(interface, base) INTERFACE_ENTRY(interface, &IID_##base, NULL)
515 #define ACTX_INTERFACE_ENTRY(interface) INTERFACE_ENTRY(interface, NULL, &CLSID_PSFactoryBuffer_actxprxy)
516 #define LCL_INTERFACE_ENTRY(interface) INTERFACE_ENTRY(interface, NULL, NULL)
517
518 static const struct regsvr_interface interface_list[] = {
519     LCL_INTERFACE_ENTRY(IUnknown),
520     LCL_INTERFACE_ENTRY(IMalloc),
521     LCL_INTERFACE_ENTRY(IMarshal),
522     BAS_INTERFACE_ENTRY(IMoniker, IPersistStream),
523     LCL_INTERFACE_ENTRY(IMessageFilter),
524     LCL_INTERFACE_ENTRY(IStdMarshalInfo),
525     LCL_INTERFACE_ENTRY(IExternalConnection),
526     LCL_INTERFACE_ENTRY(IMallocSpy),
527     LCL_INTERFACE_ENTRY(IMultiQI),
528     BAS_INTERFACE_ENTRY(IPersistStream, IPersist),
529     BAS_INTERFACE_ENTRY(IPersistStorage, IPersist),
530     BAS_INTERFACE_ENTRY(IPersistFile, IPersist),
531     LCL_INTERFACE_ENTRY(IDataAdviseHolder),
532     LCL_INTERFACE_ENTRY(IOleAdviseHolder),
533     BAS_INTERFACE_ENTRY(IOleInPlaceObject, IOleWindow),
534     BAS_INTERFACE_ENTRY(IOleInPlaceUIWindow, IOleWindow),
535     BAS_INTERFACE_ENTRY(IOleInPlaceActiveObject, IOleWindow),
536     BAS_INTERFACE_ENTRY(IOleInPlaceSite, IOleWindow),
537     BAS_INTERFACE_ENTRY(IOleContainer, IParseDisplayName),
538     BAS_INTERFACE_ENTRY(IOleItemContainer, IOleContainer),
539     LCL_INTERFACE_ENTRY(IDropSource),
540     BAS_INTERFACE_ENTRY(IAdviseSink2, IAdviseSink),
541     BAS_INTERFACE_ENTRY(IViewObject2, IViewObject),
542     BAS_INTERFACE_ENTRY(IOleCache2, IOleCache),
543     LCL_INTERFACE_ENTRY(IClientSecurity),
544     LCL_INTERFACE_ENTRY(IServerSecurity),
545     ACTX_INTERFACE_ENTRY(IEnumGUID),
546     ACTX_INTERFACE_ENTRY(IEnumCATEGORYINFO),
547     ACTX_INTERFACE_ENTRY(ICatRegister),
548     ACTX_INTERFACE_ENTRY(ICatInformation),
549     { NULL }                    /* list terminator */
550 };
551
552 /***********************************************************************
553  *              DllRegisterServer (OLE32.@)
554  */
555 HRESULT WINAPI DllRegisterServer(void)
556 {
557     HRESULT hr;
558
559     TRACE("\n");
560
561     hr = OLE32_DllRegisterServer();
562     if (SUCCEEDED(hr))
563         hr = register_coclasses(coclass_list);
564     if (SUCCEEDED(hr))
565         hr = register_interfaces(interface_list);
566     return hr;
567 }
568
569 /***********************************************************************
570  *              DllUnregisterServer (OLE32.@)
571  */
572 HRESULT WINAPI DllUnregisterServer(void)
573 {
574     HRESULT hr;
575
576     TRACE("\n");
577
578     hr = unregister_coclasses(coclass_list);
579     if (SUCCEEDED(hr))
580         hr = unregister_interfaces(interface_list);
581     if (SUCCEEDED(hr))
582         hr = OLE32_DllUnregisterServer();
583     return hr;
584 }