shlwapi/tests: Make some variables static.
[wine] / dlls / windowscodecs / regsvr.c
1 /*
2  * Copyright 2009 Vincent Povirk for CodeWeavers
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18
19 #define NONAMELESSUNION
20 #define NONAMELESSSTRUCT
21 #define COBJMACROS
22 #include <stdarg.h>
23 #include <string.h>
24
25 #include "windef.h"
26 #include "winbase.h"
27 #include "wingdi.h"
28 #include "winuser.h"
29 #include "winreg.h"
30 #include "winerror.h"
31
32 #include "objbase.h"
33 #include "ocidl.h"
34 #include "wincodec.h"
35
36 #include "wine/debug.h"
37 #include "wine/unicode.h"
38
39 #include "wincodecs_private.h"
40
41 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
42
43 /***********************************************************************
44  *              interface for self-registering
45  */
46 struct regsvr_coclass
47 {
48     CLSID const *clsid;         /* NULL for end of list */
49     LPCSTR name;                /* can be NULL to omit */
50     LPCSTR ips;                 /* can be NULL to omit */
51     LPCSTR ips32;               /* can be NULL to omit */
52     LPCSTR ips32_tmodel;        /* can be NULL to omit */
53     LPCSTR progid;              /* can be NULL to omit */
54     LPCSTR viprogid;            /* can be NULL to omit */
55     LPCSTR progid_extra;        /* can be NULL to omit */
56 };
57
58 static HRESULT register_coclasses(struct regsvr_coclass const *list);
59 static HRESULT unregister_coclasses(struct regsvr_coclass const *list);
60
61 struct decoder_pattern
62 {
63     DWORD length;    /* 0 for end of list */
64     DWORD position;
65     const BYTE *pattern;
66     const BYTE *mask;
67     DWORD endofstream;
68 };
69
70 struct regsvr_decoder
71 {
72     CLSID const *clsid;         /* NULL for end of list */
73     LPCSTR author;
74     LPCSTR friendlyname;
75     LPCSTR version;
76     GUID const *vendor;
77     LPCSTR mimetypes;
78     LPCSTR extensions;
79     GUID const * const *formats;
80     const struct decoder_pattern *patterns;
81 };
82
83 static HRESULT register_decoders(struct regsvr_decoder const *list);
84 static HRESULT unregister_decoders(struct regsvr_decoder const *list);
85
86 struct regsvr_encoder
87 {
88     CLSID const *clsid;         /* NULL for end of list */
89     LPCSTR author;
90     LPCSTR friendlyname;
91     LPCSTR version;
92     GUID const *vendor;
93     LPCSTR mimetypes;
94     LPCSTR extensions;
95     GUID const * const *formats;
96 };
97
98 static HRESULT register_encoders(struct regsvr_encoder const *list);
99 static HRESULT unregister_encoders(struct regsvr_encoder const *list);
100
101 struct regsvr_converter
102 {
103     CLSID const *clsid;         /* NULL for end of list */
104     LPCSTR author;
105     LPCSTR friendlyname;
106     LPCSTR version;
107     GUID const *vendor;
108     GUID const * const *formats;
109 };
110
111 static HRESULT register_converters(struct regsvr_converter const *list);
112 static HRESULT unregister_converters(struct regsvr_converter const *list);
113
114 /***********************************************************************
115  *              static string constants
116  */
117 static WCHAR const clsid_keyname[6] = {
118     'C', 'L', 'S', 'I', 'D', 0 };
119 static WCHAR const curver_keyname[7] = {
120     'C', 'u', 'r', 'V', 'e', 'r', 0 };
121 static WCHAR const ips_keyname[13] = {
122     'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
123     0 };
124 static WCHAR const ips32_keyname[15] = {
125     'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
126     '3', '2', 0 };
127 static WCHAR const progid_keyname[7] = {
128     'P', 'r', 'o', 'g', 'I', 'D', 0 };
129 static WCHAR const viprogid_keyname[25] = {
130     'V', 'e', 'r', 's', 'i', 'o', 'n', 'I', 'n', 'd', 'e', 'p',
131     'e', 'n', 'd', 'e', 'n', 't', 'P', 'r', 'o', 'g', 'I', 'D',
132     0 };
133 static char const tmodel_valuename[] = "ThreadingModel";
134 static char const author_valuename[] = "Author";
135 static char const friendlyname_valuename[] = "FriendlyName";
136 static WCHAR const vendor_valuename[] = {'V','e','n','d','o','r',0};
137 static char const version_valuename[] = "Version";
138 static char const mimetypes_valuename[] = "MimeTypes";
139 static char const extensions_valuename[] = "FileExtensions";
140 static WCHAR const formats_keyname[] = {'F','o','r','m','a','t','s',0};
141 static WCHAR const patterns_keyname[] = {'P','a','t','t','e','r','n','s',0};
142 static WCHAR const instance_keyname[] = {'I','n','s','t','a','n','c','e',0};
143 static WCHAR const clsid_valuename[] = {'C','L','S','I','D',0};
144 static char const length_valuename[] = "Length";
145 static char const position_valuename[] = "Position";
146 static char const pattern_valuename[] = "Pattern";
147 static char const mask_valuename[] = "Mask";
148 static char const endofstream_valuename[] = "EndOfStream";
149 static WCHAR const pixelformats_keyname[] = {'P','i','x','e','l','F','o','r','m','a','t','s',0};
150
151 /***********************************************************************
152  *              static helper functions
153  */
154 static LONG register_key_defvalueW(HKEY base, WCHAR const *name,
155                                    WCHAR const *value);
156 static LONG register_key_defvalueA(HKEY base, WCHAR const *name,
157                                    char const *value);
158 static LONG register_progid(WCHAR const *clsid,
159                             char const *progid, char const *curver_progid,
160                             char const *name, char const *extra);
161
162 /***********************************************************************
163  *              register_coclasses
164  */
165 static HRESULT register_coclasses(struct regsvr_coclass const *list)
166 {
167     LONG res = ERROR_SUCCESS;
168     HKEY coclass_key;
169
170     res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0,
171                           KEY_READ | KEY_WRITE, NULL, &coclass_key, NULL);
172     if (res != ERROR_SUCCESS) goto error_return;
173
174     for (; res == ERROR_SUCCESS && list->clsid; ++list) {
175         WCHAR buf[39];
176         HKEY clsid_key;
177
178         StringFromGUID2(list->clsid, buf, 39);
179         res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
180                               KEY_READ | KEY_WRITE, NULL, &clsid_key, NULL);
181         if (res != ERROR_SUCCESS) goto error_close_coclass_key;
182
183         if (list->name) {
184             res = RegSetValueExA(clsid_key, NULL, 0, REG_SZ,
185                                  (CONST BYTE*)(list->name),
186                                  strlen(list->name) + 1);
187             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
188         }
189
190         if (list->ips) {
191             res = register_key_defvalueA(clsid_key, ips_keyname, list->ips);
192             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
193         }
194
195         if (list->ips32) {
196             HKEY ips32_key;
197
198             res = RegCreateKeyExW(clsid_key, ips32_keyname, 0, NULL, 0,
199                                   KEY_READ | KEY_WRITE, NULL,
200                                   &ips32_key, NULL);
201             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
202
203             res = RegSetValueExA(ips32_key, NULL, 0, REG_SZ,
204                                  (CONST BYTE*)list->ips32,
205                                  lstrlenA(list->ips32) + 1);
206             if (res == ERROR_SUCCESS && list->ips32_tmodel)
207                 res = RegSetValueExA(ips32_key, tmodel_valuename, 0, REG_SZ,
208                                      (CONST BYTE*)list->ips32_tmodel,
209                                      strlen(list->ips32_tmodel) + 1);
210             RegCloseKey(ips32_key);
211             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
212         }
213
214         if (list->progid) {
215             res = register_key_defvalueA(clsid_key, progid_keyname,
216                                          list->progid);
217             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
218
219             res = register_progid(buf, list->progid, NULL,
220                                   list->name, list->progid_extra);
221             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
222         }
223
224         if (list->viprogid) {
225             res = register_key_defvalueA(clsid_key, viprogid_keyname,
226                                          list->viprogid);
227             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
228
229             res = register_progid(buf, list->viprogid, list->progid,
230                                   list->name, list->progid_extra);
231             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
232         }
233
234     error_close_clsid_key:
235         RegCloseKey(clsid_key);
236     }
237
238 error_close_coclass_key:
239     RegCloseKey(coclass_key);
240 error_return:
241     return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
242 }
243
244 /***********************************************************************
245  *              unregister_coclasses
246  */
247 static HRESULT unregister_coclasses(struct regsvr_coclass const *list)
248 {
249     LONG res = ERROR_SUCCESS;
250     HKEY coclass_key;
251
252     res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0,
253                         KEY_READ | KEY_WRITE, &coclass_key);
254     if (res == ERROR_FILE_NOT_FOUND) return S_OK;
255     if (res != ERROR_SUCCESS) goto error_return;
256
257     for (; res == ERROR_SUCCESS && list->clsid; ++list) {
258         WCHAR buf[39];
259
260         StringFromGUID2(list->clsid, buf, 39);
261         res = RegDeleteTreeW(coclass_key, buf);
262         if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
263         if (res != ERROR_SUCCESS) goto error_close_coclass_key;
264
265         if (list->progid) {
266             res = RegDeleteTreeA(HKEY_CLASSES_ROOT, list->progid);
267             if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
268             if (res != ERROR_SUCCESS) goto error_close_coclass_key;
269         }
270
271         if (list->viprogid) {
272             res = RegDeleteTreeA(HKEY_CLASSES_ROOT, list->viprogid);
273             if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
274             if (res != ERROR_SUCCESS) goto error_close_coclass_key;
275         }
276     }
277
278 error_close_coclass_key:
279     RegCloseKey(coclass_key);
280 error_return:
281     return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
282 }
283
284 /***********************************************************************
285  *              register_decoders
286  */
287 static HRESULT register_decoders(struct regsvr_decoder const *list)
288 {
289     LONG res = ERROR_SUCCESS;
290     HKEY coclass_key;
291     WCHAR buf[39];
292     HKEY decoders_key;
293     HKEY instance_key;
294
295     res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0,
296                           KEY_READ | KEY_WRITE, NULL, &coclass_key, NULL);
297     if (res == ERROR_SUCCESS)  {
298         StringFromGUID2(&CATID_WICBitmapDecoders, buf, 39);
299         res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
300                               KEY_READ | KEY_WRITE, NULL, &decoders_key, NULL);
301         if (res == ERROR_SUCCESS)
302         {
303             res = RegCreateKeyExW(decoders_key, instance_keyname, 0, NULL, 0,
304                               KEY_READ | KEY_WRITE, NULL, &instance_key, NULL);
305             if (res != ERROR_SUCCESS) goto error_close_coclass_key;
306         }
307         if (res != ERROR_SUCCESS)
308             RegCloseKey(coclass_key);
309     }
310     if (res != ERROR_SUCCESS) goto error_return;
311
312     for (; res == ERROR_SUCCESS && list->clsid; ++list) {
313         HKEY clsid_key;
314         HKEY instance_clsid_key;
315
316         StringFromGUID2(list->clsid, buf, 39);
317         res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
318                               KEY_READ | KEY_WRITE, NULL, &clsid_key, NULL);
319         if (res != ERROR_SUCCESS) goto error_close_coclass_key;
320
321         StringFromGUID2(list->clsid, buf, 39);
322         res = RegCreateKeyExW(instance_key, buf, 0, NULL, 0,
323                               KEY_READ | KEY_WRITE, NULL, &instance_clsid_key, NULL);
324         if (res == ERROR_SUCCESS) {
325             res = RegSetValueExW(instance_clsid_key, clsid_valuename, 0, REG_SZ,
326                                  (CONST BYTE*)(buf), 78);
327             RegCloseKey(instance_clsid_key);
328         }
329         if (res != ERROR_SUCCESS) goto error_close_clsid_key;
330
331         if (list->author) {
332             res = RegSetValueExA(clsid_key, author_valuename, 0, REG_SZ,
333                                  (CONST BYTE*)(list->author),
334                                  strlen(list->author) + 1);
335             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
336         }
337
338         if (list->friendlyname) {
339             res = RegSetValueExA(clsid_key, friendlyname_valuename, 0, REG_SZ,
340                                  (CONST BYTE*)(list->friendlyname),
341                                  strlen(list->friendlyname) + 1);
342             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
343         }
344
345         if (list->vendor) {
346             StringFromGUID2(list->vendor, buf, 39);
347             res = RegSetValueExW(clsid_key, vendor_valuename, 0, REG_SZ,
348                                  (CONST BYTE*)(buf), 78);
349             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
350         }
351
352         if (list->version) {
353             res = RegSetValueExA(clsid_key, version_valuename, 0, REG_SZ,
354                                  (CONST BYTE*)(list->version),
355                                  strlen(list->version) + 1);
356             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
357         }
358
359         if (list->mimetypes) {
360             res = RegSetValueExA(clsid_key, mimetypes_valuename, 0, REG_SZ,
361                                  (CONST BYTE*)(list->mimetypes),
362                                  strlen(list->mimetypes) + 1);
363             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
364         }
365
366         if (list->extensions) {
367             res = RegSetValueExA(clsid_key, extensions_valuename, 0, REG_SZ,
368                                  (CONST BYTE*)(list->extensions),
369                                  strlen(list->extensions) + 1);
370             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
371         }
372
373         if (list->formats) {
374             HKEY formats_key;
375             GUID const * const *format;
376
377             res = RegCreateKeyExW(clsid_key, formats_keyname, 0, NULL, 0,
378                                   KEY_READ | KEY_WRITE, NULL, &formats_key, NULL);
379             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
380             for (format=list->formats; *format; ++format)
381             {
382                 HKEY format_key;
383                 StringFromGUID2(*format, buf, 39);
384                 res = RegCreateKeyExW(formats_key, buf, 0, NULL, 0,
385                                       KEY_READ | KEY_WRITE, NULL, &format_key, NULL);
386                 if (res != ERROR_SUCCESS) break;
387                 RegCloseKey(format_key);
388             }
389             RegCloseKey(formats_key);
390             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
391         }
392
393         if (list->patterns) {
394             HKEY patterns_key;
395             int i;
396
397             res = RegCreateKeyExW(clsid_key, patterns_keyname, 0, NULL, 0,
398                                   KEY_READ | KEY_WRITE, NULL, &patterns_key, NULL);
399             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
400             for (i=0; list->patterns[i].length; i++)
401             {
402                 HKEY pattern_key;
403                 static const WCHAR int_format[] = {'%','i',0};
404                 snprintfW(buf, 39, int_format, i);
405                 res = RegCreateKeyExW(patterns_key, buf, 0, NULL, 0,
406                                       KEY_READ | KEY_WRITE, NULL, &pattern_key, NULL);
407                 if (res != ERROR_SUCCESS) break;
408                 res = RegSetValueExA(pattern_key, length_valuename, 0, REG_DWORD,
409                                      (CONST BYTE*)(&list->patterns[i].length), 4);
410                 if (res == ERROR_SUCCESS)
411                     res = RegSetValueExA(pattern_key, position_valuename, 0, REG_DWORD,
412                                          (CONST BYTE*)(&list->patterns[i].position), 4);
413                 if (res == ERROR_SUCCESS)
414                     res = RegSetValueExA(pattern_key, pattern_valuename, 0, REG_BINARY,
415                                          list->patterns[i].pattern,
416                                          list->patterns[i].length);
417                 if (res == ERROR_SUCCESS)
418                     res = RegSetValueExA(pattern_key, mask_valuename, 0, REG_BINARY,
419                                          list->patterns[i].mask,
420                                          list->patterns[i].length);
421                 if (res == ERROR_SUCCESS)
422                     res = RegSetValueExA(pattern_key, endofstream_valuename, 0, REG_DWORD,
423                                          (CONST BYTE*)&(list->patterns[i].endofstream), 4);
424                 RegCloseKey(pattern_key);
425             }
426             RegCloseKey(patterns_key);
427             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
428         }
429
430     error_close_clsid_key:
431         RegCloseKey(clsid_key);
432     }
433
434 error_close_coclass_key:
435     RegCloseKey(instance_key);
436     RegCloseKey(decoders_key);
437     RegCloseKey(coclass_key);
438 error_return:
439     return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
440 }
441
442 /***********************************************************************
443  *              unregister_decoders
444  */
445 static HRESULT unregister_decoders(struct regsvr_decoder const *list)
446 {
447     LONG res = ERROR_SUCCESS;
448     HKEY coclass_key;
449     WCHAR buf[39];
450     HKEY decoders_key;
451     HKEY instance_key;
452
453     res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0,
454                         KEY_READ | KEY_WRITE, &coclass_key);
455     if (res == ERROR_FILE_NOT_FOUND) return S_OK;
456
457     if (res == ERROR_SUCCESS)  {
458         StringFromGUID2(&CATID_WICBitmapDecoders, buf, 39);
459         res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
460                               KEY_READ | KEY_WRITE, NULL, &decoders_key, NULL);
461         if (res == ERROR_SUCCESS)
462         {
463             res = RegCreateKeyExW(decoders_key, instance_keyname, 0, NULL, 0,
464                               KEY_READ | KEY_WRITE, NULL, &instance_key, NULL);
465             if (res != ERROR_SUCCESS) goto error_close_coclass_key;
466         }
467         if (res != ERROR_SUCCESS)
468             RegCloseKey(coclass_key);
469     }
470     if (res != ERROR_SUCCESS) goto error_return;
471
472     for (; res == ERROR_SUCCESS && list->clsid; ++list) {
473         StringFromGUID2(list->clsid, buf, 39);
474
475         res = RegDeleteTreeW(coclass_key, buf);
476         if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
477         if (res != ERROR_SUCCESS) goto error_close_coclass_key;
478
479         res = RegDeleteTreeW(instance_key, buf);
480         if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
481         if (res != ERROR_SUCCESS) goto error_close_coclass_key;
482     }
483
484 error_close_coclass_key:
485     RegCloseKey(instance_key);
486     RegCloseKey(decoders_key);
487     RegCloseKey(coclass_key);
488 error_return:
489     return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
490 }
491
492 /***********************************************************************
493  *              register_encoders
494  */
495 static HRESULT register_encoders(struct regsvr_encoder const *list)
496 {
497     LONG res = ERROR_SUCCESS;
498     HKEY coclass_key;
499     WCHAR buf[39];
500     HKEY encoders_key;
501     HKEY instance_key;
502
503     res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0,
504                           KEY_READ | KEY_WRITE, NULL, &coclass_key, NULL);
505     if (res == ERROR_SUCCESS)  {
506         StringFromGUID2(&CATID_WICBitmapEncoders, buf, 39);
507         res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
508                               KEY_READ | KEY_WRITE, NULL, &encoders_key, NULL);
509         if (res == ERROR_SUCCESS)
510         {
511             res = RegCreateKeyExW(encoders_key, instance_keyname, 0, NULL, 0,
512                               KEY_READ | KEY_WRITE, NULL, &instance_key, NULL);
513             if (res != ERROR_SUCCESS) goto error_close_coclass_key;
514         }
515         if (res != ERROR_SUCCESS)
516             RegCloseKey(coclass_key);
517     }
518     if (res != ERROR_SUCCESS) goto error_return;
519
520     for (; res == ERROR_SUCCESS && list->clsid; ++list) {
521         HKEY clsid_key;
522         HKEY instance_clsid_key;
523
524         StringFromGUID2(list->clsid, buf, 39);
525         res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
526                               KEY_READ | KEY_WRITE, NULL, &clsid_key, NULL);
527         if (res != ERROR_SUCCESS) goto error_close_coclass_key;
528
529         StringFromGUID2(list->clsid, buf, 39);
530         res = RegCreateKeyExW(instance_key, buf, 0, NULL, 0,
531                               KEY_READ | KEY_WRITE, NULL, &instance_clsid_key, NULL);
532         if (res == ERROR_SUCCESS) {
533             res = RegSetValueExW(instance_clsid_key, clsid_valuename, 0, REG_SZ,
534                                  (CONST BYTE*)(buf), 78);
535             RegCloseKey(instance_clsid_key);
536         }
537         if (res != ERROR_SUCCESS) goto error_close_clsid_key;
538
539         if (list->author) {
540             res = RegSetValueExA(clsid_key, author_valuename, 0, REG_SZ,
541                                  (CONST BYTE*)(list->author),
542                                  strlen(list->author) + 1);
543             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
544         }
545
546         if (list->friendlyname) {
547             res = RegSetValueExA(clsid_key, friendlyname_valuename, 0, REG_SZ,
548                                  (CONST BYTE*)(list->friendlyname),
549                                  strlen(list->friendlyname) + 1);
550             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
551         }
552
553         if (list->vendor) {
554             StringFromGUID2(list->vendor, buf, 39);
555             res = RegSetValueExW(clsid_key, vendor_valuename, 0, REG_SZ,
556                                  (CONST BYTE*)(buf), 78);
557             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
558         }
559
560         if (list->version) {
561             res = RegSetValueExA(clsid_key, version_valuename, 0, REG_SZ,
562                                  (CONST BYTE*)(list->version),
563                                  strlen(list->version) + 1);
564             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
565         }
566
567         if (list->mimetypes) {
568             res = RegSetValueExA(clsid_key, mimetypes_valuename, 0, REG_SZ,
569                                  (CONST BYTE*)(list->mimetypes),
570                                  strlen(list->mimetypes) + 1);
571             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
572         }
573
574         if (list->extensions) {
575             res = RegSetValueExA(clsid_key, extensions_valuename, 0, REG_SZ,
576                                  (CONST BYTE*)(list->extensions),
577                                  strlen(list->extensions) + 1);
578             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
579         }
580
581         if (list->formats) {
582             HKEY formats_key;
583             GUID const * const *format;
584
585             res = RegCreateKeyExW(clsid_key, formats_keyname, 0, NULL, 0,
586                                   KEY_READ | KEY_WRITE, NULL, &formats_key, NULL);
587             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
588             for (format=list->formats; *format; ++format)
589             {
590                 HKEY format_key;
591                 StringFromGUID2(*format, buf, 39);
592                 res = RegCreateKeyExW(formats_key, buf, 0, NULL, 0,
593                                       KEY_READ | KEY_WRITE, NULL, &format_key, NULL);
594                 if (res != ERROR_SUCCESS) break;
595                 RegCloseKey(format_key);
596             }
597             RegCloseKey(formats_key);
598             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
599         }
600
601     error_close_clsid_key:
602         RegCloseKey(clsid_key);
603     }
604
605 error_close_coclass_key:
606     RegCloseKey(instance_key);
607     RegCloseKey(encoders_key);
608     RegCloseKey(coclass_key);
609 error_return:
610     return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
611 }
612
613 /***********************************************************************
614  *              unregister_encoders
615  */
616 static HRESULT unregister_encoders(struct regsvr_encoder const *list)
617 {
618     LONG res = ERROR_SUCCESS;
619     HKEY coclass_key;
620     WCHAR buf[39];
621     HKEY encoders_key;
622     HKEY instance_key;
623
624     res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0,
625                         KEY_READ | KEY_WRITE, &coclass_key);
626     if (res == ERROR_FILE_NOT_FOUND) return S_OK;
627
628     if (res == ERROR_SUCCESS)  {
629         StringFromGUID2(&CATID_WICBitmapEncoders, buf, 39);
630         res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
631                               KEY_READ | KEY_WRITE, NULL, &encoders_key, NULL);
632         if (res == ERROR_SUCCESS)
633         {
634             res = RegCreateKeyExW(encoders_key, instance_keyname, 0, NULL, 0,
635                               KEY_READ | KEY_WRITE, NULL, &instance_key, NULL);
636             if (res != ERROR_SUCCESS) goto error_close_coclass_key;
637         }
638         if (res != ERROR_SUCCESS)
639             RegCloseKey(coclass_key);
640     }
641     if (res != ERROR_SUCCESS) goto error_return;
642
643     for (; res == ERROR_SUCCESS && list->clsid; ++list) {
644         StringFromGUID2(list->clsid, buf, 39);
645
646         res = RegDeleteTreeW(coclass_key, buf);
647         if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
648         if (res != ERROR_SUCCESS) goto error_close_coclass_key;
649
650         res = RegDeleteTreeW(instance_key, buf);
651         if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
652         if (res != ERROR_SUCCESS) goto error_close_coclass_key;
653     }
654
655 error_close_coclass_key:
656     RegCloseKey(instance_key);
657     RegCloseKey(encoders_key);
658     RegCloseKey(coclass_key);
659 error_return:
660     return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
661 }
662
663 /***********************************************************************
664  *              register_converters
665  */
666 static HRESULT register_converters(struct regsvr_converter const *list)
667 {
668     LONG res = ERROR_SUCCESS;
669     HKEY coclass_key;
670     WCHAR buf[39];
671     HKEY converters_key;
672     HKEY instance_key;
673
674     res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0,
675                           KEY_READ | KEY_WRITE, NULL, &coclass_key, NULL);
676     if (res == ERROR_SUCCESS)  {
677         StringFromGUID2(&CATID_WICFormatConverters, buf, 39);
678         res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
679                               KEY_READ | KEY_WRITE, NULL, &converters_key, NULL);
680         if (res == ERROR_SUCCESS)
681         {
682             res = RegCreateKeyExW(converters_key, instance_keyname, 0, NULL, 0,
683                               KEY_READ | KEY_WRITE, NULL, &instance_key, NULL);
684             if (res != ERROR_SUCCESS) goto error_close_coclass_key;
685         }
686         if (res != ERROR_SUCCESS)
687             RegCloseKey(coclass_key);
688     }
689     if (res != ERROR_SUCCESS) goto error_return;
690
691     for (; res == ERROR_SUCCESS && list->clsid; ++list) {
692         HKEY clsid_key;
693         HKEY instance_clsid_key;
694
695         StringFromGUID2(list->clsid, buf, 39);
696         res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
697                               KEY_READ | KEY_WRITE, NULL, &clsid_key, NULL);
698         if (res != ERROR_SUCCESS) goto error_close_coclass_key;
699
700         StringFromGUID2(list->clsid, buf, 39);
701         res = RegCreateKeyExW(instance_key, buf, 0, NULL, 0,
702                               KEY_READ | KEY_WRITE, NULL, &instance_clsid_key, NULL);
703         if (res == ERROR_SUCCESS) {
704             res = RegSetValueExW(instance_clsid_key, clsid_valuename, 0, REG_SZ,
705                                  (CONST BYTE*)(buf), 78);
706             RegCloseKey(instance_clsid_key);
707         }
708         if (res != ERROR_SUCCESS) goto error_close_clsid_key;
709
710         if (list->author) {
711             res = RegSetValueExA(clsid_key, author_valuename, 0, REG_SZ,
712                                  (CONST BYTE*)(list->author),
713                                  strlen(list->author) + 1);
714             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
715         }
716
717         if (list->friendlyname) {
718             res = RegSetValueExA(clsid_key, friendlyname_valuename, 0, REG_SZ,
719                                  (CONST BYTE*)(list->friendlyname),
720                                  strlen(list->friendlyname) + 1);
721             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
722         }
723
724         if (list->vendor) {
725             StringFromGUID2(list->vendor, buf, 39);
726             res = RegSetValueExW(clsid_key, vendor_valuename, 0, REG_SZ,
727                                  (CONST BYTE*)(buf), 78);
728             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
729         }
730
731         if (list->version) {
732             res = RegSetValueExA(clsid_key, version_valuename, 0, REG_SZ,
733                                  (CONST BYTE*)(list->version),
734                                  strlen(list->version) + 1);
735             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
736         }
737
738         if (list->formats) {
739             HKEY formats_key;
740             GUID const * const *format;
741
742             res = RegCreateKeyExW(clsid_key, pixelformats_keyname, 0, NULL, 0,
743                                   KEY_READ | KEY_WRITE, NULL, &formats_key, NULL);
744             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
745             for (format=list->formats; *format; ++format)
746             {
747                 HKEY format_key;
748                 StringFromGUID2(*format, buf, 39);
749                 res = RegCreateKeyExW(formats_key, buf, 0, NULL, 0,
750                                       KEY_READ | KEY_WRITE, NULL, &format_key, NULL);
751                 if (res != ERROR_SUCCESS) break;
752                 RegCloseKey(format_key);
753             }
754             RegCloseKey(formats_key);
755             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
756         }
757
758     error_close_clsid_key:
759         RegCloseKey(clsid_key);
760     }
761
762 error_close_coclass_key:
763     RegCloseKey(instance_key);
764     RegCloseKey(converters_key);
765     RegCloseKey(coclass_key);
766 error_return:
767     return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
768 }
769
770 /***********************************************************************
771  *              unregister_converters
772  */
773 static HRESULT unregister_converters(struct regsvr_converter const *list)
774 {
775     LONG res = ERROR_SUCCESS;
776     HKEY coclass_key;
777     WCHAR buf[39];
778     HKEY converters_key;
779     HKEY instance_key;
780
781     res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0,
782                         KEY_READ | KEY_WRITE, &coclass_key);
783     if (res == ERROR_FILE_NOT_FOUND) return S_OK;
784
785     if (res == ERROR_SUCCESS)  {
786         StringFromGUID2(&CATID_WICFormatConverters, buf, 39);
787         res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
788                               KEY_READ | KEY_WRITE, NULL, &converters_key, NULL);
789         if (res == ERROR_SUCCESS)
790         {
791             res = RegCreateKeyExW(converters_key, instance_keyname, 0, NULL, 0,
792                               KEY_READ | KEY_WRITE, NULL, &instance_key, NULL);
793             if (res != ERROR_SUCCESS) goto error_close_coclass_key;
794         }
795         if (res != ERROR_SUCCESS)
796             RegCloseKey(coclass_key);
797     }
798     if (res != ERROR_SUCCESS) goto error_return;
799
800     for (; res == ERROR_SUCCESS && list->clsid; ++list) {
801         StringFromGUID2(list->clsid, buf, 39);
802
803         res = RegDeleteTreeW(coclass_key, buf);
804         if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
805         if (res != ERROR_SUCCESS) goto error_close_coclass_key;
806
807         res = RegDeleteTreeW(instance_key, buf);
808         if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
809         if (res != ERROR_SUCCESS) goto error_close_coclass_key;
810     }
811
812 error_close_coclass_key:
813     RegCloseKey(instance_key);
814     RegCloseKey(converters_key);
815     RegCloseKey(coclass_key);
816 error_return:
817     return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
818 }
819
820 /***********************************************************************
821  *              register_key_defvalueW
822  */
823 static LONG register_key_defvalueW(
824     HKEY base,
825     WCHAR const *name,
826     WCHAR const *value)
827 {
828     LONG res;
829     HKEY key;
830
831     res = RegCreateKeyExW(base, name, 0, NULL, 0,
832                           KEY_READ | KEY_WRITE, NULL, &key, NULL);
833     if (res != ERROR_SUCCESS) return res;
834     res = RegSetValueExW(key, NULL, 0, REG_SZ, (CONST BYTE*)value,
835                          (lstrlenW(value) + 1) * sizeof(WCHAR));
836     RegCloseKey(key);
837     return res;
838 }
839
840 /***********************************************************************
841  *              register_key_defvalueA
842  */
843 static LONG register_key_defvalueA(
844     HKEY base,
845     WCHAR const *name,
846     char const *value)
847 {
848     LONG res;
849     HKEY key;
850
851     res = RegCreateKeyExW(base, name, 0, NULL, 0,
852                           KEY_READ | KEY_WRITE, NULL, &key, NULL);
853     if (res != ERROR_SUCCESS) return res;
854     res = RegSetValueExA(key, NULL, 0, REG_SZ, (CONST BYTE*)value,
855                          lstrlenA(value) + 1);
856     RegCloseKey(key);
857     return res;
858 }
859
860 /***********************************************************************
861  *              register_progid
862  */
863 static LONG register_progid(
864     WCHAR const *clsid,
865     char const *progid,
866     char const *curver_progid,
867     char const *name,
868     char const *extra)
869 {
870     LONG res;
871     HKEY progid_key;
872
873     res = RegCreateKeyExA(HKEY_CLASSES_ROOT, progid, 0,
874                           NULL, 0, KEY_READ | KEY_WRITE, NULL,
875                           &progid_key, NULL);
876     if (res != ERROR_SUCCESS) return res;
877
878     if (name) {
879         res = RegSetValueExA(progid_key, NULL, 0, REG_SZ,
880                              (CONST BYTE*)name, strlen(name) + 1);
881         if (res != ERROR_SUCCESS) goto error_close_progid_key;
882     }
883
884     if (clsid) {
885         res = register_key_defvalueW(progid_key, clsid_keyname, clsid);
886         if (res != ERROR_SUCCESS) goto error_close_progid_key;
887     }
888
889     if (curver_progid) {
890         res = register_key_defvalueA(progid_key, curver_keyname,
891                                      curver_progid);
892         if (res != ERROR_SUCCESS) goto error_close_progid_key;
893     }
894
895     if (extra) {
896         HKEY extra_key;
897
898         res = RegCreateKeyExA(progid_key, extra, 0,
899                               NULL, 0, KEY_READ | KEY_WRITE, NULL,
900                               &extra_key, NULL);
901         if (res == ERROR_SUCCESS)
902             RegCloseKey(extra_key);
903     }
904
905 error_close_progid_key:
906     RegCloseKey(progid_key);
907     return res;
908 }
909
910 /***********************************************************************
911  *              coclass list
912  */
913 static struct regsvr_coclass const coclass_list[] = {
914     {   &CLSID_WICImagingFactory,
915         "WIC Imaging Factory",
916         NULL,
917         "windowscodecs.dll",
918         "Both"
919     },
920     {   &CLSID_WICBmpDecoder,
921         "WIC BMP Decoder",
922         NULL,
923         "windowscodecs.dll",
924         "Both"
925     },
926     {   &CLSID_WICPngDecoder,
927         "WIC PNG Decoder",
928         NULL,
929         "windowscodecs.dll",
930         "Both"
931     },
932     {   &CLSID_WICPngEncoder,
933         "WIC PNG Encoder",
934         NULL,
935         "windowscodecs.dll",
936         "Both"
937     },
938     {   &CLSID_WICBmpEncoder,
939         "WIC BMP Encoder",
940         NULL,
941         "windowscodecs.dll",
942         "Apartment"
943     },
944     {   &CLSID_WICGifDecoder,
945         "WIC GIF Decoder",
946         NULL,
947         "windowscodecs.dll",
948         "Both"
949     },
950     {   &CLSID_WICIcoDecoder,
951         "WIC ICO Decoder",
952         NULL,
953         "windowscodecs.dll",
954         "Both"
955     },
956     {   &CLSID_WICJpegDecoder,
957         "WIC JPEG Decoder",
958         NULL,
959         "windowscodecs.dll",
960         "Both"
961     },
962     {   &CLSID_WICTiffDecoder,
963         "WIC TIFF Decoder",
964         NULL,
965         "windowscodecs.dll",
966         "Both"
967     },
968     {
969         &CLSID_WICIcnsEncoder,
970         "WIC ICNS Encoder",
971         NULL,
972         "windowscodecs.dll",
973         "Both"
974     },
975     {   &CLSID_WICDefaultFormatConverter,
976         "WIC Default Format Converter",
977         NULL,
978         "windowscodecs.dll",
979         "Both"
980     },
981     { NULL }                    /* list terminator */
982 };
983
984 /***********************************************************************
985  *              decoder list
986  */
987 static const BYTE mask_all[] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
988
989 static const BYTE bmp_magic[] = {0x42,0x4d};
990
991 static GUID const * const bmp_formats[] = {
992     &GUID_WICPixelFormat1bppIndexed,
993     &GUID_WICPixelFormat2bppIndexed,
994     &GUID_WICPixelFormat4bppIndexed,
995     &GUID_WICPixelFormat8bppIndexed,
996     &GUID_WICPixelFormat16bppBGR555,
997     &GUID_WICPixelFormat16bppBGR565,
998     &GUID_WICPixelFormat24bppBGR,
999     &GUID_WICPixelFormat32bppBGR,
1000     &GUID_WICPixelFormat32bppBGRA,
1001     NULL
1002 };
1003
1004 static struct decoder_pattern const bmp_patterns[] = {
1005     {2,0,bmp_magic,mask_all,0},
1006     {0}
1007 };
1008
1009 static const BYTE gif87a_magic[6] = "GIF87a";
1010 static const BYTE gif89a_magic[6] = "GIF89a";
1011
1012 static GUID const * const gif_formats[] = {
1013     &GUID_WICPixelFormat8bppIndexed,
1014     NULL
1015 };
1016
1017 static struct decoder_pattern const gif_patterns[] = {
1018     {6,0,gif87a_magic,mask_all,0},
1019     {6,0,gif89a_magic,mask_all,0},
1020     {0}
1021 };
1022
1023 static const BYTE ico_magic[] = {00,00,01,00};
1024
1025 static GUID const * const ico_formats[] = {
1026     &GUID_WICPixelFormat32bppBGRA,
1027     NULL
1028 };
1029
1030 static struct decoder_pattern const ico_patterns[] = {
1031     {4,0,ico_magic,mask_all,0},
1032     {0}
1033 };
1034
1035 static const BYTE jpeg_magic[] = {0xff, 0xd8, 0xff, 0xe0};
1036
1037 static GUID const * const jpeg_formats[] = {
1038     &GUID_WICPixelFormat24bppBGR,
1039     &GUID_WICPixelFormat32bppCMYK,
1040     &GUID_WICPixelFormat8bppGray,
1041     NULL
1042 };
1043
1044 static struct decoder_pattern const jpeg_patterns[] = {
1045     {4,0,jpeg_magic,mask_all,0},
1046     {0}
1047 };
1048
1049 static const BYTE png_magic[] = {137,80,78,71,13,10,26,10};
1050
1051 static GUID const * const png_formats[] = {
1052     &GUID_WICPixelFormatBlackWhite,
1053     &GUID_WICPixelFormat2bppGray,
1054     &GUID_WICPixelFormat4bppGray,
1055     &GUID_WICPixelFormat8bppGray,
1056     &GUID_WICPixelFormat16bppGray,
1057     &GUID_WICPixelFormat32bppBGRA,
1058     &GUID_WICPixelFormat64bppRGBA,
1059     &GUID_WICPixelFormat1bppIndexed,
1060     &GUID_WICPixelFormat2bppIndexed,
1061     &GUID_WICPixelFormat4bppIndexed,
1062     &GUID_WICPixelFormat8bppIndexed,
1063     &GUID_WICPixelFormat24bppBGR,
1064     &GUID_WICPixelFormat48bppRGB,
1065     NULL
1066 };
1067
1068 static struct decoder_pattern const png_patterns[] = {
1069     {8,0,png_magic,mask_all,0},
1070     {0}
1071 };
1072
1073 static const BYTE tiff_magic_le[] = {0x49,0x49,42,0};
1074 static const BYTE tiff_magic_be[] = {0x4d,0x4d,0,42};
1075
1076 static GUID const * const tiff_formats[] = {
1077     &GUID_WICPixelFormatBlackWhite,
1078     &GUID_WICPixelFormat4bppGray,
1079     &GUID_WICPixelFormat8bppGray,
1080     &GUID_WICPixelFormat4bppIndexed,
1081     &GUID_WICPixelFormat8bppIndexed,
1082     &GUID_WICPixelFormat32bppBGR,
1083     &GUID_WICPixelFormat32bppBGRA,
1084     &GUID_WICPixelFormat32bppPBGRA,
1085     &GUID_WICPixelFormat48bppRGB,
1086     NULL
1087 };
1088
1089 static struct decoder_pattern const tiff_patterns[] = {
1090     {4,0,tiff_magic_le,mask_all,0},
1091     {4,0,tiff_magic_be,mask_all,0},
1092     {0}
1093 };
1094
1095 static struct regsvr_decoder const decoder_list[] = {
1096     {   &CLSID_WICBmpDecoder,
1097         "The Wine Project",
1098         "BMP Decoder",
1099         "1.0.0.0",
1100         &GUID_VendorMicrosoft,
1101         "image/bmp",
1102         ".bmp,.dib,.rle",
1103         bmp_formats,
1104         bmp_patterns
1105     },
1106     {   &CLSID_WICGifDecoder,
1107         "The Wine Project",
1108         "GIF Decoder",
1109         "1.0.0.0",
1110         &GUID_VendorMicrosoft,
1111         "image/gif",
1112         ".gif",
1113         gif_formats,
1114         gif_patterns
1115     },
1116     {   &CLSID_WICIcoDecoder,
1117         "The Wine Project",
1118         "ICO Decoder",
1119         "1.0.0.0",
1120         &GUID_VendorMicrosoft,
1121         "image/vnd.microsoft.icon",
1122         ".ico",
1123         ico_formats,
1124         ico_patterns
1125     },
1126     {   &CLSID_WICJpegDecoder,
1127         "The Wine Project",
1128         "JPEG Decoder",
1129         "1.0.0.0",
1130         &GUID_VendorMicrosoft,
1131         "image/jpeg",
1132         ".jpg;.jpeg;.jfif",
1133         jpeg_formats,
1134         jpeg_patterns
1135     },
1136     {   &CLSID_WICPngDecoder,
1137         "The Wine Project",
1138         "PNG Decoder",
1139         "1.0.0.0",
1140         &GUID_VendorMicrosoft,
1141         "image/png",
1142         ".png",
1143         png_formats,
1144         png_patterns
1145     },
1146     {   &CLSID_WICTiffDecoder,
1147         "The Wine Project",
1148         "TIFF Decoder",
1149         "1.0.0.0",
1150         &GUID_VendorMicrosoft,
1151         "image/tiff",
1152         ".tif;.tiff",
1153         tiff_formats,
1154         tiff_patterns
1155     },
1156     { NULL }                    /* list terminator */
1157 };
1158
1159 static GUID const * const bmp_encode_formats[] = {
1160     &GUID_WICPixelFormat16bppBGR555,
1161     &GUID_WICPixelFormat16bppBGR565,
1162     &GUID_WICPixelFormat24bppBGR,
1163     &GUID_WICPixelFormat32bppBGR,
1164     NULL
1165 };
1166
1167 static GUID const * const png_encode_formats[] = {
1168     &GUID_WICPixelFormat24bppBGR,
1169     &GUID_WICPixelFormatBlackWhite,
1170     &GUID_WICPixelFormat2bppGray,
1171     &GUID_WICPixelFormat4bppGray,
1172     &GUID_WICPixelFormat8bppGray,
1173     &GUID_WICPixelFormat16bppGray,
1174     &GUID_WICPixelFormat32bppBGR,
1175     &GUID_WICPixelFormat32bppBGRA,
1176     &GUID_WICPixelFormat48bppRGB,
1177     &GUID_WICPixelFormat64bppRGBA,
1178     NULL
1179 };
1180
1181 static GUID const * const icns_encode_formats[] = {
1182     &GUID_WICPixelFormat32bppBGRA,
1183     NULL
1184 };
1185
1186 static struct regsvr_encoder const encoder_list[] = {
1187     {   &CLSID_WICBmpEncoder,
1188         "The Wine Project",
1189         "BMP Encoder",
1190         "1.0.0.0",
1191         &GUID_VendorMicrosoft,
1192         "image/bmp",
1193         ".bmp,.dib,.rle",
1194         bmp_encode_formats
1195     },
1196     {   &CLSID_WICPngEncoder,
1197         "The Wine Project",
1198         "PNG Encoder",
1199         "1.0.0.0",
1200         &GUID_VendorMicrosoft,
1201         "image/png",
1202         ".png",
1203         png_encode_formats
1204     },
1205     {   &CLSID_WICIcnsEncoder,
1206         "The Wine Project",
1207         "ICNS Encoder",
1208         "1.0.0.0",
1209         &GUID_VendorWine,
1210         "image/icns",
1211         ".icns",
1212         icns_encode_formats
1213     },
1214     { NULL }                    /* list terminator */
1215 };
1216
1217 static GUID const * const converter_formats[] = {
1218     &GUID_WICPixelFormat1bppIndexed,
1219     &GUID_WICPixelFormat2bppIndexed,
1220     &GUID_WICPixelFormat4bppIndexed,
1221     &GUID_WICPixelFormat8bppIndexed,
1222     &GUID_WICPixelFormatBlackWhite,
1223     &GUID_WICPixelFormat2bppGray,
1224     &GUID_WICPixelFormat4bppGray,
1225     &GUID_WICPixelFormat8bppGray,
1226     &GUID_WICPixelFormat16bppGray,
1227     &GUID_WICPixelFormat16bppBGR555,
1228     &GUID_WICPixelFormat16bppBGR565,
1229     &GUID_WICPixelFormat24bppBGR,
1230     &GUID_WICPixelFormat32bppBGR,
1231     &GUID_WICPixelFormat32bppBGRA,
1232     &GUID_WICPixelFormat48bppRGB,
1233     &GUID_WICPixelFormat64bppRGBA,
1234     &GUID_WICPixelFormat32bppCMYK,
1235     NULL
1236 };
1237
1238 static struct regsvr_converter const converter_list[] = {
1239     {   &CLSID_WICDefaultFormatConverter,
1240         "The Wine Project",
1241         "Default Pixel Format Converter",
1242         "1.0.0.0",
1243         &GUID_VendorMicrosoft,
1244         converter_formats
1245     },
1246     { NULL }                    /* list terminator */
1247 };
1248
1249 HRESULT WINAPI DllRegisterServer(void)
1250 {
1251     HRESULT hr;
1252
1253     TRACE("\n");
1254
1255     hr = register_coclasses(coclass_list);
1256     if (SUCCEEDED(hr))
1257         register_decoders(decoder_list);
1258     if (SUCCEEDED(hr))
1259         register_encoders(encoder_list);
1260     if (SUCCEEDED(hr))
1261         register_converters(converter_list);
1262     return hr;
1263 }
1264
1265 HRESULT WINAPI DllUnregisterServer(void)
1266 {
1267     HRESULT hr;
1268
1269     TRACE("\n");
1270
1271     hr = unregister_coclasses(coclass_list);
1272     if (SUCCEEDED(hr))
1273         unregister_decoders(decoder_list);
1274     if (SUCCEEDED(hr))
1275         unregister_encoders(encoder_list);
1276     if (SUCCEEDED(hr))
1277         unregister_converters(converter_list);
1278     return hr;
1279 }