regedit: Merge accelerators into the main resource file.
[wine/multimedia.git] / dlls / windowscodecs / regsvr.c
blob9b7baeac425816fb347a1a5a192f0a69a2ec6fd6
1 /*
2 * Copyright 2009 Vincent Povirk for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #define NONAMELESSUNION
20 #define NONAMELESSSTRUCT
21 #define COBJMACROS
22 #include <stdarg.h>
23 #include <string.h>
25 #include "windef.h"
26 #include "winbase.h"
27 #include "wingdi.h"
28 #include "winuser.h"
29 #include "winreg.h"
30 #include "winerror.h"
32 #include "objbase.h"
33 #include "ocidl.h"
34 #include "wincodec.h"
36 #include "wine/debug.h"
37 #include "wine/unicode.h"
39 #include "wincodecs_private.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
43 /***********************************************************************
44 * interface for self-registering
46 struct decoder_pattern
48 DWORD length; /* 0 for end of list */
49 DWORD position;
50 const BYTE *pattern;
51 const BYTE *mask;
52 DWORD endofstream;
55 struct regsvr_decoder
57 CLSID const *clsid; /* NULL for end of list */
58 LPCSTR author;
59 LPCSTR friendlyname;
60 LPCSTR version;
61 GUID const *vendor;
62 LPCSTR mimetypes;
63 LPCSTR extensions;
64 GUID const * const *formats;
65 const struct decoder_pattern *patterns;
68 static HRESULT register_decoders(struct regsvr_decoder const *list);
69 static HRESULT unregister_decoders(struct regsvr_decoder const *list);
71 struct regsvr_encoder
73 CLSID const *clsid; /* NULL for end of list */
74 LPCSTR author;
75 LPCSTR friendlyname;
76 LPCSTR version;
77 GUID const *vendor;
78 LPCSTR mimetypes;
79 LPCSTR extensions;
80 GUID const * const *formats;
83 static HRESULT register_encoders(struct regsvr_encoder const *list);
84 static HRESULT unregister_encoders(struct regsvr_encoder const *list);
86 struct regsvr_converter
88 CLSID const *clsid; /* NULL for end of list */
89 LPCSTR author;
90 LPCSTR friendlyname;
91 LPCSTR version;
92 GUID const *vendor;
93 GUID const * const *formats;
96 static HRESULT register_converters(struct regsvr_converter const *list);
97 static HRESULT unregister_converters(struct regsvr_converter const *list);
99 /***********************************************************************
100 * static string constants
102 static WCHAR const clsid_keyname[] = {
103 'C', 'L', 'S', 'I', 'D', 0 };
104 static WCHAR const curver_keyname[] = {
105 'C', 'u', 'r', 'V', 'e', 'r', 0 };
106 static WCHAR const ips_keyname[] = {
107 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
108 0 };
109 static WCHAR const ips32_keyname[] = {
110 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
111 '3', '2', 0 };
112 static WCHAR const progid_keyname[] = {
113 'P', 'r', 'o', 'g', 'I', 'D', 0 };
114 static WCHAR const viprogid_keyname[] = {
115 'V', 'e', 'r', 's', 'i', 'o', 'n', 'I', 'n', 'd', 'e', 'p',
116 'e', 'n', 'd', 'e', 'n', 't', 'P', 'r', 'o', 'g', 'I', 'D',
117 0 };
118 static char const tmodel_valuename[] = "ThreadingModel";
119 static char const author_valuename[] = "Author";
120 static char const friendlyname_valuename[] = "FriendlyName";
121 static WCHAR const vendor_valuename[] = {'V','e','n','d','o','r',0};
122 static char const version_valuename[] = "Version";
123 static char const mimetypes_valuename[] = "MimeTypes";
124 static char const extensions_valuename[] = "FileExtensions";
125 static WCHAR const formats_keyname[] = {'F','o','r','m','a','t','s',0};
126 static WCHAR const patterns_keyname[] = {'P','a','t','t','e','r','n','s',0};
127 static WCHAR const instance_keyname[] = {'I','n','s','t','a','n','c','e',0};
128 static WCHAR const clsid_valuename[] = {'C','L','S','I','D',0};
129 static char const length_valuename[] = "Length";
130 static char const position_valuename[] = "Position";
131 static char const pattern_valuename[] = "Pattern";
132 static char const mask_valuename[] = "Mask";
133 static char const endofstream_valuename[] = "EndOfStream";
134 static WCHAR const pixelformats_keyname[] = {'P','i','x','e','l','F','o','r','m','a','t','s',0};
136 /***********************************************************************
137 * register_decoders
139 static HRESULT register_decoders(struct regsvr_decoder const *list)
141 LONG res = ERROR_SUCCESS;
142 HKEY coclass_key;
143 WCHAR buf[39];
144 HKEY decoders_key;
145 HKEY instance_key;
147 res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0,
148 KEY_READ | KEY_WRITE, NULL, &coclass_key, NULL);
149 if (res == ERROR_SUCCESS) {
150 StringFromGUID2(&CATID_WICBitmapDecoders, buf, 39);
151 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
152 KEY_READ | KEY_WRITE, NULL, &decoders_key, NULL);
153 if (res == ERROR_SUCCESS)
155 res = RegCreateKeyExW(decoders_key, instance_keyname, 0, NULL, 0,
156 KEY_READ | KEY_WRITE, NULL, &instance_key, NULL);
157 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
159 if (res != ERROR_SUCCESS)
160 RegCloseKey(coclass_key);
162 if (res != ERROR_SUCCESS) goto error_return;
164 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
165 HKEY clsid_key;
166 HKEY instance_clsid_key;
168 StringFromGUID2(list->clsid, buf, 39);
169 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
170 KEY_READ | KEY_WRITE, NULL, &clsid_key, NULL);
171 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
173 StringFromGUID2(list->clsid, buf, 39);
174 res = RegCreateKeyExW(instance_key, buf, 0, NULL, 0,
175 KEY_READ | KEY_WRITE, NULL, &instance_clsid_key, NULL);
176 if (res == ERROR_SUCCESS) {
177 res = RegSetValueExW(instance_clsid_key, clsid_valuename, 0, REG_SZ,
178 (CONST BYTE*)(buf), 78);
179 RegCloseKey(instance_clsid_key);
181 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
183 if (list->author) {
184 res = RegSetValueExA(clsid_key, author_valuename, 0, REG_SZ,
185 (CONST BYTE*)(list->author),
186 strlen(list->author) + 1);
187 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
190 if (list->friendlyname) {
191 res = RegSetValueExA(clsid_key, friendlyname_valuename, 0, REG_SZ,
192 (CONST BYTE*)(list->friendlyname),
193 strlen(list->friendlyname) + 1);
194 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
197 if (list->vendor) {
198 StringFromGUID2(list->vendor, buf, 39);
199 res = RegSetValueExW(clsid_key, vendor_valuename, 0, REG_SZ,
200 (CONST BYTE*)(buf), 78);
201 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
204 if (list->version) {
205 res = RegSetValueExA(clsid_key, version_valuename, 0, REG_SZ,
206 (CONST BYTE*)(list->version),
207 strlen(list->version) + 1);
208 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
211 if (list->mimetypes) {
212 res = RegSetValueExA(clsid_key, mimetypes_valuename, 0, REG_SZ,
213 (CONST BYTE*)(list->mimetypes),
214 strlen(list->mimetypes) + 1);
215 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
218 if (list->extensions) {
219 res = RegSetValueExA(clsid_key, extensions_valuename, 0, REG_SZ,
220 (CONST BYTE*)(list->extensions),
221 strlen(list->extensions) + 1);
222 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
225 if (list->formats) {
226 HKEY formats_key;
227 GUID const * const *format;
229 res = RegCreateKeyExW(clsid_key, formats_keyname, 0, NULL, 0,
230 KEY_READ | KEY_WRITE, NULL, &formats_key, NULL);
231 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
232 for (format=list->formats; *format; ++format)
234 HKEY format_key;
235 StringFromGUID2(*format, buf, 39);
236 res = RegCreateKeyExW(formats_key, buf, 0, NULL, 0,
237 KEY_READ | KEY_WRITE, NULL, &format_key, NULL);
238 if (res != ERROR_SUCCESS) break;
239 RegCloseKey(format_key);
241 RegCloseKey(formats_key);
242 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
245 if (list->patterns) {
246 HKEY patterns_key;
247 int i;
249 res = RegCreateKeyExW(clsid_key, patterns_keyname, 0, NULL, 0,
250 KEY_READ | KEY_WRITE, NULL, &patterns_key, NULL);
251 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
252 for (i=0; list->patterns[i].length; i++)
254 HKEY pattern_key;
255 static const WCHAR int_format[] = {'%','i',0};
256 snprintfW(buf, 39, int_format, i);
257 res = RegCreateKeyExW(patterns_key, buf, 0, NULL, 0,
258 KEY_READ | KEY_WRITE, NULL, &pattern_key, NULL);
259 if (res != ERROR_SUCCESS) break;
260 res = RegSetValueExA(pattern_key, length_valuename, 0, REG_DWORD,
261 (CONST BYTE*)(&list->patterns[i].length), 4);
262 if (res == ERROR_SUCCESS)
263 res = RegSetValueExA(pattern_key, position_valuename, 0, REG_DWORD,
264 (CONST BYTE*)(&list->patterns[i].position), 4);
265 if (res == ERROR_SUCCESS)
266 res = RegSetValueExA(pattern_key, pattern_valuename, 0, REG_BINARY,
267 list->patterns[i].pattern,
268 list->patterns[i].length);
269 if (res == ERROR_SUCCESS)
270 res = RegSetValueExA(pattern_key, mask_valuename, 0, REG_BINARY,
271 list->patterns[i].mask,
272 list->patterns[i].length);
273 if (res == ERROR_SUCCESS)
274 res = RegSetValueExA(pattern_key, endofstream_valuename, 0, REG_DWORD,
275 (CONST BYTE*)&(list->patterns[i].endofstream), 4);
276 RegCloseKey(pattern_key);
278 RegCloseKey(patterns_key);
279 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
282 error_close_clsid_key:
283 RegCloseKey(clsid_key);
286 error_close_coclass_key:
287 RegCloseKey(instance_key);
288 RegCloseKey(decoders_key);
289 RegCloseKey(coclass_key);
290 error_return:
291 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
294 /***********************************************************************
295 * unregister_decoders
297 static HRESULT unregister_decoders(struct regsvr_decoder const *list)
299 LONG res = ERROR_SUCCESS;
300 HKEY coclass_key;
301 WCHAR buf[39];
302 HKEY decoders_key;
303 HKEY instance_key;
305 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0,
306 KEY_READ | KEY_WRITE, &coclass_key);
307 if (res == ERROR_FILE_NOT_FOUND) return S_OK;
309 if (res == ERROR_SUCCESS) {
310 StringFromGUID2(&CATID_WICBitmapDecoders, buf, 39);
311 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
312 KEY_READ | KEY_WRITE, NULL, &decoders_key, NULL);
313 if (res == ERROR_SUCCESS)
315 res = RegCreateKeyExW(decoders_key, instance_keyname, 0, NULL, 0,
316 KEY_READ | KEY_WRITE, NULL, &instance_key, NULL);
317 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
319 if (res != ERROR_SUCCESS)
320 RegCloseKey(coclass_key);
322 if (res != ERROR_SUCCESS) goto error_return;
324 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
325 StringFromGUID2(list->clsid, buf, 39);
327 res = RegDeleteTreeW(coclass_key, buf);
328 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
329 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
331 res = RegDeleteTreeW(instance_key, buf);
332 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
333 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
336 error_close_coclass_key:
337 RegCloseKey(instance_key);
338 RegCloseKey(decoders_key);
339 RegCloseKey(coclass_key);
340 error_return:
341 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
344 /***********************************************************************
345 * register_encoders
347 static HRESULT register_encoders(struct regsvr_encoder const *list)
349 LONG res = ERROR_SUCCESS;
350 HKEY coclass_key;
351 WCHAR buf[39];
352 HKEY encoders_key;
353 HKEY instance_key;
355 res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0,
356 KEY_READ | KEY_WRITE, NULL, &coclass_key, NULL);
357 if (res == ERROR_SUCCESS) {
358 StringFromGUID2(&CATID_WICBitmapEncoders, buf, 39);
359 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
360 KEY_READ | KEY_WRITE, NULL, &encoders_key, NULL);
361 if (res == ERROR_SUCCESS)
363 res = RegCreateKeyExW(encoders_key, instance_keyname, 0, NULL, 0,
364 KEY_READ | KEY_WRITE, NULL, &instance_key, NULL);
365 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
367 if (res != ERROR_SUCCESS)
368 RegCloseKey(coclass_key);
370 if (res != ERROR_SUCCESS) goto error_return;
372 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
373 HKEY clsid_key;
374 HKEY instance_clsid_key;
376 StringFromGUID2(list->clsid, buf, 39);
377 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
378 KEY_READ | KEY_WRITE, NULL, &clsid_key, NULL);
379 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
381 StringFromGUID2(list->clsid, buf, 39);
382 res = RegCreateKeyExW(instance_key, buf, 0, NULL, 0,
383 KEY_READ | KEY_WRITE, NULL, &instance_clsid_key, NULL);
384 if (res == ERROR_SUCCESS) {
385 res = RegSetValueExW(instance_clsid_key, clsid_valuename, 0, REG_SZ,
386 (CONST BYTE*)(buf), 78);
387 RegCloseKey(instance_clsid_key);
389 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
391 if (list->author) {
392 res = RegSetValueExA(clsid_key, author_valuename, 0, REG_SZ,
393 (CONST BYTE*)(list->author),
394 strlen(list->author) + 1);
395 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
398 if (list->friendlyname) {
399 res = RegSetValueExA(clsid_key, friendlyname_valuename, 0, REG_SZ,
400 (CONST BYTE*)(list->friendlyname),
401 strlen(list->friendlyname) + 1);
402 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
405 if (list->vendor) {
406 StringFromGUID2(list->vendor, buf, 39);
407 res = RegSetValueExW(clsid_key, vendor_valuename, 0, REG_SZ,
408 (CONST BYTE*)(buf), 78);
409 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
412 if (list->version) {
413 res = RegSetValueExA(clsid_key, version_valuename, 0, REG_SZ,
414 (CONST BYTE*)(list->version),
415 strlen(list->version) + 1);
416 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
419 if (list->mimetypes) {
420 res = RegSetValueExA(clsid_key, mimetypes_valuename, 0, REG_SZ,
421 (CONST BYTE*)(list->mimetypes),
422 strlen(list->mimetypes) + 1);
423 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
426 if (list->extensions) {
427 res = RegSetValueExA(clsid_key, extensions_valuename, 0, REG_SZ,
428 (CONST BYTE*)(list->extensions),
429 strlen(list->extensions) + 1);
430 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
433 if (list->formats) {
434 HKEY formats_key;
435 GUID const * const *format;
437 res = RegCreateKeyExW(clsid_key, formats_keyname, 0, NULL, 0,
438 KEY_READ | KEY_WRITE, NULL, &formats_key, NULL);
439 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
440 for (format=list->formats; *format; ++format)
442 HKEY format_key;
443 StringFromGUID2(*format, buf, 39);
444 res = RegCreateKeyExW(formats_key, buf, 0, NULL, 0,
445 KEY_READ | KEY_WRITE, NULL, &format_key, NULL);
446 if (res != ERROR_SUCCESS) break;
447 RegCloseKey(format_key);
449 RegCloseKey(formats_key);
450 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
453 error_close_clsid_key:
454 RegCloseKey(clsid_key);
457 error_close_coclass_key:
458 RegCloseKey(instance_key);
459 RegCloseKey(encoders_key);
460 RegCloseKey(coclass_key);
461 error_return:
462 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
465 /***********************************************************************
466 * unregister_encoders
468 static HRESULT unregister_encoders(struct regsvr_encoder const *list)
470 LONG res = ERROR_SUCCESS;
471 HKEY coclass_key;
472 WCHAR buf[39];
473 HKEY encoders_key;
474 HKEY instance_key;
476 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0,
477 KEY_READ | KEY_WRITE, &coclass_key);
478 if (res == ERROR_FILE_NOT_FOUND) return S_OK;
480 if (res == ERROR_SUCCESS) {
481 StringFromGUID2(&CATID_WICBitmapEncoders, buf, 39);
482 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
483 KEY_READ | KEY_WRITE, NULL, &encoders_key, NULL);
484 if (res == ERROR_SUCCESS)
486 res = RegCreateKeyExW(encoders_key, instance_keyname, 0, NULL, 0,
487 KEY_READ | KEY_WRITE, NULL, &instance_key, NULL);
488 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
490 if (res != ERROR_SUCCESS)
491 RegCloseKey(coclass_key);
493 if (res != ERROR_SUCCESS) goto error_return;
495 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
496 StringFromGUID2(list->clsid, buf, 39);
498 res = RegDeleteTreeW(coclass_key, buf);
499 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
500 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
502 res = RegDeleteTreeW(instance_key, buf);
503 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
504 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
507 error_close_coclass_key:
508 RegCloseKey(instance_key);
509 RegCloseKey(encoders_key);
510 RegCloseKey(coclass_key);
511 error_return:
512 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
515 /***********************************************************************
516 * register_converters
518 static HRESULT register_converters(struct regsvr_converter const *list)
520 LONG res = ERROR_SUCCESS;
521 HKEY coclass_key;
522 WCHAR buf[39];
523 HKEY converters_key;
524 HKEY instance_key;
526 res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0,
527 KEY_READ | KEY_WRITE, NULL, &coclass_key, NULL);
528 if (res == ERROR_SUCCESS) {
529 StringFromGUID2(&CATID_WICFormatConverters, buf, 39);
530 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
531 KEY_READ | KEY_WRITE, NULL, &converters_key, NULL);
532 if (res == ERROR_SUCCESS)
534 res = RegCreateKeyExW(converters_key, instance_keyname, 0, NULL, 0,
535 KEY_READ | KEY_WRITE, NULL, &instance_key, NULL);
536 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
538 if (res != ERROR_SUCCESS)
539 RegCloseKey(coclass_key);
541 if (res != ERROR_SUCCESS) goto error_return;
543 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
544 HKEY clsid_key;
545 HKEY instance_clsid_key;
547 StringFromGUID2(list->clsid, buf, 39);
548 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
549 KEY_READ | KEY_WRITE, NULL, &clsid_key, NULL);
550 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
552 StringFromGUID2(list->clsid, buf, 39);
553 res = RegCreateKeyExW(instance_key, buf, 0, NULL, 0,
554 KEY_READ | KEY_WRITE, NULL, &instance_clsid_key, NULL);
555 if (res == ERROR_SUCCESS) {
556 res = RegSetValueExW(instance_clsid_key, clsid_valuename, 0, REG_SZ,
557 (CONST BYTE*)(buf), 78);
558 RegCloseKey(instance_clsid_key);
560 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
562 if (list->author) {
563 res = RegSetValueExA(clsid_key, author_valuename, 0, REG_SZ,
564 (CONST BYTE*)(list->author),
565 strlen(list->author) + 1);
566 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
569 if (list->friendlyname) {
570 res = RegSetValueExA(clsid_key, friendlyname_valuename, 0, REG_SZ,
571 (CONST BYTE*)(list->friendlyname),
572 strlen(list->friendlyname) + 1);
573 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
576 if (list->vendor) {
577 StringFromGUID2(list->vendor, buf, 39);
578 res = RegSetValueExW(clsid_key, vendor_valuename, 0, REG_SZ,
579 (CONST BYTE*)(buf), 78);
580 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
583 if (list->version) {
584 res = RegSetValueExA(clsid_key, version_valuename, 0, REG_SZ,
585 (CONST BYTE*)(list->version),
586 strlen(list->version) + 1);
587 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
590 if (list->formats) {
591 HKEY formats_key;
592 GUID const * const *format;
594 res = RegCreateKeyExW(clsid_key, pixelformats_keyname, 0, NULL, 0,
595 KEY_READ | KEY_WRITE, NULL, &formats_key, NULL);
596 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
597 for (format=list->formats; *format; ++format)
599 HKEY format_key;
600 StringFromGUID2(*format, buf, 39);
601 res = RegCreateKeyExW(formats_key, buf, 0, NULL, 0,
602 KEY_READ | KEY_WRITE, NULL, &format_key, NULL);
603 if (res != ERROR_SUCCESS) break;
604 RegCloseKey(format_key);
606 RegCloseKey(formats_key);
607 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
610 error_close_clsid_key:
611 RegCloseKey(clsid_key);
614 error_close_coclass_key:
615 RegCloseKey(instance_key);
616 RegCloseKey(converters_key);
617 RegCloseKey(coclass_key);
618 error_return:
619 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
622 /***********************************************************************
623 * unregister_converters
625 static HRESULT unregister_converters(struct regsvr_converter const *list)
627 LONG res = ERROR_SUCCESS;
628 HKEY coclass_key;
629 WCHAR buf[39];
630 HKEY converters_key;
631 HKEY instance_key;
633 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0,
634 KEY_READ | KEY_WRITE, &coclass_key);
635 if (res == ERROR_FILE_NOT_FOUND) return S_OK;
637 if (res == ERROR_SUCCESS) {
638 StringFromGUID2(&CATID_WICFormatConverters, buf, 39);
639 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
640 KEY_READ | KEY_WRITE, NULL, &converters_key, NULL);
641 if (res == ERROR_SUCCESS)
643 res = RegCreateKeyExW(converters_key, instance_keyname, 0, NULL, 0,
644 KEY_READ | KEY_WRITE, NULL, &instance_key, NULL);
645 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
647 if (res != ERROR_SUCCESS)
648 RegCloseKey(coclass_key);
650 if (res != ERROR_SUCCESS) goto error_return;
652 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
653 StringFromGUID2(list->clsid, buf, 39);
655 res = RegDeleteTreeW(coclass_key, buf);
656 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
657 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
659 res = RegDeleteTreeW(instance_key, buf);
660 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
661 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
664 error_close_coclass_key:
665 RegCloseKey(instance_key);
666 RegCloseKey(converters_key);
667 RegCloseKey(coclass_key);
668 error_return:
669 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
672 /***********************************************************************
673 * decoder list
675 static const BYTE mask_all[] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
677 static const BYTE bmp_magic[] = {0x42,0x4d};
679 static GUID const * const bmp_formats[] = {
680 &GUID_WICPixelFormat1bppIndexed,
681 &GUID_WICPixelFormat2bppIndexed,
682 &GUID_WICPixelFormat4bppIndexed,
683 &GUID_WICPixelFormat8bppIndexed,
684 &GUID_WICPixelFormat16bppBGR555,
685 &GUID_WICPixelFormat16bppBGR565,
686 &GUID_WICPixelFormat24bppBGR,
687 &GUID_WICPixelFormat32bppBGR,
688 &GUID_WICPixelFormat32bppBGRA,
689 NULL
692 static struct decoder_pattern const bmp_patterns[] = {
693 {2,0,bmp_magic,mask_all,0},
697 static const BYTE gif87a_magic[6] = "GIF87a";
698 static const BYTE gif89a_magic[6] = "GIF89a";
700 static GUID const * const gif_formats[] = {
701 &GUID_WICPixelFormat8bppIndexed,
702 NULL
705 static struct decoder_pattern const gif_patterns[] = {
706 {6,0,gif87a_magic,mask_all,0},
707 {6,0,gif89a_magic,mask_all,0},
711 static const BYTE ico_magic[] = {00,00,01,00};
713 static GUID const * const ico_formats[] = {
714 &GUID_WICPixelFormat32bppBGRA,
715 NULL
718 static struct decoder_pattern const ico_patterns[] = {
719 {4,0,ico_magic,mask_all,0},
723 static const BYTE jpeg_magic[] = {0xff, 0xd8};
725 static GUID const * const jpeg_formats[] = {
726 &GUID_WICPixelFormat24bppBGR,
727 &GUID_WICPixelFormat32bppCMYK,
728 &GUID_WICPixelFormat8bppGray,
729 NULL
732 static struct decoder_pattern const jpeg_patterns[] = {
733 {2,0,jpeg_magic,mask_all,0},
737 static const BYTE png_magic[] = {137,80,78,71,13,10,26,10};
739 static GUID const * const png_formats[] = {
740 &GUID_WICPixelFormatBlackWhite,
741 &GUID_WICPixelFormat2bppGray,
742 &GUID_WICPixelFormat4bppGray,
743 &GUID_WICPixelFormat8bppGray,
744 &GUID_WICPixelFormat16bppGray,
745 &GUID_WICPixelFormat32bppBGRA,
746 &GUID_WICPixelFormat64bppRGBA,
747 &GUID_WICPixelFormat1bppIndexed,
748 &GUID_WICPixelFormat2bppIndexed,
749 &GUID_WICPixelFormat4bppIndexed,
750 &GUID_WICPixelFormat8bppIndexed,
751 &GUID_WICPixelFormat24bppBGR,
752 &GUID_WICPixelFormat48bppRGB,
753 NULL
756 static struct decoder_pattern const png_patterns[] = {
757 {8,0,png_magic,mask_all,0},
761 static const BYTE tiff_magic_le[] = {0x49,0x49,42,0};
762 static const BYTE tiff_magic_be[] = {0x4d,0x4d,0,42};
764 static GUID const * const tiff_decode_formats[] = {
765 &GUID_WICPixelFormatBlackWhite,
766 &GUID_WICPixelFormat4bppGray,
767 &GUID_WICPixelFormat8bppGray,
768 &GUID_WICPixelFormat4bppIndexed,
769 &GUID_WICPixelFormat8bppIndexed,
770 &GUID_WICPixelFormat24bppBGR,
771 &GUID_WICPixelFormat32bppBGR,
772 &GUID_WICPixelFormat32bppBGRA,
773 &GUID_WICPixelFormat32bppPBGRA,
774 &GUID_WICPixelFormat48bppRGB,
775 &GUID_WICPixelFormat64bppRGBA,
776 &GUID_WICPixelFormat64bppPRGBA,
777 NULL
780 static struct decoder_pattern const tiff_patterns[] = {
781 {4,0,tiff_magic_le,mask_all,0},
782 {4,0,tiff_magic_be,mask_all,0},
786 static const BYTE tga_footer_magic[18] = "TRUEVISION-XFILE.";
788 static const BYTE tga_indexed_magic[18] = {0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0};
789 static const BYTE tga_indexed_mask[18] = {0,0xff,0xf7,0,0,0,0,0,0,0,0,0,0,0,0,0,0xff,0xcf};
791 static const BYTE tga_truecolor_magic[18] = {0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
792 static const BYTE tga_truecolor_mask[18] = {0,0xff,0xf7,0,0,0,0,0,0,0,0,0,0,0,0,0,0x87,0xc0};
794 static const BYTE tga_grayscale_magic[18] = {0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0};
795 static const BYTE tga_grayscale_mask[18] = {0,0xff,0xf7,0,0,0,0,0,0,0,0,0,0,0,0,0,0xff,0xcf};
797 static GUID const * const tga_formats[] = {
798 &GUID_WICPixelFormat8bppGray,
799 &GUID_WICPixelFormat8bppIndexed,
800 &GUID_WICPixelFormat16bppGray,
801 &GUID_WICPixelFormat16bppBGR555,
802 &GUID_WICPixelFormat24bppBGR,
803 &GUID_WICPixelFormat32bppBGRA,
804 &GUID_WICPixelFormat32bppPBGRA,
805 NULL
808 static struct decoder_pattern const tga_patterns[] = {
809 {18,18,tga_footer_magic,mask_all,1},
810 {18,0,tga_indexed_magic,tga_indexed_mask,0},
811 {18,0,tga_truecolor_magic,tga_truecolor_mask,0},
812 {18,0,tga_grayscale_magic,tga_grayscale_mask,0},
816 static struct regsvr_decoder const decoder_list[] = {
817 { &CLSID_WICBmpDecoder,
818 "The Wine Project",
819 "BMP Decoder",
820 "1.0.0.0",
821 &GUID_VendorMicrosoft,
822 "image/bmp",
823 ".bmp,.dib,.rle",
824 bmp_formats,
825 bmp_patterns
827 { &CLSID_WICGifDecoder,
828 "The Wine Project",
829 "GIF Decoder",
830 "1.0.0.0",
831 &GUID_VendorMicrosoft,
832 "image/gif",
833 ".gif",
834 gif_formats,
835 gif_patterns
837 { &CLSID_WICIcoDecoder,
838 "The Wine Project",
839 "ICO Decoder",
840 "1.0.0.0",
841 &GUID_VendorMicrosoft,
842 "image/vnd.microsoft.icon",
843 ".ico",
844 ico_formats,
845 ico_patterns
847 { &CLSID_WICJpegDecoder,
848 "The Wine Project",
849 "JPEG Decoder",
850 "1.0.0.0",
851 &GUID_VendorMicrosoft,
852 "image/jpeg",
853 ".jpg;.jpeg;.jfif",
854 jpeg_formats,
855 jpeg_patterns
857 { &CLSID_WICPngDecoder,
858 "The Wine Project",
859 "PNG Decoder",
860 "1.0.0.0",
861 &GUID_VendorMicrosoft,
862 "image/png",
863 ".png",
864 png_formats,
865 png_patterns
867 { &CLSID_WICTiffDecoder,
868 "The Wine Project",
869 "TIFF Decoder",
870 "1.0.0.0",
871 &GUID_VendorMicrosoft,
872 "image/tiff",
873 ".tif;.tiff",
874 tiff_decode_formats,
875 tiff_patterns
877 { &CLSID_WineTgaDecoder,
878 "The Wine Project",
879 "TGA Decoder",
880 "1.0.0.0",
881 &GUID_VendorWine,
882 "image/x-targa",
883 ".tga;.tpic",
884 tga_formats,
885 tga_patterns
887 { NULL } /* list terminator */
890 static GUID const * const bmp_encode_formats[] = {
891 &GUID_WICPixelFormat16bppBGR555,
892 &GUID_WICPixelFormat16bppBGR565,
893 &GUID_WICPixelFormat24bppBGR,
894 &GUID_WICPixelFormat32bppBGR,
895 NULL
898 static GUID const * const png_encode_formats[] = {
899 &GUID_WICPixelFormat24bppBGR,
900 &GUID_WICPixelFormatBlackWhite,
901 &GUID_WICPixelFormat2bppGray,
902 &GUID_WICPixelFormat4bppGray,
903 &GUID_WICPixelFormat8bppGray,
904 &GUID_WICPixelFormat16bppGray,
905 &GUID_WICPixelFormat32bppBGR,
906 &GUID_WICPixelFormat32bppBGRA,
907 &GUID_WICPixelFormat48bppRGB,
908 &GUID_WICPixelFormat64bppRGBA,
909 NULL
912 static GUID const * const tiff_encode_formats[] = {
913 &GUID_WICPixelFormatBlackWhite,
914 &GUID_WICPixelFormat4bppGray,
915 &GUID_WICPixelFormat8bppGray,
916 &GUID_WICPixelFormat24bppBGR,
917 &GUID_WICPixelFormat32bppBGRA,
918 &GUID_WICPixelFormat32bppPBGRA,
919 &GUID_WICPixelFormat48bppRGB,
920 &GUID_WICPixelFormat64bppRGBA,
921 &GUID_WICPixelFormat64bppPRGBA,
922 NULL
925 static GUID const * const icns_encode_formats[] = {
926 &GUID_WICPixelFormat32bppBGRA,
927 NULL
930 static struct regsvr_encoder const encoder_list[] = {
931 { &CLSID_WICBmpEncoder,
932 "The Wine Project",
933 "BMP Encoder",
934 "1.0.0.0",
935 &GUID_VendorMicrosoft,
936 "image/bmp",
937 ".bmp,.dib,.rle",
938 bmp_encode_formats
940 { &CLSID_WICPngEncoder,
941 "The Wine Project",
942 "PNG Encoder",
943 "1.0.0.0",
944 &GUID_VendorMicrosoft,
945 "image/png",
946 ".png",
947 png_encode_formats
949 { &CLSID_WICTiffEncoder,
950 "The Wine Project",
951 "TIFF Encoder",
952 "1.0.0.0",
953 &GUID_VendorMicrosoft,
954 "image/tiff",
955 ".tif;.tiff",
956 tiff_encode_formats
958 { &CLSID_WICIcnsEncoder,
959 "The Wine Project",
960 "ICNS Encoder",
961 "1.0.0.0",
962 &GUID_VendorWine,
963 "image/icns",
964 ".icns",
965 icns_encode_formats
967 { NULL } /* list terminator */
970 static GUID const * const converter_formats[] = {
971 &GUID_WICPixelFormat1bppIndexed,
972 &GUID_WICPixelFormat2bppIndexed,
973 &GUID_WICPixelFormat4bppIndexed,
974 &GUID_WICPixelFormat8bppIndexed,
975 &GUID_WICPixelFormatBlackWhite,
976 &GUID_WICPixelFormat2bppGray,
977 &GUID_WICPixelFormat4bppGray,
978 &GUID_WICPixelFormat8bppGray,
979 &GUID_WICPixelFormat16bppGray,
980 &GUID_WICPixelFormat16bppBGR555,
981 &GUID_WICPixelFormat16bppBGR565,
982 &GUID_WICPixelFormat16bppBGRA5551,
983 &GUID_WICPixelFormat24bppBGR,
984 &GUID_WICPixelFormat32bppBGR,
985 &GUID_WICPixelFormat32bppBGRA,
986 &GUID_WICPixelFormat32bppPBGRA,
987 &GUID_WICPixelFormat48bppRGB,
988 &GUID_WICPixelFormat64bppRGBA,
989 &GUID_WICPixelFormat32bppCMYK,
990 NULL
993 static struct regsvr_converter const converter_list[] = {
994 { &CLSID_WICDefaultFormatConverter,
995 "The Wine Project",
996 "Default Pixel Format Converter",
997 "1.0.0.0",
998 &GUID_VendorMicrosoft,
999 converter_formats
1001 { NULL } /* list terminator */
1004 extern HRESULT WINAPI WIC_DllRegisterServer(void) DECLSPEC_HIDDEN;
1005 extern HRESULT WINAPI WIC_DllUnregisterServer(void) DECLSPEC_HIDDEN;
1007 HRESULT WINAPI DllRegisterServer(void)
1009 HRESULT hr;
1011 TRACE("\n");
1013 hr = WIC_DllRegisterServer();
1014 if (SUCCEEDED(hr))
1015 register_decoders(decoder_list);
1016 if (SUCCEEDED(hr))
1017 register_encoders(encoder_list);
1018 if (SUCCEEDED(hr))
1019 register_converters(converter_list);
1020 return hr;
1023 HRESULT WINAPI DllUnregisterServer(void)
1025 HRESULT hr;
1027 TRACE("\n");
1029 hr = WIC_DllUnregisterServer();
1030 if (SUCCEEDED(hr))
1031 unregister_decoders(decoder_list);
1032 if (SUCCEEDED(hr))
1033 unregister_encoders(encoder_list);
1034 if (SUCCEEDED(hr))
1035 unregister_converters(converter_list);
1036 return hr;