xref: /reactos/dll/win32/windowscodecs/regsvr.c (revision 5bfe6a53)
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             static const WCHAR valuename_format[] = {'%','d',0};
1036             HKEY masks_key;
1037             UINT i, mask_size;
1038             WCHAR mask_valuename[11];
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_WICPixelFormat4bppIndexed,
1358     &GUID_WICPixelFormat8bppIndexed,
1359     NULL
1360 };
1361 
1362 static GUID const * const png_encode_formats[] = {
1363     &GUID_WICPixelFormat24bppBGR,
1364     &GUID_WICPixelFormatBlackWhite,
1365     &GUID_WICPixelFormat2bppGray,
1366     &GUID_WICPixelFormat4bppGray,
1367     &GUID_WICPixelFormat8bppGray,
1368     &GUID_WICPixelFormat16bppGray,
1369     &GUID_WICPixelFormat32bppBGR,
1370     &GUID_WICPixelFormat32bppBGRA,
1371     &GUID_WICPixelFormat48bppRGB,
1372     &GUID_WICPixelFormat64bppRGBA,
1373     &GUID_WICPixelFormat1bppIndexed,
1374     &GUID_WICPixelFormat2bppIndexed,
1375     &GUID_WICPixelFormat4bppIndexed,
1376     &GUID_WICPixelFormat8bppIndexed,
1377     NULL
1378 };
1379 
1380 static GUID const * const tiff_encode_formats[] = {
1381     &GUID_WICPixelFormatBlackWhite,
1382     &GUID_WICPixelFormat4bppGray,
1383     &GUID_WICPixelFormat8bppGray,
1384     &GUID_WICPixelFormat1bppIndexed,
1385     &GUID_WICPixelFormat4bppIndexed,
1386     &GUID_WICPixelFormat8bppIndexed,
1387     &GUID_WICPixelFormat24bppBGR,
1388     &GUID_WICPixelFormat32bppBGRA,
1389     &GUID_WICPixelFormat32bppPBGRA,
1390     &GUID_WICPixelFormat48bppRGB,
1391     &GUID_WICPixelFormat64bppRGBA,
1392     &GUID_WICPixelFormat64bppPRGBA,
1393     NULL
1394 };
1395 
1396 static GUID const * const icns_encode_formats[] = {
1397     &GUID_WICPixelFormat32bppBGRA,
1398     NULL
1399 };
1400 
1401 static struct regsvr_encoder const encoder_list[] = {
1402     {   &CLSID_WICBmpEncoder,
1403 	"The Wine Project",
1404 	"BMP Encoder",
1405 	"1.0.0.0",
1406 	&GUID_VendorMicrosoft,
1407 	&GUID_ContainerFormatBmp,
1408 	"image/bmp",
1409 	".bmp,.dib,.rle",
1410 	bmp_encode_formats
1411     },
1412     {   &CLSID_WICGifEncoder,
1413 	"The Wine Project",
1414 	"GIF Encoder",
1415 	"1.0.0.0",
1416 	&GUID_VendorMicrosoft,
1417 	&GUID_ContainerFormatGif,
1418 	"image/gif",
1419 	".gif",
1420 	gif_formats
1421     },
1422     {   &CLSID_WICJpegEncoder,
1423 	"The Wine Project",
1424 	"JPEG Encoder",
1425 	"1.0.0.0",
1426 	&GUID_VendorMicrosoft,
1427 	&GUID_ContainerFormatJpeg,
1428 	"image/jpeg",
1429 	".jpg;.jpeg;.jfif",
1430 	jpeg_formats
1431     },
1432     {   &CLSID_WICPngEncoder,
1433 	"The Wine Project",
1434 	"PNG Encoder",
1435 	"1.0.0.0",
1436 	&GUID_VendorMicrosoft,
1437 	&GUID_ContainerFormatPng,
1438 	"image/png",
1439 	".png",
1440 	png_encode_formats
1441     },
1442     {   &CLSID_WICTiffEncoder,
1443 	"The Wine Project",
1444 	"TIFF Encoder",
1445 	"1.0.0.0",
1446 	&GUID_VendorMicrosoft,
1447 	&GUID_ContainerFormatTiff,
1448 	"image/tiff",
1449 	".tif;.tiff",
1450 	tiff_encode_formats
1451     },
1452     {   &CLSID_WICIcnsEncoder,
1453 	"The Wine Project",
1454 	"ICNS Encoder",
1455 	"1.0.0.0",
1456 	&GUID_VendorWine,
1457 	NULL, /* no container format guid */
1458 	"image/icns",
1459 	".icns",
1460 	icns_encode_formats
1461     },
1462     { NULL }			/* list terminator */
1463 };
1464 
1465 static GUID const * const converter_formats[] = {
1466     &GUID_WICPixelFormat1bppIndexed,
1467     &GUID_WICPixelFormat2bppIndexed,
1468     &GUID_WICPixelFormat4bppIndexed,
1469     &GUID_WICPixelFormat8bppIndexed,
1470     &GUID_WICPixelFormatBlackWhite,
1471     &GUID_WICPixelFormat2bppGray,
1472     &GUID_WICPixelFormat4bppGray,
1473     &GUID_WICPixelFormat8bppGray,
1474     &GUID_WICPixelFormat16bppGray,
1475     &GUID_WICPixelFormat16bppBGR555,
1476     &GUID_WICPixelFormat16bppBGR565,
1477     &GUID_WICPixelFormat16bppBGRA5551,
1478     &GUID_WICPixelFormat24bppBGR,
1479     &GUID_WICPixelFormat24bppRGB,
1480     &GUID_WICPixelFormat32bppBGR,
1481     &GUID_WICPixelFormat32bppRGB,
1482     &GUID_WICPixelFormat32bppBGRA,
1483     &GUID_WICPixelFormat32bppRGBA,
1484     &GUID_WICPixelFormat32bppPBGRA,
1485     &GUID_WICPixelFormat32bppPRGBA,
1486     &GUID_WICPixelFormat32bppGrayFloat,
1487     &GUID_WICPixelFormat48bppRGB,
1488     &GUID_WICPixelFormat64bppRGBA,
1489     &GUID_WICPixelFormat32bppCMYK,
1490     NULL
1491 };
1492 
1493 static struct regsvr_converter const converter_list[] = {
1494     {   &CLSID_WICDefaultFormatConverter,
1495 	"The Wine Project",
1496 	"Default Pixel Format Converter",
1497 	"1.0.0.0",
1498 	&GUID_VendorMicrosoft,
1499 	converter_formats
1500     },
1501     { NULL }			/* list terminator */
1502 };
1503 
1504 static const BYTE no_magic[1] = { 0 };
1505 static const BYTE no_mask[1] = { 0 };
1506 
1507 static const struct metadata_pattern ifd_metadata_pattern[] = {
1508     { 0, 1, no_magic, no_mask, 0 },
1509     { 0 }
1510 };
1511 
1512 static const struct reader_containers ifd_containers[] = {
1513     {
1514         &GUID_ContainerFormatTiff,
1515         ifd_metadata_pattern
1516     },
1517     { NULL } /* list terminator */
1518 };
1519 
1520 static const BYTE tEXt[] = "tEXt";
1521 
1522 static const struct metadata_pattern pngtext_metadata_pattern[] = {
1523     { 4, 4, tEXt, mask_all, 4 },
1524     { 0 }
1525 };
1526 
1527 static const struct reader_containers pngtext_containers[] = {
1528     {
1529         &GUID_ContainerFormatPng,
1530         pngtext_metadata_pattern
1531     },
1532     { NULL } /* list terminator */
1533 };
1534 
1535 static const BYTE gAMA[] = "gAMA";
1536 
1537 static const struct metadata_pattern pnggama_metadata_pattern[] = {
1538     { 4, 4, gAMA, mask_all, 4 },
1539     { 0 }
1540 };
1541 
1542 static const struct reader_containers pnggama_containers[] = {
1543     {
1544         &GUID_ContainerFormatPng,
1545         pnggama_metadata_pattern
1546     },
1547     { NULL } /* list terminator */
1548 };
1549 
1550 static const BYTE cHRM[] = "cHRM";
1551 
1552 static const struct metadata_pattern pngchrm_metadata_pattern[] = {
1553     { 4, 4, cHRM, mask_all, 4 },
1554     { 0 }
1555 };
1556 
1557 static const struct reader_containers pngchrm_containers[] = {
1558     {
1559         &GUID_ContainerFormatPng,
1560         pngchrm_metadata_pattern
1561     },
1562     { NULL } /* list terminator */
1563 };
1564 
1565 static const struct metadata_pattern lsd_metadata_patterns[] = {
1566     { 0, 6, gif87a_magic, mask_all, 0 },
1567     { 0, 6, gif89a_magic, mask_all, 0 },
1568     { 0 }
1569 };
1570 
1571 static const struct reader_containers lsd_containers[] = {
1572     {
1573         &GUID_ContainerFormatGif,
1574         lsd_metadata_patterns
1575     },
1576     { NULL } /* list terminator */
1577 };
1578 
1579 static const BYTE imd_magic[] = { 0x2c };
1580 
1581 static const struct metadata_pattern imd_metadata_pattern[] = {
1582     { 0, 1, imd_magic, mask_all, 1 },
1583     { 0 }
1584 };
1585 
1586 static const struct reader_containers imd_containers[] = {
1587     {
1588         &GUID_ContainerFormatGif,
1589         imd_metadata_pattern
1590     },
1591     { NULL } /* list terminator */
1592 };
1593 
1594 static const BYTE gce_magic[] = { 0x21, 0xf9, 0x04 };
1595 
1596 static const struct metadata_pattern gce_metadata_pattern[] = {
1597     { 0, 3, gce_magic, mask_all, 3 },
1598     { 0 }
1599 };
1600 
1601 static const struct reader_containers gce_containers[] = {
1602     {
1603         &GUID_ContainerFormatGif,
1604         gce_metadata_pattern
1605     },
1606     { NULL } /* list terminator */
1607 };
1608 
1609 static const BYTE ape_magic[] = { 0x21, 0xff, 0x0b };
1610 
1611 static const struct metadata_pattern ape_metadata_pattern[] = {
1612     { 0, 3, ape_magic, mask_all, 0 },
1613     { 0 }
1614 };
1615 
1616 static const struct reader_containers ape_containers[] = {
1617     {
1618         &GUID_ContainerFormatGif,
1619         ape_metadata_pattern
1620     },
1621     { NULL } /* list terminator */
1622 };
1623 
1624 static const BYTE gif_comment_magic[] = { 0x21, 0xfe };
1625 
1626 static const struct metadata_pattern gif_comment_metadata_pattern[] = {
1627     { 0, 2, gif_comment_magic, mask_all, 0 },
1628     { 0 }
1629 };
1630 
1631 static const struct reader_containers gif_comment_containers[] = {
1632     {
1633         &GUID_ContainerFormatGif,
1634         gif_comment_metadata_pattern
1635     },
1636     { NULL } /* list terminator */
1637 };
1638 
1639 static struct regsvr_metadatareader const metadatareader_list[] = {
1640     {   &CLSID_WICUnknownMetadataReader,
1641         "The Wine Project",
1642         "Unknown Metadata Reader",
1643         "1.0.0.0",
1644         "1.0.0.0",
1645         &GUID_VendorMicrosoft,
1646         &GUID_MetadataFormatUnknown,
1647         0, 0, 0,
1648         NULL
1649     },
1650     {   &CLSID_WICIfdMetadataReader,
1651         "The Wine Project",
1652         "Ifd Reader",
1653         "1.0.0.0",
1654         "1.0.0.0",
1655         &GUID_VendorMicrosoft,
1656         &GUID_MetadataFormatIfd,
1657         1, 1, 0,
1658         ifd_containers
1659     },
1660     {   &CLSID_WICPngChrmMetadataReader,
1661         "The Wine Project",
1662         "Chunk cHRM Reader",
1663         "1.0.0.0",
1664         "1.0.0.0",
1665         &GUID_VendorMicrosoft,
1666         &GUID_MetadataFormatChunkcHRM,
1667         0, 0, 0,
1668         pngchrm_containers
1669     },
1670     {   &CLSID_WICPngGamaMetadataReader,
1671         "The Wine Project",
1672         "Chunk gAMA Reader",
1673         "1.0.0.0",
1674         "1.0.0.0",
1675         &GUID_VendorMicrosoft,
1676         &GUID_MetadataFormatChunkgAMA,
1677         0, 0, 0,
1678         pnggama_containers
1679     },
1680     {   &CLSID_WICPngTextMetadataReader,
1681         "The Wine Project",
1682         "Chunk tEXt Reader",
1683         "1.0.0.0",
1684         "1.0.0.0",
1685         &GUID_VendorMicrosoft,
1686         &GUID_MetadataFormatChunktEXt,
1687         0, 0, 0,
1688         pngtext_containers
1689     },
1690     {   &CLSID_WICLSDMetadataReader,
1691         "The Wine Project",
1692         "Logical Screen Descriptor Reader",
1693         "1.0.0.0",
1694         "1.0.0.0",
1695         &GUID_VendorMicrosoft,
1696         &GUID_MetadataFormatLSD,
1697         0, 0, 0,
1698         lsd_containers
1699     },
1700     {   &CLSID_WICIMDMetadataReader,
1701         "The Wine Project",
1702         "Image Descriptor Reader",
1703         "1.0.0.0",
1704         "1.0.0.0",
1705         &GUID_VendorMicrosoft,
1706         &GUID_MetadataFormatIMD,
1707         0, 0, 0,
1708         imd_containers
1709     },
1710     {   &CLSID_WICGCEMetadataReader,
1711         "The Wine Project",
1712         "Graphic Control Extension Reader",
1713         "1.0.0.0",
1714         "1.0.0.0",
1715         &GUID_VendorMicrosoft,
1716         &GUID_MetadataFormatGCE,
1717         0, 0, 0,
1718         gce_containers
1719     },
1720     {   &CLSID_WICAPEMetadataReader,
1721         "The Wine Project",
1722         "Application Extension Reader",
1723         "1.0.0.0",
1724         "1.0.0.0",
1725         &GUID_VendorMicrosoft,
1726         &GUID_MetadataFormatAPE,
1727         0, 0, 0,
1728         ape_containers
1729     },
1730     {   &CLSID_WICGifCommentMetadataReader,
1731         "The Wine Project",
1732         "Comment Extension Reader",
1733         "1.0.0.0",
1734         "1.0.0.0",
1735         &GUID_VendorMicrosoft,
1736         &GUID_MetadataFormatGifComment,
1737         0, 0, 0,
1738         gif_comment_containers
1739     },
1740     { NULL }			/* list terminator */
1741 };
1742 
1743 static BYTE const channel_mask_1bit[] = { 0x01 };
1744 static BYTE const channel_mask_2bit[] = { 0x03 };
1745 static BYTE const channel_mask_4bit[] = { 0x0f };
1746 
1747 static BYTE const channel_mask_8bit[] = { 0xff, 0x00, 0x00, 0x00 };
1748 static BYTE const channel_mask_8bit2[] = { 0x00, 0xff, 0x00, 0x00 };
1749 static BYTE const channel_mask_8bit3[] = { 0x00, 0x00, 0xff, 0x00 };
1750 static BYTE const channel_mask_8bit4[] = { 0x00, 0x00, 0x00, 0xff };
1751 
1752 static BYTE const channel_mask_16bit[] = { 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
1753 static BYTE const channel_mask_16bit2[] = { 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 };
1754 static BYTE const channel_mask_16bit3[] = { 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00 };
1755 static BYTE const channel_mask_16bit4[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff };
1756 
1757 static BYTE const channel_mask_32bit[] = { 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 };
1758 
1759 static BYTE const channel_mask_128bit1[] = { 0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
1760 static BYTE const channel_mask_128bit2[] = { 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
1761 static BYTE const channel_mask_128bit3[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00 };
1762 static BYTE const channel_mask_128bit4[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff };
1763 
1764 static BYTE const channel_mask_5bit[] = { 0x1f, 0x00 };
1765 static BYTE const channel_mask_5bit2[] = { 0xe0, 0x03 };
1766 static BYTE const channel_mask_5bit3[] = { 0x00, 0x7c };
1767 static BYTE const channel_mask_5bit4[] = { 0x00, 0x80 };
1768 
1769 static BYTE const channel_mask_BGR565_2[] = { 0xe0, 0x07 };
1770 static BYTE const channel_mask_BGR565_3[] = { 0x00, 0xf8 };
1771 
1772 static BYTE const * const channel_masks_1bit[] = { channel_mask_1bit };
1773 static BYTE const * const channel_masks_2bit[] = { channel_mask_2bit };
1774 static BYTE const * const channel_masks_4bit[] = { channel_mask_4bit };
1775 static BYTE const * const channel_masks_8bit[] = { channel_mask_8bit,
1776     channel_mask_8bit2, channel_mask_8bit3, channel_mask_8bit4 };
1777 static BYTE const * const channel_masks_16bit[] = { channel_mask_16bit,
1778     channel_mask_16bit2, channel_mask_16bit3, channel_mask_16bit4};
1779 
1780 static BYTE const * const channel_masks_32bit[] = { channel_mask_32bit };
1781 static BYTE const * const channel_masks_128bit[] = { channel_mask_128bit1, channel_mask_128bit2, channel_mask_128bit3, channel_mask_128bit4 };
1782 
1783 static BYTE const * const channel_masks_BGRA5551[] = { channel_mask_5bit,
1784     channel_mask_5bit2, channel_mask_5bit3, channel_mask_5bit4 };
1785 
1786 static BYTE const * const channel_masks_BGR565[] = { channel_mask_5bit,
1787     channel_mask_BGR565_2, channel_mask_BGR565_3 };
1788 
1789 static struct regsvr_pixelformat const pixelformat_list[] = {
1790     {   &GUID_WICPixelFormat1bppIndexed,
1791         "The Wine Project",
1792         "1bpp Indexed",
1793         NULL, /* no version */
1794         &GUID_VendorMicrosoft,
1795         1, /* bitsperpixel */
1796         1, /* channel count */
1797         channel_masks_1bit,
1798         WICPixelFormatNumericRepresentationIndexed,
1799         0
1800     },
1801     {   &GUID_WICPixelFormat2bppIndexed,
1802         "The Wine Project",
1803         "2bpp Indexed",
1804         NULL, /* no version */
1805         &GUID_VendorMicrosoft,
1806         2, /* bitsperpixel */
1807         1, /* channel count */
1808         channel_masks_2bit,
1809         WICPixelFormatNumericRepresentationIndexed,
1810         0
1811     },
1812     {   &GUID_WICPixelFormat4bppIndexed,
1813         "The Wine Project",
1814         "4bpp Indexed",
1815         NULL, /* no version */
1816         &GUID_VendorMicrosoft,
1817         4, /* bitsperpixel */
1818         1, /* channel count */
1819         channel_masks_4bit,
1820         WICPixelFormatNumericRepresentationIndexed,
1821         0
1822     },
1823     {   &GUID_WICPixelFormat8bppIndexed,
1824         "The Wine Project",
1825         "8bpp Indexed",
1826         NULL, /* no version */
1827         &GUID_VendorMicrosoft,
1828         8, /* bitsperpixel */
1829         1, /* channel count */
1830         channel_masks_8bit,
1831         WICPixelFormatNumericRepresentationIndexed,
1832         0
1833     },
1834     {   &GUID_WICPixelFormatBlackWhite,
1835         "The Wine Project",
1836         "Black and White",
1837         NULL, /* no version */
1838         &GUID_VendorMicrosoft,
1839         1, /* bitsperpixel */
1840         1, /* channel count */
1841         channel_masks_1bit,
1842         WICPixelFormatNumericRepresentationUnsignedInteger,
1843         0
1844     },
1845     {   &GUID_WICPixelFormat2bppGray,
1846         "The Wine Project",
1847         "2bpp Grayscale",
1848         NULL, /* no version */
1849         &GUID_VendorMicrosoft,
1850         2, /* bitsperpixel */
1851         1, /* channel count */
1852         channel_masks_2bit,
1853         WICPixelFormatNumericRepresentationUnsignedInteger,
1854         0
1855     },
1856     {   &GUID_WICPixelFormat4bppGray,
1857         "The Wine Project",
1858         "4bpp Grayscale",
1859         NULL, /* no version */
1860         &GUID_VendorMicrosoft,
1861         4, /* bitsperpixel */
1862         1, /* channel count */
1863         channel_masks_4bit,
1864         WICPixelFormatNumericRepresentationUnsignedInteger,
1865         0
1866     },
1867     {   &GUID_WICPixelFormat8bppGray,
1868         "The Wine Project",
1869         "8bpp Grayscale",
1870         NULL, /* no version */
1871         &GUID_VendorMicrosoft,
1872         8, /* bitsperpixel */
1873         1, /* channel count */
1874         channel_masks_8bit,
1875         WICPixelFormatNumericRepresentationUnsignedInteger,
1876         0
1877     },
1878     {   &GUID_WICPixelFormat16bppGray,
1879         "The Wine Project",
1880         "16bpp Grayscale",
1881         NULL, /* no version */
1882         &GUID_VendorMicrosoft,
1883         16, /* bitsperpixel */
1884         1, /* channel count */
1885         channel_masks_16bit,
1886         WICPixelFormatNumericRepresentationUnsignedInteger,
1887         0
1888     },
1889     {   &GUID_WICPixelFormat16bppBGR555,
1890         "The Wine Project",
1891         "16bpp BGR555",
1892         NULL, /* no version */
1893         &GUID_VendorMicrosoft,
1894         16, /* bitsperpixel */
1895         3, /* channel count */
1896         channel_masks_BGRA5551,
1897         WICPixelFormatNumericRepresentationUnsignedInteger,
1898         0
1899     },
1900     {   &GUID_WICPixelFormat16bppBGR565,
1901         "The Wine Project",
1902         "16bpp BGR565",
1903         NULL, /* no version */
1904         &GUID_VendorMicrosoft,
1905         16, /* bitsperpixel */
1906         3, /* channel count */
1907         channel_masks_BGR565,
1908         WICPixelFormatNumericRepresentationUnsignedInteger,
1909         0
1910     },
1911     {   &GUID_WICPixelFormat16bppBGRA5551,
1912         "The Wine Project",
1913         "16bpp BGRA5551",
1914         NULL, /* no version */
1915         &GUID_VendorMicrosoft,
1916         16, /* bitsperpixel */
1917         4, /* channel count */
1918         channel_masks_BGRA5551,
1919         WICPixelFormatNumericRepresentationUnsignedInteger,
1920         1
1921     },
1922     {   &GUID_WICPixelFormat24bppBGR,
1923         "The Wine Project",
1924         "24bpp BGR",
1925         NULL, /* no version */
1926         &GUID_VendorMicrosoft,
1927         24, /* bitsperpixel */
1928         3, /* channel count */
1929         channel_masks_8bit,
1930         WICPixelFormatNumericRepresentationUnsignedInteger,
1931         0
1932     },
1933     {   &GUID_WICPixelFormat24bppRGB,
1934         "The Wine Project",
1935         "24bpp RGB",
1936         NULL, /* no version */
1937         &GUID_VendorMicrosoft,
1938         24, /* bitsperpixel */
1939         3, /* channel count */
1940         channel_masks_8bit,
1941         WICPixelFormatNumericRepresentationUnsignedInteger,
1942         0
1943     },
1944     {   &GUID_WICPixelFormat32bppBGR,
1945         "The Wine Project",
1946         "32bpp BGR",
1947         NULL, /* no version */
1948         &GUID_VendorMicrosoft,
1949         32, /* bitsperpixel */
1950         3, /* channel count */
1951         channel_masks_8bit,
1952         WICPixelFormatNumericRepresentationUnsignedInteger,
1953         0
1954     },
1955     {   &GUID_WICPixelFormat32bppRGB,
1956         "The Wine Project",
1957         "32bpp RGB",
1958         NULL, /* no version */
1959         &GUID_VendorMicrosoft,
1960         32, /* bitsperpixel */
1961         3, /* channel count */
1962         channel_masks_8bit,
1963         WICPixelFormatNumericRepresentationUnsignedInteger,
1964         0
1965     },
1966     {   &GUID_WICPixelFormat32bppBGRA,
1967         "The Wine Project",
1968         "32bpp BGRA",
1969         NULL, /* no version */
1970         &GUID_VendorMicrosoft,
1971         32, /* bitsperpixel */
1972         4, /* channel count */
1973         channel_masks_8bit,
1974         WICPixelFormatNumericRepresentationUnsignedInteger,
1975         1
1976     },
1977     {   &GUID_WICPixelFormat32bppRGBA,
1978         "The Wine Project",
1979         "32bpp RGBA",
1980         NULL, /* no version */
1981         &GUID_VendorMicrosoft,
1982         32, /* bitsperpixel */
1983         4, /* channel count */
1984         channel_masks_8bit,
1985         WICPixelFormatNumericRepresentationUnsignedInteger,
1986         1
1987     },
1988     {   &GUID_WICPixelFormat32bppPBGRA,
1989         "The Wine Project",
1990         "32bpp PBGRA",
1991         NULL, /* no version */
1992         &GUID_VendorMicrosoft,
1993         32, /* bitsperpixel */
1994         4, /* channel count */
1995         channel_masks_8bit,
1996         WICPixelFormatNumericRepresentationUnsignedInteger,
1997         1
1998     },
1999     {   &GUID_WICPixelFormat32bppPRGBA,
2000         "The Wine Project",
2001         "32bpp PRGBA",
2002         NULL, /* no version */
2003         &GUID_VendorMicrosoft,
2004         32, /* bitsperpixel */
2005         4, /* channel count */
2006         channel_masks_8bit,
2007         WICPixelFormatNumericRepresentationUnsignedInteger,
2008         1
2009     },
2010     {   &GUID_WICPixelFormat32bppGrayFloat,
2011         "The Wine Project",
2012         "32bpp GrayFloat",
2013         NULL, /* no version */
2014         &GUID_VendorMicrosoft,
2015         32, /* bitsperpixel */
2016         1, /* channel count */
2017         channel_masks_32bit,
2018         WICPixelFormatNumericRepresentationFloat,
2019         0
2020     },
2021     {   &GUID_WICPixelFormat48bppRGB,
2022         "The Wine Project",
2023         "48bpp RGB",
2024         NULL, /* no version */
2025         &GUID_VendorMicrosoft,
2026         48, /* bitsperpixel */
2027         3, /* channel count */
2028         channel_masks_16bit,
2029         WICPixelFormatNumericRepresentationUnsignedInteger,
2030         0
2031     },
2032     {   &GUID_WICPixelFormat64bppRGBA,
2033         "The Wine Project",
2034         "64bpp RGBA",
2035         NULL, /* no version */
2036         &GUID_VendorMicrosoft,
2037         64, /* bitsperpixel */
2038         4, /* channel count */
2039         channel_masks_16bit,
2040         WICPixelFormatNumericRepresentationUnsignedInteger,
2041         1
2042     },
2043     {   &GUID_WICPixelFormat64bppPRGBA,
2044         "The Wine Project",
2045         "64bpp PRGBA",
2046         NULL, /* no version */
2047         &GUID_VendorMicrosoft,
2048         64, /* bitsperpixel */
2049         4, /* channel count */
2050         channel_masks_16bit,
2051         WICPixelFormatNumericRepresentationUnsignedInteger,
2052         1
2053     },
2054     {   &GUID_WICPixelFormat32bppCMYK,
2055         "The Wine Project",
2056         "32bpp CMYK",
2057         NULL, /* no version */
2058         &GUID_VendorMicrosoft,
2059         32, /* bitsperpixel */
2060         4, /* channel count */
2061         channel_masks_8bit,
2062         WICPixelFormatNumericRepresentationUnsignedInteger,
2063         0
2064     },
2065     {   &GUID_WICPixelFormat64bppCMYK,
2066         "The Wine Project",
2067         "64bpp CMYK",
2068         NULL, /* no version */
2069         &GUID_VendorMicrosoft,
2070         64, /* bitsperpixel */
2071         4, /* channel count */
2072         channel_masks_16bit,
2073         WICPixelFormatNumericRepresentationUnsignedInteger,
2074         0
2075     },
2076     {   &GUID_WICPixelFormat128bppRGBAFloat,
2077         "The Wine Project",
2078         "128bpp RGBAFloat",
2079         NULL, /* no version */
2080         &GUID_VendorMicrosoft,
2081         128, /* bitsperpixel */
2082         4, /* channel count */
2083         channel_masks_128bit,
2084         WICPixelFormatNumericRepresentationFloat,
2085         1
2086     },
2087     { NULL }			/* list terminator */
2088 };
2089 
2090 struct regsvr_category
2091 {
2092     const CLSID *clsid; /* NULL for end of list */
2093 };
2094 
2095 static const struct regsvr_category category_list[] = {
2096     { &CATID_WICBitmapDecoders },
2097     { &CATID_WICBitmapEncoders },
2098     { &CATID_WICFormatConverters },
2099     { &CATID_WICMetadataReader },
2100     { &CATID_WICPixelFormats },
2101     { NULL }
2102 };
2103 
2104 static HRESULT register_categories(const struct regsvr_category *list)
2105 {
2106     LONG res;
2107     WCHAR buf[39];
2108     HKEY coclass_key, categories_key, instance_key;
2109 
2110     res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0,
2111                           KEY_READ | KEY_WRITE, NULL, &coclass_key, NULL);
2112     if (res != ERROR_SUCCESS) return HRESULT_FROM_WIN32(res);
2113 
2114     StringFromGUID2(&CLSID_WICImagingCategories, buf, 39);
2115     res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
2116                           KEY_READ | KEY_WRITE, NULL, &categories_key, NULL);
2117     if (res != ERROR_SUCCESS)
2118     {
2119         RegCloseKey(coclass_key);
2120         return HRESULT_FROM_WIN32(res);
2121     }
2122 
2123     res = RegCreateKeyExW(categories_key, instance_keyname, 0, NULL, 0,
2124                           KEY_READ | KEY_WRITE, NULL, &instance_key, NULL);
2125 
2126     for (; res == ERROR_SUCCESS && list->clsid; list++)
2127     {
2128         HKEY instance_clsid_key;
2129 
2130         StringFromGUID2(list->clsid, buf, 39);
2131         res = RegCreateKeyExW(instance_key, buf, 0, NULL, 0,
2132                               KEY_READ | KEY_WRITE, NULL, &instance_clsid_key, NULL);
2133         if (res == ERROR_SUCCESS)
2134         {
2135             res = RegSetValueExW(instance_clsid_key, clsid_valuename, 0, REG_SZ,
2136                                  (const BYTE *)buf, 78);
2137             RegCloseKey(instance_clsid_key);
2138         }
2139     }
2140 
2141     RegCloseKey(instance_key);
2142     RegCloseKey(categories_key);
2143     RegCloseKey(coclass_key);
2144 
2145     return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
2146 }
2147 
2148 static HRESULT unregister_categories(const struct regsvr_category *list)
2149 {
2150     LONG res;
2151     WCHAR buf[39];
2152     HKEY coclass_key, categories_key, instance_key;
2153 
2154     res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0,
2155                         KEY_READ | KEY_WRITE, &coclass_key);
2156     if (res != ERROR_SUCCESS) return HRESULT_FROM_WIN32(res);
2157 
2158     StringFromGUID2(&CLSID_WICImagingCategories, buf, 39);
2159     res = RegOpenKeyExW(coclass_key, buf, 0,
2160                         KEY_READ | KEY_WRITE, &categories_key);
2161     if (res != ERROR_SUCCESS)
2162     {
2163         if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
2164         RegCloseKey(coclass_key);
2165         return HRESULT_FROM_WIN32(res);
2166     }
2167 
2168     res = RegOpenKeyExW(categories_key, instance_keyname, 0,
2169                           KEY_READ | KEY_WRITE, &instance_key);
2170 
2171     for (; res == ERROR_SUCCESS && list->clsid; list++)
2172     {
2173         StringFromGUID2(list->clsid, buf, 39);
2174         res = RegDeleteTreeW(instance_key, buf);
2175     }
2176 
2177     RegCloseKey(instance_key);
2178     RegCloseKey(categories_key);
2179 
2180     StringFromGUID2(&CLSID_WICImagingCategories, buf, 39);
2181     res = RegDeleteTreeW(coclass_key, buf);
2182 
2183     RegCloseKey(coclass_key);
2184 
2185     return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
2186 }
2187 
2188 extern HRESULT WINAPI WIC_DllRegisterServer(void) DECLSPEC_HIDDEN;
2189 extern HRESULT WINAPI WIC_DllUnregisterServer(void) DECLSPEC_HIDDEN;
2190 
2191 HRESULT WINAPI DllRegisterServer(void)
2192 {
2193     HRESULT hr;
2194 
2195     TRACE("\n");
2196 
2197     hr = WIC_DllRegisterServer();
2198     if (SUCCEEDED(hr))
2199         hr = register_categories(category_list);
2200     if (SUCCEEDED(hr))
2201         hr = register_decoders(decoder_list);
2202     if (SUCCEEDED(hr))
2203         hr = register_encoders(encoder_list);
2204     if (SUCCEEDED(hr))
2205         hr = register_converters(converter_list);
2206     if (SUCCEEDED(hr))
2207         hr = register_metadatareaders(metadatareader_list);
2208     if (SUCCEEDED(hr))
2209         hr = register_pixelformats(pixelformat_list);
2210     return hr;
2211 }
2212 
2213 HRESULT WINAPI DllUnregisterServer(void)
2214 {
2215     HRESULT hr;
2216 
2217     TRACE("\n");
2218 
2219     hr = WIC_DllUnregisterServer();
2220     if (SUCCEEDED(hr))
2221         hr = unregister_categories(category_list);
2222     if (SUCCEEDED(hr))
2223         hr = unregister_decoders(decoder_list);
2224     if (SUCCEEDED(hr))
2225         hr = unregister_encoders(encoder_list);
2226     if (SUCCEEDED(hr))
2227         hr = unregister_converters(converter_list);
2228     if (SUCCEEDED(hr))
2229         hr = unregister_metadatareaders(metadatareader_list);
2230     if (SUCCEEDED(hr))
2231         hr = unregister_pixelformats(pixelformat_list);
2232     return hr;
2233 }
2234