/* 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 PPB_Load( IPersistPropertyBag * iface, IPropertyBag *pPropBag, IErrorLog *pErrorLog ) { VfwCapture *This = impl_from_IPersistPropertyBag(iface); HRESULT hr; VARIANT var; const OLECHAR VFWIndex[] = {'V','F','W','I','n','d','e','x',0}; TRACE("%p/%p-> (%p, %p)\n", iface, This, pPropBag, pErrorLog); V_VT(&var) = VT_I4; hr = IPropertyBag_Read(pPropBag, VFWIndex, &var, pErrorLog); if (SUCCEEDED(hr)) { VfwPinImpl *pin; This->driver_info = qcap_driver_init( This->pOutputPin, var.__VARIANT_NAME_1.__VARIANT_NAME_2.__VARIANT_NAME_3.ulVal ); if (This->driver_info) { pin = (VfwPinImpl *)This->pOutputPin; pin->parent = This; This->init = TRUE; hr = S_OK; } else hr = E_FAIL; } return 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_BSTR(&var), -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; }
static HRESULT WINAPI AVICompressorPropertyBag_Load(IPersistPropertyBag *iface, IPropertyBag *pPropBag, IErrorLog *pErrorLog) { AVICompressor *This = impl_from_IPersistPropertyBag(iface); BSTR str; VARIANT v; HRESULT hres; static const WCHAR fcc_handlerW[] = {'F','c','c','H','a','n','d','l','e','r',0}; TRACE("(%p)->(%p %p)\n", This, pPropBag, pErrorLog); V_VT(&v) = VT_EMPTY; hres = IPropertyBag_Read(pPropBag, fcc_handlerW, &v, NULL); if(FAILED(hres)) { WARN("Could not read FccHandler: %08x\n", hres); return hres; } if(V_VT(&v) != VT_BSTR) { FIXME("Got vt %d\n", V_VT(&v)); VariantClear(&v); return E_FAIL; } str = V_BSTR(&v); TRACE("FccHandler = %s\n", debugstr_w(str)); if(SysStringLen(str) != 4) { FIXME("Invalid FccHandler len\n"); SysFreeString(str); return E_FAIL; } This->fcc_handler = FCC(str[0], str[1], str[2], str[3]); SysFreeString(str); return S_OK; }
/** * Cycle through available devices using the device enumerator devenum, * retrieve the device with type specified by devtype and return the * pointer to the object found in *pfilter. * If pfilter is NULL, list all device names. */ static int dshow_cycle_devices(AVFormatContext *avctx, ICreateDevEnum *devenum, enum dshowDeviceType devtype, enum dshowSourceFilterType sourcetype, IBaseFilter **pfilter) { struct dshow_ctx *ctx = avctx->priv_data; IBaseFilter *device_filter = NULL; IEnumMoniker *classenum = NULL; IMoniker *m = NULL; const char *device_name = ctx->device_name[devtype]; int skip = (devtype == VideoDevice) ? ctx->video_device_number : ctx->audio_device_number; int r; const GUID *device_guid[2] = { &CLSID_VideoInputDeviceCategory, &CLSID_AudioInputDeviceCategory }; const char *devtypename = (devtype == VideoDevice) ? "video" : "audio only"; const char *sourcetypename = (sourcetype == VideoSourceDevice) ? "video" : "audio"; r = ICreateDevEnum_CreateClassEnumerator(devenum, device_guid[sourcetype], (IEnumMoniker **) &classenum, 0); if (r != S_OK) { av_log(avctx, AV_LOG_ERROR, "Could not enumerate %s devices (or none found).\n", devtypename); return AVERROR(EIO); } while (!device_filter && IEnumMoniker_Next(classenum, 1, &m, NULL) == S_OK) { IPropertyBag *bag = NULL; char *friendly_name = NULL; char *unique_name = NULL; VARIANT var; IBindCtx *bind_ctx = NULL; LPOLESTR olestr = NULL; LPMALLOC co_malloc = NULL; int i; r = CoGetMalloc(1, &co_malloc); if (r != S_OK) goto fail1; r = CreateBindCtx(0, &bind_ctx); if (r != S_OK) goto fail1; /* GetDisplayname works for both video and audio, DevicePath doesn't */ r = IMoniker_GetDisplayName(m, bind_ctx, NULL, &olestr); if (r != S_OK) goto fail1; unique_name = dup_wchar_to_utf8(olestr); /* replace ':' with '_' since we use : to delineate between sources */ for (i = 0; i < strlen(unique_name); i++) { if (unique_name[i] == ':') unique_name[i] = '_'; } r = IMoniker_BindToStorage(m, 0, 0, &IID_IPropertyBag, (void *) &bag); if (r != S_OK) goto fail1; var.vt = VT_BSTR; r = IPropertyBag_Read(bag, L"FriendlyName", &var, NULL); if (r != S_OK) goto fail1; friendly_name = dup_wchar_to_utf8(var.bstrVal); if (pfilter) { if (strcmp(device_name, friendly_name) && strcmp(device_name, unique_name)) goto fail1; if (!skip--) { r = IMoniker_BindToObject(m, 0, 0, &IID_IBaseFilter, (void *) &device_filter); if (r != S_OK) { av_log(avctx, AV_LOG_ERROR, "Unable to BindToObject for %s\n", device_name); goto fail1; } } } else { av_log(avctx, AV_LOG_INFO, " \"%s\"\n", friendly_name); av_log(avctx, AV_LOG_INFO, " Alternative name \"%s\"\n", unique_name); } fail1: if (olestr && co_malloc) IMalloc_Free(co_malloc, olestr); if (bind_ctx) IBindCtx_Release(bind_ctx); av_free(friendly_name); av_free(unique_name); if (bag) IPropertyBag_Release(bag); IMoniker_Release(m); } IEnumMoniker_Release(classenum); if (pfilter) { if (!device_filter) { av_log(avctx, AV_LOG_ERROR, "Could not find %s device with name [%s] among source devices of type %s.\n", devtypename, device_name, sourcetypename); return AVERROR(EIO); } *pfilter = device_filter; } return 0; }
/** * Cycle through available devices using the device enumerator devenum, * retrieve the device with type specified by devtype and return the * pointer to the object found in *pfilter. * If pfilter is NULL, list all device names. */ static int dshow_cycle_devices(AVFormatContext *avctx, ICreateDevEnum *devenum, enum dshowDeviceType devtype, IBaseFilter **pfilter) { struct dshow_ctx *ctx = avctx->priv_data; IBaseFilter *device_filter = NULL; IEnumMoniker *classenum = NULL; IMoniker *m = NULL; const char *device_name = ctx->device_name[devtype]; int skip = (devtype == VideoDevice) ? ctx->video_device_number : ctx->audio_device_number; int r; const GUID *device_guid[2] = { &CLSID_VideoInputDeviceCategory, &CLSID_AudioInputDeviceCategory }; const char *devtypename = (devtype == VideoDevice) ? "video" : "audio"; r = ICreateDevEnum_CreateClassEnumerator(devenum, device_guid[devtype], (IEnumMoniker **) &classenum, 0); if (r != S_OK) { av_log(avctx, AV_LOG_ERROR, "Could not enumerate %s devices.\n", devtypename); return AVERROR(EIO); } while (!device_filter && IEnumMoniker_Next(classenum, 1, &m, NULL) == S_OK) { IPropertyBag *bag = NULL; char *buf = NULL; VARIANT var; r = IMoniker_BindToStorage(m, 0, 0, &IID_IPropertyBag, (void *) &bag); if (r != S_OK) goto fail1; var.vt = VT_BSTR; r = IPropertyBag_Read(bag, L"FriendlyName", &var, NULL); if (r != S_OK) goto fail1; buf = dup_wchar_to_utf8(var.bstrVal); if (pfilter) { if (strcmp(device_name, buf)) goto fail1; if (!skip--) IMoniker_BindToObject(m, 0, 0, &IID_IBaseFilter, (void *) &device_filter); } else { av_log(avctx, AV_LOG_INFO, " \"%s\"\n", buf); } fail1: if (buf) av_free(buf); if (bag) IPropertyBag_Release(bag); IMoniker_Release(m); } IEnumMoniker_Release(classenum); if (pfilter) { if (!device_filter) { av_log(avctx, AV_LOG_ERROR, "Could not find %s device.\n", devtypename); return AVERROR(EIO); } *pfilter = device_filter; } return 0; }
static GValueArray * gst_dshowaudiosrc_get_device_name_values (GstDshowAudioSrc * src) { GValueArray *array = g_value_array_new (0); GValue value = { 0 }; ICreateDevEnum *devices_enum = NULL; IEnumMoniker *moniker_enum = NULL; IMoniker *moniker = NULL; HRESULT hres = S_FALSE; ULONG fetched; g_value_init (&value, G_TYPE_STRING); hres = CoCreateInstance (&CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, &IID_ICreateDevEnum, (void **) &devices_enum); if (hres != S_OK) { GST_CAT_ERROR (dshowaudiosrc_debug, "Can't create an instance of the system device enumerator (error=%d)", hres); array = NULL; goto clean; } hres = ICreateDevEnum_CreateClassEnumerator (devices_enum, &CLSID_AudioInputDeviceCategory, &moniker_enum, 0); if (hres != S_OK || !moniker_enum) { GST_CAT_ERROR (dshowaudiosrc_debug, "Can't get enumeration of audio devices (error=%d)", hres); array = NULL; goto clean; } IEnumMoniker_Reset (moniker_enum); while (hres = IEnumMoniker_Next (moniker_enum, 1, &moniker, &fetched), hres == S_OK) { IPropertyBag *property_bag = NULL; hres = IMoniker_BindToStorage (moniker, NULL, NULL, &IID_IPropertyBag, (void **) &property_bag); if (SUCCEEDED (hres) && property_bag) { VARIANT varFriendlyName; VariantInit (&varFriendlyName); hres = IPropertyBag_Read (property_bag, L"FriendlyName", &varFriendlyName, NULL); if (hres == S_OK && varFriendlyName.bstrVal) { gchar *friendly_name = g_utf16_to_utf8 ((const gunichar2 *) varFriendlyName.bstrVal, wcslen (varFriendlyName.bstrVal), NULL, NULL, NULL); g_value_set_string (&value, friendly_name); g_value_array_append (array, &value); g_value_unset (&value); g_free (friendly_name); SysFreeString (varFriendlyName.bstrVal); } IPropertyBag_Release (property_bag); } IMoniker_Release (moniker); } clean: if (moniker_enum) { IEnumMoniker_Release (moniker_enum); } if (devices_enum) { ICreateDevEnum_Release (devices_enum); } return array; }
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 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); }