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 WCHAR
const interface_keyname
[10] = {
128 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c', 'e', 0 };
129 static WCHAR
const base_ifa_keyname
[14] = {
130 'B', 'a', 's', 'e', 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c',
132 static WCHAR
const num_methods_keyname
[11] = {
133 'N', 'u', 'm', 'M', 'e', 't', 'h', 'o', 'd', 's', 0 };
134 static WCHAR
const ps_clsid_keyname
[15] = {
135 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
137 static WCHAR
const ps_clsid32_keyname
[17] = {
138 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
139 'i', 'd', '3', '2', 0 };
140 static WCHAR
const clsid_keyname
[6] = {
141 'C', 'L', 'S', 'I', 'D', 0 };
142 static WCHAR
const curver_keyname
[7] = {
143 'C', 'u', 'r', 'V', 'e', 'r', 0 };
144 static WCHAR
const ips_keyname
[13] = {
145 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
147 static WCHAR
const ips32_keyname
[15] = {
148 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
150 static WCHAR
const progid_keyname
[7] = {
151 'P', 'r', 'o', 'g', 'I', 'D', 0 };
152 static WCHAR
const viprogid_keyname
[25] = {
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 char const tmodel_valuename
[] = "ThreadingModel";
157 static WCHAR
const mediatype_name
[11] = {
158 'M', 'e', 'd', 'i', 'a', ' ', 'T', 'y', 'p', 'e', 0 };
159 static WCHAR
const subtype_valuename
[8] = {
160 'S', 'u', 'b', 't', 'y', 'p', 'e', 0 };
161 static WCHAR
const sourcefilter_valuename
[14] = {
162 'S', 'o', 'u', 'r', 'c', 'e', ' ', 'F', 'i', 'l', 't', 'e', 'r', 0 };
163 static WCHAR
const extensions_keyname
[11] = {
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
,
201 (CONST BYTE
*)(list
->name
),
202 strlen(list
->name
) + 1);
203 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
206 if (list
->base_iid
) {
207 res
= register_key_guid(iid_key
, base_ifa_keyname
, list
->base_iid
);
208 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
211 if (0 <= list
->num_methods
) {
212 static WCHAR
const fmt
[3] = { '%', 'd', 0 };
215 res
= RegCreateKeyExW(iid_key
, num_methods_keyname
, 0, NULL
, 0,
216 KEY_READ
| KEY_WRITE
, NULL
, &key
, NULL
);
217 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
219 sprintfW(buf
, fmt
, list
->num_methods
);
220 res
= RegSetValueExW(key
, NULL
, 0, REG_SZ
,
222 (lstrlenW(buf
) + 1) * sizeof(WCHAR
));
225 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
228 if (list
->ps_clsid
) {
229 res
= register_key_guid(iid_key
, ps_clsid_keyname
, list
->ps_clsid
);
230 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
233 if (list
->ps_clsid32
) {
234 res
= register_key_guid(iid_key
, ps_clsid32_keyname
, list
->ps_clsid32
);
235 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
239 RegCloseKey(iid_key
);
242 error_close_interface_key
:
243 RegCloseKey(interface_key
);
245 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
248 /***********************************************************************
249 * unregister_interfaces
251 static HRESULT
unregister_interfaces(struct regsvr_interface
const *list
)
253 LONG res
= ERROR_SUCCESS
;
256 res
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, interface_keyname
, 0,
257 KEY_READ
| KEY_WRITE
, &interface_key
);
258 if (res
== ERROR_FILE_NOT_FOUND
) return S_OK
;
259 if (res
!= ERROR_SUCCESS
) goto error_return
;
261 for (; res
== ERROR_SUCCESS
&& list
->iid
; ++list
) {
264 StringFromGUID2(list
->iid
, buf
, 39);
265 res
= RegDeleteTreeW(interface_key
, buf
);
266 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
269 RegCloseKey(interface_key
);
271 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
274 /***********************************************************************
277 static HRESULT
register_coclasses(struct regsvr_coclass
const *list
)
279 LONG res
= ERROR_SUCCESS
;
282 res
= RegCreateKeyExW(HKEY_CLASSES_ROOT
, clsid_keyname
, 0, NULL
, 0,
283 KEY_READ
| KEY_WRITE
, NULL
, &coclass_key
, NULL
);
284 if (res
!= ERROR_SUCCESS
) goto error_return
;
286 for (; res
== ERROR_SUCCESS
&& list
->clsid
; ++list
) {
290 StringFromGUID2(list
->clsid
, buf
, 39);
291 res
= RegCreateKeyExW(coclass_key
, buf
, 0, NULL
, 0,
292 KEY_READ
| KEY_WRITE
, NULL
, &clsid_key
, NULL
);
293 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
296 res
= RegSetValueExA(clsid_key
, NULL
, 0, REG_SZ
,
297 (CONST BYTE
*)(list
->name
),
298 strlen(list
->name
) + 1);
299 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
303 res
= register_key_defvalueA(clsid_key
, ips_keyname
, list
->ips
);
304 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
310 res
= RegCreateKeyExW(clsid_key
, ips32_keyname
, 0, NULL
, 0,
311 KEY_READ
| KEY_WRITE
, NULL
,
313 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
315 res
= RegSetValueExA(ips32_key
, NULL
, 0, REG_SZ
,
316 (CONST BYTE
*)list
->ips32
,
317 lstrlenA(list
->ips32
) + 1);
318 if (res
== ERROR_SUCCESS
&& list
->ips32_tmodel
)
319 res
= RegSetValueExA(ips32_key
, tmodel_valuename
, 0, REG_SZ
,
320 (CONST BYTE
*)list
->ips32_tmodel
,
321 strlen(list
->ips32_tmodel
) + 1);
322 RegCloseKey(ips32_key
);
323 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
327 res
= register_key_defvalueA(clsid_key
, progid_keyname
,
329 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
331 res
= register_progid(buf
, list
->progid
, NULL
,
332 list
->name
, list
->progid_extra
);
333 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
336 if (list
->viprogid
) {
337 res
= register_key_defvalueA(clsid_key
, viprogid_keyname
,
339 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
341 res
= register_progid(buf
, list
->viprogid
, list
->progid
,
342 list
->name
, list
->progid_extra
);
343 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
346 error_close_clsid_key
:
347 RegCloseKey(clsid_key
);
350 error_close_coclass_key
:
351 RegCloseKey(coclass_key
);
353 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
356 /***********************************************************************
357 * unregister_coclasses
359 static HRESULT
unregister_coclasses(struct regsvr_coclass
const *list
)
361 LONG res
= ERROR_SUCCESS
;
364 res
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, clsid_keyname
, 0,
365 KEY_READ
| KEY_WRITE
, &coclass_key
);
366 if (res
== ERROR_FILE_NOT_FOUND
) return S_OK
;
367 if (res
!= ERROR_SUCCESS
) goto error_return
;
369 for (; res
== ERROR_SUCCESS
&& list
->clsid
; ++list
) {
372 StringFromGUID2(list
->clsid
, buf
, 39);
373 res
= RegDeleteTreeW(coclass_key
, buf
);
374 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
375 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
378 res
= RegDeleteTreeA(HKEY_CLASSES_ROOT
, list
->progid
);
379 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
380 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
383 if (list
->viprogid
) {
384 res
= RegDeleteTreeA(HKEY_CLASSES_ROOT
, list
->viprogid
);
385 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
386 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
390 error_close_coclass_key
:
391 RegCloseKey(coclass_key
);
393 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
396 /***********************************************************************
397 * register_mediatypes_parsing
399 static HRESULT
register_mediatypes_parsing(struct regsvr_mediatype_parsing
const *list
)
401 LONG res
= ERROR_SUCCESS
;
406 res
= RegCreateKeyExW(HKEY_CLASSES_ROOT
, mediatype_name
, 0, NULL
, 0,
407 KEY_READ
| KEY_WRITE
, NULL
, &mediatype_key
, NULL
);
408 if (res
!= ERROR_SUCCESS
) return HRESULT_FROM_WIN32(res
);
410 for (; res
== ERROR_SUCCESS
&& list
->majortype
; ++list
) {
411 HKEY majortype_key
= NULL
;
412 HKEY subtype_key
= NULL
;
414 StringFromGUID2(list
->majortype
, buf
, 39);
415 res
= RegCreateKeyExW(mediatype_key
, buf
, 0, NULL
, 0,
416 KEY_READ
| KEY_WRITE
, NULL
, &majortype_key
, NULL
);
417 if (res
!= ERROR_SUCCESS
) goto error_close_keys
;
419 StringFromGUID2(list
->subtype
, buf
, 39);
420 res
= RegCreateKeyExW(majortype_key
, buf
, 0, NULL
, 0,
421 KEY_READ
| KEY_WRITE
, NULL
, &subtype_key
, NULL
);
422 if (res
!= ERROR_SUCCESS
) goto error_close_keys
;
424 StringFromGUID2(&CLSID_AsyncReader
, buf
, 39);
425 res
= RegSetValueExW(subtype_key
, sourcefilter_valuename
, 0, REG_SZ
, (CONST BYTE
*)buf
,
426 (lstrlenW(buf
) + 1) * sizeof(WCHAR
));
427 if (res
!= ERROR_SUCCESS
) goto error_close_keys
;
429 for(i
= 0; list
->line
[i
]; i
++) {
431 wsprintfA(buffer
, "%d", i
);
432 res
= RegSetValueExA(subtype_key
, buffer
, 0, REG_SZ
, (CONST BYTE
*)list
->line
[i
],
433 lstrlenA(list
->line
[i
]));
434 if (res
!= ERROR_SUCCESS
) goto error_close_keys
;
439 RegCloseKey(majortype_key
);
441 RegCloseKey(subtype_key
);
444 RegCloseKey(mediatype_key
);
446 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
449 /***********************************************************************
450 * register_mediatypes_extension
452 static HRESULT
register_mediatypes_extension(struct regsvr_mediatype_extension
const *list
)
454 LONG res
= ERROR_SUCCESS
;
456 HKEY extensions_root_key
= NULL
;
459 res
= RegCreateKeyExW(HKEY_CLASSES_ROOT
, mediatype_name
, 0, NULL
, 0,
460 KEY_READ
| KEY_WRITE
, NULL
, &mediatype_key
, NULL
);
461 if (res
!= ERROR_SUCCESS
) return HRESULT_FROM_WIN32(res
);
463 res
= RegCreateKeyExW(mediatype_key
, extensions_keyname
, 0, NULL
, 0,
464 KEY_READ
| KEY_WRITE
, NULL
, &extensions_root_key
, NULL
);
465 if (res
!= ERROR_SUCCESS
) goto error_return
;
467 for (; res
== ERROR_SUCCESS
&& list
->majortype
; ++list
) {
470 res
= RegCreateKeyExA(extensions_root_key
, list
->extension
, 0, NULL
, 0,
471 KEY_READ
| KEY_WRITE
, NULL
, &extension_key
, NULL
);
472 if (res
!= ERROR_SUCCESS
) break;
474 StringFromGUID2(list
->majortype
, buf
, 39);
475 res
= RegSetValueExW(extension_key
, mediatype_name
, 0, REG_SZ
, (CONST BYTE
*)buf
,
476 (lstrlenW(buf
) + 1) * sizeof(WCHAR
));
477 if (res
!= ERROR_SUCCESS
) goto error_close_key
;
479 StringFromGUID2(list
->subtype
, buf
, 39);
480 res
= RegSetValueExW(extension_key
, subtype_valuename
, 0, REG_SZ
, (CONST BYTE
*)buf
,
481 (lstrlenW(buf
) + 1) * sizeof(WCHAR
));
482 if (res
!= ERROR_SUCCESS
) goto error_close_key
;
484 StringFromGUID2(&CLSID_AsyncReader
, buf
, 39);
485 res
= RegSetValueExW(extension_key
, sourcefilter_valuename
, 0, REG_SZ
, (CONST BYTE
*)buf
,
486 (lstrlenW(buf
) + 1) * sizeof(WCHAR
));
487 if (res
!= ERROR_SUCCESS
) goto error_close_key
;
490 RegCloseKey(extension_key
);
494 RegCloseKey(mediatype_key
);
495 if (extensions_root_key
)
496 RegCloseKey(extensions_root_key
);
498 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
501 /***********************************************************************
502 * unregister_mediatypes_parsing
504 static HRESULT
unregister_mediatypes_parsing(struct regsvr_mediatype_parsing
const *list
)
511 res
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, mediatype_name
, 0,
512 KEY_READ
| KEY_WRITE
, &mediatype_key
);
513 if (res
== ERROR_FILE_NOT_FOUND
) return S_OK
;
514 if (res
!= ERROR_SUCCESS
) return HRESULT_FROM_WIN32(res
);
516 for (; res
== ERROR_SUCCESS
&& list
->majortype
; ++list
) {
517 StringFromGUID2(list
->majortype
, buf
, 39);
518 res
= RegOpenKeyExW(mediatype_key
, buf
, 0,
519 KEY_READ
| KEY_WRITE
, &majortype_key
);
520 if (res
== ERROR_FILE_NOT_FOUND
) {
524 if (res
!= ERROR_SUCCESS
) break;
526 StringFromGUID2(list
->subtype
, buf
, 39);
527 res
= RegDeleteTreeW(majortype_key
, buf
);
528 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
530 /* Removed majortype key if there is no more subtype key */
531 res
= RegDeleteKeyW(majortype_key
, 0);
532 if (res
== ERROR_ACCESS_DENIED
) res
= ERROR_SUCCESS
;
534 RegCloseKey(majortype_key
);
537 RegCloseKey(mediatype_key
);
539 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
542 /***********************************************************************
543 * unregister_mediatypes_extension
545 static HRESULT
unregister_mediatypes_extension(struct regsvr_mediatype_extension
const *list
)
549 HKEY extensions_root_key
= NULL
;
551 res
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, mediatype_name
, 0,
552 KEY_READ
| KEY_WRITE
, &mediatype_key
);
553 if (res
== ERROR_FILE_NOT_FOUND
) return S_OK
;
554 if (res
!= ERROR_SUCCESS
) return HRESULT_FROM_WIN32(res
);
556 res
= RegOpenKeyExW(mediatype_key
, extensions_keyname
, 0,
557 KEY_READ
| KEY_WRITE
, &extensions_root_key
);
558 if (res
== ERROR_FILE_NOT_FOUND
)
560 else if (res
== ERROR_SUCCESS
)
561 for (; res
== ERROR_SUCCESS
&& list
->majortype
; ++list
) {
562 res
= RegDeleteTreeA(extensions_root_key
, list
->extension
);
563 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
566 RegCloseKey(mediatype_key
);
567 if (extensions_root_key
)
568 RegCloseKey(extensions_root_key
);
570 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
573 /***********************************************************************
576 static HRESULT
register_filters(struct regsvr_filter
const *list
)
579 IFilterMapper2
* pFM2
= NULL
;
582 hr
= CoCreateInstance(&CLSID_FilterMapper2
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IFilterMapper2
, (LPVOID
*)&pFM2
);
585 for (; SUCCEEDED(hr
) && list
->clsid
; ++list
) {
587 REGFILTERPINS2
* prfp2
;
590 for (i
= 0; list
->pins
[i
].flags
!= 0xFFFFFFFF; i
++) ;
592 rf2
.dwMerit
= list
->merit
;
594 rf2
.u
.s1
.rgPins2
= prfp2
= CoTaskMemAlloc(i
*sizeof(REGFILTERPINS2
));
599 for (i
= 0; list
->pins
[i
].flags
!= 0xFFFFFFFF; i
++) {
600 REGPINTYPES
* lpMediatype
;
604 for (nbmt
= 0; list
->pins
[i
].mediatypes
[nbmt
].majortype
; nbmt
++) ;
605 /* Allocate a single buffer for regpintypes struct and clsids */
606 lpMediatype
= CoTaskMemAlloc(nbmt
*(sizeof(REGPINTYPES
) + 2*sizeof(CLSID
)));
611 lpClsid
= (CLSID
*) (lpMediatype
+ nbmt
);
612 for (j
= 0; j
< nbmt
; j
++) {
613 (lpMediatype
+ j
)->clsMajorType
= lpClsid
+ j
*2;
614 memcpy(lpClsid
+ j
*2, list
->pins
[i
].mediatypes
[j
].majortype
, sizeof(CLSID
));
615 (lpMediatype
+ j
)->clsMinorType
= lpClsid
+ j
*2 + 1;
616 if (list
->pins
[i
].mediatypes
[j
].subtype
)
617 memcpy(lpClsid
+ j
*2 + 1, list
->pins
[i
].mediatypes
[j
].subtype
, sizeof(CLSID
));
619 /* Subtype are often a combination of major type + fourcc/tag */
620 memcpy(lpClsid
+ j
*2 + 1, list
->pins
[i
].mediatypes
[j
].majortype
, sizeof(CLSID
));
621 *(DWORD
*)(lpClsid
+ j
*2 + 1) = list
->pins
[i
].mediatypes
[j
].fourcc
;
624 prfp2
[i
].dwFlags
= list
->pins
[i
].flags
;
625 prfp2
[i
].cInstances
= 0;
626 prfp2
[i
].nMediaTypes
= j
;
627 prfp2
[i
].lpMediaType
= lpMediatype
;
628 prfp2
[i
].nMediums
= 0;
629 prfp2
[i
].lpMedium
= NULL
;
630 prfp2
[i
].clsPinCategory
= NULL
;
634 ERR("failed to register with hresult 0x%x\n", hr
);
635 CoTaskMemFree(prfp2
);
639 hr
= IFilterMapper2_RegisterFilter(pFM2
, list
->clsid
, list
->name
, NULL
, list
->category
, NULL
, &rf2
);
642 CoTaskMemFree((REGPINTYPES
*)prfp2
[i
-1].lpMediaType
);
645 CoTaskMemFree(prfp2
);
650 IFilterMapper2_Release(pFM2
);
657 /***********************************************************************
660 static HRESULT
unregister_filters(struct regsvr_filter
const *list
)
663 IFilterMapper2
* pFM2
;
667 hr
= CoCreateInstance(&CLSID_FilterMapper2
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IFilterMapper2
, (LPVOID
*)&pFM2
);
670 for (; SUCCEEDED(hr
) && list
->clsid
; ++list
)
671 hr
= IFilterMapper2_UnregisterFilter(pFM2
, list
->category
, NULL
, list
->clsid
);
672 IFilterMapper2_Release(pFM2
);
680 /***********************************************************************
683 static LONG
register_key_guid(HKEY base
, WCHAR
const *name
, GUID
const *guid
)
687 StringFromGUID2(guid
, buf
, 39);
688 return register_key_defvalueW(base
, name
, buf
);
691 /***********************************************************************
692 * regsvr_key_defvalueW
694 static LONG
register_key_defvalueW(
702 res
= RegCreateKeyExW(base
, name
, 0, NULL
, 0,
703 KEY_READ
| KEY_WRITE
, NULL
, &key
, NULL
);
704 if (res
!= ERROR_SUCCESS
) return res
;
705 res
= RegSetValueExW(key
, NULL
, 0, REG_SZ
, (CONST BYTE
*)value
,
706 (lstrlenW(value
) + 1) * sizeof(WCHAR
));
711 /***********************************************************************
712 * regsvr_key_defvalueA
714 static LONG
register_key_defvalueA(
722 res
= RegCreateKeyExW(base
, name
, 0, NULL
, 0,
723 KEY_READ
| KEY_WRITE
, NULL
, &key
, NULL
);
724 if (res
!= ERROR_SUCCESS
) return res
;
725 res
= RegSetValueExA(key
, NULL
, 0, REG_SZ
, (CONST BYTE
*)value
,
726 lstrlenA(value
) + 1);
731 /***********************************************************************
734 static LONG
register_progid(
737 char const *curver_progid
,
744 res
= RegCreateKeyExA(HKEY_CLASSES_ROOT
, progid
, 0,
745 NULL
, 0, KEY_READ
| KEY_WRITE
, NULL
,
747 if (res
!= ERROR_SUCCESS
) return res
;
750 res
= RegSetValueExA(progid_key
, NULL
, 0, REG_SZ
,
751 (CONST BYTE
*)name
, strlen(name
) + 1);
752 if (res
!= ERROR_SUCCESS
) goto error_close_progid_key
;
756 res
= register_key_defvalueW(progid_key
, clsid_keyname
, clsid
);
757 if (res
!= ERROR_SUCCESS
) goto error_close_progid_key
;
761 res
= register_key_defvalueA(progid_key
, curver_keyname
,
763 if (res
!= ERROR_SUCCESS
) goto error_close_progid_key
;
769 res
= RegCreateKeyExA(progid_key
, extra
, 0,
770 NULL
, 0, KEY_READ
| KEY_WRITE
, NULL
,
772 if (res
== ERROR_SUCCESS
)
773 RegCloseKey(extra_key
);
776 error_close_progid_key
:
777 RegCloseKey(progid_key
);
781 static GUID
const CLSID_PSFactoryBuffer
= {
782 0x92a3a302, 0xda7c, 0x4a1f, {0xba,0x7e,0x18,0x02,0xbb,0x5d,0x2d,0x02} };
784 /***********************************************************************
787 static struct regsvr_coclass
const coclass_list
[] = {
788 { &CLSID_FilterGraph
,
794 { &CLSID_FilterGraphNoThread
,
800 { &CLSID_FilterMapper
,
806 { &CLSID_FilterMapper2
,
812 { &CLSID_SystemClock
,
818 { &CLSID_MemoryAllocator
,
824 { &CLSID_SeekingPassThru
,
830 { &CLSID_AsyncReader
,
831 "File Source Filter",
836 { &CLSID_AviSplitter
,
842 { &CLSID_MPEG1Splitter
,
843 "MPEG-I Stream Splitter",
854 { &CLSID_DSoundRender
,
855 "DirectSound Audio Renderer",
860 { &CLSID_AudioRender
,
861 "Wave Audio Renderer",
866 { &CLSID_NullRenderer
,
872 { &CLSID_VideoRenderer
,
878 { &CLSID_VideoRendererDefault
,
879 "Default Video Renderer",
896 { NULL
} /* list terminator */
899 /***********************************************************************
903 static struct regsvr_interface
const interface_list
[] = {
904 { NULL
} /* list terminator */
907 /***********************************************************************
911 static struct regsvr_mediatype_parsing
const mediatype_parsing_list
[] = {
914 { "0,4,,52494646,8,4,,41564920",
918 &MEDIASUBTYPE_MPEG1System
,
919 { "0, 16, FFFFFFFFF100010001800001FFFFFFFF, 000001BA2100010001800001000001BB",
923 &MEDIASUBTYPE_MPEG1VideoCD
,
924 { "0, 4, , 52494646, 8, 8, , 43445841666D7420, 36, 20, FFFFFFFF00000000FFFFFFFFFFFFFFFFFFFFFFFF, 646174610000000000FFFFFFFFFFFFFFFFFFFF00",
928 &MEDIASUBTYPE_MPEG1Video
,
929 { "0, 4, , 000001B3",
933 &MEDIASUBTYPE_MPEG1Audio
,
934 { "0, 2, FFE0, FFE0",
935 "0, 10, FFFFFF00000080808080, 494433000000000000",
939 &MEDIASUBTYPE_QTMovie
,
940 { "4, 4, , 6d646174",
946 { "0,4,,52494646,8,4,,57415645",
956 { "0,4,,464f524d,8,4,,41494646",
957 "0,4,,464f524d,8,4,,41494643",
968 { "0,4,,52494646,8,4,,524D4944",
972 { NULL
} /* list terminator */
975 /***********************************************************************
979 static struct regsvr_mediatype_extension
const mediatype_extension_list
[] = {
981 &MEDIASUBTYPE_MPEG1Audio
,
984 { NULL
} /* list terminator */
987 /***********************************************************************
991 static struct regsvr_filter
const filter_list
[] = {
992 { &CLSID_AviSplitter
,
993 &CLSID_LegacyAmFilterCategory
,
994 {'A','V','I',' ','S','p','l','i','t','t','e','r',0},
997 { { &MEDIATYPE_Stream
, &MEDIASUBTYPE_Avi
},
1001 { REG_PINFLAG_B_OUTPUT
,
1002 { { &MEDIATYPE_Video
, &GUID_NULL
},
1009 { &CLSID_MPEG1Splitter
,
1010 &CLSID_LegacyAmFilterCategory
,
1011 {'M','P','E','G','-','I',' ','S','t','r','e','a','m',' ','S','p','l','i','t','t','e','r',0},
1014 { { &MEDIATYPE_Stream
, &MEDIASUBTYPE_MPEG1Audio
},
1015 { &MEDIATYPE_Stream
, &MEDIASUBTYPE_MPEG1Video
},
1016 { &MEDIATYPE_Stream
, &MEDIASUBTYPE_MPEG1System
},
1017 { &MEDIATYPE_Stream
, &MEDIASUBTYPE_MPEG1VideoCD
},
1021 { REG_PINFLAG_B_OUTPUT
,
1022 { { &MEDIATYPE_Audio
, &MEDIASUBTYPE_MPEG1Packet
},
1023 { &MEDIATYPE_Audio
, &MEDIASUBTYPE_MPEG1AudioPayload
},
1027 { REG_PINFLAG_B_OUTPUT
,
1028 { { &MEDIATYPE_Video
, &MEDIASUBTYPE_MPEG1Packet
},
1029 { &MEDIATYPE_Video
, &MEDIASUBTYPE_MPEG1Payload
},
1036 { &CLSID_NullRenderer
,
1037 &CLSID_LegacyAmFilterCategory
,
1038 {'N','u','l','l',' ','R','e','n','d','e','r','e','r',0},
1040 { { REG_PINFLAG_B_RENDERER
,
1041 { { &MEDIATYPE_NULL
, &GUID_NULL
},
1048 { &CLSID_VideoRenderer
,
1049 &CLSID_LegacyAmFilterCategory
,
1050 {'V','i','d','e','o',' ','R','e','n','d','e','r','e','r',0},
1052 { { REG_PINFLAG_B_RENDERER
,
1053 { { &MEDIATYPE_Video
, &GUID_NULL
},
1060 { &CLSID_VideoRendererDefault
,
1061 &CLSID_LegacyAmFilterCategory
,
1062 {'V','i','d','e','o',' ','R','e','n','d','e','r','e','r',0},
1064 { { REG_PINFLAG_B_RENDERER
,
1065 { { &MEDIATYPE_Video
, &GUID_NULL
},
1072 { &CLSID_DSoundRender
,
1073 &CLSID_LegacyAmFilterCategory
,
1074 {'A','u','d','i','o',' ','R','e','n','d','e','r','e','r',0},
1076 { { REG_PINFLAG_B_RENDERER
,
1077 { { &MEDIATYPE_Audio
, &MEDIASUBTYPE_PCM
},
1078 /* { &MEDIATYPE_Audio, &MEDIASUBTYPE_IEEE_FLOAT }, */
1085 { &CLSID_AudioRender
,
1086 &CLSID_LegacyAmFilterCategory
,
1087 {'A','u','d','i','o',' ','R','e','n','d','e','r','e','r',0},
1089 { { REG_PINFLAG_B_RENDERER
,
1090 { { &MEDIATYPE_Audio
, &MEDIASUBTYPE_PCM
},
1091 /* { &MEDIATYPE_Audio, &MEDIASUBTYPE_IEEE_FLOAT }, */
1099 &CLSID_LegacyAmFilterCategory
,
1100 {'A','V','I',' ','D','e','c','o','m','p','r','e','s','s','o','r',0},
1103 { { &MEDIATYPE_Video
, &GUID_NULL
},
1107 { REG_PINFLAG_B_OUTPUT
,
1108 { { &MEDIATYPE_Video
, &GUID_NULL
},
1115 { &CLSID_AsyncReader
,
1116 &CLSID_LegacyAmFilterCategory
,
1117 {'F','i','l','e',' ','S','o','u','r','c','e',' ','(','A','s','y','n','c','.',')',0},
1119 { { REG_PINFLAG_B_OUTPUT
,
1120 { { &MEDIATYPE_Stream
, &GUID_NULL
},
1127 { &CLSID_ACMWrapper
,
1128 &CLSID_LegacyAmFilterCategory
,
1129 {'A','C','M',' ','W','r','a','p','p','e','r',0},
1132 { { &MEDIATYPE_Audio
, &GUID_NULL
},
1136 { REG_PINFLAG_B_OUTPUT
,
1137 { { &MEDIATYPE_Audio
, &GUID_NULL
},
1144 { &CLSID_WAVEParser
,
1145 &CLSID_LegacyAmFilterCategory
,
1146 {'W','a','v','e',' ','P','a','r','s','e','r',0},
1149 { { &MEDIATYPE_Stream
, &MEDIASUBTYPE_WAVE
},
1150 { &MEDIATYPE_Stream
, &MEDIASUBTYPE_AU
},
1151 { &MEDIATYPE_Stream
, &MEDIASUBTYPE_AIFF
},
1155 { REG_PINFLAG_B_OUTPUT
,
1156 { { &MEDIATYPE_Audio
, &GUID_NULL
},
1163 { NULL
} /* list terminator */
1166 extern HRESULT WINAPI
QUARTZ_DllRegisterServer(void) DECLSPEC_HIDDEN
;
1167 extern HRESULT WINAPI
QUARTZ_DllUnregisterServer(void) DECLSPEC_HIDDEN
;
1169 /***********************************************************************
1170 * DllRegisterServer (QUARTZ.@)
1172 HRESULT WINAPI
DllRegisterServer(void)
1178 hr
= QUARTZ_DllRegisterServer();
1180 hr
= register_coclasses(coclass_list
);
1182 hr
= register_interfaces(interface_list
);
1184 hr
= register_mediatypes_parsing(mediatype_parsing_list
);
1186 hr
= register_mediatypes_extension(mediatype_extension_list
);
1188 hr
= register_filters(filter_list
);
1192 /***********************************************************************
1193 * DllUnregisterServer (QUARTZ.@)
1195 HRESULT WINAPI
DllUnregisterServer(void)
1201 hr
= unregister_filters(filter_list
);
1203 hr
= unregister_coclasses(coclass_list
);
1205 hr
= unregister_interfaces(interface_list
);
1207 hr
= unregister_mediatypes_parsing(mediatype_parsing_list
);
1209 hr
= unregister_mediatypes_extension(mediatype_extension_list
);
1211 hr
= QUARTZ_DllUnregisterServer();