mshtml: Implement IHTMLWindow2::get_top.
[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 extern GUID const CLSID_Picture_Metafile;
412 extern GUID const CLSID_Picture_Dib;
413
414 static struct regsvr_coclass const coclass_list[] = {
415     {   &CLSID_StdOleLink,
416         "StdOleLink",
417         NULL,
418         "ole32.dll",
419         NULL
420     },
421     {   &CLSID_FileMoniker,
422         "FileMoniker",
423         NULL,
424         "ole32.dll",
425         "Both",
426         "file"
427     },
428     {   &CLSID_ItemMoniker,
429         "ItemMoniker",
430         NULL,
431         "ole32.dll",
432         "Both"
433     },
434     {   &CLSID_AntiMoniker,
435         "AntiMoniker",
436         NULL,
437         "ole32.dll",
438         "Both"
439     },
440     {   &CLSID_PointerMoniker,
441         "PointerMoniker",
442         NULL,
443         "ole32.dll",
444         "Both"
445     },
446     {   &CLSID_PackagerMoniker,
447         "PackagerMoniker",
448         NULL,
449         "ole32.dll",
450         "Both"
451     },
452     {   &CLSID_CompositeMoniker,
453         "CompositeMoniker",
454         NULL,
455         "ole32.dll",
456         "Both"
457     },
458     {   &CLSID_DfMarshal,
459         "DfMarshal",
460         NULL,
461         "ole32.dll",
462         "Both"
463     },
464     {   &CLSID_Picture_Metafile,
465         "Picture (Metafile)",
466         NULL,
467         "ole32.dll",
468         NULL,
469         "StaticMetafile"
470     },
471     {   &CLSID_Picture_Dib,
472         "Picture (Device Independent Bitmap)",
473         NULL,
474         "ole32.dll",
475         NULL,
476         "StaticDib"
477     },
478     {   &CLSID_ClassMoniker,
479         "ClassMoniker",
480         NULL,
481         "ole32.dll",
482         "Both",
483         "CLSID"
484     },
485     {   &CLSID_PSFactoryBuffer,
486         "PSFactoryBuffer",
487         NULL,
488         "ole32.dll",
489         "Both"
490     },
491     {   &CLSID_StdGlobalInterfaceTable,
492         "StdGlobalInterfaceTable",
493         NULL,
494         "ole32.dll",
495         "Apartment"
496     },
497     {   &CLSID_StdComponentCategoriesMgr,
498         "Component Categories Manager",
499         NULL,
500         "ole32.dll",
501         "Both"
502     },
503     { NULL }                    /* list terminator */
504 };
505
506 /***********************************************************************
507  *              interface list
508  */
509
510 #define INTERFACE_ENTRY(interface, base) { &IID_##interface, #interface, base, sizeof(interface##Vtbl)/sizeof(void*), NULL, NULL }
511
512 static const struct regsvr_interface interface_list[] = {
513     INTERFACE_ENTRY( IUnknown, NULL ),
514     INTERFACE_ENTRY( IMalloc, NULL ),
515     INTERFACE_ENTRY( IMarshal, NULL ),
516     INTERFACE_ENTRY( IMoniker, &IID_IPersistStream ),
517     INTERFACE_ENTRY( IMessageFilter, NULL ),
518     INTERFACE_ENTRY( IStdMarshalInfo, NULL ),
519     INTERFACE_ENTRY( IExternalConnection, NULL ),
520     INTERFACE_ENTRY( IMallocSpy, NULL ),
521     INTERFACE_ENTRY( IMultiQI, NULL ),
522     INTERFACE_ENTRY( IPersistStream, &IID_IPersist ),
523     INTERFACE_ENTRY( IPersistStorage, &IID_IPersist ),
524     INTERFACE_ENTRY( IPersistFile, &IID_IPersist ),
525     INTERFACE_ENTRY( IDataAdviseHolder, NULL ),
526     INTERFACE_ENTRY( IOleAdviseHolder, NULL ),
527     INTERFACE_ENTRY( IOleInPlaceObject, &IID_IOleWindow ),
528     INTERFACE_ENTRY( IOleInPlaceUIWindow, &IID_IOleWindow ),
529     INTERFACE_ENTRY( IOleInPlaceActiveObject, &IID_IOleWindow ),
530     INTERFACE_ENTRY( IOleInPlaceSite, &IID_IOleWindow ),
531     INTERFACE_ENTRY( IOleContainer, &IID_IParseDisplayName ),
532     INTERFACE_ENTRY( IOleItemContainer, &IID_IOleContainer ),
533     INTERFACE_ENTRY( IDropSource, NULL ),
534     INTERFACE_ENTRY( IAdviseSink2, &IID_IAdviseSink ),
535     INTERFACE_ENTRY( IViewObject2, &IID_IViewObject ),
536     INTERFACE_ENTRY( IOleCache2, &IID_IOleCache ),
537     INTERFACE_ENTRY( IClientSecurity, NULL ),
538     INTERFACE_ENTRY( IServerSecurity, NULL ),
539     { NULL }                    /* list terminator */
540 };
541
542 /***********************************************************************
543  *              DllRegisterServer (OLE32.@)
544  */
545 HRESULT WINAPI DllRegisterServer(void)
546 {
547     HRESULT hr;
548
549     TRACE("\n");
550
551     hr = OLE32_DllRegisterServer();
552     if (SUCCEEDED(hr))
553         hr = register_coclasses(coclass_list);
554     if (SUCCEEDED(hr))
555         hr = register_interfaces(interface_list);
556     return hr;
557 }
558
559 /***********************************************************************
560  *              DllUnregisterServer (OLE32.@)
561  */
562 HRESULT WINAPI DllUnregisterServer(void)
563 {
564     HRESULT hr;
565
566     TRACE("\n");
567
568     hr = unregister_coclasses(coclass_list);
569     if (SUCCEEDED(hr))
570         hr = unregister_interfaces(interface_list);
571     if (SUCCEEDED(hr))
572         hr = OLE32_DllUnregisterServer();
573     return hr;
574 }