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
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
);
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 */
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 */
98 CLSID
const *majortype
; /* NULL for end of list */
105 DWORD flags
; /* 0xFFFFFFFF for end of list */
106 struct mediatype mediatypes
[11];
111 CLSID
const *clsid
; /* NULL for end of list */
112 CLSID
const *category
;
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',
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',
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',
147 static const WCHAR ips32_keyname
[] = {
148 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
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',
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
,
172 static LONG
register_key_defvalueA(HKEY base
, WCHAR
const *name
,
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
;
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
) {
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
;
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 };
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
));
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
;
237 RegCloseKey(iid_key
);
240 error_close_interface_key
:
241 RegCloseKey(interface_key
);
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
;
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
) {
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
);
269 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
272 /***********************************************************************
275 static HRESULT
register_coclasses(struct regsvr_coclass
const *list
)
277 LONG res
= ERROR_SUCCESS
;
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
) {
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
;
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
;
300 res
= register_key_defvalueA(clsid_key
, ips_keyname
, list
->ips
);
301 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
307 res
= RegCreateKeyExW(clsid_key
, ips32_keyname
, 0, NULL
, 0,
308 KEY_READ
| KEY_WRITE
, 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
;
323 res
= register_key_defvalueA(clsid_key
, progid_keyname
,
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
,
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
);
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
;
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
) {
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
;
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
);
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
;
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
++) {
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
;
435 RegCloseKey(majortype_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
;
452 HKEY extensions_root_key
= NULL
;
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
) {
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
;
486 RegCloseKey(extension_key
);
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
)
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
) {
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
)
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
)
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 /***********************************************************************
572 static HRESULT
register_filters(struct regsvr_filter
const *list
)
575 IFilterMapper2
* pFM2
= NULL
;
578 hr
= CoCreateInstance(&CLSID_FilterMapper2
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IFilterMapper2
, (LPVOID
*)&pFM2
);
581 for (; SUCCEEDED(hr
) && list
->clsid
; ++list
) {
583 REGFILTERPINS2
* prfp2
;
586 for (i
= 0; list
->pins
[i
].flags
!= 0xFFFFFFFF; i
++) ;
588 rf2
.dwMerit
= list
->merit
;
590 rf2
.u
.s2
.rgPins2
= prfp2
= CoTaskMemAlloc(i
*sizeof(REGFILTERPINS2
));
595 for (i
= 0; list
->pins
[i
].flags
!= 0xFFFFFFFF; i
++) {
596 REGPINTYPES
* lpMediatype
;
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
)));
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
));
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
;
630 ERR("failed to register with hresult 0x%x\n", hr
);
631 CoTaskMemFree(prfp2
);
635 hr
= IFilterMapper2_RegisterFilter(pFM2
, list
->clsid
, list
->name
, NULL
, list
->category
, NULL
, &rf2
);
638 CoTaskMemFree((REGPINTYPES
*)prfp2
[i
-1].lpMediaType
);
641 CoTaskMemFree(prfp2
);
646 IFilterMapper2_Release(pFM2
);
653 /***********************************************************************
656 static HRESULT
unregister_filters(struct regsvr_filter
const *list
)
659 IFilterMapper2
* pFM2
;
663 hr
= CoCreateInstance(&CLSID_FilterMapper2
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IFilterMapper2
, (LPVOID
*)&pFM2
);
666 for (; SUCCEEDED(hr
) && list
->clsid
; ++list
)
667 hr
= IFilterMapper2_UnregisterFilter(pFM2
, list
->category
, NULL
, list
->clsid
);
668 IFilterMapper2_Release(pFM2
);
676 /***********************************************************************
679 static LONG
register_key_guid(HKEY base
, WCHAR
const *name
, GUID
const *guid
)
683 StringFromGUID2(guid
, buf
, 39);
684 return register_key_defvalueW(base
, name
, buf
);
687 /***********************************************************************
688 * regsvr_key_defvalueW
690 static LONG
register_key_defvalueW(
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
));
707 /***********************************************************************
708 * regsvr_key_defvalueA
710 static LONG
register_key_defvalueA(
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);
726 /***********************************************************************
729 static LONG
register_progid(
732 char const *curver_progid
,
739 res
= RegCreateKeyExA(HKEY_CLASSES_ROOT
, progid
, 0,
740 NULL
, 0, KEY_READ
| KEY_WRITE
, NULL
,
742 if (res
!= ERROR_SUCCESS
) return res
;
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
;
750 res
= register_key_defvalueW(progid_key
, clsid_keyname
, clsid
);
751 if (res
!= ERROR_SUCCESS
) goto error_close_progid_key
;
755 res
= register_key_defvalueA(progid_key
, curver_keyname
,
757 if (res
!= ERROR_SUCCESS
) goto error_close_progid_key
;
763 res
= RegCreateKeyExA(progid_key
, extra
, 0,
764 NULL
, 0, KEY_READ
| KEY_WRITE
, NULL
,
766 if (res
== ERROR_SUCCESS
)
767 RegCloseKey(extra_key
);
770 error_close_progid_key
:
771 RegCloseKey(progid_key
);
775 /***********************************************************************
778 static struct regsvr_coclass
const coclass_list
[] = {
779 { NULL
} /* list terminator */
782 /***********************************************************************
786 static struct regsvr_interface
const interface_list
[] = {
787 { NULL
} /* list terminator */
790 /***********************************************************************
794 static struct regsvr_mediatype_parsing
const mediatype_parsing_list
[] = {
797 { "0,4,,52494646,8,4,,41564920",
801 &MEDIASUBTYPE_MPEG1System
,
802 { "0, 16, FFFFFFFFF100010001800001FFFFFFFF, 000001BA2100010001800001000001BB",
806 &MEDIASUBTYPE_MPEG1VideoCD
,
807 { "0, 4, , 52494646, 8, 8, , 43445841666D7420, 36, 20, FFFFFFFF00000000FFFFFFFFFFFFFFFFFFFFFFFF, 646174610000000000FFFFFFFFFFFFFFFFFFFF00",
811 &MEDIASUBTYPE_MPEG1Video
,
812 { "0, 4, , 000001B3",
816 &MEDIASUBTYPE_MPEG1Audio
,
817 { "0, 2, FFE0, FFE0",
818 "0, 10, FFFFFF00000080808080, 494433000000000000",
822 &MEDIASUBTYPE_MPEG2_PROGRAM
,
823 { "0, 5, FFFFFFFFC0, 000001BA40",
827 &MEDIASUBTYPE_QTMovie
,
828 { "4, 4, , 6d646174",
834 { "0,4,,52494646,8,4,,57415645",
844 { "0,4,,464f524d,8,4,,41494646",
845 "0,4,,464f524d,8,4,,41494643",
856 { "0,4,,52494646,8,4,,524D4944",
860 { NULL
} /* list terminator */
863 /***********************************************************************
867 static struct regsvr_mediatype_extension
const mediatype_extension_list
[] = {
869 &MEDIASUBTYPE_MPEG1Audio
,
872 { NULL
} /* list terminator */
875 /***********************************************************************
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},
885 { { &MEDIATYPE_Stream
, &MEDIASUBTYPE_Avi
},
889 { REG_PINFLAG_B_OUTPUT
,
890 { { &MEDIATYPE_Video
, &GUID_NULL
},
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},
902 { { &MEDIATYPE_Stream
, &MEDIASUBTYPE_MPEG1Audio
},
903 { &MEDIATYPE_Stream
, &MEDIASUBTYPE_MPEG1Video
},
904 { &MEDIATYPE_Stream
, &MEDIASUBTYPE_MPEG1System
},
905 { &MEDIATYPE_Stream
, &MEDIASUBTYPE_MPEG1VideoCD
},
909 { REG_PINFLAG_B_OUTPUT
,
910 { { &MEDIATYPE_Audio
, &MEDIASUBTYPE_MPEG1Packet
},
911 { &MEDIATYPE_Audio
, &MEDIASUBTYPE_MPEG1AudioPayload
},
915 { REG_PINFLAG_B_OUTPUT
,
916 { { &MEDIATYPE_Video
, &MEDIASUBTYPE_MPEG1Packet
},
917 { &MEDIATYPE_Video
, &MEDIASUBTYPE_MPEG1Payload
},
924 { &CLSID_NullRenderer
,
925 &CLSID_LegacyAmFilterCategory
,
926 {'N','u','l','l',' ','R','e','n','d','e','r','e','r',0},
928 { { REG_PINFLAG_B_RENDERER
,
929 { { &MEDIATYPE_NULL
, &GUID_NULL
},
936 { &CLSID_VideoRenderer
,
937 &CLSID_LegacyAmFilterCategory
,
938 {'V','i','d','e','o',' ','R','e','n','d','e','r','e','r',0},
940 { { REG_PINFLAG_B_RENDERER
,
941 { { &MEDIATYPE_Video
, &GUID_NULL
},
948 { &CLSID_VideoRendererDefault
,
949 &CLSID_LegacyAmFilterCategory
,
950 {'V','i','d','e','o',' ','R','e','n','d','e','r','e','r',0},
952 { { REG_PINFLAG_B_RENDERER
,
953 { { &MEDIATYPE_Video
, &GUID_NULL
},
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},
964 { { REG_PINFLAG_B_RENDERER
,
965 { { &MEDIATYPE_Video
, &GUID_NULL
},
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},
976 { { REG_PINFLAG_B_RENDERER
,
977 { { &MEDIATYPE_Video
, &GUID_NULL
},
984 { &CLSID_DSoundRender
,
985 &CLSID_LegacyAmFilterCategory
,
986 {'A','u','d','i','o',' ','R','e','n','d','e','r','e','r',0},
988 { { REG_PINFLAG_B_RENDERER
,
989 { { &MEDIATYPE_Audio
, &MEDIASUBTYPE_PCM
},
990 /* { &MEDIATYPE_Audio, &MEDIASUBTYPE_IEEE_FLOAT }, */
997 { &CLSID_AudioRender
,
998 &CLSID_LegacyAmFilterCategory
,
999 {'A','u','d','i','o',' ','R','e','n','d','e','r','e','r',0},
1001 { { REG_PINFLAG_B_RENDERER
,
1002 { { &MEDIATYPE_Audio
, &MEDIASUBTYPE_PCM
},
1003 /* { &MEDIATYPE_Audio, &MEDIASUBTYPE_IEEE_FLOAT }, */
1011 &CLSID_LegacyAmFilterCategory
,
1012 {'A','V','I',' ','D','e','c','o','m','p','r','e','s','s','o','r',0},
1015 { { &MEDIATYPE_Video
, &GUID_NULL
},
1019 { REG_PINFLAG_B_OUTPUT
,
1020 { { &MEDIATYPE_Video
, &GUID_NULL
},
1027 { &CLSID_AsyncReader
,
1028 &CLSID_LegacyAmFilterCategory
,
1029 {'F','i','l','e',' ','S','o','u','r','c','e',' ','(','A','s','y','n','c','.',')',0},
1031 { { REG_PINFLAG_B_OUTPUT
,
1032 { { &MEDIATYPE_Stream
, &GUID_NULL
},
1039 { &CLSID_ACMWrapper
,
1040 &CLSID_LegacyAmFilterCategory
,
1041 {'A','C','M',' ','W','r','a','p','p','e','r',0},
1044 { { &MEDIATYPE_Audio
, &GUID_NULL
},
1048 { REG_PINFLAG_B_OUTPUT
,
1049 { { &MEDIATYPE_Audio
, &GUID_NULL
},
1056 { &CLSID_WAVEParser
,
1057 &CLSID_LegacyAmFilterCategory
,
1058 {'W','a','v','e',' ','P','a','r','s','e','r',0},
1061 { { &MEDIATYPE_Stream
, &MEDIASUBTYPE_WAVE
},
1062 { &MEDIATYPE_Stream
, &MEDIASUBTYPE_AU
},
1063 { &MEDIATYPE_Stream
, &MEDIASUBTYPE_AIFF
},
1067 { REG_PINFLAG_B_OUTPUT
,
1068 { { &MEDIATYPE_Audio
, &GUID_NULL
},
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)
1090 hr
= QUARTZ_DllRegisterServer();
1092 hr
= register_coclasses(coclass_list
);
1094 hr
= register_interfaces(interface_list
);
1096 hr
= register_mediatypes_parsing(mediatype_parsing_list
);
1098 hr
= register_mediatypes_extension(mediatype_extension_list
);
1100 hr
= register_filters(filter_list
);
1104 /***********************************************************************
1105 * DllUnregisterServer (QUARTZ.@)
1107 HRESULT WINAPI
DllUnregisterServer(void)
1113 hr
= unregister_filters(filter_list
);
1115 hr
= unregister_coclasses(coclass_list
);
1117 hr
= unregister_interfaces(interface_list
);
1119 hr
= unregister_mediatypes_parsing(mediatype_parsing_list
);
1121 hr
= unregister_mediatypes_extension(mediatype_extension_list
);
1123 hr
= QUARTZ_DllUnregisterServer();