xref: /reactos/dll/directx/bdaplgin/pincontrol.cpp (revision c2c66aff)
1 /*
2  * COPYRIGHT:       See COPYING in the top level directory
3  * PROJECT:         ReactOS BDA Proxy
4  * FILE:            dll/directx/bdaplgin/pincontrol.cpp
5  * PURPOSE:         ClassFactory interface
6  *
7  * PROGRAMMERS:     Johannes Anderwald (johannes.anderwald@reactos.org)
8  */
9 
10 #include "precomp.h"
11 
12 #ifndef _MSC_VER
13 const GUID KSPROPSETID_BdaPinControl = {0x0ded49d5, 0xa8b7, 0x4d5d, {0x97, 0xa1, 0x12, 0xb0, 0xc1, 0x95, 0x87, 0x4d}};
14 const GUID IID_IBDA_PinControl       = {0x0DED49D5, 0xA8B7, 0x4d5d, {0x97, 0xA1, 0x12, 0xB0, 0xC1, 0x95, 0x87, 0x4D}};
15 const GUID IID_IPin = {0x56a86891, 0x0ad4, 0x11ce, {0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}};
16 #endif
17 
18 
19 class CBDAPinControl : public IBDA_PinControl
20 {
21 public:
22     STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
23 
24     STDMETHODIMP_(ULONG) AddRef()
25     {
26         InterlockedIncrement(&m_Ref);
27         return m_Ref;
28     }
29     STDMETHODIMP_(ULONG) Release()
30     {
31         InterlockedDecrement(&m_Ref);
32         if (!m_Ref)
33         {
34             delete this;
35             return 0;
36         }
37         return m_Ref;
38     }
39     // IBDA_PinControl methods
40     HRESULT STDMETHODCALLTYPE GetPinID(ULONG *pulPinID);
41     HRESULT STDMETHODCALLTYPE GetPinType(ULONG *pulPinType);
42     HRESULT STDMETHODCALLTYPE RegistrationContext(ULONG *pulRegistrationCtx);
43 
44 
45     CBDAPinControl(HANDLE hFile, IBDA_NetworkProvider * pProvider, IPin * pConnectedPin, ULONG RegistrationCtx) : m_Ref(0), m_Handle(hFile), m_pProvider(pProvider), m_pConnectedPin(pConnectedPin), m_RegistrationCtx(RegistrationCtx){};
46     virtual ~CBDAPinControl()
47     {
48         //m_pConnectedPin->Release();
49         //m_pProvider->Release();
50     };
51 
52 protected:
53     LONG m_Ref;
54     HANDLE m_Handle;
55     IBDA_NetworkProvider * m_pProvider;
56     IPin * m_pConnectedPin;
57     ULONG m_RegistrationCtx;
58 };
59 
60 HRESULT
61 STDMETHODCALLTYPE
62 CBDAPinControl::QueryInterface(
63     IN  REFIID refiid,
64     OUT PVOID* Output)
65 {
66     *Output = NULL;
67     if (IsEqualGUID(refiid, IID_IUnknown))
68     {
69         *Output = PVOID(this);
70         reinterpret_cast<IUnknown*>(*Output)->AddRef();
71         return NOERROR;
72     }
73     if (IsEqualGUID(refiid, IID_IBDA_PinControl))
74     {
75         *Output = (IBDA_PinControl*)(this);
76         reinterpret_cast<IBDA_PinControl*>(*Output)->AddRef();
77         return NOERROR;
78     }
79 DebugBreak();
80     return E_NOINTERFACE;
81 }
82 //-------------------------------------------------------------------
83 // IBDA_PinControl methods
84 //
85 HRESULT
86 STDMETHODCALLTYPE
87 CBDAPinControl::GetPinID(ULONG *pulPinID)
88 {
89     KSPROPERTY Property;
90     ULONG BytesReturned;
91     HRESULT hr;
92 
93     // setup request
94     Property.Set = KSPROPSETID_BdaPinControl;
95     Property.Id = KSPROPERTY_BDA_PIN_ID;
96     Property.Flags = KSPROPERTY_TYPE_GET;
97 
98     // perform request
99     hr = KsSynchronousDeviceControl(m_Handle, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), pulPinID, sizeof(ULONG), &BytesReturned);
100 
101 #ifdef BDAPLGIN_TRACE
102     WCHAR Buffer[100];
103     swprintf(Buffer, L"CBDAPinControl::GetPinID: hr %lx pulPinID %lu BytesReturned %lx\n", hr, *pulPinID, BytesReturned);
104     OutputDebugStringW(Buffer);
105 #endif
106 
107     return hr;
108 }
109 
110 HRESULT
111 STDMETHODCALLTYPE
112 CBDAPinControl::GetPinType(ULONG *pulPinType)
113 {
114     KSPROPERTY Property;
115     ULONG BytesReturned;
116     HRESULT hr;
117 
118     // setup request
119     Property.Set = KSPROPSETID_BdaPinControl;
120     Property.Id = KSPROPERTY_BDA_PIN_TYPE;
121     Property.Flags = KSPROPERTY_TYPE_GET;
122 
123     // perform request
124     hr = KsSynchronousDeviceControl(m_Handle, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), pulPinType, sizeof(ULONG), &BytesReturned);
125 
126 #ifdef BDAPLGIN_TRACE
127     WCHAR Buffer[100];
128     swprintf(Buffer, L"CBDAPinControl::GetPinType: hr %lx pulPinType %lu BytesReturned %lx\n", hr, *pulPinType, BytesReturned);
129     OutputDebugStringW(Buffer);
130 #endif
131 
132     return hr;
133 }
134 
135 HRESULT
136 STDMETHODCALLTYPE
137 CBDAPinControl::RegistrationContext(ULONG *pulRegistrationCtx)
138 {
139 #ifdef BDAPLGIN_TRACE
140     OutputDebugStringW(L"CBDAPinControl::RegistrationContext\n");
141 #endif
142 
143     if (!pulRegistrationCtx)
144     {
145         // invalid argument
146         return E_POINTER;
147     }
148 
149     if (m_RegistrationCtx)
150     {
151         // is registered
152         *pulRegistrationCtx = m_RegistrationCtx;
153         return NOERROR;
154     }
155 
156     //pin not registered
157     return E_FAIL;
158 }
159 
160 //-------------------------------------------------------------------
161 HRESULT
162 GetNetworkProviderFromGraph(
163     IFilterGraph * pGraph,
164     IBDA_NetworkProvider ** pOutNetworkProvider)
165 {
166     IEnumFilters *pEnumFilters = NULL;
167     IBaseFilter * ppFilter[1];
168     IBDA_NetworkProvider * pNetworkProvider = NULL;
169     HRESULT hr;
170 
171     // get IEnumFilters interface
172     hr = pGraph->EnumFilters(&pEnumFilters);
173 
174     if (FAILED(hr))
175     {
176         //clean up
177         *pOutNetworkProvider = NULL;
178         return hr;
179     }
180 
181     while(pEnumFilters->Next(1, ppFilter, NULL) == S_OK)
182     {
183         // check if that filter supports the IBDA_NetworkProvider interface
184         hr = ppFilter[0]->QueryInterface(IID_IBDA_NetworkProvider, (void**)&pNetworkProvider);
185 
186         // release IBaseFilter
187         ppFilter[0]->Release();
188 
189         if (SUCCEEDED(hr))
190             break;
191     }
192 
193     // release IEnumFilters interface
194     pEnumFilters->Release();
195 
196     //store result
197     *pOutNetworkProvider = pNetworkProvider;
198 
199     if (pNetworkProvider)
200         return S_OK;
201     else
202         return E_FAIL;
203 }
204 
205 HRESULT
206 CBDAPinControl_RealConstructor(
207     HANDLE hPin,
208     IBDA_NetworkProvider *pNetworkProvider,
209     IPin * pConnectedPin,
210     ULONG RegistrationCtx,
211     IUnknown * pUnkOuter,
212     REFIID riid,
213     LPVOID * ppv)
214 {
215     CBDAPinControl * handler = new CBDAPinControl(hPin, pNetworkProvider, pConnectedPin, RegistrationCtx);
216 
217 #ifdef BDAPLGIN_TRACE
218     OutputDebugStringW(L"CBDAPinControl_fnConstructor\n");
219 #endif
220 
221     if (!handler)
222         return E_OUTOFMEMORY;
223 
224     if (FAILED(handler->QueryInterface(riid, ppv)))
225     {
226         /* not supported */
227         delete handler;
228         return E_NOINTERFACE;
229     }
230 
231     return NOERROR;
232 }
233 
234 HRESULT
235 WINAPI
236 CBDAPinControl_fnConstructor(
237     IUnknown * pUnkOuter,
238     REFIID riid,
239     LPVOID * ppv)
240 {
241     IPin * pConnectedPin = NULL;
242     IBDA_NetworkProvider * pNetworkProvider = NULL;
243     HANDLE hFile = INVALID_HANDLE_VALUE;
244     HRESULT hr;
245     IKsObject * pObject = NULL;
246     IPin * pPin = NULL;
247     IUnknown * pUnknown = NULL;
248     PIN_INFO PinInfo;
249     FILTER_INFO FilterInfo;
250     ULONG RegistrationCtx = 0;
251 
252     if (!pUnkOuter)
253         return E_POINTER;
254 
255     OutputDebugStringW(L"CBDAPinControl_fnConstructor\n");
256     //DebugBreak();
257 
258     // query for IKsObject interface
259     hr = pUnkOuter->QueryInterface(IID_IKsObject, (void**)&pObject);
260 
261     if (FAILED(hr))
262         return hr;
263 
264     // query for IPin interface
265     hr = pObject->QueryInterface(IID_IPin, (void**)&pPin);
266 
267     if (FAILED(hr))
268     {
269         //clean up
270        pObject->Release();
271        return hr;
272     }
273 
274     // get pin info
275     hr = pPin->QueryPinInfo(&PinInfo);
276 
277     if (FAILED(hr))
278     {
279         //clean up
280        pObject->Release();
281        pPin->Release();
282        return hr;
283     }
284 
285     if (!PinInfo.pFilter)
286     {
287         //clean up
288        pObject->Release();
289        pPin->Release();
290        return hr;
291     }
292 
293     // sanity checks
294     assert(PinInfo.pFilter != NULL);
295 
296     // query filter info
297     hr = PinInfo.pFilter->QueryFilterInfo(&FilterInfo);
298 
299     // sanity check
300     assert(FilterInfo.pGraph != NULL);
301 
302     // get network provider interface
303     hr = GetNetworkProviderFromGraph(FilterInfo.pGraph, &pNetworkProvider);
304 
305     if (SUCCEEDED(hr))
306     {
307         if (PinInfo.dir == PINDIR_OUTPUT)
308         {
309             // get connected pin handle
310             hr = pPin->ConnectedTo(&pConnectedPin);
311             if (SUCCEEDED(hr))
312             {
313                 // get file handle
314                 hFile = pObject->KsGetObjectHandle();
315                 if (hFile)
316                 {
317                     hr = CBDAPinControl_RealConstructor(hFile, pNetworkProvider, pConnectedPin, 0, pUnkOuter, riid, ppv);
318                     if (SUCCEEDED(hr))
319                     {
320                         // set to null to prevent releasing
321                         pNetworkProvider = NULL;
322                         pConnectedPin = NULL;
323                     }
324                 }
325                 else
326                 {
327                     // expected file handle
328                     hr = E_UNEXPECTED;
329                 }
330             }
331         }
332         else
333         {
334             // get IUnknown from base filter
335             hr = PinInfo.pFilter->QueryInterface(IID_IUnknown, (void**)&pUnknown);
336             if (SUCCEEDED(hr))
337             {
338                 // register device filter
339                 OutputDebugStringW(L"CBDAPinControl_fnConstructor registering device filter with network provider\n");
340                 hr = pNetworkProvider->RegisterDeviceFilter(pUnknown, &RegistrationCtx);
341                 if (SUCCEEDED(hr))
342                 {
343                     // get file handle
344                     hFile = pObject->KsGetObjectHandle();
345                     if (hFile)
346                     {
347                         hr = CBDAPinControl_RealConstructor(hFile, pNetworkProvider, NULL, RegistrationCtx, pUnkOuter, riid, ppv);
348                         if (SUCCEEDED(hr))
349                         {
350                             // set to null to prevent releasing
351                             pNetworkProvider = NULL;
352                         }
353                     }
354                     else
355                     {
356                         // expected file handle
357                         hr = E_UNEXPECTED;
358                     }
359                 }
360                 else
361                 {
362                     WCHAR Buffer[100];
363                     swprintf(Buffer, L"CBDAPinControl_fnConstructor failed to register filter with %lx\n", hr);
364                     OutputDebugStringW(Buffer);
365                 }
366             }
367         }
368     }
369 
370     // release IFilterGraph interface
371     FilterInfo.pGraph->Release();
372 
373     // release IBaseFilter interface
374     PinInfo.pFilter->Release();
375 
376     // release IPin
377     pPin->Release();
378 
379     // release IKsObject
380     pObject->Release();
381 
382 
383     if (pNetworkProvider)
384     {
385         // release network provider
386         pNetworkProvider->Release();
387     }
388 
389     if (pConnectedPin)
390     {
391         // release connected pin
392         pConnectedPin->Release();
393     }
394 
395     if (pUnknown)
396     {
397         // release filter
398         pUnknown->Release();
399     }
400 
401     return hr;
402 }
403