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
);
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
[6] = {
103 'C', 'L', 'S', 'I', 'D', 0 };
104 static WCHAR
const curver_keyname
[7] = {
105 'C', 'u', 'r', 'V', 'e', 'r', 0 };
106 static WCHAR
const ips_keyname
[13] = {
107 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
109 static WCHAR
const ips32_keyname
[15] = {
110 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
112 static WCHAR
const progid_keyname
[7] = {
113 'P', 'r', 'o', 'g', 'I', 'D', 0 };
114 static WCHAR
const viprogid_keyname
[25] = {
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 /***********************************************************************
137 * static helper functions
139 static LONG
register_key_defvalueW(HKEY base
, WCHAR
const *name
,
141 static LONG
register_key_defvalueA(HKEY base
, WCHAR
const *name
,
143 static LONG
register_progid(WCHAR
const *clsid
,
144 char const *progid
, char const *curver_progid
,
145 char const *name
, char const *extra
);
147 /***********************************************************************
150 static HRESULT
register_coclasses(struct regsvr_coclass
const *list
)
152 LONG res
= ERROR_SUCCESS
;
155 res
= RegCreateKeyExW(HKEY_CLASSES_ROOT
, clsid_keyname
, 0, NULL
, 0,
156 KEY_READ
| KEY_WRITE
, NULL
, &coclass_key
, NULL
);
157 if (res
!= ERROR_SUCCESS
) goto error_return
;
159 for (; res
== ERROR_SUCCESS
&& list
->clsid
; ++list
) {
163 StringFromGUID2(list
->clsid
, buf
, 39);
164 res
= RegCreateKeyExW(coclass_key
, buf
, 0, NULL
, 0,
165 KEY_READ
| KEY_WRITE
, NULL
, &clsid_key
, NULL
);
166 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
169 res
= RegSetValueExA(clsid_key
, NULL
, 0, REG_SZ
,
170 (CONST BYTE
*)(list
->name
),
171 strlen(list
->name
) + 1);
172 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
176 res
= register_key_defvalueA(clsid_key
, ips_keyname
, list
->ips
);
177 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
183 res
= RegCreateKeyExW(clsid_key
, ips32_keyname
, 0, NULL
, 0,
184 KEY_READ
| KEY_WRITE
, NULL
,
186 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
188 res
= RegSetValueExA(ips32_key
, NULL
, 0, REG_SZ
,
189 (CONST BYTE
*)list
->ips32
,
190 lstrlenA(list
->ips32
) + 1);
191 if (res
== ERROR_SUCCESS
&& list
->ips32_tmodel
)
192 res
= RegSetValueExA(ips32_key
, tmodel_valuename
, 0, REG_SZ
,
193 (CONST BYTE
*)list
->ips32_tmodel
,
194 strlen(list
->ips32_tmodel
) + 1);
195 RegCloseKey(ips32_key
);
196 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
200 res
= register_key_defvalueA(clsid_key
, progid_keyname
,
202 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
204 res
= register_progid(buf
, list
->progid
, NULL
,
205 list
->name
, list
->progid_extra
);
206 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
209 if (list
->viprogid
) {
210 res
= register_key_defvalueA(clsid_key
, viprogid_keyname
,
212 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
214 res
= register_progid(buf
, list
->viprogid
, list
->progid
,
215 list
->name
, list
->progid_extra
);
216 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
219 error_close_clsid_key
:
220 RegCloseKey(clsid_key
);
223 error_close_coclass_key
:
224 RegCloseKey(coclass_key
);
226 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
229 /***********************************************************************
230 * unregister_coclasses
232 static HRESULT
unregister_coclasses(struct regsvr_coclass
const *list
)
234 LONG res
= ERROR_SUCCESS
;
237 res
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, clsid_keyname
, 0,
238 KEY_READ
| KEY_WRITE
, &coclass_key
);
239 if (res
== ERROR_FILE_NOT_FOUND
) return S_OK
;
240 if (res
!= ERROR_SUCCESS
) goto error_return
;
242 for (; res
== ERROR_SUCCESS
&& list
->clsid
; ++list
) {
245 StringFromGUID2(list
->clsid
, buf
, 39);
246 res
= RegDeleteTreeW(coclass_key
, buf
);
247 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
248 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
251 res
= RegDeleteTreeA(HKEY_CLASSES_ROOT
, list
->progid
);
252 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
253 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
256 if (list
->viprogid
) {
257 res
= RegDeleteTreeA(HKEY_CLASSES_ROOT
, list
->viprogid
);
258 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
259 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
263 error_close_coclass_key
:
264 RegCloseKey(coclass_key
);
266 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
269 /***********************************************************************
272 static HRESULT
register_decoders(struct regsvr_decoder
const *list
)
274 LONG res
= ERROR_SUCCESS
;
280 res
= RegCreateKeyExW(HKEY_CLASSES_ROOT
, clsid_keyname
, 0, NULL
, 0,
281 KEY_READ
| KEY_WRITE
, NULL
, &coclass_key
, NULL
);
282 if (res
== ERROR_SUCCESS
) {
283 StringFromGUID2(&CATID_WICBitmapDecoders
, buf
, 39);
284 res
= RegCreateKeyExW(coclass_key
, buf
, 0, NULL
, 0,
285 KEY_READ
| KEY_WRITE
, NULL
, &decoders_key
, NULL
);
286 if (res
== ERROR_SUCCESS
)
288 res
= RegCreateKeyExW(decoders_key
, instance_keyname
, 0, NULL
, 0,
289 KEY_READ
| KEY_WRITE
, NULL
, &instance_key
, NULL
);
290 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
292 if (res
!= ERROR_SUCCESS
)
293 RegCloseKey(coclass_key
);
295 if (res
!= ERROR_SUCCESS
) goto error_return
;
297 for (; res
== ERROR_SUCCESS
&& list
->clsid
; ++list
) {
299 HKEY instance_clsid_key
;
301 StringFromGUID2(list
->clsid
, buf
, 39);
302 res
= RegCreateKeyExW(coclass_key
, buf
, 0, NULL
, 0,
303 KEY_READ
| KEY_WRITE
, NULL
, &clsid_key
, NULL
);
304 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
306 StringFromGUID2(list
->clsid
, buf
, 39);
307 res
= RegCreateKeyExW(instance_key
, buf
, 0, NULL
, 0,
308 KEY_READ
| KEY_WRITE
, NULL
, &instance_clsid_key
, NULL
);
309 if (res
== ERROR_SUCCESS
) {
310 res
= RegSetValueExW(instance_clsid_key
, clsid_valuename
, 0, REG_SZ
,
311 (CONST BYTE
*)(buf
), 78);
312 RegCloseKey(instance_clsid_key
);
314 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
317 res
= RegSetValueExA(clsid_key
, author_valuename
, 0, REG_SZ
,
318 (CONST BYTE
*)(list
->author
),
319 strlen(list
->author
) + 1);
320 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
323 if (list
->friendlyname
) {
324 res
= RegSetValueExA(clsid_key
, friendlyname_valuename
, 0, REG_SZ
,
325 (CONST BYTE
*)(list
->friendlyname
),
326 strlen(list
->friendlyname
) + 1);
327 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
331 StringFromGUID2(list
->vendor
, buf
, 39);
332 res
= RegSetValueExW(clsid_key
, vendor_valuename
, 0, REG_SZ
,
333 (CONST BYTE
*)(buf
), 78);
334 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
338 res
= RegSetValueExA(clsid_key
, version_valuename
, 0, REG_SZ
,
339 (CONST BYTE
*)(list
->version
),
340 strlen(list
->version
) + 1);
341 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
344 if (list
->mimetypes
) {
345 res
= RegSetValueExA(clsid_key
, mimetypes_valuename
, 0, REG_SZ
,
346 (CONST BYTE
*)(list
->mimetypes
),
347 strlen(list
->mimetypes
) + 1);
348 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
351 if (list
->extensions
) {
352 res
= RegSetValueExA(clsid_key
, extensions_valuename
, 0, REG_SZ
,
353 (CONST BYTE
*)(list
->extensions
),
354 strlen(list
->extensions
) + 1);
355 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
360 GUID
const * const *format
;
362 res
= RegCreateKeyExW(clsid_key
, formats_keyname
, 0, NULL
, 0,
363 KEY_READ
| KEY_WRITE
, NULL
, &formats_key
, NULL
);
364 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
365 for (format
=list
->formats
; *format
; ++format
)
368 StringFromGUID2(*format
, buf
, 39);
369 res
= RegCreateKeyExW(formats_key
, buf
, 0, NULL
, 0,
370 KEY_READ
| KEY_WRITE
, NULL
, &format_key
, NULL
);
371 if (res
!= ERROR_SUCCESS
) break;
372 RegCloseKey(format_key
);
374 RegCloseKey(formats_key
);
375 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
378 if (list
->patterns
) {
382 res
= RegCreateKeyExW(clsid_key
, patterns_keyname
, 0, NULL
, 0,
383 KEY_READ
| KEY_WRITE
, NULL
, &patterns_key
, NULL
);
384 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
385 for (i
=0; list
->patterns
[i
].length
; i
++)
388 static const WCHAR int_format
[] = {'%','i',0};
389 snprintfW(buf
, 39, int_format
, i
);
390 res
= RegCreateKeyExW(patterns_key
, buf
, 0, NULL
, 0,
391 KEY_READ
| KEY_WRITE
, NULL
, &pattern_key
, NULL
);
392 if (res
!= ERROR_SUCCESS
) break;
393 res
= RegSetValueExA(pattern_key
, length_valuename
, 0, REG_DWORD
,
394 (CONST BYTE
*)(&list
->patterns
[i
].length
), 4);
395 if (res
== ERROR_SUCCESS
)
396 res
= RegSetValueExA(pattern_key
, position_valuename
, 0, REG_DWORD
,
397 (CONST BYTE
*)(&list
->patterns
[i
].position
), 4);
398 if (res
== ERROR_SUCCESS
)
399 res
= RegSetValueExA(pattern_key
, pattern_valuename
, 0, REG_BINARY
,
400 list
->patterns
[i
].pattern
,
401 list
->patterns
[i
].length
);
402 if (res
== ERROR_SUCCESS
)
403 res
= RegSetValueExA(pattern_key
, mask_valuename
, 0, REG_BINARY
,
404 list
->patterns
[i
].mask
,
405 list
->patterns
[i
].length
);
406 if (res
== ERROR_SUCCESS
)
407 res
= RegSetValueExA(pattern_key
, endofstream_valuename
, 0, REG_DWORD
,
408 (CONST BYTE
*)&(list
->patterns
[i
].endofstream
), 4);
409 RegCloseKey(pattern_key
);
411 RegCloseKey(patterns_key
);
412 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
415 error_close_clsid_key
:
416 RegCloseKey(clsid_key
);
419 error_close_coclass_key
:
420 RegCloseKey(instance_key
);
421 RegCloseKey(decoders_key
);
422 RegCloseKey(coclass_key
);
424 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
427 /***********************************************************************
428 * unregister_decoders
430 static HRESULT
unregister_decoders(struct regsvr_decoder
const *list
)
432 LONG res
= ERROR_SUCCESS
;
438 res
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, clsid_keyname
, 0,
439 KEY_READ
| KEY_WRITE
, &coclass_key
);
440 if (res
== ERROR_FILE_NOT_FOUND
) return S_OK
;
442 if (res
== ERROR_SUCCESS
) {
443 StringFromGUID2(&CATID_WICBitmapDecoders
, buf
, 39);
444 res
= RegCreateKeyExW(coclass_key
, buf
, 0, NULL
, 0,
445 KEY_READ
| KEY_WRITE
, NULL
, &decoders_key
, NULL
);
446 if (res
== ERROR_SUCCESS
)
448 res
= RegCreateKeyExW(decoders_key
, instance_keyname
, 0, NULL
, 0,
449 KEY_READ
| KEY_WRITE
, NULL
, &instance_key
, NULL
);
450 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
452 if (res
!= ERROR_SUCCESS
)
453 RegCloseKey(coclass_key
);
455 if (res
!= ERROR_SUCCESS
) goto error_return
;
457 for (; res
== ERROR_SUCCESS
&& list
->clsid
; ++list
) {
458 StringFromGUID2(list
->clsid
, buf
, 39);
460 res
= RegDeleteTreeW(coclass_key
, buf
);
461 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
462 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
464 res
= RegDeleteTreeW(instance_key
, buf
);
465 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
466 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
469 error_close_coclass_key
:
470 RegCloseKey(instance_key
);
471 RegCloseKey(decoders_key
);
472 RegCloseKey(coclass_key
);
474 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
477 /***********************************************************************
478 * register_converters
480 static HRESULT
register_converters(struct regsvr_converter
const *list
)
482 LONG res
= ERROR_SUCCESS
;
488 res
= RegCreateKeyExW(HKEY_CLASSES_ROOT
, clsid_keyname
, 0, NULL
, 0,
489 KEY_READ
| KEY_WRITE
, NULL
, &coclass_key
, NULL
);
490 if (res
== ERROR_SUCCESS
) {
491 StringFromGUID2(&CATID_WICFormatConverters
, buf
, 39);
492 res
= RegCreateKeyExW(coclass_key
, buf
, 0, NULL
, 0,
493 KEY_READ
| KEY_WRITE
, NULL
, &converters_key
, NULL
);
494 if (res
== ERROR_SUCCESS
)
496 res
= RegCreateKeyExW(converters_key
, instance_keyname
, 0, NULL
, 0,
497 KEY_READ
| KEY_WRITE
, NULL
, &instance_key
, NULL
);
498 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
500 if (res
!= ERROR_SUCCESS
)
501 RegCloseKey(coclass_key
);
503 if (res
!= ERROR_SUCCESS
) goto error_return
;
505 for (; res
== ERROR_SUCCESS
&& list
->clsid
; ++list
) {
507 HKEY instance_clsid_key
;
509 StringFromGUID2(list
->clsid
, buf
, 39);
510 res
= RegCreateKeyExW(coclass_key
, buf
, 0, NULL
, 0,
511 KEY_READ
| KEY_WRITE
, NULL
, &clsid_key
, NULL
);
512 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
514 StringFromGUID2(list
->clsid
, buf
, 39);
515 res
= RegCreateKeyExW(instance_key
, buf
, 0, NULL
, 0,
516 KEY_READ
| KEY_WRITE
, NULL
, &instance_clsid_key
, NULL
);
517 if (res
== ERROR_SUCCESS
) {
518 res
= RegSetValueExW(instance_clsid_key
, clsid_valuename
, 0, REG_SZ
,
519 (CONST BYTE
*)(buf
), 78);
520 RegCloseKey(instance_clsid_key
);
522 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
525 res
= RegSetValueExA(clsid_key
, author_valuename
, 0, REG_SZ
,
526 (CONST BYTE
*)(list
->author
),
527 strlen(list
->author
) + 1);
528 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
531 if (list
->friendlyname
) {
532 res
= RegSetValueExA(clsid_key
, friendlyname_valuename
, 0, REG_SZ
,
533 (CONST BYTE
*)(list
->friendlyname
),
534 strlen(list
->friendlyname
) + 1);
535 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
539 StringFromGUID2(list
->vendor
, buf
, 39);
540 res
= RegSetValueExW(clsid_key
, vendor_valuename
, 0, REG_SZ
,
541 (CONST BYTE
*)(buf
), 78);
542 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
546 res
= RegSetValueExA(clsid_key
, version_valuename
, 0, REG_SZ
,
547 (CONST BYTE
*)(list
->version
),
548 strlen(list
->version
) + 1);
549 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
554 GUID
const * const *format
;
556 res
= RegCreateKeyExW(clsid_key
, pixelformats_keyname
, 0, NULL
, 0,
557 KEY_READ
| KEY_WRITE
, NULL
, &formats_key
, NULL
);
558 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
559 for (format
=list
->formats
; *format
; ++format
)
562 StringFromGUID2(*format
, buf
, 39);
563 res
= RegCreateKeyExW(formats_key
, buf
, 0, NULL
, 0,
564 KEY_READ
| KEY_WRITE
, NULL
, &format_key
, NULL
);
565 if (res
!= ERROR_SUCCESS
) break;
566 RegCloseKey(format_key
);
568 RegCloseKey(formats_key
);
569 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
572 error_close_clsid_key
:
573 RegCloseKey(clsid_key
);
576 error_close_coclass_key
:
577 RegCloseKey(instance_key
);
578 RegCloseKey(converters_key
);
579 RegCloseKey(coclass_key
);
581 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
584 /***********************************************************************
585 * unregister_converters
587 static HRESULT
unregister_converters(struct regsvr_converter
const *list
)
589 LONG res
= ERROR_SUCCESS
;
595 res
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, clsid_keyname
, 0,
596 KEY_READ
| KEY_WRITE
, &coclass_key
);
597 if (res
== ERROR_FILE_NOT_FOUND
) return S_OK
;
599 if (res
== ERROR_SUCCESS
) {
600 StringFromGUID2(&CATID_WICFormatConverters
, buf
, 39);
601 res
= RegCreateKeyExW(coclass_key
, buf
, 0, NULL
, 0,
602 KEY_READ
| KEY_WRITE
, NULL
, &converters_key
, NULL
);
603 if (res
== ERROR_SUCCESS
)
605 res
= RegCreateKeyExW(converters_key
, instance_keyname
, 0, NULL
, 0,
606 KEY_READ
| KEY_WRITE
, NULL
, &instance_key
, NULL
);
607 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
609 if (res
!= ERROR_SUCCESS
)
610 RegCloseKey(coclass_key
);
612 if (res
!= ERROR_SUCCESS
) goto error_return
;
614 for (; res
== ERROR_SUCCESS
&& list
->clsid
; ++list
) {
615 StringFromGUID2(list
->clsid
, buf
, 39);
617 res
= RegDeleteTreeW(coclass_key
, buf
);
618 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
619 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
621 res
= RegDeleteTreeW(instance_key
, buf
);
622 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
623 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
626 error_close_coclass_key
:
627 RegCloseKey(instance_key
);
628 RegCloseKey(converters_key
);
629 RegCloseKey(coclass_key
);
631 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
634 /***********************************************************************
635 * register_key_defvalueW
637 static LONG
register_key_defvalueW(
645 res
= RegCreateKeyExW(base
, name
, 0, NULL
, 0,
646 KEY_READ
| KEY_WRITE
, NULL
, &key
, NULL
);
647 if (res
!= ERROR_SUCCESS
) return res
;
648 res
= RegSetValueExW(key
, NULL
, 0, REG_SZ
, (CONST BYTE
*)value
,
649 (lstrlenW(value
) + 1) * sizeof(WCHAR
));
654 /***********************************************************************
655 * register_key_defvalueA
657 static LONG
register_key_defvalueA(
665 res
= RegCreateKeyExW(base
, name
, 0, NULL
, 0,
666 KEY_READ
| KEY_WRITE
, NULL
, &key
, NULL
);
667 if (res
!= ERROR_SUCCESS
) return res
;
668 res
= RegSetValueExA(key
, NULL
, 0, REG_SZ
, (CONST BYTE
*)value
,
669 lstrlenA(value
) + 1);
674 /***********************************************************************
677 static LONG
register_progid(
680 char const *curver_progid
,
687 res
= RegCreateKeyExA(HKEY_CLASSES_ROOT
, progid
, 0,
688 NULL
, 0, KEY_READ
| KEY_WRITE
, NULL
,
690 if (res
!= ERROR_SUCCESS
) return res
;
693 res
= RegSetValueExA(progid_key
, NULL
, 0, REG_SZ
,
694 (CONST BYTE
*)name
, strlen(name
) + 1);
695 if (res
!= ERROR_SUCCESS
) goto error_close_progid_key
;
699 res
= register_key_defvalueW(progid_key
, clsid_keyname
, clsid
);
700 if (res
!= ERROR_SUCCESS
) goto error_close_progid_key
;
704 res
= register_key_defvalueA(progid_key
, curver_keyname
,
706 if (res
!= ERROR_SUCCESS
) goto error_close_progid_key
;
712 res
= RegCreateKeyExA(progid_key
, extra
, 0,
713 NULL
, 0, KEY_READ
| KEY_WRITE
, NULL
,
715 if (res
== ERROR_SUCCESS
)
716 RegCloseKey(extra_key
);
719 error_close_progid_key
:
720 RegCloseKey(progid_key
);
724 /***********************************************************************
727 static struct regsvr_coclass
const coclass_list
[] = {
728 { &CLSID_WICImagingFactory
,
729 "WIC Imaging Factory",
734 { &CLSID_WICBmpDecoder
,
740 { &CLSID_WICPngDecoder
,
746 { &CLSID_WICPngEncoder
,
752 { &CLSID_WICBmpEncoder
,
758 { &CLSID_WICGifDecoder
,
764 { &CLSID_WICIcoDecoder
,
770 { &CLSID_WICJpegDecoder
,
776 { &CLSID_WICTiffDecoder
,
783 &CLSID_WICIcnsEncoder
,
789 { &CLSID_WICDefaultFormatConverter
,
790 "WIC Default Format Converter",
795 { NULL
} /* list terminator */
798 /***********************************************************************
801 static const BYTE mask_all
[] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
803 static const BYTE bmp_magic
[] = {0x42,0x4d};
805 static GUID
const * const bmp_formats
[] = {
806 &GUID_WICPixelFormat1bppIndexed
,
807 &GUID_WICPixelFormat2bppIndexed
,
808 &GUID_WICPixelFormat4bppIndexed
,
809 &GUID_WICPixelFormat8bppIndexed
,
810 &GUID_WICPixelFormat16bppBGR555
,
811 &GUID_WICPixelFormat16bppBGR565
,
812 &GUID_WICPixelFormat24bppBGR
,
813 &GUID_WICPixelFormat32bppBGR
,
814 &GUID_WICPixelFormat32bppBGRA
,
818 static struct decoder_pattern
const bmp_patterns
[] = {
819 {2,0,bmp_magic
,mask_all
,0},
823 static const BYTE gif87a_magic
[6] = "GIF87a";
824 static const BYTE gif89a_magic
[6] = "GIF89a";
826 static GUID
const * const gif_formats
[] = {
827 &GUID_WICPixelFormat8bppIndexed
,
831 static struct decoder_pattern
const gif_patterns
[] = {
832 {6,0,gif87a_magic
,mask_all
,0},
833 {6,0,gif89a_magic
,mask_all
,0},
837 static const BYTE ico_magic
[] = {00,00,01,00};
839 static GUID
const * const ico_formats
[] = {
840 &GUID_WICPixelFormat32bppBGRA
,
844 static struct decoder_pattern
const ico_patterns
[] = {
845 {4,0,ico_magic
,mask_all
,0},
849 static const BYTE jpeg_magic
[] = {0xff, 0xd8, 0xff, 0xe0};
851 static GUID
const * const jpeg_formats
[] = {
852 &GUID_WICPixelFormat24bppBGR
,
853 &GUID_WICPixelFormat8bppGray
,
857 static struct decoder_pattern
const jpeg_patterns
[] = {
858 {4,0,jpeg_magic
,mask_all
,0},
862 static const BYTE png_magic
[] = {137,80,78,71,13,10,26,10};
864 static GUID
const * const png_formats
[] = {
865 &GUID_WICPixelFormatBlackWhite
,
866 &GUID_WICPixelFormat2bppGray
,
867 &GUID_WICPixelFormat4bppGray
,
868 &GUID_WICPixelFormat8bppGray
,
869 &GUID_WICPixelFormat16bppGray
,
870 &GUID_WICPixelFormat32bppBGRA
,
871 &GUID_WICPixelFormat64bppRGBA
,
872 &GUID_WICPixelFormat1bppIndexed
,
873 &GUID_WICPixelFormat2bppIndexed
,
874 &GUID_WICPixelFormat4bppIndexed
,
875 &GUID_WICPixelFormat8bppIndexed
,
876 &GUID_WICPixelFormat24bppBGR
,
877 &GUID_WICPixelFormat48bppRGB
,
881 static struct decoder_pattern
const png_patterns
[] = {
882 {8,0,png_magic
,mask_all
,0},
886 static const BYTE tiff_magic_le
[] = {0x49,0x49,42,0};
887 static const BYTE tiff_magic_be
[] = {0x4d,0x4d,0,42};
889 static GUID
const * const tiff_formats
[] = {
890 &GUID_WICPixelFormatBlackWhite
,
891 &GUID_WICPixelFormat4bppGray
,
892 &GUID_WICPixelFormat8bppGray
,
893 &GUID_WICPixelFormat4bppIndexed
,
894 &GUID_WICPixelFormat8bppIndexed
,
895 &GUID_WICPixelFormat32bppBGR
,
896 &GUID_WICPixelFormat32bppBGRA
,
897 &GUID_WICPixelFormat32bppPBGRA
,
898 &GUID_WICPixelFormat48bppRGB
,
902 static struct decoder_pattern
const tiff_patterns
[] = {
903 {4,0,tiff_magic_le
,mask_all
,0},
904 {4,0,tiff_magic_be
,mask_all
,0},
908 static struct regsvr_decoder
const decoder_list
[] = {
909 { &CLSID_WICBmpDecoder
,
913 &GUID_VendorMicrosoft
,
919 { &CLSID_WICGifDecoder
,
923 &GUID_VendorMicrosoft
,
929 { &CLSID_WICIcoDecoder
,
933 &GUID_VendorMicrosoft
,
934 "image/vnd.microsoft.icon",
939 { &CLSID_WICJpegDecoder
,
943 &GUID_VendorMicrosoft
,
949 { &CLSID_WICPngDecoder
,
953 &GUID_VendorMicrosoft
,
959 { &CLSID_WICTiffDecoder
,
963 &GUID_VendorMicrosoft
,
969 { NULL
} /* list terminator */
972 static GUID
const * const converter_formats
[] = {
973 &GUID_WICPixelFormat1bppIndexed
,
974 &GUID_WICPixelFormat2bppIndexed
,
975 &GUID_WICPixelFormat4bppIndexed
,
976 &GUID_WICPixelFormat8bppIndexed
,
977 &GUID_WICPixelFormatBlackWhite
,
978 &GUID_WICPixelFormat2bppGray
,
979 &GUID_WICPixelFormat4bppGray
,
980 &GUID_WICPixelFormat8bppGray
,
981 &GUID_WICPixelFormat16bppGray
,
982 &GUID_WICPixelFormat16bppBGR555
,
983 &GUID_WICPixelFormat16bppBGR565
,
984 &GUID_WICPixelFormat24bppBGR
,
985 &GUID_WICPixelFormat32bppBGR
,
986 &GUID_WICPixelFormat32bppBGRA
,
987 &GUID_WICPixelFormat48bppRGB
,
988 &GUID_WICPixelFormat64bppRGBA
,
992 static struct regsvr_converter
const converter_list
[] = {
993 { &CLSID_WICDefaultFormatConverter
,
995 "Default Pixel Format Converter",
997 &GUID_VendorMicrosoft
,
1000 { NULL
} /* list terminator */
1003 HRESULT WINAPI
DllRegisterServer(void)
1009 hr
= register_coclasses(coclass_list
);
1011 register_decoders(decoder_list
);
1013 register_converters(converter_list
);
1017 HRESULT WINAPI
DllUnregisterServer(void)
1023 hr
= unregister_coclasses(coclass_list
);
1025 unregister_decoders(decoder_list
);
1027 unregister_converters(converter_list
);