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
37 #include "wine/debug.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(quartz
);
42 * Near the bottom of this file are the exported DllRegisterServer and
43 * DllUnregisterServer, which make all this worthwhile.
46 /***********************************************************************
47 * interface for self-registering
49 struct regsvr_interface
51 IID
const *iid
; /* NULL for end of list */
52 LPCSTR name
; /* can be NULL to omit */
53 IID
const *base_iid
; /* can be NULL to omit */
54 int num_methods
; /* can be <0 to omit */
55 CLSID
const *ps_clsid
; /* can be NULL to omit */
56 CLSID
const *ps_clsid32
; /* can be NULL to omit */
59 static HRESULT
register_interfaces(struct regsvr_interface
const *list
);
60 static HRESULT
unregister_interfaces(struct regsvr_interface
const *list
);
64 CLSID
const *clsid
; /* NULL for end of list */
65 LPCSTR name
; /* can be NULL to omit */
66 LPCSTR ips
; /* can be NULL to omit */
67 LPCSTR ips32
; /* can be NULL to omit */
68 LPCSTR ips32_tmodel
; /* can be NULL to omit */
69 LPCSTR progid
; /* can be NULL to omit */
70 LPCSTR viprogid
; /* can be NULL to omit */
71 LPCSTR progid_extra
; /* can be NULL to omit */
74 static HRESULT
register_coclasses(struct regsvr_coclass
const *list
);
75 static HRESULT
unregister_coclasses(struct regsvr_coclass
const *list
);
77 struct regsvr_mediatype_parsing
79 CLSID
const *majortype
; /* NULL for end of list */
81 LPCSTR line
[11]; /* NULL for end of list */
84 static HRESULT
register_mediatypes_parsing(struct regsvr_mediatype_parsing
const *list
);
85 static HRESULT
unregister_mediatypes_parsing(struct regsvr_mediatype_parsing
const *list
);
87 struct regsvr_mediatype_extension
89 CLSID
const *majortype
; /* NULL for end of list */
96 CLSID
const *majortype
; /* NULL for end of list */
103 DWORD flags
; /* 0xFFFFFFFF for end of list */
104 struct mediatype mediatypes
[11];
109 CLSID
const *clsid
; /* NULL for end of list */
110 CLSID
const *category
;
116 static HRESULT
register_mediatypes_extension(struct regsvr_mediatype_extension
const *list
);
117 static HRESULT
unregister_mediatypes_extension(struct regsvr_mediatype_extension
const *list
);
119 static HRESULT
register_filters(struct regsvr_filter
const *list
);
120 static HRESULT
unregister_filters(struct regsvr_filter
const *list
);
122 /***********************************************************************
123 * static string constants
125 static WCHAR
const interface_keyname
[10] = {
126 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c', 'e', 0 };
127 static WCHAR
const base_ifa_keyname
[14] = {
128 'B', 'a', 's', 'e', 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c',
130 static WCHAR
const num_methods_keyname
[11] = {
131 'N', 'u', 'm', 'M', 'e', 't', 'h', 'o', 'd', 's', 0 };
132 static WCHAR
const ps_clsid_keyname
[15] = {
133 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
135 static WCHAR
const ps_clsid32_keyname
[17] = {
136 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
137 'i', 'd', '3', '2', 0 };
138 static WCHAR
const clsid_keyname
[6] = {
139 'C', 'L', 'S', 'I', 'D', 0 };
140 static WCHAR
const curver_keyname
[7] = {
141 'C', 'u', 'r', 'V', 'e', 'r', 0 };
142 static WCHAR
const ips_keyname
[13] = {
143 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
145 static WCHAR
const ips32_keyname
[15] = {
146 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
148 static WCHAR
const progid_keyname
[7] = {
149 'P', 'r', 'o', 'g', 'I', 'D', 0 };
150 static WCHAR
const viprogid_keyname
[25] = {
151 'V', 'e', 'r', 's', 'i', 'o', 'n', 'I', 'n', 'd', 'e', 'p',
152 'e', 'n', 'd', 'e', 'n', 't', 'P', 'r', 'o', 'g', 'I', 'D',
154 static char const tmodel_valuename
[] = "ThreadingModel";
155 static WCHAR
const mediatype_name
[11] = {
156 'M', 'e', 'd', 'i', 'a', ' ', 'T', 'y', 'p', 'e', 0 };
157 static WCHAR
const subtype_valuename
[8] = {
158 'S', 'u', 'b', 't', 'y', 'p', 'e', 0 };
159 static WCHAR
const sourcefilter_valuename
[14] = {
160 'S', 'o', 'u', 'r', 'c', 'e', ' ', 'F', 'i', 'l', 't', 'e', 'r', 0 };
161 static WCHAR
const extensions_keyname
[11] = {
162 'E', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 's', 0 };
164 /***********************************************************************
165 * static helper functions
167 static LONG
register_key_guid(HKEY base
, WCHAR
const *name
, GUID
const *guid
);
168 static LONG
register_key_defvalueW(HKEY base
, WCHAR
const *name
,
170 static LONG
register_key_defvalueA(HKEY base
, WCHAR
const *name
,
172 static LONG
register_progid(WCHAR
const *clsid
,
173 char const *progid
, char const *curver_progid
,
174 char const *name
, char const *extra
);
175 static LONG
recursive_delete_key(HKEY key
);
176 static LONG
recursive_delete_keyA(HKEY base
, char const *name
);
177 static LONG
recursive_delete_keyW(HKEY base
, WCHAR
const *name
);
179 /***********************************************************************
180 * register_interfaces
182 static HRESULT
register_interfaces(struct regsvr_interface
const *list
)
184 LONG res
= ERROR_SUCCESS
;
187 res
= RegCreateKeyExW(HKEY_CLASSES_ROOT
, interface_keyname
, 0, NULL
, 0,
188 KEY_READ
| KEY_WRITE
, NULL
, &interface_key
, NULL
);
189 if (res
!= ERROR_SUCCESS
) goto error_return
;
191 for (; res
== ERROR_SUCCESS
&& list
->iid
; ++list
) {
195 StringFromGUID2(list
->iid
, buf
, 39);
196 res
= RegCreateKeyExW(interface_key
, buf
, 0, NULL
, 0,
197 KEY_READ
| KEY_WRITE
, NULL
, &iid_key
, NULL
);
198 if (res
!= ERROR_SUCCESS
) goto error_close_interface_key
;
201 res
= RegSetValueExA(iid_key
, NULL
, 0, REG_SZ
,
202 (CONST BYTE
*)(list
->name
),
203 strlen(list
->name
) + 1);
204 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
207 if (list
->base_iid
) {
208 res
= register_key_guid(iid_key
, base_ifa_keyname
, list
->base_iid
);
209 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
212 if (0 <= list
->num_methods
) {
213 static WCHAR
const fmt
[3] = { '%', 'd', 0 };
216 res
= RegCreateKeyExW(iid_key
, num_methods_keyname
, 0, NULL
, 0,
217 KEY_READ
| KEY_WRITE
, NULL
, &key
, NULL
);
218 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
220 wsprintfW(buf
, fmt
, list
->num_methods
);
221 res
= RegSetValueExW(key
, NULL
, 0, REG_SZ
,
223 (lstrlenW(buf
) + 1) * sizeof(WCHAR
));
226 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
229 if (list
->ps_clsid
) {
230 res
= register_key_guid(iid_key
, ps_clsid_keyname
, list
->ps_clsid
);
231 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
234 if (list
->ps_clsid32
) {
235 res
= register_key_guid(iid_key
, ps_clsid32_keyname
, list
->ps_clsid32
);
236 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
240 RegCloseKey(iid_key
);
243 error_close_interface_key
:
244 RegCloseKey(interface_key
);
246 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
249 /***********************************************************************
250 * unregister_interfaces
252 static HRESULT
unregister_interfaces(struct regsvr_interface
const *list
)
254 LONG res
= ERROR_SUCCESS
;
257 res
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, interface_keyname
, 0,
258 KEY_READ
| KEY_WRITE
, &interface_key
);
259 if (res
== ERROR_FILE_NOT_FOUND
) return S_OK
;
260 if (res
!= ERROR_SUCCESS
) goto error_return
;
262 for (; res
== ERROR_SUCCESS
&& list
->iid
; ++list
) {
265 StringFromGUID2(list
->iid
, buf
, 39);
266 res
= recursive_delete_keyW(interface_key
, buf
);
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
= recursive_delete_keyW(coclass_key
, buf
);
374 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
377 res
= recursive_delete_keyA(HKEY_CLASSES_ROOT
, list
->progid
);
378 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
381 if (list
->viprogid
) {
382 res
= recursive_delete_keyA(HKEY_CLASSES_ROOT
, list
->viprogid
);
383 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
387 error_close_coclass_key
:
388 RegCloseKey(coclass_key
);
390 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
393 /***********************************************************************
394 * register_mediatypes_parsing
396 static HRESULT
register_mediatypes_parsing(struct regsvr_mediatype_parsing
const *list
)
398 LONG res
= ERROR_SUCCESS
;
403 res
= RegCreateKeyExW(HKEY_CLASSES_ROOT
, mediatype_name
, 0, NULL
, 0,
404 KEY_READ
| KEY_WRITE
, NULL
, &mediatype_key
, NULL
);
405 if (res
!= ERROR_SUCCESS
) return HRESULT_FROM_WIN32(res
);
407 for (; res
== ERROR_SUCCESS
&& list
->majortype
; ++list
) {
408 HKEY majortype_key
= NULL
;
409 HKEY subtype_key
= NULL
;
411 StringFromGUID2(list
->majortype
, buf
, 39);
412 res
= RegCreateKeyExW(mediatype_key
, buf
, 0, NULL
, 0,
413 KEY_READ
| KEY_WRITE
, NULL
, &majortype_key
, NULL
);
414 if (res
!= ERROR_SUCCESS
) goto error_close_keys
;
416 StringFromGUID2(list
->subtype
, buf
, 39);
417 res
= RegCreateKeyExW(majortype_key
, buf
, 0, NULL
, 0,
418 KEY_READ
| KEY_WRITE
, NULL
, &subtype_key
, NULL
);
419 if (res
!= ERROR_SUCCESS
) goto error_close_keys
;
421 StringFromGUID2(&CLSID_AsyncReader
, buf
, 39);
422 res
= RegSetValueExW(subtype_key
, sourcefilter_valuename
, 0, REG_SZ
, (CONST BYTE
*)buf
,
423 (lstrlenW(buf
) + 1) * sizeof(WCHAR
));
424 if (res
!= ERROR_SUCCESS
) goto error_close_keys
;
426 for(i
= 0; list
->line
[i
]; i
++) {
428 wsprintfA(buffer
, "%d", i
);
429 res
= RegSetValueExA(subtype_key
, buffer
, 0, REG_SZ
, (CONST BYTE
*)list
->line
[i
],
430 lstrlenA(list
->line
[i
]));
431 if (res
!= ERROR_SUCCESS
) goto error_close_keys
;
436 RegCloseKey(majortype_key
);
438 RegCloseKey(subtype_key
);
441 RegCloseKey(mediatype_key
);
443 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
446 /***********************************************************************
447 * register_mediatypes_extension
449 static HRESULT
register_mediatypes_extension(struct regsvr_mediatype_extension
const *list
)
451 LONG res
= ERROR_SUCCESS
;
453 HKEY extensions_root_key
= NULL
;
456 res
= RegCreateKeyExW(HKEY_CLASSES_ROOT
, mediatype_name
, 0, NULL
, 0,
457 KEY_READ
| KEY_WRITE
, NULL
, &mediatype_key
, NULL
);
458 if (res
!= ERROR_SUCCESS
) return HRESULT_FROM_WIN32(res
);
460 res
= RegCreateKeyExW(mediatype_key
, extensions_keyname
, 0, NULL
, 0,
461 KEY_READ
| KEY_WRITE
, NULL
, &extensions_root_key
, NULL
);
462 if (res
!= ERROR_SUCCESS
) goto error_return
;
464 for (; res
== ERROR_SUCCESS
&& list
->majortype
; ++list
) {
467 res
= RegCreateKeyExA(extensions_root_key
, list
->extension
, 0, NULL
, 0,
468 KEY_READ
| KEY_WRITE
, NULL
, &extension_key
, NULL
);
469 if (res
!= ERROR_SUCCESS
) break;
471 StringFromGUID2(list
->majortype
, buf
, 39);
472 res
= RegSetValueExW(extension_key
, mediatype_name
, 0, REG_SZ
, (CONST BYTE
*)buf
,
473 (lstrlenW(buf
) + 1) * sizeof(WCHAR
));
474 if (res
!= ERROR_SUCCESS
) goto error_close_key
;
476 StringFromGUID2(list
->subtype
, buf
, 39);
477 res
= RegSetValueExW(extension_key
, subtype_valuename
, 0, REG_SZ
, (CONST BYTE
*)buf
,
478 (lstrlenW(buf
) + 1) * sizeof(WCHAR
));
479 if (res
!= ERROR_SUCCESS
) goto error_close_key
;
481 StringFromGUID2(&CLSID_AsyncReader
, buf
, 39);
482 res
= RegSetValueExW(extension_key
, sourcefilter_valuename
, 0, REG_SZ
, (CONST BYTE
*)buf
,
483 (lstrlenW(buf
) + 1) * sizeof(WCHAR
));
484 if (res
!= ERROR_SUCCESS
) goto error_close_key
;
487 RegCloseKey(extension_key
);
491 RegCloseKey(mediatype_key
);
492 if (extensions_root_key
)
493 RegCloseKey(extensions_root_key
);
495 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
498 /***********************************************************************
499 * unregister_mediatypes_parsing
501 static HRESULT
unregister_mediatypes_parsing(struct regsvr_mediatype_parsing
const *list
)
508 res
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, mediatype_name
, 0,
509 KEY_READ
| KEY_WRITE
, &mediatype_key
);
510 if (res
== ERROR_FILE_NOT_FOUND
) return S_OK
;
511 if (res
!= ERROR_SUCCESS
) return HRESULT_FROM_WIN32(res
);
513 for (; res
== ERROR_SUCCESS
&& list
->majortype
; ++list
) {
514 StringFromGUID2(list
->majortype
, buf
, 39);
515 res
= RegOpenKeyExW(mediatype_key
, buf
, 0,
516 KEY_READ
| KEY_WRITE
, &majortype_key
);
517 if (res
== ERROR_FILE_NOT_FOUND
) {
521 if (res
!= ERROR_SUCCESS
) break;
523 StringFromGUID2(list
->subtype
, buf
, 39);
524 res
= recursive_delete_keyW(majortype_key
, buf
);
525 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
527 /* Removed majortype key if there is no more subtype key */
528 res
= RegDeleteKeyW(majortype_key
, 0);
529 if (res
== ERROR_ACCESS_DENIED
) res
= ERROR_SUCCESS
;
531 RegCloseKey(majortype_key
);
534 RegCloseKey(mediatype_key
);
536 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
539 /***********************************************************************
540 * unregister_mediatypes_extension
542 static HRESULT
unregister_mediatypes_extension(struct regsvr_mediatype_extension
const *list
)
546 HKEY extensions_root_key
= NULL
;
548 res
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, mediatype_name
, 0,
549 KEY_READ
| KEY_WRITE
, &mediatype_key
);
550 if (res
== ERROR_FILE_NOT_FOUND
) return S_OK
;
551 if (res
!= ERROR_SUCCESS
) return HRESULT_FROM_WIN32(res
);
553 res
= RegOpenKeyExW(mediatype_key
, extensions_keyname
, 0,
554 KEY_READ
| KEY_WRITE
, &extensions_root_key
);
555 if (res
== ERROR_FILE_NOT_FOUND
)
557 else if (res
== ERROR_SUCCESS
)
558 for (; res
== ERROR_SUCCESS
&& list
->majortype
; ++list
) {
559 res
= recursive_delete_keyA(extensions_root_key
, list
->extension
);
560 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
563 RegCloseKey(mediatype_key
);
564 if (extensions_root_key
)
565 RegCloseKey(extensions_root_key
);
567 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
570 /***********************************************************************
573 static HRESULT
register_filters(struct regsvr_filter
const *list
)
576 IFilterMapper2
* pFM2
= NULL
;
579 hr
= CoCreateInstance(&CLSID_FilterMapper2
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IFilterMapper2
, (LPVOID
*)&pFM2
);
582 for (; SUCCEEDED(hr
) && list
->clsid
; ++list
) {
584 REGFILTERPINS2
* prfp2
;
587 for (i
= 0; list
->pins
[i
].flags
!= 0xFFFFFFFF; i
++) ;
589 rf2
.dwMerit
= list
->merit
;
591 rf2
.u
.s1
.rgPins2
= prfp2
= CoTaskMemAlloc(i
*sizeof(REGFILTERPINS2
));
596 for (i
= 0; list
->pins
[i
].flags
!= 0xFFFFFFFF; i
++) {
597 REGPINTYPES
* lpMediatype
;
601 for (nbmt
= 0; list
->pins
[i
].mediatypes
[nbmt
].majortype
; nbmt
++) ;
602 /* Allocate a single buffer for regpintypes struct and clsids */
603 lpMediatype
= CoTaskMemAlloc(nbmt
*(sizeof(REGPINTYPES
) + 2*sizeof(CLSID
)));
608 lpClsid
= (CLSID
*) (lpMediatype
+ nbmt
);
609 for (j
= 0; j
< nbmt
; j
++) {
610 (lpMediatype
+ j
)->clsMajorType
= lpClsid
+ j
*2;
611 memcpy(lpClsid
+ j
*2, list
->pins
[i
].mediatypes
[j
].majortype
, sizeof(CLSID
));
612 (lpMediatype
+ j
)->clsMinorType
= lpClsid
+ j
*2 + 1;
613 if (list
->pins
[i
].mediatypes
[j
].subtype
)
614 memcpy(lpClsid
+ j
*2 + 1, list
->pins
[i
].mediatypes
[j
].subtype
, sizeof(CLSID
));
616 /* Subtype are often a combination of major type + fourcc/tag */
617 memcpy(lpClsid
+ j
*2 + 1, list
->pins
[i
].mediatypes
[j
].majortype
, sizeof(CLSID
));
618 *(DWORD
*)(lpClsid
+ j
*2 + 1) = list
->pins
[i
].mediatypes
[j
].fourcc
;
621 prfp2
[i
].dwFlags
= list
->pins
[i
].flags
;
622 prfp2
[i
].cInstances
= 0;
623 prfp2
[i
].nMediaTypes
= j
;
624 prfp2
[i
].lpMediaType
= lpMediatype
;
625 prfp2
[i
].nMediums
= 0;
626 prfp2
[i
].lpMedium
= NULL
;
627 prfp2
[i
].clsPinCategory
= NULL
;
631 ERR("failed to register with hresult 0x%x\n", hr
);
632 CoTaskMemFree(prfp2
);
636 hr
= IFilterMapper2_RegisterFilter(pFM2
, list
->clsid
, list
->name
, NULL
, list
->category
, NULL
, &rf2
);
639 CoTaskMemFree((REGPINTYPES
*)prfp2
[i
-1].lpMediaType
);
642 CoTaskMemFree(prfp2
);
647 IFilterMapper2_Release(pFM2
);
654 /***********************************************************************
657 static HRESULT
unregister_filters(struct regsvr_filter
const *list
)
660 IFilterMapper2
* pFM2
;
664 hr
= CoCreateInstance(&CLSID_FilterMapper2
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IFilterMapper2
, (LPVOID
*)&pFM2
);
667 for (; SUCCEEDED(hr
) && list
->clsid
; ++list
)
668 hr
= IFilterMapper2_UnregisterFilter(pFM2
, list
->category
, NULL
, list
->clsid
);
669 IFilterMapper2_Release(pFM2
);
677 /***********************************************************************
680 static LONG
register_key_guid(HKEY base
, WCHAR
const *name
, GUID
const *guid
)
684 StringFromGUID2(guid
, buf
, 39);
685 return register_key_defvalueW(base
, name
, buf
);
688 /***********************************************************************
689 * regsvr_key_defvalueW
691 static LONG
register_key_defvalueW(
699 res
= RegCreateKeyExW(base
, name
, 0, NULL
, 0,
700 KEY_READ
| KEY_WRITE
, NULL
, &key
, NULL
);
701 if (res
!= ERROR_SUCCESS
) return res
;
702 res
= RegSetValueExW(key
, NULL
, 0, REG_SZ
, (CONST BYTE
*)value
,
703 (lstrlenW(value
) + 1) * sizeof(WCHAR
));
708 /***********************************************************************
709 * regsvr_key_defvalueA
711 static LONG
register_key_defvalueA(
719 res
= RegCreateKeyExW(base
, name
, 0, NULL
, 0,
720 KEY_READ
| KEY_WRITE
, NULL
, &key
, NULL
);
721 if (res
!= ERROR_SUCCESS
) return res
;
722 res
= RegSetValueExA(key
, NULL
, 0, REG_SZ
, (CONST BYTE
*)value
,
723 lstrlenA(value
) + 1);
728 /***********************************************************************
731 static LONG
register_progid(
734 char const *curver_progid
,
741 res
= RegCreateKeyExA(HKEY_CLASSES_ROOT
, progid
, 0,
742 NULL
, 0, KEY_READ
| KEY_WRITE
, NULL
,
744 if (res
!= ERROR_SUCCESS
) return res
;
747 res
= RegSetValueExA(progid_key
, NULL
, 0, REG_SZ
,
748 (CONST BYTE
*)name
, strlen(name
) + 1);
749 if (res
!= ERROR_SUCCESS
) goto error_close_progid_key
;
753 res
= register_key_defvalueW(progid_key
, clsid_keyname
, clsid
);
754 if (res
!= ERROR_SUCCESS
) goto error_close_progid_key
;
758 res
= register_key_defvalueA(progid_key
, curver_keyname
,
760 if (res
!= ERROR_SUCCESS
) goto error_close_progid_key
;
766 res
= RegCreateKeyExA(progid_key
, extra
, 0,
767 NULL
, 0, KEY_READ
| KEY_WRITE
, NULL
,
769 if (res
== ERROR_SUCCESS
)
770 RegCloseKey(extra_key
);
773 error_close_progid_key
:
774 RegCloseKey(progid_key
);
778 /***********************************************************************
779 * recursive_delete_key
781 static LONG
recursive_delete_key(HKEY key
)
784 WCHAR subkey_name
[MAX_PATH
];
789 cName
= sizeof(subkey_name
) / sizeof(WCHAR
);
790 res
= RegEnumKeyExW(key
, 0, subkey_name
, &cName
,
791 NULL
, NULL
, NULL
, NULL
);
792 if (res
!= ERROR_SUCCESS
&& res
!= ERROR_MORE_DATA
) {
793 res
= ERROR_SUCCESS
; /* presumably we're done enumerating */
796 res
= RegOpenKeyExW(key
, subkey_name
, 0,
797 KEY_READ
| KEY_WRITE
, &subkey
);
798 if (res
== ERROR_FILE_NOT_FOUND
) continue;
799 if (res
!= ERROR_SUCCESS
) break;
801 res
= recursive_delete_key(subkey
);
803 if (res
!= ERROR_SUCCESS
) break;
806 if (res
== ERROR_SUCCESS
) res
= RegDeleteKeyW(key
, 0);
810 /***********************************************************************
811 * recursive_delete_keyA
813 static LONG
recursive_delete_keyA(HKEY base
, char const *name
)
818 res
= RegOpenKeyExA(base
, name
, 0, KEY_READ
| KEY_WRITE
, &key
);
819 if (res
== ERROR_FILE_NOT_FOUND
) return ERROR_SUCCESS
;
820 if (res
!= ERROR_SUCCESS
) return res
;
821 res
= recursive_delete_key(key
);
826 /***********************************************************************
827 * recursive_delete_keyW
829 static LONG
recursive_delete_keyW(HKEY base
, WCHAR
const *name
)
834 res
= RegOpenKeyExW(base
, name
, 0, KEY_READ
| KEY_WRITE
, &key
);
835 if (res
== ERROR_FILE_NOT_FOUND
) return ERROR_SUCCESS
;
836 if (res
!= ERROR_SUCCESS
) return res
;
837 res
= recursive_delete_key(key
);
843 static GUID
const CLSID_PSFactoryBuffer
= {
844 0x92a3a302, 0xda7c, 0x4a1f, {0xba,0x7e,0x18,0x02,0xbb,0x5d,0x2d,0x02} };
846 /***********************************************************************
849 static struct regsvr_coclass
const coclass_list
[] = {
850 { &CLSID_FilterGraph
,
856 { &CLSID_FilterGraphNoThread
,
862 { &CLSID_FilterMapper
,
868 { &CLSID_FilterMapper2
,
874 { &CLSID_SystemClock
,
880 { &CLSID_MemoryAllocator
,
886 { &CLSID_SeekingPassThru
,
892 { &CLSID_AsyncReader
,
893 "File Source Filter",
898 { &CLSID_AviSplitter
,
904 { &CLSID_MPEG1Splitter
,
905 "MPEG-I Stream Splitter",
916 { &CLSID_DSoundRender
,
917 "DirectSound Audio Renderer",
922 { &CLSID_VideoRenderer
,
940 { NULL
} /* list terminator */
943 /***********************************************************************
947 static struct regsvr_interface
const interface_list
[] = {
953 &CLSID_PSFactoryBuffer
955 { &IID_IFilterGraph2
,
960 &CLSID_PSFactoryBuffer
962 { &IID_IFilterMapper
,
967 &CLSID_PSFactoryBuffer
969 { &IID_IFilterMapper2
,
974 &CLSID_PSFactoryBuffer
977 { &IID_SeekingPassThru,
982 &CLSID_PSFactoryBuffer
989 &CLSID_PSFactoryBuffer
996 &CLSID_PSFactoryBuffer
998 { NULL
} /* list terminator */
1001 /***********************************************************************
1005 static struct regsvr_mediatype_parsing
const mediatype_parsing_list
[] = {
1006 { &MEDIATYPE_Stream
,
1008 { "0,4,,52494646,8,4,,41564920",
1011 { &MEDIATYPE_Stream
,
1012 &MEDIASUBTYPE_MPEG1System
,
1013 { "0, 16, FFFFFFFFF100010001800001FFFFFFFF, 000001BA2100010001800001000001BB",
1016 { &MEDIATYPE_Stream
,
1017 &MEDIASUBTYPE_MPEG1VideoCD
,
1018 { "0, 4, , 52494646, 8, 8, , 43445841666D7420, 36, 20, FFFFFFFF00000000FFFFFFFFFFFFFFFFFFFFFFFF, 646174610000000000FFFFFFFFFFFFFFFFFFFF00",
1021 { &MEDIATYPE_Stream
,
1022 &MEDIASUBTYPE_MPEG1Video
,
1023 { "0, 4, , 000001B3",
1026 { &MEDIATYPE_Stream
,
1027 &MEDIASUBTYPE_MPEG1Audio
,
1028 { "0, 2, FFE0, FFE0",
1029 "0, 10, FFFFFFFF000000000000, 494433030080808080",
1032 { &MEDIATYPE_Stream
,
1033 &MEDIASUBTYPE_QTMovie
,
1034 { "4, 4, , 6d646174",
1038 { &MEDIATYPE_Stream
,
1040 { "0,4,,52494646,8,4,,57415645",
1043 { &MEDIATYPE_Stream
,
1048 { &MEDIATYPE_Stream
,
1050 { "0,4,,464f524d,8,4,,41494646",
1051 "0,4,,464f524d,8,4,,41494643",
1054 { &MEDIATYPE_Stream
,
1060 { &MEDIATYPE_Stream
,
1062 { "0,4,,52494646,8,4,,524D4944",
1066 { NULL
} /* list terminator */
1069 /***********************************************************************
1073 static struct regsvr_mediatype_extension
const mediatype_extension_list
[] = {
1074 { &MEDIATYPE_Stream
,
1075 &MEDIASUBTYPE_MPEG1Audio
,
1078 { NULL
} /* list terminator */
1081 /***********************************************************************
1085 static struct regsvr_filter
const filter_list
[] = {
1086 { &CLSID_AviSplitter
,
1087 &CLSID_LegacyAmFilterCategory
,
1088 {'A','V','I',' ','S','p','l','i','t','t','e','r',0},
1091 { { &MEDIATYPE_Stream
, &MEDIASUBTYPE_Avi
},
1095 { REG_PINFLAG_B_OUTPUT
,
1096 { { &MEDIATYPE_Video
, &GUID_NULL
},
1103 { &CLSID_MPEG1Splitter
,
1104 &CLSID_LegacyAmFilterCategory
,
1105 {'M','P','E','G','-','I',' ','S','t','r','e','a','m',' ','S','p','l','i','t','t','e','r',0},
1108 { { &MEDIATYPE_Stream
, &MEDIASUBTYPE_MPEG1Audio
},
1109 { &MEDIATYPE_Stream
, &MEDIASUBTYPE_MPEG1Video
},
1110 { &MEDIATYPE_Stream
, &MEDIASUBTYPE_MPEG1System
},
1111 { &MEDIATYPE_Stream
, &MEDIASUBTYPE_MPEG1VideoCD
},
1115 { REG_PINFLAG_B_OUTPUT
,
1116 { { &MEDIATYPE_Audio
, &MEDIASUBTYPE_MPEG1Packet
},
1117 { &MEDIATYPE_Audio
, &MEDIASUBTYPE_MPEG1AudioPayload
},
1121 { REG_PINFLAG_B_OUTPUT
,
1122 { { &MEDIATYPE_Video
, &MEDIASUBTYPE_MPEG1Packet
},
1123 { &MEDIATYPE_Video
, &MEDIASUBTYPE_MPEG1Payload
},
1130 { &CLSID_VideoRenderer
,
1131 &CLSID_LegacyAmFilterCategory
,
1132 {'V','i','d','e','o',' ','R','e','n','d','e','r','e','r',0},
1134 { { REG_PINFLAG_B_RENDERER
,
1135 { { &MEDIATYPE_Video
, &GUID_NULL
},
1143 &CLSID_LegacyAmFilterCategory
,
1144 {'A','V','I',' ','D','e','c','o','m','p','r','e','s','s','o','r',0},
1147 { { &MEDIATYPE_Video
, &GUID_NULL
},
1151 { REG_PINFLAG_B_OUTPUT
,
1152 { { &MEDIATYPE_Video
, &GUID_NULL
},
1159 { &CLSID_AsyncReader
,
1160 &CLSID_LegacyAmFilterCategory
,
1161 {'F','i','l','e',' ','S','o','u','r','c','e',' ','(','A','s','y','n','c','.',')',0},
1163 { { REG_PINFLAG_B_OUTPUT
,
1164 { { &MEDIATYPE_Stream
, &GUID_NULL
},
1171 { &CLSID_ACMWrapper
,
1172 &CLSID_LegacyAmFilterCategory
,
1173 {'A','C','M',' ','W','r','a','p','p','e','r',0},
1176 { { &MEDIATYPE_Audio
, &GUID_NULL
},
1180 { REG_PINFLAG_B_OUTPUT
,
1181 { { &MEDIATYPE_Audio
, &GUID_NULL
},
1188 { &CLSID_WAVEParser
,
1189 &CLSID_LegacyAmFilterCategory
,
1190 {'W','a','v','e',' ','P','a','r','s','e','r',0},
1193 { { &MEDIATYPE_Stream
, &MEDIASUBTYPE_WAVE
},
1194 { &MEDIATYPE_Stream
, &MEDIASUBTYPE_AU
},
1195 { &MEDIATYPE_Stream
, &MEDIASUBTYPE_AIFF
},
1199 { REG_PINFLAG_B_OUTPUT
,
1200 { { &MEDIATYPE_Audio
, &GUID_NULL
},
1207 { NULL
} /* list terminator */
1210 /***********************************************************************
1211 * DllRegisterServer (QUARTZ.@)
1213 HRESULT WINAPI
DllRegisterServer(void)
1219 hr
= register_coclasses(coclass_list
);
1221 hr
= register_interfaces(interface_list
);
1223 hr
= register_mediatypes_parsing(mediatype_parsing_list
);
1225 hr
= register_mediatypes_extension(mediatype_extension_list
);
1227 hr
= register_filters(filter_list
);
1231 /***********************************************************************
1232 * DllUnregisterServer (QUARTZ.@)
1234 HRESULT WINAPI
DllUnregisterServer(void)
1240 hr
= unregister_filters(filter_list
);
1242 hr
= unregister_coclasses(coclass_list
);
1244 hr
= unregister_interfaces(interface_list
);
1246 hr
= unregister_mediatypes_parsing(mediatype_parsing_list
);
1248 hr
= unregister_mediatypes_extension(mediatype_extension_list
);