[CABMAN]
[reactos.git] / reactos / dll / directx / wine / quartz / regsvr.c
1 /*
2 * self-registerable dll functions for quartz.dll
3 *
4 * Copyright (C) 2003 John K. Hohm
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21 #define WIN32_NO_STATUS
22 #define _INC_WINDOWS
23 #define COM_NO_WINDOWS_H
24
25 #define NONAMELESSUNION
26 #define NONAMELESSSTRUCT
27 #define COBJMACROS
28 #include <stdarg.h>
29 //#include <string.h>
30
31 #include <windef.h>
32 #include <winbase.h>
33 #include <wingdi.h>
34 #include <winuser.h>
35 #include <winreg.h>
36 //#include "winerror.h"
37
38 //#include "ole2.h"
39 #include "objbase.h"
40 #include <uuids.h>
41 #include <strmif.h>
42
43 #include <wine/debug.h>
44 #include <wine/unicode.h>
45
46 WINE_DEFAULT_DEBUG_CHANNEL(quartz);
47
48 /*
49 * Near the bottom of this file are the exported DllRegisterServer and
50 * DllUnregisterServer, which make all this worthwhile.
51 */
52
53 /***********************************************************************
54 * interface for self-registering
55 */
56 struct regsvr_interface
57 {
58 IID const *iid; /* NULL for end of list */
59 LPCSTR name; /* can be NULL to omit */
60 IID const *base_iid; /* can be NULL to omit */
61 int num_methods; /* can be <0 to omit */
62 CLSID const *ps_clsid; /* can be NULL to omit */
63 CLSID const *ps_clsid32; /* can be NULL to omit */
64 };
65
66 static HRESULT register_interfaces(struct regsvr_interface const *list);
67 static HRESULT unregister_interfaces(struct regsvr_interface const *list);
68
69 struct regsvr_coclass
70 {
71 CLSID const *clsid; /* NULL for end of list */
72 LPCSTR name; /* can be NULL to omit */
73 LPCSTR ips; /* can be NULL to omit */
74 LPCSTR ips32; /* can be NULL to omit */
75 LPCSTR ips32_tmodel; /* can be NULL to omit */
76 LPCSTR progid; /* can be NULL to omit */
77 LPCSTR viprogid; /* can be NULL to omit */
78 LPCSTR progid_extra; /* can be NULL to omit */
79 };
80
81 static HRESULT register_coclasses(struct regsvr_coclass const *list);
82 static HRESULT unregister_coclasses(struct regsvr_coclass const *list);
83
84 struct regsvr_mediatype_parsing
85 {
86 CLSID const *majortype; /* NULL for end of list */
87 CLSID const *subtype;
88 LPCSTR line[11]; /* NULL for end of list */
89 };
90
91 static HRESULT register_mediatypes_parsing(struct regsvr_mediatype_parsing const *list);
92 static HRESULT unregister_mediatypes_parsing(struct regsvr_mediatype_parsing const *list);
93
94 struct regsvr_mediatype_extension
95 {
96 CLSID const *majortype; /* NULL for end of list */
97 CLSID const *subtype;
98 LPCSTR extension;
99 };
100
101 struct mediatype
102 {
103 CLSID const *majortype; /* NULL for end of list */
104 CLSID const *subtype;
105 DWORD fourcc;
106 };
107
108 struct pin
109 {
110 DWORD flags; /* 0xFFFFFFFF for end of list */
111 struct mediatype mediatypes[11];
112 };
113
114 struct regsvr_filter
115 {
116 CLSID const *clsid; /* NULL for end of list */
117 CLSID const *category;
118 WCHAR name[50];
119 DWORD merit;
120 struct pin pins[11];
121 };
122
123 static HRESULT register_mediatypes_extension(struct regsvr_mediatype_extension const *list);
124 static HRESULT unregister_mediatypes_extension(struct regsvr_mediatype_extension const *list);
125
126 static HRESULT register_filters(struct regsvr_filter const *list);
127 static HRESULT unregister_filters(struct regsvr_filter const *list);
128
129 /***********************************************************************
130 * static string constants
131 */
132 static const WCHAR interface_keyname[] = {
133 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c', 'e', 0 };
134 static const WCHAR base_ifa_keyname[] = {
135 'B', 'a', 's', 'e', 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c',
136 'e', 0 };
137 static const WCHAR num_methods_keyname[] = {
138 'N', 'u', 'm', 'M', 'e', 't', 'h', 'o', 'd', 's', 0 };
139 static const WCHAR ps_clsid_keyname[] = {
140 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
141 'i', 'd', 0 };
142 static const WCHAR ps_clsid32_keyname[] = {
143 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
144 'i', 'd', '3', '2', 0 };
145 static const WCHAR clsid_keyname[] = {
146 'C', 'L', 'S', 'I', 'D', 0 };
147 static const WCHAR curver_keyname[] = {
148 'C', 'u', 'r', 'V', 'e', 'r', 0 };
149 static const WCHAR ips_keyname[] = {
150 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
151 0 };
152 static const WCHAR ips32_keyname[] = {
153 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
154 '3', '2', 0 };
155 static const WCHAR progid_keyname[] = {
156 'P', 'r', 'o', 'g', 'I', 'D', 0 };
157 static const WCHAR viprogid_keyname[] = {
158 'V', 'e', 'r', 's', 'i', 'o', 'n', 'I', 'n', 'd', 'e', 'p',
159 'e', 'n', 'd', 'e', 'n', 't', 'P', 'r', 'o', 'g', 'I', 'D',
160 0 };
161 static const char tmodel_valuename[] = "ThreadingModel";
162 static const WCHAR mediatype_name[] = {
163 'M', 'e', 'd', 'i', 'a', ' ', 'T', 'y', 'p', 'e', 0 };
164 static const WCHAR subtype_valuename[] = {
165 'S', 'u', 'b', 't', 'y', 'p', 'e', 0 };
166 static const WCHAR sourcefilter_valuename[] = {
167 'S', 'o', 'u', 'r', 'c', 'e', ' ', 'F', 'i', 'l', 't', 'e', 'r', 0 };
168 static const WCHAR extensions_keyname[] = {
169 'E', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 's', 0 };
170
171 /***********************************************************************
172 * static helper functions
173 */
174 static LONG register_key_guid(HKEY base, WCHAR const *name, GUID const *guid);
175 static LONG register_key_defvalueW(HKEY base, WCHAR const *name,
176 WCHAR const *value);
177 static LONG register_key_defvalueA(HKEY base, WCHAR const *name,
178 char const *value);
179 static LONG register_progid(WCHAR const *clsid,
180 char const *progid, char const *curver_progid,
181 char const *name, char const *extra);
182
183 /***********************************************************************
184 * register_interfaces
185 */
186 static HRESULT register_interfaces(struct regsvr_interface const *list)
187 {
188 LONG res = ERROR_SUCCESS;
189 HKEY interface_key;
190
191 res = RegCreateKeyExW(HKEY_CLASSES_ROOT, interface_keyname, 0, NULL, 0,
192 KEY_READ | KEY_WRITE, NULL, &interface_key, NULL);
193 if (res != ERROR_SUCCESS) goto error_return;
194
195 for (; res == ERROR_SUCCESS && list->iid; ++list) {
196 WCHAR buf[39];
197 HKEY iid_key;
198
199 StringFromGUID2(list->iid, buf, 39);
200 res = RegCreateKeyExW(interface_key, buf, 0, NULL, 0,
201 KEY_READ | KEY_WRITE, NULL, &iid_key, NULL);
202 if (res != ERROR_SUCCESS) goto error_close_interface_key;
203
204 if (list->name) {
205 res = RegSetValueExA(iid_key, NULL, 0, REG_SZ,
206 (CONST BYTE*)(list->name),
207 strlen(list->name) + 1);
208 if (res != ERROR_SUCCESS) goto error_close_iid_key;
209 }
210
211 if (list->base_iid) {
212 res = register_key_guid(iid_key, base_ifa_keyname, list->base_iid);
213 if (res != ERROR_SUCCESS) goto error_close_iid_key;
214 }
215
216 if (0 <= list->num_methods) {
217 static const WCHAR fmt[] = { '%', 'd', 0 };
218 HKEY key;
219
220 res = RegCreateKeyExW(iid_key, num_methods_keyname, 0, NULL, 0,
221 KEY_READ | KEY_WRITE, NULL, &key, NULL);
222 if (res != ERROR_SUCCESS) goto error_close_iid_key;
223
224 sprintfW(buf, fmt, list->num_methods);
225 res = RegSetValueExW(key, NULL, 0, REG_SZ,
226 (CONST BYTE*)buf,
227 (lstrlenW(buf) + 1) * sizeof(WCHAR));
228 RegCloseKey(key);
229
230 if (res != ERROR_SUCCESS) goto error_close_iid_key;
231 }
232
233 if (list->ps_clsid) {
234 res = register_key_guid(iid_key, ps_clsid_keyname, list->ps_clsid);
235 if (res != ERROR_SUCCESS) goto error_close_iid_key;
236 }
237
238 if (list->ps_clsid32) {
239 res = register_key_guid(iid_key, ps_clsid32_keyname, list->ps_clsid32);
240 if (res != ERROR_SUCCESS) goto error_close_iid_key;
241 }
242
243 error_close_iid_key:
244 RegCloseKey(iid_key);
245 }
246
247 error_close_interface_key:
248 RegCloseKey(interface_key);
249 error_return:
250 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
251 }
252
253 /***********************************************************************
254 * unregister_interfaces
255 */
256 static HRESULT unregister_interfaces(struct regsvr_interface const *list)
257 {
258 LONG res = ERROR_SUCCESS;
259 HKEY interface_key;
260
261 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, interface_keyname, 0,
262 KEY_READ | KEY_WRITE, &interface_key);
263 if (res == ERROR_FILE_NOT_FOUND) return S_OK;
264 if (res != ERROR_SUCCESS) goto error_return;
265
266 for (; res == ERROR_SUCCESS && list->iid; ++list) {
267 WCHAR buf[39];
268
269 StringFromGUID2(list->iid, buf, 39);
270 res = RegDeleteTreeW(interface_key, buf);
271 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
272 }
273
274 RegCloseKey(interface_key);
275 error_return:
276 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
277 }
278
279 /***********************************************************************
280 * register_coclasses
281 */
282 static HRESULT register_coclasses(struct regsvr_coclass const *list)
283 {
284 LONG res = ERROR_SUCCESS;
285 HKEY coclass_key;
286
287 res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0,
288 KEY_READ | KEY_WRITE, NULL, &coclass_key, NULL);
289 if (res != ERROR_SUCCESS) goto error_return;
290
291 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
292 WCHAR buf[39];
293 HKEY clsid_key;
294
295 StringFromGUID2(list->clsid, buf, 39);
296 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
297 KEY_READ | KEY_WRITE, NULL, &clsid_key, NULL);
298 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
299
300 if (list->name) {
301 res = RegSetValueExA(clsid_key, NULL, 0, REG_SZ,
302 (CONST BYTE*)(list->name),
303 strlen(list->name) + 1);
304 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
305 }
306
307 if (list->ips) {
308 res = register_key_defvalueA(clsid_key, ips_keyname, list->ips);
309 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
310 }
311
312 if (list->ips32) {
313 HKEY ips32_key;
314
315 res = RegCreateKeyExW(clsid_key, ips32_keyname, 0, NULL, 0,
316 KEY_READ | KEY_WRITE, NULL,
317 &ips32_key, NULL);
318 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
319
320 res = RegSetValueExA(ips32_key, NULL, 0, REG_SZ,
321 (CONST BYTE*)list->ips32,
322 lstrlenA(list->ips32) + 1);
323 if (res == ERROR_SUCCESS && list->ips32_tmodel)
324 res = RegSetValueExA(ips32_key, tmodel_valuename, 0, REG_SZ,
325 (CONST BYTE*)list->ips32_tmodel,
326 strlen(list->ips32_tmodel) + 1);
327 RegCloseKey(ips32_key);
328 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
329 }
330
331 if (list->progid) {
332 res = register_key_defvalueA(clsid_key, progid_keyname,
333 list->progid);
334 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
335
336 res = register_progid(buf, list->progid, NULL,
337 list->name, list->progid_extra);
338 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
339 }
340
341 if (list->viprogid) {
342 res = register_key_defvalueA(clsid_key, viprogid_keyname,
343 list->viprogid);
344 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
345
346 res = register_progid(buf, list->viprogid, list->progid,
347 list->name, list->progid_extra);
348 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
349 }
350
351 error_close_clsid_key:
352 RegCloseKey(clsid_key);
353 }
354
355 error_close_coclass_key:
356 RegCloseKey(coclass_key);
357 error_return:
358 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
359 }
360
361 /***********************************************************************
362 * unregister_coclasses
363 */
364 static HRESULT unregister_coclasses(struct regsvr_coclass const *list)
365 {
366 LONG res = ERROR_SUCCESS;
367 HKEY coclass_key;
368
369 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0,
370 KEY_READ | KEY_WRITE, &coclass_key);
371 if (res == ERROR_FILE_NOT_FOUND) return S_OK;
372 if (res != ERROR_SUCCESS) goto error_return;
373
374 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
375 WCHAR buf[39];
376
377 StringFromGUID2(list->clsid, buf, 39);
378 res = RegDeleteTreeW(coclass_key, buf);
379 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
380 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
381
382 if (list->progid) {
383 res = RegDeleteTreeA(HKEY_CLASSES_ROOT, list->progid);
384 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
385 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
386 }
387
388 if (list->viprogid) {
389 res = RegDeleteTreeA(HKEY_CLASSES_ROOT, list->viprogid);
390 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
391 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
392 }
393 }
394
395 error_close_coclass_key:
396 RegCloseKey(coclass_key);
397 error_return:
398 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
399 }
400
401 /***********************************************************************
402 * register_mediatypes_parsing
403 */
404 static HRESULT register_mediatypes_parsing(struct regsvr_mediatype_parsing const *list)
405 {
406 LONG res = ERROR_SUCCESS;
407 HKEY mediatype_key;
408 WCHAR buf[39];
409 int i;
410
411 res = RegCreateKeyExW(HKEY_CLASSES_ROOT, mediatype_name, 0, NULL, 0,
412 KEY_READ | KEY_WRITE, NULL, &mediatype_key, NULL);
413 if (res != ERROR_SUCCESS) return HRESULT_FROM_WIN32(res);
414
415 for (; res == ERROR_SUCCESS && list->majortype; ++list) {
416 HKEY majortype_key = NULL;
417 HKEY subtype_key = NULL;
418
419 StringFromGUID2(list->majortype, buf, 39);
420 res = RegCreateKeyExW(mediatype_key, buf, 0, NULL, 0,
421 KEY_READ | KEY_WRITE, NULL, &majortype_key, NULL);
422 if (res != ERROR_SUCCESS) goto error_close_keys;
423
424 StringFromGUID2(list->subtype, buf, 39);
425 res = RegCreateKeyExW(majortype_key, buf, 0, NULL, 0,
426 KEY_READ | KEY_WRITE, NULL, &subtype_key, NULL);
427 if (res != ERROR_SUCCESS) goto error_close_keys;
428
429 StringFromGUID2(&CLSID_AsyncReader, buf, 39);
430 res = RegSetValueExW(subtype_key, sourcefilter_valuename, 0, REG_SZ, (CONST BYTE*)buf,
431 (lstrlenW(buf) + 1) * sizeof(WCHAR));
432 if (res != ERROR_SUCCESS) goto error_close_keys;
433
434 for(i = 0; list->line[i]; i++) {
435 char buffer[3];
436 wsprintfA(buffer, "%d", i);
437 res = RegSetValueExA(subtype_key, buffer, 0, REG_SZ, (CONST BYTE*)list->line[i],
438 lstrlenA(list->line[i]));
439 if (res != ERROR_SUCCESS) goto error_close_keys;
440 }
441
442 error_close_keys:
443 if (majortype_key)
444 RegCloseKey(majortype_key);
445 if (subtype_key)
446 RegCloseKey(subtype_key);
447 }
448
449 RegCloseKey(mediatype_key);
450
451 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
452 }
453
454 /***********************************************************************
455 * register_mediatypes_extension
456 */
457 static HRESULT register_mediatypes_extension(struct regsvr_mediatype_extension const *list)
458 {
459 LONG res = ERROR_SUCCESS;
460 HKEY mediatype_key;
461 HKEY extensions_root_key = NULL;
462 WCHAR buf[39];
463
464 res = RegCreateKeyExW(HKEY_CLASSES_ROOT, mediatype_name, 0, NULL, 0,
465 KEY_READ | KEY_WRITE, NULL, &mediatype_key, NULL);
466 if (res != ERROR_SUCCESS) return HRESULT_FROM_WIN32(res);
467
468 res = RegCreateKeyExW(mediatype_key, extensions_keyname, 0, NULL, 0,
469 KEY_READ | KEY_WRITE, NULL, &extensions_root_key, NULL);
470 if (res != ERROR_SUCCESS) goto error_return;
471
472 for (; res == ERROR_SUCCESS && list->majortype; ++list) {
473 HKEY extension_key;
474
475 res = RegCreateKeyExA(extensions_root_key, list->extension, 0, NULL, 0,
476 KEY_READ | KEY_WRITE, NULL, &extension_key, NULL);
477 if (res != ERROR_SUCCESS) break;
478
479 StringFromGUID2(list->majortype, buf, 39);
480 res = RegSetValueExW(extension_key, mediatype_name, 0, REG_SZ, (CONST BYTE*)buf,
481 (lstrlenW(buf) + 1) * sizeof(WCHAR));
482 if (res != ERROR_SUCCESS) goto error_close_key;
483
484 StringFromGUID2(list->subtype, buf, 39);
485 res = RegSetValueExW(extension_key, subtype_valuename, 0, REG_SZ, (CONST BYTE*)buf,
486 (lstrlenW(buf) + 1) * sizeof(WCHAR));
487 if (res != ERROR_SUCCESS) goto error_close_key;
488
489 StringFromGUID2(&CLSID_AsyncReader, buf, 39);
490 res = RegSetValueExW(extension_key, sourcefilter_valuename, 0, REG_SZ, (CONST BYTE*)buf,
491 (lstrlenW(buf) + 1) * sizeof(WCHAR));
492 if (res != ERROR_SUCCESS) goto error_close_key;
493
494 error_close_key:
495 RegCloseKey(extension_key);
496 }
497
498 error_return:
499 RegCloseKey(mediatype_key);
500 if (extensions_root_key)
501 RegCloseKey(extensions_root_key);
502
503 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
504 }
505
506 /***********************************************************************
507 * unregister_mediatypes_parsing
508 */
509 static HRESULT unregister_mediatypes_parsing(struct regsvr_mediatype_parsing const *list)
510 {
511 LONG res;
512 HKEY mediatype_key;
513 HKEY majortype_key;
514 WCHAR buf[39];
515
516 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, mediatype_name, 0,
517 KEY_READ | KEY_WRITE, &mediatype_key);
518 if (res == ERROR_FILE_NOT_FOUND) return S_OK;
519 if (res != ERROR_SUCCESS) return HRESULT_FROM_WIN32(res);
520
521 for (; res == ERROR_SUCCESS && list->majortype; ++list) {
522 StringFromGUID2(list->majortype, buf, 39);
523 res = RegOpenKeyExW(mediatype_key, buf, 0,
524 KEY_READ | KEY_WRITE, &majortype_key);
525 if (res == ERROR_FILE_NOT_FOUND) {
526 res = ERROR_SUCCESS;
527 continue;
528 }
529 if (res != ERROR_SUCCESS) break;
530
531 StringFromGUID2(list->subtype, buf, 39);
532 res = RegDeleteTreeW(majortype_key, buf);
533 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
534
535 /* Removed majortype key if there is no more subtype key */
536 res = RegDeleteKeyW(majortype_key, 0);
537 if (res == ERROR_ACCESS_DENIED) res = ERROR_SUCCESS;
538
539 RegCloseKey(majortype_key);
540 }
541
542 RegCloseKey(mediatype_key);
543
544 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
545 }
546
547 /***********************************************************************
548 * unregister_mediatypes_extension
549 */
550 static HRESULT unregister_mediatypes_extension(struct regsvr_mediatype_extension const *list)
551 {
552 LONG res;
553 HKEY mediatype_key;
554 HKEY extensions_root_key = NULL;
555
556 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, mediatype_name, 0,
557 KEY_READ | KEY_WRITE, &mediatype_key);
558 if (res == ERROR_FILE_NOT_FOUND) return S_OK;
559 if (res != ERROR_SUCCESS) return HRESULT_FROM_WIN32(res);
560
561 res = RegOpenKeyExW(mediatype_key, extensions_keyname, 0,
562 KEY_READ | KEY_WRITE, &extensions_root_key);
563 if (res == ERROR_FILE_NOT_FOUND)
564 res = ERROR_SUCCESS;
565 else if (res == ERROR_SUCCESS)
566 for (; res == ERROR_SUCCESS && list->majortype; ++list) {
567 res = RegDeleteTreeA(extensions_root_key, list->extension);
568 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
569 }
570
571 RegCloseKey(mediatype_key);
572 if (extensions_root_key)
573 RegCloseKey(extensions_root_key);
574
575 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
576 }
577
578 /***********************************************************************
579 * register_filters
580 */
581 static HRESULT register_filters(struct regsvr_filter const *list)
582 {
583 HRESULT hr;
584 IFilterMapper2* pFM2 = NULL;
585
586 CoInitialize(NULL);
587 hr = CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC_SERVER, &IID_IFilterMapper2, (LPVOID*)&pFM2);
588
589 if (SUCCEEDED(hr)) {
590 for (; SUCCEEDED(hr) && list->clsid; ++list) {
591 REGFILTER2 rf2;
592 REGFILTERPINS2* prfp2;
593 int i;
594
595 for (i = 0; list->pins[i].flags != 0xFFFFFFFF; i++) ;
596 rf2.dwVersion = 2;
597 rf2.dwMerit = list->merit;
598 rf2.u.s2.cPins2 = i;
599 rf2.u.s2.rgPins2 = prfp2 = CoTaskMemAlloc(i*sizeof(REGFILTERPINS2));
600 if (!prfp2) {
601 hr = E_OUTOFMEMORY;
602 break;
603 }
604 for (i = 0; list->pins[i].flags != 0xFFFFFFFF; i++) {
605 REGPINTYPES* lpMediatype;
606 CLSID* lpClsid;
607 int j, nbmt;
608
609 for (nbmt = 0; list->pins[i].mediatypes[nbmt].majortype; nbmt++) ;
610 /* Allocate a single buffer for regpintypes struct and clsids */
611 lpMediatype = CoTaskMemAlloc(nbmt*(sizeof(REGPINTYPES) + 2*sizeof(CLSID)));
612 if (!lpMediatype) {
613 hr = E_OUTOFMEMORY;
614 break;
615 }
616 lpClsid = (CLSID*) (lpMediatype + nbmt);
617 for (j = 0; j < nbmt; j++) {
618 (lpMediatype + j)->clsMajorType = lpClsid + j*2;
619 memcpy(lpClsid + j*2, list->pins[i].mediatypes[j].majortype, sizeof(CLSID));
620 (lpMediatype + j)->clsMinorType = lpClsid + j*2 + 1;
621 if (list->pins[i].mediatypes[j].subtype)
622 memcpy(lpClsid + j*2 + 1, list->pins[i].mediatypes[j].subtype, sizeof(CLSID));
623 else {
624 /* Subtype are often a combination of major type + fourcc/tag */
625 memcpy(lpClsid + j*2 + 1, list->pins[i].mediatypes[j].majortype, sizeof(CLSID));
626 *(DWORD*)(lpClsid + j*2 + 1) = list->pins[i].mediatypes[j].fourcc;
627 }
628 }
629 prfp2[i].dwFlags = list->pins[i].flags;
630 prfp2[i].cInstances = 0;
631 prfp2[i].nMediaTypes = j;
632 prfp2[i].lpMediaType = lpMediatype;
633 prfp2[i].nMediums = 0;
634 prfp2[i].lpMedium = NULL;
635 prfp2[i].clsPinCategory = NULL;
636 }
637
638 if (FAILED(hr)) {
639 ERR("failed to register with hresult 0x%x\n", hr);
640 CoTaskMemFree(prfp2);
641 break;
642 }
643
644 hr = IFilterMapper2_RegisterFilter(pFM2, list->clsid, list->name, NULL, list->category, NULL, &rf2);
645
646 while (i) {
647 CoTaskMemFree((REGPINTYPES*)prfp2[i-1].lpMediaType);
648 i--;
649 }
650 CoTaskMemFree(prfp2);
651 }
652 }
653
654 if (pFM2)
655 IFilterMapper2_Release(pFM2);
656
657 CoUninitialize();
658
659 return hr;
660 }
661
662 /***********************************************************************
663 * unregister_filters
664 */
665 static HRESULT unregister_filters(struct regsvr_filter const *list)
666 {
667 HRESULT hr;
668 IFilterMapper2* pFM2;
669
670 CoInitialize(NULL);
671
672 hr = CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC_SERVER, &IID_IFilterMapper2, (LPVOID*)&pFM2);
673
674 if (SUCCEEDED(hr)) {
675 for (; SUCCEEDED(hr) && list->clsid; ++list)
676 hr = IFilterMapper2_UnregisterFilter(pFM2, list->category, NULL, list->clsid);
677 IFilterMapper2_Release(pFM2);
678 }
679
680 CoUninitialize();
681
682 return hr;
683 }
684
685 /***********************************************************************
686 * regsvr_key_guid
687 */
688 static LONG register_key_guid(HKEY base, WCHAR const *name, GUID const *guid)
689 {
690 WCHAR buf[39];
691
692 StringFromGUID2(guid, buf, 39);
693 return register_key_defvalueW(base, name, buf);
694 }
695
696 /***********************************************************************
697 * regsvr_key_defvalueW
698 */
699 static LONG register_key_defvalueW(
700 HKEY base,
701 WCHAR const *name,
702 WCHAR const *value)
703 {
704 LONG res;
705 HKEY key;
706
707 res = RegCreateKeyExW(base, name, 0, NULL, 0,
708 KEY_READ | KEY_WRITE, NULL, &key, NULL);
709 if (res != ERROR_SUCCESS) return res;
710 res = RegSetValueExW(key, NULL, 0, REG_SZ, (CONST BYTE*)value,
711 (lstrlenW(value) + 1) * sizeof(WCHAR));
712 RegCloseKey(key);
713 return res;
714 }
715
716 /***********************************************************************
717 * regsvr_key_defvalueA
718 */
719 static LONG register_key_defvalueA(
720 HKEY base,
721 WCHAR const *name,
722 char const *value)
723 {
724 LONG res;
725 HKEY key;
726
727 res = RegCreateKeyExW(base, name, 0, NULL, 0,
728 KEY_READ | KEY_WRITE, NULL, &key, NULL);
729 if (res != ERROR_SUCCESS) return res;
730 res = RegSetValueExA(key, NULL, 0, REG_SZ, (CONST BYTE*)value,
731 lstrlenA(value) + 1);
732 RegCloseKey(key);
733 return res;
734 }
735
736 /***********************************************************************
737 * regsvr_progid
738 */
739 static LONG register_progid(
740 WCHAR const *clsid,
741 char const *progid,
742 char const *curver_progid,
743 char const *name,
744 char const *extra)
745 {
746 LONG res;
747 HKEY progid_key;
748
749 res = RegCreateKeyExA(HKEY_CLASSES_ROOT, progid, 0,
750 NULL, 0, KEY_READ | KEY_WRITE, NULL,
751 &progid_key, NULL);
752 if (res != ERROR_SUCCESS) return res;
753
754 if (name) {
755 res = RegSetValueExA(progid_key, NULL, 0, REG_SZ,
756 (CONST BYTE*)name, strlen(name) + 1);
757 if (res != ERROR_SUCCESS) goto error_close_progid_key;
758 }
759
760 if (clsid) {
761 res = register_key_defvalueW(progid_key, clsid_keyname, clsid);
762 if (res != ERROR_SUCCESS) goto error_close_progid_key;
763 }
764
765 if (curver_progid) {
766 res = register_key_defvalueA(progid_key, curver_keyname,
767 curver_progid);
768 if (res != ERROR_SUCCESS) goto error_close_progid_key;
769 }
770
771 if (extra) {
772 HKEY extra_key;
773
774 res = RegCreateKeyExA(progid_key, extra, 0,
775 NULL, 0, KEY_READ | KEY_WRITE, NULL,
776 &extra_key, NULL);
777 if (res == ERROR_SUCCESS)
778 RegCloseKey(extra_key);
779 }
780
781 error_close_progid_key:
782 RegCloseKey(progid_key);
783 return res;
784 }
785
786 /***********************************************************************
787 * coclass list
788 */
789 static struct regsvr_coclass const coclass_list[] = {
790 { NULL } /* list terminator */
791 };
792
793 /***********************************************************************
794 * interface list
795 */
796
797 static struct regsvr_interface const interface_list[] = {
798 { NULL } /* list terminator */
799 };
800
801 /***********************************************************************
802 * mediatype list
803 */
804
805 static struct regsvr_mediatype_parsing const mediatype_parsing_list[] = {
806 { &MEDIATYPE_Stream,
807 &MEDIASUBTYPE_Avi,
808 { "0,4,,52494646,8,4,,41564920",
809 NULL }
810 },
811 { &MEDIATYPE_Stream,
812 &MEDIASUBTYPE_MPEG1System,
813 { "0, 16, FFFFFFFFF100010001800001FFFFFFFF, 000001BA2100010001800001000001BB",
814 NULL }
815 },
816 { &MEDIATYPE_Stream,
817 &MEDIASUBTYPE_MPEG1VideoCD,
818 { "0, 4, , 52494646, 8, 8, , 43445841666D7420, 36, 20, FFFFFFFF00000000FFFFFFFFFFFFFFFFFFFFFFFF, 646174610000000000FFFFFFFFFFFFFFFFFFFF00",
819 NULL }
820 },
821 { &MEDIATYPE_Stream,
822 &MEDIASUBTYPE_MPEG1Video,
823 { "0, 4, , 000001B3",
824 NULL }
825 },
826 { &MEDIATYPE_Stream,
827 &MEDIASUBTYPE_MPEG1Audio,
828 { "0, 2, FFE0, FFE0",
829 "0, 10, FFFFFF00000080808080, 494433000000000000",
830 NULL }
831 },
832 { &MEDIATYPE_Stream,
833 &MEDIASUBTYPE_QTMovie,
834 { "4, 4, , 6d646174",
835 "4, 4, , 6d6f6f76",
836 NULL }
837 },
838 { &MEDIATYPE_Stream,
839 &MEDIASUBTYPE_WAVE,
840 { "0,4,,52494646,8,4,,57415645",
841 NULL }
842 },
843 { &MEDIATYPE_Stream,
844 &MEDIASUBTYPE_AU,
845 { "0,4,,2e736e64",
846 NULL }
847 },
848 { &MEDIATYPE_Stream,
849 &MEDIASUBTYPE_AIFF,
850 { "0,4,,464f524d,8,4,,41494646",
851 "0,4,,464f524d,8,4,,41494643",
852 NULL }
853 },
854 { &MEDIATYPE_Stream,
855 &MEDIATYPE_Text,
856 { "0,4,,4C595249",
857 "0,4,,6C797269",
858 NULL }
859 },
860 { &MEDIATYPE_Stream,
861 &MEDIATYPE_Midi,
862 { "0,4,,52494646,8,4,,524D4944",
863 "0,4,,4D546864",
864 NULL }
865 },
866 { NULL } /* list terminator */
867 };
868
869 /***********************************************************************
870 * mediatype list
871 */
872
873 static struct regsvr_mediatype_extension const mediatype_extension_list[] = {
874 { &MEDIATYPE_Stream,
875 &MEDIASUBTYPE_MPEG1Audio,
876 ".mp3"
877 },
878 { NULL } /* list terminator */
879 };
880
881 /***********************************************************************
882 * filter list
883 */
884
885 static struct regsvr_filter const filter_list[] = {
886 { &CLSID_AviSplitter,
887 &CLSID_LegacyAmFilterCategory,
888 {'A','V','I',' ','S','p','l','i','t','t','e','r',0},
889 0x5ffff0,
890 { { 0,
891 { { &MEDIATYPE_Stream, &MEDIASUBTYPE_Avi },
892 { NULL }
893 },
894 },
895 { REG_PINFLAG_B_OUTPUT,
896 { { &MEDIATYPE_Video, &GUID_NULL },
897 { NULL }
898 },
899 },
900 { 0xFFFFFFFF },
901 }
902 },
903 { &CLSID_MPEG1Splitter,
904 &CLSID_LegacyAmFilterCategory,
905 {'M','P','E','G','-','I',' ','S','t','r','e','a','m',' ','S','p','l','i','t','t','e','r',0},
906 0x5ffff0,
907 { { 0,
908 { { &MEDIATYPE_Stream, &MEDIASUBTYPE_MPEG1Audio },
909 { &MEDIATYPE_Stream, &MEDIASUBTYPE_MPEG1Video },
910 { &MEDIATYPE_Stream, &MEDIASUBTYPE_MPEG1System },
911 { &MEDIATYPE_Stream, &MEDIASUBTYPE_MPEG1VideoCD },
912 { NULL }
913 },
914 },
915 { REG_PINFLAG_B_OUTPUT,
916 { { &MEDIATYPE_Audio, &MEDIASUBTYPE_MPEG1Packet },
917 { &MEDIATYPE_Audio, &MEDIASUBTYPE_MPEG1AudioPayload },
918 { NULL }
919 },
920 },
921 { REG_PINFLAG_B_OUTPUT,
922 { { &MEDIATYPE_Video, &MEDIASUBTYPE_MPEG1Packet },
923 { &MEDIATYPE_Video, &MEDIASUBTYPE_MPEG1Payload },
924 { NULL }
925 },
926 },
927 { 0xFFFFFFFF },
928 }
929 },
930 { &CLSID_NullRenderer,
931 &CLSID_LegacyAmFilterCategory,
932 {'N','u','l','l',' ','R','e','n','d','e','r','e','r',0},
933 0x200000,
934 { { REG_PINFLAG_B_RENDERER,
935 { { &MEDIATYPE_NULL, &GUID_NULL },
936 { NULL }
937 },
938 },
939 { 0xFFFFFFFF },
940 }
941 },
942 { &CLSID_VideoRenderer,
943 &CLSID_LegacyAmFilterCategory,
944 {'V','i','d','e','o',' ','R','e','n','d','e','r','e','r',0},
945 0x800000,
946 { { REG_PINFLAG_B_RENDERER,
947 { { &MEDIATYPE_Video, &GUID_NULL },
948 { NULL }
949 },
950 },
951 { 0xFFFFFFFF },
952 }
953 },
954 { &CLSID_VideoRendererDefault,
955 &CLSID_LegacyAmFilterCategory,
956 {'V','i','d','e','o',' ','R','e','n','d','e','r','e','r',0},
957 0x800000,
958 { { REG_PINFLAG_B_RENDERER,
959 { { &MEDIATYPE_Video, &GUID_NULL },
960 { NULL }
961 },
962 },
963 { 0xFFFFFFFF },
964 }
965 },
966 { &CLSID_VideoMixingRenderer9,
967 &CLSID_LegacyAmFilterCategory,
968 {'V','i','d','e','o',' ','M','i','x','i','n','g',' ','R','e','n','d','e','r','e','r',' ','9',0},
969 0x200000,
970 { { REG_PINFLAG_B_RENDERER,
971 { { &MEDIATYPE_Video, &GUID_NULL },
972 { NULL }
973 },
974 },
975 { 0xFFFFFFFF },
976 }
977 },
978 { &CLSID_DSoundRender,
979 &CLSID_LegacyAmFilterCategory,
980 {'A','u','d','i','o',' ','R','e','n','d','e','r','e','r',0},
981 0x800000,
982 { { REG_PINFLAG_B_RENDERER,
983 { { &MEDIATYPE_Audio, &MEDIASUBTYPE_PCM },
984 /* { &MEDIATYPE_Audio, &MEDIASUBTYPE_IEEE_FLOAT }, */
985 { NULL }
986 },
987 },
988 { 0xFFFFFFFF },
989 }
990 },
991 { &CLSID_AudioRender,
992 &CLSID_LegacyAmFilterCategory,
993 {'A','u','d','i','o',' ','R','e','n','d','e','r','e','r',0},
994 0x800000,
995 { { REG_PINFLAG_B_RENDERER,
996 { { &MEDIATYPE_Audio, &MEDIASUBTYPE_PCM },
997 /* { &MEDIATYPE_Audio, &MEDIASUBTYPE_IEEE_FLOAT }, */
998 { NULL }
999 },
1000 },
1001 { 0xFFFFFFFF },
1002 }
1003 },
1004 { &CLSID_AVIDec,
1005 &CLSID_LegacyAmFilterCategory,
1006 {'A','V','I',' ','D','e','c','o','m','p','r','e','s','s','o','r',0},
1007 0x5ffff0,
1008 { { 0,
1009 { { &MEDIATYPE_Video, &GUID_NULL },
1010 { NULL }
1011 },
1012 },
1013 { REG_PINFLAG_B_OUTPUT,
1014 { { &MEDIATYPE_Video, &GUID_NULL },
1015 { NULL }
1016 },
1017 },
1018 { 0xFFFFFFFF },
1019 }
1020 },
1021 { &CLSID_AsyncReader,
1022 &CLSID_LegacyAmFilterCategory,
1023 {'F','i','l','e',' ','S','o','u','r','c','e',' ','(','A','s','y','n','c','.',')',0},
1024 0x400000,
1025 { { REG_PINFLAG_B_OUTPUT,
1026 { { &MEDIATYPE_Stream, &GUID_NULL },
1027 { NULL }
1028 },
1029 },
1030 { 0xFFFFFFFF },
1031 }
1032 },
1033 { &CLSID_ACMWrapper,
1034 &CLSID_LegacyAmFilterCategory,
1035 {'A','C','M',' ','W','r','a','p','p','e','r',0},
1036 0x5ffff0,
1037 { { 0,
1038 { { &MEDIATYPE_Audio, &GUID_NULL },
1039 { NULL }
1040 },
1041 },
1042 { REG_PINFLAG_B_OUTPUT,
1043 { { &MEDIATYPE_Audio, &GUID_NULL },
1044 { NULL }
1045 },
1046 },
1047 { 0xFFFFFFFF },
1048 }
1049 },
1050 { &CLSID_WAVEParser,
1051 &CLSID_LegacyAmFilterCategory,
1052 {'W','a','v','e',' ','P','a','r','s','e','r',0},
1053 0x400000,
1054 { { 0,
1055 { { &MEDIATYPE_Stream, &MEDIASUBTYPE_WAVE },
1056 { &MEDIATYPE_Stream, &MEDIASUBTYPE_AU },
1057 { &MEDIATYPE_Stream, &MEDIASUBTYPE_AIFF },
1058 { NULL }
1059 },
1060 },
1061 { REG_PINFLAG_B_OUTPUT,
1062 { { &MEDIATYPE_Audio, &GUID_NULL },
1063 { NULL }
1064 },
1065 },
1066 { 0xFFFFFFFF },
1067 }
1068 },
1069 { NULL } /* list terminator */
1070 };
1071
1072 extern HRESULT WINAPI QUARTZ_DllRegisterServer(void) DECLSPEC_HIDDEN;
1073 extern HRESULT WINAPI QUARTZ_DllUnregisterServer(void) DECLSPEC_HIDDEN;
1074
1075 /***********************************************************************
1076 * DllRegisterServer (QUARTZ.@)
1077 */
1078 HRESULT WINAPI DllRegisterServer(void)
1079 {
1080 HRESULT hr;
1081
1082 TRACE("\n");
1083
1084 hr = QUARTZ_DllRegisterServer();
1085 if (SUCCEEDED(hr))
1086 hr = register_coclasses(coclass_list);
1087 if (SUCCEEDED(hr))
1088 hr = register_interfaces(interface_list);
1089 if (SUCCEEDED(hr))
1090 hr = register_mediatypes_parsing(mediatype_parsing_list);
1091 if (SUCCEEDED(hr))
1092 hr = register_mediatypes_extension(mediatype_extension_list);
1093 if (SUCCEEDED(hr))
1094 hr = register_filters(filter_list);
1095 return hr;
1096 }
1097
1098 /***********************************************************************
1099 * DllUnregisterServer (QUARTZ.@)
1100 */
1101 HRESULT WINAPI DllUnregisterServer(void)
1102 {
1103 HRESULT hr;
1104
1105 TRACE("\n");
1106
1107 hr = unregister_filters(filter_list);
1108 if (SUCCEEDED(hr))
1109 hr = unregister_coclasses(coclass_list);
1110 if (SUCCEEDED(hr))
1111 hr = unregister_interfaces(interface_list);
1112 if (SUCCEEDED(hr))
1113 hr = unregister_mediatypes_parsing(mediatype_parsing_list);
1114 if (SUCCEEDED(hr))
1115 hr = unregister_mediatypes_extension(mediatype_extension_list);
1116 if (SUCCEEDED(hr))
1117 hr = QUARTZ_DllUnregisterServer();
1118 return hr;
1119 }