aba6c0a0ee63637d75f7cf25bcd8588f2dbbabcf
[reactos.git] / dll / win32 / windowscodecs / regsvr.c
1 /*
2 * Copyright 2009 Vincent Povirk for CodeWeavers
3 *
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.
8 *
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.
13 *
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
17 */
18
19 #include "wincodecs_private.h"
20
21 #include <shlwapi.h>
22
23 /***********************************************************************
24 * interface for self-registering
25 */
26 struct decoder_pattern
27 {
28 DWORD length; /* 0 for end of list */
29 DWORD position;
30 const BYTE *pattern;
31 const BYTE *mask;
32 DWORD endofstream;
33 };
34
35 struct regsvr_decoder
36 {
37 CLSID const *clsid; /* NULL for end of list */
38 LPCSTR author;
39 LPCSTR friendlyname;
40 LPCSTR version;
41 GUID const *vendor;
42 GUID const *container_format;
43 LPCSTR mimetypes;
44 LPCSTR extensions;
45 GUID const * const *formats;
46 const struct decoder_pattern *patterns;
47 };
48
49 static HRESULT register_decoders(struct regsvr_decoder const *list);
50 static HRESULT unregister_decoders(struct regsvr_decoder const *list);
51
52 struct regsvr_encoder
53 {
54 CLSID const *clsid; /* NULL for end of list */
55 LPCSTR author;
56 LPCSTR friendlyname;
57 LPCSTR version;
58 GUID const *vendor;
59 GUID const *container_format;
60 LPCSTR mimetypes;
61 LPCSTR extensions;
62 GUID const * const *formats;
63 };
64
65 static HRESULT register_encoders(struct regsvr_encoder const *list);
66 static HRESULT unregister_encoders(struct regsvr_encoder const *list);
67
68 struct regsvr_converter
69 {
70 CLSID const *clsid; /* NULL for end of list */
71 LPCSTR author;
72 LPCSTR friendlyname;
73 LPCSTR version;
74 GUID const *vendor;
75 GUID const * const *formats;
76 };
77
78 static HRESULT register_converters(struct regsvr_converter const *list);
79 static HRESULT unregister_converters(struct regsvr_converter const *list);
80
81 struct metadata_pattern
82 {
83 DWORD position;
84 DWORD length;
85 const BYTE *pattern;
86 const BYTE *mask;
87 DWORD data_offset;
88 };
89
90 struct reader_containers
91 {
92 GUID const *format;
93 const struct metadata_pattern *patterns;
94 };
95
96 struct regsvr_metadatareader
97 {
98 CLSID const *clsid; /* NULL for end of list */
99 LPCSTR author;
100 LPCSTR friendlyname;
101 LPCSTR version;
102 LPCSTR specversion;
103 GUID const *vendor;
104 GUID const *metadata_format;
105 DWORD requires_fullstream;
106 DWORD supports_padding;
107 DWORD requires_fixedsize;
108 const struct reader_containers *containers;
109 };
110
111 static HRESULT register_metadatareaders(struct regsvr_metadatareader const *list);
112 static HRESULT unregister_metadatareaders(struct regsvr_metadatareader const *list);
113
114 struct regsvr_pixelformat
115 {
116 CLSID const *clsid; /* NULL for end of list */
117 LPCSTR author;
118 LPCSTR friendlyname;
119 LPCSTR version;
120 GUID const *vendor;
121 UINT bitsperpixel;
122 UINT channelcount;
123 BYTE const * const *channelmasks;
124 WICPixelFormatNumericRepresentation numericrepresentation;
125 UINT supportsalpha;
126 };
127
128 static HRESULT register_pixelformats(struct regsvr_pixelformat const *list);
129 static HRESULT unregister_pixelformats(struct regsvr_pixelformat const *list);
130
131 /***********************************************************************
132 * static string constants
133 */
134 static const WCHAR clsid_keyname[] = {
135 'C', 'L', 'S', 'I', 'D', 0 };
136 static const char author_valuename[] = "Author";
137 static const char friendlyname_valuename[] = "FriendlyName";
138 static const WCHAR vendor_valuename[] = {'V','e','n','d','o','r',0};
139 static const WCHAR containerformat_valuename[] = {'C','o','n','t','a','i','n','e','r','F','o','r','m','a','t',0};
140 static const char version_valuename[] = "Version";
141 static const char mimetypes_valuename[] = "MimeTypes";
142 static const char extensions_valuename[] = "FileExtensions";
143 static const WCHAR formats_keyname[] = {'F','o','r','m','a','t','s',0};
144 static const WCHAR patterns_keyname[] = {'P','a','t','t','e','r','n','s',0};
145 static const WCHAR instance_keyname[] = {'I','n','s','t','a','n','c','e',0};
146 static const WCHAR clsid_valuename[] = {'C','L','S','I','D',0};
147 static const char length_valuename[] = "Length";
148 static const char position_valuename[] = "Position";
149 static const char pattern_valuename[] = "Pattern";
150 static const char mask_valuename[] = "Mask";
151 static const char endofstream_valuename[] = "EndOfStream";
152 static const WCHAR pixelformats_keyname[] = {'P','i','x','e','l','F','o','r','m','a','t','s',0};
153 static const WCHAR metadataformat_valuename[] = {'M','e','t','a','d','a','t','a','F','o','r','m','a','t',0};
154 static const char specversion_valuename[] = "SpecVersion";
155 static const char requiresfullstream_valuename[] = "RequiresFullStream";
156 static const char supportspadding_valuename[] = "SupportsPadding";
157 static const char requiresfixedsize_valuename[] = "FixedSize";
158 static const WCHAR containers_keyname[] = {'C','o','n','t','a','i','n','e','r','s',0};
159 static const char dataoffset_valuename[] = "DataOffset";
160 static const char bitsperpixel_valuename[] = "BitLength";
161 static const char channelcount_valuename[] = "ChannelCount";
162 static const char numericrepresentation_valuename[] = "NumericRepresentation";
163 static const char supportstransparency_valuename[] = "SupportsTransparency";
164 static const WCHAR channelmasks_keyname[] = {'C','h','a','n','n','e','l','M','a','s','k','s',0};
165
166 /***********************************************************************
167 * register_decoders
168 */
169 static HRESULT register_decoders(struct regsvr_decoder const *list)
170 {
171 LONG res = ERROR_SUCCESS;
172 HKEY coclass_key;
173 WCHAR buf[39];
174 HKEY decoders_key;
175 HKEY instance_key;
176
177 res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0,
178 KEY_READ | KEY_WRITE, NULL, &coclass_key, NULL);
179 if (res == ERROR_SUCCESS) {
180 StringFromGUID2(&CATID_WICBitmapDecoders, buf, 39);
181 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
182 KEY_READ | KEY_WRITE, NULL, &decoders_key, NULL);
183 if (res == ERROR_SUCCESS)
184 {
185 res = RegCreateKeyExW(decoders_key, instance_keyname, 0, NULL, 0,
186 KEY_READ | KEY_WRITE, NULL, &instance_key, NULL);
187 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
188 }
189 if (res != ERROR_SUCCESS)
190 RegCloseKey(coclass_key);
191 }
192 if (res != ERROR_SUCCESS) goto error_return;
193
194 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
195 HKEY clsid_key;
196 HKEY instance_clsid_key;
197
198 StringFromGUID2(list->clsid, buf, 39);
199 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
200 KEY_READ | KEY_WRITE, NULL, &clsid_key, NULL);
201 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
202
203 StringFromGUID2(list->clsid, buf, 39);
204 res = RegCreateKeyExW(instance_key, buf, 0, NULL, 0,
205 KEY_READ | KEY_WRITE, NULL, &instance_clsid_key, NULL);
206 if (res == ERROR_SUCCESS) {
207 res = RegSetValueExW(instance_clsid_key, clsid_valuename, 0, REG_SZ,
208 (const BYTE*)buf, 78);
209 RegCloseKey(instance_clsid_key);
210 }
211 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
212
213 if (list->author) {
214 res = RegSetValueExA(clsid_key, author_valuename, 0, REG_SZ,
215 (const BYTE*)list->author,
216 strlen(list->author) + 1);
217 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
218 }
219
220 if (list->friendlyname) {
221 res = RegSetValueExA(clsid_key, friendlyname_valuename, 0, REG_SZ,
222 (const BYTE*)list->friendlyname,
223 strlen(list->friendlyname) + 1);
224 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
225 }
226
227 if (list->vendor) {
228 StringFromGUID2(list->vendor, buf, 39);
229 res = RegSetValueExW(clsid_key, vendor_valuename, 0, REG_SZ,
230 (const BYTE*)buf, 78);
231 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
232 }
233
234 if (list->container_format) {
235 StringFromGUID2(list->container_format, buf, 39);
236 res = RegSetValueExW(clsid_key, containerformat_valuename, 0, REG_SZ,
237 (const BYTE*)buf, 78);
238 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
239 }
240
241 if (list->version) {
242 res = RegSetValueExA(clsid_key, version_valuename, 0, REG_SZ,
243 (const BYTE*)list->version,
244 strlen(list->version) + 1);
245 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
246 }
247
248 if (list->mimetypes) {
249 res = RegSetValueExA(clsid_key, mimetypes_valuename, 0, REG_SZ,
250 (const BYTE*)list->mimetypes,
251 strlen(list->mimetypes) + 1);
252 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
253 }
254
255 if (list->extensions) {
256 res = RegSetValueExA(clsid_key, extensions_valuename, 0, REG_SZ,
257 (const BYTE*)list->extensions,
258 strlen(list->extensions) + 1);
259 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
260 }
261
262 if (list->formats) {
263 HKEY formats_key;
264 GUID const * const *format;
265
266 res = RegCreateKeyExW(clsid_key, formats_keyname, 0, NULL, 0,
267 KEY_READ | KEY_WRITE, NULL, &formats_key, NULL);
268 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
269 for (format=list->formats; *format; ++format)
270 {
271 HKEY format_key;
272 StringFromGUID2(*format, buf, 39);
273 res = RegCreateKeyExW(formats_key, buf, 0, NULL, 0,
274 KEY_READ | KEY_WRITE, NULL, &format_key, NULL);
275 if (res != ERROR_SUCCESS) break;
276 RegCloseKey(format_key);
277 }
278 RegCloseKey(formats_key);
279 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
280 }
281
282 if (list->patterns) {
283 HKEY patterns_key;
284 int i;
285
286 res = RegCreateKeyExW(clsid_key, patterns_keyname, 0, NULL, 0,
287 KEY_READ | KEY_WRITE, NULL, &patterns_key, NULL);
288 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
289 for (i=0; list->patterns[i].length; i++)
290 {
291 HKEY pattern_key;
292 static const WCHAR int_format[] = {'%','i',0};
293 snprintfW(buf, 39, int_format, i);
294 res = RegCreateKeyExW(patterns_key, buf, 0, NULL, 0,
295 KEY_READ | KEY_WRITE, NULL, &pattern_key, NULL);
296 if (res != ERROR_SUCCESS) break;
297 res = RegSetValueExA(pattern_key, length_valuename, 0, REG_DWORD,
298 (const BYTE*)&list->patterns[i].length, 4);
299 if (res == ERROR_SUCCESS)
300 res = RegSetValueExA(pattern_key, position_valuename, 0, REG_DWORD,
301 (const BYTE*)&list->patterns[i].position, 4);
302 if (res == ERROR_SUCCESS)
303 res = RegSetValueExA(pattern_key, pattern_valuename, 0, REG_BINARY,
304 list->patterns[i].pattern,
305 list->patterns[i].length);
306 if (res == ERROR_SUCCESS)
307 res = RegSetValueExA(pattern_key, mask_valuename, 0, REG_BINARY,
308 list->patterns[i].mask,
309 list->patterns[i].length);
310 if (res == ERROR_SUCCESS)
311 res = RegSetValueExA(pattern_key, endofstream_valuename, 0, REG_DWORD,
312 (const BYTE*)&list->patterns[i].endofstream, 4);
313 RegCloseKey(pattern_key);
314 }
315 RegCloseKey(patterns_key);
316 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
317 }
318
319 error_close_clsid_key:
320 RegCloseKey(clsid_key);
321 }
322
323 error_close_coclass_key:
324 RegCloseKey(instance_key);
325 RegCloseKey(decoders_key);
326 RegCloseKey(coclass_key);
327 error_return:
328 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
329 }
330
331 /***********************************************************************
332 * unregister_decoders
333 */
334 static HRESULT unregister_decoders(struct regsvr_decoder const *list)
335 {
336 LONG res = ERROR_SUCCESS;
337 HKEY coclass_key;
338 WCHAR buf[39];
339 HKEY decoders_key;
340 HKEY instance_key;
341
342 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0,
343 KEY_READ | KEY_WRITE, &coclass_key);
344 if (res == ERROR_FILE_NOT_FOUND) return S_OK;
345
346 if (res == ERROR_SUCCESS) {
347 StringFromGUID2(&CATID_WICBitmapDecoders, buf, 39);
348 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
349 KEY_READ | KEY_WRITE, NULL, &decoders_key, NULL);
350 if (res == ERROR_SUCCESS)
351 {
352 res = RegCreateKeyExW(decoders_key, instance_keyname, 0, NULL, 0,
353 KEY_READ | KEY_WRITE, NULL, &instance_key, NULL);
354 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
355 }
356 if (res != ERROR_SUCCESS)
357 RegCloseKey(coclass_key);
358 }
359 if (res != ERROR_SUCCESS) goto error_return;
360
361 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
362 StringFromGUID2(list->clsid, buf, 39);
363
364 res = RegDeleteTreeW(coclass_key, buf);
365 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
366 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
367
368 res = RegDeleteTreeW(instance_key, buf);
369 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
370 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
371 }
372
373 error_close_coclass_key:
374 RegCloseKey(instance_key);
375 RegCloseKey(decoders_key);
376 RegCloseKey(coclass_key);
377 error_return:
378 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
379 }
380
381 /***********************************************************************
382 * register_encoders
383 */
384 static HRESULT register_encoders(struct regsvr_encoder const *list)
385 {
386 LONG res = ERROR_SUCCESS;
387 HKEY coclass_key;
388 WCHAR buf[39];
389 HKEY encoders_key;
390 HKEY instance_key;
391
392 res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0,
393 KEY_READ | KEY_WRITE, NULL, &coclass_key, NULL);
394 if (res == ERROR_SUCCESS) {
395 StringFromGUID2(&CATID_WICBitmapEncoders, buf, 39);
396 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
397 KEY_READ | KEY_WRITE, NULL, &encoders_key, NULL);
398 if (res == ERROR_SUCCESS)
399 {
400 res = RegCreateKeyExW(encoders_key, instance_keyname, 0, NULL, 0,
401 KEY_READ | KEY_WRITE, NULL, &instance_key, NULL);
402 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
403 }
404 if (res != ERROR_SUCCESS)
405 RegCloseKey(coclass_key);
406 }
407 if (res != ERROR_SUCCESS) goto error_return;
408
409 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
410 HKEY clsid_key;
411 HKEY instance_clsid_key;
412
413 StringFromGUID2(list->clsid, buf, 39);
414 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
415 KEY_READ | KEY_WRITE, NULL, &clsid_key, NULL);
416 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
417
418 StringFromGUID2(list->clsid, buf, 39);
419 res = RegCreateKeyExW(instance_key, buf, 0, NULL, 0,
420 KEY_READ | KEY_WRITE, NULL, &instance_clsid_key, NULL);
421 if (res == ERROR_SUCCESS) {
422 res = RegSetValueExW(instance_clsid_key, clsid_valuename, 0, REG_SZ,
423 (const BYTE*)buf, 78);
424 RegCloseKey(instance_clsid_key);
425 }
426 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
427
428 if (list->author) {
429 res = RegSetValueExA(clsid_key, author_valuename, 0, REG_SZ,
430 (const BYTE*)list->author,
431 strlen(list->author) + 1);
432 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
433 }
434
435 if (list->friendlyname) {
436 res = RegSetValueExA(clsid_key, friendlyname_valuename, 0, REG_SZ,
437 (const BYTE*)list->friendlyname,
438 strlen(list->friendlyname) + 1);
439 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
440 }
441
442 if (list->vendor) {
443 StringFromGUID2(list->vendor, buf, 39);
444 res = RegSetValueExW(clsid_key, vendor_valuename, 0, REG_SZ,
445 (const BYTE*)buf, 78);
446 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
447 }
448
449 if (list->container_format) {
450 StringFromGUID2(list->container_format, buf, 39);
451 res = RegSetValueExW(clsid_key, containerformat_valuename, 0, REG_SZ,
452 (const BYTE*)buf, 78);
453 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
454 }
455
456 if (list->version) {
457 res = RegSetValueExA(clsid_key, version_valuename, 0, REG_SZ,
458 (const BYTE*)list->version,
459 strlen(list->version) + 1);
460 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
461 }
462
463 if (list->mimetypes) {
464 res = RegSetValueExA(clsid_key, mimetypes_valuename, 0, REG_SZ,
465 (const BYTE*)list->mimetypes,
466 strlen(list->mimetypes) + 1);
467 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
468 }
469
470 if (list->extensions) {
471 res = RegSetValueExA(clsid_key, extensions_valuename, 0, REG_SZ,
472 (const BYTE*)list->extensions,
473 strlen(list->extensions) + 1);
474 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
475 }
476
477 if (list->formats) {
478 HKEY formats_key;
479 GUID const * const *format;
480
481 res = RegCreateKeyExW(clsid_key, formats_keyname, 0, NULL, 0,
482 KEY_READ | KEY_WRITE, NULL, &formats_key, NULL);
483 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
484 for (format=list->formats; *format; ++format)
485 {
486 HKEY format_key;
487 StringFromGUID2(*format, buf, 39);
488 res = RegCreateKeyExW(formats_key, buf, 0, NULL, 0,
489 KEY_READ | KEY_WRITE, NULL, &format_key, NULL);
490 if (res != ERROR_SUCCESS) break;
491 RegCloseKey(format_key);
492 }
493 RegCloseKey(formats_key);
494 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
495 }
496
497 error_close_clsid_key:
498 RegCloseKey(clsid_key);
499 }
500
501 error_close_coclass_key:
502 RegCloseKey(instance_key);
503 RegCloseKey(encoders_key);
504 RegCloseKey(coclass_key);
505 error_return:
506 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
507 }
508
509 /***********************************************************************
510 * unregister_encoders
511 */
512 static HRESULT unregister_encoders(struct regsvr_encoder const *list)
513 {
514 LONG res = ERROR_SUCCESS;
515 HKEY coclass_key;
516 WCHAR buf[39];
517 HKEY encoders_key;
518 HKEY instance_key;
519
520 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0,
521 KEY_READ | KEY_WRITE, &coclass_key);
522 if (res == ERROR_FILE_NOT_FOUND) return S_OK;
523
524 if (res == ERROR_SUCCESS) {
525 StringFromGUID2(&CATID_WICBitmapEncoders, buf, 39);
526 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
527 KEY_READ | KEY_WRITE, NULL, &encoders_key, NULL);
528 if (res == ERROR_SUCCESS)
529 {
530 res = RegCreateKeyExW(encoders_key, instance_keyname, 0, NULL, 0,
531 KEY_READ | KEY_WRITE, NULL, &instance_key, NULL);
532 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
533 }
534 if (res != ERROR_SUCCESS)
535 RegCloseKey(coclass_key);
536 }
537 if (res != ERROR_SUCCESS) goto error_return;
538
539 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
540 StringFromGUID2(list->clsid, buf, 39);
541
542 res = RegDeleteTreeW(coclass_key, buf);
543 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
544 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
545
546 res = RegDeleteTreeW(instance_key, buf);
547 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
548 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
549 }
550
551 error_close_coclass_key:
552 RegCloseKey(instance_key);
553 RegCloseKey(encoders_key);
554 RegCloseKey(coclass_key);
555 error_return:
556 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
557 }
558
559 /***********************************************************************
560 * register_converters
561 */
562 static HRESULT register_converters(struct regsvr_converter const *list)
563 {
564 LONG res = ERROR_SUCCESS;
565 HKEY coclass_key;
566 WCHAR buf[39];
567 HKEY converters_key;
568 HKEY instance_key;
569
570 res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0,
571 KEY_READ | KEY_WRITE, NULL, &coclass_key, NULL);
572 if (res == ERROR_SUCCESS) {
573 StringFromGUID2(&CATID_WICFormatConverters, buf, 39);
574 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
575 KEY_READ | KEY_WRITE, NULL, &converters_key, NULL);
576 if (res == ERROR_SUCCESS)
577 {
578 res = RegCreateKeyExW(converters_key, instance_keyname, 0, NULL, 0,
579 KEY_READ | KEY_WRITE, NULL, &instance_key, NULL);
580 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
581 }
582 if (res != ERROR_SUCCESS)
583 RegCloseKey(coclass_key);
584 }
585 if (res != ERROR_SUCCESS) goto error_return;
586
587 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
588 HKEY clsid_key;
589 HKEY instance_clsid_key;
590
591 StringFromGUID2(list->clsid, buf, 39);
592 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
593 KEY_READ | KEY_WRITE, NULL, &clsid_key, NULL);
594 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
595
596 StringFromGUID2(list->clsid, buf, 39);
597 res = RegCreateKeyExW(instance_key, buf, 0, NULL, 0,
598 KEY_READ | KEY_WRITE, NULL, &instance_clsid_key, NULL);
599 if (res == ERROR_SUCCESS) {
600 res = RegSetValueExW(instance_clsid_key, clsid_valuename, 0, REG_SZ,
601 (const BYTE*)buf, 78);
602 RegCloseKey(instance_clsid_key);
603 }
604 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
605
606 if (list->author) {
607 res = RegSetValueExA(clsid_key, author_valuename, 0, REG_SZ,
608 (const BYTE*)list->author,
609 strlen(list->author) + 1);
610 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
611 }
612
613 if (list->friendlyname) {
614 res = RegSetValueExA(clsid_key, friendlyname_valuename, 0, REG_SZ,
615 (const BYTE*)list->friendlyname,
616 strlen(list->friendlyname) + 1);
617 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
618 }
619
620 if (list->vendor) {
621 StringFromGUID2(list->vendor, buf, 39);
622 res = RegSetValueExW(clsid_key, vendor_valuename, 0, REG_SZ,
623 (const BYTE*)buf, 78);
624 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
625 }
626
627 if (list->version) {
628 res = RegSetValueExA(clsid_key, version_valuename, 0, REG_SZ,
629 (const BYTE*)list->version,
630 strlen(list->version) + 1);
631 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
632 }
633
634 if (list->formats) {
635 HKEY formats_key;
636 GUID const * const *format;
637
638 res = RegCreateKeyExW(clsid_key, pixelformats_keyname, 0, NULL, 0,
639 KEY_READ | KEY_WRITE, NULL, &formats_key, NULL);
640 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
641 for (format=list->formats; *format; ++format)
642 {
643 HKEY format_key;
644 StringFromGUID2(*format, buf, 39);
645 res = RegCreateKeyExW(formats_key, buf, 0, NULL, 0,
646 KEY_READ | KEY_WRITE, NULL, &format_key, NULL);
647 if (res != ERROR_SUCCESS) break;
648 RegCloseKey(format_key);
649 }
650 RegCloseKey(formats_key);
651 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
652 }
653
654 error_close_clsid_key:
655 RegCloseKey(clsid_key);
656 }
657
658 error_close_coclass_key:
659 RegCloseKey(instance_key);
660 RegCloseKey(converters_key);
661 RegCloseKey(coclass_key);
662 error_return:
663 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
664 }
665
666 /***********************************************************************
667 * unregister_converters
668 */
669 static HRESULT unregister_converters(struct regsvr_converter const *list)
670 {
671 LONG res = ERROR_SUCCESS;
672 HKEY coclass_key;
673 WCHAR buf[39];
674 HKEY converters_key;
675 HKEY instance_key;
676
677 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0,
678 KEY_READ | KEY_WRITE, &coclass_key);
679 if (res == ERROR_FILE_NOT_FOUND) return S_OK;
680
681 if (res == ERROR_SUCCESS) {
682 StringFromGUID2(&CATID_WICFormatConverters, buf, 39);
683 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
684 KEY_READ | KEY_WRITE, NULL, &converters_key, NULL);
685 if (res == ERROR_SUCCESS)
686 {
687 res = RegCreateKeyExW(converters_key, instance_keyname, 0, NULL, 0,
688 KEY_READ | KEY_WRITE, NULL, &instance_key, NULL);
689 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
690 }
691 if (res != ERROR_SUCCESS)
692 RegCloseKey(coclass_key);
693 }
694 if (res != ERROR_SUCCESS) goto error_return;
695
696 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
697 StringFromGUID2(list->clsid, buf, 39);
698
699 res = RegDeleteTreeW(coclass_key, buf);
700 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
701 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
702
703 res = RegDeleteTreeW(instance_key, buf);
704 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
705 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
706 }
707
708 error_close_coclass_key:
709 RegCloseKey(instance_key);
710 RegCloseKey(converters_key);
711 RegCloseKey(coclass_key);
712 error_return:
713 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
714 }
715
716 /***********************************************************************
717 * register_metadatareaders
718 */
719 static HRESULT register_metadatareaders(struct regsvr_metadatareader const *list)
720 {
721 LONG res = ERROR_SUCCESS;
722 HKEY coclass_key;
723 WCHAR buf[39];
724 HKEY readers_key;
725 HKEY instance_key;
726
727 res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0,
728 KEY_READ | KEY_WRITE, NULL, &coclass_key, NULL);
729 if (res == ERROR_SUCCESS) {
730 StringFromGUID2(&CATID_WICMetadataReader, buf, 39);
731 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
732 KEY_READ | KEY_WRITE, NULL, &readers_key, NULL);
733 if (res == ERROR_SUCCESS)
734 {
735 res = RegCreateKeyExW(readers_key, instance_keyname, 0, NULL, 0,
736 KEY_READ | KEY_WRITE, NULL, &instance_key, NULL);
737 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
738 }
739 if (res != ERROR_SUCCESS)
740 RegCloseKey(coclass_key);
741 }
742 if (res != ERROR_SUCCESS) goto error_return;
743
744 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
745 HKEY clsid_key;
746 HKEY instance_clsid_key;
747
748 StringFromGUID2(list->clsid, buf, 39);
749 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
750 KEY_READ | KEY_WRITE, NULL, &clsid_key, NULL);
751 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
752
753 StringFromGUID2(list->clsid, buf, 39);
754 res = RegCreateKeyExW(instance_key, buf, 0, NULL, 0,
755 KEY_READ | KEY_WRITE, NULL, &instance_clsid_key, NULL);
756 if (res == ERROR_SUCCESS) {
757 res = RegSetValueExW(instance_clsid_key, clsid_valuename, 0, REG_SZ,
758 (const BYTE*)buf, 78);
759 RegCloseKey(instance_clsid_key);
760 }
761 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
762
763 if (list->author) {
764 res = RegSetValueExA(clsid_key, author_valuename, 0, REG_SZ,
765 (const BYTE*)list->author,
766 strlen(list->author) + 1);
767 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
768 }
769
770 if (list->friendlyname) {
771 res = RegSetValueExA(clsid_key, friendlyname_valuename, 0, REG_SZ,
772 (const BYTE*)list->friendlyname,
773 strlen(list->friendlyname) + 1);
774 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
775 }
776
777 if (list->vendor) {
778 StringFromGUID2(list->vendor, buf, 39);
779 res = RegSetValueExW(clsid_key, vendor_valuename, 0, REG_SZ,
780 (const BYTE*)buf, 78);
781 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
782 }
783
784 if (list->metadata_format) {
785 StringFromGUID2(list->metadata_format, buf, 39);
786 res = RegSetValueExW(clsid_key, metadataformat_valuename, 0, REG_SZ,
787 (const BYTE*)buf, 78);
788 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
789 }
790
791 if (list->version) {
792 res = RegSetValueExA(clsid_key, version_valuename, 0, REG_SZ,
793 (const BYTE*)list->version,
794 strlen(list->version) + 1);
795 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
796 }
797
798 if (list->specversion) {
799 res = RegSetValueExA(clsid_key, specversion_valuename, 0, REG_SZ,
800 (const BYTE*)list->version,
801 strlen(list->version) + 1);
802 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
803 }
804
805 res = RegSetValueExA(clsid_key, requiresfullstream_valuename, 0, REG_DWORD,
806 (const BYTE*)&list->requires_fullstream, 4);
807 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
808
809 res = RegSetValueExA(clsid_key, supportspadding_valuename, 0, REG_DWORD,
810 (const BYTE*)&list->supports_padding, 4);
811 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
812
813 if (list->requires_fixedsize) {
814 res = RegSetValueExA(clsid_key, requiresfixedsize_valuename, 0, REG_DWORD,
815 (const BYTE*)&list->requires_fixedsize, 4);
816 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
817 }
818
819 if (list->containers) {
820 HKEY containers_key;
821 const struct reader_containers *container;
822
823 res = RegCreateKeyExW(clsid_key, containers_keyname, 0, NULL, 0,
824 KEY_READ | KEY_WRITE, NULL, &containers_key, NULL);
825 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
826 for (container=list->containers; container->format; ++container)
827 {
828 HKEY format_key;
829 int i;
830 StringFromGUID2(container->format, buf, 39);
831 res = RegCreateKeyExW(containers_key, buf, 0, NULL, 0,
832 KEY_READ | KEY_WRITE, NULL, &format_key, NULL);
833 if (res != ERROR_SUCCESS) break;
834
835 for (i=0; container->patterns[i].length; i++)
836 {
837 HKEY pattern_key;
838 static const WCHAR int_format[] = {'%','i',0};
839 snprintfW(buf, 39, int_format, i);
840 res = RegCreateKeyExW(format_key, buf, 0, NULL, 0,
841 KEY_READ | KEY_WRITE, NULL, &pattern_key, NULL);
842 if (res != ERROR_SUCCESS) break;
843 res = RegSetValueExA(pattern_key, position_valuename, 0, REG_DWORD,
844 (const BYTE*)&container->patterns[i].position, 4);
845 if (res == ERROR_SUCCESS)
846 res = RegSetValueExA(pattern_key, pattern_valuename, 0, REG_BINARY,
847 container->patterns[i].pattern,
848 container->patterns[i].length);
849 if (res == ERROR_SUCCESS)
850 res = RegSetValueExA(pattern_key, mask_valuename, 0, REG_BINARY,
851 container->patterns[i].mask,
852 container->patterns[i].length);
853 if (res == ERROR_SUCCESS && container->patterns[i].data_offset)
854 res = RegSetValueExA(pattern_key, dataoffset_valuename, 0, REG_DWORD,
855 (const BYTE*)&container->patterns[i].data_offset, 4);
856 RegCloseKey(pattern_key);
857 }
858
859 RegCloseKey(format_key);
860 }
861 RegCloseKey(containers_key);
862 }
863
864 error_close_clsid_key:
865 RegCloseKey(clsid_key);
866 }
867
868 error_close_coclass_key:
869 RegCloseKey(instance_key);
870 RegCloseKey(readers_key);
871 RegCloseKey(coclass_key);
872 error_return:
873 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
874 }
875
876 /***********************************************************************
877 * unregister_metadatareaders
878 */
879 static HRESULT unregister_metadatareaders(struct regsvr_metadatareader const *list)
880 {
881 LONG res = ERROR_SUCCESS;
882 HKEY coclass_key;
883 WCHAR buf[39];
884 HKEY readers_key;
885 HKEY instance_key;
886
887 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0,
888 KEY_READ | KEY_WRITE, &coclass_key);
889 if (res == ERROR_FILE_NOT_FOUND) return S_OK;
890
891 if (res == ERROR_SUCCESS) {
892 StringFromGUID2(&CATID_WICMetadataReader, buf, 39);
893 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
894 KEY_READ | KEY_WRITE, NULL, &readers_key, NULL);
895 if (res == ERROR_SUCCESS)
896 {
897 res = RegCreateKeyExW(readers_key, instance_keyname, 0, NULL, 0,
898 KEY_READ | KEY_WRITE, NULL, &instance_key, NULL);
899 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
900 }
901 if (res != ERROR_SUCCESS)
902 RegCloseKey(coclass_key);
903 }
904 if (res != ERROR_SUCCESS) goto error_return;
905
906 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
907 StringFromGUID2(list->clsid, buf, 39);
908
909 res = RegDeleteTreeW(coclass_key, buf);
910 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
911 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
912
913 res = RegDeleteTreeW(instance_key, buf);
914 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
915 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
916 }
917
918 error_close_coclass_key:
919 RegCloseKey(instance_key);
920 RegCloseKey(readers_key);
921 RegCloseKey(coclass_key);
922 error_return:
923 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
924 }
925
926 /***********************************************************************
927 * register_pixelformats
928 */
929 static HRESULT register_pixelformats(struct regsvr_pixelformat const *list)
930 {
931 LONG res = ERROR_SUCCESS;
932 HKEY coclass_key;
933 WCHAR buf[39];
934 HKEY formats_key;
935 HKEY instance_key;
936
937 res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0,
938 KEY_READ | KEY_WRITE, NULL, &coclass_key, NULL);
939 if (res == ERROR_SUCCESS) {
940 StringFromGUID2(&CATID_WICPixelFormats, buf, 39);
941 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
942 KEY_READ | KEY_WRITE, NULL, &formats_key, NULL);
943 if (res == ERROR_SUCCESS)
944 {
945 res = RegCreateKeyExW(formats_key, instance_keyname, 0, NULL, 0,
946 KEY_READ | KEY_WRITE, NULL, &instance_key, NULL);
947 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
948 }
949 if (res != ERROR_SUCCESS)
950 RegCloseKey(coclass_key);
951 }
952 if (res != ERROR_SUCCESS) goto error_return;
953
954 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
955 HKEY clsid_key;
956 HKEY instance_clsid_key;
957
958 StringFromGUID2(list->clsid, buf, 39);
959 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
960 KEY_READ | KEY_WRITE, NULL, &clsid_key, NULL);
961 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
962
963 StringFromGUID2(list->clsid, buf, 39);
964 res = RegCreateKeyExW(instance_key, buf, 0, NULL, 0,
965 KEY_READ | KEY_WRITE, NULL, &instance_clsid_key, NULL);
966 if (res == ERROR_SUCCESS) {
967 res = RegSetValueExW(instance_clsid_key, clsid_valuename, 0, REG_SZ,
968 (const BYTE*)buf, 78);
969 RegCloseKey(instance_clsid_key);
970 }
971 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
972
973 if (list->author) {
974 res = RegSetValueExA(clsid_key, author_valuename, 0, REG_SZ,
975 (const BYTE*)list->author,
976 strlen(list->author) + 1);
977 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
978 }
979
980 if (list->friendlyname) {
981 res = RegSetValueExA(clsid_key, friendlyname_valuename, 0, REG_SZ,
982 (const BYTE*)list->friendlyname,
983 strlen(list->friendlyname) + 1);
984 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
985 }
986
987 if (list->vendor) {
988 StringFromGUID2(list->vendor, buf, 39);
989 res = RegSetValueExW(clsid_key, vendor_valuename, 0, REG_SZ,
990 (const BYTE*)buf, 78);
991 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
992 }
993
994 if (list->version) {
995 res = RegSetValueExA(clsid_key, version_valuename, 0, REG_SZ,
996 (const BYTE*)list->version,
997 strlen(list->version) + 1);
998 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
999 }
1000
1001 res = RegSetValueExA(clsid_key, bitsperpixel_valuename, 0, REG_DWORD,
1002 (const BYTE*)&list->bitsperpixel, 4);
1003 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
1004
1005 res = RegSetValueExA(clsid_key, channelcount_valuename, 0, REG_DWORD,
1006 (const BYTE*)&list->channelcount, 4);
1007 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
1008
1009 res = RegSetValueExA(clsid_key, numericrepresentation_valuename, 0, REG_DWORD,
1010 (const BYTE*)&list->numericrepresentation, 4);
1011 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
1012
1013 res = RegSetValueExA(clsid_key, supportstransparency_valuename, 0, REG_DWORD,
1014 (const BYTE*)&list->supportsalpha, 4);
1015 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
1016
1017 if (list->channelmasks) {
1018 HKEY masks_key;
1019 UINT i, mask_size;
1020 WCHAR mask_valuename[11];
1021 const WCHAR valuename_format[] = {'%','d',0};
1022
1023 mask_size = (list->bitsperpixel + 7)/8;
1024
1025 res = RegCreateKeyExW(clsid_key, channelmasks_keyname, 0, NULL, 0,
1026 KEY_READ | KEY_WRITE, NULL, &masks_key, NULL);
1027 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
1028 for (i=0; i < list->channelcount; i++)
1029 {
1030 sprintfW(mask_valuename, valuename_format, i);
1031 res = RegSetValueExW(masks_key, mask_valuename, 0, REG_BINARY,
1032 list->channelmasks[i], mask_size);
1033 if (res != ERROR_SUCCESS) break;
1034 }
1035 RegCloseKey(masks_key);
1036 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
1037 }
1038
1039 error_close_clsid_key:
1040 RegCloseKey(clsid_key);
1041 }
1042
1043 error_close_coclass_key:
1044 RegCloseKey(instance_key);
1045 RegCloseKey(formats_key);
1046 RegCloseKey(coclass_key);
1047 error_return:
1048 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
1049 }
1050
1051 /***********************************************************************
1052 * unregister_pixelformats
1053 */
1054 static HRESULT unregister_pixelformats(struct regsvr_pixelformat const *list)
1055 {
1056 LONG res = ERROR_SUCCESS;
1057 HKEY coclass_key;
1058 WCHAR buf[39];
1059 HKEY formats_key;
1060 HKEY instance_key;
1061
1062 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0,
1063 KEY_READ | KEY_WRITE, &coclass_key);
1064 if (res == ERROR_FILE_NOT_FOUND) return S_OK;
1065
1066 if (res == ERROR_SUCCESS) {
1067 StringFromGUID2(&CATID_WICPixelFormats, buf, 39);
1068 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
1069 KEY_READ | KEY_WRITE, NULL, &formats_key, NULL);
1070 if (res == ERROR_SUCCESS)
1071 {
1072 res = RegCreateKeyExW(formats_key, instance_keyname, 0, NULL, 0,
1073 KEY_READ | KEY_WRITE, NULL, &instance_key, NULL);
1074 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
1075 }
1076 if (res != ERROR_SUCCESS)
1077 RegCloseKey(coclass_key);
1078 }
1079 if (res != ERROR_SUCCESS) goto error_return;
1080
1081 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
1082 StringFromGUID2(list->clsid, buf, 39);
1083
1084 res = RegDeleteTreeW(coclass_key, buf);
1085 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
1086 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
1087
1088 res = RegDeleteTreeW(instance_key, buf);
1089 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
1090 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
1091 }
1092
1093 error_close_coclass_key:
1094 RegCloseKey(instance_key);
1095 RegCloseKey(formats_key);
1096 RegCloseKey(coclass_key);
1097 error_return:
1098 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
1099 }
1100
1101 /***********************************************************************
1102 * decoder list
1103 */
1104 static const BYTE mask_all[] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
1105
1106 static const BYTE bmp_magic[] = {0x42,0x4d};
1107
1108 static GUID const * const bmp_formats[] = {
1109 &GUID_WICPixelFormat1bppIndexed,
1110 &GUID_WICPixelFormat2bppIndexed,
1111 &GUID_WICPixelFormat4bppIndexed,
1112 &GUID_WICPixelFormat8bppIndexed,
1113 &GUID_WICPixelFormat16bppBGR555,
1114 &GUID_WICPixelFormat16bppBGR565,
1115 &GUID_WICPixelFormat24bppBGR,
1116 &GUID_WICPixelFormat32bppBGR,
1117 &GUID_WICPixelFormat32bppBGRA,
1118 NULL
1119 };
1120
1121 static struct decoder_pattern const bmp_patterns[] = {
1122 {2,0,bmp_magic,mask_all,0},
1123 {0}
1124 };
1125
1126 static const BYTE gif87a_magic[6] = "GIF87a";
1127 static const BYTE gif89a_magic[6] = "GIF89a";
1128
1129 static GUID const * const gif_formats[] = {
1130 &GUID_WICPixelFormat8bppIndexed,
1131 NULL
1132 };
1133
1134 static struct decoder_pattern const gif_patterns[] = {
1135 {6,0,gif87a_magic,mask_all,0},
1136 {6,0,gif89a_magic,mask_all,0},
1137 {0}
1138 };
1139
1140 static const BYTE ico_magic[] = {00,00,01,00};
1141
1142 static GUID const * const ico_formats[] = {
1143 &GUID_WICPixelFormat32bppBGRA,
1144 NULL
1145 };
1146
1147 static struct decoder_pattern const ico_patterns[] = {
1148 {4,0,ico_magic,mask_all,0},
1149 {0}
1150 };
1151
1152 static const BYTE jpeg_magic[] = {0xff, 0xd8};
1153
1154 static GUID const * const jpeg_formats[] = {
1155 &GUID_WICPixelFormat24bppBGR,
1156 &GUID_WICPixelFormat32bppCMYK,
1157 &GUID_WICPixelFormat8bppGray,
1158 NULL
1159 };
1160
1161 static struct decoder_pattern const jpeg_patterns[] = {
1162 {2,0,jpeg_magic,mask_all,0},
1163 {0}
1164 };
1165
1166 static const BYTE png_magic[] = {137,80,78,71,13,10,26,10};
1167
1168 static GUID const * const png_formats[] = {
1169 &GUID_WICPixelFormatBlackWhite,
1170 &GUID_WICPixelFormat2bppGray,
1171 &GUID_WICPixelFormat4bppGray,
1172 &GUID_WICPixelFormat8bppGray,
1173 &GUID_WICPixelFormat16bppGray,
1174 &GUID_WICPixelFormat32bppBGRA,
1175 &GUID_WICPixelFormat64bppRGBA,
1176 &GUID_WICPixelFormat1bppIndexed,
1177 &GUID_WICPixelFormat2bppIndexed,
1178 &GUID_WICPixelFormat4bppIndexed,
1179 &GUID_WICPixelFormat8bppIndexed,
1180 &GUID_WICPixelFormat24bppBGR,
1181 &GUID_WICPixelFormat48bppRGB,
1182 NULL
1183 };
1184
1185 static struct decoder_pattern const png_patterns[] = {
1186 {8,0,png_magic,mask_all,0},
1187 {0}
1188 };
1189
1190 static const BYTE tiff_magic_le[] = {0x49,0x49,42,0};
1191 static const BYTE tiff_magic_be[] = {0x4d,0x4d,0,42};
1192
1193 static GUID const * const tiff_decode_formats[] = {
1194 &GUID_WICPixelFormatBlackWhite,
1195 &GUID_WICPixelFormat4bppGray,
1196 &GUID_WICPixelFormat8bppGray,
1197 &GUID_WICPixelFormat16bppGray,
1198 &GUID_WICPixelFormat32bppGrayFloat,
1199 &GUID_WICPixelFormat1bppIndexed,
1200 &GUID_WICPixelFormat2bppIndexed,
1201 &GUID_WICPixelFormat4bppIndexed,
1202 &GUID_WICPixelFormat8bppIndexed,
1203 &GUID_WICPixelFormat24bppBGR,
1204 &GUID_WICPixelFormat32bppBGR,
1205 &GUID_WICPixelFormat32bppBGRA,
1206 &GUID_WICPixelFormat32bppPBGRA,
1207 &GUID_WICPixelFormat48bppRGB,
1208 &GUID_WICPixelFormat64bppRGBA,
1209 &GUID_WICPixelFormat64bppPRGBA,
1210 &GUID_WICPixelFormat32bppCMYK,
1211 &GUID_WICPixelFormat64bppCMYK,
1212 &GUID_WICPixelFormat128bppRGBAFloat,
1213 NULL
1214 };
1215
1216 static struct decoder_pattern const tiff_patterns[] = {
1217 {4,0,tiff_magic_le,mask_all,0},
1218 {4,0,tiff_magic_be,mask_all,0},
1219 {0}
1220 };
1221
1222 static const BYTE tga_footer_magic[18] = "TRUEVISION-XFILE.";
1223
1224 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};
1225 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};
1226
1227 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};
1228 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};
1229
1230 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};
1231 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};
1232
1233 static GUID const * const tga_formats[] = {
1234 &GUID_WICPixelFormat8bppGray,
1235 &GUID_WICPixelFormat8bppIndexed,
1236 &GUID_WICPixelFormat16bppGray,
1237 &GUID_WICPixelFormat16bppBGR555,
1238 &GUID_WICPixelFormat24bppBGR,
1239 &GUID_WICPixelFormat32bppBGRA,
1240 &GUID_WICPixelFormat32bppPBGRA,
1241 NULL
1242 };
1243
1244 static struct decoder_pattern const tga_patterns[] = {
1245 {18,18,tga_footer_magic,mask_all,1},
1246 {18,0,tga_indexed_magic,tga_indexed_mask,0},
1247 {18,0,tga_truecolor_magic,tga_truecolor_mask,0},
1248 {18,0,tga_grayscale_magic,tga_grayscale_mask,0},
1249 {0}
1250 };
1251
1252 static struct regsvr_decoder const decoder_list[] = {
1253 { &CLSID_WICBmpDecoder,
1254 "The Wine Project",
1255 "BMP Decoder",
1256 "1.0.0.0",
1257 &GUID_VendorMicrosoft,
1258 &GUID_ContainerFormatBmp,
1259 "image/bmp",
1260 ".bmp,.dib,.rle",
1261 bmp_formats,
1262 bmp_patterns
1263 },
1264 { &CLSID_WICGifDecoder,
1265 "The Wine Project",
1266 "GIF Decoder",
1267 "1.0.0.0",
1268 &GUID_VendorMicrosoft,
1269 &GUID_ContainerFormatGif,
1270 "image/gif",
1271 ".gif",
1272 gif_formats,
1273 gif_patterns
1274 },
1275 { &CLSID_WICIcoDecoder,
1276 "The Wine Project",
1277 "ICO Decoder",
1278 "1.0.0.0",
1279 &GUID_VendorMicrosoft,
1280 &GUID_ContainerFormatIco,
1281 "image/vnd.microsoft.icon",
1282 ".ico",
1283 ico_formats,
1284 ico_patterns
1285 },
1286 { &CLSID_WICJpegDecoder,
1287 "The Wine Project",
1288 "JPEG Decoder",
1289 "1.0.0.0",
1290 &GUID_VendorMicrosoft,
1291 &GUID_ContainerFormatJpeg,
1292 "image/jpeg",
1293 ".jpg;.jpeg;.jfif",
1294 jpeg_formats,
1295 jpeg_patterns
1296 },
1297 { &CLSID_WICPngDecoder,
1298 "The Wine Project",
1299 "PNG Decoder",
1300 "1.0.0.0",
1301 &GUID_VendorMicrosoft,
1302 &GUID_ContainerFormatPng,
1303 "image/png",
1304 ".png",
1305 png_formats,
1306 png_patterns
1307 },
1308 { &CLSID_WICTiffDecoder,
1309 "The Wine Project",
1310 "TIFF Decoder",
1311 "1.0.0.0",
1312 &GUID_VendorMicrosoft,
1313 &GUID_ContainerFormatTiff,
1314 "image/tiff",
1315 ".tif;.tiff",
1316 tiff_decode_formats,
1317 tiff_patterns
1318 },
1319 { &CLSID_WineTgaDecoder,
1320 "The Wine Project",
1321 "TGA Decoder",
1322 "1.0.0.0",
1323 &GUID_VendorWine,
1324 &GUID_WineContainerFormatTga,
1325 "image/x-targa",
1326 ".tga;.tpic",
1327 tga_formats,
1328 tga_patterns
1329 },
1330 { NULL } /* list terminator */
1331 };
1332
1333 static GUID const * const bmp_encode_formats[] = {
1334 &GUID_WICPixelFormat16bppBGR555,
1335 &GUID_WICPixelFormat16bppBGR565,
1336 &GUID_WICPixelFormat24bppBGR,
1337 &GUID_WICPixelFormat32bppBGR,
1338 &GUID_WICPixelFormatBlackWhite,
1339 &GUID_WICPixelFormat1bppIndexed,
1340 &GUID_WICPixelFormat2bppIndexed,
1341 &GUID_WICPixelFormat4bppIndexed,
1342 &GUID_WICPixelFormat8bppIndexed,
1343 NULL
1344 };
1345
1346 static GUID const * const png_encode_formats[] = {
1347 &GUID_WICPixelFormat24bppBGR,
1348 &GUID_WICPixelFormatBlackWhite,
1349 &GUID_WICPixelFormat2bppGray,
1350 &GUID_WICPixelFormat4bppGray,
1351 &GUID_WICPixelFormat8bppGray,
1352 &GUID_WICPixelFormat16bppGray,
1353 &GUID_WICPixelFormat32bppBGR,
1354 &GUID_WICPixelFormat32bppBGRA,
1355 &GUID_WICPixelFormat48bppRGB,
1356 &GUID_WICPixelFormat64bppRGBA,
1357 &GUID_WICPixelFormat1bppIndexed,
1358 &GUID_WICPixelFormat2bppIndexed,
1359 &GUID_WICPixelFormat4bppIndexed,
1360 &GUID_WICPixelFormat8bppIndexed,
1361 NULL
1362 };
1363
1364 static GUID const * const tiff_encode_formats[] = {
1365 &GUID_WICPixelFormatBlackWhite,
1366 &GUID_WICPixelFormat4bppGray,
1367 &GUID_WICPixelFormat8bppGray,
1368 &GUID_WICPixelFormat1bppIndexed,
1369 &GUID_WICPixelFormat2bppIndexed,
1370 &GUID_WICPixelFormat4bppIndexed,
1371 &GUID_WICPixelFormat8bppIndexed,
1372 &GUID_WICPixelFormat24bppBGR,
1373 &GUID_WICPixelFormat32bppBGRA,
1374 &GUID_WICPixelFormat32bppPBGRA,
1375 &GUID_WICPixelFormat48bppRGB,
1376 &GUID_WICPixelFormat64bppRGBA,
1377 &GUID_WICPixelFormat64bppPRGBA,
1378 NULL
1379 };
1380
1381 static GUID const * const icns_encode_formats[] = {
1382 &GUID_WICPixelFormat32bppBGRA,
1383 NULL
1384 };
1385
1386 static struct regsvr_encoder const encoder_list[] = {
1387 { &CLSID_WICBmpEncoder,
1388 "The Wine Project",
1389 "BMP Encoder",
1390 "1.0.0.0",
1391 &GUID_VendorMicrosoft,
1392 &GUID_ContainerFormatBmp,
1393 "image/bmp",
1394 ".bmp,.dib,.rle",
1395 bmp_encode_formats
1396 },
1397 { &CLSID_WICGifEncoder,
1398 "The Wine Project",
1399 "GIF Encoder",
1400 "1.0.0.0",
1401 &GUID_VendorMicrosoft,
1402 &GUID_ContainerFormatGif,
1403 "image/gif",
1404 ".gif",
1405 gif_formats
1406 },
1407 { &CLSID_WICJpegEncoder,
1408 "The Wine Project",
1409 "JPEG Encoder",
1410 "1.0.0.0",
1411 &GUID_VendorMicrosoft,
1412 &GUID_ContainerFormatJpeg,
1413 "image/jpeg",
1414 ".jpg;.jpeg;.jfif",
1415 jpeg_formats
1416 },
1417 { &CLSID_WICPngEncoder,
1418 "The Wine Project",
1419 "PNG Encoder",
1420 "1.0.0.0",
1421 &GUID_VendorMicrosoft,
1422 &GUID_ContainerFormatPng,
1423 "image/png",
1424 ".png",
1425 png_encode_formats
1426 },
1427 { &CLSID_WICTiffEncoder,
1428 "The Wine Project",
1429 "TIFF Encoder",
1430 "1.0.0.0",
1431 &GUID_VendorMicrosoft,
1432 &GUID_ContainerFormatTiff,
1433 "image/tiff",
1434 ".tif;.tiff",
1435 tiff_encode_formats
1436 },
1437 { &CLSID_WICIcnsEncoder,
1438 "The Wine Project",
1439 "ICNS Encoder",
1440 "1.0.0.0",
1441 &GUID_VendorWine,
1442 NULL, /* no container format guid */
1443 "image/icns",
1444 ".icns",
1445 icns_encode_formats
1446 },
1447 { NULL } /* list terminator */
1448 };
1449
1450 static GUID const * const converter_formats[] = {
1451 &GUID_WICPixelFormat1bppIndexed,
1452 &GUID_WICPixelFormat2bppIndexed,
1453 &GUID_WICPixelFormat4bppIndexed,
1454 &GUID_WICPixelFormat8bppIndexed,
1455 &GUID_WICPixelFormatBlackWhite,
1456 &GUID_WICPixelFormat2bppGray,
1457 &GUID_WICPixelFormat4bppGray,
1458 &GUID_WICPixelFormat8bppGray,
1459 &GUID_WICPixelFormat16bppGray,
1460 &GUID_WICPixelFormat16bppBGR555,
1461 &GUID_WICPixelFormat16bppBGR565,
1462 &GUID_WICPixelFormat16bppBGRA5551,
1463 &GUID_WICPixelFormat24bppBGR,
1464 &GUID_WICPixelFormat24bppRGB,
1465 &GUID_WICPixelFormat32bppBGR,
1466 &GUID_WICPixelFormat32bppRGB,
1467 &GUID_WICPixelFormat32bppBGRA,
1468 &GUID_WICPixelFormat32bppRGBA,
1469 &GUID_WICPixelFormat32bppPBGRA,
1470 &GUID_WICPixelFormat32bppPRGBA,
1471 &GUID_WICPixelFormat32bppGrayFloat,
1472 &GUID_WICPixelFormat48bppRGB,
1473 &GUID_WICPixelFormat64bppRGBA,
1474 &GUID_WICPixelFormat32bppCMYK,
1475 NULL
1476 };
1477
1478 static struct regsvr_converter const converter_list[] = {
1479 { &CLSID_WICDefaultFormatConverter,
1480 "The Wine Project",
1481 "Default Pixel Format Converter",
1482 "1.0.0.0",
1483 &GUID_VendorMicrosoft,
1484 converter_formats
1485 },
1486 { NULL } /* list terminator */
1487 };
1488
1489 static const BYTE no_magic[1] = { 0 };
1490 static const BYTE no_mask[1] = { 0 };
1491
1492 static const struct metadata_pattern ifd_metadata_pattern[] = {
1493 { 0, 1, no_magic, no_mask, 0 },
1494 { 0 }
1495 };
1496
1497 static const struct reader_containers ifd_containers[] = {
1498 {
1499 &GUID_ContainerFormatTiff,
1500 ifd_metadata_pattern
1501 },
1502 { NULL } /* list terminator */
1503 };
1504
1505 static const BYTE tEXt[] = "tEXt";
1506
1507 static const struct metadata_pattern pngtext_metadata_pattern[] = {
1508 { 4, 4, tEXt, mask_all, 4 },
1509 { 0 }
1510 };
1511
1512 static const struct reader_containers pngtext_containers[] = {
1513 {
1514 &GUID_ContainerFormatPng,
1515 pngtext_metadata_pattern
1516 },
1517 { NULL } /* list terminator */
1518 };
1519
1520 static const BYTE gAMA[] = "gAMA";
1521
1522 static const struct metadata_pattern pnggama_metadata_pattern[] = {
1523 { 4, 4, gAMA, mask_all, 4 },
1524 { 0 }
1525 };
1526
1527 static const struct reader_containers pnggama_containers[] = {
1528 {
1529 &GUID_ContainerFormatPng,
1530 pnggama_metadata_pattern
1531 },
1532 { NULL } /* list terminator */
1533 };
1534
1535 static const BYTE cHRM[] = "cHRM";
1536
1537 static const struct metadata_pattern pngchrm_metadata_pattern[] = {
1538 { 4, 4, cHRM, mask_all, 4 },
1539 { 0 }
1540 };
1541
1542 static const struct reader_containers pngchrm_containers[] = {
1543 {
1544 &GUID_ContainerFormatPng,
1545 pngchrm_metadata_pattern
1546 },
1547 { NULL } /* list terminator */
1548 };
1549
1550 static const struct metadata_pattern lsd_metadata_patterns[] = {
1551 { 0, 6, gif87a_magic, mask_all, 0 },
1552 { 0, 6, gif89a_magic, mask_all, 0 },
1553 { 0 }
1554 };
1555
1556 static const struct reader_containers lsd_containers[] = {
1557 {
1558 &GUID_ContainerFormatGif,
1559 lsd_metadata_patterns
1560 },
1561 { NULL } /* list terminator */
1562 };
1563
1564 static const BYTE imd_magic[] = { 0x2c };
1565
1566 static const struct metadata_pattern imd_metadata_pattern[] = {
1567 { 0, 1, imd_magic, mask_all, 1 },
1568 { 0 }
1569 };
1570
1571 static const struct reader_containers imd_containers[] = {
1572 {
1573 &GUID_ContainerFormatGif,
1574 imd_metadata_pattern
1575 },
1576 { NULL } /* list terminator */
1577 };
1578
1579 static const BYTE gce_magic[] = { 0x21, 0xf9, 0x04 };
1580
1581 static const struct metadata_pattern gce_metadata_pattern[] = {
1582 { 0, 3, gce_magic, mask_all, 3 },
1583 { 0 }
1584 };
1585
1586 static const struct reader_containers gce_containers[] = {
1587 {
1588 &GUID_ContainerFormatGif,
1589 gce_metadata_pattern
1590 },
1591 { NULL } /* list terminator */
1592 };
1593
1594 static const BYTE ape_magic[] = { 0x21, 0xff, 0x0b };
1595
1596 static const struct metadata_pattern ape_metadata_pattern[] = {
1597 { 0, 3, ape_magic, mask_all, 0 },
1598 { 0 }
1599 };
1600
1601 static const struct reader_containers ape_containers[] = {
1602 {
1603 &GUID_ContainerFormatGif,
1604 ape_metadata_pattern
1605 },
1606 { NULL } /* list terminator */
1607 };
1608
1609 static const BYTE gif_comment_magic[] = { 0x21, 0xfe };
1610
1611 static const struct metadata_pattern gif_comment_metadata_pattern[] = {
1612 { 0, 2, gif_comment_magic, mask_all, 0 },
1613 { 0 }
1614 };
1615
1616 static const struct reader_containers gif_comment_containers[] = {
1617 {
1618 &GUID_ContainerFormatGif,
1619 gif_comment_metadata_pattern
1620 },
1621 { NULL } /* list terminator */
1622 };
1623
1624 static struct regsvr_metadatareader const metadatareader_list[] = {
1625 { &CLSID_WICUnknownMetadataReader,
1626 "The Wine Project",
1627 "Unknown Metadata Reader",
1628 "1.0.0.0",
1629 "1.0.0.0",
1630 &GUID_VendorMicrosoft,
1631 &GUID_MetadataFormatUnknown,
1632 0, 0, 0,
1633 NULL
1634 },
1635 { &CLSID_WICIfdMetadataReader,
1636 "The Wine Project",
1637 "Ifd Reader",
1638 "1.0.0.0",
1639 "1.0.0.0",
1640 &GUID_VendorMicrosoft,
1641 &GUID_MetadataFormatIfd,
1642 1, 1, 0,
1643 ifd_containers
1644 },
1645 { &CLSID_WICPngChrmMetadataReader,
1646 "The Wine Project",
1647 "Chunk cHRM Reader",
1648 "1.0.0.0",
1649 "1.0.0.0",
1650 &GUID_VendorMicrosoft,
1651 &GUID_MetadataFormatChunkcHRM,
1652 0, 0, 0,
1653 pngchrm_containers
1654 },
1655 { &CLSID_WICPngGamaMetadataReader,
1656 "The Wine Project",
1657 "Chunk gAMA Reader",
1658 "1.0.0.0",
1659 "1.0.0.0",
1660 &GUID_VendorMicrosoft,
1661 &GUID_MetadataFormatChunkgAMA,
1662 0, 0, 0,
1663 pnggama_containers
1664 },
1665 { &CLSID_WICPngTextMetadataReader,
1666 "The Wine Project",
1667 "Chunk tEXt Reader",
1668 "1.0.0.0",
1669 "1.0.0.0",
1670 &GUID_VendorMicrosoft,
1671 &GUID_MetadataFormatChunktEXt,
1672 0, 0, 0,
1673 pngtext_containers
1674 },
1675 { &CLSID_WICLSDMetadataReader,
1676 "The Wine Project",
1677 "Logical Screen Descriptor Reader",
1678 "1.0.0.0",
1679 "1.0.0.0",
1680 &GUID_VendorMicrosoft,
1681 &GUID_MetadataFormatLSD,
1682 0, 0, 0,
1683 lsd_containers
1684 },
1685 { &CLSID_WICIMDMetadataReader,
1686 "The Wine Project",
1687 "Image Descriptor Reader",
1688 "1.0.0.0",
1689 "1.0.0.0",
1690 &GUID_VendorMicrosoft,
1691 &GUID_MetadataFormatIMD,
1692 0, 0, 0,
1693 imd_containers
1694 },
1695 { &CLSID_WICGCEMetadataReader,
1696 "The Wine Project",
1697 "Graphic Control Extension Reader",
1698 "1.0.0.0",
1699 "1.0.0.0",
1700 &GUID_VendorMicrosoft,
1701 &GUID_MetadataFormatGCE,
1702 0, 0, 0,
1703 gce_containers
1704 },
1705 { &CLSID_WICAPEMetadataReader,
1706 "The Wine Project",
1707 "Application Extension Reader",
1708 "1.0.0.0",
1709 "1.0.0.0",
1710 &GUID_VendorMicrosoft,
1711 &GUID_MetadataFormatAPE,
1712 0, 0, 0,
1713 ape_containers
1714 },
1715 { &CLSID_WICGifCommentMetadataReader,
1716 "The Wine Project",
1717 "Comment Extension Reader",
1718 "1.0.0.0",
1719 "1.0.0.0",
1720 &GUID_VendorMicrosoft,
1721 &GUID_MetadataFormatGifComment,
1722 0, 0, 0,
1723 gif_comment_containers
1724 },
1725 { NULL } /* list terminator */
1726 };
1727
1728 static BYTE const channel_mask_1bit[] = { 0x01 };
1729 static BYTE const channel_mask_2bit[] = { 0x03 };
1730 static BYTE const channel_mask_4bit[] = { 0x0f };
1731
1732 static BYTE const channel_mask_8bit[] = { 0xff, 0x00, 0x00, 0x00 };
1733 static BYTE const channel_mask_8bit2[] = { 0x00, 0xff, 0x00, 0x00 };
1734 static BYTE const channel_mask_8bit3[] = { 0x00, 0x00, 0xff, 0x00 };
1735 static BYTE const channel_mask_8bit4[] = { 0x00, 0x00, 0x00, 0xff };
1736
1737 static BYTE const channel_mask_16bit[] = { 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
1738 static BYTE const channel_mask_16bit2[] = { 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 };
1739 static BYTE const channel_mask_16bit3[] = { 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00 };
1740 static BYTE const channel_mask_16bit4[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff };
1741
1742 static BYTE const channel_mask_32bit[] = { 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 };
1743
1744 static BYTE const channel_mask_128bit1[] = { 0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
1745 static BYTE const channel_mask_128bit2[] = { 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
1746 static BYTE const channel_mask_128bit3[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00 };
1747 static BYTE const channel_mask_128bit4[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff };
1748
1749 static BYTE const channel_mask_5bit[] = { 0x1f, 0x00 };
1750 static BYTE const channel_mask_5bit2[] = { 0xe0, 0x03 };
1751 static BYTE const channel_mask_5bit3[] = { 0x00, 0x7c };
1752 static BYTE const channel_mask_5bit4[] = { 0x00, 0x80 };
1753
1754 static BYTE const channel_mask_BGR565_2[] = { 0xe0, 0x07 };
1755 static BYTE const channel_mask_BGR565_3[] = { 0x00, 0xf8 };
1756
1757 static BYTE const * const channel_masks_1bit[] = { channel_mask_1bit };
1758 static BYTE const * const channel_masks_2bit[] = { channel_mask_2bit };
1759 static BYTE const * const channel_masks_4bit[] = { channel_mask_4bit };
1760 static BYTE const * const channel_masks_8bit[] = { channel_mask_8bit,
1761 channel_mask_8bit2, channel_mask_8bit3, channel_mask_8bit4 };
1762 static BYTE const * const channel_masks_16bit[] = { channel_mask_16bit,
1763 channel_mask_16bit2, channel_mask_16bit3, channel_mask_16bit4};
1764
1765 static BYTE const * const channel_masks_32bit[] = { channel_mask_32bit };
1766 static BYTE const * const channel_masks_128bit[] = { channel_mask_128bit1, channel_mask_128bit2, channel_mask_128bit3, channel_mask_128bit4 };
1767
1768 static BYTE const * const channel_masks_BGRA5551[] = { channel_mask_5bit,
1769 channel_mask_5bit2, channel_mask_5bit3, channel_mask_5bit4 };
1770
1771 static BYTE const * const channel_masks_BGR565[] = { channel_mask_5bit,
1772 channel_mask_BGR565_2, channel_mask_BGR565_3 };
1773
1774 static struct regsvr_pixelformat const pixelformat_list[] = {
1775 { &GUID_WICPixelFormat1bppIndexed,
1776 "The Wine Project",
1777 "1bpp Indexed",
1778 NULL, /* no version */
1779 &GUID_VendorMicrosoft,
1780 1, /* bitsperpixel */
1781 1, /* channel count */
1782 channel_masks_1bit,
1783 WICPixelFormatNumericRepresentationIndexed,
1784 0
1785 },
1786 { &GUID_WICPixelFormat2bppIndexed,
1787 "The Wine Project",
1788 "2bpp Indexed",
1789 NULL, /* no version */
1790 &GUID_VendorMicrosoft,
1791 2, /* bitsperpixel */
1792 1, /* channel count */
1793 channel_masks_2bit,
1794 WICPixelFormatNumericRepresentationIndexed,
1795 0
1796 },
1797 { &GUID_WICPixelFormat4bppIndexed,
1798 "The Wine Project",
1799 "4bpp Indexed",
1800 NULL, /* no version */
1801 &GUID_VendorMicrosoft,
1802 4, /* bitsperpixel */
1803 1, /* channel count */
1804 channel_masks_4bit,
1805 WICPixelFormatNumericRepresentationIndexed,
1806 0
1807 },
1808 { &GUID_WICPixelFormat8bppIndexed,
1809 "The Wine Project",
1810 "8bpp Indexed",
1811 NULL, /* no version */
1812 &GUID_VendorMicrosoft,
1813 8, /* bitsperpixel */
1814 1, /* channel count */
1815 channel_masks_8bit,
1816 WICPixelFormatNumericRepresentationIndexed,
1817 0
1818 },
1819 { &GUID_WICPixelFormatBlackWhite,
1820 "The Wine Project",
1821 "Black and White",
1822 NULL, /* no version */
1823 &GUID_VendorMicrosoft,
1824 1, /* bitsperpixel */
1825 1, /* channel count */
1826 channel_masks_1bit,
1827 WICPixelFormatNumericRepresentationUnsignedInteger,
1828 0
1829 },
1830 { &GUID_WICPixelFormat2bppGray,
1831 "The Wine Project",
1832 "2bpp Grayscale",
1833 NULL, /* no version */
1834 &GUID_VendorMicrosoft,
1835 2, /* bitsperpixel */
1836 1, /* channel count */
1837 channel_masks_2bit,
1838 WICPixelFormatNumericRepresentationUnsignedInteger,
1839 0
1840 },
1841 { &GUID_WICPixelFormat4bppGray,
1842 "The Wine Project",
1843 "4bpp Grayscale",
1844 NULL, /* no version */
1845 &GUID_VendorMicrosoft,
1846 4, /* bitsperpixel */
1847 1, /* channel count */
1848 channel_masks_4bit,
1849 WICPixelFormatNumericRepresentationUnsignedInteger,
1850 0
1851 },
1852 { &GUID_WICPixelFormat8bppGray,
1853 "The Wine Project",
1854 "8bpp Grayscale",
1855 NULL, /* no version */
1856 &GUID_VendorMicrosoft,
1857 8, /* bitsperpixel */
1858 1, /* channel count */
1859 channel_masks_8bit,
1860 WICPixelFormatNumericRepresentationUnsignedInteger,
1861 0
1862 },
1863 { &GUID_WICPixelFormat16bppGray,
1864 "The Wine Project",
1865 "16bpp Grayscale",
1866 NULL, /* no version */
1867 &GUID_VendorMicrosoft,
1868 16, /* bitsperpixel */
1869 1, /* channel count */
1870 channel_masks_16bit,
1871 WICPixelFormatNumericRepresentationUnsignedInteger,
1872 0
1873 },
1874 { &GUID_WICPixelFormat16bppBGR555,
1875 "The Wine Project",
1876 "16bpp BGR555",
1877 NULL, /* no version */
1878 &GUID_VendorMicrosoft,
1879 16, /* bitsperpixel */
1880 3, /* channel count */
1881 channel_masks_BGRA5551,
1882 WICPixelFormatNumericRepresentationUnsignedInteger,
1883 0
1884 },
1885 { &GUID_WICPixelFormat16bppBGR565,
1886 "The Wine Project",
1887 "16bpp BGR565",
1888 NULL, /* no version */
1889 &GUID_VendorMicrosoft,
1890 16, /* bitsperpixel */
1891 3, /* channel count */
1892 channel_masks_BGR565,
1893 WICPixelFormatNumericRepresentationUnsignedInteger,
1894 0
1895 },
1896 { &GUID_WICPixelFormat16bppBGRA5551,
1897 "The Wine Project",
1898 "16bpp BGRA5551",
1899 NULL, /* no version */
1900 &GUID_VendorMicrosoft,
1901 16, /* bitsperpixel */
1902 4, /* channel count */
1903 channel_masks_BGRA5551,
1904 WICPixelFormatNumericRepresentationUnsignedInteger,
1905 1
1906 },
1907 { &GUID_WICPixelFormat24bppBGR,
1908 "The Wine Project",
1909 "24bpp BGR",
1910 NULL, /* no version */
1911 &GUID_VendorMicrosoft,
1912 24, /* bitsperpixel */
1913 3, /* channel count */
1914 channel_masks_8bit,
1915 WICPixelFormatNumericRepresentationUnsignedInteger,
1916 0
1917 },
1918 { &GUID_WICPixelFormat24bppRGB,
1919 "The Wine Project",
1920 "24bpp RGB",
1921 NULL, /* no version */
1922 &GUID_VendorMicrosoft,
1923 24, /* bitsperpixel */
1924 3, /* channel count */
1925 channel_masks_8bit,
1926 WICPixelFormatNumericRepresentationUnsignedInteger,
1927 0
1928 },
1929 { &GUID_WICPixelFormat32bppBGR,
1930 "The Wine Project",
1931 "32bpp BGR",
1932 NULL, /* no version */
1933 &GUID_VendorMicrosoft,
1934 32, /* bitsperpixel */
1935 3, /* channel count */
1936 channel_masks_8bit,
1937 WICPixelFormatNumericRepresentationUnsignedInteger,
1938 0
1939 },
1940 { &GUID_WICPixelFormat32bppRGB,
1941 "The Wine Project",
1942 "32bpp RGB",
1943 NULL, /* no version */
1944 &GUID_VendorMicrosoft,
1945 32, /* bitsperpixel */
1946 3, /* channel count */
1947 channel_masks_8bit,
1948 WICPixelFormatNumericRepresentationUnsignedInteger,
1949 0
1950 },
1951 { &GUID_WICPixelFormat32bppBGRA,
1952 "The Wine Project",
1953 "32bpp BGRA",
1954 NULL, /* no version */
1955 &GUID_VendorMicrosoft,
1956 32, /* bitsperpixel */
1957 4, /* channel count */
1958 channel_masks_8bit,
1959 WICPixelFormatNumericRepresentationUnsignedInteger,
1960 1
1961 },
1962 { &GUID_WICPixelFormat32bppRGBA,
1963 "The Wine Project",
1964 "32bpp RGBA",
1965 NULL, /* no version */
1966 &GUID_VendorMicrosoft,
1967 32, /* bitsperpixel */
1968 4, /* channel count */
1969 channel_masks_8bit,
1970 WICPixelFormatNumericRepresentationUnsignedInteger,
1971 1
1972 },
1973 { &GUID_WICPixelFormat32bppPBGRA,
1974 "The Wine Project",
1975 "32bpp PBGRA",
1976 NULL, /* no version */
1977 &GUID_VendorMicrosoft,
1978 32, /* bitsperpixel */
1979 4, /* channel count */
1980 channel_masks_8bit,
1981 WICPixelFormatNumericRepresentationUnsignedInteger,
1982 1
1983 },
1984 { &GUID_WICPixelFormat32bppPRGBA,
1985 "The Wine Project",
1986 "32bpp PRGBA",
1987 NULL, /* no version */
1988 &GUID_VendorMicrosoft,
1989 32, /* bitsperpixel */
1990 4, /* channel count */
1991 channel_masks_8bit,
1992 WICPixelFormatNumericRepresentationUnsignedInteger,
1993 1
1994 },
1995 { &GUID_WICPixelFormat32bppGrayFloat,
1996 "The Wine Project",
1997 "32bpp GrayFloat",
1998 NULL, /* no version */
1999 &GUID_VendorMicrosoft,
2000 32, /* bitsperpixel */
2001 1, /* channel count */
2002 channel_masks_32bit,
2003 WICPixelFormatNumericRepresentationFloat,
2004 0
2005 },
2006 { &GUID_WICPixelFormat48bppRGB,
2007 "The Wine Project",
2008 "48bpp RGB",
2009 NULL, /* no version */
2010 &GUID_VendorMicrosoft,
2011 48, /* bitsperpixel */
2012 3, /* channel count */
2013 channel_masks_16bit,
2014 WICPixelFormatNumericRepresentationUnsignedInteger,
2015 0
2016 },
2017 { &GUID_WICPixelFormat64bppRGBA,
2018 "The Wine Project",
2019 "64bpp RGBA",
2020 NULL, /* no version */
2021 &GUID_VendorMicrosoft,
2022 64, /* bitsperpixel */
2023 4, /* channel count */
2024 channel_masks_16bit,
2025 WICPixelFormatNumericRepresentationUnsignedInteger,
2026 1
2027 },
2028 { &GUID_WICPixelFormat64bppPRGBA,
2029 "The Wine Project",
2030 "64bpp PRGBA",
2031 NULL, /* no version */
2032 &GUID_VendorMicrosoft,
2033 64, /* bitsperpixel */
2034 4, /* channel count */
2035 channel_masks_16bit,
2036 WICPixelFormatNumericRepresentationUnsignedInteger,
2037 1
2038 },
2039 { &GUID_WICPixelFormat32bppCMYK,
2040 "The Wine Project",
2041 "32bpp CMYK",
2042 NULL, /* no version */
2043 &GUID_VendorMicrosoft,
2044 32, /* bitsperpixel */
2045 4, /* channel count */
2046 channel_masks_8bit,
2047 WICPixelFormatNumericRepresentationUnsignedInteger,
2048 0
2049 },
2050 { &GUID_WICPixelFormat64bppCMYK,
2051 "The Wine Project",
2052 "64bpp CMYK",
2053 NULL, /* no version */
2054 &GUID_VendorMicrosoft,
2055 64, /* bitsperpixel */
2056 4, /* channel count */
2057 channel_masks_16bit,
2058 WICPixelFormatNumericRepresentationUnsignedInteger,
2059 0
2060 },
2061 { &GUID_WICPixelFormat128bppRGBAFloat,
2062 "The Wine Project",
2063 "128bpp RGBAFloat",
2064 NULL, /* no version */
2065 &GUID_VendorMicrosoft,
2066 128, /* bitsperpixel */
2067 4, /* channel count */
2068 channel_masks_128bit,
2069 WICPixelFormatNumericRepresentationFloat,
2070 1
2071 },
2072 { NULL } /* list terminator */
2073 };
2074
2075 struct regsvr_category
2076 {
2077 const CLSID *clsid; /* NULL for end of list */
2078 };
2079
2080 static const struct regsvr_category category_list[] = {
2081 { &CATID_WICBitmapDecoders },
2082 { &CATID_WICBitmapEncoders },
2083 { &CATID_WICFormatConverters },
2084 { &CATID_WICMetadataReader },
2085 { &CATID_WICPixelFormats },
2086 { NULL }
2087 };
2088
2089 static HRESULT register_categories(const struct regsvr_category *list)
2090 {
2091 LONG res;
2092 WCHAR buf[39];
2093 HKEY coclass_key, categories_key, instance_key;
2094
2095 res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0,
2096 KEY_READ | KEY_WRITE, NULL, &coclass_key, NULL);
2097 if (res != ERROR_SUCCESS) return HRESULT_FROM_WIN32(res);
2098
2099 StringFromGUID2(&CLSID_WICImagingCategories, buf, 39);
2100 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
2101 KEY_READ | KEY_WRITE, NULL, &categories_key, NULL);
2102 if (res != ERROR_SUCCESS)
2103 {
2104 RegCloseKey(coclass_key);
2105 return HRESULT_FROM_WIN32(res);
2106 }
2107
2108 res = RegCreateKeyExW(categories_key, instance_keyname, 0, NULL, 0,
2109 KEY_READ | KEY_WRITE, NULL, &instance_key, NULL);
2110
2111 for (; res == ERROR_SUCCESS && list->clsid; list++)
2112 {
2113 HKEY instance_clsid_key;
2114
2115 StringFromGUID2(list->clsid, buf, 39);
2116 res = RegCreateKeyExW(instance_key, buf, 0, NULL, 0,
2117 KEY_READ | KEY_WRITE, NULL, &instance_clsid_key, NULL);
2118 if (res == ERROR_SUCCESS)
2119 {
2120 res = RegSetValueExW(instance_clsid_key, clsid_valuename, 0, REG_SZ,
2121 (const BYTE *)buf, 78);
2122 RegCloseKey(instance_clsid_key);
2123 }
2124 }
2125
2126 RegCloseKey(instance_key);
2127 RegCloseKey(categories_key);
2128 RegCloseKey(coclass_key);
2129
2130 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
2131 }
2132
2133 static HRESULT unregister_categories(const struct regsvr_category *list)
2134 {
2135 LONG res;
2136 WCHAR buf[39];
2137 HKEY coclass_key, categories_key, instance_key;
2138
2139 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0,
2140 KEY_READ | KEY_WRITE, &coclass_key);
2141 if (res != ERROR_SUCCESS) return HRESULT_FROM_WIN32(res);
2142
2143 StringFromGUID2(&CLSID_WICImagingCategories, buf, 39);
2144 res = RegOpenKeyExW(coclass_key, buf, 0,
2145 KEY_READ | KEY_WRITE, &categories_key);
2146 if (res != ERROR_SUCCESS)
2147 {
2148 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
2149 RegCloseKey(coclass_key);
2150 return HRESULT_FROM_WIN32(res);
2151 }
2152
2153 res = RegOpenKeyExW(categories_key, instance_keyname, 0,
2154 KEY_READ | KEY_WRITE, &instance_key);
2155
2156 for (; res == ERROR_SUCCESS && list->clsid; list++)
2157 {
2158 StringFromGUID2(list->clsid, buf, 39);
2159 res = RegDeleteTreeW(instance_key, buf);
2160 }
2161
2162 RegCloseKey(instance_key);
2163 RegCloseKey(categories_key);
2164
2165 StringFromGUID2(&CLSID_WICImagingCategories, buf, 39);
2166 res = RegDeleteTreeW(coclass_key, buf);
2167
2168 RegCloseKey(coclass_key);
2169
2170 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
2171 }
2172
2173 extern HRESULT WINAPI WIC_DllRegisterServer(void) DECLSPEC_HIDDEN;
2174 extern HRESULT WINAPI WIC_DllUnregisterServer(void) DECLSPEC_HIDDEN;
2175
2176 HRESULT WINAPI DllRegisterServer(void)
2177 {
2178 HRESULT hr;
2179
2180 TRACE("\n");
2181
2182 hr = WIC_DllRegisterServer();
2183 if (SUCCEEDED(hr))
2184 hr = register_categories(category_list);
2185 if (SUCCEEDED(hr))
2186 hr = register_decoders(decoder_list);
2187 if (SUCCEEDED(hr))
2188 hr = register_encoders(encoder_list);
2189 if (SUCCEEDED(hr))
2190 hr = register_converters(converter_list);
2191 if (SUCCEEDED(hr))
2192 hr = register_metadatareaders(metadatareader_list);
2193 if (SUCCEEDED(hr))
2194 hr = register_pixelformats(pixelformat_list);
2195 return hr;
2196 }
2197
2198 HRESULT WINAPI DllUnregisterServer(void)
2199 {
2200 HRESULT hr;
2201
2202 TRACE("\n");
2203
2204 hr = WIC_DllUnregisterServer();
2205 if (SUCCEEDED(hr))
2206 hr = unregister_categories(category_list);
2207 if (SUCCEEDED(hr))
2208 hr = unregister_decoders(decoder_list);
2209 if (SUCCEEDED(hr))
2210 hr = unregister_encoders(encoder_list);
2211 if (SUCCEEDED(hr))
2212 hr = unregister_converters(converter_list);
2213 if (SUCCEEDED(hr))
2214 hr = unregister_metadatareaders(metadatareader_list);
2215 if (SUCCEEDED(hr))
2216 hr = unregister_pixelformats(pixelformat_list);
2217 return hr;
2218 }