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
36 #include "wine/debug.h"
37 #include "wine/unicode.h"
39 #include "wincodecs_private.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
43 /***********************************************************************
44 * interface for self-registering
48 CLSID const *clsid; /* NULL for end of list */
49 LPCSTR name; /* can be NULL to omit */
50 LPCSTR ips; /* can be NULL to omit */
51 LPCSTR ips32; /* can be NULL to omit */
52 LPCSTR ips32_tmodel; /* can be NULL to omit */
53 LPCSTR progid; /* can be NULL to omit */
54 LPCSTR viprogid; /* can be NULL to omit */
55 LPCSTR progid_extra; /* can be NULL to omit */
58 static HRESULT register_coclasses(struct regsvr_coclass const *list);
59 static HRESULT unregister_coclasses(struct regsvr_coclass const *list);
61 struct decoder_pattern
63 DWORD length; /* 0 for end of list */
72 CLSID const *clsid; /* NULL for end of list */
79 GUID const * const *formats;
80 const struct decoder_pattern *patterns;
83 static HRESULT register_decoders(struct regsvr_decoder const *list);
84 static HRESULT unregister_decoders(struct regsvr_decoder const *list);
88 CLSID const *clsid; /* NULL for end of list */
95 GUID const * const *formats;
98 static HRESULT register_encoders(struct regsvr_encoder const *list);
99 static HRESULT unregister_encoders(struct regsvr_encoder const *list);
101 struct regsvr_converter
103 CLSID const *clsid; /* NULL for end of list */
108 GUID const * const *formats;
111 static HRESULT register_converters(struct regsvr_converter const *list);
112 static HRESULT unregister_converters(struct regsvr_converter const *list);
114 /***********************************************************************
115 * static string constants
117 static WCHAR const clsid_keyname[6] = {
118 'C', 'L', 'S', 'I', 'D', 0 };
119 static WCHAR const curver_keyname[7] = {
120 'C', 'u', 'r', 'V', 'e', 'r', 0 };
121 static WCHAR const ips_keyname[13] = {
122 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
124 static WCHAR const ips32_keyname[15] = {
125 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
127 static WCHAR const progid_keyname[7] = {
128 'P', 'r', 'o', 'g', 'I', 'D', 0 };
129 static WCHAR const viprogid_keyname[25] = {
130 'V', 'e', 'r', 's', 'i', 'o', 'n', 'I', 'n', 'd', 'e', 'p',
131 'e', 'n', 'd', 'e', 'n', 't', 'P', 'r', 'o', 'g', 'I', 'D',
133 static char const tmodel_valuename[] = "ThreadingModel";
134 static char const author_valuename[] = "Author";
135 static char const friendlyname_valuename[] = "FriendlyName";
136 static WCHAR const vendor_valuename[] = {'V','e','n','d','o','r',0};
137 static char const version_valuename[] = "Version";
138 static char const mimetypes_valuename[] = "MimeTypes";
139 static char const extensions_valuename[] = "FileExtensions";
140 static WCHAR const formats_keyname[] = {'F','o','r','m','a','t','s',0};
141 static WCHAR const patterns_keyname[] = {'P','a','t','t','e','r','n','s',0};
142 static WCHAR const instance_keyname[] = {'I','n','s','t','a','n','c','e',0};
143 static WCHAR const clsid_valuename[] = {'C','L','S','I','D',0};
144 static char const length_valuename[] = "Length";
145 static char const position_valuename[] = "Position";
146 static char const pattern_valuename[] = "Pattern";
147 static char const mask_valuename[] = "Mask";
148 static char const endofstream_valuename[] = "EndOfStream";
149 static WCHAR const pixelformats_keyname[] = {'P','i','x','e','l','F','o','r','m','a','t','s',0};
151 /***********************************************************************
152 * static helper functions
154 static LONG register_key_defvalueW(HKEY base, WCHAR const *name,
156 static LONG register_key_defvalueA(HKEY base, WCHAR const *name,
158 static LONG register_progid(WCHAR const *clsid,
159 char const *progid, char const *curver_progid,
160 char const *name, char const *extra);
162 /***********************************************************************
165 static HRESULT register_coclasses(struct regsvr_coclass const *list)
167 LONG res = ERROR_SUCCESS;
170 res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0,
171 KEY_READ | KEY_WRITE, NULL, &coclass_key, NULL);
172 if (res != ERROR_SUCCESS) goto error_return;
174 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
178 StringFromGUID2(list->clsid, buf, 39);
179 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
180 KEY_READ | KEY_WRITE, NULL, &clsid_key, NULL);
181 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
184 res = RegSetValueExA(clsid_key, NULL, 0, REG_SZ,
185 (CONST BYTE*)(list->name),
186 strlen(list->name) + 1);
187 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
191 res = register_key_defvalueA(clsid_key, ips_keyname, list->ips);
192 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
198 res = RegCreateKeyExW(clsid_key, ips32_keyname, 0, NULL, 0,
199 KEY_READ | KEY_WRITE, NULL,
201 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
203 res = RegSetValueExA(ips32_key, NULL, 0, REG_SZ,
204 (CONST BYTE*)list->ips32,
205 lstrlenA(list->ips32) + 1);
206 if (res == ERROR_SUCCESS && list->ips32_tmodel)
207 res = RegSetValueExA(ips32_key, tmodel_valuename, 0, REG_SZ,
208 (CONST BYTE*)list->ips32_tmodel,
209 strlen(list->ips32_tmodel) + 1);
210 RegCloseKey(ips32_key);
211 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
215 res = register_key_defvalueA(clsid_key, progid_keyname,
217 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
219 res = register_progid(buf, list->progid, NULL,
220 list->name, list->progid_extra);
221 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
224 if (list->viprogid) {
225 res = register_key_defvalueA(clsid_key, viprogid_keyname,
227 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
229 res = register_progid(buf, list->viprogid, list->progid,
230 list->name, list->progid_extra);
231 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
234 error_close_clsid_key:
235 RegCloseKey(clsid_key);
238 error_close_coclass_key:
239 RegCloseKey(coclass_key);
241 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
244 /***********************************************************************
245 * unregister_coclasses
247 static HRESULT unregister_coclasses(struct regsvr_coclass const *list)
249 LONG res = ERROR_SUCCESS;
252 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0,
253 KEY_READ | KEY_WRITE, &coclass_key);
254 if (res == ERROR_FILE_NOT_FOUND) return S_OK;
255 if (res != ERROR_SUCCESS) goto error_return;
257 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
260 StringFromGUID2(list->clsid, buf, 39);
261 res = RegDeleteTreeW(coclass_key, buf);
262 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
263 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
266 res = RegDeleteTreeA(HKEY_CLASSES_ROOT, list->progid);
267 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
268 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
271 if (list->viprogid) {
272 res = RegDeleteTreeA(HKEY_CLASSES_ROOT, list->viprogid);
273 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
274 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
278 error_close_coclass_key:
279 RegCloseKey(coclass_key);
281 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
284 /***********************************************************************
287 static HRESULT register_decoders(struct regsvr_decoder const *list)
289 LONG res = ERROR_SUCCESS;
295 res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0,
296 KEY_READ | KEY_WRITE, NULL, &coclass_key, NULL);
297 if (res == ERROR_SUCCESS) {
298 StringFromGUID2(&CATID_WICBitmapDecoders, buf, 39);
299 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
300 KEY_READ | KEY_WRITE, NULL, &decoders_key, NULL);
301 if (res == ERROR_SUCCESS)
303 res = RegCreateKeyExW(decoders_key, instance_keyname, 0, NULL, 0,
304 KEY_READ | KEY_WRITE, NULL, &instance_key, NULL);
305 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
307 if (res != ERROR_SUCCESS)
308 RegCloseKey(coclass_key);
310 if (res != ERROR_SUCCESS) goto error_return;
312 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
314 HKEY instance_clsid_key;
316 StringFromGUID2(list->clsid, buf, 39);
317 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
318 KEY_READ | KEY_WRITE, NULL, &clsid_key, NULL);
319 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
321 StringFromGUID2(list->clsid, buf, 39);
322 res = RegCreateKeyExW(instance_key, buf, 0, NULL, 0,
323 KEY_READ | KEY_WRITE, NULL, &instance_clsid_key, NULL);
324 if (res == ERROR_SUCCESS) {
325 res = RegSetValueExW(instance_clsid_key, clsid_valuename, 0, REG_SZ,
326 (CONST BYTE*)(buf), 78);
327 RegCloseKey(instance_clsid_key);
329 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
332 res = RegSetValueExA(clsid_key, author_valuename, 0, REG_SZ,
333 (CONST BYTE*)(list->author),
334 strlen(list->author) + 1);
335 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
338 if (list->friendlyname) {
339 res = RegSetValueExA(clsid_key, friendlyname_valuename, 0, REG_SZ,
340 (CONST BYTE*)(list->friendlyname),
341 strlen(list->friendlyname) + 1);
342 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
346 StringFromGUID2(list->vendor, buf, 39);
347 res = RegSetValueExW(clsid_key, vendor_valuename, 0, REG_SZ,
348 (CONST BYTE*)(buf), 78);
349 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
353 res = RegSetValueExA(clsid_key, version_valuename, 0, REG_SZ,
354 (CONST BYTE*)(list->version),
355 strlen(list->version) + 1);
356 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
359 if (list->mimetypes) {
360 res = RegSetValueExA(clsid_key, mimetypes_valuename, 0, REG_SZ,
361 (CONST BYTE*)(list->mimetypes),
362 strlen(list->mimetypes) + 1);
363 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
366 if (list->extensions) {
367 res = RegSetValueExA(clsid_key, extensions_valuename, 0, REG_SZ,
368 (CONST BYTE*)(list->extensions),
369 strlen(list->extensions) + 1);
370 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
375 GUID const * const *format;
377 res = RegCreateKeyExW(clsid_key, formats_keyname, 0, NULL, 0,
378 KEY_READ | KEY_WRITE, NULL, &formats_key, NULL);
379 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
380 for (format=list->formats; *format; ++format)
383 StringFromGUID2(*format, buf, 39);
384 res = RegCreateKeyExW(formats_key, buf, 0, NULL, 0,
385 KEY_READ | KEY_WRITE, NULL, &format_key, NULL);
386 if (res != ERROR_SUCCESS) break;
387 RegCloseKey(format_key);
389 RegCloseKey(formats_key);
390 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
393 if (list->patterns) {
397 res = RegCreateKeyExW(clsid_key, patterns_keyname, 0, NULL, 0,
398 KEY_READ | KEY_WRITE, NULL, &patterns_key, NULL);
399 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
400 for (i=0; list->patterns[i].length; i++)
403 static const WCHAR int_format[] = {'%','i',0};
404 snprintfW(buf, 39, int_format, i);
405 res = RegCreateKeyExW(patterns_key, buf, 0, NULL, 0,
406 KEY_READ | KEY_WRITE, NULL, &pattern_key, NULL);
407 if (res != ERROR_SUCCESS) break;
408 res = RegSetValueExA(pattern_key, length_valuename, 0, REG_DWORD,
409 (CONST BYTE*)(&list->patterns[i].length), 4);
410 if (res == ERROR_SUCCESS)
411 res = RegSetValueExA(pattern_key, position_valuename, 0, REG_DWORD,
412 (CONST BYTE*)(&list->patterns[i].position), 4);
413 if (res == ERROR_SUCCESS)
414 res = RegSetValueExA(pattern_key, pattern_valuename, 0, REG_BINARY,
415 list->patterns[i].pattern,
416 list->patterns[i].length);
417 if (res == ERROR_SUCCESS)
418 res = RegSetValueExA(pattern_key, mask_valuename, 0, REG_BINARY,
419 list->patterns[i].mask,
420 list->patterns[i].length);
421 if (res == ERROR_SUCCESS)
422 res = RegSetValueExA(pattern_key, endofstream_valuename, 0, REG_DWORD,
423 (CONST BYTE*)&(list->patterns[i].endofstream), 4);
424 RegCloseKey(pattern_key);
426 RegCloseKey(patterns_key);
427 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
430 error_close_clsid_key:
431 RegCloseKey(clsid_key);
434 error_close_coclass_key:
435 RegCloseKey(instance_key);
436 RegCloseKey(decoders_key);
437 RegCloseKey(coclass_key);
439 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
442 /***********************************************************************
443 * unregister_decoders
445 static HRESULT unregister_decoders(struct regsvr_decoder const *list)
447 LONG res = ERROR_SUCCESS;
453 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0,
454 KEY_READ | KEY_WRITE, &coclass_key);
455 if (res == ERROR_FILE_NOT_FOUND) return S_OK;
457 if (res == ERROR_SUCCESS) {
458 StringFromGUID2(&CATID_WICBitmapDecoders, buf, 39);
459 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
460 KEY_READ | KEY_WRITE, NULL, &decoders_key, NULL);
461 if (res == ERROR_SUCCESS)
463 res = RegCreateKeyExW(decoders_key, instance_keyname, 0, NULL, 0,
464 KEY_READ | KEY_WRITE, NULL, &instance_key, NULL);
465 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
467 if (res != ERROR_SUCCESS)
468 RegCloseKey(coclass_key);
470 if (res != ERROR_SUCCESS) goto error_return;
472 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
473 StringFromGUID2(list->clsid, buf, 39);
475 res = RegDeleteTreeW(coclass_key, buf);
476 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
477 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
479 res = RegDeleteTreeW(instance_key, buf);
480 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
481 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
484 error_close_coclass_key:
485 RegCloseKey(instance_key);
486 RegCloseKey(decoders_key);
487 RegCloseKey(coclass_key);
489 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
492 /***********************************************************************
495 static HRESULT register_encoders(struct regsvr_encoder const *list)
497 LONG res = ERROR_SUCCESS;
503 res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0,
504 KEY_READ | KEY_WRITE, NULL, &coclass_key, NULL);
505 if (res == ERROR_SUCCESS) {
506 StringFromGUID2(&CATID_WICBitmapEncoders, buf, 39);
507 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
508 KEY_READ | KEY_WRITE, NULL, &encoders_key, NULL);
509 if (res == ERROR_SUCCESS)
511 res = RegCreateKeyExW(encoders_key, instance_keyname, 0, NULL, 0,
512 KEY_READ | KEY_WRITE, NULL, &instance_key, NULL);
513 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
515 if (res != ERROR_SUCCESS)
516 RegCloseKey(coclass_key);
518 if (res != ERROR_SUCCESS) goto error_return;
520 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
522 HKEY instance_clsid_key;
524 StringFromGUID2(list->clsid, buf, 39);
525 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
526 KEY_READ | KEY_WRITE, NULL, &clsid_key, NULL);
527 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
529 StringFromGUID2(list->clsid, buf, 39);
530 res = RegCreateKeyExW(instance_key, buf, 0, NULL, 0,
531 KEY_READ | KEY_WRITE, NULL, &instance_clsid_key, NULL);
532 if (res == ERROR_SUCCESS) {
533 res = RegSetValueExW(instance_clsid_key, clsid_valuename, 0, REG_SZ,
534 (CONST BYTE*)(buf), 78);
535 RegCloseKey(instance_clsid_key);
537 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
540 res = RegSetValueExA(clsid_key, author_valuename, 0, REG_SZ,
541 (CONST BYTE*)(list->author),
542 strlen(list->author) + 1);
543 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
546 if (list->friendlyname) {
547 res = RegSetValueExA(clsid_key, friendlyname_valuename, 0, REG_SZ,
548 (CONST BYTE*)(list->friendlyname),
549 strlen(list->friendlyname) + 1);
550 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
554 StringFromGUID2(list->vendor, buf, 39);
555 res = RegSetValueExW(clsid_key, vendor_valuename, 0, REG_SZ,
556 (CONST BYTE*)(buf), 78);
557 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
561 res = RegSetValueExA(clsid_key, version_valuename, 0, REG_SZ,
562 (CONST BYTE*)(list->version),
563 strlen(list->version) + 1);
564 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
567 if (list->mimetypes) {
568 res = RegSetValueExA(clsid_key, mimetypes_valuename, 0, REG_SZ,
569 (CONST BYTE*)(list->mimetypes),
570 strlen(list->mimetypes) + 1);
571 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
574 if (list->extensions) {
575 res = RegSetValueExA(clsid_key, extensions_valuename, 0, REG_SZ,
576 (CONST BYTE*)(list->extensions),
577 strlen(list->extensions) + 1);
578 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
583 GUID const * const *format;
585 res = RegCreateKeyExW(clsid_key, formats_keyname, 0, NULL, 0,
586 KEY_READ | KEY_WRITE, NULL, &formats_key, NULL);
587 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
588 for (format=list->formats; *format; ++format)
591 StringFromGUID2(*format, buf, 39);
592 res = RegCreateKeyExW(formats_key, buf, 0, NULL, 0,
593 KEY_READ | KEY_WRITE, NULL, &format_key, NULL);
594 if (res != ERROR_SUCCESS) break;
595 RegCloseKey(format_key);
597 RegCloseKey(formats_key);
598 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
601 error_close_clsid_key:
602 RegCloseKey(clsid_key);
605 error_close_coclass_key:
606 RegCloseKey(instance_key);
607 RegCloseKey(encoders_key);
608 RegCloseKey(coclass_key);
610 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
613 /***********************************************************************
614 * unregister_encoders
616 static HRESULT unregister_encoders(struct regsvr_encoder const *list)
618 LONG res = ERROR_SUCCESS;
624 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0,
625 KEY_READ | KEY_WRITE, &coclass_key);
626 if (res == ERROR_FILE_NOT_FOUND) return S_OK;
628 if (res == ERROR_SUCCESS) {
629 StringFromGUID2(&CATID_WICBitmapEncoders, buf, 39);
630 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
631 KEY_READ | KEY_WRITE, NULL, &encoders_key, NULL);
632 if (res == ERROR_SUCCESS)
634 res = RegCreateKeyExW(encoders_key, instance_keyname, 0, NULL, 0,
635 KEY_READ | KEY_WRITE, NULL, &instance_key, NULL);
636 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
638 if (res != ERROR_SUCCESS)
639 RegCloseKey(coclass_key);
641 if (res != ERROR_SUCCESS) goto error_return;
643 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
644 StringFromGUID2(list->clsid, buf, 39);
646 res = RegDeleteTreeW(coclass_key, buf);
647 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
648 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
650 res = RegDeleteTreeW(instance_key, buf);
651 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
652 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
655 error_close_coclass_key:
656 RegCloseKey(instance_key);
657 RegCloseKey(encoders_key);
658 RegCloseKey(coclass_key);
660 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
663 /***********************************************************************
664 * register_converters
666 static HRESULT register_converters(struct regsvr_converter const *list)
668 LONG res = ERROR_SUCCESS;
674 res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0,
675 KEY_READ | KEY_WRITE, NULL, &coclass_key, NULL);
676 if (res == ERROR_SUCCESS) {
677 StringFromGUID2(&CATID_WICFormatConverters, buf, 39);
678 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
679 KEY_READ | KEY_WRITE, NULL, &converters_key, NULL);
680 if (res == ERROR_SUCCESS)
682 res = RegCreateKeyExW(converters_key, instance_keyname, 0, NULL, 0,
683 KEY_READ | KEY_WRITE, NULL, &instance_key, NULL);
684 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
686 if (res != ERROR_SUCCESS)
687 RegCloseKey(coclass_key);
689 if (res != ERROR_SUCCESS) goto error_return;
691 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
693 HKEY instance_clsid_key;
695 StringFromGUID2(list->clsid, buf, 39);
696 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
697 KEY_READ | KEY_WRITE, NULL, &clsid_key, NULL);
698 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
700 StringFromGUID2(list->clsid, buf, 39);
701 res = RegCreateKeyExW(instance_key, buf, 0, NULL, 0,
702 KEY_READ | KEY_WRITE, NULL, &instance_clsid_key, NULL);
703 if (res == ERROR_SUCCESS) {
704 res = RegSetValueExW(instance_clsid_key, clsid_valuename, 0, REG_SZ,
705 (CONST BYTE*)(buf), 78);
706 RegCloseKey(instance_clsid_key);
708 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
711 res = RegSetValueExA(clsid_key, author_valuename, 0, REG_SZ,
712 (CONST BYTE*)(list->author),
713 strlen(list->author) + 1);
714 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
717 if (list->friendlyname) {
718 res = RegSetValueExA(clsid_key, friendlyname_valuename, 0, REG_SZ,
719 (CONST BYTE*)(list->friendlyname),
720 strlen(list->friendlyname) + 1);
721 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
725 StringFromGUID2(list->vendor, buf, 39);
726 res = RegSetValueExW(clsid_key, vendor_valuename, 0, REG_SZ,
727 (CONST BYTE*)(buf), 78);
728 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
732 res = RegSetValueExA(clsid_key, version_valuename, 0, REG_SZ,
733 (CONST BYTE*)(list->version),
734 strlen(list->version) + 1);
735 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
740 GUID const * const *format;
742 res = RegCreateKeyExW(clsid_key, pixelformats_keyname, 0, NULL, 0,
743 KEY_READ | KEY_WRITE, NULL, &formats_key, NULL);
744 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
745 for (format=list->formats; *format; ++format)
748 StringFromGUID2(*format, buf, 39);
749 res = RegCreateKeyExW(formats_key, buf, 0, NULL, 0,
750 KEY_READ | KEY_WRITE, NULL, &format_key, NULL);
751 if (res != ERROR_SUCCESS) break;
752 RegCloseKey(format_key);
754 RegCloseKey(formats_key);
755 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
758 error_close_clsid_key:
759 RegCloseKey(clsid_key);
762 error_close_coclass_key:
763 RegCloseKey(instance_key);
764 RegCloseKey(converters_key);
765 RegCloseKey(coclass_key);
767 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
770 /***********************************************************************
771 * unregister_converters
773 static HRESULT unregister_converters(struct regsvr_converter const *list)
775 LONG res = ERROR_SUCCESS;
781 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0,
782 KEY_READ | KEY_WRITE, &coclass_key);
783 if (res == ERROR_FILE_NOT_FOUND) return S_OK;
785 if (res == ERROR_SUCCESS) {
786 StringFromGUID2(&CATID_WICFormatConverters, buf, 39);
787 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
788 KEY_READ | KEY_WRITE, NULL, &converters_key, NULL);
789 if (res == ERROR_SUCCESS)
791 res = RegCreateKeyExW(converters_key, instance_keyname, 0, NULL, 0,
792 KEY_READ | KEY_WRITE, NULL, &instance_key, NULL);
793 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
795 if (res != ERROR_SUCCESS)
796 RegCloseKey(coclass_key);
798 if (res != ERROR_SUCCESS) goto error_return;
800 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
801 StringFromGUID2(list->clsid, buf, 39);
803 res = RegDeleteTreeW(coclass_key, buf);
804 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
805 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
807 res = RegDeleteTreeW(instance_key, buf);
808 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
809 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
812 error_close_coclass_key:
813 RegCloseKey(instance_key);
814 RegCloseKey(converters_key);
815 RegCloseKey(coclass_key);
817 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
820 /***********************************************************************
821 * register_key_defvalueW
823 static LONG register_key_defvalueW(
831 res = RegCreateKeyExW(base, name, 0, NULL, 0,
832 KEY_READ | KEY_WRITE, NULL, &key, NULL);
833 if (res != ERROR_SUCCESS) return res;
834 res = RegSetValueExW(key, NULL, 0, REG_SZ, (CONST BYTE*)value,
835 (lstrlenW(value) + 1) * sizeof(WCHAR));
840 /***********************************************************************
841 * register_key_defvalueA
843 static LONG register_key_defvalueA(
851 res = RegCreateKeyExW(base, name, 0, NULL, 0,
852 KEY_READ | KEY_WRITE, NULL, &key, NULL);
853 if (res != ERROR_SUCCESS) return res;
854 res = RegSetValueExA(key, NULL, 0, REG_SZ, (CONST BYTE*)value,
855 lstrlenA(value) + 1);
860 /***********************************************************************
863 static LONG register_progid(
866 char const *curver_progid,
873 res = RegCreateKeyExA(HKEY_CLASSES_ROOT, progid, 0,
874 NULL, 0, KEY_READ | KEY_WRITE, NULL,
876 if (res != ERROR_SUCCESS) return res;
879 res = RegSetValueExA(progid_key, NULL, 0, REG_SZ,
880 (CONST BYTE*)name, strlen(name) + 1);
881 if (res != ERROR_SUCCESS) goto error_close_progid_key;
885 res = register_key_defvalueW(progid_key, clsid_keyname, clsid);
886 if (res != ERROR_SUCCESS) goto error_close_progid_key;
890 res = register_key_defvalueA(progid_key, curver_keyname,
892 if (res != ERROR_SUCCESS) goto error_close_progid_key;
898 res = RegCreateKeyExA(progid_key, extra, 0,
899 NULL, 0, KEY_READ | KEY_WRITE, NULL,
901 if (res == ERROR_SUCCESS)
902 RegCloseKey(extra_key);
905 error_close_progid_key:
906 RegCloseKey(progid_key);
910 /***********************************************************************
913 static struct regsvr_coclass const coclass_list[] = {
914 { &CLSID_WICImagingFactory,
915 "WIC Imaging Factory",
920 { &CLSID_WICBmpDecoder,
926 { &CLSID_WICPngDecoder,
932 { &CLSID_WICPngEncoder,
938 { &CLSID_WICBmpEncoder,
944 { &CLSID_WICGifDecoder,
950 { &CLSID_WICIcoDecoder,
956 { &CLSID_WICJpegDecoder,
962 { &CLSID_WICTiffDecoder,
969 &CLSID_WICIcnsEncoder,
975 { &CLSID_WICDefaultFormatConverter,
976 "WIC Default Format Converter",
981 { NULL } /* list terminator */
984 /***********************************************************************
987 static const BYTE mask_all[] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
989 static const BYTE bmp_magic[] = {0x42,0x4d};
991 static GUID const * const bmp_formats[] = {
992 &GUID_WICPixelFormat1bppIndexed,
993 &GUID_WICPixelFormat2bppIndexed,
994 &GUID_WICPixelFormat4bppIndexed,
995 &GUID_WICPixelFormat8bppIndexed,
996 &GUID_WICPixelFormat16bppBGR555,
997 &GUID_WICPixelFormat16bppBGR565,
998 &GUID_WICPixelFormat24bppBGR,
999 &GUID_WICPixelFormat32bppBGR,
1000 &GUID_WICPixelFormat32bppBGRA,
1004 static struct decoder_pattern const bmp_patterns[] = {
1005 {2,0,bmp_magic,mask_all,0},
1009 static const BYTE gif87a_magic[6] = "GIF87a";
1010 static const BYTE gif89a_magic[6] = "GIF89a";
1012 static GUID const * const gif_formats[] = {
1013 &GUID_WICPixelFormat8bppIndexed,
1017 static struct decoder_pattern const gif_patterns[] = {
1018 {6,0,gif87a_magic,mask_all,0},
1019 {6,0,gif89a_magic,mask_all,0},
1023 static const BYTE ico_magic[] = {00,00,01,00};
1025 static GUID const * const ico_formats[] = {
1026 &GUID_WICPixelFormat32bppBGRA,
1030 static struct decoder_pattern const ico_patterns[] = {
1031 {4,0,ico_magic,mask_all,0},
1035 static const BYTE jpeg_magic[] = {0xff, 0xd8, 0xff, 0xe0};
1037 static GUID const * const jpeg_formats[] = {
1038 &GUID_WICPixelFormat24bppBGR,
1039 &GUID_WICPixelFormat32bppCMYK,
1040 &GUID_WICPixelFormat8bppGray,
1044 static struct decoder_pattern const jpeg_patterns[] = {
1045 {4,0,jpeg_magic,mask_all,0},
1049 static const BYTE png_magic[] = {137,80,78,71,13,10,26,10};
1051 static GUID const * const png_formats[] = {
1052 &GUID_WICPixelFormatBlackWhite,
1053 &GUID_WICPixelFormat2bppGray,
1054 &GUID_WICPixelFormat4bppGray,
1055 &GUID_WICPixelFormat8bppGray,
1056 &GUID_WICPixelFormat16bppGray,
1057 &GUID_WICPixelFormat32bppBGRA,
1058 &GUID_WICPixelFormat64bppRGBA,
1059 &GUID_WICPixelFormat1bppIndexed,
1060 &GUID_WICPixelFormat2bppIndexed,
1061 &GUID_WICPixelFormat4bppIndexed,
1062 &GUID_WICPixelFormat8bppIndexed,
1063 &GUID_WICPixelFormat24bppBGR,
1064 &GUID_WICPixelFormat48bppRGB,
1068 static struct decoder_pattern const png_patterns[] = {
1069 {8,0,png_magic,mask_all,0},
1073 static const BYTE tiff_magic_le[] = {0x49,0x49,42,0};
1074 static const BYTE tiff_magic_be[] = {0x4d,0x4d,0,42};
1076 static GUID const * const tiff_formats[] = {
1077 &GUID_WICPixelFormatBlackWhite,
1078 &GUID_WICPixelFormat4bppGray,
1079 &GUID_WICPixelFormat8bppGray,
1080 &GUID_WICPixelFormat4bppIndexed,
1081 &GUID_WICPixelFormat8bppIndexed,
1082 &GUID_WICPixelFormat32bppBGR,
1083 &GUID_WICPixelFormat32bppBGRA,
1084 &GUID_WICPixelFormat32bppPBGRA,
1085 &GUID_WICPixelFormat48bppRGB,
1089 static struct decoder_pattern const tiff_patterns[] = {
1090 {4,0,tiff_magic_le,mask_all,0},
1091 {4,0,tiff_magic_be,mask_all,0},
1095 static struct regsvr_decoder const decoder_list[] = {
1096 { &CLSID_WICBmpDecoder,
1100 &GUID_VendorMicrosoft,
1106 { &CLSID_WICGifDecoder,
1110 &GUID_VendorMicrosoft,
1116 { &CLSID_WICIcoDecoder,
1120 &GUID_VendorMicrosoft,
1121 "image/vnd.microsoft.icon",
1126 { &CLSID_WICJpegDecoder,
1130 &GUID_VendorMicrosoft,
1136 { &CLSID_WICPngDecoder,
1140 &GUID_VendorMicrosoft,
1146 { &CLSID_WICTiffDecoder,
1150 &GUID_VendorMicrosoft,
1156 { NULL } /* list terminator */
1159 static GUID const * const bmp_encode_formats[] = {
1160 &GUID_WICPixelFormat16bppBGR555,
1161 &GUID_WICPixelFormat16bppBGR565,
1162 &GUID_WICPixelFormat24bppBGR,
1163 &GUID_WICPixelFormat32bppBGR,
1167 static GUID const * const png_encode_formats[] = {
1168 &GUID_WICPixelFormat24bppBGR,
1169 &GUID_WICPixelFormatBlackWhite,
1170 &GUID_WICPixelFormat2bppGray,
1171 &GUID_WICPixelFormat4bppGray,
1172 &GUID_WICPixelFormat8bppGray,
1173 &GUID_WICPixelFormat16bppGray,
1174 &GUID_WICPixelFormat32bppBGR,
1175 &GUID_WICPixelFormat32bppBGRA,
1176 &GUID_WICPixelFormat48bppRGB,
1177 &GUID_WICPixelFormat64bppRGBA,
1181 static GUID const * const icns_encode_formats[] = {
1182 &GUID_WICPixelFormat32bppBGRA,
1186 static struct regsvr_encoder const encoder_list[] = {
1187 { &CLSID_WICBmpEncoder,
1191 &GUID_VendorMicrosoft,
1196 { &CLSID_WICPngEncoder,
1200 &GUID_VendorMicrosoft,
1205 { &CLSID_WICIcnsEncoder,
1214 { NULL } /* list terminator */
1217 static GUID const * const converter_formats[] = {
1218 &GUID_WICPixelFormat1bppIndexed,
1219 &GUID_WICPixelFormat2bppIndexed,
1220 &GUID_WICPixelFormat4bppIndexed,
1221 &GUID_WICPixelFormat8bppIndexed,
1222 &GUID_WICPixelFormatBlackWhite,
1223 &GUID_WICPixelFormat2bppGray,
1224 &GUID_WICPixelFormat4bppGray,
1225 &GUID_WICPixelFormat8bppGray,
1226 &GUID_WICPixelFormat16bppGray,
1227 &GUID_WICPixelFormat16bppBGR555,
1228 &GUID_WICPixelFormat16bppBGR565,
1229 &GUID_WICPixelFormat24bppBGR,
1230 &GUID_WICPixelFormat32bppBGR,
1231 &GUID_WICPixelFormat32bppBGRA,
1232 &GUID_WICPixelFormat48bppRGB,
1233 &GUID_WICPixelFormat64bppRGBA,
1234 &GUID_WICPixelFormat32bppCMYK,
1238 static struct regsvr_converter const converter_list[] = {
1239 { &CLSID_WICDefaultFormatConverter,
1241 "Default Pixel Format Converter",
1243 &GUID_VendorMicrosoft,
1246 { NULL } /* list terminator */
1249 HRESULT WINAPI DllRegisterServer(void)
1255 hr = register_coclasses(coclass_list);
1257 register_decoders(decoder_list);
1259 register_encoders(encoder_list);
1261 register_converters(converter_list);
1265 HRESULT WINAPI DllUnregisterServer(void)
1271 hr = unregister_coclasses(coclass_list);
1273 unregister_decoders(decoder_list);
1275 unregister_encoders(encoder_list);
1277 unregister_converters(converter_list);