/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS BDA Proxy * FILE: dll/directx/bdaplgin/devicecontrol.cpp * PURPOSE: ClassFactory interface * * PROGRAMMERS: Johannes Anderwald (johannes.anderwald@reactos.org) */ #include "precomp.h" const GUID IID_IKsObject = {0x423c13a2, 0x2070, 0x11d0, {0x9e, 0xf7, 0x00, 0xaa, 0x00, 0xa2, 0x16, 0xa1}}; #ifndef _MSC_VER const GUID CLSID_DVBTNetworkProvider = {0x216c62df, 0x6d7f, 0x4e9a, {0x85, 0x71, 0x5, 0xf1, 0x4e, 0xdb, 0x76, 0x6a}}; const GUID KSPROPSETID_BdaTopology = {0xa14ee835, 0x0a23, 0x11d3, {0x9c, 0xc7, 0x0, 0xc0, 0x4f, 0x79, 0x71, 0xe0}}; const GUID KSMETHODSETID_BdaDeviceConfiguration = {0x71985f45, 0x1ca1, 0x11d3, {0x9c, 0xc8, 0x0, 0xc0, 0x4f, 0x79, 0x71, 0xe0}}; const GUID KSMETHODSETID_BdaChangeSync = {0xfd0a5af3, 0xb41d, 0x11d2, {0x9c, 0x95, 0x0, 0xc0, 0x4f, 0x79, 0x71, 0xe0}}; const GUID IID_IBaseFilter = {0x56a86895, 0x0ad4, 0x11ce, {0xb0,0x3a, 0x00,0x20,0xaf,0x0b,0xa7,0x70}}; const GUID IID_IAsyncReader = {0x56A868AA, 0x0AD4, 0x11CE, {0xB0, 0x3A, 0x00, 0x20, 0xAF, 0x0B, 0xA7, 0x70}}; const GUID IID_IAMOpenProgress = {0x8E1C39A1, 0xDE53, 0x11cf, {0xAA, 0x63, 0x00, 0x80, 0xC7, 0x44, 0x52, 0x8D}}; const GUID IID_IBDA_Topology = {0x79B56888, 0x7FEA, 0x4690, {0xB4, 0x5D, 0x38, 0xFD, 0x3C, 0x78, 0x49, 0xBE}}; const GUID IID_IBDA_NetworkProvider = {0xfd501041, 0x8ebe, 0x11ce, {0x81, 0x83, 0x00, 0xaa, 0x00, 0x57, 0x7d, 0xa2}}; const GUID IID_IBDA_DeviceControl = {0xFD0A5AF3, 0xB41D, 0x11d2, {0x9C, 0x95, 0x00, 0xC0, 0x4F, 0x79, 0x71, 0xE0}}; const GUID IID_IDistributorNotify = {0x56a868af, 0x0ad4, 0x11ce, {0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}}; #endif class CBDADeviceControl : public IBDA_DeviceControl, public IBDA_Topology { public: STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface); STDMETHODIMP_(ULONG) AddRef() { InterlockedIncrement(&m_Ref); return m_Ref; } STDMETHODIMP_(ULONG) Release() { InterlockedDecrement(&m_Ref); if (!m_Ref) { delete this; return 0; } return m_Ref; } // IBDA_DeviceControl methods HRESULT STDMETHODCALLTYPE StartChanges( void); HRESULT STDMETHODCALLTYPE CheckChanges( void); HRESULT STDMETHODCALLTYPE CommitChanges( void); HRESULT STDMETHODCALLTYPE GetChangeState(ULONG *pState); // IBDA_Topology methods HRESULT STDMETHODCALLTYPE GetNodeTypes(ULONG *pulcNodeTypes, ULONG ulcNodeTypesMax, ULONG * rgulNodeTypes); HRESULT STDMETHODCALLTYPE GetNodeDescriptors(ULONG *ulcNodeDescriptors, ULONG ulcNodeDescriptorsMax, BDANODE_DESCRIPTOR * rgNodeDescriptors); HRESULT STDMETHODCALLTYPE GetNodeInterfaces(ULONG ulNodeType, ULONG *pulcInterfaces, ULONG ulcInterfacesMax, GUID * rgguidInterfaces); HRESULT STDMETHODCALLTYPE GetPinTypes(ULONG *pulcPinTypes, ULONG ulcPinTypesMax, ULONG *rgulPinTypes); HRESULT STDMETHODCALLTYPE GetTemplateConnections(ULONG *pulcConnections, ULONG ulcConnectionsMax, BDA_TEMPLATE_CONNECTION * rgConnections); HRESULT STDMETHODCALLTYPE CreatePin(ULONG ulPinType, ULONG *pulPinId); HRESULT STDMETHODCALLTYPE DeletePin(ULONG ulPinId); HRESULT STDMETHODCALLTYPE SetMediaType(ULONG ulPinId, AM_MEDIA_TYPE *pMediaType); HRESULT STDMETHODCALLTYPE SetMedium(ULONG ulPinId, REGPINMEDIUM *pMedium); HRESULT STDMETHODCALLTYPE CreateTopology(ULONG ulInputPinId, ULONG ulOutputPinId); HRESULT STDMETHODCALLTYPE GetControlNode(ULONG ulInputPinId, ULONG ulOutputPinId, ULONG ulNodeType, IUnknown **ppControlNode); CBDADeviceControl(IUnknown * pUnkOuter, IBaseFilter *pFilter, HANDLE hFile) : m_Ref(0), m_pUnkOuter(pUnkOuter), m_Handle(hFile), m_pFilter(pFilter){}; virtual ~CBDADeviceControl(){}; protected: LONG m_Ref; IUnknown * m_pUnkOuter; HANDLE m_Handle; IBaseFilter * m_pFilter; }; HRESULT STDMETHODCALLTYPE CBDADeviceControl::QueryInterface( IN REFIID refiid, OUT PVOID* Output) { *Output = NULL; if (IsEqualGUID(refiid, IID_IUnknown)) { *Output = PVOID(this); reinterpret_cast(*Output)->AddRef(); return NOERROR; } if (IsEqualGUID(refiid, IID_IBDA_DeviceControl)) { *Output = (IBDA_DeviceControl*)(this); reinterpret_cast(*Output)->AddRef(); return NOERROR; } if (IsEqualGUID(refiid, IID_IBDA_Topology)) { *Output = (IBDA_Topology*)(this); reinterpret_cast(*Output)->AddRef(); return NOERROR; } return E_NOINTERFACE; } //------------------------------------------------------------------- // IBDA_DeviceControl methods // HRESULT STDMETHODCALLTYPE CBDADeviceControl::StartChanges( void) { KSMETHOD Method; HRESULT hr; ULONG BytesReturned; /* setup request */ Method.Set = KSMETHODSETID_BdaChangeSync; Method.Id = KSMETHOD_BDA_START_CHANGES; Method.Flags = KSMETHOD_TYPE_NONE; /* execute request */ hr = KsSynchronousDeviceControl(m_Handle, IOCTL_KS_METHOD, (PVOID)&Method, sizeof(KSMETHOD), NULL, 0, &BytesReturned); #ifdef BDAPLGIN_TRACE WCHAR Buffer[100]; swprintf(Buffer, L"CBDADeviceControl::StartChanges: hr %lx, BytesReturned %lu\n", hr, BytesReturned); OutputDebugStringW(Buffer); #endif return hr; } HRESULT STDMETHODCALLTYPE CBDADeviceControl::CheckChanges( void) { KSMETHOD Method; HRESULT hr; ULONG BytesReturned; /* setup request */ Method.Set = KSMETHODSETID_BdaChangeSync; Method.Id = KSMETHOD_BDA_CHECK_CHANGES; Method.Flags = KSMETHOD_TYPE_NONE; /* execute request */ hr = KsSynchronousDeviceControl(m_Handle, IOCTL_KS_METHOD, (PVOID)&Method, sizeof(KSMETHOD), NULL, 0, &BytesReturned); #ifdef BDAPLGIN_TRACE WCHAR Buffer[100]; swprintf(Buffer, L"CBDADeviceControl::CheckChanges: hr %lx, BytesReturned %lu\n", hr, BytesReturned); OutputDebugStringW(Buffer); #endif return hr; } HRESULT STDMETHODCALLTYPE CBDADeviceControl::CommitChanges( void) { KSMETHOD Method; HRESULT hr; ULONG BytesReturned; /* setup request */ Method.Set = KSMETHODSETID_BdaChangeSync; Method.Id = KSMETHOD_BDA_COMMIT_CHANGES; Method.Flags = KSMETHOD_TYPE_NONE; /* execute request */ hr = KsSynchronousDeviceControl(m_Handle, IOCTL_KS_METHOD, (PVOID)&Method, sizeof(KSMETHOD), NULL, 0, &BytesReturned); #ifdef BDAPLGIN_TRACE WCHAR Buffer[100]; swprintf(Buffer, L"CBDADeviceControl::CommitChanges: hr %lx, BytesReturned %lu\n", hr, BytesReturned); OutputDebugStringW(Buffer); #endif return hr; } HRESULT STDMETHODCALLTYPE CBDADeviceControl::GetChangeState(ULONG *pState) { if (pState) { *pState = BDA_CHANGES_COMPLETE; return S_OK; } else { return E_POINTER; } } //------------------------------------------------------------------- // IBDA_Topology methods // HRESULT STDMETHODCALLTYPE CBDADeviceControl::GetNodeTypes(ULONG *pulcNodeTypes, ULONG ulcNodeTypesMax, ULONG * rgulNodeTypes) { KSPROPERTY Property; HRESULT hr; ULONG BytesReturned; // setup request Property.Set = KSPROPSETID_BdaTopology; Property.Id = KSPROPERTY_BDA_NODE_TYPES; Property.Flags = KSPROPERTY_TYPE_GET; // perform request hr = KsSynchronousDeviceControl(m_Handle, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), rgulNodeTypes, sizeof(ULONG) * ulcNodeTypesMax, &BytesReturned); *pulcNodeTypes = (BytesReturned / sizeof(ULONG)); #ifdef BDAPLGIN_TRACE WCHAR Buffer[100]; swprintf(Buffer, L"CBDADeviceControl::GetNodeTypes: hr %lx, BytesReturned %lu\n", hr, BytesReturned); OutputDebugStringW(Buffer); if (SUCCEEDED(hr)) { for(ULONG Index = 0; Index < *pulcNodeTypes; Index++) { swprintf(Buffer, L"CBDADeviceControl::GetPinTypes: Index %lu Value %lx\n", Index, rgulNodeTypes[Index]); OutputDebugStringW(Buffer); } } #endif return hr; } HRESULT STDMETHODCALLTYPE CBDADeviceControl::GetNodeDescriptors(ULONG *ulcNodeDescriptors, ULONG ulcNodeDescriptorsMax, BDANODE_DESCRIPTOR * rgNodeDescriptors) { KSPROPERTY Property; HRESULT hr; ULONG BytesReturned; // setup request Property.Set = KSPROPSETID_BdaTopology; Property.Id = KSPROPERTY_BDA_NODE_DESCRIPTORS; Property.Flags = KSPROPERTY_TYPE_GET; // perform request hr = KsSynchronousDeviceControl(m_Handle, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), rgNodeDescriptors, sizeof(BDANODE_DESCRIPTOR) * ulcNodeDescriptorsMax, &BytesReturned); *ulcNodeDescriptors = (BytesReturned / sizeof(BDANODE_DESCRIPTOR)); #ifdef BDAPLGIN_TRACE WCHAR Buffer[1000]; swprintf(Buffer, L"CBDADeviceControl::GetNodeDescriptors: hr %lx, BytesReturned %lu\n", hr, BytesReturned); OutputDebugStringW(Buffer); if (SUCCEEDED(hr)) { for(ULONG Index = 0; Index < min(*ulcNodeDescriptors, ulcNodeDescriptorsMax); Index++) { LPOLESTR pGUIDFunction, pGUIDName; StringFromCLSID(rgNodeDescriptors[Index].guidFunction, &pGUIDFunction); StringFromCLSID(rgNodeDescriptors[Index].guidName, &pGUIDName); swprintf(Buffer, L"CBDADeviceControl::GetPinTypes: Index %lu Value %lx\nFunction %s\n Name %s\n-----\n", Index, rgNodeDescriptors[Index].ulBdaNodeType, pGUIDFunction, pGUIDName); OutputDebugStringW(Buffer); } } #endif return hr; } HRESULT STDMETHODCALLTYPE CBDADeviceControl::GetNodeInterfaces(ULONG ulNodeType, ULONG *pulcInterfaces, ULONG ulcInterfacesMax, GUID * rgguidInterfaces) { KSP_NODE Property; HRESULT hr; ULONG BytesReturned; // setup request Property.Property.Set = KSPROPSETID_BdaTopology; Property.Property.Id = KSPROPERTY_BDA_NODE_PROPERTIES; Property.Property.Flags = KSPROPERTY_TYPE_GET; Property.NodeId = ulNodeType; Property.Reserved = 0; // perform request hr = KsSynchronousDeviceControl(m_Handle, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSP_NODE), rgguidInterfaces, sizeof(GUID) * ulcInterfacesMax, &BytesReturned); *pulcInterfaces = (BytesReturned / sizeof(GUID)); #ifdef BDAPLGIN_TRACE WCHAR Buffer[100]; swprintf(Buffer, L"CBDADeviceControl::GetNodeInterfaces: hr %lx, BytesReturned %lu ulNodeType %lu\n", hr, BytesReturned, ulNodeType); OutputDebugStringW(Buffer); if (SUCCEEDED(hr)) { for(ULONG Index = 0; Index < min(*pulcInterfaces, ulcInterfacesMax); Index++) { LPOLESTR pstr; StringFromCLSID(rgguidInterfaces[Index], &pstr); swprintf(Buffer, L"CBDADeviceControl::GetNodeInterfaces: Index %lu Name %s\n", Index, pstr); OutputDebugStringW(Buffer); } } #endif return hr; } HRESULT STDMETHODCALLTYPE CBDADeviceControl::GetPinTypes(ULONG *pulcPinTypes, ULONG ulcPinTypesMax, ULONG *rgulPinTypes) { KSPROPERTY Property; HRESULT hr; ULONG BytesReturned; // setup request Property.Set = KSPROPSETID_BdaTopology; Property.Id = KSPROPERTY_BDA_PIN_TYPES; Property.Flags = KSPROPERTY_TYPE_GET; // perform request hr = KsSynchronousDeviceControl(m_Handle, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), rgulPinTypes, sizeof(ULONG) * ulcPinTypesMax, &BytesReturned); *pulcPinTypes = (BytesReturned / sizeof(ULONG)); #ifdef BDAPLGIN_TRACE WCHAR Buffer[100]; swprintf(Buffer, L"CBDADeviceControl::GetPinTypes: hr %lx, BytesReturned %lu\n", hr, BytesReturned); OutputDebugStringW(Buffer); if (SUCCEEDED(hr)) { for(ULONG Index = 0; Index < *pulcPinTypes; Index++) { swprintf(Buffer, L"CBDADeviceControl::GetPinTypes: Index %lu Value %lx\n", Index, rgulPinTypes[Index]); OutputDebugStringW(Buffer); } } #endif return hr; } HRESULT STDMETHODCALLTYPE CBDADeviceControl::GetTemplateConnections(ULONG *pulcConnections, ULONG ulcConnectionsMax, BDA_TEMPLATE_CONNECTION * rgConnections) { #ifdef BDAPLGIN_TRACE OutputDebugStringW(L"CBDADeviceControl::GetTemplateConnections: NotImplemented\n"); #endif return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE CBDADeviceControl::CreatePin(ULONG ulPinType, ULONG *pulPinId) { #ifdef BDAPLGIN_TRACE OutputDebugStringW(L"CBDADeviceControl::CreatePin: NotImplemented\n"); #endif return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE CBDADeviceControl::DeletePin(ULONG ulPinId) { #ifdef BDAPLGIN_TRACE OutputDebugStringW(L"CBDADeviceControl::DeletePin: NotImplemented\n"); #endif return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE CBDADeviceControl::SetMediaType(ULONG ulPinId, AM_MEDIA_TYPE *pMediaType) { #ifdef BDAPLGIN_TRACE OutputDebugStringW(L"CBDADeviceControl::SetMediaType: NotImplemented\n"); #endif return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE CBDADeviceControl::SetMedium(ULONG ulPinId, REGPINMEDIUM *pMedium) { #ifdef BDAPLGIN_TRACE OutputDebugStringW(L"CBDADeviceControl::SetMedium: NotImplemented\n"); #endif return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE CBDADeviceControl::CreateTopology(ULONG ulInputPinId, ULONG ulOutputPinId) { KSM_BDA_PIN_PAIR Method; HRESULT hr; ULONG BytesReturned = 0; Method.Method.Flags = KSMETHOD_TYPE_NONE; Method.Method.Id = KSMETHOD_BDA_CREATE_TOPOLOGY; Method.Method.Set = KSMETHODSETID_BdaDeviceConfiguration; Method.InputPinId = ulInputPinId; Method.OutputPinId = ulOutputPinId; hr = KsSynchronousDeviceControl(m_Handle, IOCTL_KS_METHOD, (PVOID)&Method, sizeof(KSM_BDA_PIN_PAIR), NULL, 0, &BytesReturned); #ifdef BDAPLGIN_TRACE WCHAR Buffer[100]; swprintf(Buffer, L"CBDADeviceControl::CreateTopology: hr %lx, BytesReturned %lu\n", hr, BytesReturned); OutputDebugStringW(Buffer); #endif return hr; } HRESULT STDMETHODCALLTYPE CBDADeviceControl::GetControlNode(ULONG ulInputPinId, ULONG ulOutputPinId, ULONG ulNodeType, IUnknown **ppControlNode) { HRESULT hr; ULONG PinId = 0; ULONG BytesReturned; KSP_BDA_NODE_PIN Property; //setup request Property.Property.Set = KSPROPSETID_BdaTopology; Property.Property.Id = KSPROPERTY_BDA_CONTROLLING_PIN_ID; Property.Property.Flags = KSPROPERTY_TYPE_GET; Property.ulInputPinId = ulInputPinId; Property.ulOutputPinId = ulOutputPinId; Property.ulNodeType = ulNodeType; // perform request // WinXP SP3 expects minimum sizeof(KSP_BDA_NODE_PIN) + sizeof(ULONG) // seems a driver to be a driver bug hr = KsSynchronousDeviceControl(m_Handle, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSP_BDA_NODE_PIN) + sizeof(ULONG), &PinId, sizeof(ULONG), &BytesReturned); #ifdef BDAPLGIN_TRACE WCHAR Buffer[200]; swprintf(Buffer, L"CBDADeviceControl::GetControlNode: hr %lx, BytesReturned %lu PinId %lu ulInputPinId %lu ulOutputPinId %lu ulNodeType %lu\n", hr, BytesReturned, PinId, ulInputPinId, ulOutputPinId, ulNodeType); OutputDebugStringW(Buffer); #endif if (FAILED(hr)) return hr; hr = CControlNode_fnConstructor(m_pFilter, ulNodeType, PinId, IID_IUnknown, (LPVOID*)ppControlNode); #ifdef BDAPLGIN_TRACE swprintf(Buffer, L"CBDADeviceControl::GetControlNode: hr %lx\n", hr); OutputDebugStringW(Buffer); #endif return hr; } HRESULT WINAPI CBDADeviceControl_fnConstructor( IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv) { HRESULT hr; IKsObject *pObject = NULL; IBaseFilter *pFilter = NULL; HANDLE hFile; #ifdef BDAPLGIN_TRACE OutputDebugStringW(L"CBDADeviceControl_fnConstructor\n"); #endif //DebugBreak(); // sanity check assert(pUnkOuter); // query for IKsObject hr = pUnkOuter->QueryInterface(IID_IKsObject, (void**)&pObject); if (FAILED(hr)) return E_NOINTERFACE; // sanity check assert(hr == NOERROR); // query for IBaseFilter interface support hr = pUnkOuter->QueryInterface(IID_IBaseFilter, (void**)&pFilter); if (FAILED(hr)) { // release pObject->Release(); return E_NOINTERFACE; } // another sanity check assert(pObject != NULL); // get file handle hFile = pObject->KsGetObjectHandle(); // one more sanity check assert(hFile != NULL && hFile != INVALID_HANDLE_VALUE); // release IKsObject interface pObject->Release(); // release filter pFilter->Release(); // construct device control CBDADeviceControl * handler = new CBDADeviceControl(pUnkOuter, pFilter, hFile); if (!handler) return E_OUTOFMEMORY; if (FAILED(handler->QueryInterface(riid, ppv))) { /* not supported */ delete handler; return E_NOINTERFACE; } return NOERROR; }