jscript: Don't lookup global variables on function invocation.
[wine/multimedia.git] / dlls / windowscodecs / regsvr.c
blobac84368dd4af444c6751b2e3608f0e81cff4d8aa
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_encoder
88 CLSID const *clsid; /* NULL for end of list */
89 LPCSTR author;
90 LPCSTR friendlyname;
91 LPCSTR version;
92 GUID const *vendor;
93 LPCSTR mimetypes;
94 LPCSTR extensions;
95 GUID const * const *formats;
98 static HRESULT register_encoders(struct regsvr_encoder const *list);
99 static HRESULT unregister_encoders(struct regsvr_encoder const *list);
101 struct regsvr_converter
103 CLSID const *clsid; /* NULL for end of list */
104 LPCSTR author;
105 LPCSTR friendlyname;
106 LPCSTR version;
107 GUID const *vendor;
108 GUID const * const *formats;
111 static HRESULT register_converters(struct regsvr_converter const *list);
112 static HRESULT unregister_converters(struct regsvr_converter const *list);
114 /***********************************************************************
115 * static string constants
117 static WCHAR const clsid_keyname[6] = {
118 'C', 'L', 'S', 'I', 'D', 0 };
119 static WCHAR const curver_keyname[7] = {
120 'C', 'u', 'r', 'V', 'e', 'r', 0 };
121 static WCHAR const ips_keyname[13] = {
122 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
123 0 };
124 static WCHAR const ips32_keyname[15] = {
125 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
126 '3', '2', 0 };
127 static WCHAR const progid_keyname[7] = {
128 'P', 'r', 'o', 'g', 'I', 'D', 0 };
129 static WCHAR const viprogid_keyname[25] = {
130 'V', 'e', 'r', 's', 'i', 'o', 'n', 'I', 'n', 'd', 'e', 'p',
131 'e', 'n', 'd', 'e', 'n', 't', 'P', 'r', 'o', 'g', 'I', 'D',
132 0 };
133 static char const tmodel_valuename[] = "ThreadingModel";
134 static char const author_valuename[] = "Author";
135 static char const friendlyname_valuename[] = "FriendlyName";
136 static WCHAR const vendor_valuename[] = {'V','e','n','d','o','r',0};
137 static char const version_valuename[] = "Version";
138 static char const mimetypes_valuename[] = "MimeTypes";
139 static char const extensions_valuename[] = "FileExtensions";
140 static WCHAR const formats_keyname[] = {'F','o','r','m','a','t','s',0};
141 static WCHAR const patterns_keyname[] = {'P','a','t','t','e','r','n','s',0};
142 static WCHAR const instance_keyname[] = {'I','n','s','t','a','n','c','e',0};
143 static WCHAR const clsid_valuename[] = {'C','L','S','I','D',0};
144 static char const length_valuename[] = "Length";
145 static char const position_valuename[] = "Position";
146 static char const pattern_valuename[] = "Pattern";
147 static char const mask_valuename[] = "Mask";
148 static char const endofstream_valuename[] = "EndOfStream";
149 static WCHAR const pixelformats_keyname[] = {'P','i','x','e','l','F','o','r','m','a','t','s',0};
151 /***********************************************************************
152 * static helper functions
154 static LONG register_key_defvalueW(HKEY base, WCHAR const *name,
155 WCHAR const *value);
156 static LONG register_key_defvalueA(HKEY base, WCHAR const *name,
157 char const *value);
158 static LONG register_progid(WCHAR const *clsid,
159 char const *progid, char const *curver_progid,
160 char const *name, char const *extra);
162 /***********************************************************************
163 * register_coclasses
165 static HRESULT register_coclasses(struct regsvr_coclass const *list)
167 LONG res = ERROR_SUCCESS;
168 HKEY coclass_key;
170 res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0,
171 KEY_READ | KEY_WRITE, NULL, &coclass_key, NULL);
172 if (res != ERROR_SUCCESS) goto error_return;
174 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
175 WCHAR buf[39];
176 HKEY clsid_key;
178 StringFromGUID2(list->clsid, buf, 39);
179 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
180 KEY_READ | KEY_WRITE, NULL, &clsid_key, NULL);
181 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
183 if (list->name) {
184 res = RegSetValueExA(clsid_key, NULL, 0, REG_SZ,
185 (CONST BYTE*)(list->name),
186 strlen(list->name) + 1);
187 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
190 if (list->ips) {
191 res = register_key_defvalueA(clsid_key, ips_keyname, list->ips);
192 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
195 if (list->ips32) {
196 HKEY ips32_key;
198 res = RegCreateKeyExW(clsid_key, ips32_keyname, 0, NULL, 0,
199 KEY_READ | KEY_WRITE, NULL,
200 &ips32_key, NULL);
201 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
203 res = RegSetValueExA(ips32_key, NULL, 0, REG_SZ,
204 (CONST BYTE*)list->ips32,
205 lstrlenA(list->ips32) + 1);
206 if (res == ERROR_SUCCESS && list->ips32_tmodel)
207 res = RegSetValueExA(ips32_key, tmodel_valuename, 0, REG_SZ,
208 (CONST BYTE*)list->ips32_tmodel,
209 strlen(list->ips32_tmodel) + 1);
210 RegCloseKey(ips32_key);
211 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
214 if (list->progid) {
215 res = register_key_defvalueA(clsid_key, progid_keyname,
216 list->progid);
217 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
219 res = register_progid(buf, list->progid, NULL,
220 list->name, list->progid_extra);
221 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
224 if (list->viprogid) {
225 res = register_key_defvalueA(clsid_key, viprogid_keyname,
226 list->viprogid);
227 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
229 res = register_progid(buf, list->viprogid, list->progid,
230 list->name, list->progid_extra);
231 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
234 error_close_clsid_key:
235 RegCloseKey(clsid_key);
238 error_close_coclass_key:
239 RegCloseKey(coclass_key);
240 error_return:
241 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
244 /***********************************************************************
245 * unregister_coclasses
247 static HRESULT unregister_coclasses(struct regsvr_coclass const *list)
249 LONG res = ERROR_SUCCESS;
250 HKEY coclass_key;
252 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0,
253 KEY_READ | KEY_WRITE, &coclass_key);
254 if (res == ERROR_FILE_NOT_FOUND) return S_OK;
255 if (res != ERROR_SUCCESS) goto error_return;
257 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
258 WCHAR buf[39];
260 StringFromGUID2(list->clsid, buf, 39);
261 res = RegDeleteTreeW(coclass_key, buf);
262 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
263 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
265 if (list->progid) {
266 res = RegDeleteTreeA(HKEY_CLASSES_ROOT, list->progid);
267 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
268 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
271 if (list->viprogid) {
272 res = RegDeleteTreeA(HKEY_CLASSES_ROOT, list->viprogid);
273 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
274 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
278 error_close_coclass_key:
279 RegCloseKey(coclass_key);
280 error_return:
281 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
284 /***********************************************************************
285 * register_decoders
287 static HRESULT register_decoders(struct regsvr_decoder const *list)
289 LONG res = ERROR_SUCCESS;
290 HKEY coclass_key;
291 WCHAR buf[39];
292 HKEY decoders_key;
293 HKEY instance_key;
295 res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0,
296 KEY_READ | KEY_WRITE, NULL, &coclass_key, NULL);
297 if (res == ERROR_SUCCESS) {
298 StringFromGUID2(&CATID_WICBitmapDecoders, buf, 39);
299 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
300 KEY_READ | KEY_WRITE, NULL, &decoders_key, NULL);
301 if (res == ERROR_SUCCESS)
303 res = RegCreateKeyExW(decoders_key, instance_keyname, 0, NULL, 0,
304 KEY_READ | KEY_WRITE, NULL, &instance_key, NULL);
305 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
307 if (res != ERROR_SUCCESS)
308 RegCloseKey(coclass_key);
310 if (res != ERROR_SUCCESS) goto error_return;
312 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
313 HKEY clsid_key;
314 HKEY instance_clsid_key;
316 StringFromGUID2(list->clsid, buf, 39);
317 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
318 KEY_READ | KEY_WRITE, NULL, &clsid_key, NULL);
319 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
321 StringFromGUID2(list->clsid, buf, 39);
322 res = RegCreateKeyExW(instance_key, buf, 0, NULL, 0,
323 KEY_READ | KEY_WRITE, NULL, &instance_clsid_key, NULL);
324 if (res == ERROR_SUCCESS) {
325 res = RegSetValueExW(instance_clsid_key, clsid_valuename, 0, REG_SZ,
326 (CONST BYTE*)(buf), 78);
327 RegCloseKey(instance_clsid_key);
329 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
331 if (list->author) {
332 res = RegSetValueExA(clsid_key, author_valuename, 0, REG_SZ,
333 (CONST BYTE*)(list->author),
334 strlen(list->author) + 1);
335 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
338 if (list->friendlyname) {
339 res = RegSetValueExA(clsid_key, friendlyname_valuename, 0, REG_SZ,
340 (CONST BYTE*)(list->friendlyname),
341 strlen(list->friendlyname) + 1);
342 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
345 if (list->vendor) {
346 StringFromGUID2(list->vendor, buf, 39);
347 res = RegSetValueExW(clsid_key, vendor_valuename, 0, REG_SZ,
348 (CONST BYTE*)(buf), 78);
349 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
352 if (list->version) {
353 res = RegSetValueExA(clsid_key, version_valuename, 0, REG_SZ,
354 (CONST BYTE*)(list->version),
355 strlen(list->version) + 1);
356 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
359 if (list->mimetypes) {
360 res = RegSetValueExA(clsid_key, mimetypes_valuename, 0, REG_SZ,
361 (CONST BYTE*)(list->mimetypes),
362 strlen(list->mimetypes) + 1);
363 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
366 if (list->extensions) {
367 res = RegSetValueExA(clsid_key, extensions_valuename, 0, REG_SZ,
368 (CONST BYTE*)(list->extensions),
369 strlen(list->extensions) + 1);
370 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
373 if (list->formats) {
374 HKEY formats_key;
375 GUID const * const *format;
377 res = RegCreateKeyExW(clsid_key, formats_keyname, 0, NULL, 0,
378 KEY_READ | KEY_WRITE, NULL, &formats_key, NULL);
379 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
380 for (format=list->formats; *format; ++format)
382 HKEY format_key;
383 StringFromGUID2(*format, buf, 39);
384 res = RegCreateKeyExW(formats_key, buf, 0, NULL, 0,
385 KEY_READ | KEY_WRITE, NULL, &format_key, NULL);
386 if (res != ERROR_SUCCESS) break;
387 RegCloseKey(format_key);
389 RegCloseKey(formats_key);
390 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
393 if (list->patterns) {
394 HKEY patterns_key;
395 int i;
397 res = RegCreateKeyExW(clsid_key, patterns_keyname, 0, NULL, 0,
398 KEY_READ | KEY_WRITE, NULL, &patterns_key, NULL);
399 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
400 for (i=0; list->patterns[i].length; i++)
402 HKEY pattern_key;
403 static const WCHAR int_format[] = {'%','i',0};
404 snprintfW(buf, 39, int_format, i);
405 res = RegCreateKeyExW(patterns_key, buf, 0, NULL, 0,
406 KEY_READ | KEY_WRITE, NULL, &pattern_key, NULL);
407 if (res != ERROR_SUCCESS) break;
408 res = RegSetValueExA(pattern_key, length_valuename, 0, REG_DWORD,
409 (CONST BYTE*)(&list->patterns[i].length), 4);
410 if (res == ERROR_SUCCESS)
411 res = RegSetValueExA(pattern_key, position_valuename, 0, REG_DWORD,
412 (CONST BYTE*)(&list->patterns[i].position), 4);
413 if (res == ERROR_SUCCESS)
414 res = RegSetValueExA(pattern_key, pattern_valuename, 0, REG_BINARY,
415 list->patterns[i].pattern,
416 list->patterns[i].length);
417 if (res == ERROR_SUCCESS)
418 res = RegSetValueExA(pattern_key, mask_valuename, 0, REG_BINARY,
419 list->patterns[i].mask,
420 list->patterns[i].length);
421 if (res == ERROR_SUCCESS)
422 res = RegSetValueExA(pattern_key, endofstream_valuename, 0, REG_DWORD,
423 (CONST BYTE*)&(list->patterns[i].endofstream), 4);
424 RegCloseKey(pattern_key);
426 RegCloseKey(patterns_key);
427 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
430 error_close_clsid_key:
431 RegCloseKey(clsid_key);
434 error_close_coclass_key:
435 RegCloseKey(instance_key);
436 RegCloseKey(decoders_key);
437 RegCloseKey(coclass_key);
438 error_return:
439 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
442 /***********************************************************************
443 * unregister_decoders
445 static HRESULT unregister_decoders(struct regsvr_decoder const *list)
447 LONG res = ERROR_SUCCESS;
448 HKEY coclass_key;
449 WCHAR buf[39];
450 HKEY decoders_key;
451 HKEY instance_key;
453 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0,
454 KEY_READ | KEY_WRITE, &coclass_key);
455 if (res == ERROR_FILE_NOT_FOUND) return S_OK;
457 if (res == ERROR_SUCCESS) {
458 StringFromGUID2(&CATID_WICBitmapDecoders, buf, 39);
459 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
460 KEY_READ | KEY_WRITE, NULL, &decoders_key, NULL);
461 if (res == ERROR_SUCCESS)
463 res = RegCreateKeyExW(decoders_key, instance_keyname, 0, NULL, 0,
464 KEY_READ | KEY_WRITE, NULL, &instance_key, NULL);
465 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
467 if (res != ERROR_SUCCESS)
468 RegCloseKey(coclass_key);
470 if (res != ERROR_SUCCESS) goto error_return;
472 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
473 StringFromGUID2(list->clsid, buf, 39);
475 res = RegDeleteTreeW(coclass_key, buf);
476 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
477 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
479 res = RegDeleteTreeW(instance_key, buf);
480 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
481 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
484 error_close_coclass_key:
485 RegCloseKey(instance_key);
486 RegCloseKey(decoders_key);
487 RegCloseKey(coclass_key);
488 error_return:
489 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
492 /***********************************************************************
493 * register_encoders
495 static HRESULT register_encoders(struct regsvr_encoder const *list)
497 LONG res = ERROR_SUCCESS;
498 HKEY coclass_key;
499 WCHAR buf[39];
500 HKEY encoders_key;
501 HKEY instance_key;
503 res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0,
504 KEY_READ | KEY_WRITE, NULL, &coclass_key, NULL);
505 if (res == ERROR_SUCCESS) {
506 StringFromGUID2(&CATID_WICBitmapEncoders, buf, 39);
507 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
508 KEY_READ | KEY_WRITE, NULL, &encoders_key, NULL);
509 if (res == ERROR_SUCCESS)
511 res = RegCreateKeyExW(encoders_key, instance_keyname, 0, NULL, 0,
512 KEY_READ | KEY_WRITE, NULL, &instance_key, NULL);
513 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
515 if (res != ERROR_SUCCESS)
516 RegCloseKey(coclass_key);
518 if (res != ERROR_SUCCESS) goto error_return;
520 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
521 HKEY clsid_key;
522 HKEY instance_clsid_key;
524 StringFromGUID2(list->clsid, buf, 39);
525 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
526 KEY_READ | KEY_WRITE, NULL, &clsid_key, NULL);
527 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
529 StringFromGUID2(list->clsid, buf, 39);
530 res = RegCreateKeyExW(instance_key, buf, 0, NULL, 0,
531 KEY_READ | KEY_WRITE, NULL, &instance_clsid_key, NULL);
532 if (res == ERROR_SUCCESS) {
533 res = RegSetValueExW(instance_clsid_key, clsid_valuename, 0, REG_SZ,
534 (CONST BYTE*)(buf), 78);
535 RegCloseKey(instance_clsid_key);
537 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
539 if (list->author) {
540 res = RegSetValueExA(clsid_key, author_valuename, 0, REG_SZ,
541 (CONST BYTE*)(list->author),
542 strlen(list->author) + 1);
543 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
546 if (list->friendlyname) {
547 res = RegSetValueExA(clsid_key, friendlyname_valuename, 0, REG_SZ,
548 (CONST BYTE*)(list->friendlyname),
549 strlen(list->friendlyname) + 1);
550 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
553 if (list->vendor) {
554 StringFromGUID2(list->vendor, buf, 39);
555 res = RegSetValueExW(clsid_key, vendor_valuename, 0, REG_SZ,
556 (CONST BYTE*)(buf), 78);
557 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
560 if (list->version) {
561 res = RegSetValueExA(clsid_key, version_valuename, 0, REG_SZ,
562 (CONST BYTE*)(list->version),
563 strlen(list->version) + 1);
564 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
567 if (list->mimetypes) {
568 res = RegSetValueExA(clsid_key, mimetypes_valuename, 0, REG_SZ,
569 (CONST BYTE*)(list->mimetypes),
570 strlen(list->mimetypes) + 1);
571 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
574 if (list->extensions) {
575 res = RegSetValueExA(clsid_key, extensions_valuename, 0, REG_SZ,
576 (CONST BYTE*)(list->extensions),
577 strlen(list->extensions) + 1);
578 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
581 if (list->formats) {
582 HKEY formats_key;
583 GUID const * const *format;
585 res = RegCreateKeyExW(clsid_key, formats_keyname, 0, NULL, 0,
586 KEY_READ | KEY_WRITE, NULL, &formats_key, NULL);
587 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
588 for (format=list->formats; *format; ++format)
590 HKEY format_key;
591 StringFromGUID2(*format, buf, 39);
592 res = RegCreateKeyExW(formats_key, buf, 0, NULL, 0,
593 KEY_READ | KEY_WRITE, NULL, &format_key, NULL);
594 if (res != ERROR_SUCCESS) break;
595 RegCloseKey(format_key);
597 RegCloseKey(formats_key);
598 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
601 error_close_clsid_key:
602 RegCloseKey(clsid_key);
605 error_close_coclass_key:
606 RegCloseKey(instance_key);
607 RegCloseKey(encoders_key);
608 RegCloseKey(coclass_key);
609 error_return:
610 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
613 /***********************************************************************
614 * unregister_encoders
616 static HRESULT unregister_encoders(struct regsvr_encoder const *list)
618 LONG res = ERROR_SUCCESS;
619 HKEY coclass_key;
620 WCHAR buf[39];
621 HKEY encoders_key;
622 HKEY instance_key;
624 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0,
625 KEY_READ | KEY_WRITE, &coclass_key);
626 if (res == ERROR_FILE_NOT_FOUND) return S_OK;
628 if (res == ERROR_SUCCESS) {
629 StringFromGUID2(&CATID_WICBitmapEncoders, buf, 39);
630 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
631 KEY_READ | KEY_WRITE, NULL, &encoders_key, NULL);
632 if (res == ERROR_SUCCESS)
634 res = RegCreateKeyExW(encoders_key, instance_keyname, 0, NULL, 0,
635 KEY_READ | KEY_WRITE, NULL, &instance_key, NULL);
636 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
638 if (res != ERROR_SUCCESS)
639 RegCloseKey(coclass_key);
641 if (res != ERROR_SUCCESS) goto error_return;
643 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
644 StringFromGUID2(list->clsid, buf, 39);
646 res = RegDeleteTreeW(coclass_key, buf);
647 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
648 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
650 res = RegDeleteTreeW(instance_key, buf);
651 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
652 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
655 error_close_coclass_key:
656 RegCloseKey(instance_key);
657 RegCloseKey(encoders_key);
658 RegCloseKey(coclass_key);
659 error_return:
660 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
663 /***********************************************************************
664 * register_converters
666 static HRESULT register_converters(struct regsvr_converter const *list)
668 LONG res = ERROR_SUCCESS;
669 HKEY coclass_key;
670 WCHAR buf[39];
671 HKEY converters_key;
672 HKEY instance_key;
674 res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0,
675 KEY_READ | KEY_WRITE, NULL, &coclass_key, NULL);
676 if (res == ERROR_SUCCESS) {
677 StringFromGUID2(&CATID_WICFormatConverters, buf, 39);
678 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
679 KEY_READ | KEY_WRITE, NULL, &converters_key, NULL);
680 if (res == ERROR_SUCCESS)
682 res = RegCreateKeyExW(converters_key, instance_keyname, 0, NULL, 0,
683 KEY_READ | KEY_WRITE, NULL, &instance_key, NULL);
684 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
686 if (res != ERROR_SUCCESS)
687 RegCloseKey(coclass_key);
689 if (res != ERROR_SUCCESS) goto error_return;
691 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
692 HKEY clsid_key;
693 HKEY instance_clsid_key;
695 StringFromGUID2(list->clsid, buf, 39);
696 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
697 KEY_READ | KEY_WRITE, NULL, &clsid_key, NULL);
698 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
700 StringFromGUID2(list->clsid, buf, 39);
701 res = RegCreateKeyExW(instance_key, buf, 0, NULL, 0,
702 KEY_READ | KEY_WRITE, NULL, &instance_clsid_key, NULL);
703 if (res == ERROR_SUCCESS) {
704 res = RegSetValueExW(instance_clsid_key, clsid_valuename, 0, REG_SZ,
705 (CONST BYTE*)(buf), 78);
706 RegCloseKey(instance_clsid_key);
708 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
710 if (list->author) {
711 res = RegSetValueExA(clsid_key, author_valuename, 0, REG_SZ,
712 (CONST BYTE*)(list->author),
713 strlen(list->author) + 1);
714 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
717 if (list->friendlyname) {
718 res = RegSetValueExA(clsid_key, friendlyname_valuename, 0, REG_SZ,
719 (CONST BYTE*)(list->friendlyname),
720 strlen(list->friendlyname) + 1);
721 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
724 if (list->vendor) {
725 StringFromGUID2(list->vendor, buf, 39);
726 res = RegSetValueExW(clsid_key, vendor_valuename, 0, REG_SZ,
727 (CONST BYTE*)(buf), 78);
728 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
731 if (list->version) {
732 res = RegSetValueExA(clsid_key, version_valuename, 0, REG_SZ,
733 (CONST BYTE*)(list->version),
734 strlen(list->version) + 1);
735 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
738 if (list->formats) {
739 HKEY formats_key;
740 GUID const * const *format;
742 res = RegCreateKeyExW(clsid_key, pixelformats_keyname, 0, NULL, 0,
743 KEY_READ | KEY_WRITE, NULL, &formats_key, NULL);
744 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
745 for (format=list->formats; *format; ++format)
747 HKEY format_key;
748 StringFromGUID2(*format, buf, 39);
749 res = RegCreateKeyExW(formats_key, buf, 0, NULL, 0,
750 KEY_READ | KEY_WRITE, NULL, &format_key, NULL);
751 if (res != ERROR_SUCCESS) break;
752 RegCloseKey(format_key);
754 RegCloseKey(formats_key);
755 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
758 error_close_clsid_key:
759 RegCloseKey(clsid_key);
762 error_close_coclass_key:
763 RegCloseKey(instance_key);
764 RegCloseKey(converters_key);
765 RegCloseKey(coclass_key);
766 error_return:
767 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
770 /***********************************************************************
771 * unregister_converters
773 static HRESULT unregister_converters(struct regsvr_converter const *list)
775 LONG res = ERROR_SUCCESS;
776 HKEY coclass_key;
777 WCHAR buf[39];
778 HKEY converters_key;
779 HKEY instance_key;
781 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0,
782 KEY_READ | KEY_WRITE, &coclass_key);
783 if (res == ERROR_FILE_NOT_FOUND) return S_OK;
785 if (res == ERROR_SUCCESS) {
786 StringFromGUID2(&CATID_WICFormatConverters, buf, 39);
787 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
788 KEY_READ | KEY_WRITE, NULL, &converters_key, NULL);
789 if (res == ERROR_SUCCESS)
791 res = RegCreateKeyExW(converters_key, instance_keyname, 0, NULL, 0,
792 KEY_READ | KEY_WRITE, NULL, &instance_key, NULL);
793 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
795 if (res != ERROR_SUCCESS)
796 RegCloseKey(coclass_key);
798 if (res != ERROR_SUCCESS) goto error_return;
800 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
801 StringFromGUID2(list->clsid, buf, 39);
803 res = RegDeleteTreeW(coclass_key, buf);
804 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
805 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
807 res = RegDeleteTreeW(instance_key, buf);
808 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
809 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
812 error_close_coclass_key:
813 RegCloseKey(instance_key);
814 RegCloseKey(converters_key);
815 RegCloseKey(coclass_key);
816 error_return:
817 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
820 /***********************************************************************
821 * register_key_defvalueW
823 static LONG register_key_defvalueW(
824 HKEY base,
825 WCHAR const *name,
826 WCHAR const *value)
828 LONG res;
829 HKEY key;
831 res = RegCreateKeyExW(base, name, 0, NULL, 0,
832 KEY_READ | KEY_WRITE, NULL, &key, NULL);
833 if (res != ERROR_SUCCESS) return res;
834 res = RegSetValueExW(key, NULL, 0, REG_SZ, (CONST BYTE*)value,
835 (lstrlenW(value) + 1) * sizeof(WCHAR));
836 RegCloseKey(key);
837 return res;
840 /***********************************************************************
841 * register_key_defvalueA
843 static LONG register_key_defvalueA(
844 HKEY base,
845 WCHAR const *name,
846 char const *value)
848 LONG res;
849 HKEY key;
851 res = RegCreateKeyExW(base, name, 0, NULL, 0,
852 KEY_READ | KEY_WRITE, NULL, &key, NULL);
853 if (res != ERROR_SUCCESS) return res;
854 res = RegSetValueExA(key, NULL, 0, REG_SZ, (CONST BYTE*)value,
855 lstrlenA(value) + 1);
856 RegCloseKey(key);
857 return res;
860 /***********************************************************************
861 * register_progid
863 static LONG register_progid(
864 WCHAR const *clsid,
865 char const *progid,
866 char const *curver_progid,
867 char const *name,
868 char const *extra)
870 LONG res;
871 HKEY progid_key;
873 res = RegCreateKeyExA(HKEY_CLASSES_ROOT, progid, 0,
874 NULL, 0, KEY_READ | KEY_WRITE, NULL,
875 &progid_key, NULL);
876 if (res != ERROR_SUCCESS) return res;
878 if (name) {
879 res = RegSetValueExA(progid_key, NULL, 0, REG_SZ,
880 (CONST BYTE*)name, strlen(name) + 1);
881 if (res != ERROR_SUCCESS) goto error_close_progid_key;
884 if (clsid) {
885 res = register_key_defvalueW(progid_key, clsid_keyname, clsid);
886 if (res != ERROR_SUCCESS) goto error_close_progid_key;
889 if (curver_progid) {
890 res = register_key_defvalueA(progid_key, curver_keyname,
891 curver_progid);
892 if (res != ERROR_SUCCESS) goto error_close_progid_key;
895 if (extra) {
896 HKEY extra_key;
898 res = RegCreateKeyExA(progid_key, extra, 0,
899 NULL, 0, KEY_READ | KEY_WRITE, NULL,
900 &extra_key, NULL);
901 if (res == ERROR_SUCCESS)
902 RegCloseKey(extra_key);
905 error_close_progid_key:
906 RegCloseKey(progid_key);
907 return res;
910 /***********************************************************************
911 * coclass list
913 static struct regsvr_coclass const coclass_list[] = {
914 { &CLSID_WICImagingFactory,
915 "WIC Imaging Factory",
916 NULL,
917 "windowscodecs.dll",
918 "Both"
920 { &CLSID_WICBmpDecoder,
921 "WIC BMP Decoder",
922 NULL,
923 "windowscodecs.dll",
924 "Both"
926 { &CLSID_WICPngDecoder,
927 "WIC PNG Decoder",
928 NULL,
929 "windowscodecs.dll",
930 "Both"
932 { &CLSID_WICPngEncoder,
933 "WIC PNG Encoder",
934 NULL,
935 "windowscodecs.dll",
936 "Both"
938 { &CLSID_WICBmpEncoder,
939 "WIC BMP Encoder",
940 NULL,
941 "windowscodecs.dll",
942 "Apartment"
944 { &CLSID_WICGifDecoder,
945 "WIC GIF Decoder",
946 NULL,
947 "windowscodecs.dll",
948 "Both"
950 { &CLSID_WICIcoDecoder,
951 "WIC ICO Decoder",
952 NULL,
953 "windowscodecs.dll",
954 "Both"
956 { &CLSID_WICJpegDecoder,
957 "WIC JPEG Decoder",
958 NULL,
959 "windowscodecs.dll",
960 "Both"
962 { &CLSID_WICTiffDecoder,
963 "WIC TIFF Decoder",
964 NULL,
965 "windowscodecs.dll",
966 "Both"
969 &CLSID_WICIcnsEncoder,
970 "WIC ICNS Encoder",
971 NULL,
972 "windowscodecs.dll",
973 "Both"
975 { &CLSID_WICDefaultFormatConverter,
976 "WIC Default Format Converter",
977 NULL,
978 "windowscodecs.dll",
979 "Both"
981 { NULL } /* list terminator */
984 /***********************************************************************
985 * decoder list
987 static const BYTE mask_all[] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
989 static const BYTE bmp_magic[] = {0x42,0x4d};
991 static GUID const * const bmp_formats[] = {
992 &GUID_WICPixelFormat1bppIndexed,
993 &GUID_WICPixelFormat2bppIndexed,
994 &GUID_WICPixelFormat4bppIndexed,
995 &GUID_WICPixelFormat8bppIndexed,
996 &GUID_WICPixelFormat16bppBGR555,
997 &GUID_WICPixelFormat16bppBGR565,
998 &GUID_WICPixelFormat24bppBGR,
999 &GUID_WICPixelFormat32bppBGR,
1000 &GUID_WICPixelFormat32bppBGRA,
1001 NULL
1004 static struct decoder_pattern const bmp_patterns[] = {
1005 {2,0,bmp_magic,mask_all,0},
1009 static const BYTE gif87a_magic[6] = "GIF87a";
1010 static const BYTE gif89a_magic[6] = "GIF89a";
1012 static GUID const * const gif_formats[] = {
1013 &GUID_WICPixelFormat8bppIndexed,
1014 NULL
1017 static struct decoder_pattern const gif_patterns[] = {
1018 {6,0,gif87a_magic,mask_all,0},
1019 {6,0,gif89a_magic,mask_all,0},
1023 static const BYTE ico_magic[] = {00,00,01,00};
1025 static GUID const * const ico_formats[] = {
1026 &GUID_WICPixelFormat32bppBGRA,
1027 NULL
1030 static struct decoder_pattern const ico_patterns[] = {
1031 {4,0,ico_magic,mask_all,0},
1035 static const BYTE jpeg_magic[] = {0xff, 0xd8, 0xff, 0xe0};
1037 static GUID const * const jpeg_formats[] = {
1038 &GUID_WICPixelFormat24bppBGR,
1039 &GUID_WICPixelFormat32bppCMYK,
1040 &GUID_WICPixelFormat8bppGray,
1041 NULL
1044 static struct decoder_pattern const jpeg_patterns[] = {
1045 {4,0,jpeg_magic,mask_all,0},
1049 static const BYTE png_magic[] = {137,80,78,71,13,10,26,10};
1051 static GUID const * const png_formats[] = {
1052 &GUID_WICPixelFormatBlackWhite,
1053 &GUID_WICPixelFormat2bppGray,
1054 &GUID_WICPixelFormat4bppGray,
1055 &GUID_WICPixelFormat8bppGray,
1056 &GUID_WICPixelFormat16bppGray,
1057 &GUID_WICPixelFormat32bppBGRA,
1058 &GUID_WICPixelFormat64bppRGBA,
1059 &GUID_WICPixelFormat1bppIndexed,
1060 &GUID_WICPixelFormat2bppIndexed,
1061 &GUID_WICPixelFormat4bppIndexed,
1062 &GUID_WICPixelFormat8bppIndexed,
1063 &GUID_WICPixelFormat24bppBGR,
1064 &GUID_WICPixelFormat48bppRGB,
1065 NULL
1068 static struct decoder_pattern const png_patterns[] = {
1069 {8,0,png_magic,mask_all,0},
1073 static const BYTE tiff_magic_le[] = {0x49,0x49,42,0};
1074 static const BYTE tiff_magic_be[] = {0x4d,0x4d,0,42};
1076 static GUID const * const tiff_formats[] = {
1077 &GUID_WICPixelFormatBlackWhite,
1078 &GUID_WICPixelFormat4bppGray,
1079 &GUID_WICPixelFormat8bppGray,
1080 &GUID_WICPixelFormat4bppIndexed,
1081 &GUID_WICPixelFormat8bppIndexed,
1082 &GUID_WICPixelFormat32bppBGR,
1083 &GUID_WICPixelFormat32bppBGRA,
1084 &GUID_WICPixelFormat32bppPBGRA,
1085 &GUID_WICPixelFormat48bppRGB,
1086 NULL
1089 static struct decoder_pattern const tiff_patterns[] = {
1090 {4,0,tiff_magic_le,mask_all,0},
1091 {4,0,tiff_magic_be,mask_all,0},
1095 static struct regsvr_decoder const decoder_list[] = {
1096 { &CLSID_WICBmpDecoder,
1097 "The Wine Project",
1098 "BMP Decoder",
1099 "1.0.0.0",
1100 &GUID_VendorMicrosoft,
1101 "image/bmp",
1102 ".bmp,.dib,.rle",
1103 bmp_formats,
1104 bmp_patterns
1106 { &CLSID_WICGifDecoder,
1107 "The Wine Project",
1108 "GIF Decoder",
1109 "1.0.0.0",
1110 &GUID_VendorMicrosoft,
1111 "image/gif",
1112 ".gif",
1113 gif_formats,
1114 gif_patterns
1116 { &CLSID_WICIcoDecoder,
1117 "The Wine Project",
1118 "ICO Decoder",
1119 "1.0.0.0",
1120 &GUID_VendorMicrosoft,
1121 "image/vnd.microsoft.icon",
1122 ".ico",
1123 ico_formats,
1124 ico_patterns
1126 { &CLSID_WICJpegDecoder,
1127 "The Wine Project",
1128 "JPEG Decoder",
1129 "1.0.0.0",
1130 &GUID_VendorMicrosoft,
1131 "image/jpeg",
1132 ".jpg;.jpeg;.jfif",
1133 jpeg_formats,
1134 jpeg_patterns
1136 { &CLSID_WICPngDecoder,
1137 "The Wine Project",
1138 "PNG Decoder",
1139 "1.0.0.0",
1140 &GUID_VendorMicrosoft,
1141 "image/png",
1142 ".png",
1143 png_formats,
1144 png_patterns
1146 { &CLSID_WICTiffDecoder,
1147 "The Wine Project",
1148 "TIFF Decoder",
1149 "1.0.0.0",
1150 &GUID_VendorMicrosoft,
1151 "image/tiff",
1152 ".tif;.tiff",
1153 tiff_formats,
1154 tiff_patterns
1156 { NULL } /* list terminator */
1159 static GUID const * const bmp_encode_formats[] = {
1160 &GUID_WICPixelFormat16bppBGR555,
1161 &GUID_WICPixelFormat16bppBGR565,
1162 &GUID_WICPixelFormat24bppBGR,
1163 &GUID_WICPixelFormat32bppBGR,
1164 NULL
1167 static GUID const * const png_encode_formats[] = {
1168 &GUID_WICPixelFormat24bppBGR,
1169 &GUID_WICPixelFormatBlackWhite,
1170 &GUID_WICPixelFormat2bppGray,
1171 &GUID_WICPixelFormat4bppGray,
1172 &GUID_WICPixelFormat8bppGray,
1173 &GUID_WICPixelFormat16bppGray,
1174 &GUID_WICPixelFormat32bppBGR,
1175 &GUID_WICPixelFormat32bppBGRA,
1176 &GUID_WICPixelFormat48bppRGB,
1177 &GUID_WICPixelFormat64bppRGBA,
1178 NULL
1181 static GUID const * const icns_encode_formats[] = {
1182 &GUID_WICPixelFormat32bppBGRA,
1183 NULL
1186 static struct regsvr_encoder const encoder_list[] = {
1187 { &CLSID_WICBmpEncoder,
1188 "The Wine Project",
1189 "BMP Encoder",
1190 "1.0.0.0",
1191 &GUID_VendorMicrosoft,
1192 "image/bmp",
1193 ".bmp,.dib,.rle",
1194 bmp_encode_formats
1196 { &CLSID_WICPngEncoder,
1197 "The Wine Project",
1198 "PNG Encoder",
1199 "1.0.0.0",
1200 &GUID_VendorMicrosoft,
1201 "image/png",
1202 ".png",
1203 png_encode_formats
1205 { &CLSID_WICIcnsEncoder,
1206 "The Wine Project",
1207 "ICNS Encoder",
1208 "1.0.0.0",
1209 &GUID_VendorWine,
1210 "image/icns",
1211 ".icns",
1212 icns_encode_formats
1214 { NULL } /* list terminator */
1217 static GUID const * const converter_formats[] = {
1218 &GUID_WICPixelFormat1bppIndexed,
1219 &GUID_WICPixelFormat2bppIndexed,
1220 &GUID_WICPixelFormat4bppIndexed,
1221 &GUID_WICPixelFormat8bppIndexed,
1222 &GUID_WICPixelFormatBlackWhite,
1223 &GUID_WICPixelFormat2bppGray,
1224 &GUID_WICPixelFormat4bppGray,
1225 &GUID_WICPixelFormat8bppGray,
1226 &GUID_WICPixelFormat16bppGray,
1227 &GUID_WICPixelFormat16bppBGR555,
1228 &GUID_WICPixelFormat16bppBGR565,
1229 &GUID_WICPixelFormat24bppBGR,
1230 &GUID_WICPixelFormat32bppBGR,
1231 &GUID_WICPixelFormat32bppBGRA,
1232 &GUID_WICPixelFormat48bppRGB,
1233 &GUID_WICPixelFormat64bppRGBA,
1234 &GUID_WICPixelFormat32bppCMYK,
1235 NULL
1238 static struct regsvr_converter const converter_list[] = {
1239 { &CLSID_WICDefaultFormatConverter,
1240 "The Wine Project",
1241 "Default Pixel Format Converter",
1242 "1.0.0.0",
1243 &GUID_VendorMicrosoft,
1244 converter_formats
1246 { NULL } /* list terminator */
1249 HRESULT WINAPI DllRegisterServer(void)
1251 HRESULT hr;
1253 TRACE("\n");
1255 hr = register_coclasses(coclass_list);
1256 if (SUCCEEDED(hr))
1257 register_decoders(decoder_list);
1258 if (SUCCEEDED(hr))
1259 register_encoders(encoder_list);
1260 if (SUCCEEDED(hr))
1261 register_converters(converter_list);
1262 return hr;
1265 HRESULT WINAPI DllUnregisterServer(void)
1267 HRESULT hr;
1269 TRACE("\n");
1271 hr = unregister_coclasses(coclass_list);
1272 if (SUCCEEDED(hr))
1273 unregister_decoders(decoder_list);
1274 if (SUCCEEDED(hr))
1275 unregister_encoders(encoder_list);
1276 if (SUCCEEDED(hr))
1277 unregister_converters(converter_list);
1278 return hr;