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