windowscodecs: Add support for decoding 48-bit TIFF images.
[wine/multimedia.git] / dlls / windowscodecs / regsvr.c
blob02886335a673fb685c8ffceb229cd30a6fdf24df
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 regsvr_coclass
48 CLSID const *clsid; /* NULL for end of list */
49 LPCSTR name; /* can be NULL to omit */
50 LPCSTR ips; /* can be NULL to omit */
51 LPCSTR ips32; /* can be NULL to omit */
52 LPCSTR ips32_tmodel; /* can be NULL to omit */
53 LPCSTR progid; /* can be NULL to omit */
54 LPCSTR viprogid; /* can be NULL to omit */
55 LPCSTR progid_extra; /* can be NULL to omit */
58 static HRESULT register_coclasses(struct regsvr_coclass const *list);
59 static HRESULT unregister_coclasses(struct regsvr_coclass const *list);
61 struct decoder_pattern
63 DWORD length; /* 0 for end of list */
64 DWORD position;
65 const BYTE *pattern;
66 const BYTE *mask;
67 DWORD endofstream;
70 struct regsvr_decoder
72 CLSID const *clsid; /* NULL for end of list */
73 LPCSTR author;
74 LPCSTR friendlyname;
75 LPCSTR version;
76 GUID const *vendor;
77 LPCSTR mimetypes;
78 LPCSTR extensions;
79 GUID const * const *formats;
80 const struct decoder_pattern *patterns;
83 static HRESULT register_decoders(struct regsvr_decoder const *list);
84 static HRESULT unregister_decoders(struct regsvr_decoder const *list);
86 struct regsvr_converter
88 CLSID const *clsid; /* NULL for end of list */
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[6] = {
103 'C', 'L', 'S', 'I', 'D', 0 };
104 static WCHAR const curver_keyname[7] = {
105 'C', 'u', 'r', 'V', 'e', 'r', 0 };
106 static WCHAR const ips_keyname[13] = {
107 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
108 0 };
109 static WCHAR const ips32_keyname[15] = {
110 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
111 '3', '2', 0 };
112 static WCHAR const progid_keyname[7] = {
113 'P', 'r', 'o', 'g', 'I', 'D', 0 };
114 static WCHAR const viprogid_keyname[25] = {
115 'V', 'e', 'r', 's', 'i', 'o', 'n', 'I', 'n', 'd', 'e', 'p',
116 'e', 'n', 'd', 'e', 'n', 't', 'P', 'r', 'o', 'g', 'I', 'D',
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 * static helper functions
139 static LONG register_key_defvalueW(HKEY base, WCHAR const *name,
140 WCHAR const *value);
141 static LONG register_key_defvalueA(HKEY base, WCHAR const *name,
142 char const *value);
143 static LONG register_progid(WCHAR const *clsid,
144 char const *progid, char const *curver_progid,
145 char const *name, char const *extra);
147 /***********************************************************************
148 * register_coclasses
150 static HRESULT register_coclasses(struct regsvr_coclass const *list)
152 LONG res = ERROR_SUCCESS;
153 HKEY coclass_key;
155 res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0,
156 KEY_READ | KEY_WRITE, NULL, &coclass_key, NULL);
157 if (res != ERROR_SUCCESS) goto error_return;
159 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
160 WCHAR buf[39];
161 HKEY clsid_key;
163 StringFromGUID2(list->clsid, buf, 39);
164 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
165 KEY_READ | KEY_WRITE, NULL, &clsid_key, NULL);
166 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
168 if (list->name) {
169 res = RegSetValueExA(clsid_key, NULL, 0, REG_SZ,
170 (CONST BYTE*)(list->name),
171 strlen(list->name) + 1);
172 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
175 if (list->ips) {
176 res = register_key_defvalueA(clsid_key, ips_keyname, list->ips);
177 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
180 if (list->ips32) {
181 HKEY ips32_key;
183 res = RegCreateKeyExW(clsid_key, ips32_keyname, 0, NULL, 0,
184 KEY_READ | KEY_WRITE, NULL,
185 &ips32_key, NULL);
186 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
188 res = RegSetValueExA(ips32_key, NULL, 0, REG_SZ,
189 (CONST BYTE*)list->ips32,
190 lstrlenA(list->ips32) + 1);
191 if (res == ERROR_SUCCESS && list->ips32_tmodel)
192 res = RegSetValueExA(ips32_key, tmodel_valuename, 0, REG_SZ,
193 (CONST BYTE*)list->ips32_tmodel,
194 strlen(list->ips32_tmodel) + 1);
195 RegCloseKey(ips32_key);
196 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
199 if (list->progid) {
200 res = register_key_defvalueA(clsid_key, progid_keyname,
201 list->progid);
202 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
204 res = register_progid(buf, list->progid, NULL,
205 list->name, list->progid_extra);
206 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
209 if (list->viprogid) {
210 res = register_key_defvalueA(clsid_key, viprogid_keyname,
211 list->viprogid);
212 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
214 res = register_progid(buf, list->viprogid, list->progid,
215 list->name, list->progid_extra);
216 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
219 error_close_clsid_key:
220 RegCloseKey(clsid_key);
223 error_close_coclass_key:
224 RegCloseKey(coclass_key);
225 error_return:
226 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
229 /***********************************************************************
230 * unregister_coclasses
232 static HRESULT unregister_coclasses(struct regsvr_coclass const *list)
234 LONG res = ERROR_SUCCESS;
235 HKEY coclass_key;
237 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0,
238 KEY_READ | KEY_WRITE, &coclass_key);
239 if (res == ERROR_FILE_NOT_FOUND) return S_OK;
240 if (res != ERROR_SUCCESS) goto error_return;
242 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
243 WCHAR buf[39];
245 StringFromGUID2(list->clsid, buf, 39);
246 res = RegDeleteTreeW(coclass_key, buf);
247 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
248 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
250 if (list->progid) {
251 res = RegDeleteTreeA(HKEY_CLASSES_ROOT, list->progid);
252 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
253 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
256 if (list->viprogid) {
257 res = RegDeleteTreeA(HKEY_CLASSES_ROOT, list->viprogid);
258 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
259 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
263 error_close_coclass_key:
264 RegCloseKey(coclass_key);
265 error_return:
266 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
269 /***********************************************************************
270 * register_decoders
272 static HRESULT register_decoders(struct regsvr_decoder const *list)
274 LONG res = ERROR_SUCCESS;
275 HKEY coclass_key;
276 WCHAR buf[39];
277 HKEY decoders_key;
278 HKEY instance_key;
280 res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0,
281 KEY_READ | KEY_WRITE, NULL, &coclass_key, NULL);
282 if (res == ERROR_SUCCESS) {
283 StringFromGUID2(&CATID_WICBitmapDecoders, buf, 39);
284 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
285 KEY_READ | KEY_WRITE, NULL, &decoders_key, NULL);
286 if (res == ERROR_SUCCESS)
288 res = RegCreateKeyExW(decoders_key, instance_keyname, 0, NULL, 0,
289 KEY_READ | KEY_WRITE, NULL, &instance_key, NULL);
290 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
292 if (res != ERROR_SUCCESS)
293 RegCloseKey(coclass_key);
295 if (res != ERROR_SUCCESS) goto error_return;
297 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
298 HKEY clsid_key;
299 HKEY instance_clsid_key;
301 StringFromGUID2(list->clsid, buf, 39);
302 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
303 KEY_READ | KEY_WRITE, NULL, &clsid_key, NULL);
304 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
306 StringFromGUID2(list->clsid, buf, 39);
307 res = RegCreateKeyExW(instance_key, buf, 0, NULL, 0,
308 KEY_READ | KEY_WRITE, NULL, &instance_clsid_key, NULL);
309 if (res == ERROR_SUCCESS) {
310 res = RegSetValueExW(instance_clsid_key, clsid_valuename, 0, REG_SZ,
311 (CONST BYTE*)(buf), 78);
312 RegCloseKey(instance_clsid_key);
314 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
316 if (list->author) {
317 res = RegSetValueExA(clsid_key, author_valuename, 0, REG_SZ,
318 (CONST BYTE*)(list->author),
319 strlen(list->author) + 1);
320 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
323 if (list->friendlyname) {
324 res = RegSetValueExA(clsid_key, friendlyname_valuename, 0, REG_SZ,
325 (CONST BYTE*)(list->friendlyname),
326 strlen(list->friendlyname) + 1);
327 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
330 if (list->vendor) {
331 StringFromGUID2(list->vendor, buf, 39);
332 res = RegSetValueExW(clsid_key, vendor_valuename, 0, REG_SZ,
333 (CONST BYTE*)(buf), 78);
334 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
337 if (list->version) {
338 res = RegSetValueExA(clsid_key, version_valuename, 0, REG_SZ,
339 (CONST BYTE*)(list->version),
340 strlen(list->version) + 1);
341 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
344 if (list->mimetypes) {
345 res = RegSetValueExA(clsid_key, mimetypes_valuename, 0, REG_SZ,
346 (CONST BYTE*)(list->mimetypes),
347 strlen(list->mimetypes) + 1);
348 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
351 if (list->extensions) {
352 res = RegSetValueExA(clsid_key, extensions_valuename, 0, REG_SZ,
353 (CONST BYTE*)(list->extensions),
354 strlen(list->extensions) + 1);
355 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
358 if (list->formats) {
359 HKEY formats_key;
360 GUID const * const *format;
362 res = RegCreateKeyExW(clsid_key, formats_keyname, 0, NULL, 0,
363 KEY_READ | KEY_WRITE, NULL, &formats_key, NULL);
364 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
365 for (format=list->formats; *format; ++format)
367 HKEY format_key;
368 StringFromGUID2(*format, buf, 39);
369 res = RegCreateKeyExW(formats_key, buf, 0, NULL, 0,
370 KEY_READ | KEY_WRITE, NULL, &format_key, NULL);
371 if (res != ERROR_SUCCESS) break;
372 RegCloseKey(format_key);
374 RegCloseKey(formats_key);
375 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
378 if (list->patterns) {
379 HKEY patterns_key;
380 int i;
382 res = RegCreateKeyExW(clsid_key, patterns_keyname, 0, NULL, 0,
383 KEY_READ | KEY_WRITE, NULL, &patterns_key, NULL);
384 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
385 for (i=0; list->patterns[i].length; i++)
387 HKEY pattern_key;
388 static const WCHAR int_format[] = {'%','i',0};
389 snprintfW(buf, 39, int_format, i);
390 res = RegCreateKeyExW(patterns_key, buf, 0, NULL, 0,
391 KEY_READ | KEY_WRITE, NULL, &pattern_key, NULL);
392 if (res != ERROR_SUCCESS) break;
393 res = RegSetValueExA(pattern_key, length_valuename, 0, REG_DWORD,
394 (CONST BYTE*)(&list->patterns[i].length), 4);
395 if (res == ERROR_SUCCESS)
396 res = RegSetValueExA(pattern_key, position_valuename, 0, REG_DWORD,
397 (CONST BYTE*)(&list->patterns[i].position), 4);
398 if (res == ERROR_SUCCESS)
399 res = RegSetValueExA(pattern_key, pattern_valuename, 0, REG_BINARY,
400 list->patterns[i].pattern,
401 list->patterns[i].length);
402 if (res == ERROR_SUCCESS)
403 res = RegSetValueExA(pattern_key, mask_valuename, 0, REG_BINARY,
404 list->patterns[i].mask,
405 list->patterns[i].length);
406 if (res == ERROR_SUCCESS)
407 res = RegSetValueExA(pattern_key, endofstream_valuename, 0, REG_DWORD,
408 (CONST BYTE*)&(list->patterns[i].endofstream), 4);
409 RegCloseKey(pattern_key);
411 RegCloseKey(patterns_key);
412 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
415 error_close_clsid_key:
416 RegCloseKey(clsid_key);
419 error_close_coclass_key:
420 RegCloseKey(instance_key);
421 RegCloseKey(decoders_key);
422 RegCloseKey(coclass_key);
423 error_return:
424 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
427 /***********************************************************************
428 * unregister_decoders
430 static HRESULT unregister_decoders(struct regsvr_decoder const *list)
432 LONG res = ERROR_SUCCESS;
433 HKEY coclass_key;
434 WCHAR buf[39];
435 HKEY decoders_key;
436 HKEY instance_key;
438 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0,
439 KEY_READ | KEY_WRITE, &coclass_key);
440 if (res == ERROR_FILE_NOT_FOUND) return S_OK;
442 if (res == ERROR_SUCCESS) {
443 StringFromGUID2(&CATID_WICBitmapDecoders, buf, 39);
444 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
445 KEY_READ | KEY_WRITE, NULL, &decoders_key, NULL);
446 if (res == ERROR_SUCCESS)
448 res = RegCreateKeyExW(decoders_key, instance_keyname, 0, NULL, 0,
449 KEY_READ | KEY_WRITE, NULL, &instance_key, NULL);
450 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
452 if (res != ERROR_SUCCESS)
453 RegCloseKey(coclass_key);
455 if (res != ERROR_SUCCESS) goto error_return;
457 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
458 StringFromGUID2(list->clsid, buf, 39);
460 res = RegDeleteTreeW(coclass_key, buf);
461 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
462 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
464 res = RegDeleteTreeW(instance_key, buf);
465 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
466 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
469 error_close_coclass_key:
470 RegCloseKey(instance_key);
471 RegCloseKey(decoders_key);
472 RegCloseKey(coclass_key);
473 error_return:
474 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
477 /***********************************************************************
478 * register_converters
480 static HRESULT register_converters(struct regsvr_converter const *list)
482 LONG res = ERROR_SUCCESS;
483 HKEY coclass_key;
484 WCHAR buf[39];
485 HKEY converters_key;
486 HKEY instance_key;
488 res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0,
489 KEY_READ | KEY_WRITE, NULL, &coclass_key, NULL);
490 if (res == ERROR_SUCCESS) {
491 StringFromGUID2(&CATID_WICFormatConverters, buf, 39);
492 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
493 KEY_READ | KEY_WRITE, NULL, &converters_key, NULL);
494 if (res == ERROR_SUCCESS)
496 res = RegCreateKeyExW(converters_key, instance_keyname, 0, NULL, 0,
497 KEY_READ | KEY_WRITE, NULL, &instance_key, NULL);
498 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
500 if (res != ERROR_SUCCESS)
501 RegCloseKey(coclass_key);
503 if (res != ERROR_SUCCESS) goto error_return;
505 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
506 HKEY clsid_key;
507 HKEY instance_clsid_key;
509 StringFromGUID2(list->clsid, buf, 39);
510 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
511 KEY_READ | KEY_WRITE, NULL, &clsid_key, NULL);
512 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
514 StringFromGUID2(list->clsid, buf, 39);
515 res = RegCreateKeyExW(instance_key, buf, 0, NULL, 0,
516 KEY_READ | KEY_WRITE, NULL, &instance_clsid_key, NULL);
517 if (res == ERROR_SUCCESS) {
518 res = RegSetValueExW(instance_clsid_key, clsid_valuename, 0, REG_SZ,
519 (CONST BYTE*)(buf), 78);
520 RegCloseKey(instance_clsid_key);
522 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
524 if (list->author) {
525 res = RegSetValueExA(clsid_key, author_valuename, 0, REG_SZ,
526 (CONST BYTE*)(list->author),
527 strlen(list->author) + 1);
528 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
531 if (list->friendlyname) {
532 res = RegSetValueExA(clsid_key, friendlyname_valuename, 0, REG_SZ,
533 (CONST BYTE*)(list->friendlyname),
534 strlen(list->friendlyname) + 1);
535 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
538 if (list->vendor) {
539 StringFromGUID2(list->vendor, buf, 39);
540 res = RegSetValueExW(clsid_key, vendor_valuename, 0, REG_SZ,
541 (CONST BYTE*)(buf), 78);
542 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
545 if (list->version) {
546 res = RegSetValueExA(clsid_key, version_valuename, 0, REG_SZ,
547 (CONST BYTE*)(list->version),
548 strlen(list->version) + 1);
549 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
552 if (list->formats) {
553 HKEY formats_key;
554 GUID const * const *format;
556 res = RegCreateKeyExW(clsid_key, pixelformats_keyname, 0, NULL, 0,
557 KEY_READ | KEY_WRITE, NULL, &formats_key, NULL);
558 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
559 for (format=list->formats; *format; ++format)
561 HKEY format_key;
562 StringFromGUID2(*format, buf, 39);
563 res = RegCreateKeyExW(formats_key, buf, 0, NULL, 0,
564 KEY_READ | KEY_WRITE, NULL, &format_key, NULL);
565 if (res != ERROR_SUCCESS) break;
566 RegCloseKey(format_key);
568 RegCloseKey(formats_key);
569 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
572 error_close_clsid_key:
573 RegCloseKey(clsid_key);
576 error_close_coclass_key:
577 RegCloseKey(instance_key);
578 RegCloseKey(converters_key);
579 RegCloseKey(coclass_key);
580 error_return:
581 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
584 /***********************************************************************
585 * unregister_converters
587 static HRESULT unregister_converters(struct regsvr_converter const *list)
589 LONG res = ERROR_SUCCESS;
590 HKEY coclass_key;
591 WCHAR buf[39];
592 HKEY converters_key;
593 HKEY instance_key;
595 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0,
596 KEY_READ | KEY_WRITE, &coclass_key);
597 if (res == ERROR_FILE_NOT_FOUND) return S_OK;
599 if (res == ERROR_SUCCESS) {
600 StringFromGUID2(&CATID_WICFormatConverters, buf, 39);
601 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
602 KEY_READ | KEY_WRITE, NULL, &converters_key, NULL);
603 if (res == ERROR_SUCCESS)
605 res = RegCreateKeyExW(converters_key, instance_keyname, 0, NULL, 0,
606 KEY_READ | KEY_WRITE, NULL, &instance_key, NULL);
607 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
609 if (res != ERROR_SUCCESS)
610 RegCloseKey(coclass_key);
612 if (res != ERROR_SUCCESS) goto error_return;
614 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
615 StringFromGUID2(list->clsid, buf, 39);
617 res = RegDeleteTreeW(coclass_key, buf);
618 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
619 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
621 res = RegDeleteTreeW(instance_key, buf);
622 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
623 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
626 error_close_coclass_key:
627 RegCloseKey(instance_key);
628 RegCloseKey(converters_key);
629 RegCloseKey(coclass_key);
630 error_return:
631 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
634 /***********************************************************************
635 * register_key_defvalueW
637 static LONG register_key_defvalueW(
638 HKEY base,
639 WCHAR const *name,
640 WCHAR const *value)
642 LONG res;
643 HKEY key;
645 res = RegCreateKeyExW(base, name, 0, NULL, 0,
646 KEY_READ | KEY_WRITE, NULL, &key, NULL);
647 if (res != ERROR_SUCCESS) return res;
648 res = RegSetValueExW(key, NULL, 0, REG_SZ, (CONST BYTE*)value,
649 (lstrlenW(value) + 1) * sizeof(WCHAR));
650 RegCloseKey(key);
651 return res;
654 /***********************************************************************
655 * register_key_defvalueA
657 static LONG register_key_defvalueA(
658 HKEY base,
659 WCHAR const *name,
660 char const *value)
662 LONG res;
663 HKEY key;
665 res = RegCreateKeyExW(base, name, 0, NULL, 0,
666 KEY_READ | KEY_WRITE, NULL, &key, NULL);
667 if (res != ERROR_SUCCESS) return res;
668 res = RegSetValueExA(key, NULL, 0, REG_SZ, (CONST BYTE*)value,
669 lstrlenA(value) + 1);
670 RegCloseKey(key);
671 return res;
674 /***********************************************************************
675 * register_progid
677 static LONG register_progid(
678 WCHAR const *clsid,
679 char const *progid,
680 char const *curver_progid,
681 char const *name,
682 char const *extra)
684 LONG res;
685 HKEY progid_key;
687 res = RegCreateKeyExA(HKEY_CLASSES_ROOT, progid, 0,
688 NULL, 0, KEY_READ | KEY_WRITE, NULL,
689 &progid_key, NULL);
690 if (res != ERROR_SUCCESS) return res;
692 if (name) {
693 res = RegSetValueExA(progid_key, NULL, 0, REG_SZ,
694 (CONST BYTE*)name, strlen(name) + 1);
695 if (res != ERROR_SUCCESS) goto error_close_progid_key;
698 if (clsid) {
699 res = register_key_defvalueW(progid_key, clsid_keyname, clsid);
700 if (res != ERROR_SUCCESS) goto error_close_progid_key;
703 if (curver_progid) {
704 res = register_key_defvalueA(progid_key, curver_keyname,
705 curver_progid);
706 if (res != ERROR_SUCCESS) goto error_close_progid_key;
709 if (extra) {
710 HKEY extra_key;
712 res = RegCreateKeyExA(progid_key, extra, 0,
713 NULL, 0, KEY_READ | KEY_WRITE, NULL,
714 &extra_key, NULL);
715 if (res == ERROR_SUCCESS)
716 RegCloseKey(extra_key);
719 error_close_progid_key:
720 RegCloseKey(progid_key);
721 return res;
724 /***********************************************************************
725 * coclass list
727 static struct regsvr_coclass const coclass_list[] = {
728 { &CLSID_WICImagingFactory,
729 "WIC Imaging Factory",
730 NULL,
731 "windowscodecs.dll",
732 "Both"
734 { &CLSID_WICBmpDecoder,
735 "WIC BMP Decoder",
736 NULL,
737 "windowscodecs.dll",
738 "Both"
740 { &CLSID_WICPngDecoder,
741 "WIC PNG Decoder",
742 NULL,
743 "windowscodecs.dll",
744 "Both"
746 { &CLSID_WICPngEncoder,
747 "WIC PNG Encoder",
748 NULL,
749 "windowscodecs.dll",
750 "Both"
752 { &CLSID_WICBmpEncoder,
753 "WIC BMP Encoder",
754 NULL,
755 "windowscodecs.dll",
756 "Apartment"
758 { &CLSID_WICGifDecoder,
759 "WIC GIF Decoder",
760 NULL,
761 "windowscodecs.dll",
762 "Both"
764 { &CLSID_WICIcoDecoder,
765 "WIC ICO Decoder",
766 NULL,
767 "windowscodecs.dll",
768 "Both"
770 { &CLSID_WICJpegDecoder,
771 "WIC JPEG Decoder",
772 NULL,
773 "windowscodecs.dll",
774 "Both"
776 { &CLSID_WICTiffDecoder,
777 "WIC TIFF Decoder",
778 NULL,
779 "windowscodecs.dll",
780 "Both"
783 &CLSID_WICIcnsEncoder,
784 "WIC ICNS Encoder",
785 NULL,
786 "windowscodecs.dll",
787 "Both"
789 { &CLSID_WICDefaultFormatConverter,
790 "WIC Default Format Converter",
791 NULL,
792 "windowscodecs.dll",
793 "Both"
795 { NULL } /* list terminator */
798 /***********************************************************************
799 * decoder list
801 static const BYTE mask_all[] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
803 static const BYTE bmp_magic[] = {0x42,0x4d};
805 static GUID const * const bmp_formats[] = {
806 &GUID_WICPixelFormat1bppIndexed,
807 &GUID_WICPixelFormat2bppIndexed,
808 &GUID_WICPixelFormat4bppIndexed,
809 &GUID_WICPixelFormat8bppIndexed,
810 &GUID_WICPixelFormat16bppBGR555,
811 &GUID_WICPixelFormat16bppBGR565,
812 &GUID_WICPixelFormat24bppBGR,
813 &GUID_WICPixelFormat32bppBGR,
814 &GUID_WICPixelFormat32bppBGRA,
815 NULL
818 static struct decoder_pattern const bmp_patterns[] = {
819 {2,0,bmp_magic,mask_all,0},
823 static const BYTE gif87a_magic[6] = "GIF87a";
824 static const BYTE gif89a_magic[6] = "GIF89a";
826 static GUID const * const gif_formats[] = {
827 &GUID_WICPixelFormat8bppIndexed,
828 NULL
831 static struct decoder_pattern const gif_patterns[] = {
832 {6,0,gif87a_magic,mask_all,0},
833 {6,0,gif89a_magic,mask_all,0},
837 static const BYTE ico_magic[] = {00,00,01,00};
839 static GUID const * const ico_formats[] = {
840 &GUID_WICPixelFormat32bppBGRA,
841 NULL
844 static struct decoder_pattern const ico_patterns[] = {
845 {4,0,ico_magic,mask_all,0},
849 static const BYTE jpeg_magic[] = {0xff, 0xd8, 0xff, 0xe0};
851 static GUID const * const jpeg_formats[] = {
852 &GUID_WICPixelFormat24bppBGR,
853 &GUID_WICPixelFormat8bppGray,
854 NULL
857 static struct decoder_pattern const jpeg_patterns[] = {
858 {4,0,jpeg_magic,mask_all,0},
862 static const BYTE png_magic[] = {137,80,78,71,13,10,26,10};
864 static GUID const * const png_formats[] = {
865 &GUID_WICPixelFormatBlackWhite,
866 &GUID_WICPixelFormat2bppGray,
867 &GUID_WICPixelFormat4bppGray,
868 &GUID_WICPixelFormat8bppGray,
869 &GUID_WICPixelFormat16bppGray,
870 &GUID_WICPixelFormat32bppBGRA,
871 &GUID_WICPixelFormat64bppRGBA,
872 &GUID_WICPixelFormat1bppIndexed,
873 &GUID_WICPixelFormat2bppIndexed,
874 &GUID_WICPixelFormat4bppIndexed,
875 &GUID_WICPixelFormat8bppIndexed,
876 &GUID_WICPixelFormat24bppBGR,
877 &GUID_WICPixelFormat48bppRGB,
878 NULL
881 static struct decoder_pattern const png_patterns[] = {
882 {8,0,png_magic,mask_all,0},
886 static const BYTE tiff_magic_le[] = {0x49,0x49,42,0};
887 static const BYTE tiff_magic_be[] = {0x4d,0x4d,0,42};
889 static GUID const * const tiff_formats[] = {
890 &GUID_WICPixelFormatBlackWhite,
891 &GUID_WICPixelFormat4bppGray,
892 &GUID_WICPixelFormat8bppGray,
893 &GUID_WICPixelFormat4bppIndexed,
894 &GUID_WICPixelFormat8bppIndexed,
895 &GUID_WICPixelFormat32bppBGR,
896 &GUID_WICPixelFormat32bppBGRA,
897 &GUID_WICPixelFormat32bppPBGRA,
898 &GUID_WICPixelFormat48bppRGB,
899 NULL
902 static struct decoder_pattern const tiff_patterns[] = {
903 {4,0,tiff_magic_le,mask_all,0},
904 {4,0,tiff_magic_be,mask_all,0},
908 static struct regsvr_decoder const decoder_list[] = {
909 { &CLSID_WICBmpDecoder,
910 "The Wine Project",
911 "BMP Decoder",
912 "1.0.0.0",
913 &GUID_VendorMicrosoft,
914 "image/bmp",
915 ".bmp,.dib,.rle",
916 bmp_formats,
917 bmp_patterns
919 { &CLSID_WICGifDecoder,
920 "The Wine Project",
921 "GIF Decoder",
922 "1.0.0.0",
923 &GUID_VendorMicrosoft,
924 "image/gif",
925 ".gif",
926 gif_formats,
927 gif_patterns
929 { &CLSID_WICIcoDecoder,
930 "The Wine Project",
931 "ICO Decoder",
932 "1.0.0.0",
933 &GUID_VendorMicrosoft,
934 "image/vnd.microsoft.icon",
935 ".ico",
936 ico_formats,
937 ico_patterns
939 { &CLSID_WICJpegDecoder,
940 "The Wine Project",
941 "JPEG Decoder",
942 "1.0.0.0",
943 &GUID_VendorMicrosoft,
944 "image/jpeg",
945 ".jpg;.jpeg;.jfif",
946 jpeg_formats,
947 jpeg_patterns
949 { &CLSID_WICPngDecoder,
950 "The Wine Project",
951 "PNG Decoder",
952 "1.0.0.0",
953 &GUID_VendorMicrosoft,
954 "image/png",
955 ".png",
956 png_formats,
957 png_patterns
959 { &CLSID_WICTiffDecoder,
960 "The Wine Project",
961 "TIFF Decoder",
962 "1.0.0.0",
963 &GUID_VendorMicrosoft,
964 "image/tiff",
965 ".tif;.tiff",
966 tiff_formats,
967 tiff_patterns
969 { NULL } /* list terminator */
972 static GUID const * const converter_formats[] = {
973 &GUID_WICPixelFormat1bppIndexed,
974 &GUID_WICPixelFormat2bppIndexed,
975 &GUID_WICPixelFormat4bppIndexed,
976 &GUID_WICPixelFormat8bppIndexed,
977 &GUID_WICPixelFormatBlackWhite,
978 &GUID_WICPixelFormat2bppGray,
979 &GUID_WICPixelFormat4bppGray,
980 &GUID_WICPixelFormat8bppGray,
981 &GUID_WICPixelFormat16bppGray,
982 &GUID_WICPixelFormat16bppBGR555,
983 &GUID_WICPixelFormat16bppBGR565,
984 &GUID_WICPixelFormat24bppBGR,
985 &GUID_WICPixelFormat32bppBGR,
986 &GUID_WICPixelFormat32bppBGRA,
987 &GUID_WICPixelFormat48bppRGB,
988 &GUID_WICPixelFormat64bppRGBA,
989 NULL
992 static struct regsvr_converter const converter_list[] = {
993 { &CLSID_WICDefaultFormatConverter,
994 "The Wine Project",
995 "Default Pixel Format Converter",
996 "1.0.0.0",
997 &GUID_VendorMicrosoft,
998 converter_formats
1000 { NULL } /* list terminator */
1003 HRESULT WINAPI DllRegisterServer(void)
1005 HRESULT hr;
1007 TRACE("\n");
1009 hr = register_coclasses(coclass_list);
1010 if (SUCCEEDED(hr))
1011 register_decoders(decoder_list);
1012 if (SUCCEEDED(hr))
1013 register_converters(converter_list);
1014 return hr;
1017 HRESULT WINAPI DllUnregisterServer(void)
1019 HRESULT hr;
1021 TRACE("\n");
1023 hr = unregister_coclasses(coclass_list);
1024 if (SUCCEEDED(hr))
1025 unregister_decoders(decoder_list);
1026 if (SUCCEEDED(hr))
1027 unregister_converters(converter_list);
1028 return hr;