crypt32/tests: Fix a test failure on older crypt32.
[wine/hramrach.git] / dlls / windowscodecs / regsvr.c
blobc87aa4b2458e0516b452bbc042fd3b6745e9af86
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 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
41 /***********************************************************************
42 * interface for self-registering
44 struct regsvr_coclass
46 CLSID const *clsid; /* NULL for end of list */
47 LPCSTR name; /* can be NULL to omit */
48 LPCSTR ips; /* can be NULL to omit */
49 LPCSTR ips32; /* can be NULL to omit */
50 LPCSTR ips32_tmodel; /* can be NULL to omit */
51 LPCSTR progid; /* can be NULL to omit */
52 LPCSTR viprogid; /* can be NULL to omit */
53 LPCSTR progid_extra; /* can be NULL to omit */
56 static HRESULT register_coclasses(struct regsvr_coclass const *list);
57 static HRESULT unregister_coclasses(struct regsvr_coclass const *list);
59 struct decoder_pattern
61 DWORD length; /* 0 for end of list */
62 DWORD position;
63 const BYTE *pattern;
64 const BYTE *mask;
65 DWORD endofstream;
68 struct regsvr_decoder
70 CLSID const *clsid; /* NULL for end of list */
71 LPCSTR author;
72 LPCSTR friendlyname;
73 LPCSTR version;
74 GUID const *vendor;
75 LPCSTR mimetypes;
76 LPCSTR extensions;
77 GUID const * const *formats;
78 const struct decoder_pattern *patterns;
81 static HRESULT register_decoders(struct regsvr_decoder const *list);
82 static HRESULT unregister_decoders(struct regsvr_decoder const *list);
84 struct regsvr_converter
86 CLSID const *clsid; /* NULL for end of list */
87 LPCSTR author;
88 LPCSTR friendlyname;
89 LPCSTR version;
90 GUID const *vendor;
91 GUID const * const *formats;
94 static HRESULT register_converters(struct regsvr_converter const *list);
95 static HRESULT unregister_converters(struct regsvr_converter const *list);
97 /***********************************************************************
98 * static string constants
100 static WCHAR const clsid_keyname[6] = {
101 'C', 'L', 'S', 'I', 'D', 0 };
102 static WCHAR const curver_keyname[7] = {
103 'C', 'u', 'r', 'V', 'e', 'r', 0 };
104 static WCHAR const ips_keyname[13] = {
105 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
106 0 };
107 static WCHAR const ips32_keyname[15] = {
108 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
109 '3', '2', 0 };
110 static WCHAR const progid_keyname[7] = {
111 'P', 'r', 'o', 'g', 'I', 'D', 0 };
112 static WCHAR const viprogid_keyname[25] = {
113 'V', 'e', 'r', 's', 'i', 'o', 'n', 'I', 'n', 'd', 'e', 'p',
114 'e', 'n', 'd', 'e', 'n', 't', 'P', 'r', 'o', 'g', 'I', 'D',
115 0 };
116 static char const tmodel_valuename[] = "ThreadingModel";
117 static char const author_valuename[] = "Author";
118 static char const friendlyname_valuename[] = "FriendlyName";
119 static WCHAR const vendor_valuename[] = {'V','e','n','d','o','r',0};
120 static char const version_valuename[] = "Version";
121 static char const mimetypes_valuename[] = "MimeTypes";
122 static char const extensions_valuename[] = "FileExtensions";
123 static WCHAR const formats_keyname[] = {'F','o','r','m','a','t','s',0};
124 static WCHAR const patterns_keyname[] = {'P','a','t','t','e','r','n','s',0};
125 static WCHAR const instance_keyname[] = {'I','n','s','t','a','n','c','e',0};
126 static WCHAR const clsid_valuename[] = {'C','L','S','I','D',0};
127 static char const length_valuename[] = "Length";
128 static char const position_valuename[] = "Position";
129 static char const pattern_valuename[] = "Pattern";
130 static char const mask_valuename[] = "Mask";
131 static char const endofstream_valuename[] = "EndOfStream";
132 static WCHAR const pixelformats_keyname[] = {'P','i','x','e','l','F','o','r','m','a','t','s',0};
134 /***********************************************************************
135 * static helper functions
137 static LONG register_key_defvalueW(HKEY base, WCHAR const *name,
138 WCHAR const *value);
139 static LONG register_key_defvalueA(HKEY base, WCHAR const *name,
140 char const *value);
141 static LONG register_progid(WCHAR const *clsid,
142 char const *progid, char const *curver_progid,
143 char const *name, char const *extra);
145 /***********************************************************************
146 * register_coclasses
148 static HRESULT register_coclasses(struct regsvr_coclass const *list)
150 LONG res = ERROR_SUCCESS;
151 HKEY coclass_key;
153 res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0,
154 KEY_READ | KEY_WRITE, NULL, &coclass_key, NULL);
155 if (res != ERROR_SUCCESS) goto error_return;
157 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
158 WCHAR buf[39];
159 HKEY clsid_key;
161 StringFromGUID2(list->clsid, buf, 39);
162 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
163 KEY_READ | KEY_WRITE, NULL, &clsid_key, NULL);
164 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
166 if (list->name) {
167 res = RegSetValueExA(clsid_key, NULL, 0, REG_SZ,
168 (CONST BYTE*)(list->name),
169 strlen(list->name) + 1);
170 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
173 if (list->ips) {
174 res = register_key_defvalueA(clsid_key, ips_keyname, list->ips);
175 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
178 if (list->ips32) {
179 HKEY ips32_key;
181 res = RegCreateKeyExW(clsid_key, ips32_keyname, 0, NULL, 0,
182 KEY_READ | KEY_WRITE, NULL,
183 &ips32_key, NULL);
184 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
186 res = RegSetValueExA(ips32_key, NULL, 0, REG_SZ,
187 (CONST BYTE*)list->ips32,
188 lstrlenA(list->ips32) + 1);
189 if (res == ERROR_SUCCESS && list->ips32_tmodel)
190 res = RegSetValueExA(ips32_key, tmodel_valuename, 0, REG_SZ,
191 (CONST BYTE*)list->ips32_tmodel,
192 strlen(list->ips32_tmodel) + 1);
193 RegCloseKey(ips32_key);
194 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
197 if (list->progid) {
198 res = register_key_defvalueA(clsid_key, progid_keyname,
199 list->progid);
200 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
202 res = register_progid(buf, list->progid, NULL,
203 list->name, list->progid_extra);
204 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
207 if (list->viprogid) {
208 res = register_key_defvalueA(clsid_key, viprogid_keyname,
209 list->viprogid);
210 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
212 res = register_progid(buf, list->viprogid, list->progid,
213 list->name, list->progid_extra);
214 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
217 error_close_clsid_key:
218 RegCloseKey(clsid_key);
221 error_close_coclass_key:
222 RegCloseKey(coclass_key);
223 error_return:
224 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
227 /***********************************************************************
228 * unregister_coclasses
230 static HRESULT unregister_coclasses(struct regsvr_coclass const *list)
232 LONG res = ERROR_SUCCESS;
233 HKEY coclass_key;
235 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0,
236 KEY_READ | KEY_WRITE, &coclass_key);
237 if (res == ERROR_FILE_NOT_FOUND) return S_OK;
238 if (res != ERROR_SUCCESS) goto error_return;
240 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
241 WCHAR buf[39];
243 StringFromGUID2(list->clsid, buf, 39);
244 res = RegDeleteTreeW(coclass_key, buf);
245 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
246 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
248 if (list->progid) {
249 res = RegDeleteTreeA(HKEY_CLASSES_ROOT, list->progid);
250 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
251 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
254 if (list->viprogid) {
255 res = RegDeleteTreeA(HKEY_CLASSES_ROOT, list->viprogid);
256 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
257 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
261 error_close_coclass_key:
262 RegCloseKey(coclass_key);
263 error_return:
264 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
267 /***********************************************************************
268 * register_decoders
270 static HRESULT register_decoders(struct regsvr_decoder const *list)
272 LONG res = ERROR_SUCCESS;
273 HKEY coclass_key;
274 WCHAR buf[39];
275 HKEY decoders_key;
276 HKEY instance_key;
278 res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0,
279 KEY_READ | KEY_WRITE, NULL, &coclass_key, NULL);
280 if (res == ERROR_SUCCESS) {
281 StringFromGUID2(&CATID_WICBitmapDecoders, buf, 39);
282 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
283 KEY_READ | KEY_WRITE, NULL, &decoders_key, NULL);
284 if (res == ERROR_SUCCESS)
286 res = RegCreateKeyExW(decoders_key, instance_keyname, 0, NULL, 0,
287 KEY_READ | KEY_WRITE, NULL, &instance_key, NULL);
288 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
290 if (res != ERROR_SUCCESS)
291 RegCloseKey(coclass_key);
293 if (res != ERROR_SUCCESS) goto error_return;
295 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
296 HKEY clsid_key;
297 HKEY instance_clsid_key;
299 StringFromGUID2(list->clsid, buf, 39);
300 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
301 KEY_READ | KEY_WRITE, NULL, &clsid_key, NULL);
302 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
304 StringFromGUID2(list->clsid, buf, 39);
305 res = RegCreateKeyExW(instance_key, buf, 0, NULL, 0,
306 KEY_READ | KEY_WRITE, NULL, &instance_clsid_key, NULL);
307 if (res == ERROR_SUCCESS) {
308 res = RegSetValueExW(instance_clsid_key, clsid_valuename, 0, REG_SZ,
309 (CONST BYTE*)(buf), 78);
310 RegCloseKey(instance_clsid_key);
312 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
314 if (list->author) {
315 res = RegSetValueExA(clsid_key, author_valuename, 0, REG_SZ,
316 (CONST BYTE*)(list->author),
317 strlen(list->author) + 1);
318 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
321 if (list->friendlyname) {
322 res = RegSetValueExA(clsid_key, friendlyname_valuename, 0, REG_SZ,
323 (CONST BYTE*)(list->friendlyname),
324 strlen(list->friendlyname) + 1);
325 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
328 if (list->vendor) {
329 StringFromGUID2(list->vendor, buf, 39);
330 res = RegSetValueExW(clsid_key, vendor_valuename, 0, REG_SZ,
331 (CONST BYTE*)(buf), 78);
332 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
335 if (list->version) {
336 res = RegSetValueExA(clsid_key, version_valuename, 0, REG_SZ,
337 (CONST BYTE*)(list->version),
338 strlen(list->version) + 1);
339 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
342 if (list->mimetypes) {
343 res = RegSetValueExA(clsid_key, mimetypes_valuename, 0, REG_SZ,
344 (CONST BYTE*)(list->mimetypes),
345 strlen(list->mimetypes) + 1);
346 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
349 if (list->extensions) {
350 res = RegSetValueExA(clsid_key, extensions_valuename, 0, REG_SZ,
351 (CONST BYTE*)(list->extensions),
352 strlen(list->extensions) + 1);
353 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
356 if (list->formats) {
357 HKEY formats_key;
358 GUID const * const *format;
360 res = RegCreateKeyExW(clsid_key, formats_keyname, 0, NULL, 0,
361 KEY_READ | KEY_WRITE, NULL, &formats_key, NULL);
362 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
363 for (format=list->formats; *format; ++format)
365 HKEY format_key;
366 StringFromGUID2(*format, buf, 39);
367 res = RegCreateKeyExW(formats_key, buf, 0, NULL, 0,
368 KEY_READ | KEY_WRITE, NULL, &format_key, NULL);
369 if (res != ERROR_SUCCESS) break;
370 RegCloseKey(format_key);
372 RegCloseKey(formats_key);
373 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
376 if (list->patterns) {
377 HKEY patterns_key;
378 int i;
380 res = RegCreateKeyExW(clsid_key, patterns_keyname, 0, NULL, 0,
381 KEY_READ | KEY_WRITE, NULL, &patterns_key, NULL);
382 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
383 for (i=0; list->patterns[i].length; i++)
385 HKEY pattern_key;
386 static const WCHAR int_format[] = {'%','i',0};
387 snprintfW(buf, 39, int_format, i);
388 res = RegCreateKeyExW(patterns_key, buf, 0, NULL, 0,
389 KEY_READ | KEY_WRITE, NULL, &pattern_key, NULL);
390 if (res != ERROR_SUCCESS) break;
391 res = RegSetValueExA(pattern_key, length_valuename, 0, REG_DWORD,
392 (CONST BYTE*)(&list->patterns[i].length), 4);
393 if (res == ERROR_SUCCESS)
394 res = RegSetValueExA(pattern_key, position_valuename, 0, REG_DWORD,
395 (CONST BYTE*)(&list->patterns[i].position), 4);
396 if (res == ERROR_SUCCESS)
397 res = RegSetValueExA(pattern_key, pattern_valuename, 0, REG_BINARY,
398 list->patterns[i].pattern,
399 list->patterns[i].length);
400 if (res == ERROR_SUCCESS)
401 res = RegSetValueExA(pattern_key, mask_valuename, 0, REG_BINARY,
402 list->patterns[i].mask,
403 list->patterns[i].length);
404 if (res == ERROR_SUCCESS)
405 res = RegSetValueExA(pattern_key, endofstream_valuename, 0, REG_DWORD,
406 (CONST BYTE*)&(list->patterns[i].endofstream), 4);
407 RegCloseKey(pattern_key);
409 RegCloseKey(patterns_key);
410 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
413 error_close_clsid_key:
414 RegCloseKey(clsid_key);
417 error_close_coclass_key:
418 RegCloseKey(instance_key);
419 RegCloseKey(decoders_key);
420 RegCloseKey(coclass_key);
421 error_return:
422 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
425 /***********************************************************************
426 * unregister_decoders
428 static HRESULT unregister_decoders(struct regsvr_decoder const *list)
430 LONG res = ERROR_SUCCESS;
431 HKEY coclass_key;
432 WCHAR buf[39];
433 HKEY decoders_key;
434 HKEY instance_key;
436 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0,
437 KEY_READ | KEY_WRITE, &coclass_key);
438 if (res == ERROR_FILE_NOT_FOUND) return S_OK;
440 if (res == ERROR_SUCCESS) {
441 StringFromGUID2(&CATID_WICBitmapDecoders, buf, 39);
442 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
443 KEY_READ | KEY_WRITE, NULL, &decoders_key, NULL);
444 if (res == ERROR_SUCCESS)
446 res = RegCreateKeyExW(decoders_key, instance_keyname, 0, NULL, 0,
447 KEY_READ | KEY_WRITE, NULL, &instance_key, NULL);
448 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
450 if (res != ERROR_SUCCESS)
451 RegCloseKey(coclass_key);
453 if (res != ERROR_SUCCESS) goto error_return;
455 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
456 StringFromGUID2(list->clsid, buf, 39);
458 res = RegDeleteTreeW(coclass_key, buf);
459 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
460 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
462 res = RegDeleteTreeW(instance_key, buf);
463 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
464 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
467 error_close_coclass_key:
468 RegCloseKey(instance_key);
469 RegCloseKey(decoders_key);
470 RegCloseKey(coclass_key);
471 error_return:
472 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
475 /***********************************************************************
476 * register_converters
478 static HRESULT register_converters(struct regsvr_converter const *list)
480 LONG res = ERROR_SUCCESS;
481 HKEY coclass_key;
482 WCHAR buf[39];
483 HKEY converters_key;
484 HKEY instance_key;
486 res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0,
487 KEY_READ | KEY_WRITE, NULL, &coclass_key, NULL);
488 if (res == ERROR_SUCCESS) {
489 StringFromGUID2(&CATID_WICFormatConverters, buf, 39);
490 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
491 KEY_READ | KEY_WRITE, NULL, &converters_key, NULL);
492 if (res == ERROR_SUCCESS)
494 res = RegCreateKeyExW(converters_key, instance_keyname, 0, NULL, 0,
495 KEY_READ | KEY_WRITE, NULL, &instance_key, NULL);
496 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
498 if (res != ERROR_SUCCESS)
499 RegCloseKey(coclass_key);
501 if (res != ERROR_SUCCESS) goto error_return;
503 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
504 HKEY clsid_key;
505 HKEY instance_clsid_key;
507 StringFromGUID2(list->clsid, buf, 39);
508 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
509 KEY_READ | KEY_WRITE, NULL, &clsid_key, NULL);
510 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
512 StringFromGUID2(list->clsid, buf, 39);
513 res = RegCreateKeyExW(instance_key, buf, 0, NULL, 0,
514 KEY_READ | KEY_WRITE, NULL, &instance_clsid_key, NULL);
515 if (res == ERROR_SUCCESS) {
516 res = RegSetValueExW(instance_clsid_key, clsid_valuename, 0, REG_SZ,
517 (CONST BYTE*)(buf), 78);
518 RegCloseKey(instance_clsid_key);
520 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
522 if (list->author) {
523 res = RegSetValueExA(clsid_key, author_valuename, 0, REG_SZ,
524 (CONST BYTE*)(list->author),
525 strlen(list->author) + 1);
526 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
529 if (list->friendlyname) {
530 res = RegSetValueExA(clsid_key, friendlyname_valuename, 0, REG_SZ,
531 (CONST BYTE*)(list->friendlyname),
532 strlen(list->friendlyname) + 1);
533 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
536 if (list->vendor) {
537 StringFromGUID2(list->vendor, buf, 39);
538 res = RegSetValueExW(clsid_key, vendor_valuename, 0, REG_SZ,
539 (CONST BYTE*)(buf), 78);
540 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
543 if (list->version) {
544 res = RegSetValueExA(clsid_key, version_valuename, 0, REG_SZ,
545 (CONST BYTE*)(list->version),
546 strlen(list->version) + 1);
547 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
550 if (list->formats) {
551 HKEY formats_key;
552 GUID const * const *format;
554 res = RegCreateKeyExW(clsid_key, pixelformats_keyname, 0, NULL, 0,
555 KEY_READ | KEY_WRITE, NULL, &formats_key, NULL);
556 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
557 for (format=list->formats; *format; ++format)
559 HKEY format_key;
560 StringFromGUID2(*format, buf, 39);
561 res = RegCreateKeyExW(formats_key, buf, 0, NULL, 0,
562 KEY_READ | KEY_WRITE, NULL, &format_key, NULL);
563 if (res != ERROR_SUCCESS) break;
564 RegCloseKey(format_key);
566 RegCloseKey(formats_key);
567 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
570 error_close_clsid_key:
571 RegCloseKey(clsid_key);
574 error_close_coclass_key:
575 RegCloseKey(instance_key);
576 RegCloseKey(converters_key);
577 RegCloseKey(coclass_key);
578 error_return:
579 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
582 /***********************************************************************
583 * unregister_converters
585 static HRESULT unregister_converters(struct regsvr_converter const *list)
587 LONG res = ERROR_SUCCESS;
588 HKEY coclass_key;
589 WCHAR buf[39];
590 HKEY converters_key;
591 HKEY instance_key;
593 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0,
594 KEY_READ | KEY_WRITE, &coclass_key);
595 if (res == ERROR_FILE_NOT_FOUND) return S_OK;
597 if (res == ERROR_SUCCESS) {
598 StringFromGUID2(&CATID_WICFormatConverters, buf, 39);
599 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
600 KEY_READ | KEY_WRITE, NULL, &converters_key, NULL);
601 if (res == ERROR_SUCCESS)
603 res = RegCreateKeyExW(converters_key, instance_keyname, 0, NULL, 0,
604 KEY_READ | KEY_WRITE, NULL, &instance_key, NULL);
605 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
607 if (res != ERROR_SUCCESS)
608 RegCloseKey(coclass_key);
610 if (res != ERROR_SUCCESS) goto error_return;
612 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
613 StringFromGUID2(list->clsid, buf, 39);
615 res = RegDeleteTreeW(coclass_key, buf);
616 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
617 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
619 res = RegDeleteTreeW(instance_key, buf);
620 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
621 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
624 error_close_coclass_key:
625 RegCloseKey(instance_key);
626 RegCloseKey(converters_key);
627 RegCloseKey(coclass_key);
628 error_return:
629 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
632 /***********************************************************************
633 * register_key_defvalueW
635 static LONG register_key_defvalueW(
636 HKEY base,
637 WCHAR const *name,
638 WCHAR const *value)
640 LONG res;
641 HKEY key;
643 res = RegCreateKeyExW(base, name, 0, NULL, 0,
644 KEY_READ | KEY_WRITE, NULL, &key, NULL);
645 if (res != ERROR_SUCCESS) return res;
646 res = RegSetValueExW(key, NULL, 0, REG_SZ, (CONST BYTE*)value,
647 (lstrlenW(value) + 1) * sizeof(WCHAR));
648 RegCloseKey(key);
649 return res;
652 /***********************************************************************
653 * register_key_defvalueA
655 static LONG register_key_defvalueA(
656 HKEY base,
657 WCHAR const *name,
658 char const *value)
660 LONG res;
661 HKEY key;
663 res = RegCreateKeyExW(base, name, 0, NULL, 0,
664 KEY_READ | KEY_WRITE, NULL, &key, NULL);
665 if (res != ERROR_SUCCESS) return res;
666 res = RegSetValueExA(key, NULL, 0, REG_SZ, (CONST BYTE*)value,
667 lstrlenA(value) + 1);
668 RegCloseKey(key);
669 return res;
672 /***********************************************************************
673 * register_progid
675 static LONG register_progid(
676 WCHAR const *clsid,
677 char const *progid,
678 char const *curver_progid,
679 char const *name,
680 char const *extra)
682 LONG res;
683 HKEY progid_key;
685 res = RegCreateKeyExA(HKEY_CLASSES_ROOT, progid, 0,
686 NULL, 0, KEY_READ | KEY_WRITE, NULL,
687 &progid_key, NULL);
688 if (res != ERROR_SUCCESS) return res;
690 if (name) {
691 res = RegSetValueExA(progid_key, NULL, 0, REG_SZ,
692 (CONST BYTE*)name, strlen(name) + 1);
693 if (res != ERROR_SUCCESS) goto error_close_progid_key;
696 if (clsid) {
697 res = register_key_defvalueW(progid_key, clsid_keyname, clsid);
698 if (res != ERROR_SUCCESS) goto error_close_progid_key;
701 if (curver_progid) {
702 res = register_key_defvalueA(progid_key, curver_keyname,
703 curver_progid);
704 if (res != ERROR_SUCCESS) goto error_close_progid_key;
707 if (extra) {
708 HKEY extra_key;
710 res = RegCreateKeyExA(progid_key, extra, 0,
711 NULL, 0, KEY_READ | KEY_WRITE, NULL,
712 &extra_key, NULL);
713 if (res == ERROR_SUCCESS)
714 RegCloseKey(extra_key);
717 error_close_progid_key:
718 RegCloseKey(progid_key);
719 return res;
722 /***********************************************************************
723 * coclass list
725 static struct regsvr_coclass const coclass_list[] = {
726 { &CLSID_WICImagingFactory,
727 "WIC Imaging Factory",
728 NULL,
729 "windowscodecs.dll",
730 "Apartment"
732 { &CLSID_WICBmpDecoder,
733 "WIC BMP Decoder",
734 NULL,
735 "windowscodecs.dll",
736 "Apartment"
738 { &CLSID_WICPngDecoder,
739 "WIC PNG Decoder",
740 NULL,
741 "windowscodecs.dll",
742 "Apartment"
744 { &CLSID_WICPngEncoder,
745 "WIC PNG Encoder",
746 NULL,
747 "windowscodecs.dll",
748 "Apartment"
750 { &CLSID_WICBmpEncoder,
751 "WIC BMP Encoder",
752 NULL,
753 "windowscodecs.dll",
754 "Apartment"
756 { &CLSID_WICGifDecoder,
757 "WIC GIF Decoder",
758 NULL,
759 "windowscodecs.dll",
760 "Apartment"
762 { &CLSID_WICIcoDecoder,
763 "WIC ICO Decoder",
764 NULL,
765 "windowscodecs.dll",
766 "Apartment"
768 { &CLSID_WICJpegDecoder,
769 "WIC JPEG Decoder",
770 NULL,
771 "windowscodecs.dll",
772 "Apartment"
774 { &CLSID_WICDefaultFormatConverter,
775 "WIC Default Format Converter",
776 NULL,
777 "windowscodecs.dll",
778 "Apartment"
780 { NULL } /* list terminator */
783 /***********************************************************************
784 * decoder list
786 static const BYTE mask_all[] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
788 static const BYTE bmp_magic[] = {0x42,0x4d};
790 static GUID const * const bmp_formats[] = {
791 &GUID_WICPixelFormat1bppIndexed,
792 &GUID_WICPixelFormat2bppIndexed,
793 &GUID_WICPixelFormat4bppIndexed,
794 &GUID_WICPixelFormat8bppIndexed,
795 &GUID_WICPixelFormat16bppBGR555,
796 &GUID_WICPixelFormat16bppBGR565,
797 &GUID_WICPixelFormat24bppBGR,
798 &GUID_WICPixelFormat32bppBGR,
799 &GUID_WICPixelFormat32bppBGRA,
800 NULL
803 static struct decoder_pattern const bmp_patterns[] = {
804 {2,0,bmp_magic,mask_all,0},
808 static const BYTE gif87a_magic[6] = "GIF87a";
809 static const BYTE gif89a_magic[6] = "GIF89a";
811 static GUID const * const gif_formats[] = {
812 &GUID_WICPixelFormat8bppIndexed,
813 NULL
816 static struct decoder_pattern const gif_patterns[] = {
817 {6,0,gif87a_magic,mask_all,0},
818 {6,0,gif89a_magic,mask_all,0},
822 static const BYTE ico_magic[] = {00,00,01,00};
824 static GUID const * const ico_formats[] = {
825 &GUID_WICPixelFormat32bppBGRA,
826 NULL
829 static struct decoder_pattern const ico_patterns[] = {
830 {4,0,ico_magic,mask_all,0},
834 static const BYTE jpeg_magic[] = {0xff, 0xd8, 0xff, 0xe0};
836 static GUID const * const jpeg_formats[] = {
837 &GUID_WICPixelFormat24bppBGR,
838 &GUID_WICPixelFormat8bppGray,
839 NULL
842 static struct decoder_pattern const jpeg_patterns[] = {
843 {4,0,jpeg_magic,mask_all,0},
847 static const BYTE png_magic[] = {137,80,78,71,13,10,26,10};
849 static GUID const * const png_formats[] = {
850 &GUID_WICPixelFormatBlackWhite,
851 &GUID_WICPixelFormat2bppGray,
852 &GUID_WICPixelFormat4bppGray,
853 &GUID_WICPixelFormat8bppGray,
854 &GUID_WICPixelFormat16bppGray,
855 &GUID_WICPixelFormat32bppBGRA,
856 &GUID_WICPixelFormat64bppRGBA,
857 &GUID_WICPixelFormat1bppIndexed,
858 &GUID_WICPixelFormat2bppIndexed,
859 &GUID_WICPixelFormat4bppIndexed,
860 &GUID_WICPixelFormat8bppIndexed,
861 &GUID_WICPixelFormat24bppBGR,
862 &GUID_WICPixelFormat48bppRGB,
863 NULL
866 static struct decoder_pattern const png_patterns[] = {
867 {8,0,png_magic,mask_all,0},
871 static struct regsvr_decoder const decoder_list[] = {
872 { &CLSID_WICBmpDecoder,
873 "The Wine Project",
874 "BMP Decoder",
875 "1.0.0.0",
876 &GUID_VendorMicrosoft,
877 "image/bmp",
878 ".bmp,.dib,.rle",
879 bmp_formats,
880 bmp_patterns
882 { &CLSID_WICGifDecoder,
883 "The Wine Project",
884 "GIF Decoder",
885 "1.0.0.0",
886 &GUID_VendorMicrosoft,
887 "image/gif",
888 ".gif",
889 gif_formats,
890 gif_patterns
892 { &CLSID_WICIcoDecoder,
893 "The Wine Project",
894 "ICO Decoder",
895 "1.0.0.0",
896 &GUID_VendorMicrosoft,
897 "image/vnd.microsoft.icon",
898 ".ico",
899 ico_formats,
900 ico_patterns
902 { &CLSID_WICJpegDecoder,
903 "The Wine Project",
904 "JPEG Decoder",
905 "1.0.0.0",
906 &GUID_VendorMicrosoft,
907 "image/jpeg",
908 ".jpg;.jpeg;.jfif",
909 jpeg_formats,
910 jpeg_patterns
912 { &CLSID_WICPngDecoder,
913 "The Wine Project",
914 "PNG Decoder",
915 "1.0.0.0",
916 &GUID_VendorMicrosoft,
917 "image/png",
918 ".png",
919 png_formats,
920 png_patterns
922 { NULL } /* list terminator */
925 static GUID const * const converter_formats[] = {
926 &GUID_WICPixelFormat1bppIndexed,
927 &GUID_WICPixelFormat2bppIndexed,
928 &GUID_WICPixelFormat4bppIndexed,
929 &GUID_WICPixelFormat8bppIndexed,
930 &GUID_WICPixelFormatBlackWhite,
931 &GUID_WICPixelFormat2bppGray,
932 &GUID_WICPixelFormat4bppGray,
933 &GUID_WICPixelFormat8bppGray,
934 &GUID_WICPixelFormat16bppGray,
935 &GUID_WICPixelFormat16bppBGR555,
936 &GUID_WICPixelFormat16bppBGR565,
937 &GUID_WICPixelFormat24bppBGR,
938 &GUID_WICPixelFormat32bppBGR,
939 &GUID_WICPixelFormat32bppBGRA,
940 &GUID_WICPixelFormat48bppRGB,
941 &GUID_WICPixelFormat64bppRGBA,
942 NULL
945 static struct regsvr_converter const converter_list[] = {
946 { &CLSID_WICDefaultFormatConverter,
947 "The Wine Project",
948 "Default Pixel Format Converter",
949 "1.0.0.0",
950 &GUID_VendorMicrosoft,
951 converter_formats
953 { NULL } /* list terminator */
956 HRESULT WINAPI DllRegisterServer(void)
958 HRESULT hr;
960 TRACE("\n");
962 hr = register_coclasses(coclass_list);
963 if (SUCCEEDED(hr))
964 register_decoders(decoder_list);
965 if (SUCCEEDED(hr))
966 register_converters(converter_list);
967 return hr;
970 HRESULT WINAPI DllUnregisterServer(void)
972 HRESULT hr;
974 TRACE("\n");
976 hr = unregister_coclasses(coclass_list);
977 if (SUCCEEDED(hr))
978 unregister_decoders(decoder_list);
979 if (SUCCEEDED(hr))
980 unregister_converters(converter_list);
981 return hr;