- Sync with trunk r58248 to bring the latest changes from Amine (headers) and others...
[reactos.git] / dll / directx / 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 WCHAR const interface_keyname[10] = {
133 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c', 'e', 0 };
134 static WCHAR const base_ifa_keyname[14] = {
135 'B', 'a', 's', 'e', 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c',
136 'e', 0 };
137 static WCHAR const num_methods_keyname[11] = {
138 'N', 'u', 'm', 'M', 'e', 't', 'h', 'o', 'd', 's', 0 };
139 static WCHAR const ps_clsid_keyname[15] = {
140 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
141 'i', 'd', 0 };
142 static WCHAR const ps_clsid32_keyname[17] = {
143 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
144 'i', 'd', '3', '2', 0 };
145 static WCHAR const clsid_keyname[6] = {
146 'C', 'L', 'S', 'I', 'D', 0 };
147 static WCHAR const curver_keyname[7] = {
148 'C', 'u', 'r', 'V', 'e', 'r', 0 };
149 static WCHAR const ips_keyname[13] = {
150 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
151 0 };
152 static WCHAR const ips32_keyname[15] = {
153 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
154 '3', '2', 0 };
155 static WCHAR const progid_keyname[7] = {
156 'P', 'r', 'o', 'g', 'I', 'D', 0 };
157 static WCHAR const viprogid_keyname[25] = {
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 char const tmodel_valuename[] = "ThreadingModel";
162 static WCHAR const mediatype_name[11] = {
163 'M', 'e', 'd', 'i', 'a', ' ', 'T', 'y', 'p', 'e', 0 };
164 static WCHAR const subtype_valuename[8] = {
165 'S', 'u', 'b', 't', 'y', 'p', 'e', 0 };
166 static WCHAR const sourcefilter_valuename[14] = {
167 'S', 'o', 'u', 'r', 'c', 'e', ' ', 'F', 'i', 'l', 't', 'e', 'r', 0 };
168 static WCHAR const extensions_keyname[11] = {
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 WCHAR const fmt[3] = { '%', '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.s1.cPins2 = i;
599 rf2.u.s1.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 static GUID const CLSID_PSFactoryBuffer = {
787 0x92a3a302, 0xda7c, 0x4a1f, {0xba,0x7e,0x18,0x02,0xbb,0x5d,0x2d,0x02} };
788
789 /***********************************************************************
790 * coclass list
791 */
792 static struct regsvr_coclass const coclass_list[] = {
793 { &CLSID_FilterGraph,
794 "Filter Graph",
795 NULL,
796 "quartz.dll",
797 "Both"
798 },
799 { &CLSID_FilterGraphNoThread,
800 "Filter Graph",
801 NULL,
802 "quartz.dll",
803 "Both"
804 },
805 { &CLSID_FilterMapper,
806 "Filter Mapper",
807 NULL,
808 "quartz.dll",
809 "Both"
810 },
811 { &CLSID_FilterMapper2,
812 "Filter Mapper2",
813 NULL,
814 "quartz.dll",
815 "Both"
816 },
817 { &CLSID_SystemClock,
818 "System Clock",
819 NULL,
820 "quartz.dll",
821 "Both"
822 },
823 { &CLSID_MemoryAllocator,
824 "Memory Allocator",
825 NULL,
826 "quartz.dll",
827 "Both"
828 },
829 { &CLSID_SeekingPassThru,
830 "Seeking",
831 NULL,
832 "quartz.dll",
833 "Both"
834 },
835 { &CLSID_AsyncReader,
836 "File Source Filter",
837 NULL,
838 "quartz.dll",
839 "Both"
840 },
841 { &CLSID_AviSplitter,
842 "AVI Splitter",
843 NULL,
844 "quartz.dll",
845 "Both"
846 },
847 { &CLSID_MPEG1Splitter,
848 "MPEG-I Stream Splitter",
849 NULL,
850 "quartz.dll",
851 "Both"
852 },
853 { &CLSID_AVIDec,
854 "AVI Decompressor",
855 NULL,
856 "quartz.dll",
857 "Both"
858 },
859 { &CLSID_DSoundRender,
860 "DirectSound Audio Renderer",
861 NULL,
862 "quartz.dll",
863 "Both"
864 },
865 { &CLSID_AudioRender,
866 "Wave Audio Renderer",
867 NULL,
868 "quartz.dll",
869 "Both"
870 },
871 { &CLSID_NullRenderer,
872 "Null Renderer",
873 NULL,
874 "quartz.dll",
875 "Both"
876 },
877 { &CLSID_VideoRenderer,
878 "Video Renderer",
879 NULL,
880 "quartz.dll",
881 "Both"
882 },
883 { &CLSID_VideoRendererDefault,
884 "Default Video Renderer",
885 NULL,
886 "quartz.dll",
887 "Both"
888 },
889 { &CLSID_ACMWrapper,
890 "ACM wrapper",
891 NULL,
892 "quartz.dll",
893 "Both"
894 },
895 { &CLSID_WAVEParser,
896 "Wave Parser",
897 NULL,
898 "quartz.dll",
899 "Both"
900 },
901 { NULL } /* list terminator */
902 };
903
904 /***********************************************************************
905 * interface list
906 */
907
908 static struct regsvr_interface const interface_list[] = {
909 { NULL } /* list terminator */
910 };
911
912 /***********************************************************************
913 * mediatype list
914 */
915
916 static struct regsvr_mediatype_parsing const mediatype_parsing_list[] = {
917 { &MEDIATYPE_Stream,
918 &MEDIASUBTYPE_Avi,
919 { "0,4,,52494646,8,4,,41564920",
920 NULL }
921 },
922 { &MEDIATYPE_Stream,
923 &MEDIASUBTYPE_MPEG1System,
924 { "0, 16, FFFFFFFFF100010001800001FFFFFFFF, 000001BA2100010001800001000001BB",
925 NULL }
926 },
927 { &MEDIATYPE_Stream,
928 &MEDIASUBTYPE_MPEG1VideoCD,
929 { "0, 4, , 52494646, 8, 8, , 43445841666D7420, 36, 20, FFFFFFFF00000000FFFFFFFFFFFFFFFFFFFFFFFF, 646174610000000000FFFFFFFFFFFFFFFFFFFF00",
930 NULL }
931 },
932 { &MEDIATYPE_Stream,
933 &MEDIASUBTYPE_MPEG1Video,
934 { "0, 4, , 000001B3",
935 NULL }
936 },
937 { &MEDIATYPE_Stream,
938 &MEDIASUBTYPE_MPEG1Audio,
939 { "0, 2, FFE0, FFE0",
940 "0, 10, FFFFFF00000080808080, 494433000000000000",
941 NULL }
942 },
943 { &MEDIATYPE_Stream,
944 &MEDIASUBTYPE_QTMovie,
945 { "4, 4, , 6d646174",
946 "4, 4, , 6d6f6f76",
947 NULL }
948 },
949 { &MEDIATYPE_Stream,
950 &MEDIASUBTYPE_WAVE,
951 { "0,4,,52494646,8,4,,57415645",
952 NULL }
953 },
954 { &MEDIATYPE_Stream,
955 &MEDIASUBTYPE_AU,
956 { "0,4,,2e736e64",
957 NULL }
958 },
959 { &MEDIATYPE_Stream,
960 &MEDIASUBTYPE_AIFF,
961 { "0,4,,464f524d,8,4,,41494646",
962 "0,4,,464f524d,8,4,,41494643",
963 NULL }
964 },
965 { &MEDIATYPE_Stream,
966 &MEDIATYPE_Text,
967 { "0,4,,4C595249",
968 "0,4,,6C797269",
969 NULL }
970 },
971 { &MEDIATYPE_Stream,
972 &MEDIATYPE_Midi,
973 { "0,4,,52494646,8,4,,524D4944",
974 "0,4,,4D546864",
975 NULL }
976 },
977 { NULL } /* list terminator */
978 };
979
980 /***********************************************************************
981 * mediatype list
982 */
983
984 static struct regsvr_mediatype_extension const mediatype_extension_list[] = {
985 { &MEDIATYPE_Stream,
986 &MEDIASUBTYPE_MPEG1Audio,
987 ".mp3"
988 },
989 { NULL } /* list terminator */
990 };
991
992 /***********************************************************************
993 * filter list
994 */
995
996 static struct regsvr_filter const filter_list[] = {
997 { &CLSID_AviSplitter,
998 &CLSID_LegacyAmFilterCategory,
999 {'A','V','I',' ','S','p','l','i','t','t','e','r',0},
1000 0x600000,
1001 { { 0,
1002 { { &MEDIATYPE_Stream, &MEDIASUBTYPE_Avi },
1003 { NULL }
1004 },
1005 },
1006 { REG_PINFLAG_B_OUTPUT,
1007 { { &MEDIATYPE_Video, &GUID_NULL },
1008 { NULL }
1009 },
1010 },
1011 { 0xFFFFFFFF },
1012 }
1013 },
1014 { &CLSID_MPEG1Splitter,
1015 &CLSID_LegacyAmFilterCategory,
1016 {'M','P','E','G','-','I',' ','S','t','r','e','a','m',' ','S','p','l','i','t','t','e','r',0},
1017 0x600000,
1018 { { 0,
1019 { { &MEDIATYPE_Stream, &MEDIASUBTYPE_MPEG1Audio },
1020 { &MEDIATYPE_Stream, &MEDIASUBTYPE_MPEG1Video },
1021 { &MEDIATYPE_Stream, &MEDIASUBTYPE_MPEG1System },
1022 { &MEDIATYPE_Stream, &MEDIASUBTYPE_MPEG1VideoCD },
1023 { NULL }
1024 },
1025 },
1026 { REG_PINFLAG_B_OUTPUT,
1027 { { &MEDIATYPE_Audio, &MEDIASUBTYPE_MPEG1Packet },
1028 { &MEDIATYPE_Audio, &MEDIASUBTYPE_MPEG1AudioPayload },
1029 { NULL }
1030 },
1031 },
1032 { REG_PINFLAG_B_OUTPUT,
1033 { { &MEDIATYPE_Video, &MEDIASUBTYPE_MPEG1Packet },
1034 { &MEDIATYPE_Video, &MEDIASUBTYPE_MPEG1Payload },
1035 { NULL }
1036 },
1037 },
1038 { 0xFFFFFFFF },
1039 }
1040 },
1041 { &CLSID_NullRenderer,
1042 &CLSID_LegacyAmFilterCategory,
1043 {'N','u','l','l',' ','R','e','n','d','e','r','e','r',0},
1044 0x200000,
1045 { { REG_PINFLAG_B_RENDERER,
1046 { { &MEDIATYPE_NULL, &GUID_NULL },
1047 { NULL }
1048 },
1049 },
1050 { 0xFFFFFFFF },
1051 }
1052 },
1053 { &CLSID_VideoRenderer,
1054 &CLSID_LegacyAmFilterCategory,
1055 {'V','i','d','e','o',' ','R','e','n','d','e','r','e','r',0},
1056 0x800000,
1057 { { REG_PINFLAG_B_RENDERER,
1058 { { &MEDIATYPE_Video, &GUID_NULL },
1059 { NULL }
1060 },
1061 },
1062 { 0xFFFFFFFF },
1063 }
1064 },
1065 { &CLSID_VideoRendererDefault,
1066 &CLSID_LegacyAmFilterCategory,
1067 {'V','i','d','e','o',' ','R','e','n','d','e','r','e','r',0},
1068 0x800000,
1069 { { REG_PINFLAG_B_RENDERER,
1070 { { &MEDIATYPE_Video, &GUID_NULL },
1071 { NULL }
1072 },
1073 },
1074 { 0xFFFFFFFF },
1075 }
1076 },
1077 { &CLSID_DSoundRender,
1078 &CLSID_LegacyAmFilterCategory,
1079 {'A','u','d','i','o',' ','R','e','n','d','e','r','e','r',0},
1080 0x800000,
1081 { { REG_PINFLAG_B_RENDERER,
1082 { { &MEDIATYPE_Audio, &MEDIASUBTYPE_PCM },
1083 /* { &MEDIATYPE_Audio, &MEDIASUBTYPE_IEEE_FLOAT }, */
1084 { NULL }
1085 },
1086 },
1087 { 0xFFFFFFFF },
1088 }
1089 },
1090 { &CLSID_AudioRender,
1091 &CLSID_LegacyAmFilterCategory,
1092 {'A','u','d','i','o',' ','R','e','n','d','e','r','e','r',0},
1093 0x800000,
1094 { { REG_PINFLAG_B_RENDERER,
1095 { { &MEDIATYPE_Audio, &MEDIASUBTYPE_PCM },
1096 /* { &MEDIATYPE_Audio, &MEDIASUBTYPE_IEEE_FLOAT }, */
1097 { NULL }
1098 },
1099 },
1100 { 0xFFFFFFFF },
1101 }
1102 },
1103 { &CLSID_AVIDec,
1104 &CLSID_LegacyAmFilterCategory,
1105 {'A','V','I',' ','D','e','c','o','m','p','r','e','s','s','o','r',0},
1106 0x600000,
1107 { { 0,
1108 { { &MEDIATYPE_Video, &GUID_NULL },
1109 { NULL }
1110 },
1111 },
1112 { REG_PINFLAG_B_OUTPUT,
1113 { { &MEDIATYPE_Video, &GUID_NULL },
1114 { NULL }
1115 },
1116 },
1117 { 0xFFFFFFFF },
1118 }
1119 },
1120 { &CLSID_AsyncReader,
1121 &CLSID_LegacyAmFilterCategory,
1122 {'F','i','l','e',' ','S','o','u','r','c','e',' ','(','A','s','y','n','c','.',')',0},
1123 0x400000,
1124 { { REG_PINFLAG_B_OUTPUT,
1125 { { &MEDIATYPE_Stream, &GUID_NULL },
1126 { NULL }
1127 },
1128 },
1129 { 0xFFFFFFFF },
1130 }
1131 },
1132 { &CLSID_ACMWrapper,
1133 &CLSID_LegacyAmFilterCategory,
1134 {'A','C','M',' ','W','r','a','p','p','e','r',0},
1135 0x600000,
1136 { { 0,
1137 { { &MEDIATYPE_Audio, &GUID_NULL },
1138 { NULL }
1139 },
1140 },
1141 { REG_PINFLAG_B_OUTPUT,
1142 { { &MEDIATYPE_Audio, &GUID_NULL },
1143 { NULL }
1144 },
1145 },
1146 { 0xFFFFFFFF },
1147 }
1148 },
1149 { &CLSID_WAVEParser,
1150 &CLSID_LegacyAmFilterCategory,
1151 {'W','a','v','e',' ','P','a','r','s','e','r',0},
1152 0x400000,
1153 { { 0,
1154 { { &MEDIATYPE_Stream, &MEDIASUBTYPE_WAVE },
1155 { &MEDIATYPE_Stream, &MEDIASUBTYPE_AU },
1156 { &MEDIATYPE_Stream, &MEDIASUBTYPE_AIFF },
1157 { NULL }
1158 },
1159 },
1160 { REG_PINFLAG_B_OUTPUT,
1161 { { &MEDIATYPE_Audio, &GUID_NULL },
1162 { NULL }
1163 },
1164 },
1165 { 0xFFFFFFFF },
1166 }
1167 },
1168 { NULL } /* list terminator */
1169 };
1170
1171 extern HRESULT WINAPI QUARTZ_DllRegisterServer(void) DECLSPEC_HIDDEN;
1172 extern HRESULT WINAPI QUARTZ_DllUnregisterServer(void) DECLSPEC_HIDDEN;
1173
1174 /***********************************************************************
1175 * DllRegisterServer (QUARTZ.@)
1176 */
1177 HRESULT WINAPI DllRegisterServer(void)
1178 {
1179 HRESULT hr;
1180
1181 TRACE("\n");
1182
1183 hr = QUARTZ_DllRegisterServer();
1184 if (SUCCEEDED(hr))
1185 hr = register_coclasses(coclass_list);
1186 if (SUCCEEDED(hr))
1187 hr = register_interfaces(interface_list);
1188 if (SUCCEEDED(hr))
1189 hr = register_mediatypes_parsing(mediatype_parsing_list);
1190 if (SUCCEEDED(hr))
1191 hr = register_mediatypes_extension(mediatype_extension_list);
1192 if (SUCCEEDED(hr))
1193 hr = register_filters(filter_list);
1194 return hr;
1195 }
1196
1197 /***********************************************************************
1198 * DllUnregisterServer (QUARTZ.@)
1199 */
1200 HRESULT WINAPI DllUnregisterServer(void)
1201 {
1202 HRESULT hr;
1203
1204 TRACE("\n");
1205
1206 hr = unregister_filters(filter_list);
1207 if (SUCCEEDED(hr))
1208 hr = unregister_coclasses(coclass_list);
1209 if (SUCCEEDED(hr))
1210 hr = unregister_interfaces(interface_list);
1211 if (SUCCEEDED(hr))
1212 hr = unregister_mediatypes_parsing(mediatype_parsing_list);
1213 if (SUCCEEDED(hr))
1214 hr = unregister_mediatypes_extension(mediatype_extension_list);
1215 if (SUCCEEDED(hr))
1216 hr = QUARTZ_DllUnregisterServer();
1217 return hr;
1218 }