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
24 #define COM_NO_WINDOWS_H
38 #include "wine/debug.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(quartz);
43 * Near the bottom of this file are the exported DllRegisterServer and
44 * DllUnregisterServer, which make all this worthwhile.
47 /***********************************************************************
48 * interface for self-registering
50 struct regsvr_interface
52 IID const *iid; /* NULL for end of list */
53 LPCSTR name; /* can be NULL to omit */
54 IID const *base_iid; /* can be NULL to omit */
55 int num_methods; /* can be <0 to omit */
56 CLSID const *ps_clsid; /* can be NULL to omit */
57 CLSID const *ps_clsid32; /* can be NULL to omit */
60 static HRESULT register_interfaces(struct regsvr_interface const *list);
61 static HRESULT unregister_interfaces(struct regsvr_interface const *list);
65 CLSID const *clsid; /* NULL for end of list */
66 LPCSTR name; /* can be NULL to omit */
67 LPCSTR ips; /* can be NULL to omit */
68 LPCSTR ips32; /* can be NULL to omit */
69 LPCSTR ips32_tmodel; /* can be NULL to omit */
70 LPCSTR progid; /* can be NULL to omit */
71 LPCSTR viprogid; /* can be NULL to omit */
72 LPCSTR progid_extra; /* can be NULL to omit */
75 static HRESULT register_coclasses(struct regsvr_coclass const *list);
76 static HRESULT unregister_coclasses(struct regsvr_coclass const *list);
78 struct regsvr_mediatype_parsing
80 CLSID const *majortype; /* NULL for end of list */
82 LPCSTR line[11]; /* NULL for end of list */
85 static HRESULT register_mediatypes_parsing(struct regsvr_mediatype_parsing const *list);
86 static HRESULT unregister_mediatypes_parsing(struct regsvr_mediatype_parsing const *list);
88 struct regsvr_mediatype_extension
90 CLSID const *majortype; /* NULL for end of list */
97 CLSID const *majortype; /* NULL for end of list */
104 DWORD flags; /* 0xFFFFFFFF for end of list */
105 struct mediatype mediatypes[11];
110 CLSID const *clsid; /* NULL for end of list */
111 CLSID const *category;
117 static HRESULT register_mediatypes_extension(struct regsvr_mediatype_extension const *list);
118 static HRESULT unregister_mediatypes_extension(struct regsvr_mediatype_extension const *list);
120 static HRESULT register_filters(struct regsvr_filter const *list);
121 static HRESULT unregister_filters(struct regsvr_filter const *list);
123 /***********************************************************************
124 * static string constants
126 static WCHAR const interface_keyname[10] = {
127 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c', 'e', 0 };
128 static WCHAR const base_ifa_keyname[14] = {
129 'B', 'a', 's', 'e', 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c',
131 static WCHAR const num_methods_keyname[11] = {
132 'N', 'u', 'm', 'M', 'e', 't', 'h', 'o', 'd', 's', 0 };
133 static WCHAR const ps_clsid_keyname[15] = {
134 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
136 static WCHAR const ps_clsid32_keyname[17] = {
137 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
138 'i', 'd', '3', '2', 0 };
139 static WCHAR const clsid_keyname[6] = {
140 'C', 'L', 'S', 'I', 'D', 0 };
141 static WCHAR const curver_keyname[7] = {
142 'C', 'u', 'r', 'V', 'e', 'r', 0 };
143 static WCHAR const ips_keyname[13] = {
144 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
146 static WCHAR const ips32_keyname[15] = {
147 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
149 static WCHAR const progid_keyname[7] = {
150 'P', 'r', 'o', 'g', 'I', 'D', 0 };
151 static WCHAR const viprogid_keyname[25] = {
152 'V', 'e', 'r', 's', 'i', 'o', 'n', 'I', 'n', 'd', 'e', 'p',
153 'e', 'n', 'd', 'e', 'n', 't', 'P', 'r', 'o', 'g', 'I', 'D',
155 static char const tmodel_valuename[] = "ThreadingModel";
156 static WCHAR const mediatype_name[11] = {
157 'M', 'e', 'd', 'i', 'a', ' ', 'T', 'y', 'p', 'e', 0 };
158 static WCHAR const subtype_valuename[8] = {
159 'S', 'u', 'b', 't', 'y', 'p', 'e', 0 };
160 static WCHAR const sourcefilter_valuename[14] = {
161 'S', 'o', 'u', 'r', 'c', 'e', ' ', 'F', 'i', 'l', 't', 'e', 'r', 0 };
162 static WCHAR const extensions_keyname[11] = {
163 'E', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 's', 0 };
165 /***********************************************************************
166 * static helper functions
168 static LONG register_key_guid(HKEY base, WCHAR const *name, GUID const *guid);
169 static LONG register_key_defvalueW(HKEY base, WCHAR const *name,
171 static LONG register_key_defvalueA(HKEY base, WCHAR const *name,
173 static LONG register_progid(WCHAR const *clsid,
174 char const *progid, char const *curver_progid,
175 char const *name, char const *extra);
176 static LONG recursive_delete_key(HKEY key);
177 static LONG recursive_delete_keyA(HKEY base, char const *name);
178 static LONG recursive_delete_keyW(HKEY base, WCHAR const *name);
180 /***********************************************************************
181 * register_interfaces
183 static HRESULT register_interfaces(struct regsvr_interface const *list)
185 LONG res = ERROR_SUCCESS;
188 res = RegCreateKeyExW(HKEY_CLASSES_ROOT, interface_keyname, 0, NULL, 0,
189 KEY_READ | KEY_WRITE, NULL, &interface_key, NULL);
190 if (res != ERROR_SUCCESS) goto error_return;
192 for (; res == ERROR_SUCCESS && list->iid; ++list) {
196 StringFromGUID2(list->iid, buf, 39);
197 res = RegCreateKeyExW(interface_key, buf, 0, NULL, 0,
198 KEY_READ | KEY_WRITE, NULL, &iid_key, NULL);
199 if (res != ERROR_SUCCESS) goto error_close_interface_key;
202 res = RegSetValueExA(iid_key, NULL, 0, REG_SZ,
203 (CONST BYTE*)(list->name),
204 strlen(list->name) + 1);
205 if (res != ERROR_SUCCESS) goto error_close_iid_key;
208 if (list->base_iid) {
209 res = register_key_guid(iid_key, base_ifa_keyname, list->base_iid);
210 if (res != ERROR_SUCCESS) goto error_close_iid_key;
213 if (0 <= list->num_methods) {
214 static WCHAR const fmt[3] = { '%', 'd', 0 };
217 res = RegCreateKeyExW(iid_key, num_methods_keyname, 0, NULL, 0,
218 KEY_READ | KEY_WRITE, NULL, &key, NULL);
219 if (res != ERROR_SUCCESS) goto error_close_iid_key;
221 wsprintfW(buf, fmt, list->num_methods);
222 res = RegSetValueExW(key, NULL, 0, REG_SZ,
224 (lstrlenW(buf) + 1) * sizeof(WCHAR));
227 if (res != ERROR_SUCCESS) goto error_close_iid_key;
230 if (list->ps_clsid) {
231 register_key_guid(iid_key, ps_clsid_keyname, list->ps_clsid);
232 if (res != ERROR_SUCCESS) goto error_close_iid_key;
235 if (list->ps_clsid32) {
236 register_key_guid(iid_key, ps_clsid32_keyname, list->ps_clsid32);
237 if (res != ERROR_SUCCESS) goto error_close_iid_key;
241 RegCloseKey(iid_key);
244 error_close_interface_key:
245 RegCloseKey(interface_key);
247 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
250 /***********************************************************************
251 * unregister_interfaces
253 static HRESULT unregister_interfaces(struct regsvr_interface const *list)
255 LONG res = ERROR_SUCCESS;
258 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, interface_keyname, 0,
259 KEY_READ | KEY_WRITE, &interface_key);
260 if (res == ERROR_FILE_NOT_FOUND) return S_OK;
261 if (res != ERROR_SUCCESS) goto error_return;
263 for (; res == ERROR_SUCCESS && list->iid; ++list) {
266 StringFromGUID2(list->iid, buf, 39);
267 res = recursive_delete_keyW(interface_key, buf);
270 RegCloseKey(interface_key);
272 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
275 /***********************************************************************
278 static HRESULT register_coclasses(struct regsvr_coclass const *list)
280 LONG res = ERROR_SUCCESS;
283 res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0,
284 KEY_READ | KEY_WRITE, NULL, &coclass_key, NULL);
285 if (res != ERROR_SUCCESS) goto error_return;
287 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
291 StringFromGUID2(list->clsid, buf, 39);
292 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
293 KEY_READ | KEY_WRITE, NULL, &clsid_key, NULL);
294 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
297 res = RegSetValueExA(clsid_key, NULL, 0, REG_SZ,
298 (CONST BYTE*)(list->name),
299 strlen(list->name) + 1);
300 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
304 res = register_key_defvalueA(clsid_key, ips_keyname, list->ips);
305 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
311 res = RegCreateKeyExW(clsid_key, ips32_keyname, 0, NULL, 0,
312 KEY_READ | KEY_WRITE, NULL,
314 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
316 res = RegSetValueExA(ips32_key, NULL, 0, REG_SZ,
317 (CONST BYTE*)list->ips32,
318 lstrlenA(list->ips32) + 1);
319 if (res == ERROR_SUCCESS && list->ips32_tmodel)
320 res = RegSetValueExA(ips32_key, tmodel_valuename, 0, REG_SZ,
321 (CONST BYTE*)list->ips32_tmodel,
322 strlen(list->ips32_tmodel) + 1);
323 RegCloseKey(ips32_key);
324 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
328 res = register_key_defvalueA(clsid_key, progid_keyname,
330 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
332 res = register_progid(buf, list->progid, NULL,
333 list->name, list->progid_extra);
334 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
337 if (list->viprogid) {
338 res = register_key_defvalueA(clsid_key, viprogid_keyname,
340 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
342 res = register_progid(buf, list->viprogid, list->progid,
343 list->name, list->progid_extra);
344 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
347 error_close_clsid_key:
348 RegCloseKey(clsid_key);
351 error_close_coclass_key:
352 RegCloseKey(coclass_key);
354 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
357 /***********************************************************************
358 * unregister_coclasses
360 static HRESULT unregister_coclasses(struct regsvr_coclass const *list)
362 LONG res = ERROR_SUCCESS;
365 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0,
366 KEY_READ | KEY_WRITE, &coclass_key);
367 if (res == ERROR_FILE_NOT_FOUND) return S_OK;
368 if (res != ERROR_SUCCESS) goto error_return;
370 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
373 StringFromGUID2(list->clsid, buf, 39);
374 res = recursive_delete_keyW(coclass_key, buf);
375 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
378 res = recursive_delete_keyA(HKEY_CLASSES_ROOT, list->progid);
379 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
382 if (list->viprogid) {
383 res = recursive_delete_keyA(HKEY_CLASSES_ROOT, list->viprogid);
384 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
388 error_close_coclass_key:
389 RegCloseKey(coclass_key);
391 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
394 /***********************************************************************
395 * register_mediatypes_parsing
397 static HRESULT register_mediatypes_parsing(struct regsvr_mediatype_parsing const *list)
399 LONG res = ERROR_SUCCESS;
404 res = RegCreateKeyExW(HKEY_CLASSES_ROOT, mediatype_name, 0, NULL, 0,
405 KEY_READ | KEY_WRITE, NULL, &mediatype_key, NULL);
406 if (res != ERROR_SUCCESS) return HRESULT_FROM_WIN32(res);
408 for (; res == ERROR_SUCCESS && list->majortype; ++list) {
409 HKEY majortype_key = NULL;
410 HKEY subtype_key = NULL;
412 StringFromGUID2(list->majortype, buf, 39);
413 res = RegCreateKeyExW(mediatype_key, buf, 0, NULL, 0,
414 KEY_READ | KEY_WRITE, NULL, &majortype_key, NULL);
415 if (res != ERROR_SUCCESS) goto error_close_keys;
417 StringFromGUID2(list->subtype, buf, 39);
418 res = RegCreateKeyExW(majortype_key, buf, 0, NULL, 0,
419 KEY_READ | KEY_WRITE, NULL, &subtype_key, NULL);
420 if (res != ERROR_SUCCESS) goto error_close_keys;
422 StringFromGUID2(&CLSID_AsyncReader, buf, 39);
423 res = RegSetValueExW(subtype_key, sourcefilter_valuename, 0, REG_SZ, (CONST BYTE*)buf,
424 (lstrlenW(buf) + 1) * sizeof(WCHAR));
425 if (res != ERROR_SUCCESS) goto error_close_keys;
427 for(i = 0; list->line[i]; i++) {
429 wsprintfA(buffer, "%d", i);
430 res = RegSetValueExA(subtype_key, buffer, 0, REG_SZ, (CONST BYTE*)list->line[i],
431 lstrlenA(list->line[i]));
432 if (res != ERROR_SUCCESS) goto error_close_keys;
437 RegCloseKey(majortype_key);
439 RegCloseKey(subtype_key);
442 RegCloseKey(mediatype_key);
444 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
447 /***********************************************************************
448 * register_mediatypes_extension
450 static HRESULT register_mediatypes_extension(struct regsvr_mediatype_extension const *list)
452 LONG res = ERROR_SUCCESS;
454 HKEY extensions_root_key = NULL;
457 res = RegCreateKeyExW(HKEY_CLASSES_ROOT, mediatype_name, 0, NULL, 0,
458 KEY_READ | KEY_WRITE, NULL, &mediatype_key, NULL);
459 if (res != ERROR_SUCCESS) return HRESULT_FROM_WIN32(res);
461 res = RegCreateKeyExW(mediatype_key, extensions_keyname, 0, NULL, 0,
462 KEY_READ | KEY_WRITE, NULL, &extensions_root_key, NULL);
463 if (res != ERROR_SUCCESS) goto error_return;
465 for (; res == ERROR_SUCCESS && list->majortype; ++list) {
468 res = RegCreateKeyExA(extensions_root_key, list->extension, 0, NULL, 0,
469 KEY_READ | KEY_WRITE, NULL, &extension_key, NULL);
470 if (res != ERROR_SUCCESS) break;
472 StringFromGUID2(list->majortype, buf, 39);
473 res = RegSetValueExW(extension_key, mediatype_name, 0, REG_SZ, (CONST BYTE*)buf,
474 (lstrlenW(buf) + 1) * sizeof(WCHAR));
475 if (res != ERROR_SUCCESS) goto error_close_key;
477 StringFromGUID2(list->subtype, buf, 39);
478 res = RegSetValueExW(extension_key, subtype_valuename, 0, REG_SZ, (CONST BYTE*)buf,
479 (lstrlenW(buf) + 1) * sizeof(WCHAR));
480 if (res != ERROR_SUCCESS) goto error_close_key;
482 StringFromGUID2(&CLSID_AsyncReader, buf, 39);
483 res = RegSetValueExW(extension_key, sourcefilter_valuename, 0, REG_SZ, (CONST BYTE*)buf,
484 (lstrlenW(buf) + 1) * sizeof(WCHAR));
485 if (res != ERROR_SUCCESS) goto error_close_key;
488 RegCloseKey(extension_key);
492 RegCloseKey(mediatype_key);
493 if (extensions_root_key)
494 RegCloseKey(extensions_root_key);
496 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
499 /***********************************************************************
500 * unregister_mediatypes_parsing
502 static HRESULT unregister_mediatypes_parsing(struct regsvr_mediatype_parsing const *list)
509 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, mediatype_name, 0,
510 KEY_READ | KEY_WRITE, &mediatype_key);
511 if (res == ERROR_FILE_NOT_FOUND) return S_OK;
512 if (res != ERROR_SUCCESS) return HRESULT_FROM_WIN32(res);
514 for (; res == ERROR_SUCCESS && list->majortype; ++list) {
515 StringFromGUID2(list->majortype, buf, 39);
516 res = RegOpenKeyExW(mediatype_key, buf, 0,
517 KEY_READ | KEY_WRITE, &majortype_key);
518 if (res == ERROR_FILE_NOT_FOUND) {
522 if (res != ERROR_SUCCESS) break;
524 StringFromGUID2(list->subtype, buf, 39);
525 res = recursive_delete_keyW(majortype_key, buf);
526 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
528 /* Removed majortype key if there is no more subtype key */
529 res = RegDeleteKeyW(majortype_key, 0);
530 if (res == ERROR_ACCESS_DENIED) res = ERROR_SUCCESS;
532 RegCloseKey(majortype_key);
535 RegCloseKey(mediatype_key);
537 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
540 /***********************************************************************
541 * unregister_mediatypes_extension
543 static HRESULT unregister_mediatypes_extension(struct regsvr_mediatype_extension const *list)
547 HKEY extensions_root_key = NULL;
549 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, mediatype_name, 0,
550 KEY_READ | KEY_WRITE, &mediatype_key);
551 if (res == ERROR_FILE_NOT_FOUND) return S_OK;
552 if (res != ERROR_SUCCESS) return HRESULT_FROM_WIN32(res);
554 res = RegOpenKeyExW(mediatype_key, extensions_keyname, 0,
555 KEY_READ | KEY_WRITE, &extensions_root_key);
556 if (res == ERROR_FILE_NOT_FOUND)
558 else if (res == ERROR_SUCCESS)
559 for (; res == ERROR_SUCCESS && list->majortype; ++list) {
560 res = recursive_delete_keyA(extensions_root_key, list->extension);
561 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
564 RegCloseKey(mediatype_key);
565 if (extensions_root_key)
566 RegCloseKey(extensions_root_key);
568 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
571 /***********************************************************************
574 static HRESULT register_filters(struct regsvr_filter const *list)
577 IFilterMapper2* pFM2 = NULL;
580 hr = CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC_SERVER, &IID_IFilterMapper2, (LPVOID*)&pFM2);
583 for (; SUCCEEDED(hr) && list->clsid; ++list) {
585 REGFILTERPINS2* prfp2;
588 for (i = 0; list->pins[i].flags != 0xFFFFFFFF; i++) ;
590 rf2.dwMerit = list->merit;
592 rf2.u.s1.rgPins2 = prfp2 = (REGFILTERPINS2*) CoTaskMemAlloc(i*sizeof(REGFILTERPINS2));
597 for (i = 0; list->pins[i].flags != 0xFFFFFFFF; i++) {
598 REGPINTYPES* lpMediatype;
602 for (nbmt = 0; list->pins[i].mediatypes[nbmt].majortype; nbmt++) ;
603 /* Allocate a single buffer for regpintypes struct and clsids */
604 lpMediatype = (REGPINTYPES*) CoTaskMemAlloc(nbmt*(sizeof(REGPINTYPES) + 2*sizeof(CLSID)));
609 lpClsid = (CLSID*) (lpMediatype + nbmt);
610 for (j = 0; j < nbmt; j++) {
611 (lpMediatype + j)->clsMajorType = lpClsid + j*2;
612 memcpy(lpClsid + j*2, list->pins[i].mediatypes[j].majortype, sizeof(CLSID));
613 (lpMediatype + j)->clsMinorType = lpClsid + j*2 + 1;
614 if (list->pins[i].mediatypes[j].subtype)
615 memcpy(lpClsid + j*2 + 1, list->pins[i].mediatypes[j].subtype, sizeof(CLSID));
617 /* Subtype are often a combination of major type + fourcc/tag */
618 memcpy(lpClsid + j*2 + 1, list->pins[i].mediatypes[j].majortype, sizeof(CLSID));
619 *(DWORD*)(lpClsid + j*2 + 1) = list->pins[i].mediatypes[j].fourcc;
622 prfp2[i].dwFlags = list->pins[i].flags;
623 prfp2[i].cInstances = 0;
624 prfp2[i].nMediaTypes = j;
625 prfp2[i].lpMediaType = lpMediatype;
626 prfp2[i].nMediums = 0;
627 prfp2[i].lpMedium = NULL;
628 prfp2[i].clsPinCategory = NULL;
632 ERR("failed to register with hresult 0x%lx\n", hr);
633 CoTaskMemFree(prfp2);
637 hr = IFilterMapper2_RegisterFilter(pFM2, list->clsid, list->name, NULL, list->category, NULL, &rf2);
640 CoTaskMemFree((REGPINTYPES*)prfp2[i-1].lpMediaType);
643 CoTaskMemFree(prfp2);
648 IFilterMapper2_Release(pFM2);
655 /***********************************************************************
658 static HRESULT unregister_filters(struct regsvr_filter const *list)
661 IFilterMapper2* pFM2;
665 hr = CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC_SERVER, &IID_IFilterMapper2, (LPVOID*)&pFM2);
668 for (; SUCCEEDED(hr) && list->clsid; ++list)
669 hr = IFilterMapper2_UnregisterFilter(pFM2, list->category, NULL, list->clsid);
670 IFilterMapper2_Release(pFM2);
678 /***********************************************************************
681 static LONG register_key_guid(HKEY base, WCHAR const *name, GUID const *guid)
685 StringFromGUID2(guid, buf, 39);
686 return register_key_defvalueW(base, name, buf);
689 /***********************************************************************
690 * regsvr_key_defvalueW
692 static LONG register_key_defvalueW(
700 res = RegCreateKeyExW(base, name, 0, NULL, 0,
701 KEY_READ | KEY_WRITE, NULL, &key, NULL);
702 if (res != ERROR_SUCCESS) return res;
703 res = RegSetValueExW(key, NULL, 0, REG_SZ, (CONST BYTE*)value,
704 (lstrlenW(value) + 1) * sizeof(WCHAR));
709 /***********************************************************************
710 * regsvr_key_defvalueA
712 static LONG register_key_defvalueA(
720 res = RegCreateKeyExW(base, name, 0, NULL, 0,
721 KEY_READ | KEY_WRITE, NULL, &key, NULL);
722 if (res != ERROR_SUCCESS) return res;
723 res = RegSetValueExA(key, NULL, 0, REG_SZ, (CONST BYTE*)value,
724 lstrlenA(value) + 1);
729 /***********************************************************************
732 static LONG register_progid(
735 char const *curver_progid,
742 res = RegCreateKeyExA(HKEY_CLASSES_ROOT, progid, 0,
743 NULL, 0, KEY_READ | KEY_WRITE, NULL,
745 if (res != ERROR_SUCCESS) return res;
748 res = RegSetValueExA(progid_key, NULL, 0, REG_SZ,
749 (CONST BYTE*)name, strlen(name) + 1);
750 if (res != ERROR_SUCCESS) goto error_close_progid_key;
754 res = register_key_defvalueW(progid_key, clsid_keyname, clsid);
755 if (res != ERROR_SUCCESS) goto error_close_progid_key;
759 res = register_key_defvalueA(progid_key, curver_keyname,
761 if (res != ERROR_SUCCESS) goto error_close_progid_key;
767 res = RegCreateKeyExA(progid_key, extra, 0,
768 NULL, 0, KEY_READ | KEY_WRITE, NULL,
770 if (res == ERROR_SUCCESS)
771 RegCloseKey(extra_key);
774 error_close_progid_key:
775 RegCloseKey(progid_key);
779 /***********************************************************************
780 * recursive_delete_key
782 static LONG recursive_delete_key(HKEY key)
785 WCHAR subkey_name[MAX_PATH];
790 cName = sizeof(subkey_name) / sizeof(WCHAR);
791 res = RegEnumKeyExW(key, 0, subkey_name, &cName,
792 NULL, NULL, NULL, NULL);
793 if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) {
794 res = ERROR_SUCCESS; /* presumably we're done enumerating */
797 res = RegOpenKeyExW(key, subkey_name, 0,
798 KEY_READ | KEY_WRITE, &subkey);
799 if (res == ERROR_FILE_NOT_FOUND) continue;
800 if (res != ERROR_SUCCESS) break;
802 res = recursive_delete_key(subkey);
804 if (res != ERROR_SUCCESS) break;
807 if (res == ERROR_SUCCESS) res = RegDeleteKeyW(key, 0);
811 /***********************************************************************
812 * recursive_delete_keyA
814 static LONG recursive_delete_keyA(HKEY base, char const *name)
819 res = RegOpenKeyExA(base, name, 0, KEY_READ | KEY_WRITE, &key);
820 if (res == ERROR_FILE_NOT_FOUND) return ERROR_SUCCESS;
821 if (res != ERROR_SUCCESS) return res;
822 res = recursive_delete_key(key);
827 /***********************************************************************
828 * recursive_delete_keyW
830 static LONG recursive_delete_keyW(HKEY base, WCHAR const *name)
835 res = RegOpenKeyExW(base, name, 0, KEY_READ | KEY_WRITE, &key);
836 if (res == ERROR_FILE_NOT_FOUND) return ERROR_SUCCESS;
837 if (res != ERROR_SUCCESS) return res;
838 res = recursive_delete_key(key);
844 static GUID const CLSID_PSFactoryBuffer = {
845 0x92a3a302, 0xda7c, 0x4a1f, {0xba,0x7e,0x18,0x02,0xbb,0x5d,0x2d,0x02} };
847 /***********************************************************************
850 static struct regsvr_coclass const coclass_list[] = {
851 { &CLSID_FilterGraph,
857 { &CLSID_FilterGraphNoThread,
863 { &CLSID_FilterMapper,
869 { &CLSID_FilterMapper2,
875 { &CLSID_SystemClock,
881 { &CLSID_MemoryAllocator,
887 { &CLSID_SeekingPassThru,
893 { &CLSID_AsyncReader,
894 "File Source Filter",
899 { &CLSID_AviSplitter,
911 { &CLSID_DSoundRender,
912 "DirectSound Audio Renderer",
917 { &CLSID_VideoRenderer,
935 { NULL } /* list terminator */
938 /***********************************************************************
942 static struct regsvr_interface const interface_list[] = {
948 &CLSID_PSFactoryBuffer
950 { &IID_IFilterGraph2,
955 &CLSID_PSFactoryBuffer
957 { &IID_IFilterMapper,
962 &CLSID_PSFactoryBuffer
964 { &IID_IFilterMapper2,
969 &CLSID_PSFactoryBuffer
972 { &IID_SeekingPassThru,
977 &CLSID_PSFactoryBuffer
984 &CLSID_PSFactoryBuffer
991 &CLSID_PSFactoryBuffer
993 { NULL } /* list terminator */
996 /***********************************************************************
1000 static struct regsvr_mediatype_parsing const mediatype_parsing_list[] = {
1001 { &MEDIATYPE_Stream,
1003 { "0,4,,52494646,8,4,,41564920",
1006 { &MEDIATYPE_Stream,
1007 &MEDIASUBTYPE_MPEG1System,
1008 { "0, 16, FFFFFFFFF100010001800001FFFFFFFF, 000001BA2100010001800001000001BB",
1011 { &MEDIATYPE_Stream,
1012 &MEDIASUBTYPE_MPEG1VideoCD,
1013 { "0, 4, , 52494646, 8, 8, , 43445841666D7420, 36, 20, FFFFFFFF00000000FFFFFFFFFFFFFFFFFFFFFFFF, 646174610000000000FFFFFFFFFFFFFFFFFFFF00",
1016 { &MEDIATYPE_Stream,
1017 &MEDIASUBTYPE_MPEG1Video,
1018 { "0, 4, , 000001B3",
1021 { &MEDIATYPE_Stream,
1022 &MEDIASUBTYPE_MPEG1Audio,
1023 { "0, 2, FFE0, FFE0",
1024 "0, 10, FFFFFFFF000000000000, 494433030080808080",
1027 { &MEDIATYPE_Stream,
1028 &MEDIASUBTYPE_QTMovie,
1029 { "4, 4, , 6d646174",
1033 { &MEDIATYPE_Stream,
1035 { "0,4,,52494646,8,4,,57415645",
1038 { &MEDIATYPE_Stream,
1043 { &MEDIATYPE_Stream,
1045 { "0,4,,464f524d,8,4,,41494646",
1046 "0,4,,464f524d,8,4,,41494643",
1049 { &MEDIATYPE_Stream,
1055 { &MEDIATYPE_Stream,
1057 { "0,4,,52494646,8,4,,524D4944",
1061 { NULL } /* list terminator */
1064 /***********************************************************************
1068 static struct regsvr_mediatype_extension const mediatype_extension_list[] = {
1069 { &MEDIATYPE_Stream,
1070 &MEDIASUBTYPE_MPEG1Audio,
1073 { NULL } /* list terminator */
1076 /***********************************************************************
1080 static struct regsvr_filter const filter_list[] = {
1081 { &CLSID_AviSplitter,
1082 &CLSID_LegacyAmFilterCategory,
1083 {'A','V','I',' ','S','p','l','i','t','t','e','r',0},
1086 { { &MEDIATYPE_Stream, &MEDIASUBTYPE_Avi },
1090 { REG_PINFLAG_B_OUTPUT,
1091 { { &MEDIATYPE_Video, &GUID_NULL },
1098 { &CLSID_VideoRenderer,
1099 &CLSID_LegacyAmFilterCategory,
1100 {'V','i','d','e','o',' ','R','e','n','d','e','r','e','r',0},
1102 { { REG_PINFLAG_B_RENDERER,
1103 { { &MEDIATYPE_Video, &GUID_NULL },
1111 &CLSID_LegacyAmFilterCategory,
1112 {'A','V','I',' ','D','e','c','o','m','p','r','e','s','s','o','r',0},
1115 { { &MEDIATYPE_Video, &GUID_NULL },
1119 { REG_PINFLAG_B_OUTPUT,
1120 { { &MEDIATYPE_Video, &GUID_NULL },
1127 { &CLSID_AsyncReader,
1128 &CLSID_LegacyAmFilterCategory,
1129 {'F','i','l','e',' ','S','o','u','r','c','e',' ','(','A','s','y','n','c','.',')',0},
1131 { { REG_PINFLAG_B_OUTPUT,
1132 { { &MEDIATYPE_Stream, &GUID_NULL },
1139 { &CLSID_ACMWrapper,
1140 &CLSID_LegacyAmFilterCategory,
1141 {'A','C','M',' ','W','r','a','p','p','e','r',0},
1144 { { &MEDIATYPE_Audio, &GUID_NULL },
1148 { REG_PINFLAG_B_OUTPUT,
1149 { { &MEDIATYPE_Audio, &GUID_NULL },
1156 { &CLSID_WAVEParser,
1157 &CLSID_LegacyAmFilterCategory,
1158 {'W','a','v','e',' ','P','a','r','s','e','r',0},
1161 { { &MEDIATYPE_Stream, &MEDIASUBTYPE_WAVE },
1162 { &MEDIATYPE_Stream, &MEDIASUBTYPE_AU },
1163 { &MEDIATYPE_Stream, &MEDIASUBTYPE_AIFF },
1167 { REG_PINFLAG_B_OUTPUT,
1168 { { &MEDIATYPE_Audio, &GUID_NULL },
1175 { NULL } /* list terminator */
1178 /***********************************************************************
1179 * DllRegisterServer (QUARTZ.@)
1181 HRESULT WINAPI DllRegisterServer(void)
1187 hr = register_coclasses(coclass_list);
1189 hr = register_interfaces(interface_list);
1191 hr = register_mediatypes_parsing(mediatype_parsing_list);
1193 hr = register_mediatypes_extension(mediatype_extension_list);
1195 hr = register_filters(filter_list);
1199 /***********************************************************************
1200 * DllUnregisterServer (QUARTZ.@)
1202 HRESULT WINAPI DllUnregisterServer(void)
1208 hr = unregister_filters(filter_list);
1210 hr = unregister_coclasses(coclass_list);
1212 hr = unregister_interfaces(interface_list);
1214 hr = unregister_mediatypes_parsing(mediatype_parsing_list);
1216 hr = unregister_mediatypes_extension(mediatype_extension_list);