1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Network Provider for MPEG2 based networks
4 * FILE: dll/directx/msdvbnp/networkprovider.cpp
5 * PURPOSE: IBDA_NetworkProvider interface
6 *
7 * PROGRAMMERS: Johannes Anderwald (johannes.anderwald@reactos.org)
8 */
9 #include "precomp.h"
10
11 #define DEVICE_FILTER_MASK (0x80000000)
12
13 class CNetworkProvider : public IBaseFilter,
14 public IAMovieSetup,
15 public IBDA_NetworkProvider
16 {
17 public:
18 typedef std::vector<IUnknown*>DeviceFilterStack;
19
20 STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
21
AddRef()22 STDMETHODIMP_(ULONG) AddRef()
23 {
24 InterlockedIncrement(&m_Ref);
25 return m_Ref;
26 }
Release()27 STDMETHODIMP_(ULONG) Release()
28 {
29 InterlockedDecrement(&m_Ref);
30 if (!m_Ref)
31 {
32 delete this;
33 return 0;
34 }
35 return m_Ref;
36 }
37
38 // IBaseFilter methods
39 HRESULT STDMETHODCALLTYPE GetClassID(CLSID *pClassID);
40 HRESULT STDMETHODCALLTYPE Stop( void);
41 HRESULT STDMETHODCALLTYPE Pause( void);
42 HRESULT STDMETHODCALLTYPE Run(REFERENCE_TIME tStart);
43 HRESULT STDMETHODCALLTYPE GetState(DWORD dwMilliSecsTimeout, FILTER_STATE *State);
44 HRESULT STDMETHODCALLTYPE SetSyncSource(IReferenceClock *pClock);
45 HRESULT STDMETHODCALLTYPE GetSyncSource(IReferenceClock **pClock);
46 HRESULT STDMETHODCALLTYPE EnumPins(IEnumPins **ppEnum);
47 HRESULT STDMETHODCALLTYPE FindPin(LPCWSTR Id, IPin **ppPin);
48 HRESULT STDMETHODCALLTYPE QueryFilterInfo(FILTER_INFO *pInfo);
49 HRESULT STDMETHODCALLTYPE JoinFilterGraph(IFilterGraph *pGraph, LPCWSTR pName);
50 HRESULT STDMETHODCALLTYPE QueryVendorInfo(LPWSTR *pVendorInfo);
51
52 //IAMovieSetup methods
53 HRESULT STDMETHODCALLTYPE Register( void);
54 HRESULT STDMETHODCALLTYPE Unregister( void);
55
56 //IBDA_NetworkProvider methods
57 HRESULT STDMETHODCALLTYPE PutSignalSource(ULONG ulSignalSource);
58 HRESULT STDMETHODCALLTYPE GetSignalSource(ULONG *pulSignalSource);
59 HRESULT STDMETHODCALLTYPE GetNetworkType(GUID *pguidNetworkType);
60 HRESULT STDMETHODCALLTYPE PutTuningSpace(REFGUID guidTuningSpace);
61 HRESULT STDMETHODCALLTYPE GetTuningSpace(GUID *pguidTuingSpace);
62 HRESULT STDMETHODCALLTYPE RegisterDeviceFilter(IUnknown *pUnkFilterControl, ULONG *ppvRegistrationContext);
63 HRESULT STDMETHODCALLTYPE UnRegisterDeviceFilter(ULONG pvRegistrationContext);
64
65 CNetworkProvider(LPCGUID ClassID);
~CNetworkProvider()66 virtual ~CNetworkProvider(){};
67
68 protected:
69 LONG m_Ref;
70 IFilterGraph *m_pGraph;
71 IReferenceClock * m_ReferenceClock;
72 FILTER_STATE m_FilterState;
73 IPin * m_Pins[1];
74 GUID m_ClassID;
75 DeviceFilterStack m_DeviceFilters;
76 IScanningTuner * m_Tuner;
77 IBDA_IPV6Filter * m_IPV6Filter;
78 IBDA_IPV4Filter * m_IPV4Filter;
79 IBDA_EthernetFilter * m_EthernetFilter;
80 };
81
82 HRESULT
83 STDMETHODCALLTYPE
QueryInterface(IN REFIID refiid,OUT PVOID * Output)84 CNetworkProvider::QueryInterface(
85 IN REFIID refiid,
86 OUT PVOID* Output)
87 {
88 ULONG Index;
89 HRESULT hr;
90
91 *Output = NULL;
92
93 if (IsEqualGUID(refiid, IID_IUnknown))
94 {
95 *Output = PVOID(this);
96 reinterpret_cast<IUnknown*>(*Output)->AddRef();
97 return NOERROR;
98 }
99 if (IsEqualGUID(refiid, IID_IBaseFilter))
100 {
101 *Output = (IBaseFilter*)(this);
102 reinterpret_cast<IBaseFilter*>(*Output)->AddRef();
103 return NOERROR;
104 }
105
106 if (IsEqualGUID(refiid, IID_ITuner) ||
107 IsEqualGUID(refiid, IID_IScanningTuner))
108 {
109 // construct scanning tuner
110 if (!m_Tuner)
111 {
112 HRESULT hr = CScanningTunner_fnConstructor(m_DeviceFilters, refiid, (void**)&m_Tuner);
113 if (FAILED(hr))
114 return hr;
115 }
116 m_Tuner->AddRef();
117 *Output = (IUnknown*)m_Tuner;
118
119 return NOERROR;
120 }
121
122 if (IsEqualGUID(refiid, IID_IBDA_IPV6Filter))
123 {
124 // construct scanning tuner
125 if (!m_IPV6Filter)
126 {
127 HRESULT hr = CIPV6Filter_fnConstructor((IBDA_NetworkProvider*)this, refiid, (void**)&m_IPV6Filter);
128 if (FAILED(hr))
129 return hr;
130 }
131 m_IPV6Filter->AddRef();
132 *Output = (IUnknown*)m_IPV6Filter;
133
134 return NOERROR;
135 }
136
137 if (IsEqualGUID(refiid, IID_IBDA_IPV4Filter))
138 {
139 // construct scanning tuner
140 if (!m_IPV4Filter)
141 {
142 HRESULT hr = CIPV4Filter_fnConstructor((IBDA_NetworkProvider*)this, refiid, (void**)&m_IPV4Filter);
143 if (FAILED(hr))
144 return hr;
145 }
146 m_IPV4Filter->AddRef();
147 *Output = (IUnknown*)m_IPV4Filter;
148
149 return NOERROR;
150 }
151
152 if (IsEqualGUID(refiid, IID_IBDA_EthernetFilter))
153 {
154 // construct scanning tuner
155 if (!m_EthernetFilter)
156 {
157 HRESULT hr = CIPV4Filter_fnConstructor((IBDA_NetworkProvider*)this, refiid, (void**)&m_EthernetFilter);
158 if (FAILED(hr))
159 return hr;
160 }
161 m_EthernetFilter->AddRef();
162 *Output = (IUnknown*)m_EthernetFilter;
163
164 return NOERROR;
165 }
166
167 if (IsEqualGUID(refiid, IID_IBDA_NetworkProvider))
168 {
169 *Output = (IBDA_NetworkProvider*)(this);
170 reinterpret_cast<IBDA_NetworkProvider*>(*Output)->AddRef();
171 return NOERROR;
172 }
173
174 for(Index = 0; Index < m_DeviceFilters.size(); Index++)
175 {
176 // get device filter
177 IUnknown *pFilter = m_DeviceFilters[Index];
178
179 if (!pFilter)
180 continue;
181
182 // query for requested interface
183 hr = pFilter->QueryInterface(refiid, Output);
184 if (SUCCEEDED(hr))
185 {
186 #ifdef MSDVBNP_TRACE
187 WCHAR Buffer[MAX_PATH];
188 LPOLESTR lpstr;
189 StringFromCLSID(refiid, &lpstr);
190 swprintf(Buffer, L"CNetworkProvider::QueryInterface: DeviceFilter %lu supports %s !!!\n", Index, lpstr);
191 OutputDebugStringW(Buffer);
192 CoTaskMemFree(lpstr);
193 #endif
194 return hr;
195 }
196 }
197
198 WCHAR Buffer[MAX_PATH];
199 LPOLESTR lpstr;
200 StringFromCLSID(refiid, &lpstr);
201 swprintf(Buffer, L"CNetworkProvider::QueryInterface: NoInterface for %s !!!\n", lpstr);
202 OutputDebugStringW(Buffer);
203 CoTaskMemFree(lpstr);
204
205 return E_NOINTERFACE;
206 }
207
CNetworkProvider(LPCGUID ClassID)208 CNetworkProvider::CNetworkProvider(LPCGUID ClassID) : m_Ref(0),
209 m_pGraph(0),
210 m_ReferenceClock(0),
211 m_FilterState(State_Stopped),
212 m_DeviceFilters(),
213 m_Tuner(0),
214 m_IPV6Filter(0),
215 m_IPV4Filter(0),
216 m_EthernetFilter(0)
217 {
218 m_Pins[0] = 0;
219
220 CopyMemory(&m_ClassID, ClassID, sizeof(GUID));
221 };
222
223 //-------------------------------------------------------------------
224 // IBaseFilter interface
225 //
226
227 HRESULT
228 STDMETHODCALLTYPE
GetClassID(CLSID * pClassID)229 CNetworkProvider::GetClassID(
230 CLSID *pClassID)
231 {
232 OutputDebugStringW(L"CNetworkProvider::GetClassID\n");
233 CopyMemory(&pClassID, &m_ClassID, sizeof(GUID));
234
235 return S_OK;
236 }
237
238 HRESULT
239 STDMETHODCALLTYPE
Stop()240 CNetworkProvider::Stop()
241 {
242 OutputDebugStringW(L"CNetworkProvider::Stop\n");
243 m_FilterState = State_Stopped;
244 return S_OK;
245 }
246
247 HRESULT
248 STDMETHODCALLTYPE
Pause()249 CNetworkProvider::Pause()
250 {
251 OutputDebugStringW(L"CNetworkProvider::Pause\n");
252
253 m_FilterState = State_Paused;
254 return S_OK;
255 }
256
257 HRESULT
258 STDMETHODCALLTYPE
Run(REFERENCE_TIME tStart)259 CNetworkProvider::Run(
260 REFERENCE_TIME tStart)
261 {
262 OutputDebugStringW(L"CNetworkProvider::Run\n");
263
264 m_FilterState = State_Running;
265 return S_OK;
266 }
267
268 HRESULT
269 STDMETHODCALLTYPE
GetState(DWORD dwMilliSecsTimeout,FILTER_STATE * State)270 CNetworkProvider::GetState(
271 DWORD dwMilliSecsTimeout,
272 FILTER_STATE *State)
273 {
274 *State = m_FilterState;
275 return S_OK;
276 }
277
278 HRESULT
279 STDMETHODCALLTYPE
SetSyncSource(IReferenceClock * pClock)280 CNetworkProvider::SetSyncSource(
281 IReferenceClock *pClock)
282 {
283 if (pClock)
284 {
285 pClock->AddRef();
286
287 }
288 if (m_ReferenceClock)
289 {
290 m_ReferenceClock->Release();
291 }
292
293 m_ReferenceClock = pClock;
294 return S_OK;
295 }
296
297 HRESULT
298 STDMETHODCALLTYPE
GetSyncSource(IReferenceClock ** pClock)299 CNetworkProvider::GetSyncSource(
300 IReferenceClock **pClock)
301 {
302 if (!pClock)
303 return E_POINTER;
304
305 if (m_ReferenceClock)
306 m_ReferenceClock->AddRef();
307
308 *pClock = m_ReferenceClock;
309 return S_OK;
310 }
311
312 HRESULT
313 STDMETHODCALLTYPE
EnumPins(IEnumPins ** ppEnum)314 CNetworkProvider::EnumPins(
315 IEnumPins **ppEnum)
316 {
317 if (m_Pins[0] == 0)
318 {
319 HRESULT hr = CPin_fnConstructor(NULL, (IBaseFilter*)this, IID_IUnknown, (void**)&m_Pins[0]);
320 if (FAILED(hr))
321 return hr;
322 }
323
324 return CEnumPins_fnConstructor(NULL, 1, m_Pins, IID_IEnumPins, (void**)ppEnum);
325 }
326
327 HRESULT
328 STDMETHODCALLTYPE
FindPin(LPCWSTR Id,IPin ** ppPin)329 CNetworkProvider::FindPin(
330 LPCWSTR Id, IPin **ppPin)
331 {
332 OutputDebugStringW(L"CNetworkProvider::FindPin : NotImplemented\n");
333 return E_NOTIMPL;
334 }
335
336
337 HRESULT
338 STDMETHODCALLTYPE
QueryFilterInfo(FILTER_INFO * pInfo)339 CNetworkProvider::QueryFilterInfo(
340 FILTER_INFO *pInfo)
341 {
342 if (!pInfo)
343 return E_POINTER;
344
345 pInfo->achName[0] = L'\0';
346 pInfo->pGraph = m_pGraph;
347
348 if (m_pGraph)
349 m_pGraph->AddRef();
350
351 return S_OK;
352 }
353
354 HRESULT
355 STDMETHODCALLTYPE
JoinFilterGraph(IFilterGraph * pGraph,LPCWSTR pName)356 CNetworkProvider::JoinFilterGraph(
357 IFilterGraph *pGraph,
358 LPCWSTR pName)
359 {
360 if (pGraph)
361 {
362 // joining filter graph
363 m_pGraph = pGraph;
364 }
365 else
366 {
367 // leaving graph
368 m_pGraph = 0;
369 }
370
371 OutputDebugStringW(L"CNetworkProvider::JoinFilterGraph\n");
372 return S_OK;
373 }
374
375
376 HRESULT
377 STDMETHODCALLTYPE
QueryVendorInfo(LPWSTR * pVendorInfo)378 CNetworkProvider::QueryVendorInfo(
379 LPWSTR *pVendorInfo)
380 {
381 return E_NOTIMPL;
382 }
383
384 //-------------------------------------------------------------------
385 // IAMovieSetup interface
386 //
387
388 HRESULT
389 STDMETHODCALLTYPE
Register()390 CNetworkProvider::Register()
391 {
392 OutputDebugStringW(L"CNetworkProvider::Register : NotImplemented\n");
393 return E_NOTIMPL;
394 }
395
396 HRESULT
397 STDMETHODCALLTYPE
Unregister()398 CNetworkProvider::Unregister()
399 {
400 OutputDebugStringW(L"CNetworkProvider::Unregister : NotImplemented\n");
401 return E_NOTIMPL;
402 }
403
404 //-------------------------------------------------------------------
405 // IBDA_NetworkProvider interface
406 //
407
408 HRESULT
409 STDMETHODCALLTYPE
PutSignalSource(ULONG ulSignalSource)410 CNetworkProvider::PutSignalSource(
411 ULONG ulSignalSource)
412 {
413 OutputDebugStringW(L"CNetworkProvider::PutSignalSource : NotImplemented\n");
414 return E_NOTIMPL;
415 }
416
417 HRESULT
418 STDMETHODCALLTYPE
GetSignalSource(ULONG * pulSignalSource)419 CNetworkProvider::GetSignalSource(
420 ULONG *pulSignalSource)
421 {
422 OutputDebugStringW(L"CNetworkProvider::GetSignalSource : NotImplemented\n");
423 return E_NOTIMPL;
424 }
425
426 HRESULT
427 STDMETHODCALLTYPE
GetNetworkType(GUID * pguidNetworkType)428 CNetworkProvider::GetNetworkType(
429 GUID *pguidNetworkType)
430 {
431 OutputDebugStringW(L"CNetworkProvider::GetNetworkType : NotImplemented\n");
432 return E_NOTIMPL;
433 }
434
435 HRESULT
436 STDMETHODCALLTYPE
PutTuningSpace(REFGUID guidTuningSpace)437 CNetworkProvider::PutTuningSpace(
438 REFGUID guidTuningSpace)
439 {
440 OutputDebugStringW(L"CNetworkProvider::PutTuningSpace : NotImplemented\n");
441 return E_NOTIMPL;
442 }
443
444 HRESULT
445 STDMETHODCALLTYPE
GetTuningSpace(GUID * pguidTuingSpace)446 CNetworkProvider::GetTuningSpace(
447 GUID *pguidTuingSpace)
448 {
449 OutputDebugStringW(L"CNetworkProvider::GetTuningSpace : NotImplemented\n");
450 return E_NOTIMPL;
451 }
452
453 HRESULT
454 STDMETHODCALLTYPE
RegisterDeviceFilter(IUnknown * pUnkFilterControl,ULONG * ppvRegistrationContext)455 CNetworkProvider::RegisterDeviceFilter(
456 IUnknown *pUnkFilterControl,
457 ULONG *ppvRegistrationContext)
458 {
459 HRESULT hr;
460 IBDA_DeviceControl * pDeviceControl = NULL;
461 IBDA_Topology *pTopology = NULL;
462
463 OutputDebugStringW(L"CNetworkProvider::RegisterDeviceFilter\n");
464
465 if (!pUnkFilterControl || !ppvRegistrationContext)
466 {
467 //invalid argument
468 return E_POINTER;
469 }
470
471 // the filter must support IBDA_DeviceControl and IBDA_Topology
472 hr = pUnkFilterControl->QueryInterface(IID_IBDA_DeviceControl, (void**)&pDeviceControl);
473 if (FAILED(hr))
474 {
475 OutputDebugStringW(L"CNetworkProvider::RegisterDeviceFilter Filter does not support IBDA_DeviceControl\n");
476 return hr;
477 }
478
479 hr = pUnkFilterControl->QueryInterface(IID_IBDA_Topology, (void**)&pTopology);
480 if (FAILED(hr))
481 {
482 pDeviceControl->Release();
483 OutputDebugStringW(L"CNetworkProvider::RegisterDeviceFilter Filter does not support IID_IBDA_Topology\n");
484 return hr;
485 }
486
487 //TODO
488 // analyize device filter
489
490 // increment reference
491 pUnkFilterControl->AddRef();
492
493 // release IBDA_DeviceControl interface
494 pDeviceControl->Release();
495
496 // release IBDA_Topology interface
497 pTopology->Release();
498
499 // store registration ctx
500 *ppvRegistrationContext = (m_DeviceFilters.size() | DEVICE_FILTER_MASK);
501
502 // store filter
503 m_DeviceFilters.push_back(pUnkFilterControl);
504
505 OutputDebugStringW(L"CNetworkProvider::RegisterDeviceFilter complete\n");
506
507 return S_OK;
508 }
509
510 HRESULT
511 STDMETHODCALLTYPE
UnRegisterDeviceFilter(ULONG pvRegistrationContext)512 CNetworkProvider::UnRegisterDeviceFilter(ULONG pvRegistrationContext)
513 {
514 ULONG Index;
515 IUnknown * pUnknown;
516
517 OutputDebugStringW(L"CNetworkProvider::UnRegisterDeviceFilter\n");
518
519 if (!(pvRegistrationContext & DEVICE_FILTER_MASK))
520 {
521 // invalid argument
522 return E_INVALIDARG;
523 }
524
525 // get real index
526 Index = pvRegistrationContext & ~DEVICE_FILTER_MASK;
527
528 if (Index >= m_DeviceFilters.size())
529 {
530 // invalid argument
531 return E_INVALIDARG;
532 }
533
534 pUnknown = m_DeviceFilters[Index];
535 if (!pUnknown)
536 {
537 // filter was already de-registered
538 return E_INVALIDARG;
539 }
540
541 // remove from vector
542 m_DeviceFilters[Index] = NULL;
543
544 // release extra reference
545 pUnknown->Release();
546
547 return NOERROR;
548 }
549
550 HRESULT
551 WINAPI
CNetworkProvider_fnConstructor(IUnknown * pUnknown,REFIID riid,LPVOID * ppv)552 CNetworkProvider_fnConstructor(
553 IUnknown *pUnknown,
554 REFIID riid,
555 LPVOID * ppv)
556 {
557 CNetworkProvider * handler = new CNetworkProvider(&CLSID_DVBTNetworkProvider);
558
559 #ifdef MSDVBNP_TRACE
560 WCHAR Buffer[MAX_PATH];
561 LPOLESTR lpstr;
562 StringFromCLSID(riid, &lpstr);
563 swprintf(Buffer, L"CNetworkProvider_fnConstructor riid %s pUnknown %p\n", lpstr, pUnknown);
564 OutputDebugStringW(Buffer);
565 #endif
566
567 if (!handler)
568 return E_OUTOFMEMORY;
569
570 if (FAILED(handler->QueryInterface(riid, ppv)))
571 {
572 /* not supported */
573 delete handler;
574 return E_NOINTERFACE;
575 }
576 return NOERROR;
577 }
578