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