// (static) Creates a ShellLink that encapsulate a shortcut to local apps. nsresult JumpListShortcut::GetShellLink(nsCOMPtr<nsIJumpListItem>& item, nsRefPtr<IShellLinkW>& aShellLink, nsCOMPtr<nsIThread> &aIOThread) { HRESULT hr; IShellLinkW* psl; nsresult rv; // Shell links: // http://msdn.microsoft.com/en-us/library/bb776891(VS.85).aspx // http://msdn.microsoft.com/en-us/library/bb774950(VS.85).aspx int16_t type; if (NS_FAILED(item->GetType(&type))) return NS_ERROR_INVALID_ARG; if (type != nsIJumpListItem::JUMPLIST_ITEM_SHORTCUT) return NS_ERROR_INVALID_ARG; nsCOMPtr<nsIJumpListShortcut> shortcut = do_QueryInterface(item, &rv); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsILocalHandlerApp> handlerApp; rv = shortcut->GetApp(getter_AddRefs(handlerApp)); NS_ENSURE_SUCCESS(rv, rv); // Create a IShellLink hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLinkW, (LPVOID*)&psl); if (FAILED(hr)) return NS_ERROR_UNEXPECTED; // Retrieve the app path, title, description and optional command line args. nsAutoString appPath, appTitle, appDescription, appArgs; int32_t appIconIndex = 0; // Path nsCOMPtr<nsIFile> executable; handlerApp->GetExecutable(getter_AddRefs(executable)); rv = executable->GetPath(appPath); NS_ENSURE_SUCCESS(rv, rv); // Command line parameters uint32_t count = 0; handlerApp->GetParameterCount(&count); for (uint32_t idx = 0; idx < count; idx++) { if (idx > 0) appArgs.Append(NS_LITERAL_STRING(" ")); nsAutoString param; rv = handlerApp->GetParameter(idx, param); if (NS_FAILED(rv)) return rv; appArgs.Append(param); } handlerApp->GetName(appTitle); handlerApp->GetDetailedDescription(appDescription); bool useUriIcon = false; // if we want to use the URI icon bool usedUriIcon = false; // if we did use the URI icon shortcut->GetIconIndex(&appIconIndex); nsCOMPtr<nsIURI> iconUri; rv = shortcut->GetFaviconPageUri(getter_AddRefs(iconUri)); if (NS_SUCCEEDED(rv) && iconUri) { useUriIcon = true; } // Store the title of the app if (appTitle.Length() > 0) { IPropertyStore* pPropStore = nullptr; hr = psl->QueryInterface(IID_IPropertyStore, (LPVOID*)&pPropStore); if (FAILED(hr)) return NS_ERROR_UNEXPECTED; PROPVARIANT pv; InitPropVariantFromString(appTitle.get(), &pv); pPropStore->SetValue(PKEY_Title, pv); pPropStore->Commit(); pPropStore->Release(); PropVariantClear(&pv); } // Store the rest of the params psl->SetPath(appPath.get()); psl->SetDescription(appDescription.get()); psl->SetArguments(appArgs.get()); if (useUriIcon) { nsString icoFilePath; rv = mozilla::widget::FaviconHelper::ObtainCachedIconFile(iconUri, icoFilePath, aIOThread, false); if (NS_SUCCEEDED(rv)) { // Always use the first icon in the ICO file // our encoded icon only has 1 resource psl->SetIconLocation(icoFilePath.get(), 0); usedUriIcon = true; } } // We didn't use an ICO via URI so fall back to the app icon if (!usedUriIcon) { psl->SetIconLocation(appPath.get(), appIconIndex); } aShellLink = dont_AddRef(psl); return NS_OK; }
Error AudioDriverWASAPI::audio_device_init(AudioDeviceWASAPI *p_device, bool p_capture, bool reinit) { WAVEFORMATEX *pwfex; IMMDeviceEnumerator *enumerator = NULL; IMMDevice *device = NULL; CoInitialize(NULL); HRESULT hr = CoCreateInstance(CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, IID_IMMDeviceEnumerator, (void **)&enumerator); ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN); if (p_device->device_name == "Default") { hr = enumerator->GetDefaultAudioEndpoint(p_capture ? eCapture : eRender, eConsole, &device); } else { IMMDeviceCollection *devices = NULL; hr = enumerator->EnumAudioEndpoints(p_capture ? eCapture : eRender, DEVICE_STATE_ACTIVE, &devices); ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN); LPWSTR strId = NULL; bool found = false; UINT count = 0; hr = devices->GetCount(&count); ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN); for (ULONG i = 0; i < count && !found; i++) { IMMDevice *device = NULL; hr = devices->Item(i, &device); ERR_BREAK(hr != S_OK); IPropertyStore *props = NULL; hr = device->OpenPropertyStore(STGM_READ, &props); ERR_BREAK(hr != S_OK); PROPVARIANT propvar; PropVariantInit(&propvar); hr = props->GetValue(PKEY_Device_FriendlyName, &propvar); ERR_BREAK(hr != S_OK); if (p_device->device_name == String(propvar.pwszVal)) { hr = device->GetId(&strId); ERR_BREAK(hr != S_OK); found = true; } PropVariantClear(&propvar); props->Release(); device->Release(); } if (found) { hr = enumerator->GetDevice(strId, &device); } if (strId) { CoTaskMemFree(strId); } if (device == NULL) { hr = enumerator->GetDefaultAudioEndpoint(p_capture ? eCapture : eRender, eConsole, &device); } } if (reinit) { // In case we're trying to re-initialize the device prevent throwing this error on the console, // otherwise if there is currently no device available this will spam the console. if (hr != S_OK) { return ERR_CANT_OPEN; } } else { ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN); } hr = enumerator->RegisterEndpointNotificationCallback(¬if_client); SAFE_RELEASE(enumerator) if (hr != S_OK) { ERR_PRINT("WASAPI: RegisterEndpointNotificationCallback error"); } hr = device->Activate(IID_IAudioClient, CLSCTX_ALL, NULL, (void **)&p_device->audio_client); SAFE_RELEASE(device) if (reinit) { if (hr != S_OK) { return ERR_CANT_OPEN; } } else { ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN); } hr = p_device->audio_client->GetMixFormat(&pwfex); ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN); // Since we're using WASAPI Shared Mode we can't control any of these, we just tag along p_device->channels = pwfex->nChannels; p_device->format_tag = pwfex->wFormatTag; p_device->bits_per_sample = pwfex->wBitsPerSample; p_device->frame_size = (p_device->bits_per_sample / 8) * p_device->channels; if (p_device->format_tag == WAVE_FORMAT_EXTENSIBLE) { WAVEFORMATEXTENSIBLE *wfex = (WAVEFORMATEXTENSIBLE *)pwfex; if (wfex->SubFormat == KSDATAFORMAT_SUBTYPE_PCM) { p_device->format_tag = WAVE_FORMAT_PCM; } else if (wfex->SubFormat == KSDATAFORMAT_SUBTYPE_IEEE_FLOAT) { p_device->format_tag = WAVE_FORMAT_IEEE_FLOAT; } else { ERR_PRINT("WASAPI: Format not supported"); ERR_FAIL_V(ERR_CANT_OPEN); } } else { if (p_device->format_tag != WAVE_FORMAT_PCM && p_device->format_tag != WAVE_FORMAT_IEEE_FLOAT) { ERR_PRINT("WASAPI: Format not supported"); ERR_FAIL_V(ERR_CANT_OPEN); } } DWORD streamflags = 0; if (mix_rate != pwfex->nSamplesPerSec) { streamflags |= AUDCLNT_STREAMFLAGS_RATEADJUST; pwfex->nSamplesPerSec = mix_rate; pwfex->nAvgBytesPerSec = pwfex->nSamplesPerSec * pwfex->nChannels * (pwfex->wBitsPerSample / 8); } hr = p_device->audio_client->Initialize(AUDCLNT_SHAREMODE_SHARED, streamflags, p_capture ? REFTIMES_PER_SEC : 0, 0, pwfex, NULL); ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN); if (p_capture) { hr = p_device->audio_client->GetService(IID_IAudioCaptureClient, (void **)&p_device->capture_client); } else { hr = p_device->audio_client->GetService(IID_IAudioRenderClient, (void **)&p_device->render_client); } ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN); // Free memory CoTaskMemFree(pwfex); SAFE_RELEASE(device) return OK; }
// List the abstract services implemented by the current service. // Abstract services represent functionality that a service supports, and are used by applications to discover // that a service supports formats, properties and methods associated with that functionality. // For example, a Contacts service may implement an abstract service that represents the synchronization models supported // on that device, such as the FullEnumerationSync or AnchorSync Device Services void ListAbstractServices( _In_ IPortableDeviceService* service) { ComPtr<IPortableDeviceServiceCapabilities> capabilities; ComPtr<IPortableDevicePropVariantCollection> abstractServices; DWORD numServices = 0; // Get an IPortableDeviceServiceCapabilities interface from the IPortableDeviceService interface to // access the service capabilities-specific methods. HRESULT hr = service->Capabilities(&capabilities); if (FAILED(hr)) { wprintf(L"! Failed to get IPortableDeviceServiceCapabilities from IPortableDeviceService, hr = 0x%lx\n", hr); } // Get all abstract services implemented by the service. if (SUCCEEDED(hr)) { hr = capabilities->GetInheritedServices(WPD_SERVICE_INHERITANCE_IMPLEMENTATION, &abstractServices); if (FAILED(hr)) { wprintf(L"! Failed to get the implememted services from the service, hr = 0x%lx\n", hr); } } // Get the number of abstract services implemented by the service. if (SUCCEEDED(hr)) { hr = abstractServices->GetCount(&numServices); if (FAILED(hr)) { wprintf(L"! Failed to get number of abstract services, hr = 0x%lx\n", hr); } } // Loop through each abstract service and display it if (SUCCEEDED(hr)) { wprintf(L"\n%u Abstract Services Implemented by the service\n\n", numServices); for (DWORD index = 0; index < numServices; index++) { PROPVARIANT abstractService = {0}; hr = abstractServices->GetAt(index, &abstractService); if (SUCCEEDED(hr)) { if (*abstractService.puuid == SERVICE_FullEnumSync) { wprintf(L"\t%ws\n", NAME_FullEnumSyncSvc); } else if (*abstractService.puuid == SERVICE_AnchorSync) { wprintf(L"\t%ws\n", NAME_AnchorSyncSvc); } else { wprintf(L"\t%ws\n", (PCWSTR)CGuidToString(*abstractService.puuid)); } } PropVariantClear(&abstractService); } } }
HRESULT ReadPropertyGuid( IWiaPropertyStorage *pWiaPropertyStorage, const PROPSPEC *pPropSpec, GUID *pguidResult ) { PROPVARIANT PropVariant; HRESULT hr = pWiaPropertyStorage->ReadMultiple( 1, pPropSpec, &PropVariant ); // Generally, the return value should be checked against S_FALSE. // If ReadMultiple returns S_FALSE, it means the property name or ID // had valid syntax, but it didn't exist in this property set, so // no properties were retrieved, and each PROPVARIANT structure is set // to VT_EMPTY. But the following switch statement will handle this case // and return E_FAIL. So the caller of ReadPropertyGuid does not need // to check for S_FALSE explicitly. if (SUCCEEDED(hr)) { switch (PropVariant.vt) { case VT_CLSID: { *pguidResult = *PropVariant.puuid; hr = S_OK; break; } case VT_BSTR: { hr = CLSIDFromString(PropVariant.bstrVal, pguidResult); break; } case VT_LPWSTR: { hr = CLSIDFromString(PropVariant.pwszVal, pguidResult); break; } case VT_LPSTR: { WCHAR wszGuid[MAX_GUID_STRING_LEN]; mbstowcs_s(NULL, wszGuid, MAX_GUID_STRING_LEN, PropVariant.pszVal, MAX_GUID_STRING_LEN); wszGuid[MAX_GUID_STRING_LEN - 1] = L'\0'; hr = CLSIDFromString(wszGuid, pguidResult); break; } default: { hr = E_FAIL; break; } } } PropVariantClear(&PropVariant); return hr; }
HRESULT WiaGetImage( HWND hWndParent, LONG lDeviceType, LONG lFlags, LONG lIntent, IWiaDevMgr *pSuppliedWiaDevMgr, IWiaItem *pSuppliedItemRoot, PFNPROGRESSCALLBACK pfnProgressCallback, PVOID pProgressCallbackParam, GUID *pguidFormat, LONG *plCount, IStream ***pppStream ) { HRESULT hr; // Validate and initialize output parameters if (plCount == NULL) { return E_POINTER; } if (pppStream == NULL) { return E_POINTER; } *plCount = 0; *pppStream = NULL; // Initialize the local root item variable with the supplied value. // If no value is supplied, display the device selection common dialog. CComPtr<IWiaItem> pItemRoot = pSuppliedItemRoot; if (pItemRoot == NULL) { // Initialize the device manager pointer with the supplied value // If no value is supplied, connect to the local device manager CComPtr<IWiaDevMgr> pWiaDevMgr = pSuppliedWiaDevMgr; if (pWiaDevMgr == NULL) { hr = pWiaDevMgr.CoCreateInstance(CLSID_WiaDevMgr); if (FAILED(hr)) { return hr; } } // Display the device selection common dialog hr = pWiaDevMgr->SelectDeviceDlg( hWndParent, lDeviceType, lFlags, 0, &pItemRoot ); if (FAILED(hr) || hr == S_FALSE) { return hr; } } // Display the image selection common dialog CComPtrArray<IWiaItem> ppIWiaItem; hr = pItemRoot->DeviceDlg( hWndParent, lFlags, lIntent, &ppIWiaItem.Count(), &ppIWiaItem ); if (FAILED(hr) || hr == S_FALSE) { return hr; } // For ADF scanners, the common dialog explicitly sets the page count to one. // So in order to transfer multiple images, set the page count to ALL_PAGES // if the WIA_DEVICE_DIALOG_SINGLE_IMAGE flag is not specified, if (!(lFlags & WIA_DEVICE_DIALOG_SINGLE_IMAGE)) { // Get the property storage interface pointer for the root item CComQIPtr<IWiaPropertyStorage> pWiaRootPropertyStorage(pItemRoot); if (pWiaRootPropertyStorage == NULL) { return E_NOINTERFACE; } // Determine if the selected device is a scanner or not PROPSPEC specDevType; specDevType.ulKind = PRSPEC_PROPID; specDevType.propid = WIA_DIP_DEV_TYPE; LONG nDevType; hr = ReadPropertyLong( pWiaRootPropertyStorage, &specDevType, &nDevType ); if (SUCCEEDED(hr) && (GET_STIDEVICE_TYPE(nDevType) == StiDeviceTypeScanner)) { // Determine if the document feeder is selected or not PROPSPEC specDocumentHandlingSelect; specDocumentHandlingSelect.ulKind = PRSPEC_PROPID; specDocumentHandlingSelect.propid = WIA_DPS_DOCUMENT_HANDLING_SELECT; LONG nDocumentHandlingSelect; hr = ReadPropertyLong( pWiaRootPropertyStorage, &specDocumentHandlingSelect, &nDocumentHandlingSelect ); if (SUCCEEDED(hr) && (nDocumentHandlingSelect & FEEDER)) { PROPSPEC specPages; specPages.ulKind = PRSPEC_PROPID; specPages.propid = WIA_DPS_PAGES; PROPVARIANT varPages; varPages.vt = VT_I4; varPages.lVal = ALL_PAGES; pWiaRootPropertyStorage->WriteMultiple( 1, &specPages, &varPages, WIA_DPS_FIRST ); PropVariantClear(&varPages); } } } // If a status callback function is not supplied, use the default. // The default displays a simple dialog with a progress bar and cancel button. CComPtr<CProgressDlg> pProgressDlg; if (pfnProgressCallback == NULL) { pfnProgressCallback = DefaultProgressCallback; pProgressDlg = new CProgressDlg(hWndParent); pProgressCallbackParam = (CProgressDlg *) pProgressDlg; } // Create the data callback interface CComPtr<CDataCallback> pDataCallback = new CDataCallback( pfnProgressCallback, pProgressCallbackParam, plCount, pppStream ); if (pDataCallback == NULL) { return E_OUTOFMEMORY; } // Start the transfer of the selected items for (int i = 0; i < ppIWiaItem.Count(); ++i) { // Get the interface pointers CComQIPtr<IWiaPropertyStorage> pWiaPropertyStorage(ppIWiaItem[i]); if (pWiaPropertyStorage == NULL) { return E_NOINTERFACE; } CComQIPtr<IWiaDataTransfer> pIWiaDataTransfer(ppIWiaItem[i]); if (pIWiaDataTransfer == NULL) { return E_NOINTERFACE; } // Set the transfer type PROPSPEC specTymed; specTymed.ulKind = PRSPEC_PROPID; specTymed.propid = WIA_IPA_TYMED; PROPVARIANT varTymed; varTymed.vt = VT_I4; varTymed.lVal = TYMED_CALLBACK; hr = pWiaPropertyStorage->WriteMultiple( 1, &specTymed, &varTymed, WIA_IPA_FIRST ); PropVariantClear(&varTymed); if (FAILED(hr)) { return hr; } // If there is no transfer format specified, use the device default GUID guidFormat = GUID_NULL; if (pguidFormat == NULL) { pguidFormat = &guidFormat; } if (*pguidFormat == GUID_NULL) { PROPSPEC specPreferredFormat; specPreferredFormat.ulKind = PRSPEC_PROPID; specPreferredFormat.propid = WIA_IPA_PREFERRED_FORMAT; hr = ReadPropertyGuid( pWiaPropertyStorage, &specPreferredFormat, pguidFormat ); if (FAILED(hr)) { return hr; } } // Set the transfer format PROPSPEC specFormat; specFormat.ulKind = PRSPEC_PROPID; specFormat.propid = WIA_IPA_FORMAT; PROPVARIANT varFormat; varFormat.vt = VT_CLSID; varFormat.puuid = (CLSID *) CoTaskMemAlloc(sizeof(CLSID)); if (varFormat.puuid == NULL) { return E_OUTOFMEMORY; } *varFormat.puuid = *pguidFormat; hr = pWiaPropertyStorage->WriteMultiple( 1, &specFormat, &varFormat, WIA_IPA_FIRST ); PropVariantClear(&varFormat); if (FAILED(hr)) { return hr; } // Read the transfer buffer size from the device, default to 64K PROPSPEC specBufferSize; specBufferSize.ulKind = PRSPEC_PROPID; specBufferSize.propid = WIA_IPA_BUFFER_SIZE; LONG nBufferSize; hr = ReadPropertyLong( pWiaPropertyStorage, &specBufferSize, &nBufferSize ); if (FAILED(hr)) { nBufferSize = 64 * 1024; } // Choose double buffered transfer for better performance WIA_DATA_TRANSFER_INFO WiaDataTransferInfo = { 0 }; WiaDataTransferInfo.ulSize = sizeof(WIA_DATA_TRANSFER_INFO); WiaDataTransferInfo.ulBufferSize = 2 * nBufferSize; WiaDataTransferInfo.bDoubleBuffer = TRUE; // Start the transfer hr = pIWiaDataTransfer->idtGetBandedData( &WiaDataTransferInfo, pDataCallback ); if (FAILED(hr) || hr == S_FALSE) { return hr; } } return S_OK; }
~PropVariantClearOnExit() { PropVariantClear(m_p); }
/// <summary> /// Initialize Kinect audio stream object. /// </summary> /// <returns> /// <para>S_OK on success, otherwise failure code.</para> /// </returns> HRESULT KinectReader::InitializeAudioStream() { INuiAudioBeam* pNuiAudioSource = NULL; IMediaObject* pDMO = NULL; IPropertyStore* pPropertyStore = NULL; IStream* pStream = NULL; // Get the audio source HRESULT hr = m_pNuiSensor->NuiGetAudioSource(&pNuiAudioSource); if (SUCCEEDED(hr)) { hr = pNuiAudioSource->QueryInterface(IID_IMediaObject, (void**)&pDMO); if (SUCCEEDED(hr)) { hr = pNuiAudioSource->QueryInterface(IID_IPropertyStore, (void**)&pPropertyStore); // Set AEC-MicArray DMO system mode. This must be set for the DMO to work properly. // Possible values are: // SINGLE_CHANNEL_AEC = 0 // OPTIBEAM_ARRAY_ONLY = 2 // OPTIBEAM_ARRAY_AND_AEC = 4 // SINGLE_CHANNEL_NSAGC = 5 PROPVARIANT pvSysMode; PropVariantInit(&pvSysMode); pvSysMode.vt = VT_I4; pvSysMode.lVal = (LONG)(2); // Use OPTIBEAM_ARRAY_ONLY setting. Set OPTIBEAM_ARRAY_AND_AEC instead if you expect to have sound playing from speakers. pPropertyStore->SetValue(MFPKEY_WMAAECMA_SYSTEM_MODE, pvSysMode); PropVariantClear(&pvSysMode); // Set DMO output format WAVEFORMATEX wfxOut = {AudioFormat, AudioChannels, AudioSamplesPerSecond, AudioAverageBytesPerSecond, AudioBlockAlign, AudioBitsPerSample, 0}; DMO_MEDIA_TYPE mt = {0}; MoInitMediaType(&mt, sizeof(WAVEFORMATEX)); mt.majortype = MEDIATYPE_Audio; mt.subtype = MEDIASUBTYPE_PCM; mt.lSampleSize = 0; mt.bFixedSizeSamples = TRUE; mt.bTemporalCompression = FALSE; mt.formattype = FORMAT_WaveFormatEx; memcpy(mt.pbFormat, &wfxOut, sizeof(WAVEFORMATEX)); hr = pDMO->SetOutputType(0, &mt, 0); if (SUCCEEDED(hr)) { m_pKinectAudioStream = new KinectAudioStream(pDMO); hr = m_pKinectAudioStream->QueryInterface(IID_IStream, (void**)&pStream); if (SUCCEEDED(hr)) { hr = CoCreateInstance(CLSID_SpStream, NULL, CLSCTX_INPROC_SERVER, __uuidof(ISpStream), (void**)&m_pSpeechStream); if (SUCCEEDED(hr)) { hr = m_pSpeechStream->SetBaseStream(pStream, SPDFID_WaveFormatEx, &wfxOut); } } } MoFreeMediaType(&mt); } } SafeRelease(pStream); SafeRelease(pPropertyStore); SafeRelease(pDMO); SafeRelease(pNuiAudioSource); return hr; }
/** * This method is called when we receive a WPD_COMMAND_COMMON_GET_OBJECT_IDS_FROM_PERSISTENT_UNIQUE_IDS * command. * * The parameters sent to us are: * - WPD_PROPERTY_COMMON_PERSISTENT_UNIQUE_IDS: Contains an IPortableDevicePropVariantCollection of VT_LPWSTR, * indicating the PersistentUniqueIDs. * * The driver should: * - Iterate through the PersistentUniqueIDs, and convert to a currently valid object id. * This object ID list should be returned as an IPortableDevicePropVariantCollection of VT_LPWSTR * in WPD_PROPERTY_COMMON_OBJECT_IDS. * Order is implicit, i.e. the first element in the Persistent Unique ID list corresponds to the * to the first element of the ObjectID list and so on. * * For those elements where an existing ObjectID could not be found (e.g. the * object is no longer present on the device), the element will contain the * empty string (L""). */ HRESULT WpdBaseDriver::OnGetObjectIDsFromPersistentUniqueIDs( _In_ IPortableDeviceValues* pParams, _In_ IPortableDeviceValues* pResults) { HRESULT hr = S_OK; DWORD dwCount = 0; CComPtr<IPortableDevicePropVariantCollection> pPersistentIDs; CComPtr<IPortableDevicePropVariantCollection> pObjectIDs; if((pParams == NULL) || (pResults == NULL)) { hr = E_POINTER; CHECK_HR(hr, "Cannot have NULL parameter"); return hr; } // Get the list of Persistent IDs if (hr == S_OK) { hr = pParams->GetIPortableDevicePropVariantCollectionValue(WPD_PROPERTY_COMMON_PERSISTENT_UNIQUE_IDS, &pPersistentIDs); CHECK_HR(hr, "Failed to get WPD_PROPERTY_COMMON_PERSISTENT_UNIQUE_IDS"); } // Create the collection to hold the ObjectIDs if (hr == S_OK) { hr = CoCreateInstance(CLSID_PortableDevicePropVariantCollection, NULL, CLSCTX_INPROC_SERVER, IID_IPortableDevicePropVariantCollection, (VOID**) &pObjectIDs); CHECK_HR(hr, "Failed to CoCreate CLSID_PortableDevicePropVariantCollection"); } // Iterate through the persistent ID list and add the equivalent object ID for each element. if (hr == S_OK) { hr = pPersistentIDs->GetCount(&dwCount); CHECK_HR(hr, "Failed to get count from persistent ID collection"); if (hr == S_OK) { DWORD dwIndex = 0; PROPVARIANT pvPersistentID = {0}; PROPVARIANT pvObjectID = {0}; PropVariantInit(&pvPersistentID); PropVariantInit(&pvObjectID); for(dwIndex = 0; dwIndex < dwCount; dwIndex++) { pvObjectID.vt = VT_LPWSTR; hr = pPersistentIDs->GetAt(dwIndex, &pvPersistentID); CHECK_HR(hr, "Failed to get persistent ID at index %d", dwIndex); // Since our persistent unique identifier are identical to our object // identifiers, we just return it back to the caller. if (hr == S_OK) { pvObjectID.pwszVal = AtlAllocTaskWideString(pvPersistentID.pwszVal); } if (hr == S_OK) { hr = pObjectIDs->Add(&pvObjectID); CHECK_HR(hr, "Failed to add next Object ID"); } PropVariantClear(&pvPersistentID); PropVariantClear(&pvObjectID); if(FAILED(hr)) { break; } } } } if (hr == S_OK) { hr = pResults->SetIPortableDevicePropVariantCollectionValue(WPD_PROPERTY_COMMON_OBJECT_IDS, pObjectIDs); CHECK_HR(hr, "Failed to set WPD_PROPERTY_COMMON_OBJECT_IDS"); } return hr; }
void CAESinkDirectSound::EnumerateDevicesEx(AEDeviceInfoList &deviceInfoList, bool force) { CAEDeviceInfo deviceInfo; IMMDeviceEnumerator* pEnumerator = NULL; IMMDeviceCollection* pEnumDevices = NULL; HRESULT hr; std::string strDD = GetDefaultDevice(); /* Windows Vista or later - supporting WASAPI device probing */ hr = CoCreateInstance(CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, IID_IMMDeviceEnumerator, (void**)&pEnumerator); EXIT_ON_FAILURE(hr, __FUNCTION__": Could not allocate WASAPI device enumerator. CoCreateInstance error code: %li", hr) UINT uiCount = 0; hr = pEnumerator->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, &pEnumDevices); EXIT_ON_FAILURE(hr, __FUNCTION__": Retrieval of audio endpoint enumeration failed.") hr = pEnumDevices->GetCount(&uiCount); EXIT_ON_FAILURE(hr, __FUNCTION__": Retrieval of audio endpoint count failed.") for (UINT i = 0; i < uiCount; i++) { IMMDevice *pDevice = NULL; IPropertyStore *pProperty = NULL; PROPVARIANT varName; PropVariantInit(&varName); deviceInfo.m_channels.Reset(); deviceInfo.m_dataFormats.clear(); deviceInfo.m_sampleRates.clear(); hr = pEnumDevices->Item(i, &pDevice); if (FAILED(hr)) { CLog::Log(LOGERROR, __FUNCTION__": Retrieval of DirectSound endpoint failed."); goto failed; } hr = pDevice->OpenPropertyStore(STGM_READ, &pProperty); if (FAILED(hr)) { CLog::Log(LOGERROR, __FUNCTION__": Retrieval of DirectSound endpoint properties failed."); SAFE_RELEASE(pDevice); goto failed; } hr = pProperty->GetValue(PKEY_Device_FriendlyName, &varName); if (FAILED(hr)) { CLog::Log(LOGERROR, __FUNCTION__": Retrieval of DirectSound endpoint device name failed."); SAFE_RELEASE(pDevice); SAFE_RELEASE(pProperty); goto failed; } std::string strFriendlyName = localWideToUtf(varName.pwszVal); PropVariantClear(&varName); hr = pProperty->GetValue(PKEY_AudioEndpoint_GUID, &varName); if (FAILED(hr)) { CLog::Log(LOGERROR, __FUNCTION__": Retrieval of DirectSound endpoint GUID failed."); SAFE_RELEASE(pDevice); SAFE_RELEASE(pProperty); goto failed; } std::string strDevName = localWideToUtf(varName.pwszVal); PropVariantClear(&varName); hr = pProperty->GetValue(PKEY_AudioEndpoint_FormFactor, &varName); if (FAILED(hr)) { CLog::Log(LOGERROR, __FUNCTION__": Retrieval of DirectSound endpoint form factor failed."); SAFE_RELEASE(pDevice); SAFE_RELEASE(pProperty); goto failed; } std::string strWinDevType = winEndpoints[(EndpointFormFactor)varName.uiVal].winEndpointType; AEDeviceType aeDeviceType = winEndpoints[(EndpointFormFactor)varName.uiVal].aeDeviceType; PropVariantClear(&varName); /* In shared mode Windows tells us what format the audio must be in. */ IAudioClient *pClient; hr = pDevice->Activate(IID_IAudioClient, CLSCTX_ALL, NULL, (void**)&pClient); if (FAILED(hr)) { CLog::Log(LOGERROR, __FUNCTION__": Activate device failed (%s)", WASAPIErrToStr(hr)); goto failed; } //hr = pClient->GetMixFormat(&pwfxex); hr = pProperty->GetValue(PKEY_AudioEngine_DeviceFormat, &varName); if (SUCCEEDED(hr) && varName.blob.cbSize > 0) { WAVEFORMATEX* smpwfxex = (WAVEFORMATEX*)varName.blob.pBlobData; deviceInfo.m_channels = layoutsByChCount[std::max(std::min(smpwfxex->nChannels, (WORD) DS_SPEAKER_COUNT), (WORD) 2)]; deviceInfo.m_dataFormats.push_back(AEDataFormat(AE_FMT_FLOAT)); if (aeDeviceType != AE_DEVTYPE_PCM) { deviceInfo.m_dataFormats.push_back(AEDataFormat(AE_FMT_AC3)); // DTS is played with the same infrastructure as AC3 deviceInfo.m_dataFormats.push_back(AEDataFormat(AE_FMT_DTS)); } deviceInfo.m_sampleRates.push_back(std::min(smpwfxex->nSamplesPerSec, (DWORD) 192000)); } else { CLog::Log(LOGERROR, __FUNCTION__": Getting DeviceFormat failed (%s)", WASAPIErrToStr(hr)); } pClient->Release(); SAFE_RELEASE(pDevice); SAFE_RELEASE(pProperty); deviceInfo.m_deviceName = strDevName; deviceInfo.m_displayName = strWinDevType.append(strFriendlyName); deviceInfo.m_displayNameExtra = std::string("DIRECTSOUND: ").append(strFriendlyName); deviceInfo.m_deviceType = aeDeviceType; deviceInfoList.push_back(deviceInfo); // add the default device with m_deviceName = default if(strDD == strDevName) { deviceInfo.m_deviceName = std::string("default"); deviceInfo.m_displayName = std::string("default"); deviceInfo.m_displayNameExtra = std::string(""); deviceInfoList.push_back(deviceInfo); } } return; failed: if (FAILED(hr)) CLog::Log(LOGERROR, __FUNCTION__": Failed to enumerate WASAPI endpoint devices (%s).", WASAPIErrToStr(hr)); SAFE_RELEASE(pEnumDevices); SAFE_RELEASE(pEnumerator); }
HRESULT PkOpenPackageWithFilter( __in PPK_FILE_STREAM FileStream, __inout_opt PPK_ACTION_LIST ActionList, __in_opt PPK_PACKAGE_CALLBACK Callback, __in_opt PVOID Context, __out PPK_PACKAGE *Package ) { HRESULT result; PkFileStream *fileStream; IInArchive *inArchive; ULONG numberOfItems; ULONG i; fileStream = (PkFileStream *)FileStream; result = PkpCreateSevenZipObject(&SevenZipHandlerGuid, &IID_IInArchive_I, (void **)&inArchive); if (!SUCCEEDED(result)) return result; result = inArchive->Open(&fileStream->InStream, NULL, NULL); if (!SUCCEEDED(result)) { inArchive->Release(); return result; } if (ActionList) { result = inArchive->GetNumberOfItems((UInt32 *)&numberOfItems); if (SUCCEEDED(result)) { if (Callback) { for (i = 0; i < numberOfItems; i++) { PK_PARAMETER_FILTER_ITEM filterItem; PROPVARIANT pathValue; PROPVARIANT attributesValue; PROPVARIANT isDirValue; PropVariantInit(&pathValue); PropVariantInit(&attributesValue); PropVariantInit(&isDirValue); if (SUCCEEDED(inArchive->GetProperty(i, kpidPath, &pathValue)) && pathValue.vt == VT_BSTR && SUCCEEDED(inArchive->GetProperty(i, kpidAttrib, &attributesValue)) && SUCCEEDED(inArchive->GetProperty(i, kpidIsDir, &isDirValue))) { filterItem.Reject = FALSE; filterItem.Path.Length = wcslen(pathValue.bstrVal) * sizeof(WCHAR); filterItem.Path.Buffer = pathValue.bstrVal; filterItem.FileAttributes = attributesValue.uintVal; filterItem.NewContext = NULL; if (isDirValue.boolVal) filterItem.FileAttributes |= FILE_ATTRIBUTE_DIRECTORY; Callback(PkFilterItemMessage, NULL, &filterItem, Context); if (!filterItem.Reject) { PkAppendUpdateToActionList(ActionList, i, filterItem.NewContext); } PropVariantClear(&pathValue); PropVariantClear(&attributesValue); PropVariantClear(&isDirValue); } else { result = E_FAIL; PropVariantClear(&pathValue); PropVariantClear(&attributesValue); PropVariantClear(&isDirValue); break; } } } else { for (i = 0; i < numberOfItems; i++) { PkAppendUpdateToActionList(ActionList, i, NULL); } } } } if (SUCCEEDED(result)) *Package = (PPK_PACKAGE)inArchive; else inArchive->Release(); return result; }
HRESULT PkArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode) { HRESULT result; PPK_ACTION action; PK_ACTION localAction; PK_PARAMETER_GET_STREAM getStream; PROPVARIANT value; if (ActionList) { action = GetAction(index); if (!action) { // We don't want this file. *outStream = &(new PkFileStream(PkZeroFileStream, NULL))->OutStream; return S_OK; } } else { localAction.Type = PkUpdateType; localAction.Context = NULL; localAction.u.Update.Index = index; action = &localAction; } memset(&getStream, 0, sizeof(PK_PARAMETER_GET_STREAM)); PropVariantInit(&value); InArchive->GetProperty(index, kpidAttrib, &value); getStream.FileInformation.FileAttributes = value.uintVal; PropVariantClear(&value); InArchive->GetProperty(index, kpidCTime, &value); if (value.vt != VT_EMPTY) { getStream.FileInformation.CreationTime.LowPart = value.filetime.dwLowDateTime; getStream.FileInformation.CreationTime.HighPart = value.filetime.dwHighDateTime; } PropVariantClear(&value); InArchive->GetProperty(index, kpidATime, &value); if (value.vt != VT_EMPTY) { getStream.FileInformation.LastAccessTime.LowPart = value.filetime.dwLowDateTime; getStream.FileInformation.LastAccessTime.HighPart = value.filetime.dwHighDateTime; } PropVariantClear(&value); InArchive->GetProperty(index, kpidMTime, &value); if (value.vt != VT_EMPTY) { getStream.FileInformation.LastWriteTime.LowPart = value.filetime.dwLowDateTime; getStream.FileInformation.LastWriteTime.HighPart = value.filetime.dwHighDateTime; getStream.FileInformation.ChangeTime = getStream.FileInformation.LastWriteTime; // fake value } PropVariantClear(&value); result = Callback(PkGetStreamMessage, action, &getStream, Context); if (!SUCCEEDED(result)) return result; if (getStream.FileStream) *outStream = &((PkFileStream *)getStream.FileStream)->OutStream; else *outStream = &(new PkFileStream(PkZeroFileStream, NULL))->OutStream; return S_OK; }
bool DominoConnector::GetInfoFromFileName(const std::wstring& fileName, std::wstring& repositoryId, std::wstring& artifactId, std::wstring& artifactVersionLabel) { USES_CONVERSION; if(!PathFileExistsW(fileName.c_str())) throw Workshare::System::IO::FileNotFoundException(fileName.c_str(), _T("The filename must exist in order to extract Lotus Domino.Doc information from the document")); DWORD grfMode = STGM_READWRITE | STGM_SHARE_EXCLUSIVE; IStorage* pStorage = NULL; HRESULT hr = ::StgOpenStorage(fileName.c_str(), NULL, grfMode, NULL, 0, &pStorage); switch(hr) { case S_OK: break; case STG_E_LOCKVIOLATION: case STG_E_SHAREVIOLATION: case STG_E_ACCESSDENIED: { ILockBytesPtr spLockBytes(ReadFileIntoMemory(fileName.c_str()), false); hr = ::StgOpenStorageOnILockBytes(spLockBytes, NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &pStorage); if(FAILED(hr)) { std::tostringstream msg; msg << _T("The file, [") << fileName.c_str() << _T("], has been locked. An attempt was made to read it into memory (into an instance of ILockBytes) and open a storage from there, but that failed too.") << std::ends; throw Workshare::Com::ComException(msg.str().c_str(), hr); } } break; default: { std::tostringstream msg; msg << _T("Failed to open [") << fileName.c_str() << _T("] using StgOpenStorage while checking to see whether the document has Domino.Doc properties or not.") << std::ends; throw Workshare::Com::ComException(msg.str().c_str(), hr); } break; } IStoragePtr spStorage(pStorage, false); IPropertySetStoragePtr spPropertySetStorage(spStorage); IPropertyStorage* pPropertyStorage = NULL; hr = spPropertySetStorage->Open(FMTID_UserDefinedProperties, grfMode, &pPropertyStorage); if(FAILED(hr)) { Log(_T("Failed to open the custom properties storage from [%S] while trying to determine whether its a Domino.Doc document or not."), fileName.c_str()); return false; } IPropertyStoragePtr spPropertyStorage(pPropertyStorage, false); IEnumSTATPROPSTG *pEnumSTATPROPSTG = NULL; hr = spPropertyStorage->Enum(&pEnumSTATPROPSTG); if(FAILED(hr)) { std::tostringstream msg; msg << _T("Failed to obtain an enumeration for the custom properties of [") << fileName.c_str() << _T("] while checking to see whether the document has Domino.Doc properties or not.") << std::ends; throw Workshare::Com::ComException(msg.str().c_str(), hr); } IEnumSTATPROPSTGPtr spEnum(pEnumSTATPROPSTG, false); bool isDominoDocument = false; STATPROPSTG property; hr = spEnum->Next(1, &property, NULL); while(S_OK == hr) { PROPSPEC specification; PROPVARIANT value; PropVariantInit(&value); try { // Build a PROPSPEC for this property. ZeroMemory(&specification, sizeof(specification)); specification.ulKind = PRSPEC_PROPID; specification.propid = property.propid; hr = spPropertyStorage->ReadMultiple(1, &specification, &value); if(FAILED(hr)) { std::tostringstream msg; msg << _T("Failed to read the property with id [") << property.propid << _T("] from the custom properties of [") << fileName.c_str() << _T("] while checking to see whether the document has Domino.Doc properties or not.") << std::ends; throw Workshare::Com::ComException(msg.str().c_str(), hr); } if(value.vt == VT_LPSTR) { if(0 == lstrcmpiW(property.lpwstrName, L"DDocLibrary")) { isDominoDocument = true; repositoryId = A2W(value.pszVal); } else if(0 == lstrcmpiW(property.lpwstrName, L"DDocRevision")) { isDominoDocument = true; artifactVersionLabel = A2W(value.pszVal); } else if(0 == lstrcmpiW(property.lpwstrName, L"DDocID")) { isDominoDocument = true; artifactId = A2W(value.pszVal); } } else if(value.vt == VT_LPWSTR) { if(0 == lstrcmpiW(property.lpwstrName, L"DDocLibrary")) { isDominoDocument = true; repositoryId = value.pwszVal; } else if(0 == lstrcmpiW(property.lpwstrName, L"DDocRevision")) { isDominoDocument = true; artifactVersionLabel = value.pwszVal; } else if(0 == lstrcmpiW(property.lpwstrName, L"DDocID")) { isDominoDocument = true; artifactId = value.pwszVal; } } PropVariantClear(&value); } catch(...) { //TODO: Do we need to deal with failure to free a resource? PropVariantClear(&value); throw; } hr = spEnum->Next(1, &property, NULL); } return isDominoDocument; }
static void test_metadata_tEXt(void) { HRESULT hr; IWICMetadataReader *reader; IWICEnumMetadataItem *enumerator; PROPVARIANT schema, id, value; ULONG items_returned, count; GUID format; PropVariantInit(&schema); PropVariantInit(&id); PropVariantInit(&value); hr = CoCreateInstance(&CLSID_WICPngTextMetadataReader, NULL, CLSCTX_INPROC_SERVER, &IID_IWICMetadataReader, (void**)&reader); todo_wine ok(hr == S_OK, "CoCreateInstance failed, hr=%x\n", hr); if (FAILED(hr)) return; hr = IWICMetadataReader_GetCount(reader, NULL); ok(hr == E_INVALIDARG, "GetCount failed, hr=%x\n", hr); hr = IWICMetadataReader_GetCount(reader, &count); ok(hr == S_OK, "GetCount failed, hr=%x\n", hr); ok(count == 0, "unexpected count %i\n", count); load_stream((IUnknown*)reader, metadata_tEXt, sizeof(metadata_tEXt)); hr = IWICMetadataReader_GetCount(reader, &count); ok(hr == S_OK, "GetCount failed, hr=%x\n", hr); ok(count == 1, "unexpected count %i\n", count); hr = IWICMetadataReader_GetEnumerator(reader, NULL); ok(hr == E_INVALIDARG, "GetEnumerator failed, hr=%x\n", hr); hr = IWICMetadataReader_GetEnumerator(reader, &enumerator); ok(hr == S_OK, "GetEnumerator failed, hr=%x\n", hr); if (SUCCEEDED(hr)) { hr = IWICEnumMetadataItem_Next(enumerator, 1, &schema, &id, &value, &items_returned); ok(hr == S_OK, "Next failed, hr=%x\n", hr); ok(items_returned == 1, "unexpected item count %i\n", items_returned); if (hr == S_OK && items_returned == 1) { ok(schema.vt == VT_EMPTY, "unexpected vt: %i\n", schema.vt); ok(id.vt == VT_LPSTR, "unexpected vt: %i\n", id.vt); ok(!strcmp(id.pszVal, "winetest"), "unexpected id: %s\n", id.pszVal); ok(value.vt == VT_LPSTR, "unexpected vt: %i\n", id.vt); ok(!strcmp(value.pszVal, "value"), "unexpected value: %s\n", id.pszVal); PropVariantClear(&schema); PropVariantClear(&id); PropVariantClear(&value); } hr = IWICEnumMetadataItem_Next(enumerator, 1, &schema, &id, &value, &items_returned); ok(hr == S_FALSE, "Next failed, hr=%x\n", hr); ok(items_returned == 0, "unexpected item count %i\n", items_returned); IWICEnumMetadataItem_Release(enumerator); } hr = IWICMetadataReader_GetMetadataFormat(reader, &format); ok(hr == S_OK, "GetMetadataFormat failed, hr=%x\n", hr); ok(IsEqualGUID(&format, &GUID_MetadataFormatChunktEXt), "unexpected format %s\n", debugstr_guid(&format)); hr = IWICMetadataReader_GetMetadataFormat(reader, NULL); ok(hr == E_INVALIDARG, "GetMetadataFormat failed, hr=%x\n", hr); id.vt = VT_LPSTR; id.pszVal = CoTaskMemAlloc(strlen("winetest") + 1); strcpy(id.pszVal, "winetest"); hr = IWICMetadataReader_GetValue(reader, NULL, &id, NULL); ok(hr == S_OK, "GetValue failed, hr=%x\n", hr); hr = IWICMetadataReader_GetValue(reader, &schema, NULL, &value); ok(hr == E_INVALIDARG, "GetValue failed, hr=%x\n", hr); hr = IWICMetadataReader_GetValue(reader, &schema, &id, &value); ok(hr == S_OK, "GetValue failed, hr=%x\n", hr); ok(value.vt == VT_LPSTR, "unexpected vt: %i\n", id.vt); ok(!strcmp(value.pszVal, "value"), "unexpected value: %s\n", id.pszVal); PropVariantClear(&value); strcpy(id.pszVal, "test"); hr = IWICMetadataReader_GetValue(reader, &schema, &id, &value); ok(hr == WINCODEC_ERR_PROPERTYNOTFOUND, "GetValue failed, hr=%x\n", hr); PropVariantClear(&id); hr = IWICMetadataReader_GetValueByIndex(reader, 0, NULL, NULL, NULL); ok(hr == S_OK, "GetValueByIndex failed, hr=%x\n", hr); hr = IWICMetadataReader_GetValueByIndex(reader, 0, &schema, NULL, NULL); ok(hr == S_OK, "GetValueByIndex failed, hr=%x\n", hr); ok(schema.vt == VT_EMPTY, "unexpected vt: %i\n", schema.vt); hr = IWICMetadataReader_GetValueByIndex(reader, 0, NULL, &id, NULL); ok(hr == S_OK, "GetValueByIndex failed, hr=%x\n", hr); ok(id.vt == VT_LPSTR, "unexpected vt: %i\n", id.vt); ok(!strcmp(id.pszVal, "winetest"), "unexpected id: %s\n", id.pszVal); PropVariantClear(&id); hr = IWICMetadataReader_GetValueByIndex(reader, 0, NULL, NULL, &value); ok(hr == S_OK, "GetValueByIndex failed, hr=%x\n", hr); ok(value.vt == VT_LPSTR, "unexpected vt: %i\n", id.vt); ok(!strcmp(value.pszVal, "value"), "unexpected value: %s\n", id.pszVal); PropVariantClear(&value); hr = IWICMetadataReader_GetValueByIndex(reader, 1, NULL, NULL, NULL); ok(hr == E_INVALIDARG, "GetValueByIndex failed, hr=%x\n", hr); IWICMetadataReader_Release(reader); }
HRESULT LogAttributeValueByIndexNew(IMFAttributes *pAttr, DWORD index, MfVideoCapture::MediaType &out) { WCHAR *pGuidName = NULL; WCHAR *pGuidValName = NULL; GUID guid = { 0 }; PROPVARIANT var; PropVariantInit(&var); HRESULT hr = pAttr->GetItemByIndex(index, &guid, &var); if (FAILED(hr)) { goto done; } hr = GetGUIDNameNew(guid, &pGuidName); if (FAILED(hr)) { goto done; } hr = SpecialCaseAttributeValueNew(guid, var, out); unsigned int *p; if (FAILED(hr)) { goto done; } if (hr == S_FALSE) { switch (var.vt) { case VT_UI4: p = GetParameter(guid, out); if(p) { *p = var.ulVal; } break; case VT_UI8: break; case VT_R8: break; case VT_CLSID: if(guid == MF_MT_AM_FORMAT_TYPE) { hr = GetGUIDNameNew(*var.puuid, &pGuidValName); if (SUCCEEDED(hr)) { out.MF_MT_AM_FORMAT_TYPE = MF_MT_AM_FORMAT_TYPE; out.MF_MT_AM_FORMAT_TYPEName = std::wstring(pGuidValName); pGuidValName = NULL; } } if(guid == MF_MT_MAJOR_TYPE) { hr = GetGUIDNameNew(*var.puuid, &pGuidValName); if (SUCCEEDED(hr)) { out.MF_MT_MAJOR_TYPE = MF_MT_MAJOR_TYPE; out.MF_MT_MAJOR_TYPEName = std::wstring(pGuidValName); pGuidValName = NULL; } } if(guid == MF_MT_SUBTYPE) { hr = GetGUIDNameNew(*var.puuid, &pGuidValName); if (SUCCEEDED(hr)) { out.MF_MT_SUBTYPE = MF_MT_SUBTYPE; out.MF_MT_SUBTYPEName = std::wstring(pGuidValName); pGuidValName = NULL; } } break; case VT_LPWSTR: break; case VT_VECTOR | VT_UI1: break; case VT_UNKNOWN: break; default: break; } } done: CoTaskMemFree(pGuidName); CoTaskMemFree(pGuidValName); PropVariantClear(&var); return hr; }
// Retreives the object identifier for the persistent unique identifer void GetObjectIdentifierFromPersistentUniqueIdentifier( IPortableDevice* pDevice) { if (pDevice == NULL) { printf("! A NULL IPortableDevice interface pointer was received\n"); return; } HRESULT hr = S_OK; WCHAR szSelection[81] = {0}; CComPtr<IPortableDeviceContent> pContent; CComPtr<IPortableDevicePropVariantCollection> pPersistentUniqueIDs; CComPtr<IPortableDevicePropVariantCollection> pObjectIDs; //<SnippetContentProp7> // Prompt user to enter an unique identifier to convert to an object idenifier. printf("Enter the Persistant Unique Identifier of the object you wish to convert into an object identifier.\n>"); hr = StringCbGetsW(szSelection,sizeof(szSelection)); if (FAILED(hr)) { printf("An invalid persistent object identifier was specified, aborting the query operation\n"); } //</SnippetContentProp7> // 1) Get an IPortableDeviceContent interface from the IPortableDevice interface to // access the content-specific methods. //<SnippetContentProp8> if (SUCCEEDED(hr)) { hr = pDevice->Content(&pContent); if (FAILED(hr)) { printf("! Failed to get IPortableDeviceContent from IPortableDevice, hr = 0x%lx\n",hr); } } //</SnippetContentProp8> // 2) CoCreate an IPortableDevicePropVariantCollection interface to hold the the Unique Identifiers // to query for Object Identifiers. // // NOTE: This is a collection interface so more than 1 identifier can be requested at a time. // This sample only requests a single unique identifier. //<SnippetContentProp9> hr = CoCreateInstance(CLSID_PortableDevicePropVariantCollection, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pPersistentUniqueIDs)); //</SnippetContentProp9> //<SnippetContentProp10> if (SUCCEEDED(hr)) { if (pPersistentUniqueIDs != NULL) { PROPVARIANT pv = {0}; PropVariantInit(&pv); // Initialize a PROPVARIANT structure with the object identifier string // that the user selected above. Notice we are allocating memory for the // PWSTR value. This memory will be freed when PropVariantClear() is // called below. pv.vt = VT_LPWSTR; pv.pwszVal = AtlAllocTaskWideString(szSelection); if (pv.pwszVal != NULL) { // Add the object identifier to the objects-to-delete list // (We are only deleting 1 in this example) hr = pPersistentUniqueIDs->Add(&pv); if (SUCCEEDED(hr)) { // 3) Attempt to get the unique idenifier for the object from the device hr = pContent->GetObjectIDsFromPersistentUniqueIDs(pPersistentUniqueIDs, &pObjectIDs); if (SUCCEEDED(hr)) { PROPVARIANT pvId = {0}; hr = pObjectIDs->GetAt(0, &pvId); if (SUCCEEDED(hr)) { printf("The persistent unique identifier '%ws' relates to object identifier '%ws' on the device.\n", szSelection, pvId.pwszVal); } else { printf("! Failed to get the object identifier for '%ws' from the IPortableDevicePropVariantCollection, hr = 0x%lx\n",szSelection, hr); } // Free the returned allocated string from the GetAt() call PropVariantClear(&pvId); } else { printf("! Failed to get the object identifier from persistent object idenifier '%ws', hr = 0x%lx\n",szSelection, hr); } } else { printf("! Failed to get the object identifier from persistent object idenifier because we could no add the persistent object identifier string to the IPortableDevicePropVariantCollection, hr = 0x%lx\n",hr); } } else { hr = E_OUTOFMEMORY; printf("! Failed to get the object identifier because we could no allocate memory for the persistent object identifier string, hr = 0x%lx\n",hr); } // Free any allocated values in the PROPVARIANT before exiting PropVariantClear(&pv); } } //</SnippetContentProp10> }
static HRESULT WINAPI PersistFile_Save(IPersistFile *pFile, LPCOLESTR pszFileName, BOOL fRemember) { HRESULT hr = S_OK; INT len; CHAR *url; InternetShortcut *This = impl_from_IPersistFile(pFile); TRACE("(%p, %s, %d)\n", pFile, debugstr_w(pszFileName), fRemember); if (pszFileName != NULL && fRemember) { LPOLESTR oldFile = This->currentFile; This->currentFile = co_strdupW(pszFileName); if (This->currentFile == NULL) { This->currentFile = oldFile; return E_OUTOFMEMORY; } CoTaskMemFree(oldFile); } if (This->url == NULL) return E_FAIL; /* Windows seems to always write: * ASCII "[InternetShortcut]" headers * ASCII names in "name=value" pairs * An ASCII (probably UTF8?) value in "URL=..." */ len = WideCharToMultiByte(CP_UTF8, 0, This->url, -1, NULL, 0, 0, 0); url = heap_alloc(len); if (url != NULL) { HANDLE file; WideCharToMultiByte(CP_UTF8, 0, This->url, -1, url, len, 0, 0); file = CreateFileW(pszFileName, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (file != INVALID_HANDLE_VALUE) { DWORD bytesWritten; char *iconfile; char str_header[] = "[InternetShortcut]"; char str_URL[] = "URL="; char str_ICONFILE[] = "ICONFILE="; char str_eol[] = "\r\n"; IPropertyStorage *pPropStgRead; PROPSPEC ps[2]; PROPVARIANT pvread[2]; ps[0].ulKind = PRSPEC_PROPID; ps[0].u.propid = PID_IS_ICONFILE; ps[1].ulKind = PRSPEC_PROPID; ps[1].u.propid = PID_IS_ICONINDEX; WriteFile(file, str_header, lstrlenA(str_header), &bytesWritten, NULL); WriteFile(file, str_eol, lstrlenA(str_eol), &bytesWritten, NULL); WriteFile(file, str_URL, lstrlenA(str_URL), &bytesWritten, NULL); WriteFile(file, url, lstrlenA(url), &bytesWritten, NULL); WriteFile(file, str_eol, lstrlenA(str_eol), &bytesWritten, NULL); hr = IPropertySetStorage_Open(This->property_set_storage, &FMTID_Intshcut, STGM_READ|STGM_SHARE_EXCLUSIVE, &pPropStgRead); if SUCCEEDED(hr) { hr = IPropertyStorage_ReadMultiple(pPropStgRead, 2, ps, pvread); if (hr == S_FALSE) { /* None of the properties are present, that's ok */ hr = S_OK; IPropertyStorage_Release(pPropStgRead); } else if SUCCEEDED(hr) { char indexString[50]; len = WideCharToMultiByte(CP_UTF8, 0, pvread[0].u.pwszVal, -1, NULL, 0, 0, 0); iconfile = heap_alloc(len); if (iconfile != NULL) { WideCharToMultiByte(CP_UTF8, 0, pvread[0].u.pwszVal, -1, iconfile, len, 0, 0); WriteFile(file, str_ICONFILE, lstrlenA(str_ICONFILE), &bytesWritten, NULL); WriteFile(file, iconfile, lstrlenA(iconfile), &bytesWritten, NULL); WriteFile(file, str_eol, lstrlenA(str_eol), &bytesWritten, NULL); } sprintf(indexString, "ICONINDEX=%d", pvread[1].u.iVal); WriteFile(file, indexString, lstrlenA(indexString), &bytesWritten, NULL); WriteFile(file, str_eol, lstrlenA(str_eol), &bytesWritten, NULL); IPropertyStorage_Release(pPropStgRead); PropVariantClear(&pvread[0]); PropVariantClear(&pvread[1]); } else { TRACE("Unable to read properties.\n"); } }
// Writes a set of properties for all objects. void WriteContentPropertiesBulk( IPortableDevice* pDevice) { if (pDevice == NULL) { printf("! A NULL IPortableDevice interface pointer was received\n"); return; } HRESULT hr = S_OK; GUID guidContext = GUID_NULL; CSetBulkValuesCallback* pCallback = NULL; CComPtr<IPortableDeviceProperties> pProperties; CComPtr<IPortableDevicePropertiesBulk> pPropertiesBulk; CComPtr<IPortableDeviceValues> pObjectProperties; CComPtr<IPortableDeviceContent> pContent; CComPtr<IPortableDeviceValuesCollection> pPropertiesToWrite; CComPtr<IPortableDevicePropVariantCollection> pObjectIDs; DWORD cObjectIDs = 0; // 1) Get an IPortableDeviceContent interface from the IPortableDevice interface to // access the content-specific methods. hr = pDevice->Content(&pContent); if (FAILED(hr)) { printf("! Failed to get IPortableDeviceContent from IPortableDevice, hr = 0x%lx\n",hr); } // 2) Get an IPortableDeviceProperties interface from the IPortableDeviceContent interface // to access the property-specific methods. if (SUCCEEDED(hr)) { hr = pContent->Properties(&pProperties); if (FAILED(hr)) { printf("! Failed to get IPortableDeviceProperties from IPortableDevice, hr = 0x%lx\n",hr); } } // 3) Check to see if the driver supports BULK property operations by call QueryInterface // on the IPortableDeviceProperties interface for IPortableDevicePropertiesBulk if (SUCCEEDED(hr)) { hr = pProperties->QueryInterface(IID_PPV_ARGS(&pPropertiesBulk)); if (FAILED(hr)) { printf("This driver does not support BULK property operations.\n"); } } // 4) CoCreate an IPortableDeviceValuesCollection interface to hold the the properties // we wish to write. if (SUCCEEDED(hr)) { hr = CoCreateInstance(CLSID_PortableDeviceValuesCollection, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pPropertiesToWrite)); if (FAILED(hr)) { printf("! Failed to CoCreate IPortableDeviceValuesCollection for bulk property values, hr = 0x%lx\n", hr); } } // 6) Create an instance of the IPortableDevicePropertiesBulkCallback object. if (SUCCEEDED(hr)) { pCallback = new (std::nothrow) CSetBulkValuesCallback(); if (pCallback == NULL) { hr = E_OUTOFMEMORY; printf("! Failed to allocate CSetBulkValuesCallback, hr = 0x%lx\n", hr); } } // 7) Call our helper function CreateIPortableDevicePropVariantCollectionWithAllObjectIDs // to enumerate and create an IPortableDevicePropVariantCollection with the object // identifiers needed to perform the bulk operation on. if (SUCCEEDED(hr)) { hr = CreateIPortableDevicePropVariantCollectionWithAllObjectIDs(pContent, &pObjectIDs); } if (SUCCEEDED(hr)) { hr = pObjectIDs->GetCount(&cObjectIDs); if (FAILED(hr)) { printf("! Failed to get number of objectIDs from IPortableDevicePropVariantCollection, hr = 0x%lx\n", hr); } } // 8) Iterate through object list and add appropriate IPortableDeviceValues to collection if (SUCCEEDED(hr)) { for(DWORD dwIndex = 0; (dwIndex < cObjectIDs) && (hr == S_OK); dwIndex++) { CComPtr<IPortableDeviceValues> pValues; PROPVARIANT pv = {0}; PropVariantInit(&pv); hr = CoCreateInstance(CLSID_PortableDeviceValues, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pValues)); if (FAILED(hr)) { printf("! Failed to CoCreate CLSID_PortableDeviceValues, hr = 0x%lx\n", hr); } // Get the Object ID whose properties we will set if (hr == S_OK) { hr = pObjectIDs->GetAt(dwIndex, &pv); if (FAILED(hr)) { printf("! Failed to get next Object ID from list, hr = 0x%lx\n", hr); } } // Save them into the IPortableDeviceValues so the driver knows which object this proeprty set belongs to if (hr == S_OK) { hr = pValues->SetStringValue(WPD_OBJECT_ID, pv.pwszVal); if (FAILED(hr)) { printf("! Failed to set WPD_OBJECT_ID, hr = 0x%lx\n", hr); } } // Set the new values. In this sample, we attempt to set the name property. if (hr == S_OK) { CAtlStringW strValue; strValue.Format(L"NewName%d", dwIndex); hr = pValues->SetStringValue(WPD_OBJECT_NAME, strValue.GetString()); if (FAILED(hr)) { printf("! Failed to set WPD_OBJECT_NAME, hr = 0x%lx\n", hr); } } // Add this property set to the collection if (hr == S_OK) { hr = pPropertiesToWrite->Add(pValues); if (FAILED(hr)) { printf("! Failed to add values to collection, hr = 0x%lx\n", hr); } } PropVariantClear(&pv); } } // 9) Call QueueSetValuesByObjectList to initialize the Asynchronous // property operation. if (SUCCEEDED(hr)) { hr = pPropertiesBulk->QueueSetValuesByObjectList(pPropertiesToWrite, pCallback, &guidContext); // 10) Call Start() to actually being the property operation if(SUCCEEDED(hr)) { // Cleanup any previously created global event handles. if (g_hBulkPropertyOperationEvent != NULL) { CloseHandle(g_hBulkPropertyOperationEvent); g_hBulkPropertyOperationEvent = NULL; } // In order to create a simpler to follow example we create and wait infinitly // for the bulk property operation to complete and ignore any errors. // Production code should be written in a more robust manner. // Create the global event handle to wait on for the bulk operation // to complete. g_hBulkPropertyOperationEvent = CreateEvent(NULL, FALSE, FALSE, NULL); if (g_hBulkPropertyOperationEvent != NULL) { // Call Start() to actually being the Asynchronous bulk operation. hr = pPropertiesBulk->Start(guidContext); if(FAILED(hr)) { printf("! Failed to start property operation, hr = 0x%lx\n", hr); } } else { printf("! Failed to create the global event handle to wait on for the bulk operation. Aborting operation.\n"); } } else { printf("! QueueSetValuesByObjectList Failed, hr = 0x%lx\n", hr); } } // In order to create a simpler to follow example we will wait infinitly for the operation // to complete and ignore any errors. Production code should be written in a more // robust manner. if (SUCCEEDED(hr)) { if (g_hBulkPropertyOperationEvent != NULL) { WaitForSingleObject(g_hBulkPropertyOperationEvent, INFINITE); } } if (pCallback != NULL) { pCallback->Release(); pCallback = NULL; } // Cleanup any created global event handles before exiting.. if (g_hBulkPropertyOperationEvent != NULL) { CloseHandle(g_hBulkPropertyOperationEvent); g_hBulkPropertyOperationEvent = NULL; } }
bool CAESinkWASAPI::Initialize(AEAudioFormat &format, std::string &device) { if (m_initialized) return false; m_device = device; bool bdefault = false; /* Save requested format */ /* Clear returned format */ sinkReqFormat = format.m_dataFormat; sinkRetFormat = AE_FMT_INVALID; IMMDeviceEnumerator* pEnumerator = NULL; IMMDeviceCollection* pEnumDevices = NULL; HRESULT hr = CoCreateInstance(CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, IID_IMMDeviceEnumerator, (void**)&pEnumerator); EXIT_ON_FAILURE(hr, __FUNCTION__": Could not allocate WASAPI device enumerator. CoCreateInstance error code: %li", hr) /* Get our device. First try to find the named device. */ UINT uiCount = 0; hr = pEnumerator->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, &pEnumDevices); EXIT_ON_FAILURE(hr, __FUNCTION__": Retrieval of audio endpoint enumeration failed.") hr = pEnumDevices->GetCount(&uiCount); EXIT_ON_FAILURE(hr, __FUNCTION__": Retrieval of audio endpoint count failed.") if(StringUtils::EndsWithNoCase(device, std::string("default"))) bdefault = true; if(!bdefault) { for (UINT i = 0; i < uiCount; i++) { IPropertyStore *pProperty = NULL; PROPVARIANT varName; hr = pEnumDevices->Item(i, &m_pDevice); EXIT_ON_FAILURE(hr, __FUNCTION__": Retrieval of WASAPI endpoint failed.") hr = m_pDevice->OpenPropertyStore(STGM_READ, &pProperty); EXIT_ON_FAILURE(hr, __FUNCTION__": Retrieval of WASAPI endpoint properties failed.") hr = pProperty->GetValue(PKEY_AudioEndpoint_GUID, &varName); if (FAILED(hr)) { CLog::Log(LOGERROR, __FUNCTION__": Retrieval of WASAPI endpoint GUID failed."); SAFE_RELEASE(pProperty); goto failed; } std::string strDevName = localWideToUtf(varName.pwszVal); if (device == strDevName) i = uiCount; else SAFE_RELEASE(m_pDevice); PropVariantClear(&varName); SAFE_RELEASE(pProperty); } } SAFE_RELEASE(pEnumDevices); if (!m_pDevice) { if(!bdefault) CLog::Log(LOGINFO, __FUNCTION__": Could not locate the device named \"%s\" in the list of WASAPI endpoint devices. Trying the default device...", device.c_str()); hr = pEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &m_pDevice); EXIT_ON_FAILURE(hr, __FUNCTION__": Could not retrieve the default WASAPI audio endpoint.") IPropertyStore *pProperty = NULL; PROPVARIANT varName; hr = m_pDevice->OpenPropertyStore(STGM_READ, &pProperty); EXIT_ON_FAILURE(hr, __FUNCTION__": Retrieval of WASAPI endpoint properties failed.") hr = pProperty->GetValue(PKEY_AudioEndpoint_GUID, &varName); device = localWideToUtf(varName.pwszVal); PropVariantClear(&varName); SAFE_RELEASE(pProperty); } SAFE_RELEASE(pEnumerator); hr = m_pDevice->Activate(IID_IAudioClient, CLSCTX_ALL, NULL, (void**)&m_pAudioClient); EXIT_ON_FAILURE(hr, __FUNCTION__": Activating the WASAPI endpoint device failed.") if (!InitializeExclusive(format)) { CLog::Log(LOGINFO, __FUNCTION__": Could not Initialize Exclusive with that format"); goto failed; } /* get the buffer size and calculate the frames for AE */ m_pAudioClient->GetBufferSize(&m_uiBufferLen); format.m_frames = m_uiBufferLen; format.m_frameSamples = format.m_frames * format.m_channelLayout.Count(); m_format = format; sinkRetFormat = format.m_dataFormat; hr = m_pAudioClient->GetService(IID_IAudioRenderClient, (void**)&m_pRenderClient); EXIT_ON_FAILURE(hr, __FUNCTION__": Could not initialize the WASAPI render client interface.") m_needDataEvent = CreateEvent(NULL, FALSE, FALSE, NULL); hr = m_pAudioClient->SetEventHandle(m_needDataEvent); EXIT_ON_FAILURE(hr, __FUNCTION__": Could not set the WASAPI event handler."); m_initialized = true; m_isDirty = false; // allow feeding less samples than buffer size // if the device is opened exclusive and event driven, provided samples must match buffersize // ActiveAE tries to align provided samples with buffer size but cannot guarantee (e.g. transcoding) // this can be avoided by dropping the event mode which has not much benefit; SoftAE polls anyway delete [] m_pBuffer; m_pBuffer = new uint8_t[format.m_frames * format.m_frameSize]; m_bufferPtr = 0; return true; failed: CLog::Log(LOGERROR, __FUNCTION__": WASAPI initialization failed."); SAFE_RELEASE(pEnumDevices); SAFE_RELEASE(pEnumerator); SAFE_RELEASE(m_pRenderClient); SAFE_RELEASE(m_pAudioClient); SAFE_RELEASE(m_pDevice); if(m_needDataEvent) { CloseHandle(m_needDataEvent); m_needDataEvent = 0; } return false; }
/** * This method is called when we receive a WPD_COMMAND_OBJECT_PROPERTIES_BULK_GET_VALUES_BY_OBJECT_FORMAT_NEXT * command. * * The parameters sent to us are: * - WPD_PROPERTY_OBJECT_PROPERTIES_BULK_CONTEXT: the context the driver returned to * the client in OnGetValuesByObjectFormatStart. * * The driver should: * - Return the next set of property values in WPD_PROPERTY_OBJECT_PROPERTIES_BULK_VALUES. * If there are no more properties to be read an * empty collection should be returned. * - It is up to the driver to return as many object property values as it wants. If zero values are returned * it is assumed the bulk operation is complete and the WPD_COMMAND_OBJECT_PROPERTIES_BULK_GET_VALUES_BY_OBJECT_FORMAT_END * will be called next. * * - S_OK should be returned if the collection can be returned successfully. * - Any error return indicates that the driver did not fill in any results, and the caller will * not attempt to unpack any property values. */ HRESULT WpdObjectPropertiesBulk::OnGetValuesByObjectFormatNext( __in IPortableDeviceValues* pParams, __out IPortableDeviceValues* pResults) { HRESULT hr = S_OK; LPWSTR pwszContext = NULL; BulkPropertiesContext* pContext = NULL; DWORD cObjects = 0; CComPtr<IPortableDeviceValuesCollection> pCollection; if (hr == S_OK) { hr = pParams->GetStringValue(WPD_PROPERTY_OBJECT_PROPERTIES_BULK_CONTEXT, &pwszContext); CHECK_HR(hr, "Failed to get WPD_PROPERTY_OBJECT_PROPERTIES_BULK_CONTEXT from IPortableDeviceValues"); } // Get the bulk property operation context if (hr == S_OK) { hr = GetClientContext(pParams, pwszContext, (IUnknown**) &pContext); CHECK_HR(hr, "Failed to get bulk property context"); } // Make sure the the collection holds VT_LPWSTR values. if (hr == S_OK) { hr = pContext->ObjectIDs->ChangeType(VT_LPWSTR); CHECK_HR(hr, "Failed to change objectIDs collection to VT_LPWSTR"); } if (hr == S_OK) { hr = pContext->ObjectIDs->GetCount(&cObjects); CHECK_HR(hr, "Failed to get number of objectIDs from bulk properties context"); } if (hr == S_OK) { cObjects = cObjects - pContext->NextObject; if(cObjects > MAX_OBJECTS_TO_RETURN) { cObjects = MAX_OBJECTS_TO_RETURN; } } if (hr == S_OK) { hr = CoCreateInstance(CLSID_PortableDeviceValuesCollection, NULL, CLSCTX_INPROC_SERVER, IID_IPortableDeviceValuesCollection, (VOID**) &pCollection); CHECK_HR(hr, "Failed to CoCreate CLSID_PortableDeviceValuesCollection"); } if (hr == S_OK) { for (DWORD dwIndex = pContext->NextObject, dwCount = 0; dwCount < cObjects; dwCount++, dwIndex++) { CComPtr<IPortableDeviceValues> pValues; PROPVARIANT pv = {0}; PropVariantInit(&pv); hr = pContext->ObjectIDs->GetAt(dwIndex, &pv); CHECK_HR(hr, "Failed to get next object ID from bulk properties context"); if (hr == S_OK) { hr = CoCreateInstance(CLSID_PortableDeviceValues, NULL, CLSCTX_INPROC_SERVER, IID_IPortableDeviceValues, (VOID**) &pValues); CHECK_HR(hr, "Failed to CoCreate CLSID_PortableDeviceValuesCollection"); } if (hr == S_OK) { // If a key list was supplied, get the specified object properties, other get all // properties. if(pContext->Properties != NULL) { hr = m_pDevice->GetPropertyValues(pContext->Scope, pv.pwszVal, pContext->Properties, pValues); CHECK_HR(hr, "Failed to get property values for [%ws]", pv.pwszVal); } else { hr = m_pDevice->GetAllPropertyValues(pContext->Scope,pv.pwszVal, pValues); CHECK_HR(hr, "Failed to get property values for [%ws]", pv.pwszVal); } // Add the ObjectID to the returned results if (hr == S_OK) { hr = pValues->SetStringValue(WPD_OBJECT_ID, pv.pwszVal); CHECK_HR(hr, "Failed to set WPD_OBJECT_ID for %ws", pv.pwszVal); } } if (hr == S_OK) { hr = pCollection->Add(pValues); CHECK_HR(hr, "Failed to add IPortableDeviceValues to IPortableDeviceValuesCollection"); } PropVariantClear(&pv); pContext->NextObject++; } } if (hr == S_OK) { hr = pResults->SetIUnknownValue(WPD_PROPERTY_OBJECT_PROPERTIES_BULK_VALUES, pCollection); CHECK_HR(hr, "Failed to set WPD_PROPERTY_OBJECT_PROPERTIES_BULK_VALUES"); } // Free the memory. CoTaskMemFree ignores NULLs so no need to check. CoTaskMemFree(pwszContext); SAFE_RELEASE(pContext); return hr; }
void CAESinkWASAPI::EnumerateDevicesEx(AEDeviceInfoList &deviceInfoList, bool force) { IMMDeviceEnumerator* pEnumerator = NULL; IMMDeviceCollection* pEnumDevices = NULL; IMMDevice* pDefaultDevice = NULL; CAEDeviceInfo deviceInfo; CAEChannelInfo deviceChannels; LPWSTR pwszID = NULL; std::wstring wstrDDID; WAVEFORMATEXTENSIBLE wfxex = {0}; HRESULT hr; hr = CoCreateInstance(CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, IID_IMMDeviceEnumerator, (void**)&pEnumerator); EXIT_ON_FAILURE(hr, __FUNCTION__": Could not allocate WASAPI device enumerator. CoCreateInstance error code: %li", hr) UINT uiCount = 0; // get the default audio endpoint if(pEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &pDefaultDevice) == S_OK) { if(pDefaultDevice->GetId(&pwszID) == S_OK) { wstrDDID = pwszID; CoTaskMemFree(pwszID); } SAFE_RELEASE(pDefaultDevice); } // enumerate over all audio endpoints hr = pEnumerator->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, &pEnumDevices); EXIT_ON_FAILURE(hr, __FUNCTION__": Retrieval of audio endpoint enumeration failed.") hr = pEnumDevices->GetCount(&uiCount); EXIT_ON_FAILURE(hr, __FUNCTION__": Retrieval of audio endpoint count failed.") for (UINT i = 0; i < uiCount; i++) { IMMDevice *pDevice = NULL; IPropertyStore *pProperty = NULL; PROPVARIANT varName; PropVariantInit(&varName); deviceInfo.m_channels.Reset(); deviceInfo.m_dataFormats.clear(); deviceInfo.m_sampleRates.clear(); hr = pEnumDevices->Item(i, &pDevice); if (FAILED(hr)) { CLog::Log(LOGERROR, __FUNCTION__": Retrieval of WASAPI endpoint failed."); goto failed; } hr = pDevice->OpenPropertyStore(STGM_READ, &pProperty); if (FAILED(hr)) { CLog::Log(LOGERROR, __FUNCTION__": Retrieval of WASAPI endpoint properties failed."); SAFE_RELEASE(pDevice); goto failed; } hr = pProperty->GetValue(PKEY_Device_FriendlyName, &varName); if (FAILED(hr)) { CLog::Log(LOGERROR, __FUNCTION__": Retrieval of WASAPI endpoint device name failed."); SAFE_RELEASE(pDevice); SAFE_RELEASE(pProperty); goto failed; } std::string strFriendlyName = localWideToUtf(varName.pwszVal); PropVariantClear(&varName); hr = pProperty->GetValue(PKEY_AudioEndpoint_GUID, &varName); if(FAILED(hr)) { CLog::Log(LOGERROR, __FUNCTION__": Retrieval of WASAPI endpoint GUID failed."); SAFE_RELEASE(pDevice); SAFE_RELEASE(pProperty); goto failed; } std::string strDevName = localWideToUtf(varName.pwszVal); PropVariantClear(&varName); hr = pProperty->GetValue(PKEY_AudioEndpoint_FormFactor, &varName); if (FAILED(hr)) { CLog::Log(LOGERROR, __FUNCTION__": Retrieval of WASAPI endpoint form factor failed."); SAFE_RELEASE(pDevice); SAFE_RELEASE(pProperty); goto failed; } std::string strWinDevType = winEndpoints[(EndpointFormFactor)varName.uiVal].winEndpointType; AEDeviceType aeDeviceType = winEndpoints[(EndpointFormFactor)varName.uiVal].aeDeviceType; PropVariantClear(&varName); hr = pProperty->GetValue(PKEY_AudioEndpoint_PhysicalSpeakers, &varName); if (FAILED(hr)) { CLog::Log(LOGERROR, __FUNCTION__": Retrieval of WASAPI endpoint speaker layout failed."); SAFE_RELEASE(pDevice); SAFE_RELEASE(pProperty); goto failed; } unsigned int uiChannelMask = std::max(varName.uintVal, (unsigned int) KSAUDIO_SPEAKER_STEREO); deviceChannels.Reset(); for (unsigned int c = 0; c < WASAPI_SPEAKER_COUNT; c++) { if (uiChannelMask & WASAPIChannelOrder[c]) deviceChannels += AEChannelNames[c]; } PropVariantClear(&varName); IAudioClient *pClient; hr = pDevice->Activate(IID_IAudioClient, CLSCTX_ALL, NULL, (void**)&pClient); if (SUCCEEDED(hr)) { /* Test format DTS-HD */ wfxex.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX); wfxex.Format.nSamplesPerSec = 192000; wfxex.dwChannelMask = KSAUDIO_SPEAKER_7POINT1_SURROUND; wfxex.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; wfxex.SubFormat = KSDATAFORMAT_SUBTYPE_IEC61937_DTS_HD; wfxex.Format.wBitsPerSample = 16; wfxex.Samples.wValidBitsPerSample = 16; wfxex.Format.nChannels = 8; wfxex.Format.nBlockAlign = wfxex.Format.nChannels * (wfxex.Format.wBitsPerSample >> 3); wfxex.Format.nAvgBytesPerSec = wfxex.Format.nSamplesPerSec * wfxex.Format.nBlockAlign; hr = pClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, &wfxex.Format, NULL); if (SUCCEEDED(hr)) deviceInfo.m_dataFormats.push_back(AEDataFormat(AE_FMT_DTSHD)); /* Test format Dolby TrueHD */ wfxex.SubFormat = KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_MLP; hr = pClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, &wfxex.Format, NULL); if (SUCCEEDED(hr)) deviceInfo.m_dataFormats.push_back(AEDataFormat(AE_FMT_TRUEHD)); /* Test format Dolby EAC3 */ wfxex.SubFormat = KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_DIGITAL_PLUS; wfxex.Format.nChannels = 2; wfxex.Format.nBlockAlign = wfxex.Format.nChannels * (wfxex.Format.wBitsPerSample >> 3); wfxex.Format.nAvgBytesPerSec = wfxex.Format.nSamplesPerSec * wfxex.Format.nBlockAlign; hr = pClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, &wfxex.Format, NULL); if (SUCCEEDED(hr)) deviceInfo.m_dataFormats.push_back(AEDataFormat(AE_FMT_EAC3)); /* Test format DTS */ wfxex.Format.nSamplesPerSec = 48000; wfxex.dwChannelMask = KSAUDIO_SPEAKER_5POINT1; wfxex.SubFormat = KSDATAFORMAT_SUBTYPE_IEC61937_DTS; wfxex.Format.nBlockAlign = wfxex.Format.nChannels * (wfxex.Format.wBitsPerSample >> 3); wfxex.Format.nAvgBytesPerSec = wfxex.Format.nSamplesPerSec * wfxex.Format.nBlockAlign; hr = pClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, &wfxex.Format, NULL); if (SUCCEEDED(hr)) deviceInfo.m_dataFormats.push_back(AEDataFormat(AE_FMT_DTS)); /* Test format Dolby AC3 */ wfxex.SubFormat = KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_DIGITAL; hr = pClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, &wfxex.Format, NULL); if (SUCCEEDED(hr)) deviceInfo.m_dataFormats.push_back(AEDataFormat(AE_FMT_AC3)); /* Test format AAC */ wfxex.SubFormat = KSDATAFORMAT_SUBTYPE_IEC61937_AAC; hr = pClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, &wfxex.Format, NULL); if (SUCCEEDED(hr)) deviceInfo.m_dataFormats.push_back(AEDataFormat(AE_FMT_AAC)); /* Test format for PCM format iteration */ wfxex.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX); wfxex.dwChannelMask = KSAUDIO_SPEAKER_STEREO; wfxex.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; wfxex.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT; for (int p = AE_FMT_FLOAT; p > AE_FMT_INVALID; p--) { if (p < AE_FMT_FLOAT) wfxex.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; wfxex.Format.wBitsPerSample = CAEUtil::DataFormatToBits((AEDataFormat) p); wfxex.Format.nBlockAlign = wfxex.Format.nChannels * (wfxex.Format.wBitsPerSample >> 3); wfxex.Format.nAvgBytesPerSec = wfxex.Format.nSamplesPerSec * wfxex.Format.nBlockAlign; if (p <= AE_FMT_S24NE4 && p >= AE_FMT_S24BE4) { wfxex.Samples.wValidBitsPerSample = 24; } else { wfxex.Samples.wValidBitsPerSample = wfxex.Format.wBitsPerSample; } hr = pClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, &wfxex.Format, NULL); if (SUCCEEDED(hr)) deviceInfo.m_dataFormats.push_back((AEDataFormat) p); } /* Test format for sample rate iteration */ wfxex.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX); wfxex.dwChannelMask = KSAUDIO_SPEAKER_STEREO; wfxex.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; wfxex.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; wfxex.Format.wBitsPerSample = 16; wfxex.Samples.wValidBitsPerSample = 16; wfxex.Format.nChannels = 2; wfxex.Format.nBlockAlign = wfxex.Format.nChannels * (wfxex.Format.wBitsPerSample >> 3); wfxex.Format.nAvgBytesPerSec = wfxex.Format.nSamplesPerSec * wfxex.Format.nBlockAlign; for (int j = 0; j < WASAPISampleRateCount; j++) { wfxex.Format.nSamplesPerSec = WASAPISampleRates[j]; wfxex.Format.nAvgBytesPerSec = wfxex.Format.nSamplesPerSec * wfxex.Format.nBlockAlign; hr = pClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, &wfxex.Format, NULL); if (SUCCEEDED(hr)) deviceInfo.m_sampleRates.push_back(WASAPISampleRates[j]); } /* Test format for channels iteration */ wfxex.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX); wfxex.dwChannelMask = KSAUDIO_SPEAKER_STEREO; wfxex.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; wfxex.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; wfxex.Format.nSamplesPerSec = 48000; wfxex.Format.wBitsPerSample = 16; wfxex.Samples.wValidBitsPerSample = 16; wfxex.Format.nChannels = 2; wfxex.Format.nBlockAlign = wfxex.Format.nChannels * (wfxex.Format.wBitsPerSample >> 3); wfxex.Format.nAvgBytesPerSec = wfxex.Format.nSamplesPerSec * wfxex.Format.nBlockAlign; bool hasLpcm = false; // Try with KSAUDIO_SPEAKER_DIRECTOUT for (unsigned int k = WASAPI_SPEAKER_COUNT; k > 0; k--) { wfxex.dwChannelMask = KSAUDIO_SPEAKER_DIRECTOUT; wfxex.Format.nChannels = k; wfxex.Format.nBlockAlign = wfxex.Format.nChannels * (wfxex.Format.wBitsPerSample >> 3); wfxex.Format.nAvgBytesPerSec = wfxex.Format.nSamplesPerSec * wfxex.Format.nBlockAlign; hr = pClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, &wfxex.Format, NULL); if (SUCCEEDED(hr)) { if (k > 3) // Add only multichannel LPCM { deviceInfo.m_dataFormats.push_back(AE_FMT_LPCM); hasLpcm = true; } break; } } /* Try with reported channel mask */ for (unsigned int k = WASAPI_SPEAKER_COUNT; k > 0; k--) { wfxex.dwChannelMask = uiChannelMask; wfxex.Format.nChannels = k; wfxex.Format.nBlockAlign = wfxex.Format.nChannels * (wfxex.Format.wBitsPerSample >> 3); wfxex.Format.nAvgBytesPerSec = wfxex.Format.nSamplesPerSec * wfxex.Format.nBlockAlign; hr = pClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, &wfxex.Format, NULL); if (SUCCEEDED(hr)) { if ( !hasLpcm && k > 3) // Add only multichannel LPCM { deviceInfo.m_dataFormats.push_back(AE_FMT_LPCM); hasLpcm = true; } break; } } /* Try with specific speakers configurations */ for (unsigned int i = 0; i < ARRAYSIZE(layoutsList); i++) { unsigned int nmbOfCh; wfxex.dwChannelMask = ChLayoutToChMask(layoutsList[i], &nmbOfCh); wfxex.Format.nChannels = nmbOfCh; wfxex.Format.nBlockAlign = wfxex.Format.nChannels * (wfxex.Format.wBitsPerSample >> 3); wfxex.Format.nAvgBytesPerSec = wfxex.Format.nSamplesPerSec * wfxex.Format.nBlockAlign; hr = pClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, &wfxex.Format, NULL); if (SUCCEEDED(hr)) { if ( deviceChannels.Count() < nmbOfCh) deviceChannels = layoutsList[i]; if ( !hasLpcm && nmbOfCh > 3) // Add only multichannel LPCM { deviceInfo.m_dataFormats.push_back(AE_FMT_LPCM); hasLpcm = true; } } } pClient->Release(); } else { CLog::Log(LOGDEBUG, __FUNCTION__": Failed to activate device for passthrough capability testing."); } deviceInfo.m_deviceName = strDevName; deviceInfo.m_displayName = strWinDevType.append(strFriendlyName); deviceInfo.m_displayNameExtra = std::string("WASAPI: ").append(strFriendlyName); deviceInfo.m_deviceType = aeDeviceType; deviceInfo.m_channels = deviceChannels; /* Store the device info */ deviceInfoList.push_back(deviceInfo); if(pDevice->GetId(&pwszID) == S_OK) { if(wstrDDID.compare(pwszID) == 0) { deviceInfo.m_deviceName = std::string("default"); deviceInfo.m_displayName = std::string("default"); deviceInfo.m_displayNameExtra = std::string(""); deviceInfoList.push_back(deviceInfo); } CoTaskMemFree(pwszID); } SAFE_RELEASE(pDevice); SAFE_RELEASE(pProperty); }
//--------------------------------------------------------------------------------- static HRESULT CreateTextureFromWIC( _In_ ID3D11Device* d3dDevice, _In_opt_ ID3D11DeviceContext* d3dContext, _In_ IWICBitmapFrameDecode *frame, _In_ size_t maxsize, _In_ D3D11_USAGE usage, _In_ unsigned int bindFlags, _In_ unsigned int cpuAccessFlags, _In_ unsigned int miscFlags, _In_ bool forceSRGB, _Out_opt_ ID3D11Resource** texture, _Out_opt_ ID3D11ShaderResourceView** textureView ) { UINT width, height; HRESULT hr = frame->GetSize( &width, &height ); if ( FAILED(hr) ) return hr; assert( width > 0 && height > 0 ); if ( !maxsize ) { // This is a bit conservative because the hardware could support larger textures than // the Feature Level defined minimums, but doing it this way is much easier and more // performant for WIC than the 'fail and retry' model used by DDSTextureLoader switch( d3dDevice->GetFeatureLevel() ) { case D3D_FEATURE_LEVEL_9_1: case D3D_FEATURE_LEVEL_9_2: maxsize = 2048 /*D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION*/; break; case D3D_FEATURE_LEVEL_9_3: maxsize = 4096 /*D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION*/; break; case D3D_FEATURE_LEVEL_10_0: case D3D_FEATURE_LEVEL_10_1: maxsize = 8192 /*D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION*/; break; default: maxsize = D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; break; } } assert( maxsize > 0 ); UINT twidth, theight; if ( width > maxsize || height > maxsize ) { float ar = static_cast<float>(height) / static_cast<float>(width); if ( width > height ) { twidth = static_cast<UINT>( maxsize ); theight = static_cast<UINT>( static_cast<float>(maxsize) * ar ); } else { theight = static_cast<UINT>( maxsize ); twidth = static_cast<UINT>( static_cast<float>(maxsize) / ar ); } assert( twidth <= maxsize && theight <= maxsize ); } else { twidth = width; theight = height; } // Determine format WICPixelFormatGUID pixelFormat; hr = frame->GetPixelFormat( &pixelFormat ); if ( FAILED(hr) ) return hr; WICPixelFormatGUID convertGUID; memcpy( &convertGUID, &pixelFormat, sizeof(WICPixelFormatGUID) ); size_t bpp = 0; DXGI_FORMAT format = _WICToDXGI( pixelFormat ); if ( format == DXGI_FORMAT_UNKNOWN ) { if ( memcmp( &GUID_WICPixelFormat96bppRGBFixedPoint, &pixelFormat, sizeof(WICPixelFormatGUID) ) == 0 ) { #if (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/) || defined(_WIN7_PLATFORM_UPDATE) if ( g_WIC2 ) { memcpy( &convertGUID, &GUID_WICPixelFormat96bppRGBFloat, sizeof(WICPixelFormatGUID) ); format = DXGI_FORMAT_R32G32B32_FLOAT; } else #endif { memcpy( &convertGUID, &GUID_WICPixelFormat128bppRGBAFloat, sizeof(WICPixelFormatGUID) ); format = DXGI_FORMAT_R32G32B32A32_FLOAT; } } else { for( size_t i=0; i < _countof(g_WICConvert); ++i ) { if ( memcmp( &g_WICConvert[i].source, &pixelFormat, sizeof(WICPixelFormatGUID) ) == 0 ) { memcpy( &convertGUID, &g_WICConvert[i].target, sizeof(WICPixelFormatGUID) ); format = _WICToDXGI( g_WICConvert[i].target ); assert( format != DXGI_FORMAT_UNKNOWN ); bpp = _WICBitsPerPixel( convertGUID ); break; } } } if ( format == DXGI_FORMAT_UNKNOWN ) return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED ); } else { bpp = _WICBitsPerPixel( pixelFormat ); } #if (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/) || defined(_WIN7_PLATFORM_UPDATE) if ( (format == DXGI_FORMAT_R32G32B32_FLOAT) && d3dContext != 0 && textureView != 0 ) { // Special case test for optional device support for autogen mipchains for R32G32B32_FLOAT UINT fmtSupport = 0; hr = d3dDevice->CheckFormatSupport( DXGI_FORMAT_R32G32B32_FLOAT, &fmtSupport ); if ( FAILED(hr) || !( fmtSupport & D3D11_FORMAT_SUPPORT_MIP_AUTOGEN ) ) { // Use R32G32B32A32_FLOAT instead which is required for Feature Level 10.0 and up memcpy( &convertGUID, &GUID_WICPixelFormat128bppRGBAFloat, sizeof(WICPixelFormatGUID) ); format = DXGI_FORMAT_R32G32B32A32_FLOAT; bpp = 128; } } #endif if ( !bpp ) return E_FAIL; // Handle sRGB formats if ( forceSRGB ) { format = MakeSRGB( format ); } else { ScopedObject<IWICMetadataQueryReader> metareader; if ( SUCCEEDED( frame->GetMetadataQueryReader( &metareader ) ) ) { GUID containerFormat; if ( SUCCEEDED( metareader->GetContainerFormat( &containerFormat ) ) ) { // Check for sRGB colorspace metadata bool sRGB = false; PROPVARIANT value; PropVariantInit( &value ); if ( memcmp( &containerFormat, &GUID_ContainerFormatPng, sizeof(GUID) ) == 0 ) { // Check for sRGB chunk if ( SUCCEEDED( metareader->GetMetadataByName( L"/sRGB/RenderingIntent", &value ) ) && value.vt == VT_UI1 ) { sRGB = true; } } else if ( SUCCEEDED( metareader->GetMetadataByName( L"System.Image.ColorSpace", &value ) ) && value.vt == VT_UI2 && value.uiVal == 1 ) { sRGB = true; } PropVariantClear( &value ); if ( sRGB ) format = MakeSRGB( format ); } } } // Verify our target format is supported by the current device // (handles WDDM 1.0 or WDDM 1.1 device driver cases as well as DirectX 11.0 Runtime without 16bpp format support) UINT support = 0; hr = d3dDevice->CheckFormatSupport( format, &support ); if ( FAILED(hr) || !(support & D3D11_FORMAT_SUPPORT_TEXTURE2D) ) { // Fallback to RGBA 32-bit format which is supported by all devices memcpy( &convertGUID, &GUID_WICPixelFormat32bppRGBA, sizeof(WICPixelFormatGUID) ); format = DXGI_FORMAT_R8G8B8A8_UNORM; bpp = 32; } // Allocate temporary memory for image size_t rowPitch = ( twidth * bpp + 7 ) / 8; size_t imageSize = rowPitch * theight; std::unique_ptr<uint8_t[]> temp( new (std::nothrow) uint8_t[ imageSize ] ); if (!temp) return E_OUTOFMEMORY; // Load image data if ( memcmp( &convertGUID, &pixelFormat, sizeof(GUID) ) == 0 && twidth == width && theight == height ) { // No format conversion or resize needed hr = frame->CopyPixels( 0, static_cast<UINT>( rowPitch ), static_cast<UINT>( imageSize ), temp.get() ); if ( FAILED(hr) ) return hr; } else if ( twidth != width || theight != height ) { // Resize IWICImagingFactory* pWIC = _GetWIC(); if ( !pWIC ) return E_NOINTERFACE; ScopedObject<IWICBitmapScaler> scaler; hr = pWIC->CreateBitmapScaler( &scaler ); if ( FAILED(hr) ) return hr; hr = scaler->Initialize( frame, twidth, theight, WICBitmapInterpolationModeFant ); if ( FAILED(hr) ) return hr; WICPixelFormatGUID pfScaler; hr = scaler->GetPixelFormat( &pfScaler ); if ( FAILED(hr) ) return hr; if ( memcmp( &convertGUID, &pfScaler, sizeof(GUID) ) == 0 ) { // No format conversion needed hr = scaler->CopyPixels( 0, static_cast<UINT>( rowPitch ), static_cast<UINT>( imageSize ), temp.get() ); if ( FAILED(hr) ) return hr; } else { ScopedObject<IWICFormatConverter> FC; hr = pWIC->CreateFormatConverter( &FC ); if ( FAILED(hr) ) return hr; hr = FC->Initialize( scaler.Get(), convertGUID, WICBitmapDitherTypeErrorDiffusion, 0, 0, WICBitmapPaletteTypeCustom ); if ( FAILED(hr) ) return hr; hr = FC->CopyPixels( 0, static_cast<UINT>( rowPitch ), static_cast<UINT>( imageSize ), temp.get() ); if ( FAILED(hr) ) return hr; } } else { // Format conversion but no resize IWICImagingFactory* pWIC = _GetWIC(); if ( !pWIC ) return E_NOINTERFACE; ScopedObject<IWICFormatConverter> FC; hr = pWIC->CreateFormatConverter( &FC ); if ( FAILED(hr) ) return hr; hr = FC->Initialize( frame, convertGUID, WICBitmapDitherTypeErrorDiffusion, 0, 0, WICBitmapPaletteTypeCustom ); if ( FAILED(hr) ) return hr; hr = FC->CopyPixels( 0, static_cast<UINT>( rowPitch ), static_cast<UINT>( imageSize ), temp.get() ); if ( FAILED(hr) ) return hr; } // See if format is supported for auto-gen mipmaps (varies by feature level) bool autogen = false; if ( d3dContext != 0 && textureView != 0 ) // Must have context and shader-view to auto generate mipmaps { UINT fmtSupport = 0; hr = d3dDevice->CheckFormatSupport( format, &fmtSupport ); if ( SUCCEEDED(hr) && ( fmtSupport & D3D11_FORMAT_SUPPORT_MIP_AUTOGEN ) ) { autogen = true; } } // Create texture D3D11_TEXTURE2D_DESC desc; desc.Width = twidth; desc.Height = theight; desc.MipLevels = (autogen) ? 0 : 1; desc.ArraySize = 1; desc.Format = format; desc.SampleDesc.Count = 1; desc.SampleDesc.Quality = 0; desc.Usage = usage; desc.CPUAccessFlags = cpuAccessFlags; if ( autogen ) { desc.BindFlags = bindFlags | D3D11_BIND_RENDER_TARGET; desc.MiscFlags = miscFlags | D3D11_RESOURCE_MISC_GENERATE_MIPS; } else { desc.BindFlags = bindFlags; desc.MiscFlags = miscFlags; } D3D11_SUBRESOURCE_DATA initData; initData.pSysMem = temp.get(); initData.SysMemPitch = static_cast<UINT>( rowPitch ); initData.SysMemSlicePitch = static_cast<UINT>( imageSize ); ID3D11Texture2D* tex = nullptr; hr = d3dDevice->CreateTexture2D( &desc, (autogen) ? nullptr : &initData, &tex ); if ( SUCCEEDED(hr) && tex != 0 ) { if (textureView != 0) { D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc; memset( &SRVDesc, 0, sizeof( SRVDesc ) ); SRVDesc.Format = desc.Format; SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; SRVDesc.Texture2D.MipLevels = (autogen) ? -1 : 1; hr = d3dDevice->CreateShaderResourceView( tex, &SRVDesc, textureView ); if ( FAILED(hr) ) { tex->Release(); return hr; } if ( autogen ) { assert( d3dContext != 0 ); d3dContext->UpdateSubresource( tex, 0, nullptr, temp.get(), static_cast<UINT>(rowPitch), static_cast<UINT>(imageSize) ); d3dContext->GenerateMips( *textureView ); } } if (texture != 0) { *texture = tex; } else { SetDebugObjectName(tex, "WICTextureLoader"); tex->Release(); } } return hr; }
static void test_CreateMessage(void) { HRESULT hr; IMimeMessage *msg; IStream *stream; LARGE_INTEGER pos; LONG ref; HBODY hbody; IMimeBody *body; BODYOFFSETS offsets; ULONG count; FINDBODY find_struct; HCHARSET hcs; char text[] = "text"; HBODY *body_list; PROPVARIANT prop; static const char att_pritype[] = "att:pri-content-type"; hr = MimeOleCreateMessage(NULL, &msg); ok(hr == S_OK, "ret %08x\n", hr); CreateStreamOnHGlobal(NULL, TRUE, &stream); IStream_Write(stream, msg1, sizeof(msg1) - 1, NULL); pos.QuadPart = 0; IStream_Seek(stream, pos, STREAM_SEEK_SET, NULL); hr = IMimeMessage_Load(msg, stream); ok(hr == S_OK, "ret %08x\n", hr); hr = IMimeMessage_CountBodies(msg, HBODY_ROOT, TRUE, &count); ok(hr == S_OK, "ret %08x\n", hr); ok(count == 3, "got %d\n", count); hr = IMimeMessage_CountBodies(msg, HBODY_ROOT, FALSE, &count); ok(hr == S_OK, "ret %08x\n", hr); ok(count == 3, "got %d\n", count); hr = IMimeMessage_BindToObject(msg, HBODY_ROOT, &IID_IMimeBody, (void**)&body); ok(hr == S_OK, "ret %08x\n", hr); hr = IMimeBody_GetOffsets(body, &offsets); ok(hr == S_OK, "ret %08x\n", hr); ok(offsets.cbBoundaryStart == 0, "got %d\n", offsets.cbBoundaryStart); ok(offsets.cbHeaderStart == 0, "got %d\n", offsets.cbHeaderStart); ok(offsets.cbBodyStart == 359, "got %d\n", offsets.cbBodyStart); ok(offsets.cbBodyEnd == 666, "got %d\n", offsets.cbBodyEnd); IMimeBody_Release(body); hr = IMimeMessage_GetBody(msg, IBL_ROOT, NULL, &hbody); ok(hr == S_OK, "ret %08x\n", hr); PropVariantInit(&prop); hr = IMimeMessage_GetBodyProp(msg, hbody, att_pritype, 0, &prop); ok(hr == S_OK, "ret %08x\n", hr); ok(prop.vt == VT_LPSTR, "vt %08x\n", prop.vt); ok(!strcasecmp(prop.u.pszVal, "multipart"), "got %s\n", prop.u.pszVal); PropVariantClear(&prop); hr = IMimeMessage_GetBody(msg, IBL_FIRST, hbody, &hbody); ok(hr == S_OK, "ret %08x\n", hr); hr = IMimeMessage_BindToObject(msg, hbody, &IID_IMimeBody, (void**)&body); ok(hr == S_OK, "ret %08x\n", hr); hr = IMimeBody_GetOffsets(body, &offsets); ok(hr == S_OK, "ret %08x\n", hr); ok(offsets.cbBoundaryStart == 405, "got %d\n", offsets.cbBoundaryStart); ok(offsets.cbHeaderStart == 428, "got %d\n", offsets.cbHeaderStart); ok(offsets.cbBodyStart == 518, "got %d\n", offsets.cbBodyStart); ok(offsets.cbBodyEnd == 523, "got %d\n", offsets.cbBodyEnd); hr = IMimeBody_GetCharset(body, &hcs); ok(hr == S_OK, "ret %08x\n", hr); todo_wine { ok(hcs != NULL, "Expected non-NULL charset\n"); } IMimeBody_Release(body); hr = IMimeMessage_GetBody(msg, IBL_NEXT, hbody, &hbody); ok(hr == S_OK, "ret %08x\n", hr); hr = IMimeMessage_BindToObject(msg, hbody, &IID_IMimeBody, (void**)&body); ok(hr == S_OK, "ret %08x\n", hr); hr = IMimeBody_GetOffsets(body, &offsets); ok(hr == S_OK, "ret %08x\n", hr); ok(offsets.cbBoundaryStart == 525, "got %d\n", offsets.cbBoundaryStart); ok(offsets.cbHeaderStart == 548, "got %d\n", offsets.cbHeaderStart); ok(offsets.cbBodyStart == 629, "got %d\n", offsets.cbBodyStart); ok(offsets.cbBodyEnd == 639, "got %d\n", offsets.cbBodyEnd); IMimeBody_Release(body); find_struct.pszPriType = text; find_struct.pszSubType = NULL; hr = IMimeMessage_FindFirst(msg, &find_struct, &hbody); ok(hr == S_OK, "ret %08x\n", hr); hr = IMimeMessage_FindNext(msg, &find_struct, &hbody); ok(hr == S_OK, "ret %08x\n", hr); hr = IMimeMessage_FindNext(msg, &find_struct, &hbody); ok(hr == MIME_E_NOT_FOUND, "ret %08x\n", hr); hr = IMimeMessage_GetAttachments(msg, &count, &body_list); ok(hr == S_OK, "ret %08x\n", hr); ok(count == 2, "got %d\n", count); CoTaskMemFree(body_list); hr = IMimeBody_GetCharset(body, &hcs); ok(hr == S_OK, "ret %08x\n", hr); todo_wine { ok(hcs != NULL, "Expected non-NULL charset\n"); } IMimeMessage_Release(msg); ref = IStream_AddRef(stream); ok(ref == 2 || broken(ref == 1), /* win95 */ "ref %d\n", ref); IStream_Release(stream); IStream_Release(stream); }
HRESULT ReadPropertyLong( IWiaPropertyStorage *pWiaPropertyStorage, const PROPSPEC *pPropSpec, LONG *plResult ) { PROPVARIANT PropVariant; HRESULT hr = pWiaPropertyStorage->ReadMultiple( 1, pPropSpec, &PropVariant ); // Generally, the return value should be checked against S_FALSE. // If ReadMultiple returns S_FALSE, it means the property name or ID // had valid syntax, but it didn't exist in this property set, so // no properties were retrieved, and each PROPVARIANT structure is set // to VT_EMPTY. But the following switch statement will handle this case // and return E_FAIL. So the caller of ReadPropertyLong does not need // to check for S_FALSE explicitly. if (SUCCEEDED(hr)) { switch (PropVariant.vt) { case VT_I1: { *plResult = (LONG) PropVariant.cVal; hr = S_OK; break; } case VT_UI1: { *plResult = (LONG) PropVariant.bVal; hr = S_OK; break; } case VT_I2: { *plResult = (LONG) PropVariant.iVal; hr = S_OK; break; } case VT_UI2: { *plResult = (LONG) PropVariant.uiVal; hr = S_OK; break; } case VT_I4: { *plResult = (LONG) PropVariant.lVal; hr = S_OK; break; } case VT_UI4: { *plResult = (LONG) PropVariant.ulVal; hr = S_OK; break; } case VT_INT: { *plResult = (LONG) PropVariant.intVal; hr = S_OK; break; } case VT_UINT: { *plResult = (LONG) PropVariant.uintVal; hr = S_OK; break; } case VT_R4: { *plResult = (LONG) (PropVariant.fltVal + 0.5); hr = S_OK; break; } case VT_R8: { *plResult = (LONG) (PropVariant.dblVal + 0.5); hr = S_OK; break; } default: { hr = E_FAIL; break; } } } PropVariantClear(&PropVariant); return hr; }
static void test_ReadAndWriteProperties(void) { HRESULT hr; IUniformResourceLocatorA *urlA; IUniformResourceLocatorA *urlAFromFile; WCHAR fileNameW[MAX_PATH]; static const WCHAR shortcutW[] = {'t','e','s','t','s','h','o','r','t','c','u','t','.','u','r','l',0}; WCHAR iconPath[] = {'f','i','l','e',':','/','/','/','C',':','/','a','r','b','i','t','r','a','r','y','/','i','c','o','n','/','p','a','t','h',0}; int iconIndex = 7; char testurl[] = "http://some/bogus/url.html"; PROPSPEC ps[2]; ps[0].ulKind = PRSPEC_PROPID; U(ps[0]).propid = PID_IS_ICONFILE; ps[1].ulKind = PRSPEC_PROPID; U(ps[1]).propid = PID_IS_ICONINDEX; /* Make sure we have a valid temporary directory */ GetTempPathW(MAX_PATH, fileNameW); lstrcatW(fileNameW, shortcutW); hr = CoCreateInstance(&CLSID_InternetShortcut, NULL, CLSCTX_ALL, &IID_IUniformResourceLocatorA, (void**)&urlA); if (hr == S_OK) { IPersistFile *pf; IPropertyStorage *pPropStgWrite; IPropertySetStorage *pPropSetStg; PROPVARIANT pv[2]; /* We need to set a URL -- IPersistFile refuses to save without one. */ hr = urlA->lpVtbl->SetURL(urlA, testurl, 0); ok(hr == S_OK, "Failed to set a URL. hr=0x%x\n", hr); /* Write this shortcut out to a file so that we can test reading it in again. */ hr = urlA->lpVtbl->QueryInterface(urlA, &IID_IPersistFile, (void **) &pf); ok(hr == S_OK, "Failed to get the IPersistFile for writing. hr=0x%x\n", hr); hr = IPersistFile_Save(pf, fileNameW, TRUE); ok(hr == S_OK, "Failed to save via IPersistFile. hr=0x%x\n", hr); IPersistFile_Release(pf); pv[0].vt = VT_LPWSTR; U(pv[0]).pwszVal = (void *) iconPath; pv[1].vt = VT_I4; U(pv[1]).iVal = iconIndex; hr = urlA->lpVtbl->QueryInterface(urlA, &IID_IPropertySetStorage, (void **) &pPropSetStg); ok(hr == S_OK, "Unable to get an IPropertySetStorage, hr=0x%x\n", hr); hr = IPropertySetStorage_Open(pPropSetStg, &FMTID_Intshcut, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, &pPropStgWrite); ok(hr == S_OK, "Unable to get an IPropertyStorage for writing, hr=0x%x\n", hr); hr = IPropertyStorage_WriteMultiple(pPropStgWrite, 2, ps, pv, 0); ok(hr == S_OK, "Unable to set properties, hr=0x%x\n", hr); hr = IPropertyStorage_Commit(pPropStgWrite, STGC_DEFAULT); ok(hr == S_OK, "Failed to commit properties, hr=0x%x\n", hr); pPropStgWrite->lpVtbl->Release(pPropStgWrite); urlA->lpVtbl->Release(urlA); IPropertySetStorage_Release(pPropSetStg); } else skip("could not create a CLSID_InternetShortcut for property tests, hr=0x%x\n", hr); hr = CoCreateInstance(&CLSID_InternetShortcut, NULL, CLSCTX_ALL, &IID_IUniformResourceLocatorA, (void**)&urlAFromFile); if (hr == S_OK) { IPropertySetStorage *pPropSetStg; IPropertyStorage *pPropStgRead; PROPVARIANT pvread[2]; IPersistFile *pf; LPSTR url = NULL; /* Now read that .url file back in. */ hr = urlAFromFile->lpVtbl->QueryInterface(urlAFromFile, &IID_IPersistFile, (void **) &pf); ok(hr == S_OK, "Failed to get the IPersistFile for reading. hr=0x%x\n", hr); hr = IPersistFile_Load(pf, fileNameW, 0); ok(hr == S_OK, "Failed to load via IPersistFile. hr=0x%x\n", hr); IPersistFile_Release(pf); hr = urlAFromFile->lpVtbl->GetURL(urlAFromFile, &url); ok(hr == S_OK, "Unable to get url from file, hr=0x%x\n", hr); ok(lstrcmp(url, testurl) == 0, "Wrong url read from file: %s\n",url); hr = urlAFromFile->lpVtbl->QueryInterface(urlAFromFile, &IID_IPropertySetStorage, (void **) &pPropSetStg); ok(hr == S_OK, "Unable to get an IPropertySetStorage, hr=0x%x\n", hr); hr = IPropertySetStorage_Open(pPropSetStg, &FMTID_Intshcut, STGM_READ | STGM_SHARE_EXCLUSIVE, &pPropStgRead); ok(hr == S_OK, "Unable to get an IPropertyStorage for reading, hr=0x%x\n", hr); hr = IPropertyStorage_ReadMultiple(pPropStgRead, 2, ps, pvread); ok(hr == S_OK, "Unable to read properties, hr=0x%x\n", hr); todo_wine /* Wine doesn't yet support setting properties after save */ { ok(U(pvread[1]).iVal == iconIndex, "Read wrong icon index: %d\n", U(pvread[1]).iVal); ok(lstrcmpW(U(pvread[0]).pwszVal, iconPath) == 0, "Wrong icon path read: %s\n", wine_dbgstr_w(U(pvread[0]).pwszVal)); } PropVariantClear(&pvread[0]); PropVariantClear(&pvread[1]); IPropertyStorage_Release(pPropStgRead); IPropertySetStorage_Release(pPropSetStg); urlAFromFile->lpVtbl->Release(urlAFromFile); DeleteFileW(fileNameW); }
void Parse_MTP::mtp_get_metadata(PCWSTR object_id, IPortableDeviceContent *pdc, bool clear) { IPortableDeviceValues *pdv; IPortableDeviceKeyCollection *pdkc; IPortableDeviceProperties *pdp = NULL; HRESULT hr; scrob_entry new_entry; LPWSTR album = NULL; LPWSTR artist = NULL; LPWSTR name = NULL; ULONG usecount; ULONG skipcount; ULONG tracknum; ULONGLONG duration; PROPVARIANT date; new_entry.length = 0; hr = CoCreateInstance(CLSID_PortableDeviceValues, NULL, CLSCTX_INPROC_SERVER, IID_IPortableDeviceValues, (VOID**)&pdv); if (FAILED(hr)) { emit add_log(LOG_ERROR, QString("mtp_get_metadata: Failed to create IPortableDeviceValues: %1") .arg(hr, 0, 16)); return; } hr = CoCreateInstance(CLSID_PortableDeviceKeyCollection, NULL, CLSCTX_INPROC_SERVER, IID_IPortableDeviceKeyCollection, (VOID**)&pdkc); if (FAILED(hr)) { emit add_log(LOG_ERROR, QString("mtp_get_metadata: Failed to create IPortableDeviceKeyCollection: %1") .arg(hr, 0, 16)); return; } hr = pdc->Properties(&pdp); if (FAILED(hr)) { emit add_log(LOG_ERROR, QString("mtp_get_metadata: Failed to get properties from IPortableDeviceContent: %1") .arg(hr, 0, 16)); goto mtp_get_metadata_cleanup; } hr = pdkc->Add(WPD_MEDIA_USE_COUNT); //VT_UI4 hr = pdkc->Add(WPD_MEDIA_SKIP_COUNT); //VT_UI4 hr = pdkc->Add(WPD_MEDIA_LAST_ACCESSED_TIME); //VT_DATE hr = pdkc->Add(WPD_MUSIC_ALBUM); //VT_LPWSTR hr = pdkc->Add(WPD_MUSIC_TRACK); //VT_UI4 hr = pdkc->Add(WPD_MEDIA_DURATION); //VT_UI8, in milliseconds hr = pdkc->Add(WPD_OBJECT_NAME); //VT_LPWSTR hr = pdkc->Add(WPD_MEDIA_ARTIST); //VT_LPWSTR if (FAILED(hr)) { emit add_log(LOG_ERROR, QString("mtp_get_metadata: Failed to add to IPortableDeviceKeyCollection: %1") .arg(hr, 0, 16)); goto mtp_get_metadata_cleanup; } hr = pdp->GetValues(object_id, pdkc, &pdv); if (FAILED(hr)) { emit add_log(LOG_ERROR, QString("mtp_get_metadata: Failed to get values from IPortableDeviceProperties: %1") .arg(hr, 0, 16)); goto mtp_get_metadata_cleanup; } hr = pdv->GetStringValue(WPD_MUSIC_ALBUM, &album); if (SUCCEEDED(hr)) new_entry.album = QString::fromStdWString(album); hr = pdv->GetStringValue(WPD_MEDIA_ARTIST, &artist); if (SUCCEEDED(hr)) new_entry.artist = QString::fromStdWString(artist); hr = pdv->GetStringValue(WPD_OBJECT_NAME, &name); if (SUCCEEDED(hr)) new_entry.title = QString::fromStdWString(name); hr = pdv->GetUnsignedIntegerValue(WPD_MEDIA_USE_COUNT, &usecount); hr = pdv->GetUnsignedIntegerValue(WPD_MEDIA_SKIP_COUNT, &skipcount); hr = pdv->GetUnsignedIntegerValue(WPD_MUSIC_TRACK, &tracknum); if (SUCCEEDED(hr)) new_entry.tracknum = tracknum; hr = pdv->GetUnsignedLargeIntegerValue(WPD_MEDIA_DURATION, &duration); if (SUCCEEDED(hr)) new_entry.length = duration/1000; hr = pdv->GetValue(WPD_MEDIA_LAST_ACCESSED_TIME, &date); if (SUCCEEDED(hr)) { SYSTEMTIME st; VariantTimeToSystemTime(date.date, &st); PropVariantClear(&date); QDate d = QDate(st.wYear, st.wMonth, st.wDay); QTime t = QTime(st.wHour, st.wMinute, st.wSecond); new_entry.when = QDateTime(d, t).toTime_t() - tz_offset; // Not all MTP devices provide a valid result for // WPD_MEDIA_LAST_ACCESSED_TIME, so sanity check it // are we within (+/-) 30 days? long offset = new_entry.when - QDateTime::currentDateTime().toTime_t(); if (abs(offset) > 2592000) new_entry.when = 0; } emit add_log(LOG_TRACE, QString("%1 : %2 : %3 : %4 : %5 : %6 : %7") .arg(new_entry.artist) .arg(new_entry.title) .arg(new_entry.album) .arg(new_entry.tracknum) .arg(new_entry.length) .arg(usecount) .arg(skipcount) ); tracks++; if (usecount > 0 && new_entry.artist.length() && new_entry.title.length()) { if (clear) { IPortableDeviceValues *pdv_clear = NULL; hr = pdv->Clear(); hr = pdv->SetUnsignedIntegerValue(WPD_MEDIA_USE_COUNT, 0); hr = pdp->SetValues(object_id, pdv, &pdv_clear); if (SUCCEEDED(hr)) { if (pdv_clear != NULL) pdv_clear->Clear(); pdv_clear = NULL; } } else { playcounts++; new_entry.played = 'L'; for (ULONG i = 0; i < usecount; i++) { entries++; // Only use the last playcount for one instance // we'll recalc the rest afterwards // via Scrobble::check_timestamps() if (i > 1) new_entry.when = 0; emit entry(new_entry); } } } mtp_get_metadata_cleanup: if (album) CoTaskMemFree(album); if (artist) CoTaskMemFree(artist); if (name) CoTaskMemFree(name); if (pdp) { pdp->Release(); pdp = NULL; } if (pdv) { pdv->Release(); pdv = NULL; } }
HRESULT WIACamera::DigitalCameraCapture(IWiaItem* pIWiaRoot, IplImage** ppIplImage) { HRESULT hr = S_OK; IWiaItem* pIWiaItem = NULL; hr = pIWiaRoot->DeviceCommand( 0, &WIA_CMD_TAKE_PICTURE, &pIWiaItem ); if (pIWiaItem==NULL) { cvReleaseImage(ppIplImage); (*ppIplImage) = NULL; return hr; } IStream **ppStream = NULL; LONG lCount = 0; // Create the data callback interface CDataCallback *pDataCallback = new CDataCallback( &lCount,&ppStream ); if (pDataCallback == NULL) { return E_OUTOFMEMORY; } { // Get the interface pointers IWiaPropertyStorage *pWiaPropertyStorage; hr = pIWiaItem->QueryInterface(IID_IWiaPropertyStorage,(void**)&pWiaPropertyStorage); if (hr != S_OK) { return E_NOINTERFACE; } IWiaDataTransfer *pIWiaDataTransfer; hr = pIWiaItem->QueryInterface(IID_IWiaDataTransfer, (void**)&pIWiaDataTransfer); if (hr != S_OK) { return E_NOINTERFACE; } // Set the transfer type PROPSPEC specTymed; specTymed.ulKind = PRSPEC_PROPID; specTymed.propid = WIA_IPA_TYMED; PROPVARIANT varTymed; varTymed.vt = VT_I4; varTymed.lVal = TYMED_CALLBACK; hr = pWiaPropertyStorage->WriteMultiple(1, &specTymed, &varTymed, WIA_IPA_FIRST ); PropVariantClear(&varTymed); if (FAILED(hr)) { return hr; } // If there is no transfer format specified, use the device default GUID guidFormat = GUID_NULL; GUID *pguidFormat = &guidFormat; PROPSPEC specPreferredFormat; specPreferredFormat.ulKind = PRSPEC_PROPID; specPreferredFormat.propid = WIA_IPA_PREFERRED_FORMAT; hr = ReadPropertyGuid( pWiaPropertyStorage, &specPreferredFormat, pguidFormat ); if (FAILED(hr)) { return hr; } // Set the transfer format PROPSPEC specFormat; PROPVARIANT varFormat; specFormat.ulKind = PRSPEC_PROPID; specFormat.propid = WIA_IPA_FORMAT; varFormat.vt = VT_CLSID; varFormat.puuid = (CLSID *) CoTaskMemAlloc(sizeof(CLSID)); if (varFormat.puuid == NULL) { return E_OUTOFMEMORY; } *varFormat.puuid = *pguidFormat; hr = pWiaPropertyStorage->WriteMultiple( 1, &specFormat, &varFormat, WIA_IPA_FIRST ); PropVariantClear(&varFormat); if (FAILED(hr)) { return hr; } // Read the transfer buffer size from the device, default to 64K PROPSPEC specBufferSize; specBufferSize.ulKind = PRSPEC_PROPID; specBufferSize.propid = WIA_IPA_BUFFER_SIZE; LONG nBufferSize; hr = ReadPropertyLong( pWiaPropertyStorage, &specBufferSize, &nBufferSize ); if (FAILED(hr)) { nBufferSize = 64 * 1024; } // Choose double buffered transfer for better performance WIA_DATA_TRANSFER_INFO WiaDataTransferInfo = { 0 }; WiaDataTransferInfo.ulSize = sizeof(WIA_DATA_TRANSFER_INFO); WiaDataTransferInfo.ulBufferSize = 2 * nBufferSize; WiaDataTransferInfo.bDoubleBuffer = TRUE; // Start the transfer hr = pIWiaDataTransfer->idtGetBandedData( &WiaDataTransferInfo, pDataCallback ); if (pWiaPropertyStorage) { pWiaPropertyStorage->Release(); pWiaPropertyStorage = NULL; } if (pIWiaDataTransfer) { pIWiaDataTransfer->Release(); pIWiaDataTransfer = NULL; } } if (pIWiaItem) { // Delete file from DigitalCamera storage pIWiaItem->DeleteItem(0); pIWiaItem->Release(); pIWiaItem = NULL; } if (lCount!=1) throw "Error.\n"; if ( SUCCEEDED(hr) ) { Gdiplus::Bitmap myBmp(ppStream[0]); int Width = myBmp.GetWidth(); int Height = myBmp.GetHeight(); Gdiplus::Rect rect(0, 0, Width, Height); Gdiplus::BitmapData myBitmapData; Gdiplus::Status res = myBmp.LockBits( &rect, Gdiplus::ImageLockModeRead, PixelFormat24bppRGB, &myBitmapData ); if ( (*ppIplImage)==NULL ) { (*ppIplImage) = cvCreateImage(cvSize(Width,Height),IPL_DEPTH_8U,3); } else { CvSize oldSize = cvGetSize((*ppIplImage)); if ( oldSize.width!=Width || oldSize.height!=Height ) { throw "Warning.\n"; cvReleaseImage(&(*ppIplImage)); (*ppIplImage) = cvCreateImage(cvSize(Width,Height),IPL_DEPTH_8U,3); } } unsigned char *pIplData = (unsigned char*)(*ppIplImage)->imageData; for ( int h=0; h < Height; h++) { unsigned char *pIplLine = &pIplData[(*ppIplImage)->widthStep*h]; unsigned char *pBitmapLine = &((unsigned char*)myBitmapData.Scan0)[myBitmapData.Stride*h]; memcpy( pIplLine, pBitmapLine, sizeof(unsigned char)*Width*3 ); /* for ( int w=0; w < Width; w++) { pIplLine[w*3+0] = pBitmapLine[w*3+2]; pIplLine[w*3+1] = pBitmapLine[w*3+1]; pIplLine[w*3+2] = pBitmapLine[w*3+0]; } */ } } else { delete (*ppIplImage); (*ppIplImage) = NULL; } ppStream[0]->Release(); return hr; }
//</SnippetListSupportedFormats1> //<SnippetListSupportedEvents1> // List all supported events on the service void ListSupportedEvents( _In_ IPortableDeviceService* service) { ComPtr<IPortableDeviceServiceCapabilities> capabilities; ComPtr<IPortableDevicePropVariantCollection> events; DWORD numEvents = 0; // Get an IPortableDeviceServiceCapabilities interface from the IPortableDeviceService interface to // access the service capabilities-specific methods. HRESULT hr = service->Capabilities(&capabilities); if (FAILED(hr)) { wprintf(L"! Failed to get IPortableDeviceServiceCapabilities from IPortableDeviceService, hr = 0x%lx\n", hr); } // Get all events supported by the service. if (SUCCEEDED(hr)) { hr = capabilities->GetSupportedEvents(&events); if (FAILED(hr)) { wprintf(L"! Failed to get supported events from the service, hr = 0x%lx\n", hr); } } // Get the number of supported events found on the service. if (SUCCEEDED(hr)) { hr = events->GetCount(&numEvents); if (FAILED(hr)) { wprintf(L"! Failed to get number of supported events, hr = 0x%lx\n", hr); } } // Loop through each event and display it if (SUCCEEDED(hr)) { wprintf(L"\n%u Supported Events Found on the service\n\n", numEvents); for (DWORD index = 0; index < numEvents; index++) { PROPVARIANT event = {0}; hr = events->GetAt(index, &event); if (SUCCEEDED(hr)) { // We have an event. It is assumed that // events are returned as VT_CLSID VarTypes. if (event.vt == VT_CLSID && event.puuid != nullptr) { DisplayEvent(capabilities.Get(), *event.puuid); wprintf(L"\n"); } } PropVariantClear(&event); } } }
void DirectShowMetaDataControl::updateMetadata(IFilterGraph2 *graph, IBaseFilter *source, const QString &fileSrc) { m_metadata.clear(); #ifndef QT_NO_SHELLITEM if (!sHCreateItemFromParsingName) { QSystemLibrary lib(QStringLiteral("shell32")); sHCreateItemFromParsingName = (q_SHCreateItemFromParsingName)(lib.resolve("SHCreateItemFromParsingName")); } if (!fileSrc.isEmpty() && sHCreateItemFromParsingName) { IShellItem2* shellItem = 0; if (sHCreateItemFromParsingName(reinterpret_cast<const WCHAR*>(fileSrc.utf16()), 0, IID_PPV_ARGS(&shellItem)) == S_OK) { IPropertyStore *pStore = 0; if (shellItem->GetPropertyStore(GPS_DEFAULT, IID_PPV_ARGS(&pStore)) == S_OK) { DWORD cProps; if (SUCCEEDED(pStore->GetCount(&cProps))) { for (DWORD i = 0; i < cProps; ++i) { PROPERTYKEY key; PROPVARIANT var; PropVariantInit(&var); if (FAILED(pStore->GetAt(i, &key))) continue; if (FAILED(pStore->GetValue(key, &var))) continue; if (IsEqualPropertyKey(key, PKEY_Author)) { m_metadata.insert(QMediaMetaData::Author, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Title)) { m_metadata.insert(QMediaMetaData::Title, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Media_SubTitle)) { m_metadata.insert(QMediaMetaData::SubTitle, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_ParentalRating)) { m_metadata.insert(QMediaMetaData::ParentalRating, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Comment)) { m_metadata.insert(QMediaMetaData::Description, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Copyright)) { m_metadata.insert(QMediaMetaData::Copyright, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Media_ProviderStyle)) { m_metadata.insert(QMediaMetaData::Genre, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Media_Year)) { m_metadata.insert(QMediaMetaData::Year, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Media_DateEncoded)) { m_metadata.insert(QMediaMetaData::Date, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Rating)) { m_metadata.insert(QMediaMetaData::UserRating, int((convertValue(var).toUInt() - 1) / qreal(98) * 100)); } else if (IsEqualPropertyKey(key, PKEY_Keywords)) { m_metadata.insert(QMediaMetaData::Keywords, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Language)) { m_metadata.insert(QMediaMetaData::Language, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Media_Publisher)) { m_metadata.insert(QMediaMetaData::Publisher, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Media_Duration)) { m_metadata.insert(QMediaMetaData::Duration, (convertValue(var).toLongLong() + 10000) / 10000); } else if (IsEqualPropertyKey(key, PKEY_Audio_EncodingBitrate)) { m_metadata.insert(QMediaMetaData::AudioBitRate, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Media_AverageLevel)) { m_metadata.insert(QMediaMetaData::AverageLevel, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Audio_ChannelCount)) { m_metadata.insert(QMediaMetaData::ChannelCount, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Audio_PeakValue)) { m_metadata.insert(QMediaMetaData::PeakValue, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Audio_SampleRate)) { m_metadata.insert(QMediaMetaData::SampleRate, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Music_AlbumTitle)) { m_metadata.insert(QMediaMetaData::AlbumTitle, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Music_AlbumArtist)) { m_metadata.insert(QMediaMetaData::AlbumArtist, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Music_Artist)) { m_metadata.insert(QMediaMetaData::ContributingArtist, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Music_Composer)) { m_metadata.insert(QMediaMetaData::Composer, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Music_Conductor)) { m_metadata.insert(QMediaMetaData::Conductor, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Music_Lyrics)) { m_metadata.insert(QMediaMetaData::Lyrics, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Music_Mood)) { m_metadata.insert(QMediaMetaData::Mood, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Music_TrackNumber)) { m_metadata.insert(QMediaMetaData::TrackNumber, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Music_Genre)) { m_metadata.insert(QMediaMetaData::Genre, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_ThumbnailStream)) { m_metadata.insert(QMediaMetaData::ThumbnailImage, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Video_FrameHeight)) { QSize res; res.setHeight(convertValue(var).toUInt()); if (SUCCEEDED(pStore->GetValue(PKEY_Video_FrameWidth, &var))) res.setWidth(convertValue(var).toUInt()); m_metadata.insert(QMediaMetaData::Resolution, res); } else if (IsEqualPropertyKey(key, PKEY_Video_HorizontalAspectRatio)) { QSize aspectRatio; aspectRatio.setWidth(convertValue(var).toUInt()); if (SUCCEEDED(pStore->GetValue(PKEY_Video_VerticalAspectRatio, &var))) aspectRatio.setHeight(convertValue(var).toUInt()); m_metadata.insert(QMediaMetaData::PixelAspectRatio, aspectRatio); } else if (IsEqualPropertyKey(key, PKEY_Video_FrameRate)) { m_metadata.insert(QMediaMetaData::VideoFrameRate, convertValue(var).toReal() / 1000); } else if (IsEqualPropertyKey(key, PKEY_Video_EncodingBitrate)) { m_metadata.insert(QMediaMetaData::VideoBitRate, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Video_Director)) { m_metadata.insert(QMediaMetaData::Director, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Media_Writer)) { m_metadata.insert(QMediaMetaData::Writer, convertValue(var)); } PropVariantClear(&var); } } pStore->Release(); } shellItem->Release(); } } if (!m_metadata.isEmpty()) goto send_event; #endif #ifndef QT_NO_WMSDK IWMHeaderInfo *info = com_cast<IWMHeaderInfo>(source, IID_IWMHeaderInfo); if (info) { Q_FOREACH (const QWMMetaDataKey &key, *qt_wmMetaDataKeys()) { QVariant var = getValue(info, key.wmName); if (var.isValid()) { if (key.qtName == QMediaMetaData::Duration) { // duration is provided in 100-nanosecond units, convert to milliseconds var = (var.toLongLong() + 10000) / 10000; } else if (key.qtName == QMediaMetaData::Resolution) { QSize res; res.setHeight(var.toUInt()); res.setWidth(getValue(info, L"WM/VideoWidth").toUInt()); var = res; } else if (key.qtName == QMediaMetaData::VideoFrameRate) { var = var.toReal() / 1000.f; } else if (key.qtName == QMediaMetaData::PixelAspectRatio) { QSize aspectRatio; aspectRatio.setWidth(var.toUInt()); aspectRatio.setHeight(getValue(info, L"AspectRatioY").toUInt()); var = aspectRatio; } else if (key.qtName == QMediaMetaData::UserRating) { var = (var.toUInt() - 1) / qreal(98) * 100; } m_metadata.insert(key.qtName, var); } } info->Release(); } if (!m_metadata.isEmpty()) goto send_event; #endif { IAMMediaContent *content = 0; if ((!graph || graph->QueryInterface( IID_IAMMediaContent, reinterpret_cast<void **>(&content)) != S_OK) && (!source || source->QueryInterface( IID_IAMMediaContent, reinterpret_cast<void **>(&content)) != S_OK)) { content = 0; } if (content) { BSTR string = 0; if (content->get_AuthorName(&string) == S_OK) m_metadata.insert(QMediaMetaData::Author, convertBSTR(&string)); if (content->get_Title(&string) == S_OK) m_metadata.insert(QMediaMetaData::Title, convertBSTR(&string)); if (content->get_Description(&string) == S_OK) m_metadata.insert(QMediaMetaData::Description, convertBSTR(&string)); if (content->get_Rating(&string) == S_OK) m_metadata.insert(QMediaMetaData::UserRating, convertBSTR(&string)); if (content->get_Copyright(&string) == S_OK) m_metadata.insert(QMediaMetaData::Copyright, convertBSTR(&string)); content->Release(); } } send_event: // DirectShowMediaPlayerService holds a lock at this point so defer emitting signals to a later // time. QCoreApplication::postEvent(this, new QEvent(QEvent::Type(MetaDataChanged))); }
void CAESinkDirectSound::EnumerateDevicesEx(AEDeviceInfoList &deviceInfoList) { CAEDeviceInfo deviceInfo; IMMDeviceEnumerator* pEnumerator = NULL; IMMDeviceCollection* pEnumDevices = NULL; WAVEFORMATEX* pwfxex = NULL; HRESULT hr; /* See if we are on Windows XP */ if (!g_sysinfo.IsVistaOrHigher()) { /* We are on XP - WASAPI not supported - enumerate using DS devices */ LPGUID deviceGUID = NULL; RPC_CSTR cszGUID; std::string szGUID; std::list<DSDevice> DSDeviceList; DirectSoundEnumerate(DSEnumCallback, &DSDeviceList); for(std::list<DSDevice>::iterator itt = DSDeviceList.begin(); itt != DSDeviceList.end(); itt++) { if (UuidToString((*itt).lpGuid, &cszGUID) != RPC_S_OK) continue; /* could not convert GUID to string - skip device */ deviceInfo.m_channels.Reset(); deviceInfo.m_dataFormats.clear(); deviceInfo.m_sampleRates.clear(); szGUID = (LPSTR)cszGUID; deviceInfo.m_deviceName = "{" + szGUID + "}"; deviceInfo.m_displayName = (*itt).name; deviceInfo.m_displayNameExtra = std::string("DirectSound: ") + (*itt).name; deviceInfo.m_deviceType = AE_DEVTYPE_PCM; deviceInfo.m_channels = layoutsByChCount[2]; deviceInfo.m_dataFormats.push_back(AEDataFormat(AE_FMT_FLOAT)); deviceInfo.m_dataFormats.push_back(AEDataFormat(AE_FMT_AC3)); deviceInfo.m_sampleRates.push_back((DWORD) 96000); deviceInfoList.push_back(deviceInfo); } RpcStringFree(&cszGUID); return; } /* Windows Vista or later - supporting WASAPI device probing */ hr = CoCreateInstance(CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, IID_IMMDeviceEnumerator, (void**)&pEnumerator); EXIT_ON_FAILURE(hr, __FUNCTION__": Could not allocate WASAPI device enumerator. CoCreateInstance error code: %li", hr) UINT uiCount = 0; hr = pEnumerator->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, &pEnumDevices); EXIT_ON_FAILURE(hr, __FUNCTION__": Retrieval of audio endpoint enumeration failed.") hr = pEnumDevices->GetCount(&uiCount); EXIT_ON_FAILURE(hr, __FUNCTION__": Retrieval of audio endpoint count failed.") for (UINT i = 0; i < uiCount; i++) { IMMDevice *pDevice = NULL; IPropertyStore *pProperty = NULL; PROPVARIANT varName; PropVariantInit(&varName); deviceInfo.m_channels.Reset(); deviceInfo.m_dataFormats.clear(); deviceInfo.m_sampleRates.clear(); hr = pEnumDevices->Item(i, &pDevice); if (FAILED(hr)) { CLog::Log(LOGERROR, __FUNCTION__": Retrieval of DirectSound endpoint failed."); goto failed; } hr = pDevice->OpenPropertyStore(STGM_READ, &pProperty); if (FAILED(hr)) { CLog::Log(LOGERROR, __FUNCTION__": Retrieval of DirectSound endpoint properties failed."); SAFE_RELEASE(pDevice); goto failed; } hr = pProperty->GetValue(PKEY_Device_FriendlyName, &varName); if (FAILED(hr)) { CLog::Log(LOGERROR, __FUNCTION__": Retrieval of DirectSound endpoint device name failed."); SAFE_RELEASE(pDevice); SAFE_RELEASE(pProperty); goto failed; } std::wstring strRawFriendlyName(varName.pwszVal); std::string strFriendlyName = std::string(strRawFriendlyName.begin(), strRawFriendlyName.end()); PropVariantClear(&varName); hr = pProperty->GetValue(PKEY_AudioEndpoint_GUID, &varName); if (FAILED(hr)) { CLog::Log(LOGERROR, __FUNCTION__": Retrieval of DirectSound endpoint GUID failed."); SAFE_RELEASE(pDevice); SAFE_RELEASE(pProperty); goto failed; } std::wstring strRawDevName(varName.pwszVal); std::string strDevName = std::string(strRawDevName.begin(), strRawDevName.end()); PropVariantClear(&varName); hr = pProperty->GetValue(PKEY_AudioEndpoint_FormFactor, &varName); if (FAILED(hr)) { CLog::Log(LOGERROR, __FUNCTION__": Retrieval of DirectSound endpoint form factor failed."); SAFE_RELEASE(pDevice); SAFE_RELEASE(pProperty); goto failed; } std::string strWinDevType = winEndpoints[(EndpointFormFactor)varName.uiVal].winEndpointType; AEDeviceType aeDeviceType = winEndpoints[(EndpointFormFactor)varName.uiVal].aeDeviceType; PropVariantClear(&varName); /* In shared mode Windows tells us what format the audio must be in. */ IAudioClient *pClient; hr = pDevice->Activate(IID_IAudioClient, CLSCTX_ALL, NULL, (void**)&pClient); if (FAILED(hr)) { CLog::Log(LOGERROR, __FUNCTION__": Activate device failed (%s)", WASAPIErrToStr(hr)); } //hr = pClient->GetMixFormat(&pwfxex); hr = pProperty->GetValue(PKEY_AudioEngine_DeviceFormat, &varName); if (SUCCEEDED(hr) && varName.blob.cbSize > 0) { WAVEFORMATEX* smpwfxex = (WAVEFORMATEX*)varName.blob.pBlobData; deviceInfo.m_channels = layoutsByChCount[std::min(smpwfxex->nChannels, (WORD) 2)]; deviceInfo.m_dataFormats.push_back(AEDataFormat(AE_FMT_FLOAT)); deviceInfo.m_dataFormats.push_back(AEDataFormat(AE_FMT_AC3)); deviceInfo.m_sampleRates.push_back(std::min(smpwfxex->nSamplesPerSec, (DWORD) 96000)); } else { CLog::Log(LOGERROR, __FUNCTION__": Getting DeviceFormat failed (%s)", WASAPIErrToStr(hr)); } pClient->Release(); SAFE_RELEASE(pDevice); SAFE_RELEASE(pProperty); deviceInfo.m_deviceName = strDevName; deviceInfo.m_displayName = strWinDevType.append(strFriendlyName); deviceInfo.m_displayNameExtra = std::string("DirectSound: ").append(strFriendlyName); deviceInfo.m_deviceType = aeDeviceType; /* Now logged by AESinkFactory on startup */ //CLog::Log(LOGDEBUG,"Audio Device %d: %s", i, ((std::string)deviceInfo).c_str()); deviceInfoList.push_back(deviceInfo); } return; failed: if (FAILED(hr)) CLog::Log(LOGERROR, __FUNCTION__": Failed to enumerate WASAPI endpoint devices (%s).", WASAPIErrToStr(hr)); SAFE_RELEASE(pEnumDevices); SAFE_RELEASE(pEnumerator); }
int wf_wasapi_get_device_string(LPWSTR pattern, LPWSTR * deviceStr) { HRESULT hr; IMMDeviceEnumerator *pEnumerator = NULL; IMMDeviceCollection *pCollection = NULL; IMMDevice *pEndpoint = NULL; IPropertyStore *pProps = NULL; LPWSTR pwszID = NULL; unsigned int count, i; CoInitialize(NULL); hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, &IID_IMMDeviceEnumerator, (void **) &pEnumerator); if (FAILED(hr)) { _tprintf(_T("Failed to cocreate device enumerator\n")); exit(1); } hr = pEnumerator->lpVtbl->EnumAudioEndpoints(pEnumerator, eCapture, DEVICE_STATE_ACTIVE, &pCollection); if ( FAILED(hr) ) { _tprintf(_T("Failed to create endpoint collection\n")); exit(1); } pCollection->lpVtbl->GetCount(pCollection, &count); _tprintf(_T("Num endpoints: %d\n"), count); if (count == 0) { _tprintf(_T("No endpoints!\n")); exit(1); } for (i = 0; i < count; ++i) { PROPVARIANT nameVar; PropVariantInit(&nameVar); hr = pCollection->lpVtbl->Item(pCollection, i, &pEndpoint); if ( FAILED(hr) ) { _tprintf(_T("Failed to get endpoint %d\n"), i); exit(1); } hr = pEndpoint->lpVtbl->GetId(pEndpoint, &pwszID); if ( FAILED(hr) ) { _tprintf(_T("Failed to get endpoint ID\n")); exit(1); } hr = pEndpoint->lpVtbl->OpenPropertyStore(pEndpoint, STGM_READ, &pProps); if ( FAILED(hr) ) { _tprintf(_T("Failed to open property store\n")); exit(1); } hr = pProps->lpVtbl->GetValue(pProps, &PKEY_Device_FriendlyName, &nameVar); if ( FAILED(hr) ) { _tprintf(_T("Failed to get device friendly name\n")); exit(1); } //do this a more reliable way if (wcscmp(pattern, nameVar.pwszVal) < 0) { unsigned int devStrLen; _tprintf(_T("Using sound ouput endpoint: [%s] (%s)\n"), nameVar.pwszVal, pwszID); //_tprintf(_T("matched %d characters\n"), wcscmp(pattern, nameVar.pwszVal)); devStrLen = wcslen(pwszID); *deviceStr = (LPWSTR) malloc((devStrLen * 2) + 2); ZeroMemory(*deviceStr, (devStrLen * 2) + 2); wcscpy_s(*deviceStr, devStrLen+1, pwszID); } CoTaskMemFree(pwszID); pwszID = NULL; PropVariantClear(&nameVar); pProps->lpVtbl->Release(pProps); pProps = NULL; pEndpoint->lpVtbl->Release(pEndpoint); pEndpoint = NULL; } pCollection->lpVtbl->Release(pCollection); pCollection = NULL; pEnumerator->lpVtbl->Release(pEnumerator); pEnumerator = NULL; CoUninitialize(); return 0; }