1 /* 2 * self-registerable dll functions for quartz.dll 3 * 4 * Copyright (C) 2003 John K. Hohm 5 * 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. 10 * 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. 15 * 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 19 */ 20 21 #define NONAMELESSUNION 22 #define NONAMELESSSTRUCT 23 #define COBJMACROS 24 #include <stdarg.h> 25 #include <string.h> 26 27 #include "windef.h" 28 #include "winbase.h" 29 #include "wingdi.h" 30 #include "winuser.h" 31 #include "winreg.h" 32 #include "winerror.h" 33 34 #include "ole2.h" 35 #include "uuids.h" 36 #include "strmif.h" 37 38 #include "wine/debug.h" 39 #include "wine/unicode.h" 40 41 WINE_DEFAULT_DEBUG_CHANNEL(quartz); 42 43 /* 44 * Near the bottom of this file are the exported DllRegisterServer and 45 * DllUnregisterServer, which make all this worthwhile. 46 */ 47 48 /*********************************************************************** 49 * interface for self-registering 50 */ 51 struct regsvr_interface 52 { 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 */ 59 }; 60 61 static HRESULT register_interfaces(struct regsvr_interface const *list); 62 static HRESULT unregister_interfaces(struct regsvr_interface const *list); 63 64 struct regsvr_coclass 65 { 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 */ 74 }; 75 76 static HRESULT register_coclasses(struct regsvr_coclass const *list); 77 static HRESULT unregister_coclasses(struct regsvr_coclass const *list); 78 79 struct regsvr_mediatype_parsing 80 { 81 CLSID const *majortype; /* NULL for end of list */ 82 CLSID const *subtype; 83 LPCSTR line[11]; /* NULL for end of list */ 84 }; 85 86 static HRESULT register_mediatypes_parsing(struct regsvr_mediatype_parsing const *list); 87 static HRESULT unregister_mediatypes_parsing(struct regsvr_mediatype_parsing const *list); 88 89 struct regsvr_mediatype_extension 90 { 91 CLSID const *majortype; /* NULL for end of list */ 92 CLSID const *subtype; 93 LPCSTR extension; 94 }; 95 96 struct mediatype 97 { 98 CLSID const *majortype; /* NULL for end of list */ 99 CLSID const *subtype; 100 DWORD fourcc; 101 }; 102 103 struct pin 104 { 105 DWORD flags; /* 0xFFFFFFFF for end of list */ 106 struct mediatype mediatypes[11]; 107 }; 108 109 struct regsvr_filter 110 { 111 CLSID const *clsid; /* NULL for end of list */ 112 CLSID const *category; 113 WCHAR name[50]; 114 DWORD merit; 115 struct pin pins[11]; 116 }; 117 118 static HRESULT register_mediatypes_extension(struct regsvr_mediatype_extension const *list); 119 static HRESULT unregister_mediatypes_extension(struct regsvr_mediatype_extension const *list); 120 121 static HRESULT register_filters(struct regsvr_filter const *list); 122 static HRESULT unregister_filters(struct regsvr_filter const *list); 123 124 /*********************************************************************** 125 * static string constants 126 */ 127 static const WCHAR interface_keyname[] = { 128 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c', 'e', 0 }; 129 static const WCHAR base_ifa_keyname[] = { 130 'B', 'a', 's', 'e', 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c', 131 'e', 0 }; 132 static const WCHAR num_methods_keyname[] = { 133 'N', 'u', 'm', 'M', 'e', 't', 'h', 'o', 'd', 's', 0 }; 134 static const WCHAR ps_clsid_keyname[] = { 135 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's', 136 'i', 'd', 0 }; 137 static const WCHAR ps_clsid32_keyname[] = { 138 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's', 139 'i', 'd', '3', '2', 0 }; 140 static const WCHAR clsid_keyname[] = { 141 'C', 'L', 'S', 'I', 'D', 0 }; 142 static const WCHAR curver_keyname[] = { 143 'C', 'u', 'r', 'V', 'e', 'r', 0 }; 144 static const WCHAR ips_keyname[] = { 145 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r', 146 0 }; 147 static const WCHAR ips32_keyname[] = { 148 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r', 149 '3', '2', 0 }; 150 static const WCHAR progid_keyname[] = { 151 'P', 'r', 'o', 'g', 'I', 'D', 0 }; 152 static const WCHAR viprogid_keyname[] = { 153 'V', 'e', 'r', 's', 'i', 'o', 'n', 'I', 'n', 'd', 'e', 'p', 154 'e', 'n', 'd', 'e', 'n', 't', 'P', 'r', 'o', 'g', 'I', 'D', 155 0 }; 156 static const char tmodel_valuename[] = "ThreadingModel"; 157 static const WCHAR mediatype_name[] = { 158 'M', 'e', 'd', 'i', 'a', ' ', 'T', 'y', 'p', 'e', 0 }; 159 static const WCHAR subtype_valuename[] = { 160 'S', 'u', 'b', 't', 'y', 'p', 'e', 0 }; 161 static const WCHAR sourcefilter_valuename[] = { 162 'S', 'o', 'u', 'r', 'c', 'e', ' ', 'F', 'i', 'l', 't', 'e', 'r', 0 }; 163 static const WCHAR extensions_keyname[] = { 164 'E', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 's', 0 }; 165 166 /*********************************************************************** 167 * static helper functions 168 */ 169 static LONG register_key_guid(HKEY base, WCHAR const *name, GUID const *guid); 170 static LONG register_key_defvalueW(HKEY base, WCHAR const *name, 171 WCHAR const *value); 172 static LONG register_key_defvalueA(HKEY base, WCHAR const *name, 173 char const *value); 174 static LONG register_progid(WCHAR const *clsid, 175 char const *progid, char const *curver_progid, 176 char const *name, char const *extra); 177 178 /*********************************************************************** 179 * register_interfaces 180 */ 181 static HRESULT register_interfaces(struct regsvr_interface const *list) 182 { 183 LONG res = ERROR_SUCCESS; 184 HKEY interface_key; 185 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; 189 190 for (; res == ERROR_SUCCESS && list->iid; ++list) { 191 WCHAR buf[39]; 192 HKEY iid_key; 193 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; 198 199 if (list->name) { 200 res = RegSetValueExA(iid_key, NULL, 0, REG_SZ, (const BYTE*)list->name, 201 strlen(list->name) + 1); 202 if (res != ERROR_SUCCESS) goto error_close_iid_key; 203 } 204 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; 208 } 209 210 if (0 <= list->num_methods) { 211 static const WCHAR fmt[] = { '%', 'd', 0 }; 212 HKEY key; 213 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; 217 218 sprintfW(buf, fmt, list->num_methods); 219 res = RegSetValueExW(key, NULL, 0, REG_SZ, (const BYTE*)buf, 220 (lstrlenW(buf) + 1) * sizeof(WCHAR)); 221 RegCloseKey(key); 222 223 if (res != ERROR_SUCCESS) goto error_close_iid_key; 224 } 225 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; 229 } 230 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; 234 } 235 236 error_close_iid_key: 237 RegCloseKey(iid_key); 238 } 239 240 error_close_interface_key: 241 RegCloseKey(interface_key); 242 error_return: 243 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK; 244 } 245 246 /*********************************************************************** 247 * unregister_interfaces 248 */ 249 static HRESULT unregister_interfaces(struct regsvr_interface const *list) 250 { 251 LONG res = ERROR_SUCCESS; 252 HKEY interface_key; 253 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; 258 259 for (; res == ERROR_SUCCESS && list->iid; ++list) { 260 WCHAR buf[39]; 261 262 StringFromGUID2(list->iid, buf, 39); 263 res = RegDeleteTreeW(interface_key, buf); 264 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS; 265 } 266 267 RegCloseKey(interface_key); 268 error_return: 269 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK; 270 } 271 272 /*********************************************************************** 273 * register_coclasses 274 */ 275 static HRESULT register_coclasses(struct regsvr_coclass const *list) 276 { 277 LONG res = ERROR_SUCCESS; 278 HKEY coclass_key; 279 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; 283 284 for (; res == ERROR_SUCCESS && list->clsid; ++list) { 285 WCHAR buf[39]; 286 HKEY clsid_key; 287 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; 292 293 if (list->name) { 294 res = RegSetValueExA(clsid_key, NULL, 0, REG_SZ, (const BYTE*)list->name, 295 strlen(list->name) + 1); 296 if (res != ERROR_SUCCESS) goto error_close_clsid_key; 297 } 298 299 if (list->ips) { 300 res = register_key_defvalueA(clsid_key, ips_keyname, list->ips); 301 if (res != ERROR_SUCCESS) goto error_close_clsid_key; 302 } 303 304 if (list->ips32) { 305 HKEY ips32_key; 306 307 res = RegCreateKeyExW(clsid_key, ips32_keyname, 0, NULL, 0, 308 KEY_READ | KEY_WRITE, NULL, 309 &ips32_key, NULL); 310 if (res != ERROR_SUCCESS) goto error_close_clsid_key; 311 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; 320 } 321 322 if (list->progid) { 323 res = register_key_defvalueA(clsid_key, progid_keyname, 324 list->progid); 325 if (res != ERROR_SUCCESS) goto error_close_clsid_key; 326 327 res = register_progid(buf, list->progid, NULL, 328 list->name, list->progid_extra); 329 if (res != ERROR_SUCCESS) goto error_close_clsid_key; 330 } 331 332 if (list->viprogid) { 333 res = register_key_defvalueA(clsid_key, viprogid_keyname, 334 list->viprogid); 335 if (res != ERROR_SUCCESS) goto error_close_clsid_key; 336 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; 340 } 341 342 error_close_clsid_key: 343 RegCloseKey(clsid_key); 344 } 345 346 error_close_coclass_key: 347 RegCloseKey(coclass_key); 348 error_return: 349 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK; 350 } 351 352 /*********************************************************************** 353 * unregister_coclasses 354 */ 355 static HRESULT unregister_coclasses(struct regsvr_coclass const *list) 356 { 357 LONG res = ERROR_SUCCESS; 358 HKEY coclass_key; 359 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; 364 365 for (; res == ERROR_SUCCESS && list->clsid; ++list) { 366 WCHAR buf[39]; 367 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; 372 373 if (list->progid) { 374 res = RegDeleteTreeA(HKEY_CLASSES_ROOT, list->progid); 375 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS; 376 if (res != ERROR_SUCCESS) goto error_close_coclass_key; 377 } 378 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; 383 } 384 } 385 386 error_close_coclass_key: 387 RegCloseKey(coclass_key); 388 error_return: 389 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK; 390 } 391 392 /*********************************************************************** 393 * register_mediatypes_parsing 394 */ 395 static HRESULT register_mediatypes_parsing(struct regsvr_mediatype_parsing const *list) 396 { 397 LONG res = ERROR_SUCCESS; 398 HKEY mediatype_key; 399 WCHAR buf[39]; 400 int i; 401 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); 405 406 for (; res == ERROR_SUCCESS && list->majortype; ++list) { 407 HKEY majortype_key = NULL; 408 HKEY subtype_key = NULL; 409 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; 414 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; 419 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; 424 425 for(i = 0; list->line[i]; i++) { 426 char buffer[3]; 427 wsprintfA(buffer, "%d", i); 428 res = RegSetValueExA(subtype_key, buffer, 0, REG_SZ, (const BYTE*)list->line[i], 429 lstrlenA(list->line[i])); 430 if (res != ERROR_SUCCESS) goto error_close_keys; 431 } 432 433 error_close_keys: 434 if (majortype_key) 435 RegCloseKey(majortype_key); 436 if (subtype_key) 437 RegCloseKey(subtype_key); 438 } 439 440 RegCloseKey(mediatype_key); 441 442 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK; 443 } 444 445 /*********************************************************************** 446 * register_mediatypes_extension 447 */ 448 static HRESULT register_mediatypes_extension(struct regsvr_mediatype_extension const *list) 449 { 450 LONG res = ERROR_SUCCESS; 451 HKEY mediatype_key; 452 HKEY extensions_root_key = NULL; 453 WCHAR buf[39]; 454 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); 458 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; 462 463 for (; res == ERROR_SUCCESS && list->majortype; ++list) { 464 HKEY extension_key; 465 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; 469 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; 474 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; 479 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; 484 485 error_close_key: 486 RegCloseKey(extension_key); 487 } 488 489 error_return: 490 RegCloseKey(mediatype_key); 491 if (extensions_root_key) 492 RegCloseKey(extensions_root_key); 493 494 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK; 495 } 496 497 /*********************************************************************** 498 * unregister_mediatypes_parsing 499 */ 500 static HRESULT unregister_mediatypes_parsing(struct regsvr_mediatype_parsing const *list) 501 { 502 LONG res; 503 HKEY mediatype_key; 504 HKEY majortype_key; 505 WCHAR buf[39]; 506 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); 511 512 for (; res == ERROR_SUCCESS && list->majortype; ++list) { 513 StringFromGUID2(list->majortype, buf, 39); 514 res = RegOpenKeyExW(mediatype_key, buf, 0, 515 KEY_READ | KEY_WRITE, &majortype_key); 516 if (res == ERROR_FILE_NOT_FOUND) { 517 res = ERROR_SUCCESS; 518 continue; 519 } 520 if (res != ERROR_SUCCESS) break; 521 522 StringFromGUID2(list->subtype, buf, 39); 523 res = RegDeleteTreeW(majortype_key, buf); 524 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS; 525 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; 529 530 RegCloseKey(majortype_key); 531 } 532 533 RegCloseKey(mediatype_key); 534 535 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK; 536 } 537 538 /*********************************************************************** 539 * unregister_mediatypes_extension 540 */ 541 static HRESULT unregister_mediatypes_extension(struct regsvr_mediatype_extension const *list) 542 { 543 LONG res; 544 HKEY mediatype_key; 545 HKEY extensions_root_key = NULL; 546 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); 551 552 res = RegOpenKeyExW(mediatype_key, extensions_keyname, 0, 553 KEY_READ | KEY_WRITE, &extensions_root_key); 554 if (res == ERROR_FILE_NOT_FOUND) 555 res = ERROR_SUCCESS; 556 else if (res == ERROR_SUCCESS) 557 for (; res == ERROR_SUCCESS && list->majortype; ++list) { 558 res = RegDeleteTreeA(extensions_root_key, list->extension); 559 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS; 560 } 561 562 RegCloseKey(mediatype_key); 563 if (extensions_root_key) 564 RegCloseKey(extensions_root_key); 565 566 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK; 567 } 568 569 /*********************************************************************** 570 * register_filters 571 */ 572 static HRESULT register_filters(struct regsvr_filter const *list) 573 { 574 HRESULT hr; 575 IFilterMapper2* pFM2 = NULL; 576 577 CoInitialize(NULL); 578 hr = CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC_SERVER, &IID_IFilterMapper2, (LPVOID*)&pFM2); 579 580 if (SUCCEEDED(hr)) { 581 for (; SUCCEEDED(hr) && list->clsid; ++list) { 582 REGFILTER2 rf2; 583 REGFILTERPINS2* prfp2; 584 int i; 585 586 for (i = 0; list->pins[i].flags != 0xFFFFFFFF; i++) ; 587 rf2.dwVersion = 2; 588 rf2.dwMerit = list->merit; 589 rf2.u.s2.cPins2 = i; 590 rf2.u.s2.rgPins2 = prfp2 = CoTaskMemAlloc(i*sizeof(REGFILTERPINS2)); 591 if (!prfp2) { 592 hr = E_OUTOFMEMORY; 593 break; 594 } 595 for (i = 0; list->pins[i].flags != 0xFFFFFFFF; i++) { 596 REGPINTYPES* lpMediatype; 597 CLSID* lpClsid; 598 int j, nbmt; 599 600 for (nbmt = 0; list->pins[i].mediatypes[nbmt].majortype; nbmt++) ; 601 /* Allocate a single buffer for regpintypes struct and clsids */ 602 lpMediatype = CoTaskMemAlloc(nbmt*(sizeof(REGPINTYPES) + 2*sizeof(CLSID))); 603 if (!lpMediatype) { 604 hr = E_OUTOFMEMORY; 605 break; 606 } 607 lpClsid = (CLSID*) (lpMediatype + nbmt); 608 for (j = 0; j < nbmt; j++) { 609 (lpMediatype + j)->clsMajorType = lpClsid + j*2; 610 memcpy(lpClsid + j*2, list->pins[i].mediatypes[j].majortype, sizeof(CLSID)); 611 (lpMediatype + j)->clsMinorType = lpClsid + j*2 + 1; 612 if (list->pins[i].mediatypes[j].subtype) 613 memcpy(lpClsid + j*2 + 1, list->pins[i].mediatypes[j].subtype, sizeof(CLSID)); 614 else { 615 /* Subtypes are often a combination of major type + fourcc/tag */ 616 memcpy(lpClsid + j*2 + 1, list->pins[i].mediatypes[j].majortype, sizeof(CLSID)); 617 *(DWORD*)(lpClsid + j*2 + 1) = list->pins[i].mediatypes[j].fourcc; 618 } 619 } 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; 627 } 628 629 if (FAILED(hr)) { 630 ERR("failed to register with hresult 0x%x\n", hr); 631 CoTaskMemFree(prfp2); 632 break; 633 } 634 635 hr = IFilterMapper2_RegisterFilter(pFM2, list->clsid, list->name, NULL, list->category, NULL, &rf2); 636 637 while (i) { 638 CoTaskMemFree((REGPINTYPES*)prfp2[i-1].lpMediaType); 639 i--; 640 } 641 CoTaskMemFree(prfp2); 642 } 643 } 644 645 if (pFM2) 646 IFilterMapper2_Release(pFM2); 647 648 CoUninitialize(); 649 650 return hr; 651 } 652 653 /*********************************************************************** 654 * unregister_filters 655 */ 656 static HRESULT unregister_filters(struct regsvr_filter const *list) 657 { 658 HRESULT hr; 659 IFilterMapper2* pFM2; 660 661 CoInitialize(NULL); 662 663 hr = CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC_SERVER, &IID_IFilterMapper2, (LPVOID*)&pFM2); 664 665 if (SUCCEEDED(hr)) { 666 for (; SUCCEEDED(hr) && list->clsid; ++list) 667 hr = IFilterMapper2_UnregisterFilter(pFM2, list->category, NULL, list->clsid); 668 IFilterMapper2_Release(pFM2); 669 } 670 671 CoUninitialize(); 672 673 return hr; 674 } 675 676 /*********************************************************************** 677 * regsvr_key_guid 678 */ 679 static LONG register_key_guid(HKEY base, WCHAR const *name, GUID const *guid) 680 { 681 WCHAR buf[39]; 682 683 StringFromGUID2(guid, buf, 39); 684 return register_key_defvalueW(base, name, buf); 685 } 686 687 /*********************************************************************** 688 * regsvr_key_defvalueW 689 */ 690 static LONG register_key_defvalueW( 691 HKEY base, 692 WCHAR const *name, 693 WCHAR const *value) 694 { 695 LONG res; 696 HKEY key; 697 698 res = RegCreateKeyExW(base, name, 0, NULL, 0, 699 KEY_READ | KEY_WRITE, NULL, &key, NULL); 700 if (res != ERROR_SUCCESS) return res; 701 res = RegSetValueExW(key, NULL, 0, REG_SZ, (const BYTE*)value, 702 (lstrlenW(value) + 1) * sizeof(WCHAR)); 703 RegCloseKey(key); 704 return res; 705 } 706 707 /*********************************************************************** 708 * regsvr_key_defvalueA 709 */ 710 static LONG register_key_defvalueA( 711 HKEY base, 712 WCHAR const *name, 713 char const *value) 714 { 715 LONG res; 716 HKEY key; 717 718 res = RegCreateKeyExW(base, name, 0, NULL, 0, 719 KEY_READ | KEY_WRITE, NULL, &key, NULL); 720 if (res != ERROR_SUCCESS) return res; 721 res = RegSetValueExA(key, NULL, 0, REG_SZ, (const BYTE*)value, lstrlenA(value) + 1); 722 RegCloseKey(key); 723 return res; 724 } 725 726 /*********************************************************************** 727 * regsvr_progid 728 */ 729 static LONG register_progid( 730 WCHAR const *clsid, 731 char const *progid, 732 char const *curver_progid, 733 char const *name, 734 char const *extra) 735 { 736 LONG res; 737 HKEY progid_key; 738 739 res = RegCreateKeyExA(HKEY_CLASSES_ROOT, progid, 0, 740 NULL, 0, KEY_READ | KEY_WRITE, NULL, 741 &progid_key, NULL); 742 if (res != ERROR_SUCCESS) return res; 743 744 if (name) { 745 res = RegSetValueExA(progid_key, NULL, 0, REG_SZ, (const BYTE*)name, strlen(name) + 1); 746 if (res != ERROR_SUCCESS) goto error_close_progid_key; 747 } 748 749 if (clsid) { 750 res = register_key_defvalueW(progid_key, clsid_keyname, clsid); 751 if (res != ERROR_SUCCESS) goto error_close_progid_key; 752 } 753 754 if (curver_progid) { 755 res = register_key_defvalueA(progid_key, curver_keyname, 756 curver_progid); 757 if (res != ERROR_SUCCESS) goto error_close_progid_key; 758 } 759 760 if (extra) { 761 HKEY extra_key; 762 763 res = RegCreateKeyExA(progid_key, extra, 0, 764 NULL, 0, KEY_READ | KEY_WRITE, NULL, 765 &extra_key, NULL); 766 if (res == ERROR_SUCCESS) 767 RegCloseKey(extra_key); 768 } 769 770 error_close_progid_key: 771 RegCloseKey(progid_key); 772 return res; 773 } 774 775 /*********************************************************************** 776 * coclass list 777 */ 778 static struct regsvr_coclass const coclass_list[] = { 779 { NULL } /* list terminator */ 780 }; 781 782 /*********************************************************************** 783 * interface list 784 */ 785 786 static struct regsvr_interface const interface_list[] = { 787 { NULL } /* list terminator */ 788 }; 789 790 /*********************************************************************** 791 * mediatype list 792 */ 793 794 static struct regsvr_mediatype_parsing const mediatype_parsing_list[] = { 795 { &MEDIATYPE_Stream, 796 &MEDIASUBTYPE_Avi, 797 { "0,4,,52494646,8,4,,41564920", 798 NULL } 799 }, 800 { &MEDIATYPE_Stream, 801 &MEDIASUBTYPE_MPEG1System, 802 { "0, 16, FFFFFFFFF100010001800001FFFFFFFF, 000001BA2100010001800001000001BB", 803 NULL } 804 }, 805 { &MEDIATYPE_Stream, 806 &MEDIASUBTYPE_MPEG1VideoCD, 807 { "0, 4, , 52494646, 8, 8, , 43445841666D7420, 36, 20, FFFFFFFF00000000FFFFFFFFFFFFFFFFFFFFFFFF, 646174610000000000FFFFFFFFFFFFFFFFFFFF00", 808 NULL } 809 }, 810 { &MEDIATYPE_Stream, 811 &MEDIASUBTYPE_MPEG1Video, 812 { "0, 4, , 000001B3", 813 NULL } 814 }, 815 { &MEDIATYPE_Stream, 816 &MEDIASUBTYPE_MPEG1Audio, 817 { "0, 2, FFE0, FFE0", 818 "0, 10, FFFFFF00000080808080, 494433000000000000", 819 NULL } 820 }, 821 { &MEDIATYPE_Stream, 822 &MEDIASUBTYPE_MPEG2_PROGRAM, 823 { "0, 5, FFFFFFFFC0, 000001BA40", 824 NULL } 825 }, 826 { &MEDIATYPE_Stream, 827 &MEDIASUBTYPE_QTMovie, 828 { "4, 4, , 6d646174", 829 "4, 4, , 6d6f6f76", 830 NULL } 831 }, 832 { &MEDIATYPE_Stream, 833 &MEDIASUBTYPE_WAVE, 834 { "0,4,,52494646,8,4,,57415645", 835 NULL } 836 }, 837 { &MEDIATYPE_Stream, 838 &MEDIASUBTYPE_AU, 839 { "0,4,,2e736e64", 840 NULL } 841 }, 842 { &MEDIATYPE_Stream, 843 &MEDIASUBTYPE_AIFF, 844 { "0,4,,464f524d,8,4,,41494646", 845 "0,4,,464f524d,8,4,,41494643", 846 NULL } 847 }, 848 { &MEDIATYPE_Stream, 849 &MEDIATYPE_Text, 850 { "0,4,,4C595249", 851 "0,4,,6C797269", 852 NULL } 853 }, 854 { &MEDIATYPE_Stream, 855 &MEDIATYPE_Midi, 856 { "0,4,,52494646,8,4,,524D4944", 857 "0,4,,4D546864", 858 NULL } 859 }, 860 { NULL } /* list terminator */ 861 }; 862 863 /*********************************************************************** 864 * mediatype list 865 */ 866 867 static struct regsvr_mediatype_extension const mediatype_extension_list[] = { 868 { &MEDIATYPE_Stream, 869 &MEDIASUBTYPE_MPEG1Audio, 870 ".mp3" 871 }, 872 { NULL } /* list terminator */ 873 }; 874 875 /*********************************************************************** 876 * filter list 877 */ 878 879 static struct regsvr_filter const filter_list[] = { 880 { &CLSID_AviSplitter, 881 &CLSID_LegacyAmFilterCategory, 882 {'A','V','I',' ','S','p','l','i','t','t','e','r',0}, 883 0x5ffff0, 884 { { 0, 885 { { &MEDIATYPE_Stream, &MEDIASUBTYPE_Avi }, 886 { NULL } 887 }, 888 }, 889 { REG_PINFLAG_B_OUTPUT, 890 { { &MEDIATYPE_Video, &GUID_NULL }, 891 { NULL } 892 }, 893 }, 894 { 0xFFFFFFFF }, 895 } 896 }, 897 { &CLSID_MPEG1Splitter, 898 &CLSID_LegacyAmFilterCategory, 899 {'M','P','E','G','-','I',' ','S','t','r','e','a','m',' ','S','p','l','i','t','t','e','r',0}, 900 0x5ffff0, 901 { { 0, 902 { { &MEDIATYPE_Stream, &MEDIASUBTYPE_MPEG1Audio }, 903 { &MEDIATYPE_Stream, &MEDIASUBTYPE_MPEG1Video }, 904 { &MEDIATYPE_Stream, &MEDIASUBTYPE_MPEG1System }, 905 { &MEDIATYPE_Stream, &MEDIASUBTYPE_MPEG1VideoCD }, 906 { NULL } 907 }, 908 }, 909 { REG_PINFLAG_B_OUTPUT, 910 { { &MEDIATYPE_Audio, &MEDIASUBTYPE_MPEG1Packet }, 911 { &MEDIATYPE_Audio, &MEDIASUBTYPE_MPEG1AudioPayload }, 912 { NULL } 913 }, 914 }, 915 { REG_PINFLAG_B_OUTPUT, 916 { { &MEDIATYPE_Video, &MEDIASUBTYPE_MPEG1Packet }, 917 { &MEDIATYPE_Video, &MEDIASUBTYPE_MPEG1Payload }, 918 { NULL } 919 }, 920 }, 921 { 0xFFFFFFFF }, 922 } 923 }, 924 { &CLSID_NullRenderer, 925 &CLSID_LegacyAmFilterCategory, 926 {'N','u','l','l',' ','R','e','n','d','e','r','e','r',0}, 927 0x200000, 928 { { REG_PINFLAG_B_RENDERER, 929 { { &MEDIATYPE_NULL, &GUID_NULL }, 930 { NULL } 931 }, 932 }, 933 { 0xFFFFFFFF }, 934 } 935 }, 936 { &CLSID_VideoRenderer, 937 &CLSID_LegacyAmFilterCategory, 938 {'V','i','d','e','o',' ','R','e','n','d','e','r','e','r',0}, 939 0x800000, 940 { { REG_PINFLAG_B_RENDERER, 941 { { &MEDIATYPE_Video, &GUID_NULL }, 942 { NULL } 943 }, 944 }, 945 { 0xFFFFFFFF }, 946 } 947 }, 948 { &CLSID_VideoRendererDefault, 949 &CLSID_LegacyAmFilterCategory, 950 {'V','i','d','e','o',' ','R','e','n','d','e','r','e','r',0}, 951 0x800000, 952 { { REG_PINFLAG_B_RENDERER, 953 { { &MEDIATYPE_Video, &GUID_NULL }, 954 { NULL } 955 }, 956 }, 957 { 0xFFFFFFFF }, 958 } 959 }, 960 { &CLSID_VideoMixingRenderer, 961 &CLSID_LegacyAmFilterCategory, 962 {'V','i','d','e','o',' ','M','i','x','i','n','g',' ','R','e','n','d','e','r','e','r',0}, 963 0x200000, 964 { { REG_PINFLAG_B_RENDERER, 965 { { &MEDIATYPE_Video, &GUID_NULL }, 966 { NULL } 967 }, 968 }, 969 { 0xFFFFFFFF }, 970 } 971 }, 972 { &CLSID_VideoMixingRenderer9, 973 &CLSID_LegacyAmFilterCategory, 974 {'V','i','d','e','o',' ','M','i','x','i','n','g',' ','R','e','n','d','e','r','e','r',' ','9',0}, 975 0x200000, 976 { { REG_PINFLAG_B_RENDERER, 977 { { &MEDIATYPE_Video, &GUID_NULL }, 978 { NULL } 979 }, 980 }, 981 { 0xFFFFFFFF }, 982 } 983 }, 984 { &CLSID_DSoundRender, 985 &CLSID_LegacyAmFilterCategory, 986 {'A','u','d','i','o',' ','R','e','n','d','e','r','e','r',0}, 987 0x800000, 988 { { REG_PINFLAG_B_RENDERER, 989 { { &MEDIATYPE_Audio, &MEDIASUBTYPE_PCM }, 990 /* { &MEDIATYPE_Audio, &MEDIASUBTYPE_IEEE_FLOAT }, */ 991 { NULL } 992 }, 993 }, 994 { 0xFFFFFFFF }, 995 } 996 }, 997 { &CLSID_AudioRender, 998 &CLSID_LegacyAmFilterCategory, 999 {'A','u','d','i','o',' ','R','e','n','d','e','r','e','r',0}, 1000 0x800000, 1001 { { REG_PINFLAG_B_RENDERER, 1002 { { &MEDIATYPE_Audio, &MEDIASUBTYPE_PCM }, 1003 /* { &MEDIATYPE_Audio, &MEDIASUBTYPE_IEEE_FLOAT }, */ 1004 { NULL } 1005 }, 1006 }, 1007 { 0xFFFFFFFF }, 1008 } 1009 }, 1010 { &CLSID_AVIDec, 1011 &CLSID_LegacyAmFilterCategory, 1012 {'A','V','I',' ','D','e','c','o','m','p','r','e','s','s','o','r',0}, 1013 0x5ffff0, 1014 { { 0, 1015 { { &MEDIATYPE_Video, &GUID_NULL }, 1016 { NULL } 1017 }, 1018 }, 1019 { REG_PINFLAG_B_OUTPUT, 1020 { { &MEDIATYPE_Video, &GUID_NULL }, 1021 { NULL } 1022 }, 1023 }, 1024 { 0xFFFFFFFF }, 1025 } 1026 }, 1027 { &CLSID_AsyncReader, 1028 &CLSID_LegacyAmFilterCategory, 1029 {'F','i','l','e',' ','S','o','u','r','c','e',' ','(','A','s','y','n','c','.',')',0}, 1030 0x400000, 1031 { { REG_PINFLAG_B_OUTPUT, 1032 { { &MEDIATYPE_Stream, &GUID_NULL }, 1033 { NULL } 1034 }, 1035 }, 1036 { 0xFFFFFFFF }, 1037 } 1038 }, 1039 { &CLSID_ACMWrapper, 1040 &CLSID_LegacyAmFilterCategory, 1041 {'A','C','M',' ','W','r','a','p','p','e','r',0}, 1042 0x5ffff0, 1043 { { 0, 1044 { { &MEDIATYPE_Audio, &GUID_NULL }, 1045 { NULL } 1046 }, 1047 }, 1048 { REG_PINFLAG_B_OUTPUT, 1049 { { &MEDIATYPE_Audio, &GUID_NULL }, 1050 { NULL } 1051 }, 1052 }, 1053 { 0xFFFFFFFF }, 1054 } 1055 }, 1056 { &CLSID_WAVEParser, 1057 &CLSID_LegacyAmFilterCategory, 1058 {'W','a','v','e',' ','P','a','r','s','e','r',0}, 1059 0x400000, 1060 { { 0, 1061 { { &MEDIATYPE_Stream, &MEDIASUBTYPE_WAVE }, 1062 { &MEDIATYPE_Stream, &MEDIASUBTYPE_AU }, 1063 { &MEDIATYPE_Stream, &MEDIASUBTYPE_AIFF }, 1064 { NULL } 1065 }, 1066 }, 1067 { REG_PINFLAG_B_OUTPUT, 1068 { { &MEDIATYPE_Audio, &GUID_NULL }, 1069 { NULL } 1070 }, 1071 }, 1072 { 0xFFFFFFFF }, 1073 } 1074 }, 1075 { NULL } /* list terminator */ 1076 }; 1077 1078 extern HRESULT WINAPI QUARTZ_DllRegisterServer(void) DECLSPEC_HIDDEN; 1079 extern HRESULT WINAPI QUARTZ_DllUnregisterServer(void) DECLSPEC_HIDDEN; 1080 1081 /*********************************************************************** 1082 * DllRegisterServer (QUARTZ.@) 1083 */ 1084 HRESULT WINAPI DllRegisterServer(void) 1085 { 1086 HRESULT hr; 1087 1088 TRACE("\n"); 1089 1090 hr = QUARTZ_DllRegisterServer(); 1091 if (SUCCEEDED(hr)) 1092 hr = register_coclasses(coclass_list); 1093 if (SUCCEEDED(hr)) 1094 hr = register_interfaces(interface_list); 1095 if (SUCCEEDED(hr)) 1096 hr = register_mediatypes_parsing(mediatype_parsing_list); 1097 if (SUCCEEDED(hr)) 1098 hr = register_mediatypes_extension(mediatype_extension_list); 1099 if (SUCCEEDED(hr)) 1100 hr = register_filters(filter_list); 1101 return hr; 1102 } 1103 1104 /*********************************************************************** 1105 * DllUnregisterServer (QUARTZ.@) 1106 */ 1107 HRESULT WINAPI DllUnregisterServer(void) 1108 { 1109 HRESULT hr; 1110 1111 TRACE("\n"); 1112 1113 hr = unregister_filters(filter_list); 1114 if (SUCCEEDED(hr)) 1115 hr = unregister_coclasses(coclass_list); 1116 if (SUCCEEDED(hr)) 1117 hr = unregister_interfaces(interface_list); 1118 if (SUCCEEDED(hr)) 1119 hr = unregister_mediatypes_parsing(mediatype_parsing_list); 1120 if (SUCCEEDED(hr)) 1121 hr = unregister_mediatypes_extension(mediatype_extension_list); 1122 if (SUCCEEDED(hr)) 1123 hr = QUARTZ_DllUnregisterServer(); 1124 return hr; 1125 } 1126