d3drm: Implement IDirect3DRMMesh_AddGroup.
[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 decoder_pattern
47 {
48     DWORD length;    /* 0 for end of list */
49     DWORD position;
50     const BYTE *pattern;
51     const BYTE *mask;
52     DWORD endofstream;
53 };
54
55 struct regsvr_decoder
56 {
57     CLSID const *clsid;         /* NULL for end of list */
58     LPCSTR author;
59     LPCSTR friendlyname;
60     LPCSTR version;
61     GUID const *vendor;
62     GUID const *container_format;
63     LPCSTR mimetypes;
64     LPCSTR extensions;
65     GUID const * const *formats;
66     const struct decoder_pattern *patterns;
67 };
68
69 static HRESULT register_decoders(struct regsvr_decoder const *list);
70 static HRESULT unregister_decoders(struct regsvr_decoder const *list);
71
72 struct regsvr_encoder
73 {
74     CLSID const *clsid;         /* NULL for end of list */
75     LPCSTR author;
76     LPCSTR friendlyname;
77     LPCSTR version;
78     GUID const *vendor;
79     GUID const *container_format;
80     LPCSTR mimetypes;
81     LPCSTR extensions;
82     GUID const * const *formats;
83 };
84
85 static HRESULT register_encoders(struct regsvr_encoder const *list);
86 static HRESULT unregister_encoders(struct regsvr_encoder const *list);
87
88 struct regsvr_converter
89 {
90     CLSID const *clsid;         /* NULL for end of list */
91     LPCSTR author;
92     LPCSTR friendlyname;
93     LPCSTR version;
94     GUID const *vendor;
95     GUID const * const *formats;
96 };
97
98 static HRESULT register_converters(struct regsvr_converter const *list);
99 static HRESULT unregister_converters(struct regsvr_converter const *list);
100
101 /***********************************************************************
102  *              static string constants
103  */
104 static const WCHAR clsid_keyname[] = {
105     'C', 'L', 'S', 'I', 'D', 0 };
106 static const WCHAR curver_keyname[] = {
107     'C', 'u', 'r', 'V', 'e', 'r', 0 };
108 static const WCHAR ips_keyname[] = {
109     'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
110     0 };
111 static const WCHAR ips32_keyname[] = {
112     'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
113     '3', '2', 0 };
114 static const WCHAR progid_keyname[] = {
115     'P', 'r', 'o', 'g', 'I', 'D', 0 };
116 static const WCHAR viprogid_keyname[] = {
117     'V', 'e', 'r', 's', 'i', 'o', 'n', 'I', 'n', 'd', 'e', 'p',
118     'e', 'n', 'd', 'e', 'n', 't', 'P', 'r', 'o', 'g', 'I', 'D',
119     0 };
120 static const char tmodel_valuename[] = "ThreadingModel";
121 static const char author_valuename[] = "Author";
122 static const char friendlyname_valuename[] = "FriendlyName";
123 static const WCHAR vendor_valuename[] = {'V','e','n','d','o','r',0};
124 static const WCHAR containerformat_valuename[] = {'C','o','n','t','a','i','n','e','r','F','o','r','m','a','t',0};
125 static const char version_valuename[] = "Version";
126 static const char mimetypes_valuename[] = "MimeTypes";
127 static const char extensions_valuename[] = "FileExtensions";
128 static const WCHAR formats_keyname[] = {'F','o','r','m','a','t','s',0};
129 static const WCHAR patterns_keyname[] = {'P','a','t','t','e','r','n','s',0};
130 static const WCHAR instance_keyname[] = {'I','n','s','t','a','n','c','e',0};
131 static const WCHAR clsid_valuename[] = {'C','L','S','I','D',0};
132 static const char length_valuename[] = "Length";
133 static const char position_valuename[] = "Position";
134 static const char pattern_valuename[] = "Pattern";
135 static const char mask_valuename[] = "Mask";
136 static const char endofstream_valuename[] = "EndOfStream";
137 static const WCHAR pixelformats_keyname[] = {'P','i','x','e','l','F','o','r','m','a','t','s',0};
138
139 /***********************************************************************
140  *              register_decoders
141  */
142 static HRESULT register_decoders(struct regsvr_decoder const *list)
143 {
144     LONG res = ERROR_SUCCESS;
145     HKEY coclass_key;
146     WCHAR buf[39];
147     HKEY decoders_key;
148     HKEY instance_key;
149
150     res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0,
151                           KEY_READ | KEY_WRITE, NULL, &coclass_key, NULL);
152     if (res == ERROR_SUCCESS)  {
153         StringFromGUID2(&CATID_WICBitmapDecoders, buf, 39);
154         res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
155                               KEY_READ | KEY_WRITE, NULL, &decoders_key, NULL);
156         if (res == ERROR_SUCCESS)
157         {
158             res = RegCreateKeyExW(decoders_key, instance_keyname, 0, NULL, 0,
159                               KEY_READ | KEY_WRITE, NULL, &instance_key, NULL);
160             if (res != ERROR_SUCCESS) goto error_close_coclass_key;
161         }
162         if (res != ERROR_SUCCESS)
163             RegCloseKey(coclass_key);
164     }
165     if (res != ERROR_SUCCESS) goto error_return;
166
167     for (; res == ERROR_SUCCESS && list->clsid; ++list) {
168         HKEY clsid_key;
169         HKEY instance_clsid_key;
170
171         StringFromGUID2(list->clsid, buf, 39);
172         res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
173                               KEY_READ | KEY_WRITE, NULL, &clsid_key, NULL);
174         if (res != ERROR_SUCCESS) goto error_close_coclass_key;
175
176         StringFromGUID2(list->clsid, buf, 39);
177         res = RegCreateKeyExW(instance_key, buf, 0, NULL, 0,
178                               KEY_READ | KEY_WRITE, NULL, &instance_clsid_key, NULL);
179         if (res == ERROR_SUCCESS) {
180             res = RegSetValueExW(instance_clsid_key, clsid_valuename, 0, REG_SZ,
181                                  (CONST BYTE*)(buf), 78);
182             RegCloseKey(instance_clsid_key);
183         }
184         if (res != ERROR_SUCCESS) goto error_close_clsid_key;
185
186         if (list->author) {
187             res = RegSetValueExA(clsid_key, author_valuename, 0, REG_SZ,
188                                  (CONST BYTE*)(list->author),
189                                  strlen(list->author) + 1);
190             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
191         }
192
193         if (list->friendlyname) {
194             res = RegSetValueExA(clsid_key, friendlyname_valuename, 0, REG_SZ,
195                                  (CONST BYTE*)(list->friendlyname),
196                                  strlen(list->friendlyname) + 1);
197             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
198         }
199
200         if (list->vendor) {
201             StringFromGUID2(list->vendor, buf, 39);
202             res = RegSetValueExW(clsid_key, vendor_valuename, 0, REG_SZ,
203                                  (CONST BYTE*)(buf), 78);
204             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
205         }
206
207         if (list->container_format) {
208             StringFromGUID2(list->container_format, buf, 39);
209             res = RegSetValueExW(clsid_key, containerformat_valuename, 0, REG_SZ,
210                                  (CONST BYTE*)(buf), 78);
211             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
212         }
213
214         if (list->version) {
215             res = RegSetValueExA(clsid_key, version_valuename, 0, REG_SZ,
216                                  (CONST BYTE*)(list->version),
217                                  strlen(list->version) + 1);
218             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
219         }
220
221         if (list->mimetypes) {
222             res = RegSetValueExA(clsid_key, mimetypes_valuename, 0, REG_SZ,
223                                  (CONST BYTE*)(list->mimetypes),
224                                  strlen(list->mimetypes) + 1);
225             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
226         }
227
228         if (list->extensions) {
229             res = RegSetValueExA(clsid_key, extensions_valuename, 0, REG_SZ,
230                                  (CONST BYTE*)(list->extensions),
231                                  strlen(list->extensions) + 1);
232             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
233         }
234
235         if (list->formats) {
236             HKEY formats_key;
237             GUID const * const *format;
238
239             res = RegCreateKeyExW(clsid_key, formats_keyname, 0, NULL, 0,
240                                   KEY_READ | KEY_WRITE, NULL, &formats_key, NULL);
241             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
242             for (format=list->formats; *format; ++format)
243             {
244                 HKEY format_key;
245                 StringFromGUID2(*format, buf, 39);
246                 res = RegCreateKeyExW(formats_key, buf, 0, NULL, 0,
247                                       KEY_READ | KEY_WRITE, NULL, &format_key, NULL);
248                 if (res != ERROR_SUCCESS) break;
249                 RegCloseKey(format_key);
250             }
251             RegCloseKey(formats_key);
252             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
253         }
254
255         if (list->patterns) {
256             HKEY patterns_key;
257             int i;
258
259             res = RegCreateKeyExW(clsid_key, patterns_keyname, 0, NULL, 0,
260                                   KEY_READ | KEY_WRITE, NULL, &patterns_key, NULL);
261             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
262             for (i=0; list->patterns[i].length; i++)
263             {
264                 HKEY pattern_key;
265                 static const WCHAR int_format[] = {'%','i',0};
266                 snprintfW(buf, 39, int_format, i);
267                 res = RegCreateKeyExW(patterns_key, buf, 0, NULL, 0,
268                                       KEY_READ | KEY_WRITE, NULL, &pattern_key, NULL);
269                 if (res != ERROR_SUCCESS) break;
270                 res = RegSetValueExA(pattern_key, length_valuename, 0, REG_DWORD,
271                                      (CONST BYTE*)(&list->patterns[i].length), 4);
272                 if (res == ERROR_SUCCESS)
273                     res = RegSetValueExA(pattern_key, position_valuename, 0, REG_DWORD,
274                                          (CONST BYTE*)(&list->patterns[i].position), 4);
275                 if (res == ERROR_SUCCESS)
276                     res = RegSetValueExA(pattern_key, pattern_valuename, 0, REG_BINARY,
277                                          list->patterns[i].pattern,
278                                          list->patterns[i].length);
279                 if (res == ERROR_SUCCESS)
280                     res = RegSetValueExA(pattern_key, mask_valuename, 0, REG_BINARY,
281                                          list->patterns[i].mask,
282                                          list->patterns[i].length);
283                 if (res == ERROR_SUCCESS)
284                     res = RegSetValueExA(pattern_key, endofstream_valuename, 0, REG_DWORD,
285                                          (CONST BYTE*)&(list->patterns[i].endofstream), 4);
286                 RegCloseKey(pattern_key);
287             }
288             RegCloseKey(patterns_key);
289             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
290         }
291
292     error_close_clsid_key:
293         RegCloseKey(clsid_key);
294     }
295
296 error_close_coclass_key:
297     RegCloseKey(instance_key);
298     RegCloseKey(decoders_key);
299     RegCloseKey(coclass_key);
300 error_return:
301     return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
302 }
303
304 /***********************************************************************
305  *              unregister_decoders
306  */
307 static HRESULT unregister_decoders(struct regsvr_decoder const *list)
308 {
309     LONG res = ERROR_SUCCESS;
310     HKEY coclass_key;
311     WCHAR buf[39];
312     HKEY decoders_key;
313     HKEY instance_key;
314
315     res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0,
316                         KEY_READ | KEY_WRITE, &coclass_key);
317     if (res == ERROR_FILE_NOT_FOUND) return S_OK;
318
319     if (res == ERROR_SUCCESS)  {
320         StringFromGUID2(&CATID_WICBitmapDecoders, buf, 39);
321         res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
322                               KEY_READ | KEY_WRITE, NULL, &decoders_key, NULL);
323         if (res == ERROR_SUCCESS)
324         {
325             res = RegCreateKeyExW(decoders_key, instance_keyname, 0, NULL, 0,
326                               KEY_READ | KEY_WRITE, NULL, &instance_key, NULL);
327             if (res != ERROR_SUCCESS) goto error_close_coclass_key;
328         }
329         if (res != ERROR_SUCCESS)
330             RegCloseKey(coclass_key);
331     }
332     if (res != ERROR_SUCCESS) goto error_return;
333
334     for (; res == ERROR_SUCCESS && list->clsid; ++list) {
335         StringFromGUID2(list->clsid, buf, 39);
336
337         res = RegDeleteTreeW(coclass_key, buf);
338         if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
339         if (res != ERROR_SUCCESS) goto error_close_coclass_key;
340
341         res = RegDeleteTreeW(instance_key, buf);
342         if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
343         if (res != ERROR_SUCCESS) goto error_close_coclass_key;
344     }
345
346 error_close_coclass_key:
347     RegCloseKey(instance_key);
348     RegCloseKey(decoders_key);
349     RegCloseKey(coclass_key);
350 error_return:
351     return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
352 }
353
354 /***********************************************************************
355  *              register_encoders
356  */
357 static HRESULT register_encoders(struct regsvr_encoder const *list)
358 {
359     LONG res = ERROR_SUCCESS;
360     HKEY coclass_key;
361     WCHAR buf[39];
362     HKEY encoders_key;
363     HKEY instance_key;
364
365     res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0,
366                           KEY_READ | KEY_WRITE, NULL, &coclass_key, NULL);
367     if (res == ERROR_SUCCESS)  {
368         StringFromGUID2(&CATID_WICBitmapEncoders, buf, 39);
369         res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
370                               KEY_READ | KEY_WRITE, NULL, &encoders_key, NULL);
371         if (res == ERROR_SUCCESS)
372         {
373             res = RegCreateKeyExW(encoders_key, instance_keyname, 0, NULL, 0,
374                               KEY_READ | KEY_WRITE, NULL, &instance_key, NULL);
375             if (res != ERROR_SUCCESS) goto error_close_coclass_key;
376         }
377         if (res != ERROR_SUCCESS)
378             RegCloseKey(coclass_key);
379     }
380     if (res != ERROR_SUCCESS) goto error_return;
381
382     for (; res == ERROR_SUCCESS && list->clsid; ++list) {
383         HKEY clsid_key;
384         HKEY instance_clsid_key;
385
386         StringFromGUID2(list->clsid, buf, 39);
387         res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
388                               KEY_READ | KEY_WRITE, NULL, &clsid_key, NULL);
389         if (res != ERROR_SUCCESS) goto error_close_coclass_key;
390
391         StringFromGUID2(list->clsid, buf, 39);
392         res = RegCreateKeyExW(instance_key, buf, 0, NULL, 0,
393                               KEY_READ | KEY_WRITE, NULL, &instance_clsid_key, NULL);
394         if (res == ERROR_SUCCESS) {
395             res = RegSetValueExW(instance_clsid_key, clsid_valuename, 0, REG_SZ,
396                                  (CONST BYTE*)(buf), 78);
397             RegCloseKey(instance_clsid_key);
398         }
399         if (res != ERROR_SUCCESS) goto error_close_clsid_key;
400
401         if (list->author) {
402             res = RegSetValueExA(clsid_key, author_valuename, 0, REG_SZ,
403                                  (CONST BYTE*)(list->author),
404                                  strlen(list->author) + 1);
405             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
406         }
407
408         if (list->friendlyname) {
409             res = RegSetValueExA(clsid_key, friendlyname_valuename, 0, REG_SZ,
410                                  (CONST BYTE*)(list->friendlyname),
411                                  strlen(list->friendlyname) + 1);
412             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
413         }
414
415         if (list->vendor) {
416             StringFromGUID2(list->vendor, buf, 39);
417             res = RegSetValueExW(clsid_key, vendor_valuename, 0, REG_SZ,
418                                  (CONST BYTE*)(buf), 78);
419             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
420         }
421
422         if (list->container_format) {
423             StringFromGUID2(list->container_format, buf, 39);
424             res = RegSetValueExW(clsid_key, containerformat_valuename, 0, REG_SZ,
425                                  (CONST BYTE*)(buf), 78);
426             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
427         }
428
429         if (list->version) {
430             res = RegSetValueExA(clsid_key, version_valuename, 0, REG_SZ,
431                                  (CONST BYTE*)(list->version),
432                                  strlen(list->version) + 1);
433             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
434         }
435
436         if (list->mimetypes) {
437             res = RegSetValueExA(clsid_key, mimetypes_valuename, 0, REG_SZ,
438                                  (CONST BYTE*)(list->mimetypes),
439                                  strlen(list->mimetypes) + 1);
440             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
441         }
442
443         if (list->extensions) {
444             res = RegSetValueExA(clsid_key, extensions_valuename, 0, REG_SZ,
445                                  (CONST BYTE*)(list->extensions),
446                                  strlen(list->extensions) + 1);
447             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
448         }
449
450         if (list->formats) {
451             HKEY formats_key;
452             GUID const * const *format;
453
454             res = RegCreateKeyExW(clsid_key, formats_keyname, 0, NULL, 0,
455                                   KEY_READ | KEY_WRITE, NULL, &formats_key, NULL);
456             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
457             for (format=list->formats; *format; ++format)
458             {
459                 HKEY format_key;
460                 StringFromGUID2(*format, buf, 39);
461                 res = RegCreateKeyExW(formats_key, buf, 0, NULL, 0,
462                                       KEY_READ | KEY_WRITE, NULL, &format_key, NULL);
463                 if (res != ERROR_SUCCESS) break;
464                 RegCloseKey(format_key);
465             }
466             RegCloseKey(formats_key);
467             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
468         }
469
470     error_close_clsid_key:
471         RegCloseKey(clsid_key);
472     }
473
474 error_close_coclass_key:
475     RegCloseKey(instance_key);
476     RegCloseKey(encoders_key);
477     RegCloseKey(coclass_key);
478 error_return:
479     return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
480 }
481
482 /***********************************************************************
483  *              unregister_encoders
484  */
485 static HRESULT unregister_encoders(struct regsvr_encoder const *list)
486 {
487     LONG res = ERROR_SUCCESS;
488     HKEY coclass_key;
489     WCHAR buf[39];
490     HKEY encoders_key;
491     HKEY instance_key;
492
493     res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0,
494                         KEY_READ | KEY_WRITE, &coclass_key);
495     if (res == ERROR_FILE_NOT_FOUND) return S_OK;
496
497     if (res == ERROR_SUCCESS)  {
498         StringFromGUID2(&CATID_WICBitmapEncoders, buf, 39);
499         res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
500                               KEY_READ | KEY_WRITE, NULL, &encoders_key, NULL);
501         if (res == ERROR_SUCCESS)
502         {
503             res = RegCreateKeyExW(encoders_key, instance_keyname, 0, NULL, 0,
504                               KEY_READ | KEY_WRITE, NULL, &instance_key, NULL);
505             if (res != ERROR_SUCCESS) goto error_close_coclass_key;
506         }
507         if (res != ERROR_SUCCESS)
508             RegCloseKey(coclass_key);
509     }
510     if (res != ERROR_SUCCESS) goto error_return;
511
512     for (; res == ERROR_SUCCESS && list->clsid; ++list) {
513         StringFromGUID2(list->clsid, buf, 39);
514
515         res = RegDeleteTreeW(coclass_key, buf);
516         if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
517         if (res != ERROR_SUCCESS) goto error_close_coclass_key;
518
519         res = RegDeleteTreeW(instance_key, buf);
520         if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
521         if (res != ERROR_SUCCESS) goto error_close_coclass_key;
522     }
523
524 error_close_coclass_key:
525     RegCloseKey(instance_key);
526     RegCloseKey(encoders_key);
527     RegCloseKey(coclass_key);
528 error_return:
529     return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
530 }
531
532 /***********************************************************************
533  *              register_converters
534  */
535 static HRESULT register_converters(struct regsvr_converter const *list)
536 {
537     LONG res = ERROR_SUCCESS;
538     HKEY coclass_key;
539     WCHAR buf[39];
540     HKEY converters_key;
541     HKEY instance_key;
542
543     res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0,
544                           KEY_READ | KEY_WRITE, NULL, &coclass_key, NULL);
545     if (res == ERROR_SUCCESS)  {
546         StringFromGUID2(&CATID_WICFormatConverters, buf, 39);
547         res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
548                               KEY_READ | KEY_WRITE, NULL, &converters_key, NULL);
549         if (res == ERROR_SUCCESS)
550         {
551             res = RegCreateKeyExW(converters_key, instance_keyname, 0, NULL, 0,
552                               KEY_READ | KEY_WRITE, NULL, &instance_key, NULL);
553             if (res != ERROR_SUCCESS) goto error_close_coclass_key;
554         }
555         if (res != ERROR_SUCCESS)
556             RegCloseKey(coclass_key);
557     }
558     if (res != ERROR_SUCCESS) goto error_return;
559
560     for (; res == ERROR_SUCCESS && list->clsid; ++list) {
561         HKEY clsid_key;
562         HKEY instance_clsid_key;
563
564         StringFromGUID2(list->clsid, buf, 39);
565         res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
566                               KEY_READ | KEY_WRITE, NULL, &clsid_key, NULL);
567         if (res != ERROR_SUCCESS) goto error_close_coclass_key;
568
569         StringFromGUID2(list->clsid, buf, 39);
570         res = RegCreateKeyExW(instance_key, buf, 0, NULL, 0,
571                               KEY_READ | KEY_WRITE, NULL, &instance_clsid_key, NULL);
572         if (res == ERROR_SUCCESS) {
573             res = RegSetValueExW(instance_clsid_key, clsid_valuename, 0, REG_SZ,
574                                  (CONST BYTE*)(buf), 78);
575             RegCloseKey(instance_clsid_key);
576         }
577         if (res != ERROR_SUCCESS) goto error_close_clsid_key;
578
579         if (list->author) {
580             res = RegSetValueExA(clsid_key, author_valuename, 0, REG_SZ,
581                                  (CONST BYTE*)(list->author),
582                                  strlen(list->author) + 1);
583             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
584         }
585
586         if (list->friendlyname) {
587             res = RegSetValueExA(clsid_key, friendlyname_valuename, 0, REG_SZ,
588                                  (CONST BYTE*)(list->friendlyname),
589                                  strlen(list->friendlyname) + 1);
590             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
591         }
592
593         if (list->vendor) {
594             StringFromGUID2(list->vendor, buf, 39);
595             res = RegSetValueExW(clsid_key, vendor_valuename, 0, REG_SZ,
596                                  (CONST BYTE*)(buf), 78);
597             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
598         }
599
600         if (list->version) {
601             res = RegSetValueExA(clsid_key, version_valuename, 0, REG_SZ,
602                                  (CONST BYTE*)(list->version),
603                                  strlen(list->version) + 1);
604             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
605         }
606
607         if (list->formats) {
608             HKEY formats_key;
609             GUID const * const *format;
610
611             res = RegCreateKeyExW(clsid_key, pixelformats_keyname, 0, NULL, 0,
612                                   KEY_READ | KEY_WRITE, NULL, &formats_key, NULL);
613             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
614             for (format=list->formats; *format; ++format)
615             {
616                 HKEY format_key;
617                 StringFromGUID2(*format, buf, 39);
618                 res = RegCreateKeyExW(formats_key, buf, 0, NULL, 0,
619                                       KEY_READ | KEY_WRITE, NULL, &format_key, NULL);
620                 if (res != ERROR_SUCCESS) break;
621                 RegCloseKey(format_key);
622             }
623             RegCloseKey(formats_key);
624             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
625         }
626
627     error_close_clsid_key:
628         RegCloseKey(clsid_key);
629     }
630
631 error_close_coclass_key:
632     RegCloseKey(instance_key);
633     RegCloseKey(converters_key);
634     RegCloseKey(coclass_key);
635 error_return:
636     return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
637 }
638
639 /***********************************************************************
640  *              unregister_converters
641  */
642 static HRESULT unregister_converters(struct regsvr_converter const *list)
643 {
644     LONG res = ERROR_SUCCESS;
645     HKEY coclass_key;
646     WCHAR buf[39];
647     HKEY converters_key;
648     HKEY instance_key;
649
650     res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0,
651                         KEY_READ | KEY_WRITE, &coclass_key);
652     if (res == ERROR_FILE_NOT_FOUND) return S_OK;
653
654     if (res == ERROR_SUCCESS)  {
655         StringFromGUID2(&CATID_WICFormatConverters, buf, 39);
656         res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
657                               KEY_READ | KEY_WRITE, NULL, &converters_key, NULL);
658         if (res == ERROR_SUCCESS)
659         {
660             res = RegCreateKeyExW(converters_key, instance_keyname, 0, NULL, 0,
661                               KEY_READ | KEY_WRITE, NULL, &instance_key, NULL);
662             if (res != ERROR_SUCCESS) goto error_close_coclass_key;
663         }
664         if (res != ERROR_SUCCESS)
665             RegCloseKey(coclass_key);
666     }
667     if (res != ERROR_SUCCESS) goto error_return;
668
669     for (; res == ERROR_SUCCESS && list->clsid; ++list) {
670         StringFromGUID2(list->clsid, buf, 39);
671
672         res = RegDeleteTreeW(coclass_key, buf);
673         if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
674         if (res != ERROR_SUCCESS) goto error_close_coclass_key;
675
676         res = RegDeleteTreeW(instance_key, buf);
677         if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
678         if (res != ERROR_SUCCESS) goto error_close_coclass_key;
679     }
680
681 error_close_coclass_key:
682     RegCloseKey(instance_key);
683     RegCloseKey(converters_key);
684     RegCloseKey(coclass_key);
685 error_return:
686     return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
687 }
688
689 /***********************************************************************
690  *              decoder list
691  */
692 static const BYTE mask_all[] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
693
694 static const BYTE bmp_magic[] = {0x42,0x4d};
695
696 static GUID const * const bmp_formats[] = {
697     &GUID_WICPixelFormat1bppIndexed,
698     &GUID_WICPixelFormat2bppIndexed,
699     &GUID_WICPixelFormat4bppIndexed,
700     &GUID_WICPixelFormat8bppIndexed,
701     &GUID_WICPixelFormat16bppBGR555,
702     &GUID_WICPixelFormat16bppBGR565,
703     &GUID_WICPixelFormat24bppBGR,
704     &GUID_WICPixelFormat32bppBGR,
705     &GUID_WICPixelFormat32bppBGRA,
706     NULL
707 };
708
709 static struct decoder_pattern const bmp_patterns[] = {
710     {2,0,bmp_magic,mask_all,0},
711     {0}
712 };
713
714 static const BYTE gif87a_magic[6] = "GIF87a";
715 static const BYTE gif89a_magic[6] = "GIF89a";
716
717 static GUID const * const gif_formats[] = {
718     &GUID_WICPixelFormat8bppIndexed,
719     NULL
720 };
721
722 static struct decoder_pattern const gif_patterns[] = {
723     {6,0,gif87a_magic,mask_all,0},
724     {6,0,gif89a_magic,mask_all,0},
725     {0}
726 };
727
728 static const BYTE ico_magic[] = {00,00,01,00};
729
730 static GUID const * const ico_formats[] = {
731     &GUID_WICPixelFormat32bppBGRA,
732     NULL
733 };
734
735 static struct decoder_pattern const ico_patterns[] = {
736     {4,0,ico_magic,mask_all,0},
737     {0}
738 };
739
740 static const BYTE jpeg_magic[] = {0xff, 0xd8};
741
742 static GUID const * const jpeg_formats[] = {
743     &GUID_WICPixelFormat24bppBGR,
744     &GUID_WICPixelFormat32bppCMYK,
745     &GUID_WICPixelFormat8bppGray,
746     NULL
747 };
748
749 static struct decoder_pattern const jpeg_patterns[] = {
750     {2,0,jpeg_magic,mask_all,0},
751     {0}
752 };
753
754 static const BYTE png_magic[] = {137,80,78,71,13,10,26,10};
755
756 static GUID const * const png_formats[] = {
757     &GUID_WICPixelFormatBlackWhite,
758     &GUID_WICPixelFormat2bppGray,
759     &GUID_WICPixelFormat4bppGray,
760     &GUID_WICPixelFormat8bppGray,
761     &GUID_WICPixelFormat16bppGray,
762     &GUID_WICPixelFormat32bppBGRA,
763     &GUID_WICPixelFormat64bppRGBA,
764     &GUID_WICPixelFormat1bppIndexed,
765     &GUID_WICPixelFormat2bppIndexed,
766     &GUID_WICPixelFormat4bppIndexed,
767     &GUID_WICPixelFormat8bppIndexed,
768     &GUID_WICPixelFormat24bppBGR,
769     &GUID_WICPixelFormat48bppRGB,
770     NULL
771 };
772
773 static struct decoder_pattern const png_patterns[] = {
774     {8,0,png_magic,mask_all,0},
775     {0}
776 };
777
778 static const BYTE tiff_magic_le[] = {0x49,0x49,42,0};
779 static const BYTE tiff_magic_be[] = {0x4d,0x4d,0,42};
780
781 static GUID const * const tiff_decode_formats[] = {
782     &GUID_WICPixelFormatBlackWhite,
783     &GUID_WICPixelFormat4bppGray,
784     &GUID_WICPixelFormat8bppGray,
785     &GUID_WICPixelFormat4bppIndexed,
786     &GUID_WICPixelFormat8bppIndexed,
787     &GUID_WICPixelFormat24bppBGR,
788     &GUID_WICPixelFormat32bppBGR,
789     &GUID_WICPixelFormat32bppBGRA,
790     &GUID_WICPixelFormat32bppPBGRA,
791     &GUID_WICPixelFormat48bppRGB,
792     &GUID_WICPixelFormat64bppRGBA,
793     &GUID_WICPixelFormat64bppPRGBA,
794     NULL
795 };
796
797 static struct decoder_pattern const tiff_patterns[] = {
798     {4,0,tiff_magic_le,mask_all,0},
799     {4,0,tiff_magic_be,mask_all,0},
800     {0}
801 };
802
803 static const BYTE tga_footer_magic[18] = "TRUEVISION-XFILE.";
804
805 static const BYTE tga_indexed_magic[18] = {0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0};
806 static const BYTE tga_indexed_mask[18] = {0,0xff,0xf7,0,0,0,0,0,0,0,0,0,0,0,0,0,0xff,0xcf};
807
808 static const BYTE tga_truecolor_magic[18] = {0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
809 static const BYTE tga_truecolor_mask[18] = {0,0xff,0xf7,0,0,0,0,0,0,0,0,0,0,0,0,0,0x87,0xc0};
810
811 static const BYTE tga_grayscale_magic[18] = {0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0};
812 static const BYTE tga_grayscale_mask[18] = {0,0xff,0xf7,0,0,0,0,0,0,0,0,0,0,0,0,0,0xff,0xcf};
813
814 static GUID const * const tga_formats[] = {
815     &GUID_WICPixelFormat8bppGray,
816     &GUID_WICPixelFormat8bppIndexed,
817     &GUID_WICPixelFormat16bppGray,
818     &GUID_WICPixelFormat16bppBGR555,
819     &GUID_WICPixelFormat24bppBGR,
820     &GUID_WICPixelFormat32bppBGRA,
821     &GUID_WICPixelFormat32bppPBGRA,
822     NULL
823 };
824
825 static struct decoder_pattern const tga_patterns[] = {
826     {18,18,tga_footer_magic,mask_all,1},
827     {18,0,tga_indexed_magic,tga_indexed_mask,0},
828     {18,0,tga_truecolor_magic,tga_truecolor_mask,0},
829     {18,0,tga_grayscale_magic,tga_grayscale_mask,0},
830     {0}
831 };
832
833 static struct regsvr_decoder const decoder_list[] = {
834     {   &CLSID_WICBmpDecoder,
835         "The Wine Project",
836         "BMP Decoder",
837         "1.0.0.0",
838         &GUID_VendorMicrosoft,
839         &GUID_ContainerFormatBmp,
840         "image/bmp",
841         ".bmp,.dib,.rle",
842         bmp_formats,
843         bmp_patterns
844     },
845     {   &CLSID_WICGifDecoder,
846         "The Wine Project",
847         "GIF Decoder",
848         "1.0.0.0",
849         &GUID_VendorMicrosoft,
850         &GUID_ContainerFormatGif,
851         "image/gif",
852         ".gif",
853         gif_formats,
854         gif_patterns
855     },
856     {   &CLSID_WICIcoDecoder,
857         "The Wine Project",
858         "ICO Decoder",
859         "1.0.0.0",
860         &GUID_VendorMicrosoft,
861         &GUID_ContainerFormatIco,
862         "image/vnd.microsoft.icon",
863         ".ico",
864         ico_formats,
865         ico_patterns
866     },
867     {   &CLSID_WICJpegDecoder,
868         "The Wine Project",
869         "JPEG Decoder",
870         "1.0.0.0",
871         &GUID_VendorMicrosoft,
872         &GUID_ContainerFormatJpeg,
873         "image/jpeg",
874         ".jpg;.jpeg;.jfif",
875         jpeg_formats,
876         jpeg_patterns
877     },
878     {   &CLSID_WICPngDecoder,
879         "The Wine Project",
880         "PNG Decoder",
881         "1.0.0.0",
882         &GUID_VendorMicrosoft,
883         &GUID_ContainerFormatPng,
884         "image/png",
885         ".png",
886         png_formats,
887         png_patterns
888     },
889     {   &CLSID_WICTiffDecoder,
890         "The Wine Project",
891         "TIFF Decoder",
892         "1.0.0.0",
893         &GUID_VendorMicrosoft,
894         &GUID_ContainerFormatTiff,
895         "image/tiff",
896         ".tif;.tiff",
897         tiff_decode_formats,
898         tiff_patterns
899     },
900     {   &CLSID_WineTgaDecoder,
901         "The Wine Project",
902         "TGA Decoder",
903         "1.0.0.0",
904         &GUID_VendorWine,
905         &GUID_WineContainerFormatTga,
906         "image/x-targa",
907         ".tga;.tpic",
908         tga_formats,
909         tga_patterns
910     },
911     { NULL }                    /* list terminator */
912 };
913
914 static GUID const * const bmp_encode_formats[] = {
915     &GUID_WICPixelFormat16bppBGR555,
916     &GUID_WICPixelFormat16bppBGR565,
917     &GUID_WICPixelFormat24bppBGR,
918     &GUID_WICPixelFormat32bppBGR,
919     NULL
920 };
921
922 static GUID const * const png_encode_formats[] = {
923     &GUID_WICPixelFormat24bppBGR,
924     &GUID_WICPixelFormatBlackWhite,
925     &GUID_WICPixelFormat2bppGray,
926     &GUID_WICPixelFormat4bppGray,
927     &GUID_WICPixelFormat8bppGray,
928     &GUID_WICPixelFormat16bppGray,
929     &GUID_WICPixelFormat32bppBGR,
930     &GUID_WICPixelFormat32bppBGRA,
931     &GUID_WICPixelFormat48bppRGB,
932     &GUID_WICPixelFormat64bppRGBA,
933     NULL
934 };
935
936 static GUID const * const tiff_encode_formats[] = {
937     &GUID_WICPixelFormatBlackWhite,
938     &GUID_WICPixelFormat4bppGray,
939     &GUID_WICPixelFormat8bppGray,
940     &GUID_WICPixelFormat24bppBGR,
941     &GUID_WICPixelFormat32bppBGRA,
942     &GUID_WICPixelFormat32bppPBGRA,
943     &GUID_WICPixelFormat48bppRGB,
944     &GUID_WICPixelFormat64bppRGBA,
945     &GUID_WICPixelFormat64bppPRGBA,
946     NULL
947 };
948
949 static GUID const * const icns_encode_formats[] = {
950     &GUID_WICPixelFormat32bppBGRA,
951     NULL
952 };
953
954 static struct regsvr_encoder const encoder_list[] = {
955     {   &CLSID_WICBmpEncoder,
956         "The Wine Project",
957         "BMP Encoder",
958         "1.0.0.0",
959         &GUID_VendorMicrosoft,
960         &GUID_ContainerFormatBmp,
961         "image/bmp",
962         ".bmp,.dib,.rle",
963         bmp_encode_formats
964     },
965     {   &CLSID_WICJpegEncoder,
966         "The Wine Project",
967         "JPEG Encoder",
968         "1.0.0.0",
969         &GUID_VendorMicrosoft,
970         &GUID_ContainerFormatJpeg,
971         "image/jpeg",
972         ".jpg;.jpeg;.jfif",
973         jpeg_formats
974     },
975     {   &CLSID_WICPngEncoder,
976         "The Wine Project",
977         "PNG Encoder",
978         "1.0.0.0",
979         &GUID_VendorMicrosoft,
980         &GUID_ContainerFormatPng,
981         "image/png",
982         ".png",
983         png_encode_formats
984     },
985     {   &CLSID_WICTiffEncoder,
986         "The Wine Project",
987         "TIFF Encoder",
988         "1.0.0.0",
989         &GUID_VendorMicrosoft,
990         &GUID_ContainerFormatTiff,
991         "image/tiff",
992         ".tif;.tiff",
993         tiff_encode_formats
994     },
995     {   &CLSID_WICIcnsEncoder,
996         "The Wine Project",
997         "ICNS Encoder",
998         "1.0.0.0",
999         &GUID_VendorWine,
1000         NULL, /* no container format guid */
1001         "image/icns",
1002         ".icns",
1003         icns_encode_formats
1004     },
1005     { NULL }                    /* list terminator */
1006 };
1007
1008 static GUID const * const converter_formats[] = {
1009     &GUID_WICPixelFormat1bppIndexed,
1010     &GUID_WICPixelFormat2bppIndexed,
1011     &GUID_WICPixelFormat4bppIndexed,
1012     &GUID_WICPixelFormat8bppIndexed,
1013     &GUID_WICPixelFormatBlackWhite,
1014     &GUID_WICPixelFormat2bppGray,
1015     &GUID_WICPixelFormat4bppGray,
1016     &GUID_WICPixelFormat8bppGray,
1017     &GUID_WICPixelFormat16bppGray,
1018     &GUID_WICPixelFormat16bppBGR555,
1019     &GUID_WICPixelFormat16bppBGR565,
1020     &GUID_WICPixelFormat16bppBGRA5551,
1021     &GUID_WICPixelFormat24bppBGR,
1022     &GUID_WICPixelFormat32bppBGR,
1023     &GUID_WICPixelFormat32bppBGRA,
1024     &GUID_WICPixelFormat32bppPBGRA,
1025     &GUID_WICPixelFormat48bppRGB,
1026     &GUID_WICPixelFormat64bppRGBA,
1027     &GUID_WICPixelFormat32bppCMYK,
1028     NULL
1029 };
1030
1031 static struct regsvr_converter const converter_list[] = {
1032     {   &CLSID_WICDefaultFormatConverter,
1033         "The Wine Project",
1034         "Default Pixel Format Converter",
1035         "1.0.0.0",
1036         &GUID_VendorMicrosoft,
1037         converter_formats
1038     },
1039     { NULL }                    /* list terminator */
1040 };
1041
1042 extern HRESULT WINAPI WIC_DllRegisterServer(void) DECLSPEC_HIDDEN;
1043 extern HRESULT WINAPI WIC_DllUnregisterServer(void) DECLSPEC_HIDDEN;
1044
1045 HRESULT WINAPI DllRegisterServer(void)
1046 {
1047     HRESULT hr;
1048
1049     TRACE("\n");
1050
1051     hr = WIC_DllRegisterServer();
1052     if (SUCCEEDED(hr))
1053         register_decoders(decoder_list);
1054     if (SUCCEEDED(hr))
1055         register_encoders(encoder_list);
1056     if (SUCCEEDED(hr))
1057         register_converters(converter_list);
1058     return hr;
1059 }
1060
1061 HRESULT WINAPI DllUnregisterServer(void)
1062 {
1063     HRESULT hr;
1064
1065     TRACE("\n");
1066
1067     hr = WIC_DllUnregisterServer();
1068     if (SUCCEEDED(hr))
1069         unregister_decoders(decoder_list);
1070     if (SUCCEEDED(hr))
1071         unregister_encoders(encoder_list);
1072     if (SUCCEEDED(hr))
1073         unregister_converters(converter_list);
1074     return hr;
1075 }