Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenfiltermapper.c
Go to the documentation of this file.
00001 /* 00002 * IFilterMapper & IFilterMapper2 Implementations 00003 * 00004 * Copyright 2003 Robert Shearman 00005 * Copyright 2004 Christian Costa 00006 * 00007 * This library is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * This library is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with this library; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00020 */ 00021 00022 #define NONAMELESSUNION 00023 #define NONAMELESSSTRUCT 00024 #include <stdarg.h> 00025 00026 #include "windef.h" 00027 #include "winbase.h" 00028 #include "winuser.h" 00029 #include "winreg.h" 00030 #include "winerror.h" 00031 00032 #include "quartz_private.h" 00033 00034 #include "ole2.h" 00035 #include "olectl.h" 00036 #include "strmif.h" 00037 #include "wine/unicode.h" 00038 #include "uuids.h" 00039 00040 #include "wine/debug.h" 00041 00042 WINE_DEFAULT_DEBUG_CHANNEL(quartz); 00043 00044 #define ARRAYSIZE(array) (sizeof(array)/sizeof((array)[0])) 00045 00046 /* Unexposed IAMFilterData interface */ 00047 typedef struct IAMFilterData IAMFilterData; 00048 00049 typedef struct IAMFilterDataVtbl 00050 { 00051 BEGIN_INTERFACE 00052 00053 /*** IUnknown methods ***/ 00054 HRESULT (STDMETHODCALLTYPE *QueryInterface)( 00055 IAMFilterData *This, 00056 REFIID riid, 00057 void **ppvObject); 00058 00059 ULONG (STDMETHODCALLTYPE *AddRef)( 00060 IAMFilterData *This); 00061 00062 ULONG (STDMETHODCALLTYPE *Release)( 00063 IAMFilterData *This); 00064 00065 /*** IAMFilterData methods ***/ 00066 HRESULT (STDMETHODCALLTYPE *ParseFilterData)( 00067 IAMFilterData *This, 00068 BYTE *pData, 00069 ULONG cb, 00070 BYTE **ppRegFilter2); 00071 00072 HRESULT (STDMETHODCALLTYPE *CreateFilterData)( 00073 IAMFilterData* This, 00074 REGFILTER2 *prf2, 00075 BYTE **pRegFilterData, 00076 ULONG *pcb); 00077 00078 END_INTERFACE 00079 } IAMFilterDataVtbl; 00080 struct IAMFilterData 00081 { 00082 const IAMFilterDataVtbl *lpVtbl; 00083 }; 00084 static const GUID IID_IAMFilterData = { 00085 0x97f7c4d4, 0x547b, 0x4a5f, { 0x83,0x32, 0x53,0x64,0x30,0xad,0x2e,0x4d } 00086 }; 00087 00088 00089 typedef struct FilterMapper2Impl 00090 { 00091 const IFilterMapper2Vtbl *lpVtbl; 00092 const IFilterMapperVtbl *lpVtblFilterMapper; 00093 const IAMFilterDataVtbl *lpVtblAMFilterData; 00094 const IUnknownVtbl *IInner_vtbl; 00095 LONG refCount; 00096 IUnknown * pUnkOuter; 00097 BOOL bUnkOuterValid; 00098 BOOL bAggregatable; 00099 } FilterMapper2Impl; 00100 00101 static const IUnknownVtbl IInner_VTable; 00102 static const IFilterMapper2Vtbl fm2vtbl; 00103 static const IFilterMapperVtbl fmvtbl; 00104 static const IAMFilterDataVtbl AMFilterDataVtbl; 00105 00106 static inline FilterMapper2Impl *impl_from_IFilterMapper( IFilterMapper *iface ) 00107 { 00108 return (FilterMapper2Impl *)((char*)iface - FIELD_OFFSET(FilterMapper2Impl, lpVtblFilterMapper)); 00109 } 00110 00111 static inline FilterMapper2Impl *impl_from_IAMFilterData( IAMFilterData *iface ) 00112 { 00113 return (FilterMapper2Impl *)((char*)iface - FIELD_OFFSET(FilterMapper2Impl, lpVtblAMFilterData)); 00114 } 00115 00116 static inline FilterMapper2Impl *impl_from_inner_IUnknown( IUnknown *iface ) 00117 { 00118 return (FilterMapper2Impl *)((char*)iface - FIELD_OFFSET(FilterMapper2Impl, IInner_vtbl)); 00119 } 00120 00121 static const WCHAR wszClsidSlash[] = {'C','L','S','I','D','\\',0}; 00122 static const WCHAR wszSlashInstance[] = {'\\','I','n','s','t','a','n','c','e','\\',0}; 00123 static const WCHAR wszSlash[] = {'\\',0}; 00124 00125 /* CLSID property in media category Moniker */ 00126 static const WCHAR wszClsidName[] = {'C','L','S','I','D',0}; 00127 /* FriendlyName property in media category Moniker */ 00128 static const WCHAR wszFriendlyName[] = {'F','r','i','e','n','d','l','y','N','a','m','e',0}; 00129 /* Merit property in media category Moniker (CLSID_ActiveMovieCategories only) */ 00130 static const WCHAR wszMeritName[] = {'M','e','r','i','t',0}; 00131 /* FilterData property in media category Moniker (not CLSID_ActiveMovieCategories) */ 00132 static const WCHAR wszFilterDataName[] = {'F','i','l','t','e','r','D','a','t','a',0}; 00133 /* For filters registered with IFilterMapper */ 00134 static const WCHAR wszFilterSlash[] = {'F','i','l','t','e','r','\\',0}; 00135 static const WCHAR wszFilter[] = {'F','i','l','t','e','r',0}; 00136 /* For pins registered with IFilterMapper */ 00137 static const WCHAR wszPins[] = {'P','i','n','s',0}; 00138 static const WCHAR wszAllowedMany[] = {'A','l','l','o','w','e','d','M','a','n','y',0}; 00139 static const WCHAR wszAllowedZero[] = {'A','l','l','o','w','e','d','Z','e','r','o',0}; 00140 static const WCHAR wszDirection[] = {'D','i','r','e','c','t','i','o','n',0}; 00141 static const WCHAR wszIsRendered[] = {'I','s','R','e','n','d','e','r','e','d',0}; 00142 /* For types registered with IFilterMapper */ 00143 static const WCHAR wszTypes[] = {'T','y','p','e','s',0}; 00144 00145 00146 /* registry format for REGFILTER2 */ 00147 struct REG_RF 00148 { 00149 DWORD dwVersion; 00150 DWORD dwMerit; 00151 DWORD dwPins; 00152 DWORD dwUnused; 00153 }; 00154 00155 struct REG_RFP 00156 { 00157 BYTE signature[4]; /* e.g. "0pi3" */ 00158 DWORD dwFlags; 00159 DWORD dwInstances; 00160 DWORD dwMediaTypes; 00161 DWORD dwMediums; 00162 DWORD bCategory; /* is there a category clsid? */ 00163 /* optional: dwOffsetCategoryClsid */ 00164 }; 00165 00166 struct REG_TYPE 00167 { 00168 BYTE signature[4]; /* e.g. "0ty3" */ 00169 DWORD dwUnused; 00170 DWORD dwOffsetMajor; 00171 DWORD dwOffsetMinor; 00172 }; 00173 00174 struct MONIKER_MERIT 00175 { 00176 IMoniker * pMoniker; 00177 DWORD dwMerit; 00178 }; 00179 00180 struct Vector 00181 { 00182 LPBYTE pData; 00183 int capacity; /* in bytes */ 00184 int current; /* pointer to next free byte */ 00185 }; 00186 00187 /* returns the position it was added at */ 00188 static int add_data(struct Vector * v, const BYTE * pData, int size) 00189 { 00190 int index = v->current; 00191 if (v->current + size > v->capacity) 00192 { 00193 LPBYTE pOldData = v->pData; 00194 v->capacity = (v->capacity + size) * 2; 00195 v->pData = CoTaskMemAlloc(v->capacity); 00196 memcpy(v->pData, pOldData, v->current); 00197 CoTaskMemFree(pOldData); 00198 } 00199 memcpy(v->pData + v->current, pData, size); 00200 v->current += size; 00201 return index; 00202 } 00203 00204 static int find_data(const struct Vector * v, const BYTE * pData, int size) 00205 { 00206 int index; 00207 for (index = 0; index < v->current; index++) 00208 if (!memcmp(v->pData + index, pData, size)) 00209 return index; 00210 /* not found */ 00211 return -1; 00212 } 00213 00214 static void delete_vector(struct Vector * v) 00215 { 00216 CoTaskMemFree(v->pData); 00217 v->current = 0; 00218 v->capacity = 0; 00219 } 00220 00221 HRESULT FilterMapper2_create(IUnknown *pUnkOuter, LPVOID *ppObj) 00222 { 00223 FilterMapper2Impl * pFM2impl; 00224 00225 TRACE("(%p, %p)\n", pUnkOuter, ppObj); 00226 00227 pFM2impl = CoTaskMemAlloc(sizeof(*pFM2impl)); 00228 if (!pFM2impl) 00229 return E_OUTOFMEMORY; 00230 00231 pFM2impl->pUnkOuter = pUnkOuter; 00232 pFM2impl->bUnkOuterValid = FALSE; 00233 pFM2impl->bAggregatable = FALSE; 00234 pFM2impl->IInner_vtbl = &IInner_VTable; 00235 pFM2impl->lpVtbl = &fm2vtbl; 00236 pFM2impl->lpVtblFilterMapper = &fmvtbl; 00237 pFM2impl->lpVtblAMFilterData = &AMFilterDataVtbl; 00238 pFM2impl->refCount = 1; 00239 00240 *ppObj = pFM2impl; 00241 00242 TRACE("-- created at %p\n", pFM2impl); 00243 00244 return S_OK; 00245 } 00246 00247 HRESULT FilterMapper_create(IUnknown *pUnkOuter, LPVOID *ppObj) 00248 { 00249 FilterMapper2Impl *pFM2impl; 00250 HRESULT hr; 00251 00252 TRACE("(%p, %p)\n", pUnkOuter, ppObj); 00253 00254 hr = FilterMapper2_create(pUnkOuter, (LPVOID*)&pFM2impl); 00255 if (FAILED(hr)) 00256 return hr; 00257 00258 *ppObj = &pFM2impl->lpVtblFilterMapper; 00259 00260 return hr; 00261 } 00262 00263 /*** IUnknown (inner) methods ***/ 00264 00265 static HRESULT WINAPI Inner_QueryInterface(IUnknown * iface, REFIID riid, LPVOID * ppv) 00266 { 00267 FilterMapper2Impl *This = impl_from_inner_IUnknown(iface); 00268 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppv); 00269 00270 if (This->bAggregatable) 00271 This->bUnkOuterValid = TRUE; 00272 00273 *ppv = NULL; 00274 00275 if (IsEqualIID(riid, &IID_IUnknown)) 00276 *ppv = &This->IInner_vtbl; 00277 else if (IsEqualIID(riid, &IID_IFilterMapper2)) 00278 *ppv = This; 00279 else if (IsEqualIID(riid, &IID_IFilterMapper)) 00280 *ppv = &This->lpVtblFilterMapper; 00281 else if (IsEqualIID(riid, &IID_IAMFilterData)) 00282 *ppv = &This->lpVtblAMFilterData; 00283 00284 if (*ppv != NULL) 00285 { 00286 IUnknown_AddRef((IUnknown *)*ppv); 00287 return S_OK; 00288 } 00289 00290 FIXME("No interface for %s\n", debugstr_guid(riid)); 00291 return E_NOINTERFACE; 00292 } 00293 00294 static ULONG WINAPI Inner_AddRef(IUnknown * iface) 00295 { 00296 FilterMapper2Impl *This = impl_from_inner_IUnknown(iface); 00297 ULONG refCount = InterlockedIncrement(&This->refCount); 00298 00299 TRACE("(%p)->() AddRef from %d\n", This, refCount - 1); 00300 00301 return refCount; 00302 } 00303 00304 static ULONG WINAPI Inner_Release(IUnknown * iface) 00305 { 00306 FilterMapper2Impl *This = impl_from_inner_IUnknown(iface); 00307 ULONG refCount = InterlockedDecrement(&This->refCount); 00308 00309 TRACE("(%p)->() Release from %d\n", This, refCount + 1); 00310 00311 if (refCount == 0) 00312 { 00313 CoTaskMemFree(This); 00314 return 0; 00315 } 00316 return refCount; 00317 } 00318 00319 static const IUnknownVtbl IInner_VTable = 00320 { 00321 Inner_QueryInterface, 00322 Inner_AddRef, 00323 Inner_Release 00324 }; 00325 00326 static HRESULT WINAPI FilterMapper2_QueryInterface(IFilterMapper2 * iface, REFIID riid, LPVOID *ppv) 00327 { 00328 FilterMapper2Impl *This = (FilterMapper2Impl *)iface; 00329 00330 if (This->bAggregatable) 00331 This->bUnkOuterValid = TRUE; 00332 00333 if (This->pUnkOuter) 00334 { 00335 if (This->bAggregatable) 00336 return IUnknown_QueryInterface(This->pUnkOuter, riid, ppv); 00337 00338 if (IsEqualIID(riid, &IID_IUnknown)) 00339 { 00340 HRESULT hr; 00341 00342 IUnknown_AddRef((IUnknown *)&(This->IInner_vtbl)); 00343 hr = IUnknown_QueryInterface((IUnknown *)&(This->IInner_vtbl), riid, ppv); 00344 IUnknown_Release((IUnknown *)&(This->IInner_vtbl)); 00345 This->bAggregatable = TRUE; 00346 return hr; 00347 } 00348 00349 *ppv = NULL; 00350 return E_NOINTERFACE; 00351 } 00352 00353 return IUnknown_QueryInterface((IUnknown *)&(This->IInner_vtbl), riid, ppv); 00354 } 00355 00356 static ULONG WINAPI FilterMapper2_AddRef(IFilterMapper2 * iface) 00357 { 00358 FilterMapper2Impl *This = (FilterMapper2Impl *)iface; 00359 00360 if (This->pUnkOuter && This->bUnkOuterValid) 00361 return IUnknown_AddRef(This->pUnkOuter); 00362 return IUnknown_AddRef((IUnknown *)&(This->IInner_vtbl)); 00363 } 00364 00365 static ULONG WINAPI FilterMapper2_Release(IFilterMapper2 * iface) 00366 { 00367 FilterMapper2Impl *This = (FilterMapper2Impl *)iface; 00368 00369 if (This->pUnkOuter && This->bUnkOuterValid) 00370 return IUnknown_Release(This->pUnkOuter); 00371 return IUnknown_Release((IUnknown *)&(This->IInner_vtbl)); 00372 } 00373 00374 /*** IFilterMapper2 methods ***/ 00375 00376 static HRESULT WINAPI FilterMapper2_CreateCategory( 00377 IFilterMapper2 * iface, 00378 REFCLSID clsidCategory, 00379 DWORD dwCategoryMerit, 00380 LPCWSTR szDescription) 00381 { 00382 LPWSTR wClsidAMCat = NULL; 00383 LPWSTR wClsidCategory = NULL; 00384 WCHAR wszKeyName[ARRAYSIZE(wszClsidSlash)-1 + ARRAYSIZE(wszSlashInstance)-1 + (CHARS_IN_GUID-1) * 2 + 1]; 00385 HKEY hKey = NULL; 00386 LONG lRet; 00387 HRESULT hr; 00388 00389 TRACE("(%s, %x, %s)\n", debugstr_guid(clsidCategory), dwCategoryMerit, debugstr_w(szDescription)); 00390 00391 hr = StringFromCLSID(&CLSID_ActiveMovieCategories, &wClsidAMCat); 00392 00393 if (SUCCEEDED(hr)) 00394 { 00395 hr = StringFromCLSID(clsidCategory, &wClsidCategory); 00396 } 00397 00398 if (SUCCEEDED(hr)) 00399 { 00400 strcpyW(wszKeyName, wszClsidSlash); 00401 strcatW(wszKeyName, wClsidAMCat); 00402 strcatW(wszKeyName, wszSlashInstance); 00403 strcatW(wszKeyName, wClsidCategory); 00404 00405 lRet = RegCreateKeyExW(HKEY_CLASSES_ROOT, wszKeyName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL); 00406 hr = HRESULT_FROM_WIN32(lRet); 00407 } 00408 00409 if (SUCCEEDED(hr)) 00410 { 00411 lRet = RegSetValueExW(hKey, wszFriendlyName, 0, REG_SZ, (const BYTE*)szDescription, (strlenW(szDescription) + 1) * sizeof(WCHAR)); 00412 hr = HRESULT_FROM_WIN32(lRet); 00413 } 00414 00415 if (SUCCEEDED(hr)) 00416 { 00417 lRet = RegSetValueExW(hKey, wszClsidName, 0, REG_SZ, (LPBYTE)wClsidCategory, (strlenW(wClsidCategory) + 1) * sizeof(WCHAR)); 00418 hr = HRESULT_FROM_WIN32(lRet); 00419 } 00420 00421 if (SUCCEEDED(hr)) 00422 { 00423 lRet = RegSetValueExW(hKey, wszMeritName, 0, REG_DWORD, (LPBYTE)&dwCategoryMerit, sizeof(dwCategoryMerit)); 00424 hr = HRESULT_FROM_WIN32(lRet); 00425 } 00426 00427 CloseHandle(hKey); 00428 CoTaskMemFree(wClsidCategory); 00429 CoTaskMemFree(wClsidAMCat); 00430 00431 return hr; 00432 } 00433 00434 static HRESULT WINAPI FilterMapper2_UnregisterFilter( 00435 IFilterMapper2 * iface, 00436 const CLSID *pclsidCategory, 00437 const OLECHAR *szInstance, 00438 REFCLSID Filter) 00439 { 00440 WCHAR wszKeyName[MAX_PATH]; 00441 LPWSTR wClsidCategory = NULL; 00442 LPWSTR wFilter = NULL; 00443 HRESULT hr; 00444 00445 TRACE("(%p, %s, %s)\n", pclsidCategory, debugstr_w(szInstance), debugstr_guid(Filter)); 00446 00447 if (!pclsidCategory) 00448 pclsidCategory = &CLSID_LegacyAmFilterCategory; 00449 00450 hr = StringFromCLSID(pclsidCategory, &wClsidCategory); 00451 00452 if (SUCCEEDED(hr)) 00453 { 00454 strcpyW(wszKeyName, wszClsidSlash); 00455 strcatW(wszKeyName, wClsidCategory); 00456 strcatW(wszKeyName, wszSlashInstance); 00457 if (szInstance) 00458 strcatW(wszKeyName, szInstance); 00459 else 00460 { 00461 hr = StringFromCLSID(Filter, &wFilter); 00462 if (SUCCEEDED(hr)) 00463 strcatW(wszKeyName, wFilter); 00464 } 00465 } 00466 00467 if (SUCCEEDED(hr)) 00468 { 00469 LONG lRet = RegDeleteKeyW(HKEY_CLASSES_ROOT, wszKeyName); 00470 hr = HRESULT_FROM_WIN32(lRet); 00471 } 00472 00473 CoTaskMemFree(wClsidCategory); 00474 CoTaskMemFree(wFilter); 00475 00476 return hr; 00477 } 00478 00479 static HRESULT FM2_WriteFriendlyName(IPropertyBag * pPropBag, LPCWSTR szName) 00480 { 00481 VARIANT var; 00482 HRESULT ret; 00483 BSTR value; 00484 00485 V_VT(&var) = VT_BSTR; 00486 V_UNION(&var, bstrVal) = value = SysAllocString(szName); 00487 00488 ret = IPropertyBag_Write(pPropBag, wszFriendlyName, &var); 00489 SysFreeString(value); 00490 00491 return ret; 00492 } 00493 00494 static HRESULT FM2_WriteClsid(IPropertyBag * pPropBag, REFCLSID clsid) 00495 { 00496 LPWSTR wszClsid = NULL; 00497 VARIANT var; 00498 HRESULT hr; 00499 00500 hr = StringFromCLSID(clsid, &wszClsid); 00501 00502 if (SUCCEEDED(hr)) 00503 { 00504 V_VT(&var) = VT_BSTR; 00505 V_UNION(&var, bstrVal) = wszClsid; 00506 hr = IPropertyBag_Write(pPropBag, wszClsidName, &var); 00507 } 00508 CoTaskMemFree(wszClsid); 00509 return hr; 00510 } 00511 00512 static HRESULT FM2_WriteFilterData(const REGFILTER2 * prf2, BYTE **ppData, ULONG *pcbData) 00513 { 00514 int size = sizeof(struct REG_RF); 00515 unsigned int i; 00516 struct Vector mainStore = {NULL, 0, 0}; 00517 struct Vector clsidStore = {NULL, 0, 0}; 00518 struct REG_RF rrf; 00519 HRESULT hr = S_OK; 00520 00521 rrf.dwVersion = prf2->dwVersion; 00522 rrf.dwMerit = prf2->dwMerit; 00523 rrf.dwPins = prf2->u.s1.cPins2; 00524 rrf.dwUnused = 0; 00525 00526 add_data(&mainStore, (LPBYTE)&rrf, sizeof(rrf)); 00527 00528 for (i = 0; i < prf2->u.s1.cPins2; i++) 00529 { 00530 size += sizeof(struct REG_RFP); 00531 if (prf2->u.s1.rgPins2[i].clsPinCategory) 00532 size += sizeof(DWORD); 00533 size += prf2->u.s1.rgPins2[i].nMediaTypes * sizeof(struct REG_TYPE); 00534 size += prf2->u.s1.rgPins2[i].nMediums * sizeof(DWORD); 00535 } 00536 00537 for (i = 0; i < prf2->u.s1.cPins2; i++) 00538 { 00539 struct REG_RFP rrfp; 00540 REGFILTERPINS2 rgPin2 = prf2->u.s1.rgPins2[i]; 00541 unsigned int j; 00542 00543 rrfp.signature[0] = '0'; 00544 rrfp.signature[1] = 'p'; 00545 rrfp.signature[2] = 'i'; 00546 rrfp.signature[3] = '3'; 00547 rrfp.signature[0] += i; 00548 rrfp.dwFlags = rgPin2.dwFlags; 00549 rrfp.dwInstances = rgPin2.cInstances; 00550 rrfp.dwMediaTypes = rgPin2.nMediaTypes; 00551 rrfp.dwMediums = rgPin2.nMediums; 00552 rrfp.bCategory = rgPin2.clsPinCategory ? 1 : 0; 00553 00554 add_data(&mainStore, (LPBYTE)&rrfp, sizeof(rrfp)); 00555 if (rrfp.bCategory) 00556 { 00557 DWORD index = find_data(&clsidStore, (const BYTE*)rgPin2.clsPinCategory, sizeof(CLSID)); 00558 if (index == -1) 00559 index = add_data(&clsidStore, (const BYTE*)rgPin2.clsPinCategory, sizeof(CLSID)); 00560 index += size; 00561 00562 add_data(&mainStore, (LPBYTE)&index, sizeof(index)); 00563 } 00564 00565 for (j = 0; j < rgPin2.nMediaTypes; j++) 00566 { 00567 struct REG_TYPE rt; 00568 const CLSID * clsMinorType = rgPin2.lpMediaType[j].clsMinorType ? rgPin2.lpMediaType[j].clsMinorType : &MEDIASUBTYPE_NULL; 00569 rt.signature[0] = '0'; 00570 rt.signature[1] = 't'; 00571 rt.signature[2] = 'y'; 00572 rt.signature[3] = '3'; 00573 rt.signature[0] += j; 00574 rt.dwUnused = 0; 00575 rt.dwOffsetMajor = find_data(&clsidStore, (const BYTE*)rgPin2.lpMediaType[j].clsMajorType, sizeof(CLSID)); 00576 if (rt.dwOffsetMajor == -1) 00577 rt.dwOffsetMajor = add_data(&clsidStore, (const BYTE*)rgPin2.lpMediaType[j].clsMajorType, sizeof(CLSID)); 00578 rt.dwOffsetMajor += size; 00579 rt.dwOffsetMinor = find_data(&clsidStore, (const BYTE*)clsMinorType, sizeof(CLSID)); 00580 if (rt.dwOffsetMinor == -1) 00581 rt.dwOffsetMinor = add_data(&clsidStore, (const BYTE*)clsMinorType, sizeof(CLSID)); 00582 rt.dwOffsetMinor += size; 00583 00584 add_data(&mainStore, (LPBYTE)&rt, sizeof(rt)); 00585 } 00586 00587 for (j = 0; j < rgPin2.nMediums; j++) 00588 { 00589 DWORD index = find_data(&clsidStore, (const BYTE*)(rgPin2.lpMedium + j), sizeof(REGPINMEDIUM)); 00590 if (index == -1) 00591 index = add_data(&clsidStore, (const BYTE*)(rgPin2.lpMedium + j), sizeof(REGPINMEDIUM)); 00592 index += size; 00593 00594 add_data(&mainStore, (LPBYTE)&index, sizeof(index)); 00595 } 00596 } 00597 00598 if (SUCCEEDED(hr)) 00599 { 00600 *pcbData = mainStore.current + clsidStore.current; 00601 *ppData = CoTaskMemAlloc(*pcbData); 00602 if (!*ppData) 00603 hr = E_OUTOFMEMORY; 00604 } 00605 00606 if (SUCCEEDED(hr)) 00607 { 00608 memcpy(*ppData, mainStore.pData, mainStore.current); 00609 memcpy((*ppData) + mainStore.current, clsidStore.pData, clsidStore.current); 00610 } 00611 00612 delete_vector(&mainStore); 00613 delete_vector(&clsidStore); 00614 return hr; 00615 } 00616 00617 static HRESULT FM2_ReadFilterData(BYTE *pData, REGFILTER2 * prf2) 00618 { 00619 HRESULT hr = S_OK; 00620 struct REG_RF * prrf; 00621 LPBYTE pCurrent; 00622 DWORD i; 00623 REGFILTERPINS2 * rgPins2; 00624 00625 prrf = (struct REG_RF *)pData; 00626 pCurrent = pData; 00627 00628 if (prrf->dwVersion != 2) 00629 { 00630 FIXME("Filter registry version %d not supported\n", prrf->dwVersion); 00631 ZeroMemory(prf2, sizeof(*prf2)); 00632 hr = E_FAIL; 00633 } 00634 00635 if (SUCCEEDED(hr)) 00636 { 00637 TRACE("version = %d, merit = %x, #pins = %d, unused = %x\n", 00638 prrf->dwVersion, prrf->dwMerit, prrf->dwPins, prrf->dwUnused); 00639 00640 prf2->dwVersion = prrf->dwVersion; 00641 prf2->dwMerit = prrf->dwMerit; 00642 prf2->u.s1.cPins2 = prrf->dwPins; 00643 rgPins2 = CoTaskMemAlloc(prrf->dwPins * sizeof(*rgPins2)); 00644 prf2->u.s1.rgPins2 = rgPins2; 00645 pCurrent += sizeof(struct REG_RF); 00646 00647 for (i = 0; i < prrf->dwPins; i++) 00648 { 00649 struct REG_RFP * prrfp = (struct REG_RFP *)pCurrent; 00650 REGPINTYPES * lpMediaType; 00651 REGPINMEDIUM * lpMedium; 00652 UINT j; 00653 00654 /* FIXME: check signature */ 00655 00656 TRACE("\tsignature = %s\n", debugstr_an((const char*)prrfp->signature, 4)); 00657 00658 TRACE("\tpin[%d]: flags = %x, instances = %d, media types = %d, mediums = %d\n", 00659 i, prrfp->dwFlags, prrfp->dwInstances, prrfp->dwMediaTypes, prrfp->dwMediums); 00660 00661 rgPins2[i].dwFlags = prrfp->dwFlags; 00662 rgPins2[i].cInstances = prrfp->dwInstances; 00663 rgPins2[i].nMediaTypes = prrfp->dwMediaTypes; 00664 rgPins2[i].nMediums = prrfp->dwMediums; 00665 pCurrent += sizeof(struct REG_RFP); 00666 if (prrfp->bCategory) 00667 { 00668 CLSID * clsCat = CoTaskMemAlloc(sizeof(CLSID)); 00669 memcpy(clsCat, pData + *(DWORD*)(pCurrent), sizeof(CLSID)); 00670 pCurrent += sizeof(DWORD); 00671 rgPins2[i].clsPinCategory = clsCat; 00672 } 00673 else 00674 rgPins2[i].clsPinCategory = NULL; 00675 00676 if (rgPins2[i].nMediaTypes > 0) 00677 lpMediaType = CoTaskMemAlloc(rgPins2[i].nMediaTypes * sizeof(*lpMediaType)); 00678 else 00679 lpMediaType = NULL; 00680 00681 rgPins2[i].lpMediaType = lpMediaType; 00682 00683 for (j = 0; j < rgPins2[i].nMediaTypes; j++) 00684 { 00685 struct REG_TYPE * prt = (struct REG_TYPE *)pCurrent; 00686 CLSID * clsMajor = CoTaskMemAlloc(sizeof(CLSID)); 00687 CLSID * clsMinor = CoTaskMemAlloc(sizeof(CLSID)); 00688 00689 /* FIXME: check signature */ 00690 TRACE("\t\tsignature = %s\n", debugstr_an((const char*)prt->signature, 4)); 00691 00692 memcpy(clsMajor, pData + prt->dwOffsetMajor, sizeof(CLSID)); 00693 memcpy(clsMinor, pData + prt->dwOffsetMinor, sizeof(CLSID)); 00694 00695 lpMediaType[j].clsMajorType = clsMajor; 00696 lpMediaType[j].clsMinorType = clsMinor; 00697 00698 pCurrent += sizeof(*prt); 00699 } 00700 00701 if (rgPins2[i].nMediums > 0) 00702 lpMedium = CoTaskMemAlloc(rgPins2[i].nMediums * sizeof(*lpMedium)); 00703 else 00704 lpMedium = NULL; 00705 00706 rgPins2[i].lpMedium = lpMedium; 00707 00708 for (j = 0; j < rgPins2[i].nMediums; j++) 00709 { 00710 DWORD dwOffset = *(DWORD *)pCurrent; 00711 00712 memcpy(lpMedium + j, pData + dwOffset, sizeof(REGPINMEDIUM)); 00713 00714 pCurrent += sizeof(dwOffset); 00715 } 00716 } 00717 00718 } 00719 00720 return hr; 00721 } 00722 00723 static void FM2_DeleteRegFilter(REGFILTER2 * prf2) 00724 { 00725 UINT i; 00726 for (i = 0; i < prf2->u.s1.cPins2; i++) 00727 { 00728 UINT j; 00729 if (prf2->u.s1.rgPins2[i].clsPinCategory) 00730 CoTaskMemFree((LPVOID)prf2->u.s1.rgPins2[i].clsPinCategory); 00731 00732 for (j = 0; j < prf2->u.s1.rgPins2[i].nMediaTypes; j++) 00733 { 00734 CoTaskMemFree((LPVOID)prf2->u.s1.rgPins2[i].lpMediaType[j].clsMajorType); 00735 CoTaskMemFree((LPVOID)prf2->u.s1.rgPins2[i].lpMediaType[j].clsMinorType); 00736 } 00737 CoTaskMemFree((LPVOID)prf2->u.s1.rgPins2[i].lpMediaType); 00738 CoTaskMemFree((LPVOID)prf2->u.s1.rgPins2[i].lpMedium); 00739 } 00740 CoTaskMemFree((LPVOID)prf2->u.s1.rgPins2); 00741 } 00742 00743 static HRESULT WINAPI FilterMapper2_RegisterFilter( 00744 IFilterMapper2 * iface, 00745 REFCLSID clsidFilter, 00746 LPCWSTR szName, 00747 IMoniker **ppMoniker, 00748 const CLSID *pclsidCategory, 00749 const OLECHAR *szInstance, 00750 const REGFILTER2 *prf2) 00751 { 00752 IParseDisplayName * pParser = NULL; 00753 IBindCtx * pBindCtx = NULL; 00754 IMoniker * pMoniker = NULL; 00755 IPropertyBag * pPropBag = NULL; 00756 HRESULT hr; 00757 LPWSTR pwszParseName = NULL; 00758 LPWSTR pCurrent; 00759 static const WCHAR wszDevice[] = {'@','d','e','v','i','c','e',':','s','w',':',0}; 00760 int nameLen; 00761 ULONG ulEaten; 00762 LPWSTR szClsidTemp = NULL; 00763 REGFILTER2 regfilter2; 00764 REGFILTERPINS2* pregfp2 = NULL; 00765 00766 TRACE("(%s, %s, %p, %s, %s, %p)\n", 00767 debugstr_guid(clsidFilter), 00768 debugstr_w(szName), 00769 ppMoniker, 00770 debugstr_guid(pclsidCategory), 00771 debugstr_w(szInstance), 00772 prf2); 00773 00774 if (prf2->dwVersion == 2) 00775 { 00776 regfilter2 = *prf2; 00777 } 00778 else if (prf2->dwVersion == 1) 00779 { 00780 ULONG i; 00781 DWORD flags; 00782 /* REGFILTER2 structure is converted from version 1 to 2. Tested on Win2k. */ 00783 regfilter2.dwVersion = 2; 00784 regfilter2.dwMerit = prf2->dwMerit; 00785 regfilter2.u.s1.cPins2 = prf2->u.s.cPins; 00786 pregfp2 = CoTaskMemAlloc(prf2->u.s.cPins * sizeof(REGFILTERPINS2)); 00787 regfilter2.u.s1.rgPins2 = pregfp2; 00788 for (i = 0; i < prf2->u.s.cPins; i++) 00789 { 00790 flags = 0; 00791 if (prf2->u.s.rgPins[i].bRendered) 00792 flags |= REG_PINFLAG_B_RENDERER; 00793 if (prf2->u.s.rgPins[i].bOutput) 00794 flags |= REG_PINFLAG_B_OUTPUT; 00795 if (prf2->u.s.rgPins[i].bZero) 00796 flags |= REG_PINFLAG_B_ZERO; 00797 if (prf2->u.s.rgPins[i].bMany) 00798 flags |= REG_PINFLAG_B_MANY; 00799 pregfp2[i].dwFlags = flags; 00800 pregfp2[i].cInstances = 1; 00801 pregfp2[i].nMediaTypes = prf2->u.s.rgPins[i].nMediaTypes; 00802 pregfp2[i].lpMediaType = prf2->u.s.rgPins[i].lpMediaType; 00803 pregfp2[i].nMediums = 0; 00804 pregfp2[i].lpMedium = NULL; 00805 pregfp2[i].clsPinCategory = NULL; 00806 } 00807 } 00808 else 00809 { 00810 FIXME("dwVersion other that 1 or 2 not supported at the moment\n"); 00811 return E_NOTIMPL; 00812 } 00813 00814 if (ppMoniker) 00815 *ppMoniker = NULL; 00816 00817 if (!pclsidCategory) 00818 /* MSDN mentions the inexistent CLSID_ActiveMovieFilters GUID. 00819 * In fact this is the CLSID_LegacyAmFilterCategory one */ 00820 pclsidCategory = &CLSID_LegacyAmFilterCategory; 00821 00822 /* sizeof... will include the null terminator and 00823 * the + 1 is for the separator ('\\'). The -1 is 00824 * because CHARS_IN_GUID includes the null terminator 00825 */ 00826 nameLen = sizeof(wszDevice)/sizeof(wszDevice[0]) + CHARS_IN_GUID - 1 + 1; 00827 00828 if (szInstance) 00829 nameLen += strlenW(szInstance); 00830 else 00831 nameLen += CHARS_IN_GUID - 1; /* CHARS_IN_GUID includes null terminator */ 00832 00833 pCurrent = pwszParseName = CoTaskMemAlloc(nameLen*sizeof(WCHAR)); 00834 if (!pwszParseName) 00835 return E_OUTOFMEMORY; 00836 00837 strcpyW(pwszParseName, wszDevice); 00838 pCurrent += strlenW(wszDevice); 00839 00840 hr = StringFromCLSID(pclsidCategory, &szClsidTemp); 00841 00842 if (SUCCEEDED(hr)) 00843 { 00844 memcpy(pCurrent, szClsidTemp, CHARS_IN_GUID * sizeof(WCHAR)); 00845 pCurrent += CHARS_IN_GUID - 1; 00846 pCurrent[0] = '\\'; 00847 00848 if (szInstance) 00849 strcpyW(pCurrent+1, szInstance); 00850 else 00851 { 00852 CoTaskMemFree(szClsidTemp); 00853 szClsidTemp = NULL; 00854 00855 hr = StringFromCLSID(clsidFilter, &szClsidTemp); 00856 if (SUCCEEDED(hr)) 00857 strcpyW(pCurrent+1, szClsidTemp); 00858 } 00859 } 00860 00861 if (SUCCEEDED(hr)) 00862 hr = CoCreateInstance(&CLSID_CDeviceMoniker, NULL, CLSCTX_INPROC, &IID_IParseDisplayName, (LPVOID *)&pParser); 00863 00864 if (SUCCEEDED(hr)) 00865 hr = CreateBindCtx(0, &pBindCtx); 00866 00867 if (SUCCEEDED(hr)) 00868 hr = IParseDisplayName_ParseDisplayName(pParser, pBindCtx, pwszParseName, &ulEaten, &pMoniker); 00869 00870 if (pBindCtx) 00871 IBindCtx_Release(pBindCtx); 00872 if (pParser) 00873 IParseDisplayName_Release(pParser); 00874 00875 if (SUCCEEDED(hr)) 00876 hr = IMoniker_BindToStorage(pMoniker, NULL, NULL, &IID_IPropertyBag, (LPVOID)&pPropBag); 00877 00878 if (SUCCEEDED(hr)) 00879 hr = FM2_WriteFriendlyName(pPropBag, szName); 00880 00881 if (SUCCEEDED(hr)) 00882 hr = FM2_WriteClsid(pPropBag, clsidFilter); 00883 00884 if (SUCCEEDED(hr)) 00885 { 00886 BYTE *pData; 00887 ULONG cbData; 00888 00889 hr = FM2_WriteFilterData(®filter2, &pData, &cbData); 00890 if (SUCCEEDED(hr)) 00891 { 00892 VARIANT var; 00893 SAFEARRAY *psa; 00894 SAFEARRAYBOUND saBound; 00895 00896 saBound.lLbound = 0; 00897 saBound.cElements = cbData; 00898 psa = SafeArrayCreate(VT_UI1, 1, &saBound); 00899 if (!psa) 00900 { 00901 ERR("Couldn't create SAFEARRAY\n"); 00902 hr = E_FAIL; 00903 } 00904 00905 if (SUCCEEDED(hr)) 00906 { 00907 LPBYTE pbSAData; 00908 hr = SafeArrayAccessData(psa, (LPVOID *)&pbSAData); 00909 if (SUCCEEDED(hr)) 00910 { 00911 memcpy(pbSAData, pData, cbData); 00912 hr = SafeArrayUnaccessData(psa); 00913 } 00914 } 00915 00916 V_VT(&var) = VT_ARRAY | VT_UI1; 00917 V_UNION(&var, parray) = psa; 00918 00919 if (SUCCEEDED(hr)) 00920 hr = IPropertyBag_Write(pPropBag, wszFilterDataName, &var); 00921 00922 if (psa) 00923 SafeArrayDestroy(psa); 00924 CoTaskMemFree(pData); 00925 } 00926 } 00927 00928 if (pPropBag) 00929 IPropertyBag_Release(pPropBag); 00930 CoTaskMemFree(szClsidTemp); 00931 CoTaskMemFree(pwszParseName); 00932 00933 if (SUCCEEDED(hr) && ppMoniker) 00934 *ppMoniker = pMoniker; 00935 else if (pMoniker) 00936 IMoniker_Release(pMoniker); 00937 00938 CoTaskMemFree(pregfp2); 00939 00940 TRACE("-- returning %x\n", hr); 00941 00942 return hr; 00943 } 00944 00945 /* internal helper function */ 00946 static BOOL MatchTypes( 00947 BOOL bExactMatch, 00948 DWORD nPinTypes, 00949 const REGPINTYPES * pPinTypes, 00950 DWORD nMatchTypes, 00951 const GUID * pMatchTypes) 00952 { 00953 BOOL bMatch = FALSE; 00954 DWORD j; 00955 00956 if ((nMatchTypes == 0) && (nPinTypes > 0)) 00957 bMatch = TRUE; 00958 00959 for (j = 0; j < nPinTypes; j++) 00960 { 00961 DWORD i; 00962 for (i = 0; i < nMatchTypes*2; i+=2) 00963 { 00964 if (((!bExactMatch && IsEqualGUID(pPinTypes[j].clsMajorType, &GUID_NULL)) || IsEqualGUID(&pMatchTypes[i], &GUID_NULL) || IsEqualGUID(pPinTypes[j].clsMajorType, &pMatchTypes[i])) && 00965 ((!bExactMatch && IsEqualGUID(pPinTypes[j].clsMinorType, &GUID_NULL)) || IsEqualGUID(&pMatchTypes[i+1], &GUID_NULL) || IsEqualGUID(pPinTypes[j].clsMinorType, &pMatchTypes[i+1]))) 00966 { 00967 bMatch = TRUE; 00968 break; 00969 } 00970 } 00971 } 00972 return bMatch; 00973 } 00974 00975 /* internal helper function for qsort of MONIKER_MERIT array */ 00976 static int mm_compare(const void * left, const void * right) 00977 { 00978 const struct MONIKER_MERIT * mmLeft = left; 00979 const struct MONIKER_MERIT * mmRight = right; 00980 00981 if (mmLeft->dwMerit == mmRight->dwMerit) 00982 return 0; 00983 if (mmLeft->dwMerit > mmRight->dwMerit) 00984 return -1; 00985 return 1; 00986 } 00987 00988 /* NOTES: 00989 * Exact match means whether or not to treat GUID_NULL's in filter data as wild cards 00990 * (GUID_NULL's in input to function automatically treated as wild cards) 00991 * Input/Output needed means match only on criteria if TRUE (with zero input types 00992 * meaning match any input/output pin as long as one exists), otherwise match any 00993 * filter that meets the rest of the requirements. 00994 */ 00995 static HRESULT WINAPI FilterMapper2_EnumMatchingFilters( 00996 IFilterMapper2 * iface, 00997 IEnumMoniker **ppEnum, 00998 DWORD dwFlags, 00999 BOOL bExactMatch, 01000 DWORD dwMerit, 01001 BOOL bInputNeeded, 01002 DWORD cInputTypes, 01003 const GUID *pInputTypes, 01004 const REGPINMEDIUM *pMedIn, 01005 const CLSID *pPinCategoryIn, 01006 BOOL bRender, 01007 BOOL bOutputNeeded, 01008 DWORD cOutputTypes, 01009 const GUID *pOutputTypes, 01010 const REGPINMEDIUM *pMedOut, 01011 const CLSID *pPinCategoryOut) 01012 { 01013 ICreateDevEnum * pCreateDevEnum; 01014 IMoniker * pMonikerCat; 01015 IEnumMoniker * pEnumCat; 01016 HRESULT hr; 01017 struct Vector monikers = {NULL, 0, 0}; 01018 01019 TRACE("(%p, %x, %s, %x, %s, %d, %p, %p, %p, %s, %s, %p, %p, %p)\n", 01020 ppEnum, 01021 dwFlags, 01022 bExactMatch ? "true" : "false", 01023 dwMerit, 01024 bInputNeeded ? "true" : "false", 01025 cInputTypes, 01026 pInputTypes, 01027 pMedIn, 01028 pPinCategoryIn, 01029 bRender ? "true" : "false", 01030 bOutputNeeded ? "true" : "false", 01031 pOutputTypes, 01032 pMedOut, 01033 pPinCategoryOut); 01034 01035 if (dwFlags != 0) 01036 { 01037 FIXME("dwFlags = %x not implemented\n", dwFlags); 01038 } 01039 01040 *ppEnum = NULL; 01041 01042 hr = CoCreateInstance(&CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC, &IID_ICreateDevEnum, (LPVOID*)&pCreateDevEnum); 01043 if (FAILED(hr)) 01044 return hr; 01045 01046 hr = ICreateDevEnum_CreateClassEnumerator(pCreateDevEnum, &CLSID_ActiveMovieCategories, &pEnumCat, 0); 01047 if (FAILED(hr)) { 01048 ICreateDevEnum_Release(pCreateDevEnum); 01049 return hr; 01050 } 01051 01052 while (IEnumMoniker_Next(pEnumCat, 1, &pMonikerCat, NULL) == S_OK) 01053 { 01054 IPropertyBag * pPropBagCat = NULL; 01055 VARIANT var; 01056 HRESULT hrSub; /* this is so that one buggy filter 01057 doesn't make the whole lot fail */ 01058 01059 VariantInit(&var); 01060 01061 hrSub = IMoniker_BindToStorage(pMonikerCat, NULL, NULL, &IID_IPropertyBag, (LPVOID*)&pPropBagCat); 01062 01063 if (SUCCEEDED(hrSub)) 01064 hrSub = IPropertyBag_Read(pPropBagCat, wszMeritName, &var, NULL); 01065 01066 if (SUCCEEDED(hrSub) && (V_UNION(&var, ulVal) >= dwMerit)) 01067 { 01068 CLSID clsidCat; 01069 IEnumMoniker * pEnum; 01070 IMoniker * pMoniker; 01071 01072 VariantClear(&var); 01073 01074 if (TRACE_ON(quartz)) 01075 { 01076 VARIANT temp; 01077 V_VT(&temp) = VT_EMPTY; 01078 IPropertyBag_Read(pPropBagCat, wszFriendlyName, &temp, NULL); 01079 TRACE("Considering category %s\n", debugstr_w(V_UNION(&temp, bstrVal))); 01080 VariantClear(&temp); 01081 } 01082 01083 hrSub = IPropertyBag_Read(pPropBagCat, wszClsidName, &var, NULL); 01084 01085 if (SUCCEEDED(hrSub)) 01086 hrSub = CLSIDFromString(V_UNION(&var, bstrVal), &clsidCat); 01087 01088 if (SUCCEEDED(hrSub)) 01089 hrSub = ICreateDevEnum_CreateClassEnumerator(pCreateDevEnum, &clsidCat, &pEnum, 0); 01090 01091 if (hrSub == S_OK) 01092 { 01093 while (IEnumMoniker_Next(pEnum, 1, &pMoniker, NULL) == S_OK) 01094 { 01095 IPropertyBag * pPropBag = NULL; 01096 VARIANT var; 01097 BYTE *pData = NULL; 01098 REGFILTER2 rf2; 01099 DWORD i; 01100 BOOL bInputMatch = !bInputNeeded; 01101 BOOL bOutputMatch = !bOutputNeeded; 01102 01103 ZeroMemory(&rf2, sizeof(rf2)); 01104 VariantInit(&var); 01105 01106 hrSub = IMoniker_BindToStorage(pMoniker, NULL, NULL, &IID_IPropertyBag, (LPVOID*)&pPropBag); 01107 01108 if (TRACE_ON(quartz)) 01109 { 01110 VARIANT temp; 01111 V_VT(&temp) = VT_EMPTY; 01112 IPropertyBag_Read(pPropBag, wszFriendlyName, &temp, NULL); 01113 TRACE("Considering filter %s\n", debugstr_w(V_UNION(&temp, bstrVal))); 01114 VariantClear(&temp); 01115 } 01116 01117 if (SUCCEEDED(hrSub)) 01118 { 01119 hrSub = IPropertyBag_Read(pPropBag, wszFilterDataName, &var, NULL); 01120 } 01121 01122 if (SUCCEEDED(hrSub)) 01123 hrSub = SafeArrayAccessData(V_UNION(&var, parray), (LPVOID*)&pData); 01124 01125 if (SUCCEEDED(hrSub)) 01126 hrSub = FM2_ReadFilterData(pData, &rf2); 01127 01128 if (pData) 01129 SafeArrayUnaccessData(V_UNION(&var, parray)); 01130 01131 VariantClear(&var); 01132 01133 /* Logic used for bInputMatch expression: 01134 * There exists some pin such that bInputNeeded implies (pin is an input and 01135 * (bRender implies pin has render flag) and major/minor types members of 01136 * pInputTypes ) 01137 * bOutputMatch is similar, but without the "bRender implies ..." part 01138 * and substituting variables names containing input for output 01139 */ 01140 01141 /* determine whether filter meets requirements */ 01142 if (SUCCEEDED(hrSub) && (rf2.dwMerit >= dwMerit)) 01143 { 01144 for (i = 0; (i < rf2.u.s1.cPins2) && (!bInputMatch || !bOutputMatch); i++) 01145 { 01146 const REGFILTERPINS2 * rfp2 = rf2.u.s1.rgPins2 + i; 01147 01148 bInputMatch = bInputMatch || (!(rfp2->dwFlags & REG_PINFLAG_B_OUTPUT) && 01149 (!bRender || (rfp2->dwFlags & REG_PINFLAG_B_RENDERER)) && 01150 MatchTypes(bExactMatch, rfp2->nMediaTypes, rfp2->lpMediaType, cInputTypes, pInputTypes)); 01151 bOutputMatch = bOutputMatch || ((rfp2->dwFlags & REG_PINFLAG_B_OUTPUT) && 01152 MatchTypes(bExactMatch, rfp2->nMediaTypes, rfp2->lpMediaType, cOutputTypes, pOutputTypes)); 01153 } 01154 01155 if (bInputMatch && bOutputMatch) 01156 { 01157 struct MONIKER_MERIT mm = {pMoniker, rf2.dwMerit}; 01158 IMoniker_AddRef(pMoniker); 01159 add_data(&monikers, (LPBYTE)&mm, sizeof(mm)); 01160 } 01161 } 01162 01163 FM2_DeleteRegFilter(&rf2); 01164 if (pPropBag) 01165 IPropertyBag_Release(pPropBag); 01166 IMoniker_Release(pMoniker); 01167 } 01168 IEnumMoniker_Release(pEnum); 01169 } 01170 } 01171 01172 VariantClear(&var); 01173 if (pPropBagCat) 01174 IPropertyBag_Release(pPropBagCat); 01175 IMoniker_Release(pMonikerCat); 01176 } 01177 01178 if (SUCCEEDED(hr)) 01179 { 01180 IMoniker ** ppMoniker; 01181 unsigned int i; 01182 ULONG nMonikerCount = monikers.current / sizeof(struct MONIKER_MERIT); 01183 01184 /* sort the monikers in descending merit order */ 01185 qsort(monikers.pData, nMonikerCount, 01186 sizeof(struct MONIKER_MERIT), 01187 mm_compare); 01188 01189 /* construct an IEnumMoniker interface */ 01190 ppMoniker = CoTaskMemAlloc(nMonikerCount * sizeof(IMoniker *)); 01191 for (i = 0; i < nMonikerCount; i++) 01192 { 01193 /* no need to AddRef here as already AddRef'd above */ 01194 ppMoniker[i] = ((struct MONIKER_MERIT *)monikers.pData)[i].pMoniker; 01195 } 01196 hr = EnumMonikerImpl_Create(ppMoniker, nMonikerCount, ppEnum); 01197 CoTaskMemFree(ppMoniker); 01198 } 01199 01200 delete_vector(&monikers); 01201 IEnumMoniker_Release(pEnumCat); 01202 ICreateDevEnum_Release(pCreateDevEnum); 01203 01204 return hr; 01205 } 01206 01207 static const IFilterMapper2Vtbl fm2vtbl = 01208 { 01209 01210 FilterMapper2_QueryInterface, 01211 FilterMapper2_AddRef, 01212 FilterMapper2_Release, 01213 01214 FilterMapper2_CreateCategory, 01215 FilterMapper2_UnregisterFilter, 01216 FilterMapper2_RegisterFilter, 01217 FilterMapper2_EnumMatchingFilters 01218 }; 01219 01220 /*** IUnknown methods ***/ 01221 01222 static HRESULT WINAPI FilterMapper_QueryInterface(IFilterMapper * iface, REFIID riid, LPVOID *ppv) 01223 { 01224 FilterMapper2Impl *This = impl_from_IFilterMapper(iface); 01225 01226 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppv); 01227 01228 return FilterMapper2_QueryInterface((IFilterMapper2*)&This->lpVtbl, riid, ppv); 01229 } 01230 01231 static ULONG WINAPI FilterMapper_AddRef(IFilterMapper * iface) 01232 { 01233 FilterMapper2Impl *This = impl_from_IFilterMapper(iface); 01234 01235 return FilterMapper2_AddRef((IFilterMapper2*)This); 01236 } 01237 01238 static ULONG WINAPI FilterMapper_Release(IFilterMapper * iface) 01239 { 01240 FilterMapper2Impl *This = impl_from_IFilterMapper(iface); 01241 01242 return FilterMapper2_Release((IFilterMapper2*)This); 01243 } 01244 01245 /*** IFilterMapper methods ***/ 01246 01247 static HRESULT WINAPI FilterMapper_EnumMatchingFilters( 01248 IFilterMapper * iface, 01249 IEnumRegFilters **ppEnum, 01250 DWORD dwMerit, 01251 BOOL bInputNeeded, 01252 CLSID clsInMaj, 01253 CLSID clsInSub, 01254 BOOL bRender, 01255 BOOL bOutputNeeded, 01256 CLSID clsOutMaj, 01257 CLSID clsOutSub) 01258 { 01259 FilterMapper2Impl *This = impl_from_IFilterMapper(iface); 01260 GUID InputType[2]; 01261 GUID OutputType[2]; 01262 IEnumMoniker* ppEnumMoniker; 01263 IMoniker* IMon; 01264 ULONG nb; 01265 ULONG idx = 0, nb_mon = 0; 01266 REGFILTER* regfilters; 01267 HRESULT hr; 01268 01269 TRACE("(%p/%p)->(%p, %x, %s, %s, %s, %s, %s, %s, %s) stub!\n", 01270 iface,This, 01271 ppEnum, 01272 dwMerit, 01273 bInputNeeded ? "true" : "false", 01274 debugstr_guid(&clsInMaj), 01275 debugstr_guid(&clsInSub), 01276 bRender ? "true" : "false", 01277 bOutputNeeded ? "true" : "false", 01278 debugstr_guid(&clsOutMaj), 01279 debugstr_guid(&clsOutSub)); 01280 01281 InputType[0] = clsInMaj; 01282 InputType[1] = clsInSub; 01283 OutputType[0] = clsOutMaj; 01284 OutputType[1] = clsOutSub; 01285 01286 *ppEnum = NULL; 01287 01288 hr = IFilterMapper2_EnumMatchingFilters((IFilterMapper2*)This, 01289 &ppEnumMoniker, 01290 0, 01291 TRUE, 01292 dwMerit, 01293 bInputNeeded, 01294 1, 01295 InputType, 01296 NULL, 01297 &GUID_NULL, 01298 bRender, 01299 bOutputNeeded, 01300 1, 01301 OutputType, 01302 NULL, 01303 &GUID_NULL); 01304 01305 if (FAILED(hr)) 01306 return hr; 01307 01308 while(IEnumMoniker_Next(ppEnumMoniker, 1, &IMon, &nb) == S_OK) 01309 { 01310 IMoniker_Release(IMon); 01311 nb_mon++; 01312 } 01313 01314 if (!nb_mon) 01315 { 01316 IEnumMoniker_Release(ppEnumMoniker); 01317 return IEnumRegFiltersImpl_Construct(NULL, 0, ppEnum); 01318 } 01319 01320 regfilters = CoTaskMemAlloc(nb_mon * sizeof(REGFILTER)); 01321 if (!regfilters) 01322 { 01323 IEnumMoniker_Release(ppEnumMoniker); 01324 return E_OUTOFMEMORY; 01325 } 01326 ZeroMemory(regfilters, nb_mon * sizeof(REGFILTER)); /* will prevent bad free of Name in case of error. */ 01327 01328 IEnumMoniker_Reset(ppEnumMoniker); 01329 while(IEnumMoniker_Next(ppEnumMoniker, 1, &IMon, &nb) == S_OK) 01330 { 01331 IPropertyBag * pPropBagCat = NULL; 01332 VARIANT var; 01333 HRESULT hrSub; 01334 GUID clsid; 01335 int len; 01336 01337 VariantInit(&var); 01338 01339 hrSub = IMoniker_BindToStorage(IMon, NULL, NULL, &IID_IPropertyBag, (LPVOID*)&pPropBagCat); 01340 01341 if (SUCCEEDED(hrSub)) 01342 hrSub = IPropertyBag_Read(pPropBagCat, wszClsidName, &var, NULL); 01343 01344 if (SUCCEEDED(hrSub)) 01345 hrSub = CLSIDFromString(V_UNION(&var, bstrVal), &clsid); 01346 01347 VariantClear(&var); 01348 01349 if (SUCCEEDED(hrSub)) 01350 hrSub = IPropertyBag_Read(pPropBagCat, wszFriendlyName, &var, NULL); 01351 01352 if (SUCCEEDED(hrSub)) 01353 { 01354 len = (strlenW(V_UNION(&var, bstrVal))+1) * sizeof(WCHAR); 01355 if (!(regfilters[idx].Name = CoTaskMemAlloc(len*2))) 01356 hr = E_OUTOFMEMORY; 01357 } 01358 01359 if (SUCCEEDED(hrSub) && regfilters[idx].Name) 01360 { 01361 memcpy(regfilters[idx].Name, V_UNION(&var, bstrVal), len); 01362 regfilters[idx].Clsid = clsid; 01363 idx++; 01364 } 01365 01366 if (pPropBagCat) 01367 IPropertyBag_Release(pPropBagCat); 01368 IMoniker_Release(IMon); 01369 VariantClear(&var); 01370 } 01371 01372 if (SUCCEEDED(hr)) 01373 { 01374 hr = IEnumRegFiltersImpl_Construct(regfilters, nb_mon, ppEnum); 01375 } 01376 01377 for (idx = 0; idx < nb_mon; idx++) 01378 CoTaskMemFree(regfilters[idx].Name); 01379 CoTaskMemFree(regfilters); 01380 IEnumMoniker_Release(ppEnumMoniker); 01381 01382 return hr; 01383 } 01384 01385 01386 static HRESULT WINAPI FilterMapper_RegisterFilter(IFilterMapper * iface, CLSID clsid, LPCWSTR szName, DWORD dwMerit) 01387 { 01388 HRESULT hr; 01389 LPWSTR wszClsid = NULL; 01390 HKEY hKey; 01391 LONG lRet; 01392 WCHAR wszKeyName[ARRAYSIZE(wszFilterSlash)-1 + (CHARS_IN_GUID-1) + 1]; 01393 01394 TRACE("(%p)->(%s, %s, %x)\n", iface, debugstr_guid(&clsid), debugstr_w(szName), dwMerit); 01395 01396 hr = StringFromCLSID(&clsid, &wszClsid); 01397 01398 if (SUCCEEDED(hr)) 01399 { 01400 strcpyW(wszKeyName, wszFilterSlash); 01401 strcatW(wszKeyName, wszClsid); 01402 01403 lRet = RegCreateKeyExW(HKEY_CLASSES_ROOT, wszKeyName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL); 01404 hr = HRESULT_FROM_WIN32(lRet); 01405 } 01406 01407 if (SUCCEEDED(hr)) 01408 { 01409 lRet = RegSetValueExW(hKey, NULL, 0, REG_SZ, (const BYTE*)szName, (strlenW(szName) + 1) * sizeof(WCHAR)); 01410 hr = HRESULT_FROM_WIN32(lRet); 01411 CloseHandle(hKey); 01412 } 01413 01414 if (SUCCEEDED(hr)) 01415 { 01416 strcpyW(wszKeyName, wszClsidSlash); 01417 strcatW(wszKeyName, wszClsid); 01418 01419 lRet = RegCreateKeyExW(HKEY_CLASSES_ROOT, wszKeyName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL); 01420 hr = HRESULT_FROM_WIN32(lRet); 01421 } 01422 01423 if (SUCCEEDED(hr)) 01424 { 01425 lRet = RegSetValueExW(hKey, wszMeritName, 0, REG_DWORD, (LPBYTE)&dwMerit, sizeof(dwMerit)); 01426 hr = HRESULT_FROM_WIN32(lRet); 01427 CloseHandle(hKey); 01428 } 01429 01430 CoTaskMemFree(wszClsid); 01431 01432 return hr; 01433 } 01434 01435 static HRESULT WINAPI FilterMapper_RegisterFilterInstance(IFilterMapper * iface, CLSID clsid, LPCWSTR szName, CLSID *MRId) 01436 { 01437 TRACE("(%p)->(%s, %s, %p)\n", iface, debugstr_guid(&clsid), debugstr_w(szName), MRId); 01438 01439 /* Not implemented in Windows (tested on Win2k) */ 01440 01441 return E_NOTIMPL; 01442 } 01443 01444 static HRESULT WINAPI FilterMapper_RegisterPin( 01445 IFilterMapper * iface, 01446 CLSID Filter, 01447 LPCWSTR szName, 01448 BOOL bRendered, 01449 BOOL bOutput, 01450 BOOL bZero, 01451 BOOL bMany, 01452 CLSID ConnectsToFilter, 01453 LPCWSTR ConnectsToPin) 01454 { 01455 HRESULT hr; 01456 LONG lRet; 01457 LPWSTR wszClsid = NULL; 01458 HKEY hKey = NULL; 01459 HKEY hPinsKey = NULL; 01460 WCHAR * wszPinsKeyName; 01461 WCHAR wszKeyName[ARRAYSIZE(wszClsidSlash)-1 + (CHARS_IN_GUID-1) + 1]; 01462 01463 TRACE("(%p)->(%s, %s, %d, %d, %d, %d, %s, %s)\n", iface, debugstr_guid(&Filter), debugstr_w(szName), bRendered, 01464 bOutput, bZero, bMany, debugstr_guid(&ConnectsToFilter), debugstr_w(ConnectsToPin)); 01465 01466 hr = StringFromCLSID(&Filter, &wszClsid); 01467 01468 if (SUCCEEDED(hr)) 01469 { 01470 strcpyW(wszKeyName, wszClsidSlash); 01471 strcatW(wszKeyName, wszClsid); 01472 01473 lRet = RegOpenKeyExW(HKEY_CLASSES_ROOT, wszKeyName, 0, KEY_WRITE, &hKey); 01474 hr = HRESULT_FROM_WIN32(lRet); 01475 } 01476 01477 if (SUCCEEDED(hr)) 01478 { 01479 wszPinsKeyName = CoTaskMemAlloc((strlenW(wszPins) + 1 + strlenW(szName) + 1) * 2); 01480 if (!wszPinsKeyName) 01481 hr = E_OUTOFMEMORY; 01482 } 01483 01484 if (SUCCEEDED(hr)) 01485 { 01486 strcpyW(wszPinsKeyName, wszPins); 01487 strcatW(wszPinsKeyName, wszSlash); 01488 strcatW(wszPinsKeyName, szName); 01489 01490 lRet = RegCreateKeyExW(hKey, wszPinsKeyName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hPinsKey, NULL); 01491 hr = HRESULT_FROM_WIN32(lRet); 01492 CoTaskMemFree(wszPinsKeyName); 01493 } 01494 01495 if (SUCCEEDED(hr)) 01496 { 01497 lRet = RegSetValueExW(hPinsKey, wszAllowedMany, 0, REG_DWORD, (LPBYTE)&bMany, sizeof(bMany)); 01498 hr = HRESULT_FROM_WIN32(lRet); 01499 } 01500 01501 if (SUCCEEDED(hr)) 01502 { 01503 lRet = RegSetValueExW(hPinsKey, wszAllowedZero, 0, REG_DWORD, (LPBYTE)&bZero, sizeof(bZero)); 01504 hr = HRESULT_FROM_WIN32(lRet); 01505 } 01506 01507 if (SUCCEEDED(hr)) 01508 { 01509 lRet = RegSetValueExW(hPinsKey, wszDirection, 0, REG_DWORD, (LPBYTE)&bOutput, sizeof(bOutput)); 01510 hr = HRESULT_FROM_WIN32(lRet); 01511 } 01512 01513 if (SUCCEEDED(hr)) 01514 { 01515 lRet = RegSetValueExW(hPinsKey, wszIsRendered, 0, REG_DWORD, (LPBYTE)&bRendered, sizeof(bRendered)); 01516 hr = HRESULT_FROM_WIN32(lRet); 01517 } 01518 01519 if (SUCCEEDED(hr)) 01520 { 01521 HKEY hkeyDummy = NULL; 01522 01523 lRet = RegCreateKeyExW(hPinsKey, wszTypes, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hkeyDummy, NULL); 01524 hr = HRESULT_FROM_WIN32(lRet); 01525 01526 if (hkeyDummy) RegCloseKey(hkeyDummy); 01527 } 01528 01529 CoTaskMemFree(wszClsid); 01530 if (hKey) 01531 CloseHandle(hKey); 01532 if (hPinsKey) 01533 CloseHandle(hPinsKey); 01534 01535 return hr; 01536 } 01537 01538 01539 static HRESULT WINAPI FilterMapper_RegisterPinType( 01540 IFilterMapper * iface, 01541 CLSID clsFilter, 01542 LPCWSTR szName, 01543 CLSID clsMajorType, 01544 CLSID clsSubType) 01545 { 01546 HRESULT hr; 01547 LONG lRet; 01548 LPWSTR wszClsid = NULL; 01549 LPWSTR wszClsidMajorType = NULL; 01550 LPWSTR wszClsidSubType = NULL; 01551 HKEY hKey = NULL; 01552 WCHAR * wszTypesKey; 01553 WCHAR wszKeyName[MAX_PATH]; 01554 01555 TRACE("(%p)->(%s, %s, %s, %s)\n", iface, debugstr_guid(&clsFilter), debugstr_w(szName), 01556 debugstr_guid(&clsMajorType), debugstr_guid(&clsSubType)); 01557 01558 hr = StringFromCLSID(&clsFilter, &wszClsid); 01559 01560 if (SUCCEEDED(hr)) 01561 { 01562 hr = StringFromCLSID(&clsMajorType, &wszClsidMajorType); 01563 } 01564 01565 if (SUCCEEDED(hr)) 01566 { 01567 hr = StringFromCLSID(&clsSubType, &wszClsidSubType); 01568 } 01569 01570 if (SUCCEEDED(hr)) 01571 { 01572 wszTypesKey = CoTaskMemAlloc((strlenW(wszClsidSlash) + strlenW(wszClsid) + strlenW(wszPins) + 01573 strlenW(szName) + strlenW(wszTypes) + 3 + 1) * 2); 01574 if (!wszTypesKey) 01575 hr = E_OUTOFMEMORY; 01576 } 01577 01578 if (SUCCEEDED(hr)) 01579 { 01580 strcpyW(wszTypesKey, wszClsidSlash); 01581 strcatW(wszTypesKey, wszClsid); 01582 strcatW(wszTypesKey, wszSlash); 01583 strcatW(wszTypesKey, wszPins); 01584 strcatW(wszTypesKey, wszSlash); 01585 strcatW(wszTypesKey, szName); 01586 strcatW(wszTypesKey, wszSlash); 01587 strcatW(wszTypesKey, wszTypes); 01588 01589 lRet = RegOpenKeyExW(HKEY_CLASSES_ROOT, wszTypesKey, 0, KEY_WRITE, &hKey); 01590 hr = HRESULT_FROM_WIN32(lRet); 01591 CoTaskMemFree(wszTypesKey); 01592 } 01593 01594 if (SUCCEEDED(hr)) 01595 { 01596 HKEY hkeyDummy = NULL; 01597 01598 strcpyW(wszKeyName, wszClsidMajorType); 01599 strcatW(wszKeyName, wszSlash); 01600 strcatW(wszKeyName, wszClsidSubType); 01601 01602 lRet = RegCreateKeyExW(hKey, wszKeyName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hkeyDummy, NULL); 01603 hr = HRESULT_FROM_WIN32(lRet); 01604 CloseHandle(hKey); 01605 01606 if (hkeyDummy) RegCloseKey(hkeyDummy); 01607 } 01608 01609 CoTaskMemFree(wszClsid); 01610 CoTaskMemFree(wszClsidMajorType); 01611 CoTaskMemFree(wszClsidSubType); 01612 01613 return hr; 01614 } 01615 01616 static HRESULT WINAPI FilterMapper_UnregisterFilter(IFilterMapper * iface, CLSID Filter) 01617 { 01618 HRESULT hr; 01619 LONG lRet; 01620 LPWSTR wszClsid = NULL; 01621 HKEY hKey; 01622 WCHAR wszKeyName[ARRAYSIZE(wszClsidSlash)-1 + (CHARS_IN_GUID-1) + 1]; 01623 01624 TRACE("(%p)->(%s)\n", iface, debugstr_guid(&Filter)); 01625 01626 hr = StringFromCLSID(&Filter, &wszClsid); 01627 01628 if (SUCCEEDED(hr)) 01629 { 01630 lRet = RegOpenKeyExW(HKEY_CLASSES_ROOT, wszFilter, 0, KEY_WRITE, &hKey); 01631 hr = HRESULT_FROM_WIN32(lRet); 01632 } 01633 01634 if (SUCCEEDED(hr)) 01635 { 01636 lRet = RegDeleteKeyW(hKey, wszClsid); 01637 hr = HRESULT_FROM_WIN32(lRet); 01638 CloseHandle(hKey); 01639 } 01640 01641 if (SUCCEEDED(hr)) 01642 { 01643 strcpyW(wszKeyName, wszClsidSlash); 01644 strcatW(wszKeyName, wszClsid); 01645 01646 lRet = RegOpenKeyExW(HKEY_CLASSES_ROOT, wszKeyName, 0, KEY_WRITE, &hKey); 01647 hr = HRESULT_FROM_WIN32(lRet); 01648 } 01649 01650 if (SUCCEEDED(hr)) 01651 { 01652 lRet = RegDeleteValueW(hKey, wszMeritName); 01653 if (lRet != ERROR_SUCCESS) 01654 hr = HRESULT_FROM_WIN32(lRet); 01655 01656 lRet = RegDeleteTreeW(hKey, wszPins); 01657 if (lRet != ERROR_SUCCESS) 01658 hr = HRESULT_FROM_WIN32(lRet); 01659 01660 CloseHandle(hKey); 01661 } 01662 01663 CoTaskMemFree(wszClsid); 01664 01665 return hr; 01666 } 01667 01668 static HRESULT WINAPI FilterMapper_UnregisterFilterInstance(IFilterMapper * iface, CLSID MRId) 01669 { 01670 TRACE("(%p)->(%s)\n", iface, debugstr_guid(&MRId)); 01671 01672 /* Not implemented in Windows (tested on Win2k) */ 01673 01674 return E_NOTIMPL; 01675 } 01676 01677 static HRESULT WINAPI FilterMapper_UnregisterPin(IFilterMapper * iface, CLSID Filter, LPCWSTR Name) 01678 { 01679 HRESULT hr; 01680 LONG lRet; 01681 LPWSTR wszClsid = NULL; 01682 HKEY hKey = NULL; 01683 WCHAR * wszPinNameKey; 01684 WCHAR wszKeyName[ARRAYSIZE(wszClsidSlash)-1 + (CHARS_IN_GUID-1) + 1]; 01685 01686 TRACE("(%p)->(%s, %s)\n", iface, debugstr_guid(&Filter), debugstr_w(Name)); 01687 01688 if (!Name) 01689 return E_INVALIDARG; 01690 01691 hr = StringFromCLSID(&Filter, &wszClsid); 01692 01693 if (SUCCEEDED(hr)) 01694 { 01695 strcpyW(wszKeyName, wszClsidSlash); 01696 strcatW(wszKeyName, wszClsid); 01697 01698 lRet = RegOpenKeyExW(HKEY_CLASSES_ROOT, wszKeyName, 0, KEY_WRITE, &hKey); 01699 hr = HRESULT_FROM_WIN32(lRet); 01700 } 01701 01702 if (SUCCEEDED(hr)) 01703 { 01704 wszPinNameKey = CoTaskMemAlloc((strlenW(wszPins) + 1 + strlenW(Name) + 1) * 2); 01705 if (!wszPinNameKey) 01706 hr = E_OUTOFMEMORY; 01707 } 01708 01709 if (SUCCEEDED(hr)) 01710 { 01711 strcpyW(wszPinNameKey, wszPins); 01712 strcatW(wszPinNameKey, wszSlash); 01713 strcatW(wszPinNameKey, Name); 01714 01715 lRet = RegDeleteTreeW(hKey, wszPinNameKey); 01716 hr = HRESULT_FROM_WIN32(lRet); 01717 CoTaskMemFree(wszPinNameKey); 01718 } 01719 01720 CoTaskMemFree(wszClsid); 01721 if (hKey) 01722 CloseHandle(hKey); 01723 01724 return hr; 01725 } 01726 01727 static const IFilterMapperVtbl fmvtbl = 01728 { 01729 01730 FilterMapper_QueryInterface, 01731 FilterMapper_AddRef, 01732 FilterMapper_Release, 01733 01734 FilterMapper_RegisterFilter, 01735 FilterMapper_RegisterFilterInstance, 01736 FilterMapper_RegisterPin, 01737 FilterMapper_RegisterPinType, 01738 FilterMapper_UnregisterFilter, 01739 FilterMapper_UnregisterFilterInstance, 01740 FilterMapper_UnregisterPin, 01741 FilterMapper_EnumMatchingFilters 01742 }; 01743 01744 01745 /*** IUnknown methods ***/ 01746 static HRESULT WINAPI AMFilterData_QueryInterface(IAMFilterData * iface, REFIID riid, LPVOID *ppv) 01747 { 01748 FilterMapper2Impl *This = impl_from_IAMFilterData(iface); 01749 01750 return FilterMapper2_QueryInterface((IFilterMapper2*)This, riid, ppv); 01751 } 01752 01753 static ULONG WINAPI AMFilterData_AddRef(IAMFilterData * iface) 01754 { 01755 FilterMapper2Impl *This = impl_from_IAMFilterData(iface); 01756 01757 return FilterMapper2_AddRef((IFilterMapper2*)This); 01758 } 01759 01760 static ULONG WINAPI AMFilterData_Release(IAMFilterData * iface) 01761 { 01762 FilterMapper2Impl *This = impl_from_IAMFilterData(iface); 01763 01764 return FilterMapper2_Release((IFilterMapper2*)This); 01765 } 01766 01767 /*** IAMFilterData methods ***/ 01768 static HRESULT WINAPI AMFilterData_ParseFilterData(IAMFilterData* iface, 01769 BYTE *pData, ULONG cb, 01770 BYTE **ppRegFilter2) 01771 { 01772 FilterMapper2Impl *This = impl_from_IAMFilterData(iface); 01773 HRESULT hr = S_OK; 01774 REGFILTER2 *prf2; 01775 01776 TRACE("(%p/%p)->(%p, %d, %p)\n", This, iface, pData, cb, ppRegFilter2); 01777 01778 prf2 = CoTaskMemAlloc(sizeof(*prf2)); 01779 if (!prf2) 01780 return E_OUTOFMEMORY; 01781 *ppRegFilter2 = (BYTE *)prf2; 01782 01783 hr = FM2_ReadFilterData(pData, prf2); 01784 if (FAILED(hr)) 01785 { 01786 CoTaskMemFree(prf2); 01787 *ppRegFilter2 = NULL; 01788 } 01789 01790 return hr; 01791 } 01792 01793 static HRESULT WINAPI AMFilterData_CreateFilterData(IAMFilterData* iface, 01794 REGFILTER2 *prf2, 01795 BYTE **pRegFilterData, 01796 ULONG *pcb) 01797 { 01798 FilterMapper2Impl *This = impl_from_IAMFilterData(iface); 01799 01800 TRACE("(%p/%p)->(%p, %p, %p)\n", This, iface, prf2, pRegFilterData, pcb); 01801 01802 return FM2_WriteFilterData(prf2, pRegFilterData, pcb); 01803 } 01804 01805 static const IAMFilterDataVtbl AMFilterDataVtbl = { 01806 AMFilterData_QueryInterface, 01807 AMFilterData_AddRef, 01808 AMFilterData_Release, 01809 AMFilterData_ParseFilterData, 01810 AMFilterData_CreateFilterData 01811 }; Generated on Mon May 28 2012 04:21:27 for ReactOS by
1.7.6.1
|