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
46 struct decoder_pattern
48 DWORD length
; /* 0 for end of list */
57 CLSID
const *clsid
; /* NULL for end of list */
64 GUID
const * const *formats
;
65 const struct decoder_pattern
*patterns
;
68 static HRESULT
register_decoders(struct regsvr_decoder
const *list
);
69 static HRESULT
unregister_decoders(struct regsvr_decoder
const *list
);
73 CLSID
const *clsid
; /* NULL for end of list */
80 GUID
const * const *formats
;
83 static HRESULT
register_encoders(struct regsvr_encoder
const *list
);
84 static HRESULT
unregister_encoders(struct regsvr_encoder
const *list
);
86 struct regsvr_converter
88 CLSID
const *clsid
; /* NULL for end of list */
93 GUID
const * const *formats
;
96 static HRESULT
register_converters(struct regsvr_converter
const *list
);
97 static HRESULT
unregister_converters(struct regsvr_converter
const *list
);
99 /***********************************************************************
100 * static string constants
102 static WCHAR
const clsid_keyname
[] = {
103 'C', 'L', 'S', 'I', 'D', 0 };
104 static WCHAR
const curver_keyname
[] = {
105 'C', 'u', 'r', 'V', 'e', 'r', 0 };
106 static WCHAR
const ips_keyname
[] = {
107 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
109 static WCHAR
const ips32_keyname
[] = {
110 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
112 static WCHAR
const progid_keyname
[] = {
113 'P', 'r', 'o', 'g', 'I', 'D', 0 };
114 static WCHAR
const viprogid_keyname
[] = {
115 'V', 'e', 'r', 's', 'i', 'o', 'n', 'I', 'n', 'd', 'e', 'p',
116 'e', 'n', 'd', 'e', 'n', 't', 'P', 'r', 'o', 'g', 'I', 'D',
118 static char const tmodel_valuename
[] = "ThreadingModel";
119 static char const author_valuename
[] = "Author";
120 static char const friendlyname_valuename
[] = "FriendlyName";
121 static WCHAR
const vendor_valuename
[] = {'V','e','n','d','o','r',0};
122 static char const version_valuename
[] = "Version";
123 static char const mimetypes_valuename
[] = "MimeTypes";
124 static char const extensions_valuename
[] = "FileExtensions";
125 static WCHAR
const formats_keyname
[] = {'F','o','r','m','a','t','s',0};
126 static WCHAR
const patterns_keyname
[] = {'P','a','t','t','e','r','n','s',0};
127 static WCHAR
const instance_keyname
[] = {'I','n','s','t','a','n','c','e',0};
128 static WCHAR
const clsid_valuename
[] = {'C','L','S','I','D',0};
129 static char const length_valuename
[] = "Length";
130 static char const position_valuename
[] = "Position";
131 static char const pattern_valuename
[] = "Pattern";
132 static char const mask_valuename
[] = "Mask";
133 static char const endofstream_valuename
[] = "EndOfStream";
134 static WCHAR
const pixelformats_keyname
[] = {'P','i','x','e','l','F','o','r','m','a','t','s',0};
136 /***********************************************************************
139 static HRESULT
register_decoders(struct regsvr_decoder
const *list
)
141 LONG res
= ERROR_SUCCESS
;
147 res
= RegCreateKeyExW(HKEY_CLASSES_ROOT
, clsid_keyname
, 0, NULL
, 0,
148 KEY_READ
| KEY_WRITE
, NULL
, &coclass_key
, NULL
);
149 if (res
== ERROR_SUCCESS
) {
150 StringFromGUID2(&CATID_WICBitmapDecoders
, buf
, 39);
151 res
= RegCreateKeyExW(coclass_key
, buf
, 0, NULL
, 0,
152 KEY_READ
| KEY_WRITE
, NULL
, &decoders_key
, NULL
);
153 if (res
== ERROR_SUCCESS
)
155 res
= RegCreateKeyExW(decoders_key
, instance_keyname
, 0, NULL
, 0,
156 KEY_READ
| KEY_WRITE
, NULL
, &instance_key
, NULL
);
157 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
159 if (res
!= ERROR_SUCCESS
)
160 RegCloseKey(coclass_key
);
162 if (res
!= ERROR_SUCCESS
) goto error_return
;
164 for (; res
== ERROR_SUCCESS
&& list
->clsid
; ++list
) {
166 HKEY instance_clsid_key
;
168 StringFromGUID2(list
->clsid
, buf
, 39);
169 res
= RegCreateKeyExW(coclass_key
, buf
, 0, NULL
, 0,
170 KEY_READ
| KEY_WRITE
, NULL
, &clsid_key
, NULL
);
171 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
173 StringFromGUID2(list
->clsid
, buf
, 39);
174 res
= RegCreateKeyExW(instance_key
, buf
, 0, NULL
, 0,
175 KEY_READ
| KEY_WRITE
, NULL
, &instance_clsid_key
, NULL
);
176 if (res
== ERROR_SUCCESS
) {
177 res
= RegSetValueExW(instance_clsid_key
, clsid_valuename
, 0, REG_SZ
,
178 (CONST BYTE
*)(buf
), 78);
179 RegCloseKey(instance_clsid_key
);
181 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
184 res
= RegSetValueExA(clsid_key
, author_valuename
, 0, REG_SZ
,
185 (CONST BYTE
*)(list
->author
),
186 strlen(list
->author
) + 1);
187 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
190 if (list
->friendlyname
) {
191 res
= RegSetValueExA(clsid_key
, friendlyname_valuename
, 0, REG_SZ
,
192 (CONST BYTE
*)(list
->friendlyname
),
193 strlen(list
->friendlyname
) + 1);
194 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
198 StringFromGUID2(list
->vendor
, buf
, 39);
199 res
= RegSetValueExW(clsid_key
, vendor_valuename
, 0, REG_SZ
,
200 (CONST BYTE
*)(buf
), 78);
201 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
205 res
= RegSetValueExA(clsid_key
, version_valuename
, 0, REG_SZ
,
206 (CONST BYTE
*)(list
->version
),
207 strlen(list
->version
) + 1);
208 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
211 if (list
->mimetypes
) {
212 res
= RegSetValueExA(clsid_key
, mimetypes_valuename
, 0, REG_SZ
,
213 (CONST BYTE
*)(list
->mimetypes
),
214 strlen(list
->mimetypes
) + 1);
215 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
218 if (list
->extensions
) {
219 res
= RegSetValueExA(clsid_key
, extensions_valuename
, 0, REG_SZ
,
220 (CONST BYTE
*)(list
->extensions
),
221 strlen(list
->extensions
) + 1);
222 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
227 GUID
const * const *format
;
229 res
= RegCreateKeyExW(clsid_key
, formats_keyname
, 0, NULL
, 0,
230 KEY_READ
| KEY_WRITE
, NULL
, &formats_key
, NULL
);
231 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
232 for (format
=list
->formats
; *format
; ++format
)
235 StringFromGUID2(*format
, buf
, 39);
236 res
= RegCreateKeyExW(formats_key
, buf
, 0, NULL
, 0,
237 KEY_READ
| KEY_WRITE
, NULL
, &format_key
, NULL
);
238 if (res
!= ERROR_SUCCESS
) break;
239 RegCloseKey(format_key
);
241 RegCloseKey(formats_key
);
242 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
245 if (list
->patterns
) {
249 res
= RegCreateKeyExW(clsid_key
, patterns_keyname
, 0, NULL
, 0,
250 KEY_READ
| KEY_WRITE
, NULL
, &patterns_key
, NULL
);
251 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
252 for (i
=0; list
->patterns
[i
].length
; i
++)
255 static const WCHAR int_format
[] = {'%','i',0};
256 snprintfW(buf
, 39, int_format
, i
);
257 res
= RegCreateKeyExW(patterns_key
, buf
, 0, NULL
, 0,
258 KEY_READ
| KEY_WRITE
, NULL
, &pattern_key
, NULL
);
259 if (res
!= ERROR_SUCCESS
) break;
260 res
= RegSetValueExA(pattern_key
, length_valuename
, 0, REG_DWORD
,
261 (CONST BYTE
*)(&list
->patterns
[i
].length
), 4);
262 if (res
== ERROR_SUCCESS
)
263 res
= RegSetValueExA(pattern_key
, position_valuename
, 0, REG_DWORD
,
264 (CONST BYTE
*)(&list
->patterns
[i
].position
), 4);
265 if (res
== ERROR_SUCCESS
)
266 res
= RegSetValueExA(pattern_key
, pattern_valuename
, 0, REG_BINARY
,
267 list
->patterns
[i
].pattern
,
268 list
->patterns
[i
].length
);
269 if (res
== ERROR_SUCCESS
)
270 res
= RegSetValueExA(pattern_key
, mask_valuename
, 0, REG_BINARY
,
271 list
->patterns
[i
].mask
,
272 list
->patterns
[i
].length
);
273 if (res
== ERROR_SUCCESS
)
274 res
= RegSetValueExA(pattern_key
, endofstream_valuename
, 0, REG_DWORD
,
275 (CONST BYTE
*)&(list
->patterns
[i
].endofstream
), 4);
276 RegCloseKey(pattern_key
);
278 RegCloseKey(patterns_key
);
279 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
282 error_close_clsid_key
:
283 RegCloseKey(clsid_key
);
286 error_close_coclass_key
:
287 RegCloseKey(instance_key
);
288 RegCloseKey(decoders_key
);
289 RegCloseKey(coclass_key
);
291 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
294 /***********************************************************************
295 * unregister_decoders
297 static HRESULT
unregister_decoders(struct regsvr_decoder
const *list
)
299 LONG res
= ERROR_SUCCESS
;
305 res
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, clsid_keyname
, 0,
306 KEY_READ
| KEY_WRITE
, &coclass_key
);
307 if (res
== ERROR_FILE_NOT_FOUND
) return S_OK
;
309 if (res
== ERROR_SUCCESS
) {
310 StringFromGUID2(&CATID_WICBitmapDecoders
, buf
, 39);
311 res
= RegCreateKeyExW(coclass_key
, buf
, 0, NULL
, 0,
312 KEY_READ
| KEY_WRITE
, NULL
, &decoders_key
, NULL
);
313 if (res
== ERROR_SUCCESS
)
315 res
= RegCreateKeyExW(decoders_key
, instance_keyname
, 0, NULL
, 0,
316 KEY_READ
| KEY_WRITE
, NULL
, &instance_key
, NULL
);
317 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
319 if (res
!= ERROR_SUCCESS
)
320 RegCloseKey(coclass_key
);
322 if (res
!= ERROR_SUCCESS
) goto error_return
;
324 for (; res
== ERROR_SUCCESS
&& list
->clsid
; ++list
) {
325 StringFromGUID2(list
->clsid
, buf
, 39);
327 res
= RegDeleteTreeW(coclass_key
, buf
);
328 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
329 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
331 res
= RegDeleteTreeW(instance_key
, buf
);
332 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
333 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
336 error_close_coclass_key
:
337 RegCloseKey(instance_key
);
338 RegCloseKey(decoders_key
);
339 RegCloseKey(coclass_key
);
341 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
344 /***********************************************************************
347 static HRESULT
register_encoders(struct regsvr_encoder
const *list
)
349 LONG res
= ERROR_SUCCESS
;
355 res
= RegCreateKeyExW(HKEY_CLASSES_ROOT
, clsid_keyname
, 0, NULL
, 0,
356 KEY_READ
| KEY_WRITE
, NULL
, &coclass_key
, NULL
);
357 if (res
== ERROR_SUCCESS
) {
358 StringFromGUID2(&CATID_WICBitmapEncoders
, buf
, 39);
359 res
= RegCreateKeyExW(coclass_key
, buf
, 0, NULL
, 0,
360 KEY_READ
| KEY_WRITE
, NULL
, &encoders_key
, NULL
);
361 if (res
== ERROR_SUCCESS
)
363 res
= RegCreateKeyExW(encoders_key
, instance_keyname
, 0, NULL
, 0,
364 KEY_READ
| KEY_WRITE
, NULL
, &instance_key
, NULL
);
365 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
367 if (res
!= ERROR_SUCCESS
)
368 RegCloseKey(coclass_key
);
370 if (res
!= ERROR_SUCCESS
) goto error_return
;
372 for (; res
== ERROR_SUCCESS
&& list
->clsid
; ++list
) {
374 HKEY instance_clsid_key
;
376 StringFromGUID2(list
->clsid
, buf
, 39);
377 res
= RegCreateKeyExW(coclass_key
, buf
, 0, NULL
, 0,
378 KEY_READ
| KEY_WRITE
, NULL
, &clsid_key
, NULL
);
379 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
381 StringFromGUID2(list
->clsid
, buf
, 39);
382 res
= RegCreateKeyExW(instance_key
, buf
, 0, NULL
, 0,
383 KEY_READ
| KEY_WRITE
, NULL
, &instance_clsid_key
, NULL
);
384 if (res
== ERROR_SUCCESS
) {
385 res
= RegSetValueExW(instance_clsid_key
, clsid_valuename
, 0, REG_SZ
,
386 (CONST BYTE
*)(buf
), 78);
387 RegCloseKey(instance_clsid_key
);
389 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
392 res
= RegSetValueExA(clsid_key
, author_valuename
, 0, REG_SZ
,
393 (CONST BYTE
*)(list
->author
),
394 strlen(list
->author
) + 1);
395 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
398 if (list
->friendlyname
) {
399 res
= RegSetValueExA(clsid_key
, friendlyname_valuename
, 0, REG_SZ
,
400 (CONST BYTE
*)(list
->friendlyname
),
401 strlen(list
->friendlyname
) + 1);
402 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
406 StringFromGUID2(list
->vendor
, buf
, 39);
407 res
= RegSetValueExW(clsid_key
, vendor_valuename
, 0, REG_SZ
,
408 (CONST BYTE
*)(buf
), 78);
409 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
413 res
= RegSetValueExA(clsid_key
, version_valuename
, 0, REG_SZ
,
414 (CONST BYTE
*)(list
->version
),
415 strlen(list
->version
) + 1);
416 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
419 if (list
->mimetypes
) {
420 res
= RegSetValueExA(clsid_key
, mimetypes_valuename
, 0, REG_SZ
,
421 (CONST BYTE
*)(list
->mimetypes
),
422 strlen(list
->mimetypes
) + 1);
423 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
426 if (list
->extensions
) {
427 res
= RegSetValueExA(clsid_key
, extensions_valuename
, 0, REG_SZ
,
428 (CONST BYTE
*)(list
->extensions
),
429 strlen(list
->extensions
) + 1);
430 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
435 GUID
const * const *format
;
437 res
= RegCreateKeyExW(clsid_key
, formats_keyname
, 0, NULL
, 0,
438 KEY_READ
| KEY_WRITE
, NULL
, &formats_key
, NULL
);
439 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
440 for (format
=list
->formats
; *format
; ++format
)
443 StringFromGUID2(*format
, buf
, 39);
444 res
= RegCreateKeyExW(formats_key
, buf
, 0, NULL
, 0,
445 KEY_READ
| KEY_WRITE
, NULL
, &format_key
, NULL
);
446 if (res
!= ERROR_SUCCESS
) break;
447 RegCloseKey(format_key
);
449 RegCloseKey(formats_key
);
450 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
453 error_close_clsid_key
:
454 RegCloseKey(clsid_key
);
457 error_close_coclass_key
:
458 RegCloseKey(instance_key
);
459 RegCloseKey(encoders_key
);
460 RegCloseKey(coclass_key
);
462 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
465 /***********************************************************************
466 * unregister_encoders
468 static HRESULT
unregister_encoders(struct regsvr_encoder
const *list
)
470 LONG res
= ERROR_SUCCESS
;
476 res
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, clsid_keyname
, 0,
477 KEY_READ
| KEY_WRITE
, &coclass_key
);
478 if (res
== ERROR_FILE_NOT_FOUND
) return S_OK
;
480 if (res
== ERROR_SUCCESS
) {
481 StringFromGUID2(&CATID_WICBitmapEncoders
, buf
, 39);
482 res
= RegCreateKeyExW(coclass_key
, buf
, 0, NULL
, 0,
483 KEY_READ
| KEY_WRITE
, NULL
, &encoders_key
, NULL
);
484 if (res
== ERROR_SUCCESS
)
486 res
= RegCreateKeyExW(encoders_key
, instance_keyname
, 0, NULL
, 0,
487 KEY_READ
| KEY_WRITE
, NULL
, &instance_key
, NULL
);
488 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
490 if (res
!= ERROR_SUCCESS
)
491 RegCloseKey(coclass_key
);
493 if (res
!= ERROR_SUCCESS
) goto error_return
;
495 for (; res
== ERROR_SUCCESS
&& list
->clsid
; ++list
) {
496 StringFromGUID2(list
->clsid
, buf
, 39);
498 res
= RegDeleteTreeW(coclass_key
, buf
);
499 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
500 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
502 res
= RegDeleteTreeW(instance_key
, buf
);
503 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
504 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
507 error_close_coclass_key
:
508 RegCloseKey(instance_key
);
509 RegCloseKey(encoders_key
);
510 RegCloseKey(coclass_key
);
512 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
515 /***********************************************************************
516 * register_converters
518 static HRESULT
register_converters(struct regsvr_converter
const *list
)
520 LONG res
= ERROR_SUCCESS
;
526 res
= RegCreateKeyExW(HKEY_CLASSES_ROOT
, clsid_keyname
, 0, NULL
, 0,
527 KEY_READ
| KEY_WRITE
, NULL
, &coclass_key
, NULL
);
528 if (res
== ERROR_SUCCESS
) {
529 StringFromGUID2(&CATID_WICFormatConverters
, buf
, 39);
530 res
= RegCreateKeyExW(coclass_key
, buf
, 0, NULL
, 0,
531 KEY_READ
| KEY_WRITE
, NULL
, &converters_key
, NULL
);
532 if (res
== ERROR_SUCCESS
)
534 res
= RegCreateKeyExW(converters_key
, instance_keyname
, 0, NULL
, 0,
535 KEY_READ
| KEY_WRITE
, NULL
, &instance_key
, NULL
);
536 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
538 if (res
!= ERROR_SUCCESS
)
539 RegCloseKey(coclass_key
);
541 if (res
!= ERROR_SUCCESS
) goto error_return
;
543 for (; res
== ERROR_SUCCESS
&& list
->clsid
; ++list
) {
545 HKEY instance_clsid_key
;
547 StringFromGUID2(list
->clsid
, buf
, 39);
548 res
= RegCreateKeyExW(coclass_key
, buf
, 0, NULL
, 0,
549 KEY_READ
| KEY_WRITE
, NULL
, &clsid_key
, NULL
);
550 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
552 StringFromGUID2(list
->clsid
, buf
, 39);
553 res
= RegCreateKeyExW(instance_key
, buf
, 0, NULL
, 0,
554 KEY_READ
| KEY_WRITE
, NULL
, &instance_clsid_key
, NULL
);
555 if (res
== ERROR_SUCCESS
) {
556 res
= RegSetValueExW(instance_clsid_key
, clsid_valuename
, 0, REG_SZ
,
557 (CONST BYTE
*)(buf
), 78);
558 RegCloseKey(instance_clsid_key
);
560 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
563 res
= RegSetValueExA(clsid_key
, author_valuename
, 0, REG_SZ
,
564 (CONST BYTE
*)(list
->author
),
565 strlen(list
->author
) + 1);
566 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
569 if (list
->friendlyname
) {
570 res
= RegSetValueExA(clsid_key
, friendlyname_valuename
, 0, REG_SZ
,
571 (CONST BYTE
*)(list
->friendlyname
),
572 strlen(list
->friendlyname
) + 1);
573 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
577 StringFromGUID2(list
->vendor
, buf
, 39);
578 res
= RegSetValueExW(clsid_key
, vendor_valuename
, 0, REG_SZ
,
579 (CONST BYTE
*)(buf
), 78);
580 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
584 res
= RegSetValueExA(clsid_key
, version_valuename
, 0, REG_SZ
,
585 (CONST BYTE
*)(list
->version
),
586 strlen(list
->version
) + 1);
587 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
592 GUID
const * const *format
;
594 res
= RegCreateKeyExW(clsid_key
, pixelformats_keyname
, 0, NULL
, 0,
595 KEY_READ
| KEY_WRITE
, NULL
, &formats_key
, NULL
);
596 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
597 for (format
=list
->formats
; *format
; ++format
)
600 StringFromGUID2(*format
, buf
, 39);
601 res
= RegCreateKeyExW(formats_key
, buf
, 0, NULL
, 0,
602 KEY_READ
| KEY_WRITE
, NULL
, &format_key
, NULL
);
603 if (res
!= ERROR_SUCCESS
) break;
604 RegCloseKey(format_key
);
606 RegCloseKey(formats_key
);
607 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
610 error_close_clsid_key
:
611 RegCloseKey(clsid_key
);
614 error_close_coclass_key
:
615 RegCloseKey(instance_key
);
616 RegCloseKey(converters_key
);
617 RegCloseKey(coclass_key
);
619 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
622 /***********************************************************************
623 * unregister_converters
625 static HRESULT
unregister_converters(struct regsvr_converter
const *list
)
627 LONG res
= ERROR_SUCCESS
;
633 res
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, clsid_keyname
, 0,
634 KEY_READ
| KEY_WRITE
, &coclass_key
);
635 if (res
== ERROR_FILE_NOT_FOUND
) return S_OK
;
637 if (res
== ERROR_SUCCESS
) {
638 StringFromGUID2(&CATID_WICFormatConverters
, buf
, 39);
639 res
= RegCreateKeyExW(coclass_key
, buf
, 0, NULL
, 0,
640 KEY_READ
| KEY_WRITE
, NULL
, &converters_key
, NULL
);
641 if (res
== ERROR_SUCCESS
)
643 res
= RegCreateKeyExW(converters_key
, instance_keyname
, 0, NULL
, 0,
644 KEY_READ
| KEY_WRITE
, NULL
, &instance_key
, NULL
);
645 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
647 if (res
!= ERROR_SUCCESS
)
648 RegCloseKey(coclass_key
);
650 if (res
!= ERROR_SUCCESS
) goto error_return
;
652 for (; res
== ERROR_SUCCESS
&& list
->clsid
; ++list
) {
653 StringFromGUID2(list
->clsid
, buf
, 39);
655 res
= RegDeleteTreeW(coclass_key
, buf
);
656 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
657 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
659 res
= RegDeleteTreeW(instance_key
, buf
);
660 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
661 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
664 error_close_coclass_key
:
665 RegCloseKey(instance_key
);
666 RegCloseKey(converters_key
);
667 RegCloseKey(coclass_key
);
669 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
672 /***********************************************************************
675 static const BYTE mask_all
[] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
677 static const BYTE bmp_magic
[] = {0x42,0x4d};
679 static GUID
const * const bmp_formats
[] = {
680 &GUID_WICPixelFormat1bppIndexed
,
681 &GUID_WICPixelFormat2bppIndexed
,
682 &GUID_WICPixelFormat4bppIndexed
,
683 &GUID_WICPixelFormat8bppIndexed
,
684 &GUID_WICPixelFormat16bppBGR555
,
685 &GUID_WICPixelFormat16bppBGR565
,
686 &GUID_WICPixelFormat24bppBGR
,
687 &GUID_WICPixelFormat32bppBGR
,
688 &GUID_WICPixelFormat32bppBGRA
,
692 static struct decoder_pattern
const bmp_patterns
[] = {
693 {2,0,bmp_magic
,mask_all
,0},
697 static const BYTE gif87a_magic
[6] = "GIF87a";
698 static const BYTE gif89a_magic
[6] = "GIF89a";
700 static GUID
const * const gif_formats
[] = {
701 &GUID_WICPixelFormat8bppIndexed
,
705 static struct decoder_pattern
const gif_patterns
[] = {
706 {6,0,gif87a_magic
,mask_all
,0},
707 {6,0,gif89a_magic
,mask_all
,0},
711 static const BYTE ico_magic
[] = {00,00,01,00};
713 static GUID
const * const ico_formats
[] = {
714 &GUID_WICPixelFormat32bppBGRA
,
718 static struct decoder_pattern
const ico_patterns
[] = {
719 {4,0,ico_magic
,mask_all
,0},
723 static const BYTE jpeg_magic
[] = {0xff, 0xd8};
725 static GUID
const * const jpeg_formats
[] = {
726 &GUID_WICPixelFormat24bppBGR
,
727 &GUID_WICPixelFormat32bppCMYK
,
728 &GUID_WICPixelFormat8bppGray
,
732 static struct decoder_pattern
const jpeg_patterns
[] = {
733 {2,0,jpeg_magic
,mask_all
,0},
737 static const BYTE png_magic
[] = {137,80,78,71,13,10,26,10};
739 static GUID
const * const png_formats
[] = {
740 &GUID_WICPixelFormatBlackWhite
,
741 &GUID_WICPixelFormat2bppGray
,
742 &GUID_WICPixelFormat4bppGray
,
743 &GUID_WICPixelFormat8bppGray
,
744 &GUID_WICPixelFormat16bppGray
,
745 &GUID_WICPixelFormat32bppBGRA
,
746 &GUID_WICPixelFormat64bppRGBA
,
747 &GUID_WICPixelFormat1bppIndexed
,
748 &GUID_WICPixelFormat2bppIndexed
,
749 &GUID_WICPixelFormat4bppIndexed
,
750 &GUID_WICPixelFormat8bppIndexed
,
751 &GUID_WICPixelFormat24bppBGR
,
752 &GUID_WICPixelFormat48bppRGB
,
756 static struct decoder_pattern
const png_patterns
[] = {
757 {8,0,png_magic
,mask_all
,0},
761 static const BYTE tiff_magic_le
[] = {0x49,0x49,42,0};
762 static const BYTE tiff_magic_be
[] = {0x4d,0x4d,0,42};
764 static GUID
const * const tiff_decode_formats
[] = {
765 &GUID_WICPixelFormatBlackWhite
,
766 &GUID_WICPixelFormat4bppGray
,
767 &GUID_WICPixelFormat8bppGray
,
768 &GUID_WICPixelFormat4bppIndexed
,
769 &GUID_WICPixelFormat8bppIndexed
,
770 &GUID_WICPixelFormat24bppBGR
,
771 &GUID_WICPixelFormat32bppBGR
,
772 &GUID_WICPixelFormat32bppBGRA
,
773 &GUID_WICPixelFormat32bppPBGRA
,
774 &GUID_WICPixelFormat48bppRGB
,
775 &GUID_WICPixelFormat64bppRGBA
,
776 &GUID_WICPixelFormat64bppPRGBA
,
780 static struct decoder_pattern
const tiff_patterns
[] = {
781 {4,0,tiff_magic_le
,mask_all
,0},
782 {4,0,tiff_magic_be
,mask_all
,0},
786 static const BYTE tga_footer_magic
[18] = "TRUEVISION-XFILE.";
788 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};
789 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};
791 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};
792 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};
794 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};
795 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};
797 static GUID
const * const tga_formats
[] = {
798 &GUID_WICPixelFormat8bppGray
,
799 &GUID_WICPixelFormat8bppIndexed
,
800 &GUID_WICPixelFormat16bppGray
,
801 &GUID_WICPixelFormat16bppBGR555
,
802 &GUID_WICPixelFormat24bppBGR
,
803 &GUID_WICPixelFormat32bppBGRA
,
804 &GUID_WICPixelFormat32bppPBGRA
,
808 static struct decoder_pattern
const tga_patterns
[] = {
809 {18,18,tga_footer_magic
,mask_all
,1},
810 {18,0,tga_indexed_magic
,tga_indexed_mask
,0},
811 {18,0,tga_truecolor_magic
,tga_truecolor_mask
,0},
812 {18,0,tga_grayscale_magic
,tga_grayscale_mask
,0},
816 static struct regsvr_decoder
const decoder_list
[] = {
817 { &CLSID_WICBmpDecoder
,
821 &GUID_VendorMicrosoft
,
827 { &CLSID_WICGifDecoder
,
831 &GUID_VendorMicrosoft
,
837 { &CLSID_WICIcoDecoder
,
841 &GUID_VendorMicrosoft
,
842 "image/vnd.microsoft.icon",
847 { &CLSID_WICJpegDecoder
,
851 &GUID_VendorMicrosoft
,
857 { &CLSID_WICPngDecoder
,
861 &GUID_VendorMicrosoft
,
867 { &CLSID_WICTiffDecoder
,
871 &GUID_VendorMicrosoft
,
877 { &CLSID_WineTgaDecoder
,
887 { NULL
} /* list terminator */
890 static GUID
const * const bmp_encode_formats
[] = {
891 &GUID_WICPixelFormat16bppBGR555
,
892 &GUID_WICPixelFormat16bppBGR565
,
893 &GUID_WICPixelFormat24bppBGR
,
894 &GUID_WICPixelFormat32bppBGR
,
898 static GUID
const * const png_encode_formats
[] = {
899 &GUID_WICPixelFormat24bppBGR
,
900 &GUID_WICPixelFormatBlackWhite
,
901 &GUID_WICPixelFormat2bppGray
,
902 &GUID_WICPixelFormat4bppGray
,
903 &GUID_WICPixelFormat8bppGray
,
904 &GUID_WICPixelFormat16bppGray
,
905 &GUID_WICPixelFormat32bppBGR
,
906 &GUID_WICPixelFormat32bppBGRA
,
907 &GUID_WICPixelFormat48bppRGB
,
908 &GUID_WICPixelFormat64bppRGBA
,
912 static GUID
const * const tiff_encode_formats
[] = {
913 &GUID_WICPixelFormatBlackWhite
,
914 &GUID_WICPixelFormat4bppGray
,
915 &GUID_WICPixelFormat8bppGray
,
916 &GUID_WICPixelFormat24bppBGR
,
917 &GUID_WICPixelFormat32bppBGRA
,
918 &GUID_WICPixelFormat32bppPBGRA
,
919 &GUID_WICPixelFormat48bppRGB
,
920 &GUID_WICPixelFormat64bppRGBA
,
921 &GUID_WICPixelFormat64bppPRGBA
,
925 static GUID
const * const icns_encode_formats
[] = {
926 &GUID_WICPixelFormat32bppBGRA
,
930 static struct regsvr_encoder
const encoder_list
[] = {
931 { &CLSID_WICBmpEncoder
,
935 &GUID_VendorMicrosoft
,
940 { &CLSID_WICPngEncoder
,
944 &GUID_VendorMicrosoft
,
949 { &CLSID_WICTiffEncoder
,
953 &GUID_VendorMicrosoft
,
958 { &CLSID_WICIcnsEncoder
,
967 { NULL
} /* list terminator */
970 static GUID
const * const converter_formats
[] = {
971 &GUID_WICPixelFormat1bppIndexed
,
972 &GUID_WICPixelFormat2bppIndexed
,
973 &GUID_WICPixelFormat4bppIndexed
,
974 &GUID_WICPixelFormat8bppIndexed
,
975 &GUID_WICPixelFormatBlackWhite
,
976 &GUID_WICPixelFormat2bppGray
,
977 &GUID_WICPixelFormat4bppGray
,
978 &GUID_WICPixelFormat8bppGray
,
979 &GUID_WICPixelFormat16bppGray
,
980 &GUID_WICPixelFormat16bppBGR555
,
981 &GUID_WICPixelFormat16bppBGR565
,
982 &GUID_WICPixelFormat16bppBGRA5551
,
983 &GUID_WICPixelFormat24bppBGR
,
984 &GUID_WICPixelFormat32bppBGR
,
985 &GUID_WICPixelFormat32bppBGRA
,
986 &GUID_WICPixelFormat32bppPBGRA
,
987 &GUID_WICPixelFormat48bppRGB
,
988 &GUID_WICPixelFormat64bppRGBA
,
989 &GUID_WICPixelFormat32bppCMYK
,
993 static struct regsvr_converter
const converter_list
[] = {
994 { &CLSID_WICDefaultFormatConverter
,
996 "Default Pixel Format Converter",
998 &GUID_VendorMicrosoft
,
1001 { NULL
} /* list terminator */
1004 extern HRESULT WINAPI
WIC_DllRegisterServer(void) DECLSPEC_HIDDEN
;
1005 extern HRESULT WINAPI
WIC_DllUnregisterServer(void) DECLSPEC_HIDDEN
;
1007 HRESULT WINAPI
DllRegisterServer(void)
1013 hr
= WIC_DllRegisterServer();
1015 register_decoders(decoder_list
);
1017 register_encoders(encoder_list
);
1019 register_converters(converter_list
);
1023 HRESULT WINAPI
DllUnregisterServer(void)
1029 hr
= WIC_DllUnregisterServer();
1031 unregister_decoders(decoder_list
);
1033 unregister_encoders(encoder_list
);
1035 unregister_converters(converter_list
);