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