/* From quartz, 2008/04/07 */ static HRESULT GetFilterInfo(IMoniker *pMoniker, GUID *pclsid, VARIANT *pvar) { static const WCHAR wszClsidName[] = {'C','L','S','I','D',0}; static const WCHAR wszFriendlyName[] = {'F','r','i','e','n','d','l','y','N','a','m','e',0}; IPropertyBag *pPropBagCat = NULL; HRESULT hr; VariantInit(pvar); V_VT(pvar) = VT_BSTR; hr = IMoniker_BindToStorage(pMoniker, NULL, NULL, &IID_IPropertyBag, (LPVOID *) &pPropBagCat); if (SUCCEEDED(hr)) hr = IPropertyBag_Read(pPropBagCat, wszClsidName, pvar, NULL); if (SUCCEEDED(hr)) { hr = CLSIDFromString(V_UNION(pvar, bstrVal), pclsid); VariantClear(pvar); V_VT(pvar) = VT_BSTR; } if (SUCCEEDED(hr)) hr = IPropertyBag_Read(pPropBagCat, wszFriendlyName, pvar, NULL); if (SUCCEEDED(hr)) TRACE("Moniker = %s - %s\n", debugstr_guid(pclsid), debugstr_w(V_UNION(pvar, bstrVal))); if (pPropBagCat) IPropertyBag_Release(pPropBagCat); return hr; }
static HRESULT WINAPI DEVENUM_IPropertyBag_Write( LPPROPERTYBAG iface, LPCOLESTR pszPropName, VARIANT* pVar) { RegPropBagImpl *This = impl_from_IPropertyBag(iface); LPVOID lpData = NULL; DWORD cbData = 0; DWORD dwType = 0; HRESULT res = S_OK; TRACE("(%p)->(%s, %p)\n", This, debugstr_w(pszPropName), pVar); switch (V_VT(pVar)) { case VT_BSTR: case VT_LPWSTR: TRACE("writing %s\n", debugstr_w(V_UNION(pVar, bstrVal))); lpData = V_UNION(pVar, bstrVal); dwType = REG_SZ; cbData = (lstrlenW(V_UNION(pVar, bstrVal)) + 1) * sizeof(WCHAR); break; case VT_I4: case VT_UI4: TRACE("writing %u\n", V_UNION(pVar, ulVal)); lpData = &V_UNION(pVar, ulVal); dwType = REG_DWORD; cbData = sizeof(DWORD); break; case VT_ARRAY | VT_UI1: { LONG lUbound = 0; LONG lLbound = 0; dwType = REG_BINARY; res = SafeArrayGetLBound(V_UNION(pVar, parray), 1, &lLbound); res = SafeArrayGetUBound(V_UNION(pVar, parray), 1, &lUbound); cbData = (lUbound - lLbound + 1) /* * sizeof(BYTE)*/; TRACE("cbData: %d\n", cbData); res = SafeArrayAccessData(V_UNION(pVar, parray), &lpData); break; } default: FIXME("Variant type %d not handled\n", V_VT(pVar)); return E_FAIL; } if (RegSetValueExW(This->hkey, pszPropName, 0, dwType, lpData, cbData) != ERROR_SUCCESS) res = E_FAIL; if (V_VT(pVar) & VT_ARRAY) res = SafeArrayUnaccessData(V_UNION(pVar, parray)); return res; }
static void test_propertybag_write(IPropertyBag2 *property) { HRESULT hr; PROPBAG2 options[2] = {{0}}; VARIANT values[2]; VariantInit(&values[0]); VariantInit(&values[1]); /* 1. One unknown property */ options[0].pstrName = (LPOLESTR)wszTestInvalidProperty; hr = IPropertyBag2_Write(property, 1, options, values); ok(hr == E_FAIL, "Write for an unknown property did not fail with expected code, hr=%x\n", hr); /* 2. One property without correct type */ options[0].pstrName = (LPOLESTR)wszTestProperty1; V_VT(&values[0]) = VT_UI1; V_UNION(&values[0], bVal) = 1; hr = IPropertyBag2_Write(property, 1, options, values); ok(hr == S_OK, "Write for one property failed, hr=%x\n", hr); /* 3. One property with mismatching type */ options[0].pstrName = (LPOLESTR)wszTestProperty1; V_VT(&values[0]) = VT_I1; V_UNION(&values[0], bVal) = 2; hr = IPropertyBag2_Write(property, 1, options, values); ok(hr == WINCODEC_ERR_PROPERTYUNEXPECTEDTYPE, "Write with mismatching type did not fail with expected code hr=%x\n", hr); /* 4. Reset one property to empty */ options[0].pstrName = (LPOLESTR)wszTestProperty1; VariantClear(&values[0]); hr = IPropertyBag2_Write(property, 1, options, values); ok(hr == WINCODEC_ERR_PROPERTYUNEXPECTEDTYPE, "Write to reset to empty value does not fail with expected code, hr=%x\n", hr); /* 5. Set two properties */ options[0].pstrName = (LPOLESTR)wszTestProperty1; V_VT(&values[0]) = VT_UI1; V_UNION(&values[0], bVal) = 12; options[1].pstrName = (LPOLESTR)wszTestProperty2; V_VT(&values[1]) = VT_R4; V_UNION(&values[1], fltVal) = (float)3.14; hr = IPropertyBag2_Write(property, 2, options, values); ok(hr == S_OK, "Write for two properties failed, hr=%x\n", hr); }
/* Helper function, checks if filter with given name was enumerated. */ static BOOL enum_find_filter(const WCHAR *wszFilterName, IEnumMoniker *pEnum) { IMoniker *pMoniker = NULL; BOOL found = FALSE; ULONG nb; HRESULT hr; static const WCHAR wszFriendlyName[] = {'F','r','i','e','n','d','l','y','N','a','m','e',0}; while(!found && IEnumMoniker_Next(pEnum, 1, &pMoniker, &nb) == S_OK) { IPropertyBag * pPropBagCat = NULL; VARIANT var; VariantInit(&var); hr = IMoniker_BindToStorage(pMoniker, NULL, NULL, &IID_IPropertyBag, (LPVOID*)&pPropBagCat); ok(SUCCEEDED(hr), "IMoniker_BindToStorage failed with %x\n", hr); if (FAILED(hr) || !pPropBagCat) { VariantClear(&var); IMoniker_Release(pMoniker); continue; } hr = IPropertyBag_Read(pPropBagCat, wszFriendlyName, &var, NULL); ok(SUCCEEDED(hr), "IPropertyBag_Read failed with %x\n", hr); if (SUCCEEDED(hr)) { CHAR val1[512], val2[512]; WideCharToMultiByte(CP_ACP, 0, V_UNION(&var, bstrVal), -1, val1, sizeof(val1), 0, 0); WideCharToMultiByte(CP_ACP, 0, wszFilterName, -1, val2, sizeof(val2), 0, 0); if (!lstrcmpA(val1, val2)) found = TRUE; } IPropertyBag_Release(pPropBagCat); IMoniker_Release(pMoniker); VariantClear(&var); } return found; }
/********************************************************************** * DEVENUM_CreateSpecialCategories (INTERNAL) * * Creates the keys in the registry for the dynamic categories */ static HRESULT DEVENUM_CreateSpecialCategories(void) { HRESULT res; WCHAR szDSoundNameFormat[MAX_PATH + 1]; WCHAR szDSoundName[MAX_PATH + 1]; DWORD iDefaultDevice = -1; UINT numDevs; IFilterMapper2 * pMapper = NULL; REGFILTER2 rf2; REGFILTERPINS2 rfp2; WCHAR path[MAX_PATH]; HKEY basekey; if (DEVENUM_populate_handle) return S_OK; DEVENUM_populate_handle = CreateEventW(NULL, TRUE, FALSE, DEVENUM_populate_handle_nameW); if (GetLastError() == ERROR_ALREADY_EXISTS) { /* Webcams can take some time to scan if the driver is badly written and it enables them, * so have a 10 s timeout here */ if (WaitForSingleObject(DEVENUM_populate_handle, 10000) == WAIT_TIMEOUT) WARN("Waiting for object timed out\n"); TRACE("No need to rescan\n"); return S_OK; } TRACE("Scanning for devices\n"); /* Since devices can change between session, for example because you just plugged in a webcam * or switched from pulseaudio to alsa, delete all old devices first */ if (SUCCEEDED(DEVENUM_GetCategoryKey(&CLSID_AudioRendererCategory, &basekey, path, MAX_PATH))) RegDeleteTreeW(basekey, path); if (SUCCEEDED(DEVENUM_GetCategoryKey(&CLSID_AudioInputDeviceCategory, &basekey, path, MAX_PATH))) RegDeleteTreeW(basekey, path); if (SUCCEEDED(DEVENUM_GetCategoryKey(&CLSID_VideoInputDeviceCategory, &basekey, path, MAX_PATH))) RegDeleteTreeW(basekey, path); if (SUCCEEDED(DEVENUM_GetCategoryKey(&CLSID_MidiRendererCategory, &basekey, path, MAX_PATH))) RegDeleteTreeW(basekey, path); rf2.dwVersion = 2; rf2.dwMerit = MERIT_PREFERRED; rf2.u.s1.cPins2 = 1; rf2.u.s1.rgPins2 = &rfp2; rfp2.cInstances = 1; rfp2.nMediums = 0; rfp2.lpMedium = NULL; rfp2.clsPinCategory = &IID_NULL; if (!LoadStringW(DEVENUM_hInstance, IDS_DEVENUM_DS, szDSoundNameFormat, sizeof(szDSoundNameFormat)/sizeof(szDSoundNameFormat[0])-1)) { ERR("Couldn't get string resource (GetLastError() is %d)\n", GetLastError()); return HRESULT_FROM_WIN32(GetLastError()); } res = CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC, &IID_IFilterMapper2, (void **) &pMapper); /* * Fill in info for devices */ if (SUCCEEDED(res)) { UINT i; WAVEOUTCAPSW wocaps; WAVEINCAPSW wicaps; MIDIOUTCAPSW mocaps; REGPINTYPES * pTypes; numDevs = waveOutGetNumDevs(); res = DEVENUM_CreateAMCategoryKey(&CLSID_AudioRendererCategory); if (FAILED(res)) /* can't register any devices in this category */ numDevs = 0; rfp2.dwFlags = REG_PINFLAG_B_RENDERER; for (i = 0; i < numDevs; i++) { if (waveOutGetDevCapsW(i, &wocaps, sizeof(WAVEOUTCAPSW)) == MMSYSERR_NOERROR) { IMoniker * pMoniker = NULL; rfp2.nMediaTypes = 1; pTypes = CoTaskMemAlloc(rfp2.nMediaTypes * sizeof(REGPINTYPES)); if (!pTypes) { IFilterMapper2_Release(pMapper); return E_OUTOFMEMORY; } /* FIXME: Native devenum seems to register a lot more types for * DSound than we do. Not sure what purpose they serve */ pTypes[0].clsMajorType = &MEDIATYPE_Audio; pTypes[0].clsMinorType = &MEDIASUBTYPE_PCM; rfp2.lpMediaType = pTypes; res = IFilterMapper2_RegisterFilter(pMapper, &CLSID_AudioRender, wocaps.szPname, &pMoniker, &CLSID_AudioRendererCategory, wocaps.szPname, &rf2); /* FIXME: do additional stuff with IMoniker here, depending on what RegisterFilter does */ if (pMoniker) { IMoniker_Release(pMoniker); pMoniker = NULL; } wsprintfW(szDSoundName, szDSoundNameFormat, wocaps.szPname); res = IFilterMapper2_RegisterFilter(pMapper, &CLSID_DSoundRender, szDSoundName, &pMoniker, &CLSID_AudioRendererCategory, szDSoundName, &rf2); /* FIXME: do additional stuff with IMoniker here, depending on what RegisterFilter does */ if (pMoniker) IMoniker_Release(pMoniker); if (i == iDefaultDevice) { FIXME("Default device\n"); } CoTaskMemFree(pTypes); } } numDevs = waveInGetNumDevs(); res = DEVENUM_CreateAMCategoryKey(&CLSID_AudioInputDeviceCategory); if (FAILED(res)) /* can't register any devices in this category */ numDevs = 0; rfp2.dwFlags = REG_PINFLAG_B_OUTPUT; for (i = 0; i < numDevs; i++) { if (waveInGetDevCapsW(i, &wicaps, sizeof(WAVEINCAPSW)) == MMSYSERR_NOERROR) { IMoniker * pMoniker = NULL; rfp2.nMediaTypes = 1; pTypes = CoTaskMemAlloc(rfp2.nMediaTypes * sizeof(REGPINTYPES)); if (!pTypes) { IFilterMapper2_Release(pMapper); return E_OUTOFMEMORY; } /* FIXME: Not sure if these are correct */ pTypes[0].clsMajorType = &MEDIATYPE_Audio; pTypes[0].clsMinorType = &MEDIASUBTYPE_PCM; rfp2.lpMediaType = pTypes; res = IFilterMapper2_RegisterFilter(pMapper, &CLSID_AudioRecord, wicaps.szPname, &pMoniker, &CLSID_AudioInputDeviceCategory, wicaps.szPname, &rf2); /* FIXME: do additional stuff with IMoniker here, depending on what RegisterFilter does */ if (pMoniker) IMoniker_Release(pMoniker); CoTaskMemFree(pTypes); } } numDevs = midiOutGetNumDevs(); res = DEVENUM_CreateAMCategoryKey(&CLSID_MidiRendererCategory); if (FAILED(res)) /* can't register any devices in this category */ numDevs = 0; rfp2.dwFlags = REG_PINFLAG_B_RENDERER; for (i = 0; i < numDevs; i++) { if (midiOutGetDevCapsW(i, &mocaps, sizeof(MIDIOUTCAPSW)) == MMSYSERR_NOERROR) { IMoniker * pMoniker = NULL; rfp2.nMediaTypes = 1; pTypes = CoTaskMemAlloc(rfp2.nMediaTypes * sizeof(REGPINTYPES)); if (!pTypes) { IFilterMapper2_Release(pMapper); return E_OUTOFMEMORY; } /* FIXME: Not sure if these are correct */ pTypes[0].clsMajorType = &MEDIATYPE_Midi; pTypes[0].clsMinorType = &MEDIASUBTYPE_None; rfp2.lpMediaType = pTypes; res = IFilterMapper2_RegisterFilter(pMapper, &CLSID_AVIMIDIRender, mocaps.szPname, &pMoniker, &CLSID_MidiRendererCategory, mocaps.szPname, &rf2); /* FIXME: do additional stuff with IMoniker here, depending on what RegisterFilter does */ /* Native version sets MidiOutId */ if (pMoniker) IMoniker_Release(pMoniker); if (i == iDefaultDevice) { FIXME("Default device\n"); } CoTaskMemFree(pTypes); } } res = DEVENUM_CreateAMCategoryKey(&CLSID_VideoInputDeviceCategory); if (SUCCEEDED(res)) for (i = 0; i < 10; i++) { WCHAR szDeviceName[32], szDeviceVersion[32], szDevicePath[10]; if (capGetDriverDescriptionW ((WORD) i, szDeviceName, sizeof(szDeviceName)/sizeof(WCHAR), szDeviceVersion, sizeof(szDeviceVersion)/sizeof(WCHAR))) { IMoniker * pMoniker = NULL; IPropertyBag * pPropBag = NULL; WCHAR dprintf[] = { 'v','i','d','e','o','%','d',0 }; snprintfW(szDevicePath, sizeof(szDevicePath)/sizeof(WCHAR), dprintf, i); /* The above code prevents 1 device with a different ID overwriting another */ rfp2.nMediaTypes = 1; pTypes = CoTaskMemAlloc(rfp2.nMediaTypes * sizeof(REGPINTYPES)); if (!pTypes) { IFilterMapper2_Release(pMapper); return E_OUTOFMEMORY; } pTypes[0].clsMajorType = &MEDIATYPE_Video; pTypes[0].clsMinorType = &MEDIASUBTYPE_None; rfp2.lpMediaType = pTypes; res = IFilterMapper2_RegisterFilter(pMapper, &CLSID_VfwCapture, szDeviceName, &pMoniker, &CLSID_VideoInputDeviceCategory, szDevicePath, &rf2); if (pMoniker) { OLECHAR wszVfwIndex[] = { 'V','F','W','I','n','d','e','x',0 }; VARIANT var; V_VT(&var) = VT_I4; V_UNION(&var, ulVal) = i; res = IMoniker_BindToStorage(pMoniker, NULL, NULL, &IID_IPropertyBag, (LPVOID)&pPropBag); if (SUCCEEDED(res)) res = IPropertyBag_Write(pPropBag, wszVfwIndex, &var); IMoniker_Release(pMoniker); } if (i == iDefaultDevice) FIXME("Default device\n"); CoTaskMemFree(pTypes); } } } if (pMapper) IFilterMapper2_Release(pMapper); SetEvent(DEVENUM_populate_handle); return res; }
static HRESULT GetSplitter(MediaDetImpl *This) { IFileSourceFilter *file; LPOLESTR name; AM_MEDIA_TYPE mt; GUID type[2]; IFilterMapper2 *map; IEnumMoniker *filters; IMoniker *mon; VARIANT var; GUID clsid; IBaseFilter *splitter; IEnumPins *pins; IPin *source_pin, *splitter_pin; HRESULT hr; hr = CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC_SERVER, &IID_IFilterMapper2, (void **) &map); if (FAILED(hr)) return hr; hr = IBaseFilter_QueryInterface(This->source, &IID_IFileSourceFilter, (void **) &file); if (FAILED(hr)) { IFilterMapper2_Release(map); return hr; } hr = IFileSourceFilter_GetCurFile(file, &name, &mt); IFileSourceFilter_Release(file); CoTaskMemFree(name); if (FAILED(hr)) { IFilterMapper2_Release(map); return hr; } type[0] = mt.majortype; type[1] = mt.subtype; CoTaskMemFree(mt.pbFormat); hr = IFilterMapper2_EnumMatchingFilters(map, &filters, 0, TRUE, MERIT_UNLIKELY, FALSE, 1, type, NULL, NULL, FALSE, TRUE, 0, NULL, NULL, NULL); IFilterMapper2_Release(map); if (FAILED(hr)) return hr; hr = E_NOINTERFACE; while (IEnumMoniker_Next(filters, 1, &mon, NULL) == S_OK) { hr = GetFilterInfo(mon, &clsid, &var); IMoniker_Release(mon); if (FAILED(hr)) continue; hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IBaseFilter, (void **) &splitter); if (FAILED(hr)) { VariantClear(&var); continue; } hr = IGraphBuilder_AddFilter(This->graph, splitter, V_UNION(&var, bstrVal)); VariantClear(&var); This->splitter = splitter; if (FAILED(hr)) goto retry; hr = IBaseFilter_EnumPins(This->source, &pins); if (FAILED(hr)) goto retry; IEnumPins_Next(pins, 1, &source_pin, NULL); IEnumPins_Release(pins); hr = IBaseFilter_EnumPins(splitter, &pins); if (FAILED(hr)) { IPin_Release(source_pin); goto retry; } IEnumPins_Next(pins, 1, &splitter_pin, NULL); IEnumPins_Release(pins); hr = IPin_Connect(source_pin, splitter_pin, NULL); IPin_Release(source_pin); IPin_Release(splitter_pin); if (SUCCEEDED(hr)) break; retry: IBaseFilter_Release(splitter); This->splitter = NULL; } IEnumMoniker_Release(filters); if (FAILED(hr)) return hr; return S_OK; }
static HRESULT WINAPI DEVENUM_IMediaCatMoniker_BindToObject(IMoniker *iface, IBindCtx *pbc, IMoniker *pmkToLeft, REFIID riidResult, void **ppvResult) { MediaCatMoniker *This = impl_from_IMoniker(iface); IUnknown * pObj = NULL; IPropertyBag * pProp = NULL; CLSID clsID; VARIANT var; HRESULT res = E_FAIL; TRACE("(%p)->(%p, %p, %s, %p)\n", This, pbc, pmkToLeft, debugstr_guid(riidResult), ppvResult); VariantInit(&var); *ppvResult = NULL; if(pmkToLeft==NULL) { /* first activation of this class */ LPVOID pvptr; res=IMoniker_BindToStorage(iface, NULL, NULL, &IID_IPropertyBag, &pvptr); pProp = pvptr; if (SUCCEEDED(res)) { V_VT(&var) = VT_LPWSTR; res = IPropertyBag_Read(pProp, clsid_keyname, &var, NULL); } if (SUCCEEDED(res)) { res = CLSIDFromString(V_UNION(&var,bstrVal), &clsID); CoTaskMemFree(V_UNION(&var, bstrVal)); } if (SUCCEEDED(res)) { res=CoCreateInstance(&clsID,NULL,CLSCTX_ALL,&IID_IUnknown,&pvptr); pObj = pvptr; } } if (pObj!=NULL) { /* get the requested interface from the loaded class */ res = S_OK; if (pProp) { HRESULT res2; LPVOID ppv = NULL; res2 = IUnknown_QueryInterface(pObj, &IID_IPersistPropertyBag, &ppv); if (SUCCEEDED(res2)) { res = IPersistPropertyBag_Load((IPersistPropertyBag *) ppv, pProp, NULL); IPersistPropertyBag_Release((IPersistPropertyBag *) ppv); } } if (SUCCEEDED(res)) res= IUnknown_QueryInterface(pObj,riidResult,ppvResult); IUnknown_Release(pObj); } if (pProp) { IPropertyBag_Release(pProp); } TRACE("<- 0x%x\n", res); return res; }
static HRESULT WINAPI DEVENUM_IPropertyBag_Read( LPPROPERTYBAG iface, LPCOLESTR pszPropName, VARIANT* pVar, IErrorLog* pErrorLog) { LPVOID pData = NULL; DWORD received; DWORD type = 0; RegPropBagImpl *This = impl_from_IPropertyBag(iface); HRESULT res = S_OK; LONG reswin32; TRACE("(%p)->(%s, %p, %p)\n", This, debugstr_w(pszPropName), pVar, pErrorLog); if (!pszPropName || !pVar) return E_POINTER; reswin32 = RegQueryValueExW(This->hkey, pszPropName, NULL, NULL, NULL, &received); res = HRESULT_FROM_WIN32(reswin32); if (SUCCEEDED(res)) { pData = HeapAlloc(GetProcessHeap(), 0, received); /* work around a GCC bug that occurs here unless we use the reswin32 variable as well */ reswin32 = RegQueryValueExW(This->hkey, pszPropName, NULL, &type, pData, &received); res = HRESULT_FROM_WIN32(reswin32); } if (SUCCEEDED(res)) { res = E_INVALIDARG; /* assume we cannot coerce into right type */ TRACE("Read %d bytes (%s)\n", received, type == REG_SZ ? debugstr_w(pData) : "binary data"); switch (type) { case REG_SZ: switch (V_VT(pVar)) { case VT_LPWSTR: V_UNION(pVar, bstrVal) = CoTaskMemAlloc(received); memcpy(V_UNION(pVar, bstrVal), pData, received); res = S_OK; break; case VT_EMPTY: V_VT(pVar) = VT_BSTR; /* fall through */ case VT_BSTR: V_UNION(pVar, bstrVal) = SysAllocStringLen(pData, received/sizeof(WCHAR) - 1); res = S_OK; break; } break; case REG_DWORD: TRACE("REG_DWORD: %x\n", *(DWORD *)pData); switch (V_VT(pVar)) { case VT_EMPTY: V_VT(pVar) = VT_I4; /* fall through */ case VT_I4: case VT_UI4: V_UNION(pVar, ulVal) = *(DWORD *)pData; res = S_OK; break; } break; case REG_BINARY: { SAFEARRAYBOUND bound; void * pArrayElements; bound.lLbound = 0; bound.cElements = received; TRACE("REG_BINARY: len = %d\n", received); switch (V_VT(pVar)) { case VT_EMPTY: V_VT(pVar) = VT_ARRAY | VT_UI1; /* fall through */ case VT_ARRAY | VT_UI1: if (!(V_UNION(pVar, parray) = SafeArrayCreate(VT_UI1, 1, &bound))) res = E_OUTOFMEMORY; else res = S_OK; break; } if (res == E_INVALIDARG) break; res = SafeArrayAccessData(V_UNION(pVar, parray), &pArrayElements); if (FAILED(res)) break; CopyMemory(pArrayElements, pData, received); res = SafeArrayUnaccessData(V_UNION(pVar, parray)); break; } } if (res == E_INVALIDARG) FIXME("Variant type %x not supported for regtype %x\n", V_VT(pVar), type); } HeapFree(GetProcessHeap(), 0, pData); TRACE("<- %x\n", res); return res; }
static void test_propertybag_read(IPropertyBag2 *property) { HRESULT hr; PROPBAG2 options[3] = {{0}}; VARIANT values[3]; HRESULT itm_hr[3] = {S_OK, S_OK, S_OK}; /* 1. One unknown property */ options[0].pstrName = (LPOLESTR)wszTestInvalidProperty; hr = IPropertyBag2_Read(property, 1, options, NULL, values, itm_hr); ok(hr == E_FAIL, "Read for an unknown property did not fail with expected code, hr=%x\n", hr); /* 2. One known property */ options[0].pstrName = (LPOLESTR)wszTestProperty1; itm_hr[0] = E_FAIL; hr = IPropertyBag2_Read(property, 1, options, NULL, values, itm_hr); ok(hr == S_OK, "Read failed, hr=%x\n", hr); if (SUCCEEDED(hr)) { ok(itm_hr[0] == S_OK, "Read failed, itm_hr[0]=%x\n", itm_hr[0]); ok(V_VT(&values[0]) == VT_UI1, "Read failed, V_VT(&values[0])=%x\n", V_VT(&values[0])); ok(V_UNION(&values[0], bVal) == 12, "Read failed, &values[0]=%i\n", V_UNION(&values[0], bVal)); VariantClear(&values[0]); } /* 3. Two known properties */ options[0].pstrName = (LPOLESTR)wszTestProperty1; options[1].pstrName = (LPOLESTR)wszTestProperty2; itm_hr[0] = E_FAIL; itm_hr[1] = E_FAIL; hr = IPropertyBag2_Read(property, 2, options, NULL, values, itm_hr); ok(hr == S_OK, "Read failed, hr=%x\n", hr); if (SUCCEEDED(hr)) { ok(itm_hr[0] == S_OK, "Read failed, itm_hr[0]=%x\n", itm_hr[0]); ok(V_VT(&values[0]) == VT_UI1, "Read failed, V_VT(&values[0])=%x\n", V_VT(&values[0])); ok(V_UNION(&values[0], bVal) == 12, "Read failed, &values[0]=%i\n", V_UNION(&values[0], bVal)); ok(itm_hr[1] == S_OK, "Read failed, itm_hr[1]=%x\n", itm_hr[1]); ok(V_VT(&values[1]) == VT_R4, "Read failed, V_VT(&values[1])=%x\n", V_VT(&values[1])); ok(V_UNION(&values[1], fltVal) == (float)3.14, "Read failed, &values[1]=%f\n", V_UNION(&values[1], fltVal)); VariantClear(&values[0]); VariantClear(&values[1]); } /* 4. One unknown property between two valid */ /* Exotic initializations so we can detect what is unchanged */ itm_hr[0] = -1; itm_hr[1] = -1; itm_hr[2] = -1; V_VT(&values[0]) = VT_NULL; V_VT(&values[1]) = VT_NULL; V_VT(&values[2]) = VT_NULL; V_UNION(&values[0], bVal) = 254; V_UNION(&values[1], bVal) = 254; V_UNION(&values[2], bVal) = 254; options[0].pstrName = (LPOLESTR)wszTestProperty1; options[1].pstrName = (LPOLESTR)wszTestInvalidProperty; options[2].pstrName = (LPOLESTR)wszTestProperty2; hr = IPropertyBag2_Read(property, 3, options, NULL, values, itm_hr); ok(hr == E_FAIL, "Read failed, hr=%x\n", hr); if (hr == E_FAIL) { ok(itm_hr[0] == S_OK, "Read error code has unexpected value, itm_hr[0]=%x\n", itm_hr[0]); ok(itm_hr[1] == -1, "Read error code has unexpected value, itm_hr[1]=%x\n", itm_hr[1]); ok(itm_hr[2] == -1, "Read error code has unexpected value, itm_hr[2]=%x\n", itm_hr[2]); ok(V_VT(&values[0]) == VT_UI1, "Read variant has unexpected type, V_VT(&values[0])=%x\n", V_VT(&values[0])); ok(V_VT(&values[1]) == VT_NULL, "Read variant has unexpected type, V_VT(&values[1])=%x\n", V_VT(&values[1])); ok(V_VT(&values[2]) == VT_NULL, "Read variant has unexpected type, V_VT(&values[2])=%x\n", V_VT(&values[2])); ok(V_UNION(&values[0], bVal) == 12, "Read variant has unexpected value, V_UNION(&values[0])=%i\n", V_UNION(&values[0], bVal)); ok(V_UNION(&values[1], bVal) == 254, "Read variant has unexpected value, V_UNION(&values[1])=%i\n", V_UNION(&values[1], bVal)); ok(V_UNION(&values[2], bVal) == 254, "Read variant has unexpected value, V_UNION(&values[2])=%i\n", V_UNION(&values[2], bVal)); } }
static void test_specific_encoder_properties(IPropertyBag2 *options, const property_opt_test_data* data, PROPBAG2* all_props, int all_prop_cnt) { HRESULT hr; int i = 0; VARIANT pvarValue; HRESULT phrError = S_OK; while (data[i].name) { int idx = find_property_index(data[i].name, all_props, all_prop_cnt); PROPBAG2 pb = {0}; pb.pstrName = (LPOLESTR)data[i].name; hr = IPropertyBag2_Read(options, 1, &pb, NULL, &pvarValue, &phrError); ok(idx >= 0, "Property %s not in output of GetPropertyInfo\n", wine_dbgstr_w(data[i].name)); if (idx >= 0) { ok(all_props[idx].vt == data[i].var_type, "Property %s has unexpected vt type, vt=%i\n", wine_dbgstr_w(data[i].name), all_props[idx].vt); ok(all_props[idx].dwType == PROPBAG2_TYPE_DATA, "Property %s has unexpected dw type, vt=%i\n", wine_dbgstr_w(data[i].name), all_props[idx].dwType); ok(all_props[idx].cfType == 0, "Property %s has unexpected cf type, vt=%i\n", wine_dbgstr_w(data[i].name), all_props[idx].cfType); } ok(SUCCEEDED(hr), "Reading property %s from bag failed, hr=%x\n", wine_dbgstr_w(data[i].name), hr); if (SUCCEEDED(hr)) { /* On XP the initial type is always VT_EMPTY */ ok(V_VT(&pvarValue) == data[i].initial_var_type || V_VT(&pvarValue) == VT_EMPTY, "Property %s has unexpected initial type, V_VT=%i\n", wine_dbgstr_w(data[i].name), V_VT(&pvarValue)); if(V_VT(&pvarValue) == data[i].initial_var_type) { switch (data[i].initial_var_type) { case VT_BOOL: case VT_UI1: ok(V_UNION(&pvarValue, bVal) == data[i].i_init_val, "Property %s has an unexpected initial value, pvarValue=%i\n", wine_dbgstr_w(data[i].name), V_UNION(&pvarValue, bVal)); break; case VT_R4: ok(V_UNION(&pvarValue, fltVal) == data[i].f_init_val, "Property %s has an unexpected initial value, pvarValue=%f\n", wine_dbgstr_w(data[i].name), V_UNION(&pvarValue, fltVal)); break; default: break; } } VariantClear(&pvarValue); } i++; } }
static HRESULT DXDiag_InitDXDiagDirectShowFiltersContainer(IDxDiagContainer* pSubCont) { HRESULT hr = S_OK; static const WCHAR szName[] = {'s','z','N','a','m','e',0}; static const WCHAR szCatName[] = {'s','z','C','a','t','N','a','m','e',0}; static const WCHAR szClsidCat[] = {'s','z','C','l','s','i','d','C','a','t',0}; static const WCHAR szClsidFilter[] = {'s','z','C','l','s','i','d','F','i','l','t','e','r',0}; static const WCHAR dwInputs[] = {'d','w','I','n','p','u','t','s',0}; static const WCHAR dwOutputs[] = {'d','w','O','u','t','p','u','t','s',0}; static const WCHAR dwMerit[] = {'d','w','M','e','r','i','t',0}; /* static const WCHAR szFileName[] = {'s','z','F','i','l','e','N','a','m','e',0}; static const WCHAR szFileVersion[] = {'s','z','F','i','l','e','V','e','r','s','i','o','n',0}; */ VARIANT v; static const WCHAR wszClsidName[] = {'C','L','S','I','D',0}; static const WCHAR wszFriendlyName[] = {'F','r','i','e','n','d','l','y','N','a','m','e',0}; static const WCHAR wszFilterDataName[] = {'F','i','l','t','e','r','D','a','t','a',0}; /*static const WCHAR wszMeritName[] = {'M','e','r','i','t',0};*/ ICreateDevEnum* pCreateDevEnum = NULL; IEnumMoniker* pEmCat = NULL; IMoniker* pMCat = NULL; /** */ hr = CoCreateInstance(&CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, &IID_ICreateDevEnum, (void**) &pCreateDevEnum); if (FAILED(hr)) return hr; hr = ICreateDevEnum_CreateClassEnumerator(pCreateDevEnum, &CLSID_ActiveMovieCategories, &pEmCat, 0); if (FAILED(hr)) goto out_show_filters; VariantInit(&v); while (S_OK == IEnumMoniker_Next(pEmCat, 1, &pMCat, NULL)) { IPropertyBag* pPropBag = NULL; CLSID clsidCat; hr = IMoniker_BindToStorage(pMCat, NULL, NULL, &IID_IPropertyBag, (void**) &pPropBag); if (SUCCEEDED(hr)) { WCHAR* wszCatName = NULL; WCHAR* wszCatClsid = NULL; hr = IPropertyBag_Read(pPropBag, wszFriendlyName, &v, 0); wszCatName = SysAllocString(V_BSTR(&v)); VariantClear(&v); hr = IPropertyBag_Read(pPropBag, wszClsidName, &v, 0); wszCatClsid = SysAllocString(V_BSTR(&v)); hr = CLSIDFromString(V_UNION(&v, bstrVal), &clsidCat); VariantClear(&v); /* hr = IPropertyBag_Read(pPropBag, wszMeritName, &v, 0); hr = IDxDiagContainerImpl_AddProp(pSubCont, dwMerit, &v); VariantClear(&v); */ if (SUCCEEDED(hr)) { IEnumMoniker* pEnum = NULL; IMoniker* pMoniker = NULL; hr = ICreateDevEnum_CreateClassEnumerator(pCreateDevEnum, &clsidCat, &pEnum, 0); FIXME("\tClassEnumerator for clsid(%s) pEnum(%p)\n", debugstr_guid(&clsidCat), pEnum); if (FAILED(hr) || pEnum == NULL) { goto class_enum_failed; } while (NULL != pEnum && S_OK == IEnumMoniker_Next(pEnum, 1, &pMoniker, NULL)) { IPropertyBag* pPropFilterBag = NULL; FIXME("\tIEnumMoniker_Next(%p, 1, %p)\n", pEnum, pMoniker); hr = IMoniker_BindToStorage(pMoniker, NULL, NULL, &IID_IPropertyBag, (void**) &pPropFilterBag); if (SUCCEEDED(hr)) { LPBYTE pData = NULL; LPBYTE pCurrent = NULL; struct REG_RF* prrf = NULL; VARIANT v_data; DWORD it; DWORD dwNOutputs = 0; DWORD dwNInputs = 0; V_VT(&v) = VT_BSTR; V_BSTR(&v) = SysAllocString(wszCatName); hr = IDxDiagContainerImpl_AddProp(pSubCont, szCatName, &v); VariantClear(&v); V_VT(&v) = VT_BSTR; V_BSTR(&v) = SysAllocString(wszCatClsid); hr = IDxDiagContainerImpl_AddProp(pSubCont, szClsidCat, &v); VariantClear(&v); hr = IPropertyBag_Read(pPropFilterBag, wszFriendlyName, &v, 0); hr = IDxDiagContainerImpl_AddProp(pSubCont, szName, &v); FIXME("\tName:%s\n", debugstr_w(V_BSTR(&v))); VariantClear(&v); hr = IPropertyBag_Read(pPropFilterBag, wszClsidName, &v, 0); FIXME("\tClsid:%s\n", debugstr_w(V_BSTR(&v))); hr = IDxDiagContainerImpl_AddProp(pSubCont, szClsidFilter, &v); VariantClear(&v); hr = IPropertyBag_Read(pPropFilterBag, wszFilterDataName, &v, NULL); hr = SafeArrayAccessData(V_UNION(&v, parray), (LPVOID*) &pData); prrf = (struct REG_RF*) pData; pCurrent = pData; VariantInit(&v_data); V_VT(&v_data) = VT_UI4; V_UI4(&v_data) = prrf->dwVersion; hr = IDxDiagContainerImpl_AddProp(pSubCont, szName, &v_data); VariantClear(&v_data); V_VT(&v_data) = VT_UI4; V_UI4(&v_data) = prrf->dwMerit; hr = IDxDiagContainerImpl_AddProp(pSubCont, dwMerit, &v_data); VariantClear(&v_data); pCurrent += sizeof(struct REG_RF); for (it = 0; it < prrf->dwPins; ++it) { struct REG_RFP* prrfp = (struct REG_RFP*) pCurrent; UINT j; if (prrfp->dwFlags & REG_PINFLAG_B_OUTPUT) ++dwNOutputs; else ++dwNInputs; pCurrent += sizeof(struct REG_RFP); if (prrfp->bCategory) { pCurrent += sizeof(DWORD); } for (j = 0; j < prrfp->dwMediaTypes; ++j) { struct REG_TYPE* prt = (struct REG_TYPE *)pCurrent; pCurrent += sizeof(*prt); } for (j = 0; j < prrfp->dwMediums; ++j) { DWORD dwOffset = *(DWORD*) pCurrent; pCurrent += sizeof(dwOffset); } } V_VT(&v_data) = VT_UI4; V_UI4(&v_data) = dwNInputs; hr = IDxDiagContainerImpl_AddProp(pSubCont, dwInputs, &v_data); VariantClear(&v_data); V_VT(&v_data) = VT_UI4; V_UI4(&v_data) = dwNOutputs; hr = IDxDiagContainerImpl_AddProp(pSubCont, dwOutputs, &v_data); VariantClear(&v_data); SafeArrayUnaccessData(V_UNION(&v, parray)); VariantClear(&v); } IPropertyBag_Release(pPropFilterBag); pPropFilterBag = NULL; } IEnumMoniker_Release(pEnum); pEnum = NULL; } class_enum_failed: SysFreeString(wszCatName); SysFreeString(wszCatClsid); IPropertyBag_Release(pPropBag); pPropBag = NULL; } IEnumMoniker_Release(pMCat); pMCat = NULL; } out_show_filters: if (NULL != pEmCat) { IEnumMoniker_Release(pEmCat); pEmCat = NULL; } if (NULL != pCreateDevEnum) { ICreateDevEnum_Release(pCreateDevEnum); pCreateDevEnum = NULL; } return hr; }
static void test_devenum(IBindCtx *bind_ctx) { HRESULT res; ICreateDevEnum* create_devenum; IEnumMoniker* enum_moniker = NULL; int i; res = CoCreateInstance(&CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC, &IID_ICreateDevEnum, (LPVOID*)&create_devenum); if (res != S_OK) { skip("Cannot create SystemDeviceEnum object (%x)\n", res); return; } for (i = 0; i < (sizeof(am_categories) / sizeof(struct category)); i++) { if (winetest_debug > 1) trace("%s:\n", am_categories[i].name); res = ICreateDevEnum_CreateClassEnumerator(create_devenum, am_categories[i].clsid, &enum_moniker, 0); ok(SUCCEEDED(res), "Cannot create enum moniker (res = %x)\n", res); if (res == S_OK) { IMoniker* moniker; while (IEnumMoniker_Next(enum_moniker, 1, &moniker, NULL) == S_OK) { IPropertyBag* prop_bag = NULL; VARIANT var; HRESULT hr; VariantInit(&var); hr = IMoniker_BindToStorage(moniker, bind_ctx, NULL, &IID_IPropertyBag, (LPVOID*)&prop_bag); ok(hr == S_OK, "IMoniker_BindToStorage failed with error %x\n", hr); if (SUCCEEDED(hr)) { hr = IPropertyBag_Read(prop_bag, friendly_name, &var, NULL); ok((hr == S_OK) || broken(hr == 0x80070002), "IPropertyBag_Read failed with error %x\n", hr); if (SUCCEEDED(hr)) { if (winetest_debug > 1) trace(" %s\n", wine_dbgstr_w(V_UNION(&var, bstrVal))); VariantClear(&var); } else { trace(" ???\n"); } } if (prop_bag) IPropertyBag_Release(prop_bag); IMoniker_Release(moniker); } IEnumMoniker_Release(enum_moniker); } } ICreateDevEnum_Release(create_devenum); }