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 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs
);
41 /***********************************************************************
42 * interface for self-registering
46 CLSID
const *clsid
; /* NULL for end of list */
47 LPCSTR name
; /* can be NULL to omit */
48 LPCSTR ips
; /* can be NULL to omit */
49 LPCSTR ips32
; /* can be NULL to omit */
50 LPCSTR ips32_tmodel
; /* can be NULL to omit */
51 LPCSTR progid
; /* can be NULL to omit */
52 LPCSTR viprogid
; /* can be NULL to omit */
53 LPCSTR progid_extra
; /* can be NULL to omit */
56 static HRESULT
register_coclasses(struct regsvr_coclass
const *list
);
57 static HRESULT
unregister_coclasses(struct regsvr_coclass
const *list
);
59 struct decoder_pattern
61 DWORD length
; /* 0 for end of list */
70 CLSID
const *clsid
; /* NULL for end of list */
77 GUID
const * const *formats
;
78 const struct decoder_pattern
*patterns
;
81 static HRESULT
register_decoders(struct regsvr_decoder
const *list
);
82 static HRESULT
unregister_decoders(struct regsvr_decoder
const *list
);
84 struct regsvr_converter
86 CLSID
const *clsid
; /* NULL for end of list */
91 GUID
const * const *formats
;
94 static HRESULT
register_converters(struct regsvr_converter
const *list
);
95 static HRESULT
unregister_converters(struct regsvr_converter
const *list
);
97 /***********************************************************************
98 * static string constants
100 static WCHAR
const clsid_keyname
[6] = {
101 'C', 'L', 'S', 'I', 'D', 0 };
102 static WCHAR
const curver_keyname
[7] = {
103 'C', 'u', 'r', 'V', 'e', 'r', 0 };
104 static WCHAR
const ips_keyname
[13] = {
105 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
107 static WCHAR
const ips32_keyname
[15] = {
108 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
110 static WCHAR
const progid_keyname
[7] = {
111 'P', 'r', 'o', 'g', 'I', 'D', 0 };
112 static WCHAR
const viprogid_keyname
[25] = {
113 'V', 'e', 'r', 's', 'i', 'o', 'n', 'I', 'n', 'd', 'e', 'p',
114 'e', 'n', 'd', 'e', 'n', 't', 'P', 'r', 'o', 'g', 'I', 'D',
116 static char const tmodel_valuename
[] = "ThreadingModel";
117 static char const author_valuename
[] = "Author";
118 static char const friendlyname_valuename
[] = "FriendlyName";
119 static WCHAR
const vendor_valuename
[] = {'V','e','n','d','o','r',0};
120 static char const version_valuename
[] = "Version";
121 static char const mimetypes_valuename
[] = "MimeTypes";
122 static char const extensions_valuename
[] = "FileExtensions";
123 static WCHAR
const formats_keyname
[] = {'F','o','r','m','a','t','s',0};
124 static WCHAR
const patterns_keyname
[] = {'P','a','t','t','e','r','n','s',0};
125 static WCHAR
const instance_keyname
[] = {'I','n','s','t','a','n','c','e',0};
126 static WCHAR
const clsid_valuename
[] = {'C','L','S','I','D',0};
127 static char const length_valuename
[] = "Length";
128 static char const position_valuename
[] = "Position";
129 static char const pattern_valuename
[] = "Pattern";
130 static char const mask_valuename
[] = "Mask";
131 static char const endofstream_valuename
[] = "EndOfStream";
132 static WCHAR
const pixelformats_keyname
[] = {'P','i','x','e','l','F','o','r','m','a','t','s',0};
134 /***********************************************************************
135 * static helper functions
137 static LONG
register_key_defvalueW(HKEY base
, WCHAR
const *name
,
139 static LONG
register_key_defvalueA(HKEY base
, WCHAR
const *name
,
141 static LONG
register_progid(WCHAR
const *clsid
,
142 char const *progid
, char const *curver_progid
,
143 char const *name
, char const *extra
);
145 /***********************************************************************
148 static HRESULT
register_coclasses(struct regsvr_coclass
const *list
)
150 LONG res
= ERROR_SUCCESS
;
153 res
= RegCreateKeyExW(HKEY_CLASSES_ROOT
, clsid_keyname
, 0, NULL
, 0,
154 KEY_READ
| KEY_WRITE
, NULL
, &coclass_key
, NULL
);
155 if (res
!= ERROR_SUCCESS
) goto error_return
;
157 for (; res
== ERROR_SUCCESS
&& list
->clsid
; ++list
) {
161 StringFromGUID2(list
->clsid
, buf
, 39);
162 res
= RegCreateKeyExW(coclass_key
, buf
, 0, NULL
, 0,
163 KEY_READ
| KEY_WRITE
, NULL
, &clsid_key
, NULL
);
164 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
167 res
= RegSetValueExA(clsid_key
, NULL
, 0, REG_SZ
,
168 (CONST BYTE
*)(list
->name
),
169 strlen(list
->name
) + 1);
170 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
174 res
= register_key_defvalueA(clsid_key
, ips_keyname
, list
->ips
);
175 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
181 res
= RegCreateKeyExW(clsid_key
, ips32_keyname
, 0, NULL
, 0,
182 KEY_READ
| KEY_WRITE
, NULL
,
184 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
186 res
= RegSetValueExA(ips32_key
, NULL
, 0, REG_SZ
,
187 (CONST BYTE
*)list
->ips32
,
188 lstrlenA(list
->ips32
) + 1);
189 if (res
== ERROR_SUCCESS
&& list
->ips32_tmodel
)
190 res
= RegSetValueExA(ips32_key
, tmodel_valuename
, 0, REG_SZ
,
191 (CONST BYTE
*)list
->ips32_tmodel
,
192 strlen(list
->ips32_tmodel
) + 1);
193 RegCloseKey(ips32_key
);
194 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
198 res
= register_key_defvalueA(clsid_key
, progid_keyname
,
200 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
202 res
= register_progid(buf
, list
->progid
, NULL
,
203 list
->name
, list
->progid_extra
);
204 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
207 if (list
->viprogid
) {
208 res
= register_key_defvalueA(clsid_key
, viprogid_keyname
,
210 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
212 res
= register_progid(buf
, list
->viprogid
, list
->progid
,
213 list
->name
, list
->progid_extra
);
214 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
217 error_close_clsid_key
:
218 RegCloseKey(clsid_key
);
221 error_close_coclass_key
:
222 RegCloseKey(coclass_key
);
224 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
227 /***********************************************************************
228 * unregister_coclasses
230 static HRESULT
unregister_coclasses(struct regsvr_coclass
const *list
)
232 LONG res
= ERROR_SUCCESS
;
235 res
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, clsid_keyname
, 0,
236 KEY_READ
| KEY_WRITE
, &coclass_key
);
237 if (res
== ERROR_FILE_NOT_FOUND
) return S_OK
;
238 if (res
!= ERROR_SUCCESS
) goto error_return
;
240 for (; res
== ERROR_SUCCESS
&& list
->clsid
; ++list
) {
243 StringFromGUID2(list
->clsid
, buf
, 39);
244 res
= RegDeleteTreeW(coclass_key
, buf
);
245 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
246 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
249 res
= RegDeleteTreeA(HKEY_CLASSES_ROOT
, list
->progid
);
250 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
251 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
254 if (list
->viprogid
) {
255 res
= RegDeleteTreeA(HKEY_CLASSES_ROOT
, list
->viprogid
);
256 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
257 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
261 error_close_coclass_key
:
262 RegCloseKey(coclass_key
);
264 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
267 /***********************************************************************
270 static HRESULT
register_decoders(struct regsvr_decoder
const *list
)
272 LONG res
= ERROR_SUCCESS
;
278 res
= RegCreateKeyExW(HKEY_CLASSES_ROOT
, clsid_keyname
, 0, NULL
, 0,
279 KEY_READ
| KEY_WRITE
, NULL
, &coclass_key
, NULL
);
280 if (res
== ERROR_SUCCESS
) {
281 StringFromGUID2(&CATID_WICBitmapDecoders
, buf
, 39);
282 res
= RegCreateKeyExW(coclass_key
, buf
, 0, NULL
, 0,
283 KEY_READ
| KEY_WRITE
, NULL
, &decoders_key
, NULL
);
284 if (res
== ERROR_SUCCESS
)
286 res
= RegCreateKeyExW(decoders_key
, instance_keyname
, 0, NULL
, 0,
287 KEY_READ
| KEY_WRITE
, NULL
, &instance_key
, NULL
);
288 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
290 if (res
!= ERROR_SUCCESS
)
291 RegCloseKey(coclass_key
);
293 if (res
!= ERROR_SUCCESS
) goto error_return
;
295 for (; res
== ERROR_SUCCESS
&& list
->clsid
; ++list
) {
297 HKEY instance_clsid_key
;
299 StringFromGUID2(list
->clsid
, buf
, 39);
300 res
= RegCreateKeyExW(coclass_key
, buf
, 0, NULL
, 0,
301 KEY_READ
| KEY_WRITE
, NULL
, &clsid_key
, NULL
);
302 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
304 StringFromGUID2(list
->clsid
, buf
, 39);
305 res
= RegCreateKeyExW(instance_key
, buf
, 0, NULL
, 0,
306 KEY_READ
| KEY_WRITE
, NULL
, &instance_clsid_key
, NULL
);
307 if (res
== ERROR_SUCCESS
) {
308 res
= RegSetValueExW(instance_clsid_key
, clsid_valuename
, 0, REG_SZ
,
309 (CONST BYTE
*)(buf
), 78);
310 RegCloseKey(instance_clsid_key
);
312 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
315 res
= RegSetValueExA(clsid_key
, author_valuename
, 0, REG_SZ
,
316 (CONST BYTE
*)(list
->author
),
317 strlen(list
->author
) + 1);
318 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
321 if (list
->friendlyname
) {
322 res
= RegSetValueExA(clsid_key
, friendlyname_valuename
, 0, REG_SZ
,
323 (CONST BYTE
*)(list
->friendlyname
),
324 strlen(list
->friendlyname
) + 1);
325 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
329 StringFromGUID2(list
->vendor
, buf
, 39);
330 res
= RegSetValueExW(clsid_key
, vendor_valuename
, 0, REG_SZ
,
331 (CONST BYTE
*)(buf
), 78);
332 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
336 res
= RegSetValueExA(clsid_key
, version_valuename
, 0, REG_SZ
,
337 (CONST BYTE
*)(list
->version
),
338 strlen(list
->version
) + 1);
339 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
342 if (list
->mimetypes
) {
343 res
= RegSetValueExA(clsid_key
, mimetypes_valuename
, 0, REG_SZ
,
344 (CONST BYTE
*)(list
->mimetypes
),
345 strlen(list
->mimetypes
) + 1);
346 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
349 if (list
->extensions
) {
350 res
= RegSetValueExA(clsid_key
, extensions_valuename
, 0, REG_SZ
,
351 (CONST BYTE
*)(list
->extensions
),
352 strlen(list
->extensions
) + 1);
353 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
358 GUID
const * const *format
;
360 res
= RegCreateKeyExW(clsid_key
, formats_keyname
, 0, NULL
, 0,
361 KEY_READ
| KEY_WRITE
, NULL
, &formats_key
, NULL
);
362 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
363 for (format
=list
->formats
; *format
; ++format
)
366 StringFromGUID2(*format
, buf
, 39);
367 res
= RegCreateKeyExW(formats_key
, buf
, 0, NULL
, 0,
368 KEY_READ
| KEY_WRITE
, NULL
, &format_key
, NULL
);
369 if (res
!= ERROR_SUCCESS
) break;
370 RegCloseKey(format_key
);
372 RegCloseKey(formats_key
);
373 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
376 if (list
->patterns
) {
380 res
= RegCreateKeyExW(clsid_key
, patterns_keyname
, 0, NULL
, 0,
381 KEY_READ
| KEY_WRITE
, NULL
, &patterns_key
, NULL
);
382 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
383 for (i
=0; list
->patterns
[i
].length
; i
++)
386 static const WCHAR int_format
[] = {'%','i',0};
387 snprintfW(buf
, 39, int_format
, i
);
388 res
= RegCreateKeyExW(patterns_key
, buf
, 0, NULL
, 0,
389 KEY_READ
| KEY_WRITE
, NULL
, &pattern_key
, NULL
);
390 if (res
!= ERROR_SUCCESS
) break;
391 res
= RegSetValueExA(pattern_key
, length_valuename
, 0, REG_DWORD
,
392 (CONST BYTE
*)(&list
->patterns
[i
].length
), 4);
393 if (res
== ERROR_SUCCESS
)
394 res
= RegSetValueExA(pattern_key
, position_valuename
, 0, REG_DWORD
,
395 (CONST BYTE
*)(&list
->patterns
[i
].position
), 4);
396 if (res
== ERROR_SUCCESS
)
397 res
= RegSetValueExA(pattern_key
, pattern_valuename
, 0, REG_BINARY
,
398 list
->patterns
[i
].pattern
,
399 list
->patterns
[i
].length
);
400 if (res
== ERROR_SUCCESS
)
401 res
= RegSetValueExA(pattern_key
, mask_valuename
, 0, REG_BINARY
,
402 list
->patterns
[i
].mask
,
403 list
->patterns
[i
].length
);
404 if (res
== ERROR_SUCCESS
)
405 res
= RegSetValueExA(pattern_key
, endofstream_valuename
, 0, REG_DWORD
,
406 (CONST BYTE
*)&(list
->patterns
[i
].endofstream
), 4);
407 RegCloseKey(pattern_key
);
409 RegCloseKey(patterns_key
);
410 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
413 error_close_clsid_key
:
414 RegCloseKey(clsid_key
);
417 error_close_coclass_key
:
418 RegCloseKey(instance_key
);
419 RegCloseKey(decoders_key
);
420 RegCloseKey(coclass_key
);
422 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
425 /***********************************************************************
426 * unregister_decoders
428 static HRESULT
unregister_decoders(struct regsvr_decoder
const *list
)
430 LONG res
= ERROR_SUCCESS
;
436 res
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, clsid_keyname
, 0,
437 KEY_READ
| KEY_WRITE
, &coclass_key
);
438 if (res
== ERROR_FILE_NOT_FOUND
) return S_OK
;
440 if (res
== ERROR_SUCCESS
) {
441 StringFromGUID2(&CATID_WICBitmapDecoders
, buf
, 39);
442 res
= RegCreateKeyExW(coclass_key
, buf
, 0, NULL
, 0,
443 KEY_READ
| KEY_WRITE
, NULL
, &decoders_key
, NULL
);
444 if (res
== ERROR_SUCCESS
)
446 res
= RegCreateKeyExW(decoders_key
, instance_keyname
, 0, NULL
, 0,
447 KEY_READ
| KEY_WRITE
, NULL
, &instance_key
, NULL
);
448 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
450 if (res
!= ERROR_SUCCESS
)
451 RegCloseKey(coclass_key
);
453 if (res
!= ERROR_SUCCESS
) goto error_return
;
455 for (; res
== ERROR_SUCCESS
&& list
->clsid
; ++list
) {
456 StringFromGUID2(list
->clsid
, buf
, 39);
458 res
= RegDeleteTreeW(coclass_key
, buf
);
459 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
460 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
462 res
= RegDeleteTreeW(instance_key
, buf
);
463 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
464 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
467 error_close_coclass_key
:
468 RegCloseKey(instance_key
);
469 RegCloseKey(decoders_key
);
470 RegCloseKey(coclass_key
);
472 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
475 /***********************************************************************
476 * register_converters
478 static HRESULT
register_converters(struct regsvr_converter
const *list
)
480 LONG res
= ERROR_SUCCESS
;
486 res
= RegCreateKeyExW(HKEY_CLASSES_ROOT
, clsid_keyname
, 0, NULL
, 0,
487 KEY_READ
| KEY_WRITE
, NULL
, &coclass_key
, NULL
);
488 if (res
== ERROR_SUCCESS
) {
489 StringFromGUID2(&CATID_WICFormatConverters
, buf
, 39);
490 res
= RegCreateKeyExW(coclass_key
, buf
, 0, NULL
, 0,
491 KEY_READ
| KEY_WRITE
, NULL
, &converters_key
, NULL
);
492 if (res
== ERROR_SUCCESS
)
494 res
= RegCreateKeyExW(converters_key
, instance_keyname
, 0, NULL
, 0,
495 KEY_READ
| KEY_WRITE
, NULL
, &instance_key
, NULL
);
496 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
498 if (res
!= ERROR_SUCCESS
)
499 RegCloseKey(coclass_key
);
501 if (res
!= ERROR_SUCCESS
) goto error_return
;
503 for (; res
== ERROR_SUCCESS
&& list
->clsid
; ++list
) {
505 HKEY instance_clsid_key
;
507 StringFromGUID2(list
->clsid
, buf
, 39);
508 res
= RegCreateKeyExW(coclass_key
, buf
, 0, NULL
, 0,
509 KEY_READ
| KEY_WRITE
, NULL
, &clsid_key
, NULL
);
510 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
512 StringFromGUID2(list
->clsid
, buf
, 39);
513 res
= RegCreateKeyExW(instance_key
, buf
, 0, NULL
, 0,
514 KEY_READ
| KEY_WRITE
, NULL
, &instance_clsid_key
, NULL
);
515 if (res
== ERROR_SUCCESS
) {
516 res
= RegSetValueExW(instance_clsid_key
, clsid_valuename
, 0, REG_SZ
,
517 (CONST BYTE
*)(buf
), 78);
518 RegCloseKey(instance_clsid_key
);
520 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
523 res
= RegSetValueExA(clsid_key
, author_valuename
, 0, REG_SZ
,
524 (CONST BYTE
*)(list
->author
),
525 strlen(list
->author
) + 1);
526 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
529 if (list
->friendlyname
) {
530 res
= RegSetValueExA(clsid_key
, friendlyname_valuename
, 0, REG_SZ
,
531 (CONST BYTE
*)(list
->friendlyname
),
532 strlen(list
->friendlyname
) + 1);
533 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
537 StringFromGUID2(list
->vendor
, buf
, 39);
538 res
= RegSetValueExW(clsid_key
, vendor_valuename
, 0, REG_SZ
,
539 (CONST BYTE
*)(buf
), 78);
540 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
544 res
= RegSetValueExA(clsid_key
, version_valuename
, 0, REG_SZ
,
545 (CONST BYTE
*)(list
->version
),
546 strlen(list
->version
) + 1);
547 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
552 GUID
const * const *format
;
554 res
= RegCreateKeyExW(clsid_key
, pixelformats_keyname
, 0, NULL
, 0,
555 KEY_READ
| KEY_WRITE
, NULL
, &formats_key
, NULL
);
556 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
557 for (format
=list
->formats
; *format
; ++format
)
560 StringFromGUID2(*format
, buf
, 39);
561 res
= RegCreateKeyExW(formats_key
, buf
, 0, NULL
, 0,
562 KEY_READ
| KEY_WRITE
, NULL
, &format_key
, NULL
);
563 if (res
!= ERROR_SUCCESS
) break;
564 RegCloseKey(format_key
);
566 RegCloseKey(formats_key
);
567 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
570 error_close_clsid_key
:
571 RegCloseKey(clsid_key
);
574 error_close_coclass_key
:
575 RegCloseKey(instance_key
);
576 RegCloseKey(converters_key
);
577 RegCloseKey(coclass_key
);
579 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
582 /***********************************************************************
583 * unregister_converters
585 static HRESULT
unregister_converters(struct regsvr_converter
const *list
)
587 LONG res
= ERROR_SUCCESS
;
593 res
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, clsid_keyname
, 0,
594 KEY_READ
| KEY_WRITE
, &coclass_key
);
595 if (res
== ERROR_FILE_NOT_FOUND
) return S_OK
;
597 if (res
== ERROR_SUCCESS
) {
598 StringFromGUID2(&CATID_WICFormatConverters
, buf
, 39);
599 res
= RegCreateKeyExW(coclass_key
, buf
, 0, NULL
, 0,
600 KEY_READ
| KEY_WRITE
, NULL
, &converters_key
, NULL
);
601 if (res
== ERROR_SUCCESS
)
603 res
= RegCreateKeyExW(converters_key
, instance_keyname
, 0, NULL
, 0,
604 KEY_READ
| KEY_WRITE
, NULL
, &instance_key
, NULL
);
605 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
607 if (res
!= ERROR_SUCCESS
)
608 RegCloseKey(coclass_key
);
610 if (res
!= ERROR_SUCCESS
) goto error_return
;
612 for (; res
== ERROR_SUCCESS
&& list
->clsid
; ++list
) {
613 StringFromGUID2(list
->clsid
, buf
, 39);
615 res
= RegDeleteTreeW(coclass_key
, buf
);
616 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
617 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
619 res
= RegDeleteTreeW(instance_key
, buf
);
620 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
621 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
624 error_close_coclass_key
:
625 RegCloseKey(instance_key
);
626 RegCloseKey(converters_key
);
627 RegCloseKey(coclass_key
);
629 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
632 /***********************************************************************
633 * register_key_defvalueW
635 static LONG
register_key_defvalueW(
643 res
= RegCreateKeyExW(base
, name
, 0, NULL
, 0,
644 KEY_READ
| KEY_WRITE
, NULL
, &key
, NULL
);
645 if (res
!= ERROR_SUCCESS
) return res
;
646 res
= RegSetValueExW(key
, NULL
, 0, REG_SZ
, (CONST BYTE
*)value
,
647 (lstrlenW(value
) + 1) * sizeof(WCHAR
));
652 /***********************************************************************
653 * register_key_defvalueA
655 static LONG
register_key_defvalueA(
663 res
= RegCreateKeyExW(base
, name
, 0, NULL
, 0,
664 KEY_READ
| KEY_WRITE
, NULL
, &key
, NULL
);
665 if (res
!= ERROR_SUCCESS
) return res
;
666 res
= RegSetValueExA(key
, NULL
, 0, REG_SZ
, (CONST BYTE
*)value
,
667 lstrlenA(value
) + 1);
672 /***********************************************************************
675 static LONG
register_progid(
678 char const *curver_progid
,
685 res
= RegCreateKeyExA(HKEY_CLASSES_ROOT
, progid
, 0,
686 NULL
, 0, KEY_READ
| KEY_WRITE
, NULL
,
688 if (res
!= ERROR_SUCCESS
) return res
;
691 res
= RegSetValueExA(progid_key
, NULL
, 0, REG_SZ
,
692 (CONST BYTE
*)name
, strlen(name
) + 1);
693 if (res
!= ERROR_SUCCESS
) goto error_close_progid_key
;
697 res
= register_key_defvalueW(progid_key
, clsid_keyname
, clsid
);
698 if (res
!= ERROR_SUCCESS
) goto error_close_progid_key
;
702 res
= register_key_defvalueA(progid_key
, curver_keyname
,
704 if (res
!= ERROR_SUCCESS
) goto error_close_progid_key
;
710 res
= RegCreateKeyExA(progid_key
, extra
, 0,
711 NULL
, 0, KEY_READ
| KEY_WRITE
, NULL
,
713 if (res
== ERROR_SUCCESS
)
714 RegCloseKey(extra_key
);
717 error_close_progid_key
:
718 RegCloseKey(progid_key
);
722 /***********************************************************************
725 static struct regsvr_coclass
const coclass_list
[] = {
726 { &CLSID_WICImagingFactory
,
727 "WIC Imaging Factory",
732 { &CLSID_WICBmpDecoder
,
738 { &CLSID_WICPngDecoder
,
744 { &CLSID_WICPngEncoder
,
750 { &CLSID_WICBmpEncoder
,
756 { &CLSID_WICGifDecoder
,
762 { &CLSID_WICIcoDecoder
,
768 { &CLSID_WICJpegDecoder
,
774 { &CLSID_WICDefaultFormatConverter
,
775 "WIC Default Format Converter",
780 { NULL
} /* list terminator */
783 /***********************************************************************
786 static const BYTE mask_all
[] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
788 static const BYTE bmp_magic
[] = {0x42,0x4d};
790 static GUID
const * const bmp_formats
[] = {
791 &GUID_WICPixelFormat1bppIndexed
,
792 &GUID_WICPixelFormat2bppIndexed
,
793 &GUID_WICPixelFormat4bppIndexed
,
794 &GUID_WICPixelFormat8bppIndexed
,
795 &GUID_WICPixelFormat16bppBGR555
,
796 &GUID_WICPixelFormat16bppBGR565
,
797 &GUID_WICPixelFormat24bppBGR
,
798 &GUID_WICPixelFormat32bppBGR
,
799 &GUID_WICPixelFormat32bppBGRA
,
803 static struct decoder_pattern
const bmp_patterns
[] = {
804 {2,0,bmp_magic
,mask_all
,0},
808 static const BYTE gif87a_magic
[6] = "GIF87a";
809 static const BYTE gif89a_magic
[6] = "GIF89a";
811 static GUID
const * const gif_formats
[] = {
812 &GUID_WICPixelFormat8bppIndexed
,
816 static struct decoder_pattern
const gif_patterns
[] = {
817 {6,0,gif87a_magic
,mask_all
,0},
818 {6,0,gif89a_magic
,mask_all
,0},
822 static const BYTE ico_magic
[] = {00,00,01,00};
824 static GUID
const * const ico_formats
[] = {
825 &GUID_WICPixelFormat32bppBGRA
,
829 static struct decoder_pattern
const ico_patterns
[] = {
830 {4,0,ico_magic
,mask_all
,0},
834 static const BYTE jpeg_magic
[] = {0xff, 0xd8, 0xff, 0xe0};
836 static GUID
const * const jpeg_formats
[] = {
837 &GUID_WICPixelFormat24bppBGR
,
838 &GUID_WICPixelFormat8bppGray
,
842 static struct decoder_pattern
const jpeg_patterns
[] = {
843 {4,0,jpeg_magic
,mask_all
,0},
847 static const BYTE png_magic
[] = {137,80,78,71,13,10,26,10};
849 static GUID
const * const png_formats
[] = {
850 &GUID_WICPixelFormatBlackWhite
,
851 &GUID_WICPixelFormat2bppGray
,
852 &GUID_WICPixelFormat4bppGray
,
853 &GUID_WICPixelFormat8bppGray
,
854 &GUID_WICPixelFormat16bppGray
,
855 &GUID_WICPixelFormat32bppBGRA
,
856 &GUID_WICPixelFormat64bppRGBA
,
857 &GUID_WICPixelFormat1bppIndexed
,
858 &GUID_WICPixelFormat2bppIndexed
,
859 &GUID_WICPixelFormat4bppIndexed
,
860 &GUID_WICPixelFormat8bppIndexed
,
861 &GUID_WICPixelFormat24bppBGR
,
862 &GUID_WICPixelFormat48bppRGB
,
866 static struct decoder_pattern
const png_patterns
[] = {
867 {8,0,png_magic
,mask_all
,0},
871 static struct regsvr_decoder
const decoder_list
[] = {
872 { &CLSID_WICBmpDecoder
,
876 &GUID_VendorMicrosoft
,
882 { &CLSID_WICGifDecoder
,
886 &GUID_VendorMicrosoft
,
892 { &CLSID_WICIcoDecoder
,
896 &GUID_VendorMicrosoft
,
897 "image/vnd.microsoft.icon",
902 { &CLSID_WICJpegDecoder
,
906 &GUID_VendorMicrosoft
,
912 { &CLSID_WICPngDecoder
,
916 &GUID_VendorMicrosoft
,
922 { NULL
} /* list terminator */
925 static GUID
const * const converter_formats
[] = {
926 &GUID_WICPixelFormat1bppIndexed
,
927 &GUID_WICPixelFormat2bppIndexed
,
928 &GUID_WICPixelFormat4bppIndexed
,
929 &GUID_WICPixelFormat8bppIndexed
,
930 &GUID_WICPixelFormatBlackWhite
,
931 &GUID_WICPixelFormat2bppGray
,
932 &GUID_WICPixelFormat4bppGray
,
933 &GUID_WICPixelFormat8bppGray
,
934 &GUID_WICPixelFormat16bppGray
,
935 &GUID_WICPixelFormat16bppBGR555
,
936 &GUID_WICPixelFormat16bppBGR565
,
937 &GUID_WICPixelFormat24bppBGR
,
938 &GUID_WICPixelFormat32bppBGR
,
939 &GUID_WICPixelFormat32bppBGRA
,
940 &GUID_WICPixelFormat48bppRGB
,
941 &GUID_WICPixelFormat64bppRGBA
,
945 static struct regsvr_converter
const converter_list
[] = {
946 { &CLSID_WICDefaultFormatConverter
,
948 "Default Pixel Format Converter",
950 &GUID_VendorMicrosoft
,
953 { NULL
} /* list terminator */
956 HRESULT WINAPI
DllRegisterServer(void)
962 hr
= register_coclasses(coclass_list
);
964 register_decoders(decoder_list
);
966 register_converters(converter_list
);
970 HRESULT WINAPI
DllUnregisterServer(void)
976 hr
= unregister_coclasses(coclass_list
);
978 unregister_decoders(decoder_list
);
980 unregister_converters(converter_list
);