2 * Copyright 2009 Vincent Povirk for CodeWeavers
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.
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.
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
19 #define NONAMELESSUNION
20 #define NONAMELESSSTRUCT
35 #include "wincodecsdk.h"
37 #include "wine/debug.h"
38 #include "wine/unicode.h"
40 #include "wincodecs_private.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
44 /***********************************************************************
45 * interface for self-registering
47 struct decoder_pattern
49 DWORD length; /* 0 for end of list */
58 CLSID const *clsid; /* NULL for end of list */
63 GUID const *container_format;
66 GUID const * const *formats;
67 const struct decoder_pattern *patterns;
70 static HRESULT register_decoders(struct regsvr_decoder const *list);
71 static HRESULT unregister_decoders(struct regsvr_decoder const *list);
75 CLSID const *clsid; /* NULL for end of list */
80 GUID const *container_format;
83 GUID const * const *formats;
86 static HRESULT register_encoders(struct regsvr_encoder const *list);
87 static HRESULT unregister_encoders(struct regsvr_encoder const *list);
89 struct regsvr_converter
91 CLSID const *clsid; /* NULL for end of list */
96 GUID const * const *formats;
99 static HRESULT register_converters(struct regsvr_converter const *list);
100 static HRESULT unregister_converters(struct regsvr_converter const *list);
102 struct metadata_pattern
111 struct reader_containers
114 const struct metadata_pattern *patterns;
117 struct regsvr_metadatareader
119 CLSID const *clsid; /* NULL for end of list */
125 GUID const *metadata_format;
126 DWORD requires_fullstream;
127 DWORD supports_padding;
128 DWORD requires_fixedsize;
129 const struct reader_containers *containers;
132 static HRESULT register_metadatareaders(struct regsvr_metadatareader const *list);
133 static HRESULT unregister_metadatareaders(struct regsvr_metadatareader const *list);
135 struct regsvr_pixelformat
137 CLSID const *clsid; /* NULL for end of list */
144 BYTE const * const *channelmasks;
145 WICPixelFormatNumericRepresentation numericrepresentation;
149 static HRESULT register_pixelformats(struct regsvr_pixelformat const *list);
150 static HRESULT unregister_pixelformats(struct regsvr_pixelformat const *list);
152 /***********************************************************************
153 * static string constants
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',
162 static const WCHAR ips32_keyname[] = {
163 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
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',
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};
202 /***********************************************************************
205 static HRESULT register_decoders(struct regsvr_decoder const *list)
207 LONG res = ERROR_SUCCESS;
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)
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;
225 if (res != ERROR_SUCCESS)
226 RegCloseKey(coclass_key);
228 if (res != ERROR_SUCCESS) goto error_return;
230 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
232 HKEY instance_clsid_key;
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;
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);
247 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
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;
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;
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;
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;
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;
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;
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;
300 GUID const * const *format;
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)
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);
314 RegCloseKey(formats_key);
315 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
318 if (list->patterns) {
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++)
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);
351 RegCloseKey(patterns_key);
352 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
355 error_close_clsid_key:
356 RegCloseKey(clsid_key);
359 error_close_coclass_key:
360 RegCloseKey(instance_key);
361 RegCloseKey(decoders_key);
362 RegCloseKey(coclass_key);
364 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
367 /***********************************************************************
368 * unregister_decoders
370 static HRESULT unregister_decoders(struct regsvr_decoder const *list)
372 LONG res = ERROR_SUCCESS;
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;
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)
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;
392 if (res != ERROR_SUCCESS)
393 RegCloseKey(coclass_key);
395 if (res != ERROR_SUCCESS) goto error_return;
397 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
398 StringFromGUID2(list->clsid, buf, 39);
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;
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;
409 error_close_coclass_key:
410 RegCloseKey(instance_key);
411 RegCloseKey(decoders_key);
412 RegCloseKey(coclass_key);
414 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
417 /***********************************************************************
420 static HRESULT register_encoders(struct regsvr_encoder const *list)
422 LONG res = ERROR_SUCCESS;
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)
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;
440 if (res != ERROR_SUCCESS)
441 RegCloseKey(coclass_key);
443 if (res != ERROR_SUCCESS) goto error_return;
445 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
447 HKEY instance_clsid_key;
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;
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);
462 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
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;
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;
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;
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;
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;
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;
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;
515 GUID const * const *format;
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)
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);
529 RegCloseKey(formats_key);
530 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
533 error_close_clsid_key:
534 RegCloseKey(clsid_key);
537 error_close_coclass_key:
538 RegCloseKey(instance_key);
539 RegCloseKey(encoders_key);
540 RegCloseKey(coclass_key);
542 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
545 /***********************************************************************
546 * unregister_encoders
548 static HRESULT unregister_encoders(struct regsvr_encoder const *list)
550 LONG res = ERROR_SUCCESS;
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;
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)
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;
570 if (res != ERROR_SUCCESS)
571 RegCloseKey(coclass_key);
573 if (res != ERROR_SUCCESS) goto error_return;
575 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
576 StringFromGUID2(list->clsid, buf, 39);
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;
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;
587 error_close_coclass_key:
588 RegCloseKey(instance_key);
589 RegCloseKey(encoders_key);
590 RegCloseKey(coclass_key);
592 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
595 /***********************************************************************
596 * register_converters
598 static HRESULT register_converters(struct regsvr_converter const *list)
600 LONG res = ERROR_SUCCESS;
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)
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;
618 if (res != ERROR_SUCCESS)
619 RegCloseKey(coclass_key);
621 if (res != ERROR_SUCCESS) goto error_return;
623 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
625 HKEY instance_clsid_key;
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;
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);
640 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
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;
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;
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;
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;
672 GUID const * const *format;
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)
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);
686 RegCloseKey(formats_key);
687 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
690 error_close_clsid_key:
691 RegCloseKey(clsid_key);
694 error_close_coclass_key:
695 RegCloseKey(instance_key);
696 RegCloseKey(converters_key);
697 RegCloseKey(coclass_key);
699 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
702 /***********************************************************************
703 * unregister_converters
705 static HRESULT unregister_converters(struct regsvr_converter const *list)
707 LONG res = ERROR_SUCCESS;
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;
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)
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;
727 if (res != ERROR_SUCCESS)
728 RegCloseKey(coclass_key);
730 if (res != ERROR_SUCCESS) goto error_return;
732 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
733 StringFromGUID2(list->clsid, buf, 39);
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;
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;
744 error_close_coclass_key:
745 RegCloseKey(instance_key);
746 RegCloseKey(converters_key);
747 RegCloseKey(coclass_key);
749 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
752 /***********************************************************************
753 * register_metadatareaders
755 static HRESULT register_metadatareaders(struct regsvr_metadatareader const *list)
757 LONG res = ERROR_SUCCESS;
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)
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;
775 if (res != ERROR_SUCCESS)
776 RegCloseKey(coclass_key);
778 if (res != ERROR_SUCCESS) goto error_return;
780 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
782 HKEY instance_clsid_key;
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;
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);
797 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
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;
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;
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;
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;
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;
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;
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;
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;
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;
855 if (list->containers) {
857 const struct reader_containers *container;
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)
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;
871 for (i=0; container->patterns[i].length; i++)
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);
895 RegCloseKey(format_key);
897 RegCloseKey(containers_key);
900 error_close_clsid_key:
901 RegCloseKey(clsid_key);
904 error_close_coclass_key:
905 RegCloseKey(instance_key);
906 RegCloseKey(readers_key);
907 RegCloseKey(coclass_key);
909 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
912 /***********************************************************************
913 * unregister_metadatareaders
915 static HRESULT unregister_metadatareaders(struct regsvr_metadatareader const *list)
917 LONG res = ERROR_SUCCESS;
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;
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)
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;
937 if (res != ERROR_SUCCESS)
938 RegCloseKey(coclass_key);
940 if (res != ERROR_SUCCESS) goto error_return;
942 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
943 StringFromGUID2(list->clsid, buf, 39);
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;
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;
954 error_close_coclass_key:
955 RegCloseKey(instance_key);
956 RegCloseKey(readers_key);
957 RegCloseKey(coclass_key);
959 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
962 /***********************************************************************
963 * register_pixelformats
965 static HRESULT register_pixelformats(struct regsvr_pixelformat const *list)
967 LONG res = ERROR_SUCCESS;
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)
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;
985 if (res != ERROR_SUCCESS)
986 RegCloseKey(coclass_key);
988 if (res != ERROR_SUCCESS) goto error_return;
990 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
992 HKEY instance_clsid_key;
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;
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);
1007 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
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;
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;
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;
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;
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;
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;
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;
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;
1053 if (list->channelmasks) {
1056 WCHAR mask_valuename[11];
1057 const WCHAR valuename_format[] = {'%','d',0};
1059 mask_size = (list->bitsperpixel + 7)/8;
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++)
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;
1071 RegCloseKey(masks_key);
1072 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
1075 error_close_clsid_key:
1076 RegCloseKey(clsid_key);
1079 error_close_coclass_key:
1080 RegCloseKey(instance_key);
1081 RegCloseKey(formats_key);
1082 RegCloseKey(coclass_key);
1084 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
1087 /***********************************************************************
1088 * unregister_pixelformats
1090 static HRESULT unregister_pixelformats(struct regsvr_pixelformat const *list)
1092 LONG res = ERROR_SUCCESS;
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;
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)
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;
1112 if (res != ERROR_SUCCESS)
1113 RegCloseKey(coclass_key);
1115 if (res != ERROR_SUCCESS) goto error_return;
1117 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
1118 StringFromGUID2(list->clsid, buf, 39);
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;
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;
1129 error_close_coclass_key:
1130 RegCloseKey(instance_key);
1131 RegCloseKey(formats_key);
1132 RegCloseKey(coclass_key);
1134 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
1137 /***********************************************************************
1140 static const BYTE mask_all[] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
1142 static const BYTE bmp_magic[] = {0x42,0x4d};
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,
1157 static struct decoder_pattern const bmp_patterns[] = {
1158 {2,0,bmp_magic,mask_all,0},
1162 static const BYTE gif87a_magic[6] = "GIF87a";
1163 static const BYTE gif89a_magic[6] = "GIF89a";
1165 static GUID const * const gif_formats[] = {
1166 &GUID_WICPixelFormat8bppIndexed,
1170 static struct decoder_pattern const gif_patterns[] = {
1171 {6,0,gif87a_magic,mask_all,0},
1172 {6,0,gif89a_magic,mask_all,0},
1176 static const BYTE ico_magic[] = {00,00,01,00};
1178 static GUID const * const ico_formats[] = {
1179 &GUID_WICPixelFormat32bppBGRA,
1183 static struct decoder_pattern const ico_patterns[] = {
1184 {4,0,ico_magic,mask_all,0},
1188 static const BYTE jpeg_magic[] = {0xff, 0xd8};
1190 static GUID const * const jpeg_formats[] = {
1191 &GUID_WICPixelFormat24bppBGR,
1192 &GUID_WICPixelFormat32bppCMYK,
1193 &GUID_WICPixelFormat8bppGray,
1197 static struct decoder_pattern const jpeg_patterns[] = {
1198 {2,0,jpeg_magic,mask_all,0},
1202 static const BYTE png_magic[] = {137,80,78,71,13,10,26,10};
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,
1221 static struct decoder_pattern const png_patterns[] = {
1222 {8,0,png_magic,mask_all,0},
1226 static const BYTE tiff_magic_le[] = {0x49,0x49,42,0};
1227 static const BYTE tiff_magic_be[] = {0x4d,0x4d,0,42};
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,
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},
1251 static const BYTE tga_footer_magic[18] = "TRUEVISION-XFILE.";
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};
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};
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};
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,
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},
1281 static struct regsvr_decoder const decoder_list[] = {
1282 { &CLSID_WICBmpDecoder,
1286 &GUID_VendorMicrosoft,
1287 &GUID_ContainerFormatBmp,
1293 { &CLSID_WICGifDecoder,
1297 &GUID_VendorMicrosoft,
1298 &GUID_ContainerFormatGif,
1304 { &CLSID_WICIcoDecoder,
1308 &GUID_VendorMicrosoft,
1309 &GUID_ContainerFormatIco,
1310 "image/vnd.microsoft.icon",
1315 { &CLSID_WICJpegDecoder,
1319 &GUID_VendorMicrosoft,
1320 &GUID_ContainerFormatJpeg,
1326 { &CLSID_WICPngDecoder,
1330 &GUID_VendorMicrosoft,
1331 &GUID_ContainerFormatPng,
1337 { &CLSID_WICTiffDecoder,
1341 &GUID_VendorMicrosoft,
1342 &GUID_ContainerFormatTiff,
1345 tiff_decode_formats,
1348 { &CLSID_WineTgaDecoder,
1353 &GUID_WineContainerFormatTga,
1359 { NULL } /* list terminator */
1362 static GUID const * const bmp_encode_formats[] = {
1363 &GUID_WICPixelFormat16bppBGR555,
1364 &GUID_WICPixelFormat16bppBGR565,
1365 &GUID_WICPixelFormat24bppBGR,
1366 &GUID_WICPixelFormat32bppBGR,
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,
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,
1397 static GUID const * const icns_encode_formats[] = {
1398 &GUID_WICPixelFormat32bppBGRA,
1402 static struct regsvr_encoder const encoder_list[] = {
1403 { &CLSID_WICBmpEncoder,
1407 &GUID_VendorMicrosoft,
1408 &GUID_ContainerFormatBmp,
1413 { &CLSID_WICJpegEncoder,
1417 &GUID_VendorMicrosoft,
1418 &GUID_ContainerFormatJpeg,
1423 { &CLSID_WICPngEncoder,
1427 &GUID_VendorMicrosoft,
1428 &GUID_ContainerFormatPng,
1433 { &CLSID_WICTiffEncoder,
1437 &GUID_VendorMicrosoft,
1438 &GUID_ContainerFormatTiff,
1443 { &CLSID_WICIcnsEncoder,
1448 NULL, /* no container format guid */
1453 { NULL } /* list terminator */
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,
1479 static struct regsvr_converter const converter_list[] = {
1480 { &CLSID_WICDefaultFormatConverter,
1482 "Default Pixel Format Converter",
1484 &GUID_VendorMicrosoft,
1487 { NULL } /* list terminator */
1490 static const BYTE no_magic[1] = { 0 };
1491 static const BYTE no_mask[1] = { 0 };
1493 static const struct metadata_pattern ifd_metadata_pattern[] = {
1494 { 0, 1, no_magic, no_mask, 0 },
1498 static const struct reader_containers ifd_containers[] = {
1500 &GUID_ContainerFormatTiff,
1501 ifd_metadata_pattern
1503 { NULL } /* list terminator */
1506 static const BYTE tEXt[] = "tEXt";
1508 static const struct metadata_pattern pngtext_metadata_pattern[] = {
1509 { 4, 4, tEXt, mask_all, 4 },
1513 static const struct reader_containers pngtext_containers[] = {
1515 &GUID_ContainerFormatPng,
1516 pngtext_metadata_pattern
1518 { NULL } /* list terminator */
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 },
1527 static const struct reader_containers lsd_containers[] = {
1529 &GUID_ContainerFormatGif,
1530 lsd_metadata_patterns
1532 { NULL } /* list terminator */
1535 static const BYTE imd_magic[] = { 0x2c };
1537 static const struct metadata_pattern imd_metadata_pattern[] = {
1538 { 0, 1, imd_magic, mask_all, 1 },
1542 static const struct reader_containers imd_containers[] = {
1544 &GUID_ContainerFormatGif,
1545 imd_metadata_pattern
1547 { NULL } /* list terminator */
1550 static const BYTE gce_magic[] = { 0x21, 0xf9, 0x04 };
1552 static const struct metadata_pattern gce_metadata_pattern[] = {
1553 { 0, 3, gce_magic, mask_all, 3 },
1557 static const struct reader_containers gce_containers[] = {
1559 &GUID_ContainerFormatGif,
1560 gce_metadata_pattern
1562 { NULL } /* list terminator */
1565 static const BYTE ape_magic[] = { 0x21, 0xff, 0x0b };
1567 static const struct metadata_pattern ape_metadata_pattern[] = {
1568 { 0, 3, ape_magic, mask_all, 0 },
1572 static const struct reader_containers ape_containers[] = {
1574 &GUID_ContainerFormatGif,
1575 ape_metadata_pattern
1577 { NULL } /* list terminator */
1580 static const BYTE gif_comment_magic[] = { 0x21, 0xfe };
1582 static const struct metadata_pattern gif_comment_metadata_pattern[] = {
1583 { 0, 2, gif_comment_magic, mask_all, 0 },
1587 static const struct reader_containers gif_comment_containers[] = {
1589 &GUID_ContainerFormatGif,
1590 gif_comment_metadata_pattern
1592 { NULL } /* list terminator */
1595 static struct regsvr_metadatareader const metadatareader_list[] = {
1596 { &CLSID_WICUnknownMetadataReader,
1598 "Unknown Metadata Reader",
1601 &GUID_VendorMicrosoft,
1602 &GUID_MetadataFormatUnknown,
1606 { &CLSID_WICIfdMetadataReader,
1611 &GUID_VendorMicrosoft,
1612 &GUID_MetadataFormatIfd,
1616 { &CLSID_WICPngTextMetadataReader,
1618 "Chunk tEXt Reader",
1621 &GUID_VendorMicrosoft,
1622 &GUID_MetadataFormatChunktEXt,
1626 { &CLSID_WICLSDMetadataReader,
1628 "Logical Screen Descriptor Reader",
1631 &GUID_VendorMicrosoft,
1632 &GUID_MetadataFormatLSD,
1636 { &CLSID_WICIMDMetadataReader,
1638 "Image Descriptor Reader",
1641 &GUID_VendorMicrosoft,
1642 &GUID_MetadataFormatIMD,
1646 { &CLSID_WICGCEMetadataReader,
1648 "Graphic Control Extension Reader",
1651 &GUID_VendorMicrosoft,
1652 &GUID_MetadataFormatGCE,
1656 { &CLSID_WICAPEMetadataReader,
1658 "Application Extension Reader",
1661 &GUID_VendorMicrosoft,
1662 &GUID_MetadataFormatAPE,
1666 { &CLSID_WICGifCommentMetadataReader,
1668 "Comment Extension Reader",
1671 &GUID_VendorMicrosoft,
1672 &GUID_MetadataFormatGifComment,
1674 gif_comment_containers
1676 { NULL } /* list terminator */
1679 static BYTE const channel_mask_1bit[] = { 0x01 };
1680 static BYTE const channel_mask_2bit[] = { 0x03 };
1681 static BYTE const channel_mask_4bit[] = { 0x0f };
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 };
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 };
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 };
1698 static BYTE const channel_mask_BGR565_2[] = { 0xe0, 0x07 };
1699 static BYTE const channel_mask_BGR565_3[] = { 0x00, 0xf8 };
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};
1709 static BYTE const * const channel_masks_BGRA5551[] = { channel_mask_5bit,
1710 channel_mask_5bit2, channel_mask_5bit3, channel_mask_5bit4 };
1712 static BYTE const * const channel_masks_BGR565[] = { channel_mask_5bit,
1713 channel_mask_BGR565_2, channel_mask_BGR565_3 };
1715 static struct regsvr_pixelformat const pixelformat_list[] = {
1716 { &GUID_WICPixelFormat1bppIndexed,
1719 NULL, /* no version */
1720 &GUID_VendorMicrosoft,
1721 1, /* bitsperpixel */
1722 1, /* channel count */
1724 WICPixelFormatNumericRepresentationIndexed,
1727 { &GUID_WICPixelFormat2bppIndexed,
1730 NULL, /* no version */
1731 &GUID_VendorMicrosoft,
1732 2, /* bitsperpixel */
1733 1, /* channel count */
1735 WICPixelFormatNumericRepresentationIndexed,
1738 { &GUID_WICPixelFormat4bppIndexed,
1741 NULL, /* no version */
1742 &GUID_VendorMicrosoft,
1743 4, /* bitsperpixel */
1744 1, /* channel count */
1746 WICPixelFormatNumericRepresentationIndexed,
1749 { &GUID_WICPixelFormat8bppIndexed,
1752 NULL, /* no version */
1753 &GUID_VendorMicrosoft,
1754 8, /* bitsperpixel */
1755 1, /* channel count */
1757 WICPixelFormatNumericRepresentationIndexed,
1760 { &GUID_WICPixelFormatBlackWhite,
1763 NULL, /* no version */
1764 &GUID_VendorMicrosoft,
1765 1, /* bitsperpixel */
1766 1, /* channel count */
1768 WICPixelFormatNumericRepresentationUnsignedInteger,
1771 { &GUID_WICPixelFormat2bppGray,
1774 NULL, /* no version */
1775 &GUID_VendorMicrosoft,
1776 2, /* bitsperpixel */
1777 1, /* channel count */
1779 WICPixelFormatNumericRepresentationUnsignedInteger,
1782 { &GUID_WICPixelFormat4bppGray,
1785 NULL, /* no version */
1786 &GUID_VendorMicrosoft,
1787 4, /* bitsperpixel */
1788 1, /* channel count */
1790 WICPixelFormatNumericRepresentationUnsignedInteger,
1793 { &GUID_WICPixelFormat8bppGray,
1796 NULL, /* no version */
1797 &GUID_VendorMicrosoft,
1798 8, /* bitsperpixel */
1799 1, /* channel count */
1801 WICPixelFormatNumericRepresentationUnsignedInteger,
1804 { &GUID_WICPixelFormat16bppGray,
1807 NULL, /* no version */
1808 &GUID_VendorMicrosoft,
1809 16, /* bitsperpixel */
1810 1, /* channel count */
1811 channel_masks_16bit,
1812 WICPixelFormatNumericRepresentationUnsignedInteger,
1815 { &GUID_WICPixelFormat16bppBGR555,
1818 NULL, /* no version */
1819 &GUID_VendorMicrosoft,
1820 16, /* bitsperpixel */
1821 3, /* channel count */
1822 channel_masks_BGRA5551,
1823 WICPixelFormatNumericRepresentationUnsignedInteger,
1826 { &GUID_WICPixelFormat16bppBGR565,
1829 NULL, /* no version */
1830 &GUID_VendorMicrosoft,
1831 16, /* bitsperpixel */
1832 3, /* channel count */
1833 channel_masks_BGR565,
1834 WICPixelFormatNumericRepresentationUnsignedInteger,
1837 { &GUID_WICPixelFormat16bppBGRA5551,
1840 NULL, /* no version */
1841 &GUID_VendorMicrosoft,
1842 16, /* bitsperpixel */
1843 4, /* channel count */
1844 channel_masks_BGRA5551,
1845 WICPixelFormatNumericRepresentationUnsignedInteger,
1848 { &GUID_WICPixelFormat24bppBGR,
1851 NULL, /* no version */
1852 &GUID_VendorMicrosoft,
1853 24, /* bitsperpixel */
1854 3, /* channel count */
1856 WICPixelFormatNumericRepresentationUnsignedInteger,
1859 { &GUID_WICPixelFormat32bppBGR,
1862 NULL, /* no version */
1863 &GUID_VendorMicrosoft,
1864 32, /* bitsperpixel */
1865 3, /* channel count */
1867 WICPixelFormatNumericRepresentationUnsignedInteger,
1870 { &GUID_WICPixelFormat32bppBGRA,
1873 NULL, /* no version */
1874 &GUID_VendorMicrosoft,
1875 32, /* bitsperpixel */
1876 4, /* channel count */
1878 WICPixelFormatNumericRepresentationUnsignedInteger,
1881 { &GUID_WICPixelFormat32bppPBGRA,
1884 NULL, /* no version */
1885 &GUID_VendorMicrosoft,
1886 32, /* bitsperpixel */
1887 4, /* channel count */
1889 WICPixelFormatNumericRepresentationUnsignedInteger,
1892 { &GUID_WICPixelFormat48bppRGB,
1895 NULL, /* no version */
1896 &GUID_VendorMicrosoft,
1897 48, /* bitsperpixel */
1898 3, /* channel count */
1899 channel_masks_16bit,
1900 WICPixelFormatNumericRepresentationUnsignedInteger,
1903 { &GUID_WICPixelFormat64bppRGBA,
1906 NULL, /* no version */
1907 &GUID_VendorMicrosoft,
1908 64, /* bitsperpixel */
1909 4, /* channel count */
1910 channel_masks_16bit,
1911 WICPixelFormatNumericRepresentationUnsignedInteger,
1914 { &GUID_WICPixelFormat64bppPRGBA,
1917 NULL, /* no version */
1918 &GUID_VendorMicrosoft,
1919 64, /* bitsperpixel */
1920 4, /* channel count */
1921 channel_masks_16bit,
1922 WICPixelFormatNumericRepresentationUnsignedInteger,
1925 { &GUID_WICPixelFormat32bppCMYK,
1928 NULL, /* no version */
1929 &GUID_VendorMicrosoft,
1930 32, /* bitsperpixel */
1931 4, /* channel count */
1933 WICPixelFormatNumericRepresentationUnsignedInteger,
1936 { NULL } /* list terminator */
1939 struct regsvr_category
1941 const CLSID *clsid; /* NULL for end of list */
1944 static const struct regsvr_category category_list[] = {
1945 { &CATID_WICBitmapDecoders },
1946 { &CATID_WICBitmapEncoders },
1947 { &CATID_WICFormatConverters },
1948 { &CATID_WICMetadataReader },
1949 { &CATID_WICPixelFormats },
1953 static HRESULT register_categories(const struct regsvr_category *list)
1957 HKEY coclass_key, categories_key, instance_key;
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);
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)
1968 RegCloseKey(coclass_key);
1969 return HRESULT_FROM_WIN32(res);
1972 res = RegCreateKeyExW(categories_key, instance_keyname, 0, NULL, 0,
1973 KEY_READ | KEY_WRITE, NULL, &instance_key, NULL);
1975 for (; res == ERROR_SUCCESS && list->clsid; list++)
1977 HKEY instance_clsid_key;
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)
1984 res = RegSetValueExW(instance_clsid_key, clsid_valuename, 0, REG_SZ,
1985 (const BYTE *)buf, 78);
1986 RegCloseKey(instance_clsid_key);
1990 RegCloseKey(instance_key);
1991 RegCloseKey(categories_key);
1992 RegCloseKey(coclass_key);
1994 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
1997 static HRESULT unregister_categories(const struct regsvr_category *list)
2001 HKEY coclass_key, categories_key, instance_key;
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);
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)
2012 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
2013 RegCloseKey(coclass_key);
2014 return HRESULT_FROM_WIN32(res);
2017 res = RegOpenKeyExW(categories_key, instance_keyname, 0,
2018 KEY_READ | KEY_WRITE, &instance_key);
2020 for (; res == ERROR_SUCCESS && list->clsid; list++)
2022 StringFromGUID2(list->clsid, buf, 39);
2023 res = RegDeleteTreeW(instance_key, buf);
2026 RegCloseKey(instance_key);
2027 RegCloseKey(categories_key);
2029 StringFromGUID2(&CLSID_WICImagingCategories, buf, 39);
2030 res = RegDeleteTreeW(coclass_key, buf);
2032 RegCloseKey(coclass_key);
2034 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
2037 extern HRESULT WINAPI WIC_DllRegisterServer(void) DECLSPEC_HIDDEN;
2038 extern HRESULT WINAPI WIC_DllUnregisterServer(void) DECLSPEC_HIDDEN;
2040 HRESULT WINAPI DllRegisterServer(void)
2046 hr = WIC_DllRegisterServer();
2048 hr = register_categories(category_list);
2050 hr = register_decoders(decoder_list);
2052 hr = register_encoders(encoder_list);
2054 hr = register_converters(converter_list);
2056 hr = register_metadatareaders(metadatareader_list);
2058 hr = register_pixelformats(pixelformat_list);
2062 HRESULT WINAPI DllUnregisterServer(void)
2068 hr = WIC_DllUnregisterServer();
2070 hr = unregister_categories(category_list);
2072 hr = unregister_decoders(decoder_list);
2074 hr = unregister_encoders(encoder_list);
2076 hr = unregister_converters(converter_list);
2078 hr = unregister_metadatareaders(metadatareader_list);
2080 hr = unregister_pixelformats(pixelformat_list);