HRESULT WalkTreeFromPart( IPart *pPart, EDataFlow eDirection, bool bFollowConnector, int iTabLevel /* = 0 */ ) { HRESULT hr = S_OK; UINT nId = 0; hr = pPart->GetLocalId(&nId); if (FAILED(hr)) { LOG(L"Could not get part id: hr = 0x%08x", hr); return hr; } LPWSTR pwszPartName = NULL; hr = pPart->GetName(&pwszPartName); if (FAILED(hr)) { LOG(L"Could not get part name: hr = 0x%08x", hr); return hr; } CoTaskMemFreeOnExit freeName(pwszPartName); Tab(iTabLevel); LOG(L"0x%x: %s", nId, pwszPartName); // see if this is a volume node part IAudioVolumeLevel *pVolume = NULL; hr = pPart->Activate(CLSCTX_ALL, __uuidof(IAudioVolumeLevel), (void**)&pVolume); if (E_NOINTERFACE == hr) { // not a volume node } else if (FAILED(hr)) { LOG(L"Unexpected failure trying to activate IAudioVolumeLevel: hr = 0x%08x", hr); return hr; } else { // it's a volume node... ReleaseOnExit releaseVolume(pVolume); hr = DisplayVolume(pVolume, iTabLevel); if (FAILED(hr)) { LOG(L"DisplayVolume failed: hr = 0x%08x", hr); return hr; } } // see if this is a mute node part IAudioMute *pMute = NULL; hr = pPart->Activate(CLSCTX_ALL, __uuidof(IAudioMute), (void**)&pMute); if (E_NOINTERFACE == hr) { // not a mute node } else if (FAILED(hr)) { LOG(L"Unexpected failure trying to activate IAudioMute: hr = 0x%08x", hr); return hr; } else { // it's a mute node... ReleaseOnExit releaseMute(pMute); hr = DisplayMute(pMute, iTabLevel); if (FAILED(hr)) { LOG(L"DisplayMute failed: hr = 0x%08x", hr); return hr; } } // see if this is a jack description part IKsJackDescription *pKsJackDescription = NULL; hr = pPart->Activate(CLSCTX_ALL, __uuidof(IKsJackDescription), (void**)&pKsJackDescription); if (E_NOINTERFACE == hr) { // not a jack description part } else if (FAILED(hr)) { LOG(L"Unexpected failure trying to activate IKsJackDescription: hr = 0x%08x", hr); return hr; } else { // it's a mute node... ReleaseOnExit releaseJackDescription(pKsJackDescription); hr = DisplayKsJackDescription(pKsJackDescription, iTabLevel); if (FAILED(hr)) { LOG(L"DisplayKsJackDescription failed: hr = 0x%08x", hr); return hr; } } // get the list of incoming or outgoing parts, according to the direction IPartsList *pParts = NULL; hr = ( eRender == eDirection ? pPart->EnumPartsIncoming(&pParts) : pPart->EnumPartsOutgoing(&pParts) ); if (E_NOTFOUND == hr) { // not an error... we've just reached the end of the path } else if (FAILED(hr)) { LOG(L"Couldn't enum next parts: hr = 0x%08x", hr); return hr; } else { ReleaseOnExit releaseOnExit(pParts); UINT nParts = 0; hr = pParts->GetCount(&nParts); if (FAILED(hr)) { LOG(L"Couldn't get count of incoming parts: hr = 0x%08x", hr); return hr; } // walk the tree on each incoming/outgoing part recursively for (UINT n = 0; n < nParts; n++) { IPart *pNextPart = NULL; hr = pParts->GetPart(n, &pNextPart); if (FAILED(hr)) { LOG(L"Couldn't get part #%u (0-based) of %u (1-based:) hr = 0x%08x", n, nParts, hr); return hr; } ReleaseOnExit releaseNextPart(pNextPart); // if the incoming/outgoing part is a connector, follow it hr = WalkTreeFromPart(pNextPart, eDirection, true, iTabLevel + 1); if (FAILED(hr)) { LOG(L"Couldn't walk tree on part #%u (0-based) of %u (1-based:) hr = 0x%08x", n, nParts, hr); return hr; } } } if (bFollowConnector) { // if this part is a connector, do the connector dance IConnector *pConnHere = NULL; hr = pPart->QueryInterface(IID_PPV_ARGS(&pConnHere)); if (E_NOINTERFACE == hr) { // that's fine } else if (FAILED(hr)) { LOG(L"Unexpected failure getting the connector on the endpoint: hr = 0x%08x", hr); return hr; } else { ReleaseOnExit releaseConnHere(pConnHere); // get the connector on the other side IConnector *pConnOtherSide = NULL; hr = pConnHere->GetConnectedTo(&pConnOtherSide); if (E_NOTFOUND == hr) { // that's fine, it just isn't connected to anything } else if (FAILED(hr)) { LOG(L"Couldn't get the connector on the upstream device: hr = 0x%08x", hr); return __LINE__; } else { ReleaseOnExit releaseConnOtherSide(pConnOtherSide); // QI on the device's connector for IPart IPart *pPartOtherSide = NULL; hr = pConnOtherSide->QueryInterface(IID_PPV_ARGS(&pPartOtherSide)); if (FAILED(hr)) { LOG(L"Couldn't get the part on the other side: hr = 0x%08x", hr); return __LINE__; } ReleaseOnExit releasePartOtherSide(pPartOtherSide); // get the device topology interface for the other side IDeviceTopology *pDTOtherSide = NULL; hr = pPartOtherSide->GetTopologyObject(&pDTOtherSide); if (FAILED(hr)) { LOG(L"Couldn't get the other side's device topology: hr = 0x%08x", hr); return __LINE__; } ReleaseOnExit releaseDTOtherSide(pDTOtherSide); // get the device name for the other side LPWSTR pwszDeviceName = NULL; hr = pDTOtherSide->GetDeviceId(&pwszDeviceName); if (FAILED(hr)) { LOG(L"Could not get device name: hr = 0x%08x", hr); return hr; } CoTaskMemFreeOnExit freeDeviceName(pwszDeviceName); Tab(iTabLevel); LOG(L"%s", pwszDeviceName); // walk the other side's tree // but don't follow the connector back to here hr = WalkTreeFromPart(pPartOtherSide, eDirection, false, iTabLevel + 1); if (FAILED(hr)) { LOG(L"Couldn't walk the tree: hr = 0x%08x", hr); return __LINE__; } } } } return S_OK; }
int _tmain(int argc, _TCHAR* argv[]) { try { require( argc == 3, USAGE ); require( fileExists( argv[1] ), "File not found" ); require( fileExists( argv[2] ), "File not found" ); TCOMIXMLDOMDocument3 xml = Msxml2_tlb::CoDOMDocument60::Create(); TCOMIXMLDOMDocument3 xsl = Msxml2_tlb::CoDOMDocument60::Create(); xsl->resolveExternals = VARIANT_TRUE; load( xml, argv[1] ); load( xsl, argv[2] ); BSTR result = NULL; Msxml2_tlb::IXMLDOMNodePtr pXSLDOM = xsl->documentElement; HRESULT hr = xml->transformNode( pXSLDOM, &result ); if (FAILED(hr)) { WideString errMsg = L"Failure code obtained from transformNode. "; // Try to get extended error info... IErrorInfo* errorInfo = NULL; if ( SUCCEEDED( GetErrorInfo( 0, &errorInfo ) ) ) { boost::shared_ptr<void> releaseOnExit( errorInfo, release ); BSTR reason = NULL; if ( SUCCEEDED( errorInfo->GetDescription( &reason ) ) ) { boost::shared_ptr<void> freeStringOnExit( reason, freeString ); if ( reason ) { errMsg += WideString(reason); } } } throw Exception( UnicodeString( errMsg ) ); } boost::shared_ptr<void> freeStringOnExit( result, freeString ); WideString ws(result); std::wcout << (wchar_t*)ws; return 0; } catch( Exception& e ) { printError( e.Message ); } catch( const std::exception& e ) { printError( e.what() ); } catch( ... ) { printError( "Unspecified exception" ); } return 1; }