xref: /reactos/dll/win32/windowscodecs/regsvr.c (revision 845faec4)
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 COBJMACROS
20 #include <stdarg.h>
21 #include <string.h>
22 
23 #include "windef.h"
24 #include "winbase.h"
25 #include "wingdi.h"
26 #include "winuser.h"
27 #include "winreg.h"
28 #include "winerror.h"
29 
30 #include "objbase.h"
31 #include "ocidl.h"
32 
33 #include "wine/debug.h"
34 #include "wine/unicode.h"
35 
36 #include "wincodecs_private.h"
37 
38 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
39 
40 /***********************************************************************
41  *		interface for self-registering
42  */
43 struct decoder_pattern
44 {
45     DWORD length;    /* 0 for end of list */
46     DWORD position;
47     const BYTE *pattern;
48     const BYTE *mask;
49     DWORD endofstream;
50 };
51 
52 struct regsvr_decoder
53 {
54     CLSID const *clsid;         /* NULL for end of list */
55     LPCSTR author;
56     LPCSTR friendlyname;
57     LPCSTR version;
58     GUID const *vendor;
59     GUID const *container_format;
60     LPCSTR mimetypes;
61     LPCSTR extensions;
62     GUID const * const *formats;
63     const struct decoder_pattern *patterns;
64 };
65 
66 static HRESULT register_decoders(struct regsvr_decoder const *list);
67 static HRESULT unregister_decoders(struct regsvr_decoder const *list);
68 
69 struct regsvr_encoder
70 {
71     CLSID const *clsid;         /* NULL for end of list */
72     LPCSTR author;
73     LPCSTR friendlyname;
74     LPCSTR version;
75     GUID const *vendor;
76     GUID const *container_format;
77     LPCSTR mimetypes;
78     LPCSTR extensions;
79     GUID const * const *formats;
80 };
81 
82 static HRESULT register_encoders(struct regsvr_encoder const *list);
83 static HRESULT unregister_encoders(struct regsvr_encoder const *list);
84 
85 struct regsvr_converter
86 {
87     CLSID const *clsid;         /* NULL for end of list */
88     LPCSTR author;
89     LPCSTR friendlyname;
90     LPCSTR version;
91     GUID const *vendor;
92     GUID const * const *formats;
93 };
94 
95 static HRESULT register_converters(struct regsvr_converter const *list);
96 static HRESULT unregister_converters(struct regsvr_converter const *list);
97 
98 struct metadata_pattern
99 {
100     DWORD position;
101     DWORD length;
102     const BYTE *pattern;
103     const BYTE *mask;
104     DWORD data_offset;
105 };
106 
107 struct reader_containers
108 {
109     GUID const *format;
110     const struct metadata_pattern *patterns;
111 };
112 
113 struct regsvr_metadatareader
114 {
115     CLSID const *clsid;         /* NULL for end of list */
116     LPCSTR author;
117     LPCSTR friendlyname;
118     LPCSTR version;
119     LPCSTR specversion;
120     GUID const *vendor;
121     GUID const *metadata_format;
122     DWORD requires_fullstream;
123     DWORD supports_padding;
124     DWORD requires_fixedsize;
125     const struct reader_containers *containers;
126 };
127 
128 static HRESULT register_metadatareaders(struct regsvr_metadatareader const *list);
129 static HRESULT unregister_metadatareaders(struct regsvr_metadatareader const *list);
130 
131 struct regsvr_pixelformat
132 {
133     CLSID const *clsid;         /* NULL for end of list */
134     LPCSTR author;
135     LPCSTR friendlyname;
136     LPCSTR version;
137     GUID const *vendor;
138     UINT bitsperpixel;
139     UINT channelcount;
140     BYTE const * const *channelmasks;
141     WICPixelFormatNumericRepresentation numericrepresentation;
142     UINT supportsalpha;
143 };
144 
145 static HRESULT register_pixelformats(struct regsvr_pixelformat const *list);
146 static HRESULT unregister_pixelformats(struct regsvr_pixelformat const *list);
147 
148 /***********************************************************************
149  *		static string constants
150  */
151 static const WCHAR clsid_keyname[] = {
152     'C', 'L', 'S', 'I', 'D', 0 };
153 static const char author_valuename[] = "Author";
154 static const char friendlyname_valuename[] = "FriendlyName";
155 static const WCHAR vendor_valuename[] = {'V','e','n','d','o','r',0};
156 static const WCHAR containerformat_valuename[] = {'C','o','n','t','a','i','n','e','r','F','o','r','m','a','t',0};
157 static const char version_valuename[] = "Version";
158 static const char mimetypes_valuename[] = "MimeTypes";
159 static const char extensions_valuename[] = "FileExtensions";
160 static const WCHAR formats_keyname[] = {'F','o','r','m','a','t','s',0};
161 static const WCHAR patterns_keyname[] = {'P','a','t','t','e','r','n','s',0};
162 static const WCHAR instance_keyname[] = {'I','n','s','t','a','n','c','e',0};
163 static const WCHAR clsid_valuename[] = {'C','L','S','I','D',0};
164 static const char length_valuename[] = "Length";
165 static const char position_valuename[] = "Position";
166 static const char pattern_valuename[] = "Pattern";
167 static const char mask_valuename[] = "Mask";
168 static const char endofstream_valuename[] = "EndOfStream";
169 static const WCHAR pixelformats_keyname[] = {'P','i','x','e','l','F','o','r','m','a','t','s',0};
170 static const WCHAR metadataformat_valuename[] = {'M','e','t','a','d','a','t','a','F','o','r','m','a','t',0};
171 static const char specversion_valuename[] = "SpecVersion";
172 static const char requiresfullstream_valuename[] = "RequiresFullStream";
173 static const char supportspadding_valuename[] = "SupportsPadding";
174 static const char requiresfixedsize_valuename[] = "FixedSize";
175 static const WCHAR containers_keyname[] = {'C','o','n','t','a','i','n','e','r','s',0};
176 static const char dataoffset_valuename[] = "DataOffset";
177 static const char bitsperpixel_valuename[] = "BitLength";
178 static const char channelcount_valuename[] = "ChannelCount";
179 static const char numericrepresentation_valuename[] = "NumericRepresentation";
180 static const char supportstransparency_valuename[] = "SupportsTransparency";
181 static const WCHAR channelmasks_keyname[] = {'C','h','a','n','n','e','l','M','a','s','k','s',0};
182 
183 /***********************************************************************
184  *		register_decoders
185  */
186 static HRESULT register_decoders(struct regsvr_decoder const *list)
187 {
188     LONG res = ERROR_SUCCESS;
189     HKEY coclass_key;
190     WCHAR buf[39];
191     HKEY decoders_key;
192     HKEY instance_key;
193 
194     res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0,
195 			  KEY_READ | KEY_WRITE, NULL, &coclass_key, NULL);
196     if (res == ERROR_SUCCESS)  {
197         StringFromGUID2(&CATID_WICBitmapDecoders, buf, 39);
198         res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
199 			      KEY_READ | KEY_WRITE, NULL, &decoders_key, NULL);
200         if (res == ERROR_SUCCESS)
201         {
202             res = RegCreateKeyExW(decoders_key, instance_keyname, 0, NULL, 0,
203 		              KEY_READ | KEY_WRITE, NULL, &instance_key, NULL);
204             if (res != ERROR_SUCCESS) goto error_close_coclass_key;
205         }
206         if (res != ERROR_SUCCESS)
207             RegCloseKey(coclass_key);
208     }
209     if (res != ERROR_SUCCESS) goto error_return;
210 
211     for (; res == ERROR_SUCCESS && list->clsid; ++list) {
212 	HKEY clsid_key;
213 	HKEY instance_clsid_key;
214 
215 	StringFromGUID2(list->clsid, buf, 39);
216 	res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
217 			      KEY_READ | KEY_WRITE, NULL, &clsid_key, NULL);
218 	if (res != ERROR_SUCCESS) goto error_close_coclass_key;
219 
220 	StringFromGUID2(list->clsid, buf, 39);
221 	res = RegCreateKeyExW(instance_key, buf, 0, NULL, 0,
222 			      KEY_READ | KEY_WRITE, NULL, &instance_clsid_key, NULL);
223 	if (res == ERROR_SUCCESS) {
224 	    res = RegSetValueExW(instance_clsid_key, clsid_valuename, 0, REG_SZ,
225                                  (const BYTE*)buf, 78);
226 	    RegCloseKey(instance_clsid_key);
227 	}
228 	if (res != ERROR_SUCCESS) goto error_close_clsid_key;
229 
230         if (list->author) {
231 	    res = RegSetValueExA(clsid_key, author_valuename, 0, REG_SZ,
232                                  (const BYTE*)list->author,
233 				 strlen(list->author) + 1);
234 	    if (res != ERROR_SUCCESS) goto error_close_clsid_key;
235         }
236 
237         if (list->friendlyname) {
238 	    res = RegSetValueExA(clsid_key, friendlyname_valuename, 0, REG_SZ,
239                                  (const BYTE*)list->friendlyname,
240 				 strlen(list->friendlyname) + 1);
241 	    if (res != ERROR_SUCCESS) goto error_close_clsid_key;
242         }
243 
244         if (list->vendor) {
245             StringFromGUID2(list->vendor, buf, 39);
246 	    res = RegSetValueExW(clsid_key, vendor_valuename, 0, REG_SZ,
247                                  (const BYTE*)buf, 78);
248 	    if (res != ERROR_SUCCESS) goto error_close_clsid_key;
249         }
250 
251         if (list->container_format) {
252             StringFromGUID2(list->container_format, buf, 39);
253 	    res = RegSetValueExW(clsid_key, containerformat_valuename, 0, REG_SZ,
254                                  (const BYTE*)buf, 78);
255 	    if (res != ERROR_SUCCESS) goto error_close_clsid_key;
256         }
257 
258         if (list->version) {
259 	    res = RegSetValueExA(clsid_key, version_valuename, 0, REG_SZ,
260                                  (const BYTE*)list->version,
261 				 strlen(list->version) + 1);
262 	    if (res != ERROR_SUCCESS) goto error_close_clsid_key;
263         }
264 
265         if (list->mimetypes) {
266 	    res = RegSetValueExA(clsid_key, mimetypes_valuename, 0, REG_SZ,
267                                  (const BYTE*)list->mimetypes,
268 				 strlen(list->mimetypes) + 1);
269 	    if (res != ERROR_SUCCESS) goto error_close_clsid_key;
270         }
271 
272         if (list->extensions) {
273 	    res = RegSetValueExA(clsid_key, extensions_valuename, 0, REG_SZ,
274                                  (const BYTE*)list->extensions,
275 				 strlen(list->extensions) + 1);
276 	    if (res != ERROR_SUCCESS) goto error_close_clsid_key;
277         }
278 
279         if (list->formats) {
280             HKEY formats_key;
281             GUID const * const *format;
282 
283             res = RegCreateKeyExW(clsid_key, formats_keyname, 0, NULL, 0,
284                                   KEY_READ | KEY_WRITE, NULL, &formats_key, NULL);
285             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
286             for (format=list->formats; *format; ++format)
287             {
288                 HKEY format_key;
289                 StringFromGUID2(*format, buf, 39);
290                 res = RegCreateKeyExW(formats_key, buf, 0, NULL, 0,
291                                       KEY_READ | KEY_WRITE, NULL, &format_key, NULL);
292                 if (res != ERROR_SUCCESS) break;
293                 RegCloseKey(format_key);
294             }
295             RegCloseKey(formats_key);
296             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
297         }
298 
299         if (list->patterns) {
300             HKEY patterns_key;
301             int i;
302 
303             res = RegCreateKeyExW(clsid_key, patterns_keyname, 0, NULL, 0,
304                                   KEY_READ | KEY_WRITE, NULL, &patterns_key, NULL);
305             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
306             for (i=0; list->patterns[i].length; i++)
307             {
308                 HKEY pattern_key;
309                 static const WCHAR int_format[] = {'%','i',0};
310                 snprintfW(buf, 39, int_format, i);
311                 res = RegCreateKeyExW(patterns_key, buf, 0, NULL, 0,
312                                       KEY_READ | KEY_WRITE, NULL, &pattern_key, NULL);
313                 if (res != ERROR_SUCCESS) break;
314 	        res = RegSetValueExA(pattern_key, length_valuename, 0, REG_DWORD,
315                                      (const BYTE*)&list->patterns[i].length, 4);
316                 if (res == ERROR_SUCCESS)
317 	            res = RegSetValueExA(pattern_key, position_valuename, 0, REG_DWORD,
318                                          (const BYTE*)&list->patterns[i].position, 4);
319                 if (res == ERROR_SUCCESS)
320 	            res = RegSetValueExA(pattern_key, pattern_valuename, 0, REG_BINARY,
321 				         list->patterns[i].pattern,
322 				         list->patterns[i].length);
323                 if (res == ERROR_SUCCESS)
324 	            res = RegSetValueExA(pattern_key, mask_valuename, 0, REG_BINARY,
325 				         list->patterns[i].mask,
326 				         list->patterns[i].length);
327                 if (res == ERROR_SUCCESS)
328 	            res = RegSetValueExA(pattern_key, endofstream_valuename, 0, REG_DWORD,
329                                          (const BYTE*)&list->patterns[i].endofstream, 4);
330                 RegCloseKey(pattern_key);
331             }
332             RegCloseKey(patterns_key);
333             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
334         }
335 
336     error_close_clsid_key:
337 	RegCloseKey(clsid_key);
338     }
339 
340 error_close_coclass_key:
341     RegCloseKey(instance_key);
342     RegCloseKey(decoders_key);
343     RegCloseKey(coclass_key);
344 error_return:
345     return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
346 }
347 
348 /***********************************************************************
349  *		unregister_decoders
350  */
351 static HRESULT unregister_decoders(struct regsvr_decoder const *list)
352 {
353     LONG res = ERROR_SUCCESS;
354     HKEY coclass_key;
355     WCHAR buf[39];
356     HKEY decoders_key;
357     HKEY instance_key;
358 
359     res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0,
360 			KEY_READ | KEY_WRITE, &coclass_key);
361     if (res == ERROR_FILE_NOT_FOUND) return S_OK;
362 
363     if (res == ERROR_SUCCESS)  {
364         StringFromGUID2(&CATID_WICBitmapDecoders, buf, 39);
365         res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
366 			      KEY_READ | KEY_WRITE, NULL, &decoders_key, NULL);
367         if (res == ERROR_SUCCESS)
368         {
369             res = RegCreateKeyExW(decoders_key, instance_keyname, 0, NULL, 0,
370 		              KEY_READ | KEY_WRITE, NULL, &instance_key, NULL);
371             if (res != ERROR_SUCCESS) goto error_close_coclass_key;
372         }
373         if (res != ERROR_SUCCESS)
374             RegCloseKey(coclass_key);
375     }
376     if (res != ERROR_SUCCESS) goto error_return;
377 
378     for (; res == ERROR_SUCCESS && list->clsid; ++list) {
379 	StringFromGUID2(list->clsid, buf, 39);
380 
381 	res = RegDeleteTreeW(coclass_key, buf);
382 	if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
383 	if (res != ERROR_SUCCESS) goto error_close_coclass_key;
384 
385 	res = RegDeleteTreeW(instance_key, buf);
386 	if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
387 	if (res != ERROR_SUCCESS) goto error_close_coclass_key;
388     }
389 
390 error_close_coclass_key:
391     RegCloseKey(instance_key);
392     RegCloseKey(decoders_key);
393     RegCloseKey(coclass_key);
394 error_return:
395     return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
396 }
397 
398 /***********************************************************************
399  *		register_encoders
400  */
401 static HRESULT register_encoders(struct regsvr_encoder const *list)
402 {
403     LONG res = ERROR_SUCCESS;
404     HKEY coclass_key;
405     WCHAR buf[39];
406     HKEY encoders_key;
407     HKEY instance_key;
408 
409     res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0,
410 			  KEY_READ | KEY_WRITE, NULL, &coclass_key, NULL);
411     if (res == ERROR_SUCCESS)  {
412         StringFromGUID2(&CATID_WICBitmapEncoders, buf, 39);
413         res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
414 			      KEY_READ | KEY_WRITE, NULL, &encoders_key, NULL);
415         if (res == ERROR_SUCCESS)
416         {
417             res = RegCreateKeyExW(encoders_key, instance_keyname, 0, NULL, 0,
418 		              KEY_READ | KEY_WRITE, NULL, &instance_key, NULL);
419             if (res != ERROR_SUCCESS) goto error_close_coclass_key;
420         }
421         if (res != ERROR_SUCCESS)
422             RegCloseKey(coclass_key);
423     }
424     if (res != ERROR_SUCCESS) goto error_return;
425 
426     for (; res == ERROR_SUCCESS && list->clsid; ++list) {
427 	HKEY clsid_key;
428 	HKEY instance_clsid_key;
429 
430 	StringFromGUID2(list->clsid, buf, 39);
431 	res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
432 			      KEY_READ | KEY_WRITE, NULL, &clsid_key, NULL);
433 	if (res != ERROR_SUCCESS) goto error_close_coclass_key;
434 
435 	StringFromGUID2(list->clsid, buf, 39);
436 	res = RegCreateKeyExW(instance_key, buf, 0, NULL, 0,
437 			      KEY_READ | KEY_WRITE, NULL, &instance_clsid_key, NULL);
438 	if (res == ERROR_SUCCESS) {
439 	    res = RegSetValueExW(instance_clsid_key, clsid_valuename, 0, REG_SZ,
440                                  (const BYTE*)buf, 78);
441 	    RegCloseKey(instance_clsid_key);
442 	}
443 	if (res != ERROR_SUCCESS) goto error_close_clsid_key;
444 
445         if (list->author) {
446 	    res = RegSetValueExA(clsid_key, author_valuename, 0, REG_SZ,
447                                  (const BYTE*)list->author,
448 				 strlen(list->author) + 1);
449 	    if (res != ERROR_SUCCESS) goto error_close_clsid_key;
450         }
451 
452         if (list->friendlyname) {
453 	    res = RegSetValueExA(clsid_key, friendlyname_valuename, 0, REG_SZ,
454                                  (const BYTE*)list->friendlyname,
455 				 strlen(list->friendlyname) + 1);
456 	    if (res != ERROR_SUCCESS) goto error_close_clsid_key;
457         }
458 
459         if (list->vendor) {
460             StringFromGUID2(list->vendor, buf, 39);
461 	    res = RegSetValueExW(clsid_key, vendor_valuename, 0, REG_SZ,
462                                  (const BYTE*)buf, 78);
463 	    if (res != ERROR_SUCCESS) goto error_close_clsid_key;
464         }
465 
466         if (list->container_format) {
467             StringFromGUID2(list->container_format, buf, 39);
468 	    res = RegSetValueExW(clsid_key, containerformat_valuename, 0, REG_SZ,
469                                  (const BYTE*)buf, 78);
470 	    if (res != ERROR_SUCCESS) goto error_close_clsid_key;
471         }
472 
473         if (list->version) {
474 	    res = RegSetValueExA(clsid_key, version_valuename, 0, REG_SZ,
475                                  (const BYTE*)list->version,
476 				 strlen(list->version) + 1);
477 	    if (res != ERROR_SUCCESS) goto error_close_clsid_key;
478         }
479 
480         if (list->mimetypes) {
481 	    res = RegSetValueExA(clsid_key, mimetypes_valuename, 0, REG_SZ,
482                                  (const BYTE*)list->mimetypes,
483 				 strlen(list->mimetypes) + 1);
484 	    if (res != ERROR_SUCCESS) goto error_close_clsid_key;
485         }
486 
487         if (list->extensions) {
488 	    res = RegSetValueExA(clsid_key, extensions_valuename, 0, REG_SZ,
489                                  (const BYTE*)list->extensions,
490 				 strlen(list->extensions) + 1);
491 	    if (res != ERROR_SUCCESS) goto error_close_clsid_key;
492         }
493 
494         if (list->formats) {
495             HKEY formats_key;
496             GUID const * const *format;
497 
498             res = RegCreateKeyExW(clsid_key, formats_keyname, 0, NULL, 0,
499                                   KEY_READ | KEY_WRITE, NULL, &formats_key, NULL);
500             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
501             for (format=list->formats; *format; ++format)
502             {
503                 HKEY format_key;
504                 StringFromGUID2(*format, buf, 39);
505                 res = RegCreateKeyExW(formats_key, buf, 0, NULL, 0,
506                                       KEY_READ | KEY_WRITE, NULL, &format_key, NULL);
507                 if (res != ERROR_SUCCESS) break;
508                 RegCloseKey(format_key);
509             }
510             RegCloseKey(formats_key);
511             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
512         }
513 
514     error_close_clsid_key:
515 	RegCloseKey(clsid_key);
516     }
517 
518 error_close_coclass_key:
519     RegCloseKey(instance_key);
520     RegCloseKey(encoders_key);
521     RegCloseKey(coclass_key);
522 error_return:
523     return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
524 }
525 
526 /***********************************************************************
527  *		unregister_encoders
528  */
529 static HRESULT unregister_encoders(struct regsvr_encoder const *list)
530 {
531     LONG res = ERROR_SUCCESS;
532     HKEY coclass_key;
533     WCHAR buf[39];
534     HKEY encoders_key;
535     HKEY instance_key;
536 
537     res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0,
538 			KEY_READ | KEY_WRITE, &coclass_key);
539     if (res == ERROR_FILE_NOT_FOUND) return S_OK;
540 
541     if (res == ERROR_SUCCESS)  {
542         StringFromGUID2(&CATID_WICBitmapEncoders, buf, 39);
543         res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
544 			      KEY_READ | KEY_WRITE, NULL, &encoders_key, NULL);
545         if (res == ERROR_SUCCESS)
546         {
547             res = RegCreateKeyExW(encoders_key, instance_keyname, 0, NULL, 0,
548 		              KEY_READ | KEY_WRITE, NULL, &instance_key, NULL);
549             if (res != ERROR_SUCCESS) goto error_close_coclass_key;
550         }
551         if (res != ERROR_SUCCESS)
552             RegCloseKey(coclass_key);
553     }
554     if (res != ERROR_SUCCESS) goto error_return;
555 
556     for (; res == ERROR_SUCCESS && list->clsid; ++list) {
557 	StringFromGUID2(list->clsid, buf, 39);
558 
559 	res = RegDeleteTreeW(coclass_key, buf);
560 	if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
561 	if (res != ERROR_SUCCESS) goto error_close_coclass_key;
562 
563 	res = RegDeleteTreeW(instance_key, buf);
564 	if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
565 	if (res != ERROR_SUCCESS) goto error_close_coclass_key;
566     }
567 
568 error_close_coclass_key:
569     RegCloseKey(instance_key);
570     RegCloseKey(encoders_key);
571     RegCloseKey(coclass_key);
572 error_return:
573     return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
574 }
575 
576 /***********************************************************************
577  *		register_converters
578  */
579 static HRESULT register_converters(struct regsvr_converter const *list)
580 {
581     LONG res = ERROR_SUCCESS;
582     HKEY coclass_key;
583     WCHAR buf[39];
584     HKEY converters_key;
585     HKEY instance_key;
586 
587     res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0,
588 			  KEY_READ | KEY_WRITE, NULL, &coclass_key, NULL);
589     if (res == ERROR_SUCCESS)  {
590         StringFromGUID2(&CATID_WICFormatConverters, buf, 39);
591         res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
592 			      KEY_READ | KEY_WRITE, NULL, &converters_key, NULL);
593         if (res == ERROR_SUCCESS)
594         {
595             res = RegCreateKeyExW(converters_key, instance_keyname, 0, NULL, 0,
596 		              KEY_READ | KEY_WRITE, NULL, &instance_key, NULL);
597             if (res != ERROR_SUCCESS) goto error_close_coclass_key;
598         }
599         if (res != ERROR_SUCCESS)
600             RegCloseKey(coclass_key);
601     }
602     if (res != ERROR_SUCCESS) goto error_return;
603 
604     for (; res == ERROR_SUCCESS && list->clsid; ++list) {
605 	HKEY clsid_key;
606 	HKEY instance_clsid_key;
607 
608 	StringFromGUID2(list->clsid, buf, 39);
609 	res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
610 			      KEY_READ | KEY_WRITE, NULL, &clsid_key, NULL);
611 	if (res != ERROR_SUCCESS) goto error_close_coclass_key;
612 
613 	StringFromGUID2(list->clsid, buf, 39);
614 	res = RegCreateKeyExW(instance_key, buf, 0, NULL, 0,
615 			      KEY_READ | KEY_WRITE, NULL, &instance_clsid_key, NULL);
616 	if (res == ERROR_SUCCESS) {
617 	    res = RegSetValueExW(instance_clsid_key, clsid_valuename, 0, REG_SZ,
618                                  (const BYTE*)buf, 78);
619 	    RegCloseKey(instance_clsid_key);
620 	}
621 	if (res != ERROR_SUCCESS) goto error_close_clsid_key;
622 
623         if (list->author) {
624 	    res = RegSetValueExA(clsid_key, author_valuename, 0, REG_SZ,
625                                  (const BYTE*)list->author,
626 				 strlen(list->author) + 1);
627 	    if (res != ERROR_SUCCESS) goto error_close_clsid_key;
628         }
629 
630         if (list->friendlyname) {
631 	    res = RegSetValueExA(clsid_key, friendlyname_valuename, 0, REG_SZ,
632                                  (const BYTE*)list->friendlyname,
633 				 strlen(list->friendlyname) + 1);
634 	    if (res != ERROR_SUCCESS) goto error_close_clsid_key;
635         }
636 
637         if (list->vendor) {
638             StringFromGUID2(list->vendor, buf, 39);
639 	    res = RegSetValueExW(clsid_key, vendor_valuename, 0, REG_SZ,
640                                  (const BYTE*)buf, 78);
641 	    if (res != ERROR_SUCCESS) goto error_close_clsid_key;
642         }
643 
644         if (list->version) {
645 	    res = RegSetValueExA(clsid_key, version_valuename, 0, REG_SZ,
646                                  (const BYTE*)list->version,
647 				 strlen(list->version) + 1);
648 	    if (res != ERROR_SUCCESS) goto error_close_clsid_key;
649         }
650 
651         if (list->formats) {
652             HKEY formats_key;
653             GUID const * const *format;
654 
655             res = RegCreateKeyExW(clsid_key, pixelformats_keyname, 0, NULL, 0,
656                                   KEY_READ | KEY_WRITE, NULL, &formats_key, NULL);
657             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
658             for (format=list->formats; *format; ++format)
659             {
660                 HKEY format_key;
661                 StringFromGUID2(*format, buf, 39);
662                 res = RegCreateKeyExW(formats_key, buf, 0, NULL, 0,
663                                       KEY_READ | KEY_WRITE, NULL, &format_key, NULL);
664                 if (res != ERROR_SUCCESS) break;
665                 RegCloseKey(format_key);
666             }
667             RegCloseKey(formats_key);
668             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
669         }
670 
671     error_close_clsid_key:
672 	RegCloseKey(clsid_key);
673     }
674 
675 error_close_coclass_key:
676     RegCloseKey(instance_key);
677     RegCloseKey(converters_key);
678     RegCloseKey(coclass_key);
679 error_return:
680     return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
681 }
682 
683 /***********************************************************************
684  *		unregister_converters
685  */
686 static HRESULT unregister_converters(struct regsvr_converter const *list)
687 {
688     LONG res = ERROR_SUCCESS;
689     HKEY coclass_key;
690     WCHAR buf[39];
691     HKEY converters_key;
692     HKEY instance_key;
693 
694     res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0,
695 			KEY_READ | KEY_WRITE, &coclass_key);
696     if (res == ERROR_FILE_NOT_FOUND) return S_OK;
697 
698     if (res == ERROR_SUCCESS)  {
699         StringFromGUID2(&CATID_WICFormatConverters, buf, 39);
700         res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
701 			      KEY_READ | KEY_WRITE, NULL, &converters_key, NULL);
702         if (res == ERROR_SUCCESS)
703         {
704             res = RegCreateKeyExW(converters_key, instance_keyname, 0, NULL, 0,
705 		              KEY_READ | KEY_WRITE, NULL, &instance_key, NULL);
706             if (res != ERROR_SUCCESS) goto error_close_coclass_key;
707         }
708         if (res != ERROR_SUCCESS)
709             RegCloseKey(coclass_key);
710     }
711     if (res != ERROR_SUCCESS) goto error_return;
712 
713     for (; res == ERROR_SUCCESS && list->clsid; ++list) {
714 	StringFromGUID2(list->clsid, buf, 39);
715 
716 	res = RegDeleteTreeW(coclass_key, buf);
717 	if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
718 	if (res != ERROR_SUCCESS) goto error_close_coclass_key;
719 
720 	res = RegDeleteTreeW(instance_key, buf);
721 	if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
722 	if (res != ERROR_SUCCESS) goto error_close_coclass_key;
723     }
724 
725 error_close_coclass_key:
726     RegCloseKey(instance_key);
727     RegCloseKey(converters_key);
728     RegCloseKey(coclass_key);
729 error_return:
730     return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
731 }
732 
733 /***********************************************************************
734  *		register_metadatareaders
735  */
736 static HRESULT register_metadatareaders(struct regsvr_metadatareader const *list)
737 {
738     LONG res = ERROR_SUCCESS;
739     HKEY coclass_key;
740     WCHAR buf[39];
741     HKEY readers_key;
742     HKEY instance_key;
743 
744     res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0,
745 			  KEY_READ | KEY_WRITE, NULL, &coclass_key, NULL);
746     if (res == ERROR_SUCCESS)  {
747         StringFromGUID2(&CATID_WICMetadataReader, buf, 39);
748         res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
749 			      KEY_READ | KEY_WRITE, NULL, &readers_key, NULL);
750         if (res == ERROR_SUCCESS)
751         {
752             res = RegCreateKeyExW(readers_key, instance_keyname, 0, NULL, 0,
753 		              KEY_READ | KEY_WRITE, NULL, &instance_key, NULL);
754             if (res != ERROR_SUCCESS) goto error_close_coclass_key;
755         }
756         if (res != ERROR_SUCCESS)
757             RegCloseKey(coclass_key);
758     }
759     if (res != ERROR_SUCCESS) goto error_return;
760 
761     for (; res == ERROR_SUCCESS && list->clsid; ++list) {
762 	HKEY clsid_key;
763 	HKEY instance_clsid_key;
764 
765 	StringFromGUID2(list->clsid, buf, 39);
766 	res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
767 			      KEY_READ | KEY_WRITE, NULL, &clsid_key, NULL);
768 	if (res != ERROR_SUCCESS) goto error_close_coclass_key;
769 
770 	StringFromGUID2(list->clsid, buf, 39);
771 	res = RegCreateKeyExW(instance_key, buf, 0, NULL, 0,
772 			      KEY_READ | KEY_WRITE, NULL, &instance_clsid_key, NULL);
773 	if (res == ERROR_SUCCESS) {
774 	    res = RegSetValueExW(instance_clsid_key, clsid_valuename, 0, REG_SZ,
775                                  (const BYTE*)buf, 78);
776 	    RegCloseKey(instance_clsid_key);
777 	}
778 	if (res != ERROR_SUCCESS) goto error_close_clsid_key;
779 
780         if (list->author) {
781 	    res = RegSetValueExA(clsid_key, author_valuename, 0, REG_SZ,
782                                  (const BYTE*)list->author,
783 				 strlen(list->author) + 1);
784 	    if (res != ERROR_SUCCESS) goto error_close_clsid_key;
785         }
786 
787         if (list->friendlyname) {
788 	    res = RegSetValueExA(clsid_key, friendlyname_valuename, 0, REG_SZ,
789                                  (const BYTE*)list->friendlyname,
790 				 strlen(list->friendlyname) + 1);
791 	    if (res != ERROR_SUCCESS) goto error_close_clsid_key;
792         }
793 
794         if (list->vendor) {
795             StringFromGUID2(list->vendor, buf, 39);
796 	    res = RegSetValueExW(clsid_key, vendor_valuename, 0, REG_SZ,
797                                  (const BYTE*)buf, 78);
798 	    if (res != ERROR_SUCCESS) goto error_close_clsid_key;
799         }
800 
801         if (list->metadata_format) {
802             StringFromGUID2(list->metadata_format, buf, 39);
803 	    res = RegSetValueExW(clsid_key, metadataformat_valuename, 0, REG_SZ,
804                                  (const BYTE*)buf, 78);
805 	    if (res != ERROR_SUCCESS) goto error_close_clsid_key;
806         }
807 
808         if (list->version) {
809 	    res = RegSetValueExA(clsid_key, version_valuename, 0, REG_SZ,
810                                  (const BYTE*)list->version,
811 				 strlen(list->version) + 1);
812 	    if (res != ERROR_SUCCESS) goto error_close_clsid_key;
813         }
814 
815         if (list->specversion) {
816 	    res = RegSetValueExA(clsid_key, specversion_valuename, 0, REG_SZ,
817                                  (const BYTE*)list->version,
818 				 strlen(list->version) + 1);
819 	    if (res != ERROR_SUCCESS) goto error_close_clsid_key;
820         }
821 
822         res = RegSetValueExA(clsid_key, requiresfullstream_valuename, 0, REG_DWORD,
823                              (const BYTE*)&list->requires_fullstream, 4);
824         if (res != ERROR_SUCCESS) goto error_close_clsid_key;
825 
826         res = RegSetValueExA(clsid_key, supportspadding_valuename, 0, REG_DWORD,
827                              (const BYTE*)&list->supports_padding, 4);
828         if (res != ERROR_SUCCESS) goto error_close_clsid_key;
829 
830         if (list->requires_fixedsize) {
831 	    res = RegSetValueExA(clsid_key, requiresfixedsize_valuename, 0, REG_DWORD,
832                                  (const BYTE*)&list->requires_fixedsize, 4);
833 	    if (res != ERROR_SUCCESS) goto error_close_clsid_key;
834         }
835 
836         if (list->containers) {
837             HKEY containers_key;
838             const struct reader_containers *container;
839 
840             res = RegCreateKeyExW(clsid_key, containers_keyname, 0, NULL, 0,
841                                   KEY_READ | KEY_WRITE, NULL, &containers_key, NULL);
842             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
843             for (container=list->containers; container->format; ++container)
844             {
845                 HKEY format_key;
846                 int i;
847                 StringFromGUID2(container->format, buf, 39);
848                 res = RegCreateKeyExW(containers_key, buf, 0, NULL, 0,
849                                       KEY_READ | KEY_WRITE, NULL, &format_key, NULL);
850                 if (res != ERROR_SUCCESS) break;
851 
852                 for (i=0; container->patterns[i].length; i++)
853                 {
854                     HKEY pattern_key;
855                     static const WCHAR int_format[] = {'%','i',0};
856                     snprintfW(buf, 39, int_format, i);
857                     res = RegCreateKeyExW(format_key, buf, 0, NULL, 0,
858                                           KEY_READ | KEY_WRITE, NULL, &pattern_key, NULL);
859                     if (res != ERROR_SUCCESS) break;
860                     res = RegSetValueExA(pattern_key, position_valuename, 0, REG_DWORD,
861                                          (const BYTE*)&container->patterns[i].position, 4);
862                     if (res == ERROR_SUCCESS)
863                         res = RegSetValueExA(pattern_key, pattern_valuename, 0, REG_BINARY,
864                                              container->patterns[i].pattern,
865                                              container->patterns[i].length);
866                     if (res == ERROR_SUCCESS)
867                         res = RegSetValueExA(pattern_key, mask_valuename, 0, REG_BINARY,
868                                              container->patterns[i].mask,
869                                              container->patterns[i].length);
870                     if (res == ERROR_SUCCESS && container->patterns[i].data_offset)
871                         res = RegSetValueExA(pattern_key, dataoffset_valuename, 0, REG_DWORD,
872                                              (const BYTE*)&container->patterns[i].data_offset, 4);
873                     RegCloseKey(pattern_key);
874                 }
875 
876                 RegCloseKey(format_key);
877             }
878             RegCloseKey(containers_key);
879         }
880 
881     error_close_clsid_key:
882 	RegCloseKey(clsid_key);
883     }
884 
885 error_close_coclass_key:
886     RegCloseKey(instance_key);
887     RegCloseKey(readers_key);
888     RegCloseKey(coclass_key);
889 error_return:
890     return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
891 }
892 
893 /***********************************************************************
894  *		unregister_metadatareaders
895  */
896 static HRESULT unregister_metadatareaders(struct regsvr_metadatareader const *list)
897 {
898     LONG res = ERROR_SUCCESS;
899     HKEY coclass_key;
900     WCHAR buf[39];
901     HKEY readers_key;
902     HKEY instance_key;
903 
904     res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0,
905 			KEY_READ | KEY_WRITE, &coclass_key);
906     if (res == ERROR_FILE_NOT_FOUND) return S_OK;
907 
908     if (res == ERROR_SUCCESS)  {
909         StringFromGUID2(&CATID_WICMetadataReader, buf, 39);
910         res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
911 			      KEY_READ | KEY_WRITE, NULL, &readers_key, NULL);
912         if (res == ERROR_SUCCESS)
913         {
914             res = RegCreateKeyExW(readers_key, instance_keyname, 0, NULL, 0,
915 		              KEY_READ | KEY_WRITE, NULL, &instance_key, NULL);
916             if (res != ERROR_SUCCESS) goto error_close_coclass_key;
917         }
918         if (res != ERROR_SUCCESS)
919             RegCloseKey(coclass_key);
920     }
921     if (res != ERROR_SUCCESS) goto error_return;
922 
923     for (; res == ERROR_SUCCESS && list->clsid; ++list) {
924 	StringFromGUID2(list->clsid, buf, 39);
925 
926 	res = RegDeleteTreeW(coclass_key, buf);
927 	if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
928 	if (res != ERROR_SUCCESS) goto error_close_coclass_key;
929 
930 	res = RegDeleteTreeW(instance_key, buf);
931 	if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
932 	if (res != ERROR_SUCCESS) goto error_close_coclass_key;
933     }
934 
935 error_close_coclass_key:
936     RegCloseKey(instance_key);
937     RegCloseKey(readers_key);
938     RegCloseKey(coclass_key);
939 error_return:
940     return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
941 }
942 
943 /***********************************************************************
944  *                register_pixelformats
945  */
946 static HRESULT register_pixelformats(struct regsvr_pixelformat const *list)
947 {
948     LONG res = ERROR_SUCCESS;
949     HKEY coclass_key;
950     WCHAR buf[39];
951     HKEY formats_key;
952     HKEY instance_key;
953 
954     res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0,
955                           KEY_READ | KEY_WRITE, NULL, &coclass_key, NULL);
956     if (res == ERROR_SUCCESS)  {
957         StringFromGUID2(&CATID_WICPixelFormats, buf, 39);
958         res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
959                               KEY_READ | KEY_WRITE, NULL, &formats_key, NULL);
960         if (res == ERROR_SUCCESS)
961         {
962             res = RegCreateKeyExW(formats_key, instance_keyname, 0, NULL, 0,
963                               KEY_READ | KEY_WRITE, NULL, &instance_key, NULL);
964             if (res != ERROR_SUCCESS) goto error_close_coclass_key;
965         }
966         if (res != ERROR_SUCCESS)
967             RegCloseKey(coclass_key);
968     }
969     if (res != ERROR_SUCCESS) goto error_return;
970 
971     for (; res == ERROR_SUCCESS && list->clsid; ++list) {
972         HKEY clsid_key;
973         HKEY instance_clsid_key;
974 
975         StringFromGUID2(list->clsid, buf, 39);
976         res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
977                               KEY_READ | KEY_WRITE, NULL, &clsid_key, NULL);
978         if (res != ERROR_SUCCESS) goto error_close_coclass_key;
979 
980         StringFromGUID2(list->clsid, buf, 39);
981         res = RegCreateKeyExW(instance_key, buf, 0, NULL, 0,
982                               KEY_READ | KEY_WRITE, NULL, &instance_clsid_key, NULL);
983         if (res == ERROR_SUCCESS) {
984             res = RegSetValueExW(instance_clsid_key, clsid_valuename, 0, REG_SZ,
985                                  (const BYTE*)buf, 78);
986             RegCloseKey(instance_clsid_key);
987         }
988         if (res != ERROR_SUCCESS) goto error_close_clsid_key;
989 
990         if (list->author) {
991             res = RegSetValueExA(clsid_key, author_valuename, 0, REG_SZ,
992                                  (const BYTE*)list->author,
993                                  strlen(list->author) + 1);
994             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
995         }
996 
997         if (list->friendlyname) {
998             res = RegSetValueExA(clsid_key, friendlyname_valuename, 0, REG_SZ,
999                                  (const BYTE*)list->friendlyname,
1000                                  strlen(list->friendlyname) + 1);
1001             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
1002         }
1003 
1004         if (list->vendor) {
1005             StringFromGUID2(list->vendor, buf, 39);
1006             res = RegSetValueExW(clsid_key, vendor_valuename, 0, REG_SZ,
1007                                  (const BYTE*)buf, 78);
1008             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
1009         }
1010 
1011         if (list->version) {
1012             res = RegSetValueExA(clsid_key, version_valuename, 0, REG_SZ,
1013                                  (const BYTE*)list->version,
1014                                  strlen(list->version) + 1);
1015             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
1016         }
1017 
1018         res = RegSetValueExA(clsid_key, bitsperpixel_valuename, 0, REG_DWORD,
1019                              (const BYTE*)&list->bitsperpixel, 4);
1020         if (res != ERROR_SUCCESS) goto error_close_clsid_key;
1021 
1022         res = RegSetValueExA(clsid_key, channelcount_valuename, 0, REG_DWORD,
1023                              (const BYTE*)&list->channelcount, 4);
1024         if (res != ERROR_SUCCESS) goto error_close_clsid_key;
1025 
1026         res = RegSetValueExA(clsid_key, numericrepresentation_valuename, 0, REG_DWORD,
1027                              (const BYTE*)&list->numericrepresentation, 4);
1028         if (res != ERROR_SUCCESS) goto error_close_clsid_key;
1029 
1030         res = RegSetValueExA(clsid_key, supportstransparency_valuename, 0, REG_DWORD,
1031                              (const BYTE*)&list->supportsalpha, 4);
1032         if (res != ERROR_SUCCESS) goto error_close_clsid_key;
1033 
1034         if (list->channelmasks) {
1035             HKEY masks_key;
1036             UINT i, mask_size;
1037             WCHAR mask_valuename[11];
1038             const WCHAR valuename_format[] = {'%','d',0};
1039 
1040             mask_size = (list->bitsperpixel + 7)/8;
1041 
1042             res = RegCreateKeyExW(clsid_key, channelmasks_keyname, 0, NULL, 0,
1043                                   KEY_READ | KEY_WRITE, NULL, &masks_key, NULL);
1044             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
1045             for (i=0; i < list->channelcount; i++)
1046             {
1047                 sprintfW(mask_valuename, valuename_format, i);
1048                 res = RegSetValueExW(masks_key, mask_valuename, 0, REG_BINARY,
1049                                      list->channelmasks[i], mask_size);
1050                 if (res != ERROR_SUCCESS) break;
1051             }
1052             RegCloseKey(masks_key);
1053             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
1054         }
1055 
1056     error_close_clsid_key:
1057         RegCloseKey(clsid_key);
1058     }
1059 
1060 error_close_coclass_key:
1061     RegCloseKey(instance_key);
1062     RegCloseKey(formats_key);
1063     RegCloseKey(coclass_key);
1064 error_return:
1065     return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
1066 }
1067 
1068 /***********************************************************************
1069  *                unregister_pixelformats
1070  */
1071 static HRESULT unregister_pixelformats(struct regsvr_pixelformat const *list)
1072 {
1073     LONG res = ERROR_SUCCESS;
1074     HKEY coclass_key;
1075     WCHAR buf[39];
1076     HKEY formats_key;
1077     HKEY instance_key;
1078 
1079     res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0,
1080                         KEY_READ | KEY_WRITE, &coclass_key);
1081     if (res == ERROR_FILE_NOT_FOUND) return S_OK;
1082 
1083     if (res == ERROR_SUCCESS)  {
1084         StringFromGUID2(&CATID_WICPixelFormats, buf, 39);
1085         res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
1086                               KEY_READ | KEY_WRITE, NULL, &formats_key, NULL);
1087         if (res == ERROR_SUCCESS)
1088         {
1089             res = RegCreateKeyExW(formats_key, instance_keyname, 0, NULL, 0,
1090                               KEY_READ | KEY_WRITE, NULL, &instance_key, NULL);
1091             if (res != ERROR_SUCCESS) goto error_close_coclass_key;
1092         }
1093         if (res != ERROR_SUCCESS)
1094             RegCloseKey(coclass_key);
1095     }
1096     if (res != ERROR_SUCCESS) goto error_return;
1097 
1098     for (; res == ERROR_SUCCESS && list->clsid; ++list) {
1099         StringFromGUID2(list->clsid, buf, 39);
1100 
1101         res = RegDeleteTreeW(coclass_key, buf);
1102         if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
1103         if (res != ERROR_SUCCESS) goto error_close_coclass_key;
1104 
1105         res = RegDeleteTreeW(instance_key, buf);
1106         if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
1107         if (res != ERROR_SUCCESS) goto error_close_coclass_key;
1108     }
1109 
1110 error_close_coclass_key:
1111     RegCloseKey(instance_key);
1112     RegCloseKey(formats_key);
1113     RegCloseKey(coclass_key);
1114 error_return:
1115     return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
1116 }
1117 
1118 /***********************************************************************
1119  *		decoder list
1120  */
1121 static const BYTE mask_all[] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
1122 
1123 static const BYTE bmp_magic[] = {0x42,0x4d};
1124 
1125 static GUID const * const bmp_formats[] = {
1126     &GUID_WICPixelFormat1bppIndexed,
1127     &GUID_WICPixelFormat2bppIndexed,
1128     &GUID_WICPixelFormat4bppIndexed,
1129     &GUID_WICPixelFormat8bppIndexed,
1130     &GUID_WICPixelFormat16bppBGR555,
1131     &GUID_WICPixelFormat16bppBGR565,
1132     &GUID_WICPixelFormat24bppBGR,
1133     &GUID_WICPixelFormat32bppBGR,
1134     &GUID_WICPixelFormat32bppBGRA,
1135     NULL
1136 };
1137 
1138 static struct decoder_pattern const bmp_patterns[] = {
1139     {2,0,bmp_magic,mask_all,0},
1140     {0}
1141 };
1142 
1143 static const BYTE gif87a_magic[6] = "GIF87a";
1144 static const BYTE gif89a_magic[6] = "GIF89a";
1145 
1146 static GUID const * const gif_formats[] = {
1147     &GUID_WICPixelFormat8bppIndexed,
1148     NULL
1149 };
1150 
1151 static struct decoder_pattern const gif_patterns[] = {
1152     {6,0,gif87a_magic,mask_all,0},
1153     {6,0,gif89a_magic,mask_all,0},
1154     {0}
1155 };
1156 
1157 static const BYTE ico_magic[] = {00,00,01,00};
1158 
1159 static GUID const * const ico_formats[] = {
1160     &GUID_WICPixelFormat32bppBGRA,
1161     NULL
1162 };
1163 
1164 static struct decoder_pattern const ico_patterns[] = {
1165     {4,0,ico_magic,mask_all,0},
1166     {0}
1167 };
1168 
1169 static const BYTE jpeg_magic[] = {0xff, 0xd8};
1170 
1171 static GUID const * const jpeg_formats[] = {
1172     &GUID_WICPixelFormat24bppBGR,
1173     &GUID_WICPixelFormat32bppCMYK,
1174     &GUID_WICPixelFormat8bppGray,
1175     NULL
1176 };
1177 
1178 static struct decoder_pattern const jpeg_patterns[] = {
1179     {2,0,jpeg_magic,mask_all,0},
1180     {0}
1181 };
1182 
1183 static const BYTE png_magic[] = {137,80,78,71,13,10,26,10};
1184 
1185 static GUID const * const png_formats[] = {
1186     &GUID_WICPixelFormatBlackWhite,
1187     &GUID_WICPixelFormat2bppGray,
1188     &GUID_WICPixelFormat4bppGray,
1189     &GUID_WICPixelFormat8bppGray,
1190     &GUID_WICPixelFormat16bppGray,
1191     &GUID_WICPixelFormat32bppBGRA,
1192     &GUID_WICPixelFormat64bppRGBA,
1193     &GUID_WICPixelFormat1bppIndexed,
1194     &GUID_WICPixelFormat2bppIndexed,
1195     &GUID_WICPixelFormat4bppIndexed,
1196     &GUID_WICPixelFormat8bppIndexed,
1197     &GUID_WICPixelFormat24bppBGR,
1198     &GUID_WICPixelFormat48bppRGB,
1199     NULL
1200 };
1201 
1202 static struct decoder_pattern const png_patterns[] = {
1203     {8,0,png_magic,mask_all,0},
1204     {0}
1205 };
1206 
1207 static const BYTE tiff_magic_le[] = {0x49,0x49,42,0};
1208 static const BYTE tiff_magic_be[] = {0x4d,0x4d,0,42};
1209 
1210 static GUID const * const tiff_decode_formats[] = {
1211     &GUID_WICPixelFormatBlackWhite,
1212     &GUID_WICPixelFormat4bppGray,
1213     &GUID_WICPixelFormat8bppGray,
1214     &GUID_WICPixelFormat16bppGray,
1215     &GUID_WICPixelFormat32bppGrayFloat,
1216     &GUID_WICPixelFormat1bppIndexed,
1217     &GUID_WICPixelFormat2bppIndexed,
1218     &GUID_WICPixelFormat4bppIndexed,
1219     &GUID_WICPixelFormat8bppIndexed,
1220     &GUID_WICPixelFormat24bppBGR,
1221     &GUID_WICPixelFormat32bppBGR,
1222     &GUID_WICPixelFormat32bppBGRA,
1223     &GUID_WICPixelFormat32bppPBGRA,
1224     &GUID_WICPixelFormat48bppRGB,
1225     &GUID_WICPixelFormat64bppRGBA,
1226     &GUID_WICPixelFormat64bppPRGBA,
1227     &GUID_WICPixelFormat32bppCMYK,
1228     &GUID_WICPixelFormat64bppCMYK,
1229     &GUID_WICPixelFormat128bppRGBAFloat,
1230     NULL
1231 };
1232 
1233 static struct decoder_pattern const tiff_patterns[] = {
1234     {4,0,tiff_magic_le,mask_all,0},
1235     {4,0,tiff_magic_be,mask_all,0},
1236     {0}
1237 };
1238 
1239 static const BYTE tga_footer_magic[18] = "TRUEVISION-XFILE.";
1240 
1241 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};
1242 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};
1243 
1244 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};
1245 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};
1246 
1247 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};
1248 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};
1249 
1250 static GUID const * const tga_formats[] = {
1251     &GUID_WICPixelFormat8bppGray,
1252     &GUID_WICPixelFormat8bppIndexed,
1253     &GUID_WICPixelFormat16bppGray,
1254     &GUID_WICPixelFormat16bppBGR555,
1255     &GUID_WICPixelFormat24bppBGR,
1256     &GUID_WICPixelFormat32bppBGRA,
1257     &GUID_WICPixelFormat32bppPBGRA,
1258     NULL
1259 };
1260 
1261 static struct decoder_pattern const tga_patterns[] = {
1262     {18,18,tga_footer_magic,mask_all,1},
1263     {18,0,tga_indexed_magic,tga_indexed_mask,0},
1264     {18,0,tga_truecolor_magic,tga_truecolor_mask,0},
1265     {18,0,tga_grayscale_magic,tga_grayscale_mask,0},
1266     {0}
1267 };
1268 
1269 static struct regsvr_decoder const decoder_list[] = {
1270     {   &CLSID_WICBmpDecoder,
1271 	"The Wine Project",
1272 	"BMP Decoder",
1273 	"1.0.0.0",
1274 	&GUID_VendorMicrosoft,
1275 	&GUID_ContainerFormatBmp,
1276 	"image/bmp",
1277 	".bmp,.dib,.rle",
1278 	bmp_formats,
1279 	bmp_patterns
1280     },
1281     {   &CLSID_WICGifDecoder,
1282 	"The Wine Project",
1283 	"GIF Decoder",
1284 	"1.0.0.0",
1285 	&GUID_VendorMicrosoft,
1286 	&GUID_ContainerFormatGif,
1287 	"image/gif",
1288 	".gif",
1289 	gif_formats,
1290 	gif_patterns
1291     },
1292     {   &CLSID_WICIcoDecoder,
1293 	"The Wine Project",
1294 	"ICO Decoder",
1295 	"1.0.0.0",
1296 	&GUID_VendorMicrosoft,
1297 	&GUID_ContainerFormatIco,
1298 	"image/vnd.microsoft.icon",
1299 	".ico",
1300 	ico_formats,
1301 	ico_patterns
1302     },
1303     {   &CLSID_WICJpegDecoder,
1304 	"The Wine Project",
1305 	"JPEG Decoder",
1306 	"1.0.0.0",
1307 	&GUID_VendorMicrosoft,
1308 	&GUID_ContainerFormatJpeg,
1309 	"image/jpeg",
1310 	".jpg;.jpeg;.jfif",
1311 	jpeg_formats,
1312 	jpeg_patterns
1313     },
1314     {   &CLSID_WICPngDecoder,
1315 	"The Wine Project",
1316 	"PNG Decoder",
1317 	"1.0.0.0",
1318 	&GUID_VendorMicrosoft,
1319 	&GUID_ContainerFormatPng,
1320 	"image/png",
1321 	".png",
1322 	png_formats,
1323 	png_patterns
1324     },
1325     {   &CLSID_WICTiffDecoder,
1326 	"The Wine Project",
1327 	"TIFF Decoder",
1328 	"1.0.0.0",
1329 	&GUID_VendorMicrosoft,
1330 	&GUID_ContainerFormatTiff,
1331 	"image/tiff",
1332 	".tif;.tiff",
1333 	tiff_decode_formats,
1334 	tiff_patterns
1335     },
1336     {   &CLSID_WineTgaDecoder,
1337 	"The Wine Project",
1338 	"TGA Decoder",
1339 	"1.0.0.0",
1340 	&GUID_VendorWine,
1341 	&GUID_WineContainerFormatTga,
1342 	"image/x-targa",
1343 	".tga;.tpic",
1344 	tga_formats,
1345 	tga_patterns
1346     },
1347     { NULL }			/* list terminator */
1348 };
1349 
1350 static GUID const * const bmp_encode_formats[] = {
1351     &GUID_WICPixelFormat16bppBGR555,
1352     &GUID_WICPixelFormat16bppBGR565,
1353     &GUID_WICPixelFormat24bppBGR,
1354     &GUID_WICPixelFormat32bppBGR,
1355     &GUID_WICPixelFormatBlackWhite,
1356     &GUID_WICPixelFormat1bppIndexed,
1357     &GUID_WICPixelFormat2bppIndexed,
1358     &GUID_WICPixelFormat4bppIndexed,
1359     &GUID_WICPixelFormat8bppIndexed,
1360     NULL
1361 };
1362 
1363 static GUID const * const png_encode_formats[] = {
1364     &GUID_WICPixelFormat24bppBGR,
1365     &GUID_WICPixelFormatBlackWhite,
1366     &GUID_WICPixelFormat2bppGray,
1367     &GUID_WICPixelFormat4bppGray,
1368     &GUID_WICPixelFormat8bppGray,
1369     &GUID_WICPixelFormat16bppGray,
1370     &GUID_WICPixelFormat32bppBGR,
1371     &GUID_WICPixelFormat32bppBGRA,
1372     &GUID_WICPixelFormat48bppRGB,
1373     &GUID_WICPixelFormat64bppRGBA,
1374     &GUID_WICPixelFormat1bppIndexed,
1375     &GUID_WICPixelFormat2bppIndexed,
1376     &GUID_WICPixelFormat4bppIndexed,
1377     &GUID_WICPixelFormat8bppIndexed,
1378     NULL
1379 };
1380 
1381 static GUID const * const tiff_encode_formats[] = {
1382     &GUID_WICPixelFormatBlackWhite,
1383     &GUID_WICPixelFormat4bppGray,
1384     &GUID_WICPixelFormat8bppGray,
1385     &GUID_WICPixelFormat1bppIndexed,
1386     &GUID_WICPixelFormat2bppIndexed,
1387     &GUID_WICPixelFormat4bppIndexed,
1388     &GUID_WICPixelFormat8bppIndexed,
1389     &GUID_WICPixelFormat24bppBGR,
1390     &GUID_WICPixelFormat32bppBGRA,
1391     &GUID_WICPixelFormat32bppPBGRA,
1392     &GUID_WICPixelFormat48bppRGB,
1393     &GUID_WICPixelFormat64bppRGBA,
1394     &GUID_WICPixelFormat64bppPRGBA,
1395     NULL
1396 };
1397 
1398 static GUID const * const icns_encode_formats[] = {
1399     &GUID_WICPixelFormat32bppBGRA,
1400     NULL
1401 };
1402 
1403 static struct regsvr_encoder const encoder_list[] = {
1404     {   &CLSID_WICBmpEncoder,
1405 	"The Wine Project",
1406 	"BMP Encoder",
1407 	"1.0.0.0",
1408 	&GUID_VendorMicrosoft,
1409 	&GUID_ContainerFormatBmp,
1410 	"image/bmp",
1411 	".bmp,.dib,.rle",
1412 	bmp_encode_formats
1413     },
1414     {   &CLSID_WICGifEncoder,
1415 	"The Wine Project",
1416 	"GIF Encoder",
1417 	"1.0.0.0",
1418 	&GUID_VendorMicrosoft,
1419 	&GUID_ContainerFormatGif,
1420 	"image/gif",
1421 	".gif",
1422 	gif_formats
1423     },
1424     {   &CLSID_WICJpegEncoder,
1425 	"The Wine Project",
1426 	"JPEG Encoder",
1427 	"1.0.0.0",
1428 	&GUID_VendorMicrosoft,
1429 	&GUID_ContainerFormatJpeg,
1430 	"image/jpeg",
1431 	".jpg;.jpeg;.jfif",
1432 	jpeg_formats
1433     },
1434     {   &CLSID_WICPngEncoder,
1435 	"The Wine Project",
1436 	"PNG Encoder",
1437 	"1.0.0.0",
1438 	&GUID_VendorMicrosoft,
1439 	&GUID_ContainerFormatPng,
1440 	"image/png",
1441 	".png",
1442 	png_encode_formats
1443     },
1444     {   &CLSID_WICTiffEncoder,
1445 	"The Wine Project",
1446 	"TIFF Encoder",
1447 	"1.0.0.0",
1448 	&GUID_VendorMicrosoft,
1449 	&GUID_ContainerFormatTiff,
1450 	"image/tiff",
1451 	".tif;.tiff",
1452 	tiff_encode_formats
1453     },
1454     {   &CLSID_WICIcnsEncoder,
1455 	"The Wine Project",
1456 	"ICNS Encoder",
1457 	"1.0.0.0",
1458 	&GUID_VendorWine,
1459 	NULL, /* no container format guid */
1460 	"image/icns",
1461 	".icns",
1462 	icns_encode_formats
1463     },
1464     { NULL }			/* list terminator */
1465 };
1466 
1467 static GUID const * const converter_formats[] = {
1468     &GUID_WICPixelFormat1bppIndexed,
1469     &GUID_WICPixelFormat2bppIndexed,
1470     &GUID_WICPixelFormat4bppIndexed,
1471     &GUID_WICPixelFormat8bppIndexed,
1472     &GUID_WICPixelFormatBlackWhite,
1473     &GUID_WICPixelFormat2bppGray,
1474     &GUID_WICPixelFormat4bppGray,
1475     &GUID_WICPixelFormat8bppGray,
1476     &GUID_WICPixelFormat16bppGray,
1477     &GUID_WICPixelFormat16bppBGR555,
1478     &GUID_WICPixelFormat16bppBGR565,
1479     &GUID_WICPixelFormat16bppBGRA5551,
1480     &GUID_WICPixelFormat24bppBGR,
1481     &GUID_WICPixelFormat24bppRGB,
1482     &GUID_WICPixelFormat32bppBGR,
1483     &GUID_WICPixelFormat32bppRGB,
1484     &GUID_WICPixelFormat32bppBGRA,
1485     &GUID_WICPixelFormat32bppRGBA,
1486     &GUID_WICPixelFormat32bppPBGRA,
1487     &GUID_WICPixelFormat32bppPRGBA,
1488     &GUID_WICPixelFormat32bppGrayFloat,
1489     &GUID_WICPixelFormat48bppRGB,
1490     &GUID_WICPixelFormat64bppRGBA,
1491     &GUID_WICPixelFormat32bppCMYK,
1492     NULL
1493 };
1494 
1495 static struct regsvr_converter const converter_list[] = {
1496     {   &CLSID_WICDefaultFormatConverter,
1497 	"The Wine Project",
1498 	"Default Pixel Format Converter",
1499 	"1.0.0.0",
1500 	&GUID_VendorMicrosoft,
1501 	converter_formats
1502     },
1503     { NULL }			/* list terminator */
1504 };
1505 
1506 static const BYTE no_magic[1] = { 0 };
1507 static const BYTE no_mask[1] = { 0 };
1508 
1509 static const struct metadata_pattern ifd_metadata_pattern[] = {
1510     { 0, 1, no_magic, no_mask, 0 },
1511     { 0 }
1512 };
1513 
1514 static const struct reader_containers ifd_containers[] = {
1515     {
1516         &GUID_ContainerFormatTiff,
1517         ifd_metadata_pattern
1518     },
1519     { NULL } /* list terminator */
1520 };
1521 
1522 static const BYTE tEXt[] = "tEXt";
1523 
1524 static const struct metadata_pattern pngtext_metadata_pattern[] = {
1525     { 4, 4, tEXt, mask_all, 4 },
1526     { 0 }
1527 };
1528 
1529 static const struct reader_containers pngtext_containers[] = {
1530     {
1531         &GUID_ContainerFormatPng,
1532         pngtext_metadata_pattern
1533     },
1534     { NULL } /* list terminator */
1535 };
1536 
1537 static const BYTE gAMA[] = "gAMA";
1538 
1539 static const struct metadata_pattern pnggama_metadata_pattern[] = {
1540     { 4, 4, gAMA, mask_all, 4 },
1541     { 0 }
1542 };
1543 
1544 static const struct reader_containers pnggama_containers[] = {
1545     {
1546         &GUID_ContainerFormatPng,
1547         pnggama_metadata_pattern
1548     },
1549     { NULL } /* list terminator */
1550 };
1551 
1552 static const BYTE cHRM[] = "cHRM";
1553 
1554 static const struct metadata_pattern pngchrm_metadata_pattern[] = {
1555     { 4, 4, cHRM, mask_all, 4 },
1556     { 0 }
1557 };
1558 
1559 static const struct reader_containers pngchrm_containers[] = {
1560     {
1561         &GUID_ContainerFormatPng,
1562         pngchrm_metadata_pattern
1563     },
1564     { NULL } /* list terminator */
1565 };
1566 
1567 static const struct metadata_pattern lsd_metadata_patterns[] = {
1568     { 0, 6, gif87a_magic, mask_all, 0 },
1569     { 0, 6, gif89a_magic, mask_all, 0 },
1570     { 0 }
1571 };
1572 
1573 static const struct reader_containers lsd_containers[] = {
1574     {
1575         &GUID_ContainerFormatGif,
1576         lsd_metadata_patterns
1577     },
1578     { NULL } /* list terminator */
1579 };
1580 
1581 static const BYTE imd_magic[] = { 0x2c };
1582 
1583 static const struct metadata_pattern imd_metadata_pattern[] = {
1584     { 0, 1, imd_magic, mask_all, 1 },
1585     { 0 }
1586 };
1587 
1588 static const struct reader_containers imd_containers[] = {
1589     {
1590         &GUID_ContainerFormatGif,
1591         imd_metadata_pattern
1592     },
1593     { NULL } /* list terminator */
1594 };
1595 
1596 static const BYTE gce_magic[] = { 0x21, 0xf9, 0x04 };
1597 
1598 static const struct metadata_pattern gce_metadata_pattern[] = {
1599     { 0, 3, gce_magic, mask_all, 3 },
1600     { 0 }
1601 };
1602 
1603 static const struct reader_containers gce_containers[] = {
1604     {
1605         &GUID_ContainerFormatGif,
1606         gce_metadata_pattern
1607     },
1608     { NULL } /* list terminator */
1609 };
1610 
1611 static const BYTE ape_magic[] = { 0x21, 0xff, 0x0b };
1612 
1613 static const struct metadata_pattern ape_metadata_pattern[] = {
1614     { 0, 3, ape_magic, mask_all, 0 },
1615     { 0 }
1616 };
1617 
1618 static const struct reader_containers ape_containers[] = {
1619     {
1620         &GUID_ContainerFormatGif,
1621         ape_metadata_pattern
1622     },
1623     { NULL } /* list terminator */
1624 };
1625 
1626 static const BYTE gif_comment_magic[] = { 0x21, 0xfe };
1627 
1628 static const struct metadata_pattern gif_comment_metadata_pattern[] = {
1629     { 0, 2, gif_comment_magic, mask_all, 0 },
1630     { 0 }
1631 };
1632 
1633 static const struct reader_containers gif_comment_containers[] = {
1634     {
1635         &GUID_ContainerFormatGif,
1636         gif_comment_metadata_pattern
1637     },
1638     { NULL } /* list terminator */
1639 };
1640 
1641 static struct regsvr_metadatareader const metadatareader_list[] = {
1642     {   &CLSID_WICUnknownMetadataReader,
1643         "The Wine Project",
1644         "Unknown Metadata Reader",
1645         "1.0.0.0",
1646         "1.0.0.0",
1647         &GUID_VendorMicrosoft,
1648         &GUID_MetadataFormatUnknown,
1649         0, 0, 0,
1650         NULL
1651     },
1652     {   &CLSID_WICIfdMetadataReader,
1653         "The Wine Project",
1654         "Ifd Reader",
1655         "1.0.0.0",
1656         "1.0.0.0",
1657         &GUID_VendorMicrosoft,
1658         &GUID_MetadataFormatIfd,
1659         1, 1, 0,
1660         ifd_containers
1661     },
1662     {   &CLSID_WICPngChrmMetadataReader,
1663         "The Wine Project",
1664         "Chunk cHRM Reader",
1665         "1.0.0.0",
1666         "1.0.0.0",
1667         &GUID_VendorMicrosoft,
1668         &GUID_MetadataFormatChunkcHRM,
1669         0, 0, 0,
1670         pngchrm_containers
1671     },
1672     {   &CLSID_WICPngGamaMetadataReader,
1673         "The Wine Project",
1674         "Chunk gAMA Reader",
1675         "1.0.0.0",
1676         "1.0.0.0",
1677         &GUID_VendorMicrosoft,
1678         &GUID_MetadataFormatChunkgAMA,
1679         0, 0, 0,
1680         pnggama_containers
1681     },
1682     {   &CLSID_WICPngTextMetadataReader,
1683         "The Wine Project",
1684         "Chunk tEXt Reader",
1685         "1.0.0.0",
1686         "1.0.0.0",
1687         &GUID_VendorMicrosoft,
1688         &GUID_MetadataFormatChunktEXt,
1689         0, 0, 0,
1690         pngtext_containers
1691     },
1692     {   &CLSID_WICLSDMetadataReader,
1693         "The Wine Project",
1694         "Logical Screen Descriptor Reader",
1695         "1.0.0.0",
1696         "1.0.0.0",
1697         &GUID_VendorMicrosoft,
1698         &GUID_MetadataFormatLSD,
1699         0, 0, 0,
1700         lsd_containers
1701     },
1702     {   &CLSID_WICIMDMetadataReader,
1703         "The Wine Project",
1704         "Image Descriptor Reader",
1705         "1.0.0.0",
1706         "1.0.0.0",
1707         &GUID_VendorMicrosoft,
1708         &GUID_MetadataFormatIMD,
1709         0, 0, 0,
1710         imd_containers
1711     },
1712     {   &CLSID_WICGCEMetadataReader,
1713         "The Wine Project",
1714         "Graphic Control Extension Reader",
1715         "1.0.0.0",
1716         "1.0.0.0",
1717         &GUID_VendorMicrosoft,
1718         &GUID_MetadataFormatGCE,
1719         0, 0, 0,
1720         gce_containers
1721     },
1722     {   &CLSID_WICAPEMetadataReader,
1723         "The Wine Project",
1724         "Application Extension Reader",
1725         "1.0.0.0",
1726         "1.0.0.0",
1727         &GUID_VendorMicrosoft,
1728         &GUID_MetadataFormatAPE,
1729         0, 0, 0,
1730         ape_containers
1731     },
1732     {   &CLSID_WICGifCommentMetadataReader,
1733         "The Wine Project",
1734         "Comment Extension Reader",
1735         "1.0.0.0",
1736         "1.0.0.0",
1737         &GUID_VendorMicrosoft,
1738         &GUID_MetadataFormatGifComment,
1739         0, 0, 0,
1740         gif_comment_containers
1741     },
1742     { NULL }			/* list terminator */
1743 };
1744 
1745 static BYTE const channel_mask_1bit[] = { 0x01 };
1746 static BYTE const channel_mask_2bit[] = { 0x03 };
1747 static BYTE const channel_mask_4bit[] = { 0x0f };
1748 
1749 static BYTE const channel_mask_8bit[] = { 0xff, 0x00, 0x00, 0x00 };
1750 static BYTE const channel_mask_8bit2[] = { 0x00, 0xff, 0x00, 0x00 };
1751 static BYTE const channel_mask_8bit3[] = { 0x00, 0x00, 0xff, 0x00 };
1752 static BYTE const channel_mask_8bit4[] = { 0x00, 0x00, 0x00, 0xff };
1753 
1754 static BYTE const channel_mask_16bit[] = { 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
1755 static BYTE const channel_mask_16bit2[] = { 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 };
1756 static BYTE const channel_mask_16bit3[] = { 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00 };
1757 static BYTE const channel_mask_16bit4[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff };
1758 
1759 static BYTE const channel_mask_32bit[] = { 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 };
1760 
1761 static BYTE const channel_mask_128bit1[] = { 0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
1762 static BYTE const channel_mask_128bit2[] = { 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
1763 static BYTE const channel_mask_128bit3[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00 };
1764 static BYTE const channel_mask_128bit4[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff };
1765 
1766 static BYTE const channel_mask_5bit[] = { 0x1f, 0x00 };
1767 static BYTE const channel_mask_5bit2[] = { 0xe0, 0x03 };
1768 static BYTE const channel_mask_5bit3[] = { 0x00, 0x7c };
1769 static BYTE const channel_mask_5bit4[] = { 0x00, 0x80 };
1770 
1771 static BYTE const channel_mask_BGR565_2[] = { 0xe0, 0x07 };
1772 static BYTE const channel_mask_BGR565_3[] = { 0x00, 0xf8 };
1773 
1774 static BYTE const * const channel_masks_1bit[] = { channel_mask_1bit };
1775 static BYTE const * const channel_masks_2bit[] = { channel_mask_2bit };
1776 static BYTE const * const channel_masks_4bit[] = { channel_mask_4bit };
1777 static BYTE const * const channel_masks_8bit[] = { channel_mask_8bit,
1778     channel_mask_8bit2, channel_mask_8bit3, channel_mask_8bit4 };
1779 static BYTE const * const channel_masks_16bit[] = { channel_mask_16bit,
1780     channel_mask_16bit2, channel_mask_16bit3, channel_mask_16bit4};
1781 
1782 static BYTE const * const channel_masks_32bit[] = { channel_mask_32bit };
1783 static BYTE const * const channel_masks_128bit[] = { channel_mask_128bit1, channel_mask_128bit2, channel_mask_128bit3, channel_mask_128bit4 };
1784 
1785 static BYTE const * const channel_masks_BGRA5551[] = { channel_mask_5bit,
1786     channel_mask_5bit2, channel_mask_5bit3, channel_mask_5bit4 };
1787 
1788 static BYTE const * const channel_masks_BGR565[] = { channel_mask_5bit,
1789     channel_mask_BGR565_2, channel_mask_BGR565_3 };
1790 
1791 static struct regsvr_pixelformat const pixelformat_list[] = {
1792     {   &GUID_WICPixelFormat1bppIndexed,
1793         "The Wine Project",
1794         "1bpp Indexed",
1795         NULL, /* no version */
1796         &GUID_VendorMicrosoft,
1797         1, /* bitsperpixel */
1798         1, /* channel count */
1799         channel_masks_1bit,
1800         WICPixelFormatNumericRepresentationIndexed,
1801         0
1802     },
1803     {   &GUID_WICPixelFormat2bppIndexed,
1804         "The Wine Project",
1805         "2bpp Indexed",
1806         NULL, /* no version */
1807         &GUID_VendorMicrosoft,
1808         2, /* bitsperpixel */
1809         1, /* channel count */
1810         channel_masks_2bit,
1811         WICPixelFormatNumericRepresentationIndexed,
1812         0
1813     },
1814     {   &GUID_WICPixelFormat4bppIndexed,
1815         "The Wine Project",
1816         "4bpp Indexed",
1817         NULL, /* no version */
1818         &GUID_VendorMicrosoft,
1819         4, /* bitsperpixel */
1820         1, /* channel count */
1821         channel_masks_4bit,
1822         WICPixelFormatNumericRepresentationIndexed,
1823         0
1824     },
1825     {   &GUID_WICPixelFormat8bppIndexed,
1826         "The Wine Project",
1827         "8bpp Indexed",
1828         NULL, /* no version */
1829         &GUID_VendorMicrosoft,
1830         8, /* bitsperpixel */
1831         1, /* channel count */
1832         channel_masks_8bit,
1833         WICPixelFormatNumericRepresentationIndexed,
1834         0
1835     },
1836     {   &GUID_WICPixelFormatBlackWhite,
1837         "The Wine Project",
1838         "Black and White",
1839         NULL, /* no version */
1840         &GUID_VendorMicrosoft,
1841         1, /* bitsperpixel */
1842         1, /* channel count */
1843         channel_masks_1bit,
1844         WICPixelFormatNumericRepresentationUnsignedInteger,
1845         0
1846     },
1847     {   &GUID_WICPixelFormat2bppGray,
1848         "The Wine Project",
1849         "2bpp Grayscale",
1850         NULL, /* no version */
1851         &GUID_VendorMicrosoft,
1852         2, /* bitsperpixel */
1853         1, /* channel count */
1854         channel_masks_2bit,
1855         WICPixelFormatNumericRepresentationUnsignedInteger,
1856         0
1857     },
1858     {   &GUID_WICPixelFormat4bppGray,
1859         "The Wine Project",
1860         "4bpp Grayscale",
1861         NULL, /* no version */
1862         &GUID_VendorMicrosoft,
1863         4, /* bitsperpixel */
1864         1, /* channel count */
1865         channel_masks_4bit,
1866         WICPixelFormatNumericRepresentationUnsignedInteger,
1867         0
1868     },
1869     {   &GUID_WICPixelFormat8bppGray,
1870         "The Wine Project",
1871         "8bpp Grayscale",
1872         NULL, /* no version */
1873         &GUID_VendorMicrosoft,
1874         8, /* bitsperpixel */
1875         1, /* channel count */
1876         channel_masks_8bit,
1877         WICPixelFormatNumericRepresentationUnsignedInteger,
1878         0
1879     },
1880     {   &GUID_WICPixelFormat16bppGray,
1881         "The Wine Project",
1882         "16bpp Grayscale",
1883         NULL, /* no version */
1884         &GUID_VendorMicrosoft,
1885         16, /* bitsperpixel */
1886         1, /* channel count */
1887         channel_masks_16bit,
1888         WICPixelFormatNumericRepresentationUnsignedInteger,
1889         0
1890     },
1891     {   &GUID_WICPixelFormat16bppBGR555,
1892         "The Wine Project",
1893         "16bpp BGR555",
1894         NULL, /* no version */
1895         &GUID_VendorMicrosoft,
1896         16, /* bitsperpixel */
1897         3, /* channel count */
1898         channel_masks_BGRA5551,
1899         WICPixelFormatNumericRepresentationUnsignedInteger,
1900         0
1901     },
1902     {   &GUID_WICPixelFormat16bppBGR565,
1903         "The Wine Project",
1904         "16bpp BGR565",
1905         NULL, /* no version */
1906         &GUID_VendorMicrosoft,
1907         16, /* bitsperpixel */
1908         3, /* channel count */
1909         channel_masks_BGR565,
1910         WICPixelFormatNumericRepresentationUnsignedInteger,
1911         0
1912     },
1913     {   &GUID_WICPixelFormat16bppBGRA5551,
1914         "The Wine Project",
1915         "16bpp BGRA5551",
1916         NULL, /* no version */
1917         &GUID_VendorMicrosoft,
1918         16, /* bitsperpixel */
1919         4, /* channel count */
1920         channel_masks_BGRA5551,
1921         WICPixelFormatNumericRepresentationUnsignedInteger,
1922         1
1923     },
1924     {   &GUID_WICPixelFormat24bppBGR,
1925         "The Wine Project",
1926         "24bpp BGR",
1927         NULL, /* no version */
1928         &GUID_VendorMicrosoft,
1929         24, /* bitsperpixel */
1930         3, /* channel count */
1931         channel_masks_8bit,
1932         WICPixelFormatNumericRepresentationUnsignedInteger,
1933         0
1934     },
1935     {   &GUID_WICPixelFormat24bppRGB,
1936         "The Wine Project",
1937         "24bpp RGB",
1938         NULL, /* no version */
1939         &GUID_VendorMicrosoft,
1940         24, /* bitsperpixel */
1941         3, /* channel count */
1942         channel_masks_8bit,
1943         WICPixelFormatNumericRepresentationUnsignedInteger,
1944         0
1945     },
1946     {   &GUID_WICPixelFormat32bppBGR,
1947         "The Wine Project",
1948         "32bpp BGR",
1949         NULL, /* no version */
1950         &GUID_VendorMicrosoft,
1951         32, /* bitsperpixel */
1952         3, /* channel count */
1953         channel_masks_8bit,
1954         WICPixelFormatNumericRepresentationUnsignedInteger,
1955         0
1956     },
1957     {   &GUID_WICPixelFormat32bppRGB,
1958         "The Wine Project",
1959         "32bpp RGB",
1960         NULL, /* no version */
1961         &GUID_VendorMicrosoft,
1962         32, /* bitsperpixel */
1963         3, /* channel count */
1964         channel_masks_8bit,
1965         WICPixelFormatNumericRepresentationUnsignedInteger,
1966         0
1967     },
1968     {   &GUID_WICPixelFormat32bppBGRA,
1969         "The Wine Project",
1970         "32bpp BGRA",
1971         NULL, /* no version */
1972         &GUID_VendorMicrosoft,
1973         32, /* bitsperpixel */
1974         4, /* channel count */
1975         channel_masks_8bit,
1976         WICPixelFormatNumericRepresentationUnsignedInteger,
1977         1
1978     },
1979     {   &GUID_WICPixelFormat32bppRGBA,
1980         "The Wine Project",
1981         "32bpp RGBA",
1982         NULL, /* no version */
1983         &GUID_VendorMicrosoft,
1984         32, /* bitsperpixel */
1985         4, /* channel count */
1986         channel_masks_8bit,
1987         WICPixelFormatNumericRepresentationUnsignedInteger,
1988         1
1989     },
1990     {   &GUID_WICPixelFormat32bppPBGRA,
1991         "The Wine Project",
1992         "32bpp PBGRA",
1993         NULL, /* no version */
1994         &GUID_VendorMicrosoft,
1995         32, /* bitsperpixel */
1996         4, /* channel count */
1997         channel_masks_8bit,
1998         WICPixelFormatNumericRepresentationUnsignedInteger,
1999         1
2000     },
2001     {   &GUID_WICPixelFormat32bppPRGBA,
2002         "The Wine Project",
2003         "32bpp PRGBA",
2004         NULL, /* no version */
2005         &GUID_VendorMicrosoft,
2006         32, /* bitsperpixel */
2007         4, /* channel count */
2008         channel_masks_8bit,
2009         WICPixelFormatNumericRepresentationUnsignedInteger,
2010         1
2011     },
2012     {   &GUID_WICPixelFormat32bppGrayFloat,
2013         "The Wine Project",
2014         "32bpp GrayFloat",
2015         NULL, /* no version */
2016         &GUID_VendorMicrosoft,
2017         32, /* bitsperpixel */
2018         1, /* channel count */
2019         channel_masks_32bit,
2020         WICPixelFormatNumericRepresentationFloat,
2021         0
2022     },
2023     {   &GUID_WICPixelFormat48bppRGB,
2024         "The Wine Project",
2025         "48bpp RGB",
2026         NULL, /* no version */
2027         &GUID_VendorMicrosoft,
2028         48, /* bitsperpixel */
2029         3, /* channel count */
2030         channel_masks_16bit,
2031         WICPixelFormatNumericRepresentationUnsignedInteger,
2032         0
2033     },
2034     {   &GUID_WICPixelFormat64bppRGBA,
2035         "The Wine Project",
2036         "64bpp RGBA",
2037         NULL, /* no version */
2038         &GUID_VendorMicrosoft,
2039         64, /* bitsperpixel */
2040         4, /* channel count */
2041         channel_masks_16bit,
2042         WICPixelFormatNumericRepresentationUnsignedInteger,
2043         1
2044     },
2045     {   &GUID_WICPixelFormat64bppPRGBA,
2046         "The Wine Project",
2047         "64bpp PRGBA",
2048         NULL, /* no version */
2049         &GUID_VendorMicrosoft,
2050         64, /* bitsperpixel */
2051         4, /* channel count */
2052         channel_masks_16bit,
2053         WICPixelFormatNumericRepresentationUnsignedInteger,
2054         1
2055     },
2056     {   &GUID_WICPixelFormat32bppCMYK,
2057         "The Wine Project",
2058         "32bpp CMYK",
2059         NULL, /* no version */
2060         &GUID_VendorMicrosoft,
2061         32, /* bitsperpixel */
2062         4, /* channel count */
2063         channel_masks_8bit,
2064         WICPixelFormatNumericRepresentationUnsignedInteger,
2065         0
2066     },
2067     {   &GUID_WICPixelFormat64bppCMYK,
2068         "The Wine Project",
2069         "64bpp CMYK",
2070         NULL, /* no version */
2071         &GUID_VendorMicrosoft,
2072         64, /* bitsperpixel */
2073         4, /* channel count */
2074         channel_masks_16bit,
2075         WICPixelFormatNumericRepresentationUnsignedInteger,
2076         0
2077     },
2078     {   &GUID_WICPixelFormat128bppRGBAFloat,
2079         "The Wine Project",
2080         "128bpp RGBAFloat",
2081         NULL, /* no version */
2082         &GUID_VendorMicrosoft,
2083         128, /* bitsperpixel */
2084         4, /* channel count */
2085         channel_masks_128bit,
2086         WICPixelFormatNumericRepresentationFloat,
2087         1
2088     },
2089     { NULL }			/* list terminator */
2090 };
2091 
2092 struct regsvr_category
2093 {
2094     const CLSID *clsid; /* NULL for end of list */
2095 };
2096 
2097 static const struct regsvr_category category_list[] = {
2098     { &CATID_WICBitmapDecoders },
2099     { &CATID_WICBitmapEncoders },
2100     { &CATID_WICFormatConverters },
2101     { &CATID_WICMetadataReader },
2102     { &CATID_WICPixelFormats },
2103     { NULL }
2104 };
2105 
2106 static HRESULT register_categories(const struct regsvr_category *list)
2107 {
2108     LONG res;
2109     WCHAR buf[39];
2110     HKEY coclass_key, categories_key, instance_key;
2111 
2112     res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0,
2113                           KEY_READ | KEY_WRITE, NULL, &coclass_key, NULL);
2114     if (res != ERROR_SUCCESS) return HRESULT_FROM_WIN32(res);
2115 
2116     StringFromGUID2(&CLSID_WICImagingCategories, buf, 39);
2117     res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
2118                           KEY_READ | KEY_WRITE, NULL, &categories_key, NULL);
2119     if (res != ERROR_SUCCESS)
2120     {
2121         RegCloseKey(coclass_key);
2122         return HRESULT_FROM_WIN32(res);
2123     }
2124 
2125     res = RegCreateKeyExW(categories_key, instance_keyname, 0, NULL, 0,
2126                           KEY_READ | KEY_WRITE, NULL, &instance_key, NULL);
2127 
2128     for (; res == ERROR_SUCCESS && list->clsid; list++)
2129     {
2130         HKEY instance_clsid_key;
2131 
2132         StringFromGUID2(list->clsid, buf, 39);
2133         res = RegCreateKeyExW(instance_key, buf, 0, NULL, 0,
2134                               KEY_READ | KEY_WRITE, NULL, &instance_clsid_key, NULL);
2135         if (res == ERROR_SUCCESS)
2136         {
2137             res = RegSetValueExW(instance_clsid_key, clsid_valuename, 0, REG_SZ,
2138                                  (const BYTE *)buf, 78);
2139             RegCloseKey(instance_clsid_key);
2140         }
2141     }
2142 
2143     RegCloseKey(instance_key);
2144     RegCloseKey(categories_key);
2145     RegCloseKey(coclass_key);
2146 
2147     return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
2148 }
2149 
2150 static HRESULT unregister_categories(const struct regsvr_category *list)
2151 {
2152     LONG res;
2153     WCHAR buf[39];
2154     HKEY coclass_key, categories_key, instance_key;
2155 
2156     res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0,
2157                         KEY_READ | KEY_WRITE, &coclass_key);
2158     if (res != ERROR_SUCCESS) return HRESULT_FROM_WIN32(res);
2159 
2160     StringFromGUID2(&CLSID_WICImagingCategories, buf, 39);
2161     res = RegOpenKeyExW(coclass_key, buf, 0,
2162                         KEY_READ | KEY_WRITE, &categories_key);
2163     if (res != ERROR_SUCCESS)
2164     {
2165         if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
2166         RegCloseKey(coclass_key);
2167         return HRESULT_FROM_WIN32(res);
2168     }
2169 
2170     res = RegOpenKeyExW(categories_key, instance_keyname, 0,
2171                           KEY_READ | KEY_WRITE, &instance_key);
2172 
2173     for (; res == ERROR_SUCCESS && list->clsid; list++)
2174     {
2175         StringFromGUID2(list->clsid, buf, 39);
2176         res = RegDeleteTreeW(instance_key, buf);
2177     }
2178 
2179     RegCloseKey(instance_key);
2180     RegCloseKey(categories_key);
2181 
2182     StringFromGUID2(&CLSID_WICImagingCategories, buf, 39);
2183     res = RegDeleteTreeW(coclass_key, buf);
2184 
2185     RegCloseKey(coclass_key);
2186 
2187     return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
2188 }
2189 
2190 extern HRESULT WINAPI WIC_DllRegisterServer(void) DECLSPEC_HIDDEN;
2191 extern HRESULT WINAPI WIC_DllUnregisterServer(void) DECLSPEC_HIDDEN;
2192 
2193 HRESULT WINAPI DllRegisterServer(void)
2194 {
2195     HRESULT hr;
2196 
2197     TRACE("\n");
2198 
2199     hr = WIC_DllRegisterServer();
2200     if (SUCCEEDED(hr))
2201         hr = register_categories(category_list);
2202     if (SUCCEEDED(hr))
2203         hr = register_decoders(decoder_list);
2204     if (SUCCEEDED(hr))
2205         hr = register_encoders(encoder_list);
2206     if (SUCCEEDED(hr))
2207         hr = register_converters(converter_list);
2208     if (SUCCEEDED(hr))
2209         hr = register_metadatareaders(metadatareader_list);
2210     if (SUCCEEDED(hr))
2211         hr = register_pixelformats(pixelformat_list);
2212     return hr;
2213 }
2214 
2215 HRESULT WINAPI DllUnregisterServer(void)
2216 {
2217     HRESULT hr;
2218 
2219     TRACE("\n");
2220 
2221     hr = WIC_DllUnregisterServer();
2222     if (SUCCEEDED(hr))
2223         hr = unregister_categories(category_list);
2224     if (SUCCEEDED(hr))
2225         hr = unregister_decoders(decoder_list);
2226     if (SUCCEEDED(hr))
2227         hr = unregister_encoders(encoder_list);
2228     if (SUCCEEDED(hr))
2229         hr = unregister_converters(converter_list);
2230     if (SUCCEEDED(hr))
2231         hr = unregister_metadatareaders(metadatareader_list);
2232     if (SUCCEEDED(hr))
2233         hr = unregister_pixelformats(pixelformat_list);
2234     return hr;
2235 }
2236