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 22 STDMETHODIMP_(ULONG) AddRef() 23 { 24 InterlockedIncrement(&m_Ref); 25 return m_Ref; 26 } 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); 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 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 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 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 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 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 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 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 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 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 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 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 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 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 378 CNetworkProvider::QueryVendorInfo( 379 LPWSTR *pVendorInfo) 380 { 381 return E_NOTIMPL; 382 } 383 384 //------------------------------------------------------------------- 385 // IAMovieSetup interface 386 // 387 388 HRESULT 389 STDMETHODCALLTYPE 390 CNetworkProvider::Register() 391 { 392 OutputDebugStringW(L"CNetworkProvider::Register : NotImplemented\n"); 393 return E_NOTIMPL; 394 } 395 396 HRESULT 397 STDMETHODCALLTYPE 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 410 CNetworkProvider::PutSignalSource( 411 ULONG ulSignalSource) 412 { 413 OutputDebugStringW(L"CNetworkProvider::PutSignalSource : NotImplemented\n"); 414 return E_NOTIMPL; 415 } 416 417 HRESULT 418 STDMETHODCALLTYPE 419 CNetworkProvider::GetSignalSource( 420 ULONG *pulSignalSource) 421 { 422 OutputDebugStringW(L"CNetworkProvider::GetSignalSource : NotImplemented\n"); 423 return E_NOTIMPL; 424 } 425 426 HRESULT 427 STDMETHODCALLTYPE 428 CNetworkProvider::GetNetworkType( 429 GUID *pguidNetworkType) 430 { 431 OutputDebugStringW(L"CNetworkProvider::GetNetworkType : NotImplemented\n"); 432 return E_NOTIMPL; 433 } 434 435 HRESULT 436 STDMETHODCALLTYPE 437 CNetworkProvider::PutTuningSpace( 438 REFGUID guidTuningSpace) 439 { 440 OutputDebugStringW(L"CNetworkProvider::PutTuningSpace : NotImplemented\n"); 441 return E_NOTIMPL; 442 } 443 444 HRESULT 445 STDMETHODCALLTYPE 446 CNetworkProvider::GetTuningSpace( 447 GUID *pguidTuingSpace) 448 { 449 OutputDebugStringW(L"CNetworkProvider::GetTuningSpace : NotImplemented\n"); 450 return E_NOTIMPL; 451 } 452 453 HRESULT 454 STDMETHODCALLTYPE 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 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 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