sync with trunk r46493
[reactos.git] / dll / directx / bdaplgin / pincontrol.cpp
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS BDA Proxy
4 * FILE: dll/directx/bdaplgin/classfactory.cpp
5 * PURPOSE: ClassFactory interface
6 *
7 * PROGRAMMERS: Johannes Anderwald (janderwald@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 hr = pNetworkProvider->RegisterDeviceFilter(pUnknown, &RegistrationCtx);
340 if (SUCCEEDED(hr))
341 {
342 // get file handle
343 hFile = pObject->KsGetObjectHandle();
344 if (hFile)
345 {
346 hr = CBDAPinControl_RealConstructor(hFile, pNetworkProvider, NULL, RegistrationCtx, pUnkOuter, riid, ppv);
347 if (SUCCEEDED(hr))
348 {
349 // set to null to prevent releasing
350 pNetworkProvider = NULL;
351 }
352 }
353 else
354 {
355 // expected file handle
356 hr = E_UNEXPECTED;
357 }
358 }
359 else
360 {
361 WCHAR Buffer[100];
362 swprintf(Buffer, L"CBDAPinControl_fnConstructor failed to register filter with %lx\n", hr);
363 OutputDebugStringW(Buffer);
364 DebugBreak();
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 }