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