quartz/tests: Add more tests for IMediaSeeking.
[wine.git] / dlls / quartz / regsvr.c
blob196e0649d87b056bbb281f3d6ca11e57b512244e
1 /*
2 * self-registerable dll functions for quartz.dll
4 * Copyright (C) 2003 John K. Hohm
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.
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.
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
21 #define NONAMELESSUNION
22 #define NONAMELESSSTRUCT
23 #define COBJMACROS
24 #include <stdarg.h>
25 #include <string.h>
27 #include "windef.h"
28 #include "winbase.h"
29 #include "wingdi.h"
30 #include "winuser.h"
31 #include "winreg.h"
32 #include "winerror.h"
34 #include "ole2.h"
35 #include "uuids.h"
36 #include "strmif.h"
38 #include "wine/debug.h"
39 #include "wine/unicode.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(quartz);
44 * Near the bottom of this file are the exported DllRegisterServer and
45 * DllUnregisterServer, which make all this worthwhile.
48 /***********************************************************************
49 * interface for self-registering
51 struct regsvr_interface
53 IID const *iid; /* NULL for end of list */
54 LPCSTR name; /* can be NULL to omit */
55 IID const *base_iid; /* can be NULL to omit */
56 int num_methods; /* can be <0 to omit */
57 CLSID const *ps_clsid; /* can be NULL to omit */
58 CLSID const *ps_clsid32; /* can be NULL to omit */
61 static HRESULT register_interfaces(struct regsvr_interface const *list);
62 static HRESULT unregister_interfaces(struct regsvr_interface const *list);
64 struct regsvr_coclass
66 CLSID const *clsid; /* NULL for end of list */
67 LPCSTR name; /* can be NULL to omit */
68 LPCSTR ips; /* can be NULL to omit */
69 LPCSTR ips32; /* can be NULL to omit */
70 LPCSTR ips32_tmodel; /* can be NULL to omit */
71 LPCSTR progid; /* can be NULL to omit */
72 LPCSTR viprogid; /* can be NULL to omit */
73 LPCSTR progid_extra; /* can be NULL to omit */
76 static HRESULT register_coclasses(struct regsvr_coclass const *list);
77 static HRESULT unregister_coclasses(struct regsvr_coclass const *list);
79 struct regsvr_mediatype_parsing
81 CLSID const *majortype; /* NULL for end of list */
82 CLSID const *subtype;
83 LPCSTR line[11]; /* NULL for end of list */
86 static HRESULT register_mediatypes_parsing(struct regsvr_mediatype_parsing const *list);
87 static HRESULT unregister_mediatypes_parsing(struct regsvr_mediatype_parsing const *list);
89 struct regsvr_mediatype_extension
91 CLSID const *majortype; /* NULL for end of list */
92 CLSID const *subtype;
93 LPCSTR extension;
96 struct mediatype
98 CLSID const *majortype; /* NULL for end of list */
99 CLSID const *subtype;
100 DWORD fourcc;
103 struct pin
105 DWORD flags; /* 0xFFFFFFFF for end of list */
106 struct mediatype mediatypes[11];
109 struct regsvr_filter
111 CLSID const *clsid; /* NULL for end of list */
112 CLSID const *category;
113 WCHAR name[50];
114 DWORD merit;
115 struct pin pins[11];
118 static HRESULT register_mediatypes_extension(struct regsvr_mediatype_extension const *list);
119 static HRESULT unregister_mediatypes_extension(struct regsvr_mediatype_extension const *list);
121 static HRESULT register_filters(struct regsvr_filter const *list);
122 static HRESULT unregister_filters(struct regsvr_filter const *list);
124 /***********************************************************************
125 * static string constants
127 static const WCHAR interface_keyname[] = {
128 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c', 'e', 0 };
129 static const WCHAR base_ifa_keyname[] = {
130 'B', 'a', 's', 'e', 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c',
131 'e', 0 };
132 static const WCHAR num_methods_keyname[] = {
133 'N', 'u', 'm', 'M', 'e', 't', 'h', 'o', 'd', 's', 0 };
134 static const WCHAR ps_clsid_keyname[] = {
135 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
136 'i', 'd', 0 };
137 static const WCHAR ps_clsid32_keyname[] = {
138 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
139 'i', 'd', '3', '2', 0 };
140 static const WCHAR clsid_keyname[] = {
141 'C', 'L', 'S', 'I', 'D', 0 };
142 static const WCHAR curver_keyname[] = {
143 'C', 'u', 'r', 'V', 'e', 'r', 0 };
144 static const WCHAR ips_keyname[] = {
145 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
146 0 };
147 static const WCHAR ips32_keyname[] = {
148 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
149 '3', '2', 0 };
150 static const WCHAR progid_keyname[] = {
151 'P', 'r', 'o', 'g', 'I', 'D', 0 };
152 static const WCHAR viprogid_keyname[] = {
153 'V', 'e', 'r', 's', 'i', 'o', 'n', 'I', 'n', 'd', 'e', 'p',
154 'e', 'n', 'd', 'e', 'n', 't', 'P', 'r', 'o', 'g', 'I', 'D',
155 0 };
156 static const char tmodel_valuename[] = "ThreadingModel";
157 static const WCHAR mediatype_name[] = {
158 'M', 'e', 'd', 'i', 'a', ' ', 'T', 'y', 'p', 'e', 0 };
159 static const WCHAR subtype_valuename[] = {
160 'S', 'u', 'b', 't', 'y', 'p', 'e', 0 };
161 static const WCHAR sourcefilter_valuename[] = {
162 'S', 'o', 'u', 'r', 'c', 'e', ' ', 'F', 'i', 'l', 't', 'e', 'r', 0 };
163 static const WCHAR extensions_keyname[] = {
164 'E', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 's', 0 };
166 /***********************************************************************
167 * static helper functions
169 static LONG register_key_guid(HKEY base, WCHAR const *name, GUID const *guid);
170 static LONG register_key_defvalueW(HKEY base, WCHAR const *name,
171 WCHAR const *value);
172 static LONG register_key_defvalueA(HKEY base, WCHAR const *name,
173 char const *value);
174 static LONG register_progid(WCHAR const *clsid,
175 char const *progid, char const *curver_progid,
176 char const *name, char const *extra);
178 /***********************************************************************
179 * register_interfaces
181 static HRESULT register_interfaces(struct regsvr_interface const *list)
183 LONG res = ERROR_SUCCESS;
184 HKEY interface_key;
186 res = RegCreateKeyExW(HKEY_CLASSES_ROOT, interface_keyname, 0, NULL, 0,
187 KEY_READ | KEY_WRITE, NULL, &interface_key, NULL);
188 if (res != ERROR_SUCCESS) goto error_return;
190 for (; res == ERROR_SUCCESS && list->iid; ++list) {
191 WCHAR buf[39];
192 HKEY iid_key;
194 StringFromGUID2(list->iid, buf, 39);
195 res = RegCreateKeyExW(interface_key, buf, 0, NULL, 0,
196 KEY_READ | KEY_WRITE, NULL, &iid_key, NULL);
197 if (res != ERROR_SUCCESS) goto error_close_interface_key;
199 if (list->name) {
200 res = RegSetValueExA(iid_key, NULL, 0, REG_SZ, (const BYTE*)list->name,
201 strlen(list->name) + 1);
202 if (res != ERROR_SUCCESS) goto error_close_iid_key;
205 if (list->base_iid) {
206 res = register_key_guid(iid_key, base_ifa_keyname, list->base_iid);
207 if (res != ERROR_SUCCESS) goto error_close_iid_key;
210 if (0 <= list->num_methods) {
211 static const WCHAR fmt[] = { '%', 'd', 0 };
212 HKEY key;
214 res = RegCreateKeyExW(iid_key, num_methods_keyname, 0, NULL, 0,
215 KEY_READ | KEY_WRITE, NULL, &key, NULL);
216 if (res != ERROR_SUCCESS) goto error_close_iid_key;
218 sprintfW(buf, fmt, list->num_methods);
219 res = RegSetValueExW(key, NULL, 0, REG_SZ, (const BYTE*)buf,
220 (lstrlenW(buf) + 1) * sizeof(WCHAR));
221 RegCloseKey(key);
223 if (res != ERROR_SUCCESS) goto error_close_iid_key;
226 if (list->ps_clsid) {
227 res = register_key_guid(iid_key, ps_clsid_keyname, list->ps_clsid);
228 if (res != ERROR_SUCCESS) goto error_close_iid_key;
231 if (list->ps_clsid32) {
232 res = register_key_guid(iid_key, ps_clsid32_keyname, list->ps_clsid32);
233 if (res != ERROR_SUCCESS) goto error_close_iid_key;
236 error_close_iid_key:
237 RegCloseKey(iid_key);
240 error_close_interface_key:
241 RegCloseKey(interface_key);
242 error_return:
243 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
246 /***********************************************************************
247 * unregister_interfaces
249 static HRESULT unregister_interfaces(struct regsvr_interface const *list)
251 LONG res = ERROR_SUCCESS;
252 HKEY interface_key;
254 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, interface_keyname, 0,
255 KEY_READ | KEY_WRITE, &interface_key);
256 if (res == ERROR_FILE_NOT_FOUND) return S_OK;
257 if (res != ERROR_SUCCESS) goto error_return;
259 for (; res == ERROR_SUCCESS && list->iid; ++list) {
260 WCHAR buf[39];
262 StringFromGUID2(list->iid, buf, 39);
263 res = RegDeleteTreeW(interface_key, buf);
264 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
267 RegCloseKey(interface_key);
268 error_return:
269 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
272 /***********************************************************************
273 * register_coclasses
275 static HRESULT register_coclasses(struct regsvr_coclass const *list)
277 LONG res = ERROR_SUCCESS;
278 HKEY coclass_key;
280 res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0,
281 KEY_READ | KEY_WRITE, NULL, &coclass_key, NULL);
282 if (res != ERROR_SUCCESS) goto error_return;
284 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
285 WCHAR buf[39];
286 HKEY clsid_key;
288 StringFromGUID2(list->clsid, buf, 39);
289 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
290 KEY_READ | KEY_WRITE, NULL, &clsid_key, NULL);
291 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
293 if (list->name) {
294 res = RegSetValueExA(clsid_key, NULL, 0, REG_SZ, (const BYTE*)list->name,
295 strlen(list->name) + 1);
296 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
299 if (list->ips) {
300 res = register_key_defvalueA(clsid_key, ips_keyname, list->ips);
301 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
304 if (list->ips32) {
305 HKEY ips32_key;
307 res = RegCreateKeyExW(clsid_key, ips32_keyname, 0, NULL, 0,
308 KEY_READ | KEY_WRITE, NULL,
309 &ips32_key, NULL);
310 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
312 res = RegSetValueExA(ips32_key, NULL, 0, REG_SZ, (const BYTE*)list->ips32,
313 lstrlenA(list->ips32) + 1);
314 if (res == ERROR_SUCCESS && list->ips32_tmodel)
315 res = RegSetValueExA(ips32_key, tmodel_valuename, 0, REG_SZ,
316 (const BYTE*)list->ips32_tmodel,
317 strlen(list->ips32_tmodel) + 1);
318 RegCloseKey(ips32_key);
319 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
322 if (list->progid) {
323 res = register_key_defvalueA(clsid_key, progid_keyname,
324 list->progid);
325 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
327 res = register_progid(buf, list->progid, NULL,
328 list->name, list->progid_extra);
329 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
332 if (list->viprogid) {
333 res = register_key_defvalueA(clsid_key, viprogid_keyname,
334 list->viprogid);
335 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
337 res = register_progid(buf, list->viprogid, list->progid,
338 list->name, list->progid_extra);
339 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
342 error_close_clsid_key:
343 RegCloseKey(clsid_key);
346 error_close_coclass_key:
347 RegCloseKey(coclass_key);
348 error_return:
349 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
352 /***********************************************************************
353 * unregister_coclasses
355 static HRESULT unregister_coclasses(struct regsvr_coclass const *list)
357 LONG res = ERROR_SUCCESS;
358 HKEY coclass_key;
360 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0,
361 KEY_READ | KEY_WRITE, &coclass_key);
362 if (res == ERROR_FILE_NOT_FOUND) return S_OK;
363 if (res != ERROR_SUCCESS) goto error_return;
365 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
366 WCHAR buf[39];
368 StringFromGUID2(list->clsid, buf, 39);
369 res = RegDeleteTreeW(coclass_key, buf);
370 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
371 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
373 if (list->progid) {
374 res = RegDeleteTreeA(HKEY_CLASSES_ROOT, list->progid);
375 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
376 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
379 if (list->viprogid) {
380 res = RegDeleteTreeA(HKEY_CLASSES_ROOT, list->viprogid);
381 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
382 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
386 error_close_coclass_key:
387 RegCloseKey(coclass_key);
388 error_return:
389 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
392 /***********************************************************************
393 * register_mediatypes_parsing
395 static HRESULT register_mediatypes_parsing(struct regsvr_mediatype_parsing const *list)
397 LONG res = ERROR_SUCCESS;
398 HKEY mediatype_key;
399 WCHAR buf[39];
400 int i;
402 res = RegCreateKeyExW(HKEY_CLASSES_ROOT, mediatype_name, 0, NULL, 0,
403 KEY_READ | KEY_WRITE, NULL, &mediatype_key, NULL);
404 if (res != ERROR_SUCCESS) return HRESULT_FROM_WIN32(res);
406 for (; res == ERROR_SUCCESS && list->majortype; ++list) {
407 HKEY majortype_key = NULL;
408 HKEY subtype_key = NULL;
410 StringFromGUID2(list->majortype, buf, 39);
411 res = RegCreateKeyExW(mediatype_key, buf, 0, NULL, 0,
412 KEY_READ | KEY_WRITE, NULL, &majortype_key, NULL);
413 if (res != ERROR_SUCCESS) goto error_close_keys;
415 StringFromGUID2(list->subtype, buf, 39);
416 res = RegCreateKeyExW(majortype_key, buf, 0, NULL, 0,
417 KEY_READ | KEY_WRITE, NULL, &subtype_key, NULL);
418 if (res != ERROR_SUCCESS) goto error_close_keys;
420 StringFromGUID2(&CLSID_AsyncReader, buf, 39);
421 res = RegSetValueExW(subtype_key, sourcefilter_valuename, 0, REG_SZ, (const BYTE*)buf,
422 (lstrlenW(buf) + 1) * sizeof(WCHAR));
423 if (res != ERROR_SUCCESS) goto error_close_keys;
425 for(i = 0; list->line[i]; i++) {
426 char buffer[3];
427 wsprintfA(buffer, "%d", i);
428 res = RegSetValueExA(subtype_key, buffer, 0, REG_SZ, (const BYTE*)list->line[i],
429 lstrlenA(list->line[i]));
430 if (res != ERROR_SUCCESS) goto error_close_keys;
433 error_close_keys:
434 if (majortype_key)
435 RegCloseKey(majortype_key);
436 if (subtype_key)
437 RegCloseKey(subtype_key);
440 RegCloseKey(mediatype_key);
442 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
445 /***********************************************************************
446 * register_mediatypes_extension
448 static HRESULT register_mediatypes_extension(struct regsvr_mediatype_extension const *list)
450 LONG res = ERROR_SUCCESS;
451 HKEY mediatype_key;
452 HKEY extensions_root_key = NULL;
453 WCHAR buf[39];
455 res = RegCreateKeyExW(HKEY_CLASSES_ROOT, mediatype_name, 0, NULL, 0,
456 KEY_READ | KEY_WRITE, NULL, &mediatype_key, NULL);
457 if (res != ERROR_SUCCESS) return HRESULT_FROM_WIN32(res);
459 res = RegCreateKeyExW(mediatype_key, extensions_keyname, 0, NULL, 0,
460 KEY_READ | KEY_WRITE, NULL, &extensions_root_key, NULL);
461 if (res != ERROR_SUCCESS) goto error_return;
463 for (; res == ERROR_SUCCESS && list->majortype; ++list) {
464 HKEY extension_key;
466 res = RegCreateKeyExA(extensions_root_key, list->extension, 0, NULL, 0,
467 KEY_READ | KEY_WRITE, NULL, &extension_key, NULL);
468 if (res != ERROR_SUCCESS) break;
470 StringFromGUID2(list->majortype, buf, 39);
471 res = RegSetValueExW(extension_key, mediatype_name, 0, REG_SZ, (const BYTE*)buf,
472 (lstrlenW(buf) + 1) * sizeof(WCHAR));
473 if (res != ERROR_SUCCESS) goto error_close_key;
475 StringFromGUID2(list->subtype, buf, 39);
476 res = RegSetValueExW(extension_key, subtype_valuename, 0, REG_SZ, (const BYTE*)buf,
477 (lstrlenW(buf) + 1) * sizeof(WCHAR));
478 if (res != ERROR_SUCCESS) goto error_close_key;
480 StringFromGUID2(&CLSID_AsyncReader, buf, 39);
481 res = RegSetValueExW(extension_key, sourcefilter_valuename, 0, REG_SZ, (const BYTE*)buf,
482 (lstrlenW(buf) + 1) * sizeof(WCHAR));
483 if (res != ERROR_SUCCESS) goto error_close_key;
485 error_close_key:
486 RegCloseKey(extension_key);
489 error_return:
490 RegCloseKey(mediatype_key);
491 if (extensions_root_key)
492 RegCloseKey(extensions_root_key);
494 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
497 /***********************************************************************
498 * unregister_mediatypes_parsing
500 static HRESULT unregister_mediatypes_parsing(struct regsvr_mediatype_parsing const *list)
502 LONG res;
503 HKEY mediatype_key;
504 HKEY majortype_key;
505 WCHAR buf[39];
507 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, mediatype_name, 0,
508 KEY_READ | KEY_WRITE, &mediatype_key);
509 if (res == ERROR_FILE_NOT_FOUND) return S_OK;
510 if (res != ERROR_SUCCESS) return HRESULT_FROM_WIN32(res);
512 for (; res == ERROR_SUCCESS && list->majortype; ++list) {
513 StringFromGUID2(list->majortype, buf, 39);
514 res = RegOpenKeyExW(mediatype_key, buf, 0,
515 KEY_READ | KEY_WRITE, &majortype_key);
516 if (res == ERROR_FILE_NOT_FOUND) {
517 res = ERROR_SUCCESS;
518 continue;
520 if (res != ERROR_SUCCESS) break;
522 StringFromGUID2(list->subtype, buf, 39);
523 res = RegDeleteTreeW(majortype_key, buf);
524 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
526 /* Removed majortype key if there is no more subtype key */
527 res = RegDeleteKeyW(majortype_key, 0);
528 if (res == ERROR_ACCESS_DENIED) res = ERROR_SUCCESS;
530 RegCloseKey(majortype_key);
533 RegCloseKey(mediatype_key);
535 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
538 /***********************************************************************
539 * unregister_mediatypes_extension
541 static HRESULT unregister_mediatypes_extension(struct regsvr_mediatype_extension const *list)
543 LONG res;
544 HKEY mediatype_key;
545 HKEY extensions_root_key = NULL;
547 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, mediatype_name, 0,
548 KEY_READ | KEY_WRITE, &mediatype_key);
549 if (res == ERROR_FILE_NOT_FOUND) return S_OK;
550 if (res != ERROR_SUCCESS) return HRESULT_FROM_WIN32(res);
552 res = RegOpenKeyExW(mediatype_key, extensions_keyname, 0,
553 KEY_READ | KEY_WRITE, &extensions_root_key);
554 if (res == ERROR_FILE_NOT_FOUND)
555 res = ERROR_SUCCESS;
556 else if (res == ERROR_SUCCESS)
557 for (; res == ERROR_SUCCESS && list->majortype; ++list) {
558 res = RegDeleteTreeA(extensions_root_key, list->extension);
559 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
562 RegCloseKey(mediatype_key);
563 if (extensions_root_key)
564 RegCloseKey(extensions_root_key);
566 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
569 /***********************************************************************
570 * register_filters
572 static HRESULT register_filters(struct regsvr_filter const *list)
574 HRESULT hr;
575 IFilterMapper2* pFM2 = NULL;
577 CoInitialize(NULL);
578 hr = CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC_SERVER, &IID_IFilterMapper2, (LPVOID*)&pFM2);
580 if (SUCCEEDED(hr)) {
581 for (; SUCCEEDED(hr) && list->clsid; ++list) {
582 REGFILTER2 rf2;
583 REGFILTERPINS2* prfp2;
584 int i;
586 for (i = 0; list->pins[i].flags != 0xFFFFFFFF; i++) ;
587 rf2.dwVersion = 2;
588 rf2.dwMerit = list->merit;
589 rf2.u.s2.cPins2 = i;
590 rf2.u.s2.rgPins2 = prfp2 = CoTaskMemAlloc(i*sizeof(REGFILTERPINS2));
591 if (!prfp2) {
592 hr = E_OUTOFMEMORY;
593 break;
595 for (i = 0; list->pins[i].flags != 0xFFFFFFFF; i++) {
596 REGPINTYPES* lpMediatype;
597 CLSID* lpClsid;
598 int j, nbmt;
600 for (nbmt = 0; list->pins[i].mediatypes[nbmt].majortype; nbmt++) ;
601 /* Allocate a single buffer for regpintypes struct and clsids */
602 lpMediatype = CoTaskMemAlloc(nbmt*(sizeof(REGPINTYPES) + 2*sizeof(CLSID)));
603 if (!lpMediatype) {
604 hr = E_OUTOFMEMORY;
605 break;
607 lpClsid = (CLSID*) (lpMediatype + nbmt);
608 for (j = 0; j < nbmt; j++) {
609 (lpMediatype + j)->clsMajorType = lpClsid + j*2;
610 memcpy(lpClsid + j*2, list->pins[i].mediatypes[j].majortype, sizeof(CLSID));
611 (lpMediatype + j)->clsMinorType = lpClsid + j*2 + 1;
612 if (list->pins[i].mediatypes[j].subtype)
613 memcpy(lpClsid + j*2 + 1, list->pins[i].mediatypes[j].subtype, sizeof(CLSID));
614 else {
615 /* Subtypes are often a combination of major type + fourcc/tag */
616 memcpy(lpClsid + j*2 + 1, list->pins[i].mediatypes[j].majortype, sizeof(CLSID));
617 *(DWORD*)(lpClsid + j*2 + 1) = list->pins[i].mediatypes[j].fourcc;
620 prfp2[i].dwFlags = list->pins[i].flags;
621 prfp2[i].cInstances = 0;
622 prfp2[i].nMediaTypes = j;
623 prfp2[i].lpMediaType = lpMediatype;
624 prfp2[i].nMediums = 0;
625 prfp2[i].lpMedium = NULL;
626 prfp2[i].clsPinCategory = NULL;
629 if (FAILED(hr)) {
630 ERR("failed to register with hresult 0x%x\n", hr);
631 CoTaskMemFree(prfp2);
632 break;
635 hr = IFilterMapper2_RegisterFilter(pFM2, list->clsid, list->name, NULL, list->category, NULL, &rf2);
637 while (i) {
638 CoTaskMemFree((REGPINTYPES*)prfp2[i-1].lpMediaType);
639 i--;
641 CoTaskMemFree(prfp2);
645 if (pFM2)
646 IFilterMapper2_Release(pFM2);
648 CoUninitialize();
650 return hr;
653 /***********************************************************************
654 * unregister_filters
656 static HRESULT unregister_filters(struct regsvr_filter const *list)
658 HRESULT hr;
659 IFilterMapper2* pFM2;
661 CoInitialize(NULL);
663 hr = CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC_SERVER, &IID_IFilterMapper2, (LPVOID*)&pFM2);
665 if (SUCCEEDED(hr)) {
666 for (; SUCCEEDED(hr) && list->clsid; ++list)
667 hr = IFilterMapper2_UnregisterFilter(pFM2, list->category, NULL, list->clsid);
668 IFilterMapper2_Release(pFM2);
671 CoUninitialize();
673 return hr;
676 /***********************************************************************
677 * regsvr_key_guid
679 static LONG register_key_guid(HKEY base, WCHAR const *name, GUID const *guid)
681 WCHAR buf[39];
683 StringFromGUID2(guid, buf, 39);
684 return register_key_defvalueW(base, name, buf);
687 /***********************************************************************
688 * regsvr_key_defvalueW
690 static LONG register_key_defvalueW(
691 HKEY base,
692 WCHAR const *name,
693 WCHAR const *value)
695 LONG res;
696 HKEY key;
698 res = RegCreateKeyExW(base, name, 0, NULL, 0,
699 KEY_READ | KEY_WRITE, NULL, &key, NULL);
700 if (res != ERROR_SUCCESS) return res;
701 res = RegSetValueExW(key, NULL, 0, REG_SZ, (const BYTE*)value,
702 (lstrlenW(value) + 1) * sizeof(WCHAR));
703 RegCloseKey(key);
704 return res;
707 /***********************************************************************
708 * regsvr_key_defvalueA
710 static LONG register_key_defvalueA(
711 HKEY base,
712 WCHAR const *name,
713 char const *value)
715 LONG res;
716 HKEY key;
718 res = RegCreateKeyExW(base, name, 0, NULL, 0,
719 KEY_READ | KEY_WRITE, NULL, &key, NULL);
720 if (res != ERROR_SUCCESS) return res;
721 res = RegSetValueExA(key, NULL, 0, REG_SZ, (const BYTE*)value, lstrlenA(value) + 1);
722 RegCloseKey(key);
723 return res;
726 /***********************************************************************
727 * regsvr_progid
729 static LONG register_progid(
730 WCHAR const *clsid,
731 char const *progid,
732 char const *curver_progid,
733 char const *name,
734 char const *extra)
736 LONG res;
737 HKEY progid_key;
739 res = RegCreateKeyExA(HKEY_CLASSES_ROOT, progid, 0,
740 NULL, 0, KEY_READ | KEY_WRITE, NULL,
741 &progid_key, NULL);
742 if (res != ERROR_SUCCESS) return res;
744 if (name) {
745 res = RegSetValueExA(progid_key, NULL, 0, REG_SZ, (const BYTE*)name, strlen(name) + 1);
746 if (res != ERROR_SUCCESS) goto error_close_progid_key;
749 if (clsid) {
750 res = register_key_defvalueW(progid_key, clsid_keyname, clsid);
751 if (res != ERROR_SUCCESS) goto error_close_progid_key;
754 if (curver_progid) {
755 res = register_key_defvalueA(progid_key, curver_keyname,
756 curver_progid);
757 if (res != ERROR_SUCCESS) goto error_close_progid_key;
760 if (extra) {
761 HKEY extra_key;
763 res = RegCreateKeyExA(progid_key, extra, 0,
764 NULL, 0, KEY_READ | KEY_WRITE, NULL,
765 &extra_key, NULL);
766 if (res == ERROR_SUCCESS)
767 RegCloseKey(extra_key);
770 error_close_progid_key:
771 RegCloseKey(progid_key);
772 return res;
775 /***********************************************************************
776 * coclass list
778 static struct regsvr_coclass const coclass_list[] = {
779 { NULL } /* list terminator */
782 /***********************************************************************
783 * interface list
786 static struct regsvr_interface const interface_list[] = {
787 { NULL } /* list terminator */
790 /***********************************************************************
791 * mediatype list
794 static struct regsvr_mediatype_parsing const mediatype_parsing_list[] = {
795 { &MEDIATYPE_Stream,
796 &MEDIASUBTYPE_Avi,
797 { "0,4,,52494646,8,4,,41564920",
798 NULL }
800 { &MEDIATYPE_Stream,
801 &MEDIASUBTYPE_MPEG1System,
802 { "0, 16, FFFFFFFFF100010001800001FFFFFFFF, 000001BA2100010001800001000001BB",
803 NULL }
805 { &MEDIATYPE_Stream,
806 &MEDIASUBTYPE_MPEG1VideoCD,
807 { "0, 4, , 52494646, 8, 8, , 43445841666D7420, 36, 20, FFFFFFFF00000000FFFFFFFFFFFFFFFFFFFFFFFF, 646174610000000000FFFFFFFFFFFFFFFFFFFF00",
808 NULL }
810 { &MEDIATYPE_Stream,
811 &MEDIASUBTYPE_MPEG1Video,
812 { "0, 4, , 000001B3",
813 NULL }
815 { &MEDIATYPE_Stream,
816 &MEDIASUBTYPE_MPEG1Audio,
817 { "0, 2, FFE0, FFE0",
818 "0, 10, FFFFFF00000080808080, 494433000000000000",
819 NULL }
821 { &MEDIATYPE_Stream,
822 &MEDIASUBTYPE_MPEG2_PROGRAM,
823 { "0, 5, FFFFFFFFC0, 000001BA40",
824 NULL }
826 { &MEDIATYPE_Stream,
827 &MEDIASUBTYPE_QTMovie,
828 { "4, 4, , 6d646174",
829 "4, 4, , 6d6f6f76",
830 NULL }
832 { &MEDIATYPE_Stream,
833 &MEDIASUBTYPE_WAVE,
834 { "0,4,,52494646,8,4,,57415645",
835 NULL }
837 { &MEDIATYPE_Stream,
838 &MEDIASUBTYPE_AU,
839 { "0,4,,2e736e64",
840 NULL }
842 { &MEDIATYPE_Stream,
843 &MEDIASUBTYPE_AIFF,
844 { "0,4,,464f524d,8,4,,41494646",
845 "0,4,,464f524d,8,4,,41494643",
846 NULL }
848 { &MEDIATYPE_Stream,
849 &MEDIATYPE_Text,
850 { "0,4,,4C595249",
851 "0,4,,6C797269",
852 NULL }
854 { &MEDIATYPE_Stream,
855 &MEDIATYPE_Midi,
856 { "0,4,,52494646,8,4,,524D4944",
857 "0,4,,4D546864",
858 NULL }
860 { NULL } /* list terminator */
863 /***********************************************************************
864 * mediatype list
867 static struct regsvr_mediatype_extension const mediatype_extension_list[] = {
868 { &MEDIATYPE_Stream,
869 &MEDIASUBTYPE_MPEG1Audio,
870 ".mp3"
872 { NULL } /* list terminator */
875 /***********************************************************************
876 * filter list
879 static struct regsvr_filter const filter_list[] = {
880 { &CLSID_AviSplitter,
881 &CLSID_LegacyAmFilterCategory,
882 {'A','V','I',' ','S','p','l','i','t','t','e','r',0},
883 0x5ffff0,
884 { { 0,
885 { { &MEDIATYPE_Stream, &MEDIASUBTYPE_Avi },
886 { NULL }
889 { REG_PINFLAG_B_OUTPUT,
890 { { &MEDIATYPE_Video, &GUID_NULL },
891 { NULL }
894 { 0xFFFFFFFF },
897 { &CLSID_MPEG1Splitter,
898 &CLSID_LegacyAmFilterCategory,
899 {'M','P','E','G','-','I',' ','S','t','r','e','a','m',' ','S','p','l','i','t','t','e','r',0},
900 0x5ffff0,
901 { { 0,
902 { { &MEDIATYPE_Stream, &MEDIASUBTYPE_MPEG1Audio },
903 { &MEDIATYPE_Stream, &MEDIASUBTYPE_MPEG1Video },
904 { &MEDIATYPE_Stream, &MEDIASUBTYPE_MPEG1System },
905 { &MEDIATYPE_Stream, &MEDIASUBTYPE_MPEG1VideoCD },
906 { NULL }
909 { REG_PINFLAG_B_OUTPUT,
910 { { &MEDIATYPE_Audio, &MEDIASUBTYPE_MPEG1Packet },
911 { &MEDIATYPE_Audio, &MEDIASUBTYPE_MPEG1AudioPayload },
912 { NULL }
915 { REG_PINFLAG_B_OUTPUT,
916 { { &MEDIATYPE_Video, &MEDIASUBTYPE_MPEG1Packet },
917 { &MEDIATYPE_Video, &MEDIASUBTYPE_MPEG1Payload },
918 { NULL }
921 { 0xFFFFFFFF },
924 { &CLSID_NullRenderer,
925 &CLSID_LegacyAmFilterCategory,
926 {'N','u','l','l',' ','R','e','n','d','e','r','e','r',0},
927 0x200000,
928 { { REG_PINFLAG_B_RENDERER,
929 { { &MEDIATYPE_NULL, &GUID_NULL },
930 { NULL }
933 { 0xFFFFFFFF },
936 { &CLSID_VideoRenderer,
937 &CLSID_LegacyAmFilterCategory,
938 {'V','i','d','e','o',' ','R','e','n','d','e','r','e','r',0},
939 0x800000,
940 { { REG_PINFLAG_B_RENDERER,
941 { { &MEDIATYPE_Video, &GUID_NULL },
942 { NULL }
945 { 0xFFFFFFFF },
948 { &CLSID_VideoRendererDefault,
949 &CLSID_LegacyAmFilterCategory,
950 {'V','i','d','e','o',' ','R','e','n','d','e','r','e','r',0},
951 0x800000,
952 { { REG_PINFLAG_B_RENDERER,
953 { { &MEDIATYPE_Video, &GUID_NULL },
954 { NULL }
957 { 0xFFFFFFFF },
960 { &CLSID_VideoMixingRenderer,
961 &CLSID_LegacyAmFilterCategory,
962 {'V','i','d','e','o',' ','M','i','x','i','n','g',' ','R','e','n','d','e','r','e','r',0},
963 0x200000,
964 { { REG_PINFLAG_B_RENDERER,
965 { { &MEDIATYPE_Video, &GUID_NULL },
966 { NULL }
969 { 0xFFFFFFFF },
972 { &CLSID_VideoMixingRenderer9,
973 &CLSID_LegacyAmFilterCategory,
974 {'V','i','d','e','o',' ','M','i','x','i','n','g',' ','R','e','n','d','e','r','e','r',' ','9',0},
975 0x200000,
976 { { REG_PINFLAG_B_RENDERER,
977 { { &MEDIATYPE_Video, &GUID_NULL },
978 { NULL }
981 { 0xFFFFFFFF },
984 { &CLSID_DSoundRender,
985 &CLSID_LegacyAmFilterCategory,
986 {'A','u','d','i','o',' ','R','e','n','d','e','r','e','r',0},
987 0x800000,
988 { { REG_PINFLAG_B_RENDERER,
989 { { &MEDIATYPE_Audio, &MEDIASUBTYPE_PCM },
990 /* { &MEDIATYPE_Audio, &MEDIASUBTYPE_IEEE_FLOAT }, */
991 { NULL }
994 { 0xFFFFFFFF },
997 { &CLSID_AudioRender,
998 &CLSID_LegacyAmFilterCategory,
999 {'A','u','d','i','o',' ','R','e','n','d','e','r','e','r',0},
1000 0x800000,
1001 { { REG_PINFLAG_B_RENDERER,
1002 { { &MEDIATYPE_Audio, &MEDIASUBTYPE_PCM },
1003 /* { &MEDIATYPE_Audio, &MEDIASUBTYPE_IEEE_FLOAT }, */
1004 { NULL }
1007 { 0xFFFFFFFF },
1010 { &CLSID_AVIDec,
1011 &CLSID_LegacyAmFilterCategory,
1012 {'A','V','I',' ','D','e','c','o','m','p','r','e','s','s','o','r',0},
1013 0x5ffff0,
1014 { { 0,
1015 { { &MEDIATYPE_Video, &GUID_NULL },
1016 { NULL }
1019 { REG_PINFLAG_B_OUTPUT,
1020 { { &MEDIATYPE_Video, &GUID_NULL },
1021 { NULL }
1024 { 0xFFFFFFFF },
1027 { &CLSID_AsyncReader,
1028 &CLSID_LegacyAmFilterCategory,
1029 {'F','i','l','e',' ','S','o','u','r','c','e',' ','(','A','s','y','n','c','.',')',0},
1030 0x400000,
1031 { { REG_PINFLAG_B_OUTPUT,
1032 { { &MEDIATYPE_Stream, &GUID_NULL },
1033 { NULL }
1036 { 0xFFFFFFFF },
1039 { &CLSID_ACMWrapper,
1040 &CLSID_LegacyAmFilterCategory,
1041 {'A','C','M',' ','W','r','a','p','p','e','r',0},
1042 0x5ffff0,
1043 { { 0,
1044 { { &MEDIATYPE_Audio, &GUID_NULL },
1045 { NULL }
1048 { REG_PINFLAG_B_OUTPUT,
1049 { { &MEDIATYPE_Audio, &GUID_NULL },
1050 { NULL }
1053 { 0xFFFFFFFF },
1056 { &CLSID_WAVEParser,
1057 &CLSID_LegacyAmFilterCategory,
1058 {'W','a','v','e',' ','P','a','r','s','e','r',0},
1059 0x400000,
1060 { { 0,
1061 { { &MEDIATYPE_Stream, &MEDIASUBTYPE_WAVE },
1062 { &MEDIATYPE_Stream, &MEDIASUBTYPE_AU },
1063 { &MEDIATYPE_Stream, &MEDIASUBTYPE_AIFF },
1064 { NULL }
1067 { REG_PINFLAG_B_OUTPUT,
1068 { { &MEDIATYPE_Audio, &GUID_NULL },
1069 { NULL }
1072 { 0xFFFFFFFF },
1075 { NULL } /* list terminator */
1078 extern HRESULT WINAPI QUARTZ_DllRegisterServer(void) DECLSPEC_HIDDEN;
1079 extern HRESULT WINAPI QUARTZ_DllUnregisterServer(void) DECLSPEC_HIDDEN;
1081 /***********************************************************************
1082 * DllRegisterServer (QUARTZ.@)
1084 HRESULT WINAPI DllRegisterServer(void)
1086 HRESULT hr;
1088 TRACE("\n");
1090 hr = QUARTZ_DllRegisterServer();
1091 if (SUCCEEDED(hr))
1092 hr = register_coclasses(coclass_list);
1093 if (SUCCEEDED(hr))
1094 hr = register_interfaces(interface_list);
1095 if (SUCCEEDED(hr))
1096 hr = register_mediatypes_parsing(mediatype_parsing_list);
1097 if (SUCCEEDED(hr))
1098 hr = register_mediatypes_extension(mediatype_extension_list);
1099 if (SUCCEEDED(hr))
1100 hr = register_filters(filter_list);
1101 return hr;
1104 /***********************************************************************
1105 * DllUnregisterServer (QUARTZ.@)
1107 HRESULT WINAPI DllUnregisterServer(void)
1109 HRESULT hr;
1111 TRACE("\n");
1113 hr = unregister_filters(filter_list);
1114 if (SUCCEEDED(hr))
1115 hr = unregister_coclasses(coclass_list);
1116 if (SUCCEEDED(hr))
1117 hr = unregister_interfaces(interface_list);
1118 if (SUCCEEDED(hr))
1119 hr = unregister_mediatypes_parsing(mediatype_parsing_list);
1120 if (SUCCEEDED(hr))
1121 hr = unregister_mediatypes_extension(mediatype_extension_list);
1122 if (SUCCEEDED(hr))
1123 hr = QUARTZ_DllUnregisterServer();
1124 return hr;