msi: Add tests for the RegLocator part of the AppSearch action.
[wine] / dlls / oleaut32 / regsvr.c
1 /*
2  *      self-registerable dll functions for oleaut32.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 <stdarg.h>
22 #include <string.h>
23
24 #include "windef.h"
25 #include "winbase.h"
26 #include "winuser.h"
27 #include "winreg.h"
28 #include "winerror.h"
29
30 #include "ole2.h"
31 #include "olectl.h"
32 #include "oleauto.h"
33 #include "initguid.h"
34 #include "typelib.h"
35
36 #include "wine/debug.h"
37
38 WINE_DEFAULT_DEBUG_CHANNEL(ole);
39
40 /*
41  * Near the bottom of this file are the exported DllRegisterServer and
42  * DllUnregisterServer, which make all this worthwhile.
43  */
44
45 /***********************************************************************
46  *              interface for self-registering
47  */
48 struct regsvr_interface
49 {
50     IID const *iid;             /* NULL for end of list */
51     LPCSTR name;                /* can be NULL to omit */
52     IID const *base_iid;        /* can be NULL to omit */
53     int num_methods;            /* can be <0 to omit */
54     CLSID const *ps_clsid;      /* can be NULL to omit */
55     CLSID const *ps_clsid32;    /* can be NULL to omit */
56 };
57
58 static HRESULT register_interfaces(struct regsvr_interface const *list);
59 static HRESULT unregister_interfaces(struct regsvr_interface const *list);
60
61 struct regsvr_coclass
62 {
63     CLSID const *clsid;         /* NULL for end of list */
64     LPCSTR name;                /* can be NULL to omit */
65     LPCSTR ips;                 /* can be NULL to omit */
66     LPCSTR ips32;               /* can be NULL to omit */
67     LPCSTR ips32_tmodel;        /* can be NULL to omit */
68     LPCSTR clsid_str;           /* can be NULL to omit */
69     LPCSTR progid;              /* can be NULL to omit */
70 };
71
72 static HRESULT register_coclasses(struct regsvr_coclass const *list);
73 static HRESULT unregister_coclasses(struct regsvr_coclass const *list);
74
75 /***********************************************************************
76  *              static string constants
77  */
78 static WCHAR const interface_keyname[10] = {
79     'I', 'n', 't', 'e', 'r', 'f', 'a', 'c', 'e', 0 };
80 static WCHAR const base_ifa_keyname[14] = {
81     'B', 'a', 's', 'e', 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c',
82     'e', 0 };
83 static WCHAR const num_methods_keyname[11] = {
84     'N', 'u', 'm', 'M', 'e', 't', 'h', 'o', 'd', 's', 0 };
85 static WCHAR const ps_clsid_keyname[15] = {
86     'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
87     'i', 'd', 0 };
88 static WCHAR const ps_clsid32_keyname[17] = {
89     'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
90     'i', 'd', '3', '2', 0 };
91 static WCHAR const clsid_keyname[6] = {
92     'C', 'L', 'S', 'I', 'D', 0 };
93 static WCHAR const ips_keyname[13] = {
94     'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
95     0 };
96 static WCHAR const ips32_keyname[15] = {
97     'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
98     '3', '2', 0 };
99 static WCHAR const progid_keyname[7] = {
100     'P', 'r', 'o', 'g', 'I', 'D', 0 };
101 static char const tmodel_valuename[] = "ThreadingModel";
102
103 /***********************************************************************
104  *              static helper functions
105  */
106 static LONG register_key_guid(HKEY base, WCHAR const *name, GUID const *guid);
107 static LONG register_key_defvalueW(HKEY base, WCHAR const *name,
108                                    WCHAR const *value);
109 static LONG register_key_defvalueA(HKEY base, WCHAR const *name,
110                                    char const *value);
111
112 /***********************************************************************
113  *              register_interfaces
114  */
115 static HRESULT register_interfaces(struct regsvr_interface const *list)
116 {
117     LONG res = ERROR_SUCCESS;
118     HKEY interface_key;
119
120     res = RegCreateKeyExW(HKEY_CLASSES_ROOT, interface_keyname, 0, NULL, 0,
121                           KEY_READ | KEY_WRITE, NULL, &interface_key, NULL);
122     if (res != ERROR_SUCCESS) goto error_return;
123
124     for (; res == ERROR_SUCCESS && list->iid; ++list) {
125         WCHAR buf[39];
126         HKEY iid_key;
127
128         StringFromGUID2(list->iid, buf, 39);
129         res = RegCreateKeyExW(interface_key, buf, 0, NULL, 0,
130                               KEY_READ | KEY_WRITE, NULL, &iid_key, NULL);
131         if (res != ERROR_SUCCESS) goto error_close_interface_key;
132
133         if (list->name) {
134             res = RegSetValueExA(iid_key, NULL, 0, REG_SZ,
135                                  (CONST BYTE*)(list->name),
136                                  strlen(list->name) + 1);
137             if (res != ERROR_SUCCESS) goto error_close_iid_key;
138         }
139
140         if (list->base_iid) {
141             res = register_key_guid(iid_key, base_ifa_keyname, list->base_iid);
142             if (res != ERROR_SUCCESS) goto error_close_iid_key;
143         }
144
145         if (0 <= list->num_methods) {
146             static WCHAR const fmt[3] = { '%', 'd', 0 };
147             HKEY key;
148
149             res = RegCreateKeyExW(iid_key, num_methods_keyname, 0, NULL, 0,
150                                   KEY_READ | KEY_WRITE, NULL, &key, NULL);
151             if (res != ERROR_SUCCESS) goto error_close_iid_key;
152
153             wsprintfW(buf, fmt, list->num_methods);
154             res = RegSetValueExW(key, NULL, 0, REG_SZ,
155                                  (CONST BYTE*)buf,
156                                  (lstrlenW(buf) + 1) * sizeof(WCHAR));
157             RegCloseKey(key);
158
159             if (res != ERROR_SUCCESS) goto error_close_iid_key;
160         }
161
162         if (list->ps_clsid) {
163             res = register_key_guid(iid_key, ps_clsid_keyname, list->ps_clsid);
164             if (res != ERROR_SUCCESS) goto error_close_iid_key;
165         }
166
167         if (list->ps_clsid32) {
168             res = register_key_guid(iid_key, ps_clsid32_keyname, list->ps_clsid32);
169             if (res != ERROR_SUCCESS) goto error_close_iid_key;
170         }
171
172     error_close_iid_key:
173         RegCloseKey(iid_key);
174     }
175
176 error_close_interface_key:
177     RegCloseKey(interface_key);
178 error_return:
179     return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
180 }
181
182 /***********************************************************************
183  *              unregister_interfaces
184  */
185 static HRESULT unregister_interfaces(struct regsvr_interface const *list)
186 {
187     LONG res = ERROR_SUCCESS;
188     HKEY interface_key;
189
190     res = RegOpenKeyExW(HKEY_CLASSES_ROOT, interface_keyname, 0,
191                         KEY_READ | KEY_WRITE, &interface_key);
192     if (res == ERROR_FILE_NOT_FOUND) return S_OK;
193     if (res != ERROR_SUCCESS) goto error_return;
194
195     for (; res == ERROR_SUCCESS && list->iid; ++list) {
196         WCHAR buf[39];
197
198         StringFromGUID2(list->iid, buf, 39);
199         res = RegDeleteTreeW(interface_key, buf);
200         if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
201     }
202
203     RegCloseKey(interface_key);
204 error_return:
205     return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
206 }
207
208 /***********************************************************************
209  *              register_coclasses
210  */
211 static HRESULT register_coclasses(struct regsvr_coclass const *list)
212 {
213     LONG res = ERROR_SUCCESS;
214     HKEY coclass_key;
215
216     res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0,
217                           KEY_READ | KEY_WRITE, NULL, &coclass_key, NULL);
218     if (res != ERROR_SUCCESS) goto error_return;
219
220     for (; res == ERROR_SUCCESS && list->clsid; ++list) {
221         WCHAR buf[39];
222         HKEY clsid_key;
223
224         StringFromGUID2(list->clsid, buf, 39);
225         res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
226                               KEY_READ | KEY_WRITE, NULL, &clsid_key, NULL);
227         if (res != ERROR_SUCCESS) goto error_close_coclass_key;
228
229         if (list->name) {
230             res = RegSetValueExA(clsid_key, NULL, 0, REG_SZ,
231                                  (CONST BYTE*)(list->name),
232                                  strlen(list->name) + 1);
233             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
234         }
235
236         if (list->ips) {
237             res = register_key_defvalueA(clsid_key, ips_keyname, list->ips);
238             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
239         }
240
241         if (list->ips32) {
242             HKEY ips32_key;
243
244             res = RegCreateKeyExW(clsid_key, ips32_keyname, 0, NULL, 0,
245                                   KEY_READ | KEY_WRITE, NULL,
246                                   &ips32_key, NULL);
247             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
248
249             res = RegSetValueExA(ips32_key, NULL, 0, REG_SZ,
250                                  (CONST BYTE*)list->ips32,
251                                  lstrlenA(list->ips32) + 1);
252             if (res == ERROR_SUCCESS && list->ips32_tmodel)
253                 res = RegSetValueExA(ips32_key, tmodel_valuename, 0, REG_SZ,
254                                      (CONST BYTE*)list->ips32_tmodel,
255                                      strlen(list->ips32_tmodel) + 1);
256             RegCloseKey(ips32_key);
257             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
258         }
259
260         if (list->clsid_str) {
261             res = register_key_defvalueA(clsid_key, clsid_keyname,
262                                          list->clsid_str);
263             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
264         }
265
266         if (list->progid) {
267             HKEY progid_key;
268
269             res = register_key_defvalueA(clsid_key, progid_keyname,
270                                          list->progid);
271             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
272
273             res = RegCreateKeyExA(HKEY_CLASSES_ROOT, list->progid, 0,
274                                   NULL, 0, KEY_READ | KEY_WRITE, NULL,
275                                   &progid_key, NULL);
276             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
277
278             res = register_key_defvalueW(progid_key, clsid_keyname, buf);
279             RegCloseKey(progid_key);
280             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
281         }
282
283     error_close_clsid_key:
284         RegCloseKey(clsid_key);
285     }
286
287 error_close_coclass_key:
288     RegCloseKey(coclass_key);
289 error_return:
290     return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
291 }
292
293 /***********************************************************************
294  *              unregister_coclasses
295  */
296 static HRESULT unregister_coclasses(struct regsvr_coclass const *list)
297 {
298     LONG res = ERROR_SUCCESS;
299     HKEY coclass_key;
300
301     res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0,
302                         KEY_READ | KEY_WRITE, &coclass_key);
303     if (res == ERROR_FILE_NOT_FOUND) return S_OK;
304     if (res != ERROR_SUCCESS) goto error_return;
305
306     for (; res == ERROR_SUCCESS && list->clsid; ++list) {
307         WCHAR buf[39];
308
309         StringFromGUID2(list->clsid, buf, 39);
310         res = RegDeleteTreeW(coclass_key, buf);
311         if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
312         if (res != ERROR_SUCCESS) goto error_close_coclass_key;
313
314         if (list->progid) {
315             res = RegDeleteTreeA(HKEY_CLASSES_ROOT, list->progid);
316             if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
317             if (res != ERROR_SUCCESS) goto error_close_coclass_key;
318         }
319     }
320
321 error_close_coclass_key:
322     RegCloseKey(coclass_key);
323 error_return:
324     return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
325 }
326
327 /***********************************************************************
328  *              regsvr_key_guid
329  */
330 static LONG register_key_guid(HKEY base, WCHAR const *name, GUID const *guid)
331 {
332     WCHAR buf[39];
333
334     StringFromGUID2(guid, buf, 39);
335     return register_key_defvalueW(base, name, buf);
336 }
337
338 /***********************************************************************
339  *              regsvr_key_defvalueW
340  */
341 static LONG register_key_defvalueW(
342     HKEY base,
343     WCHAR const *name,
344     WCHAR const *value)
345 {
346     LONG res;
347     HKEY key;
348
349     res = RegCreateKeyExW(base, name, 0, NULL, 0,
350                           KEY_READ | KEY_WRITE, NULL, &key, NULL);
351     if (res != ERROR_SUCCESS) return res;
352     res = RegSetValueExW(key, NULL, 0, REG_SZ, (CONST BYTE*)value,
353                          (lstrlenW(value) + 1) * sizeof(WCHAR));
354     RegCloseKey(key);
355     return res;
356 }
357
358 /***********************************************************************
359  *              regsvr_key_defvalueA
360  */
361 static LONG register_key_defvalueA(
362     HKEY base,
363     WCHAR const *name,
364     char const *value)
365 {
366     LONG res;
367     HKEY key;
368
369     res = RegCreateKeyExW(base, name, 0, NULL, 0,
370                           KEY_READ | KEY_WRITE, NULL, &key, NULL);
371     if (res != ERROR_SUCCESS) return res;
372     res = RegSetValueExA(key, NULL, 0, REG_SZ, (CONST BYTE*)value,
373                          lstrlenA(value) + 1);
374     RegCloseKey(key);
375     return res;
376 }
377
378 /***********************************************************************
379  *              coclass list
380  */
381 static GUID const CLSID_RecordInfo = {
382     0x0000002F, 0x0000, 0x0000, {0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46} };
383
384 static GUID const CLSID_OldFont = {
385     0x46763EE0, 0xCAB2, 0x11CE, {0x8C,0x20,0x00,0xAA,0x00,0x51,0xE5,0xD4} };
386
387 static GUID const CLSID_PSFactoryBuffer = {
388     0xB196B286, 0xBAB4, 0x101A, {0xB6,0x9C,0x00,0xAA,0x00,0x34,0x1D,0x07} };
389
390 static struct regsvr_coclass const coclass_list[] = {
391     {   &CLSID_RecordInfo,
392         "CLSID_RecordInfo",
393         NULL,
394         "oleaut32.dll",
395         "Both"
396     },
397     {   &CLSID_PSDispatch,
398         "PSDispatch",
399         "ole2disp.dll",
400         "oleaut32.dll",
401         "Both"
402     },
403     {   &CLSID_StdFont,
404         "CLSID_StdFont",
405         NULL,
406         "oleaut32.dll",
407         "Both",
408         "Standard Font",
409         "StdFont"
410     },
411     {   &CLSID_StdPicture,
412         "CLSID_StdPict",
413         NULL,
414         "oleaut32.dll",
415         "Apartment",
416         "Standard Picture",
417         "StdPicture"
418     },
419     {   &CLSID_PSEnumVariant,
420         "PSEnumVariant",
421         "ole2disp.dll",
422         "oleaut32.dll",
423         "Both"
424     },
425     {   &CLSID_PSTypeInfo,
426         "PSTypeInfo",
427         "ole2disp.dll",
428         "oleaut32.dll",
429         "Both"
430     },
431     {   &CLSID_PSTypeLib,
432         "PSTypeLib",
433         "ole2disp.dll",
434         "oleaut32.dll",
435         "Both"
436     },
437     {   &CLSID_PSOAInterface,
438         "PSOAInterface",
439         "ole2disp.dll",
440         "oleaut32.dll",
441         "Both"
442     },
443     {   &CLSID_PSTypeComp,
444         "PSTypeComp",
445         "ole2disp.dll",
446         "oleaut32.dll",
447         "Both"
448     },
449     {   &CLSID_OldFont,
450         "Obsolete Font",
451         NULL,
452         "oleaut32.dll",
453         NULL,
454         "Obsolete Font",
455         "OldFont"
456     },
457     {   &CLSID_PSFactoryBuffer,
458         "PSFactoryBuffer",
459         NULL,
460         "oleaut32.dll",
461         "Both"
462     },
463     { NULL }                    /* list terminator */
464 };
465
466 /***********************************************************************
467  *              interface list
468  */
469 static struct regsvr_interface const interface_list[] = {
470     {   &IID_IDispatch,
471         "IDispatch",
472         NULL,
473         7,
474         &CLSID_PSDispatch,
475         &CLSID_PSDispatch
476     },
477     {   &IID_ITypeInfo,
478         "ITypeInfo",
479         NULL,
480         22,
481         &CLSID_PSTypeInfo,
482         &CLSID_PSTypeInfo
483     },
484     {   &IID_ITypeLib,
485         "ITypeLib",
486         NULL,
487         13,
488         &CLSID_PSTypeLib,
489         &CLSID_PSTypeLib
490     },
491     {   &IID_ITypeComp,
492         "ITypeComp",
493         NULL,
494         5,
495         &CLSID_PSTypeComp,
496         &CLSID_PSTypeComp
497     },
498     {   &IID_IEnumVARIANT,
499         "IEnumVARIANT",
500         NULL,
501         15,
502         &CLSID_PSEnumVariant,
503         &CLSID_PSEnumVariant
504     },
505     {   &IID_ICreateTypeInfo,
506         "ICreateTypeInfo",
507         NULL,
508         26,
509         NULL,
510         NULL
511     },
512     {   &IID_ICreateTypeLib,
513         "ICreateTypeLib",
514         NULL,
515         13,
516         NULL,
517         NULL
518     },
519     {   &IID_ITypeInfo2,
520         "ITypeInfo2",
521         NULL,
522         32,
523         NULL,
524         &CLSID_PSDispatch
525     },
526     {   &IID_ITypeLib2,
527         "ITypeLib2",
528         NULL,
529         16,
530         NULL,
531         &CLSID_PSDispatch
532     },
533     {   &IID_IPropertyPage2,
534         "IPropertyPage2",
535         NULL,
536         15,
537         NULL,
538         &CLSID_PSFactoryBuffer
539     },
540     {   &IID_IErrorInfo,
541         "IErrorInfo",
542         NULL,
543         8,
544         NULL,
545         &CLSID_PSFactoryBuffer
546     },
547     {   &IID_ICreateErrorInfo,
548         "ICreateErrorInfo",
549         NULL,
550         8,
551         NULL,
552         &CLSID_PSFactoryBuffer
553     },
554     {   &IID_IPersistPropertyBag2,
555         "IPersistPropertyBag2",
556         NULL,
557         8,
558         NULL,
559         &CLSID_PSFactoryBuffer
560     },
561     {   &IID_IPropertyBag2,
562         "IPropertyBag2",
563         NULL,
564         8,
565         NULL,
566         &CLSID_PSFactoryBuffer
567     },
568     {   &IID_IErrorLog,
569         "IErrorLog",
570         NULL,
571         4,
572         NULL,
573         &CLSID_PSFactoryBuffer
574     },
575     {   &IID_IPerPropertyBrowsing,
576         "IPerPropertyBrowsing",
577         NULL,
578         7,
579         NULL,
580         &CLSID_PSFactoryBuffer
581     },
582     {   &IID_IPersistPropertyBag,
583         "IPersistPropertyBag",
584         NULL,
585         7,
586         NULL,
587         &CLSID_PSFactoryBuffer
588     },
589     {   &IID_IAdviseSinkEx,
590         "IAdviseSinkEx",
591         NULL,
592         9,
593         NULL,
594         &CLSID_PSFactoryBuffer
595     },
596     {   &IID_IFontEventsDisp,
597         "FontEvents",
598         NULL,
599         7,
600         NULL,
601         &CLSID_PSDispatch
602     },
603     {   &IID_IPropertyBag,
604         "IPropertyBag",
605         NULL,
606         5,
607         NULL,
608         &CLSID_PSFactoryBuffer
609     },
610     {   &IID_IPointerInactive,
611         "IPointerInactive",
612         NULL,
613         6,
614         NULL,
615         &CLSID_PSFactoryBuffer
616     },
617     {   &IID_ISimpleFrameSite,
618         "ISimpleFrameSite",
619         NULL,
620         5,
621         NULL,
622         &CLSID_PSFactoryBuffer
623     },
624     {   &IID_IPicture,
625         "IPicture",
626         NULL,
627         17,
628         NULL,
629         &CLSID_PSFactoryBuffer
630     },
631     {   &IID_IPictureDisp,
632         "Picture",
633         NULL,
634         7,
635         NULL,
636         &CLSID_PSDispatch
637     },
638     {   &IID_IPersistStreamInit,
639         "IPersistStreamInit",
640         NULL,
641         9,
642         NULL,
643         &CLSID_PSFactoryBuffer
644     },
645     {   &IID_IOleUndoUnit,
646         "IOleUndoUnit",
647         NULL,
648         7,
649         NULL,
650         &CLSID_PSFactoryBuffer
651     },
652     {   &IID_IPropertyNotifySink,
653         "IPropertyNotifySink",
654         NULL,
655         5,
656         NULL,
657         &CLSID_PSFactoryBuffer
658     },
659     {   &IID_IOleInPlaceSiteEx,
660         "IOleInPlaceSiteEx",
661         NULL,
662         18,
663         NULL,
664         &CLSID_PSFactoryBuffer
665     },
666     {   &IID_IOleParentUndoUnit,
667         "IOleParentUndoUnit",
668         NULL,
669         12,
670         NULL,
671         &CLSID_PSFactoryBuffer
672     },
673     {   &IID_IProvideClassInfo2,
674         "IProvideClassInfo2",
675         NULL,
676         5,
677         NULL,
678         &CLSID_PSFactoryBuffer
679     },
680     {   &IID_IProvideMultipleClassInfo,
681         "IProvideMultipleClassInfo",
682         NULL,
683         7,
684         NULL,
685         &CLSID_PSFactoryBuffer
686     },
687     {   &IID_IProvideClassInfo,
688         "IProvideClassInfo",
689         NULL,
690         4,
691         NULL,
692         &CLSID_PSFactoryBuffer
693     },
694     {   &IID_IConnectionPointContainer,
695         "IConnectionPointContainer",
696         NULL,
697         5,
698         NULL,
699         &CLSID_PSFactoryBuffer
700     },
701     {   &IID_IEnumConnectionPoints,
702         "IEnumConnectionPoints",
703         NULL,
704         7,
705         NULL,
706         &CLSID_PSFactoryBuffer
707     },
708     {   &IID_IConnectionPoint,
709         "IConnectionPoint",
710         NULL,
711         8,
712         NULL,
713         &CLSID_PSFactoryBuffer
714     },
715     {   &IID_IEnumConnections,
716         "IEnumConnections",
717         NULL,
718         7,
719         NULL,
720         &CLSID_PSFactoryBuffer
721     },
722     {   &IID_IOleControl,
723         "IOleControl",
724         NULL,
725         7,
726         NULL,
727         &CLSID_PSFactoryBuffer
728     },
729     {   &IID_IOleControlSite,
730         "IOleControlSite",
731         NULL,
732         10,
733         NULL,
734         &CLSID_PSFactoryBuffer
735     },
736     {   &IID_ISpecifyPropertyPages,
737         "ISpecifyPropertyPages",
738         NULL,
739         4,
740         NULL,
741         &CLSID_PSFactoryBuffer
742     },
743     {   &IID_IPropertyPageSite,
744         "IPropertyPageSite",
745         NULL,
746         7,
747         NULL,
748         &CLSID_PSFactoryBuffer
749     },
750     {   &IID_IPropertyPage,
751         "IPropertyPage",
752         NULL,
753         14,
754         NULL,
755         &CLSID_PSFactoryBuffer
756     },
757     {   &IID_IClassFactory2,
758         "IClassFactory2",
759         NULL,
760         8,
761         NULL,
762         &CLSID_PSFactoryBuffer
763     },
764     {   &IID_IEnumOleUndoUnits,
765         "IEnumOleUndoUnits",
766         NULL,
767         7,
768         NULL,
769         &CLSID_PSFactoryBuffer
770     },
771     {   &IID_IPersistMemory,
772         "IPersistMemory",
773         NULL,
774         9,
775         NULL,
776         &CLSID_PSFactoryBuffer
777     },
778     {   &IID_IFont,
779         "IFont",
780         NULL,
781         27,
782         NULL,
783         &CLSID_PSFactoryBuffer
784     },
785     {   &IID_IFontDisp,
786         "Font",
787         NULL,
788         7,
789         NULL,
790         &CLSID_PSDispatch
791     },
792     {   &IID_IQuickActivate,
793         "IQuickActivate",
794         NULL,
795         6,
796         NULL,
797         &CLSID_PSFactoryBuffer
798     },
799     {   &IID_IOleUndoManager,
800         "IOleUndoManager",
801         NULL,
802         15,
803         NULL,
804         &CLSID_PSFactoryBuffer
805     },
806     {   &IID_IObjectWithSite,
807         "IObjectWithSite",
808         NULL,
809         5,
810         NULL,
811         &CLSID_PSFactoryBuffer
812     },
813     { NULL }                    /* list terminator */
814 };
815
816 /***********************************************************************
817  *              DllRegisterServer (OLEAUT32.@)
818  */
819 HRESULT WINAPI DllRegisterServer(void)
820 {
821     HRESULT hr;
822
823     TRACE("\n");
824
825     hr = register_coclasses(coclass_list);
826     if (SUCCEEDED(hr))
827         hr = register_interfaces(interface_list);
828     return hr;
829 }
830
831 /***********************************************************************
832  *              DllUnregisterServer (OLEAUT32.@)
833  */
834 HRESULT WINAPI DllUnregisterServer(void)
835 {
836     HRESULT hr;
837
838     TRACE("\n");
839
840     hr = unregister_coclasses(coclass_list);
841     if (SUCCEEDED(hr))
842         hr = unregister_interfaces(interface_list);
843     return hr;
844 }