1 /*
2  * COPYRIGHT:       See COPYING in the top level directory
3  * PROJECT:         ReactOS Network Provider for MPEG2 based networks
4  * FILE:            dll/directx/msdvbnp/scanningtuner.cpp
5  * PURPOSE:         IScanningTunner interface
6  *
7  * PROGRAMMERS:     Johannes Anderwald (johannes.anderwald@reactos.org)
8  */
9 #include "precomp.h"
10 
11 class CScanningTunner : public IScanningTuner
12 {
13 public:
14     STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
15 
16     STDMETHODIMP_(ULONG) AddRef()
17     {
18         InterlockedIncrement(&m_Ref);
19         return m_Ref;
20     }
21     STDMETHODIMP_(ULONG) Release()
22     {
23         InterlockedDecrement(&m_Ref);
24         if (!m_Ref)
25         {
26             delete this;
27             return 0;
28         }
29         return m_Ref;
30     }
31 
32     //ITuner methods
33     HRESULT STDMETHODCALLTYPE get_TuningSpace(ITuningSpace **TuningSpace);
34     HRESULT STDMETHODCALLTYPE put_TuningSpace(ITuningSpace *TuningSpace);
35     HRESULT STDMETHODCALLTYPE EnumTuningSpaces(IEnumTuningSpaces **ppEnum);
36     HRESULT STDMETHODCALLTYPE get_TuneRequest(ITuneRequest **TuneRequest);
37     HRESULT STDMETHODCALLTYPE put_TuneRequest(ITuneRequest *TuneRequest);
38     HRESULT STDMETHODCALLTYPE Validate(ITuneRequest *TuneRequest);
39     HRESULT STDMETHODCALLTYPE get_PreferredComponentTypes(IComponentTypes **ComponentTypes);
40     HRESULT STDMETHODCALLTYPE put_PreferredComponentTypes(IComponentTypes *ComponentTypes);
41     HRESULT STDMETHODCALLTYPE get_SignalStrength(long *Strength);
42     HRESULT STDMETHODCALLTYPE TriggerSignalEvents(long Interval);
43 
44     //IScanningTuner methods
45     HRESULT STDMETHODCALLTYPE SeekUp();
46     HRESULT STDMETHODCALLTYPE SeekDown();
47     HRESULT STDMETHODCALLTYPE ScanUp(long MillisecondsPause);
48     HRESULT STDMETHODCALLTYPE ScanDown(long MillisecondsPause);
49     HRESULT STDMETHODCALLTYPE AutoProgram();
50 
51     CScanningTunner(std::vector<IUnknown*> & DeviceFilters) : m_Ref(0), m_TuningSpace(0), m_DeviceFilters(DeviceFilters){};
52     virtual ~CScanningTunner() {};
53     HRESULT STDMETHODCALLTYPE StartChanges();
54     HRESULT STDMETHODCALLTYPE CommitChanges();
55     HRESULT STDMETHODCALLTYPE CheckChanges();
56     HRESULT STDMETHODCALLTYPE SetLnbInfo(IBDA_LNBInfo * pLnbInfo, ULONG ulLOFLow, ULONG ulLOFHigh, ULONG ulSwitchFrequency);
57     HRESULT STDMETHODCALLTYPE SetDigitalDemodulator(IBDA_DigitalDemodulator * pDigitalDemo, ModulationType ModType, FECMethod InnerFEC, BinaryConvolutionCodeRate InnerFECRate, FECMethod OuterFEC, BinaryConvolutionCodeRate OuterFECRate, ULONG SymbolRate);
58     HRESULT SetFrequency(IBDA_FrequencyFilter * pFrequency, ULONG FrequencyMultiplier, ULONG Frequency, Polarisation Polarity, ULONG Range, ULONG Bandwidth);
59     HRESULT STDMETHODCALLTYPE performDVBTTune(IDVBTuneRequest * pDVBTRequest, IDVBTLocator *pDVBTLocator);
60 protected:
61     LONG m_Ref;
62     ITuningSpace * m_TuningSpace;
63     std::vector<IUnknown*> & m_DeviceFilters;
64 };
65 
66 HRESULT
67 STDMETHODCALLTYPE
68 CScanningTunner::QueryInterface(
69     IN  REFIID refiid,
70     OUT PVOID* Output)
71 {
72     if (IsEqualGUID(refiid, IID_IUnknown))
73     {
74         *Output = PVOID(this);
75         reinterpret_cast<IUnknown*>(*Output)->AddRef();
76         return NOERROR;
77     }
78     if (IsEqualGUID(refiid, IID_ITuner))
79     {
80         *Output = (ITuner*)(this);
81         reinterpret_cast<ITuner*>(*Output)->AddRef();
82         return NOERROR;
83     }
84 
85     if (IsEqualGUID(refiid, IID_IScanningTuner))
86     {
87         *Output = (IScanningTuner*)(this);
88         reinterpret_cast<IScanningTuner*>(*Output)->AddRef();
89         return NOERROR;
90     }
91 
92     WCHAR Buffer[MAX_PATH];
93     LPOLESTR lpstr;
94     StringFromCLSID(refiid, &lpstr);
95     swprintf(Buffer, L"CScanningTunner::QueryInterface: NoInterface for %s\n", lpstr);
96     OutputDebugStringW(Buffer);
97     CoTaskMemFree(lpstr);
98 
99 
100     return E_NOINTERFACE;
101 }
102 
103 //-------------------------------------------------------------------
104 //ITuner
105 //
106 HRESULT
107 STDMETHODCALLTYPE
108 CScanningTunner::get_TuningSpace(
109     ITuningSpace **TuningSpace)
110 {
111     OutputDebugStringW(L"CScanningTunner::get_TuningSpace\n");
112 
113     *TuningSpace = m_TuningSpace;
114     return S_OK;
115 }
116 
117 HRESULT
118 STDMETHODCALLTYPE
119 CScanningTunner::put_TuningSpace(
120     ITuningSpace *TuningSpace)
121 {
122     OutputDebugStringW(L"CScanningTunner::put_TuningSpace\n");
123     m_TuningSpace = TuningSpace;
124     return S_OK;
125 }
126 
127 HRESULT
128 STDMETHODCALLTYPE
129 CScanningTunner::EnumTuningSpaces(
130     IEnumTuningSpaces **ppEnum)
131 {
132     OutputDebugStringW(L"CScanningTunner::EnumTuningSpaces : NotImplemented\n");
133     return E_NOTIMPL;
134 }
135 
136 HRESULT
137 STDMETHODCALLTYPE
138 CScanningTunner::get_TuneRequest(
139     ITuneRequest **TuneRequest)
140 {
141     OutputDebugStringW(L"CScanningTunner::get_TuneRequest : NotImplemented\n");
142     return E_NOTIMPL;
143 }
144 
145 HRESULT
146 STDMETHODCALLTYPE
147 CScanningTunner::put_TuneRequest(
148     ITuneRequest *TuneRequest)
149 {
150     IDVBTuneRequest * pDVBTRequest;
151     ILocator *pLocator;
152     IDVBTLocator *pDVBTLocator;
153     HRESULT hr;
154 
155 
156     OutputDebugStringW(L"CScanningTunner::put_TuneRequest\n");
157 
158     // query for IDVBTuneRequest interface
159     hr = TuneRequest->QueryInterface(IID_IDVBTuneRequest, (void**)&pDVBTRequest);
160 
161     // sanity check
162     assert(hr == NOERROR);
163 
164     // get the IDVBTLocator
165     hr = pDVBTRequest->get_Locator((ILocator**)&pLocator);
166 
167     // sanity check
168     assert(hr == NOERROR);
169     assert(pLocator);
170 
171     hr = pLocator->QueryInterface(IID_ILocator, (void**)&pDVBTLocator);
172 
173     // sanity check
174     assert(hr == NOERROR);
175 
176 
177     StartChanges();
178     CommitChanges();
179     StartChanges();
180 
181     hr = performDVBTTune(pDVBTRequest, pDVBTLocator);
182 
183 
184     pDVBTLocator->Release();
185     pDVBTRequest->Release();
186 
187     CheckChanges();
188     CommitChanges();
189     StartChanges();
190 
191     return NOERROR;
192 }
193 
194 HRESULT
195 STDMETHODCALLTYPE
196 CScanningTunner::Validate(
197     ITuneRequest *TuneRequest)
198 {
199     OutputDebugStringW(L"CScanningTunner::Validate : NotImplemented\n");
200     return E_NOTIMPL;
201 }
202 
203 HRESULT
204 STDMETHODCALLTYPE
205 CScanningTunner::get_PreferredComponentTypes(
206     IComponentTypes **ComponentTypes)
207 {
208     OutputDebugStringW(L"CScanningTunner::get_PreferredComponentTypes : NotImplemented\n");
209     return E_NOTIMPL;
210 }
211 
212 HRESULT
213 STDMETHODCALLTYPE
214 CScanningTunner::put_PreferredComponentTypes(
215     IComponentTypes *ComponentTypes)
216 {
217     OutputDebugStringW(L"CScanningTunner::put_PreferredComponentTypes : NotImplemented\n");
218     return E_NOTIMPL;
219 }
220 
221 HRESULT
222 STDMETHODCALLTYPE
223 CScanningTunner::get_SignalStrength(
224     long *Strength)
225 {
226     OutputDebugStringW(L"CScanningTunner::get_SignalStrength : NotImplemented\n");
227     return E_NOTIMPL;
228 }
229 
230 HRESULT
231 STDMETHODCALLTYPE
232 CScanningTunner::TriggerSignalEvents(
233     long Interval)
234 {
235     OutputDebugStringW(L"CScanningTunner::TriggerSignalEvents : NotImplemented\n");
236     return E_NOTIMPL;
237 }
238 
239 //-------------------------------------------------------------------
240 //IScanningTuner
241 HRESULT
242 STDMETHODCALLTYPE
243 CScanningTunner::SeekUp()
244 {
245     OutputDebugStringW(L"CScanningTunner::SeekUp : NotImplemented\n");
246     return E_NOTIMPL;
247 }
248 
249 HRESULT
250 STDMETHODCALLTYPE
251 CScanningTunner::SeekDown()
252 {
253     OutputDebugStringW(L"CScanningTunner::SeekDown : NotImplemented\n");
254     return E_NOTIMPL;
255 }
256 
257 HRESULT
258 STDMETHODCALLTYPE
259 CScanningTunner::ScanUp(
260     long MillisecondsPause)
261 {
262     OutputDebugStringW(L"CScanningTunner::ScanUp : NotImplemented\n");
263     return E_NOTIMPL;
264 }
265 
266 HRESULT
267 STDMETHODCALLTYPE
268 CScanningTunner::ScanDown(
269     long MillisecondsPause)
270 {
271     OutputDebugStringW(L"CScanningTunner::ScanDown : NotImplemented\n");
272     return E_NOTIMPL;
273 }
274 
275 HRESULT
276 STDMETHODCALLTYPE
277 CScanningTunner::AutoProgram()
278 {
279     OutputDebugStringW(L"CScanningTunner::AutoProgram : NotImplemented\n");
280     return E_NOTIMPL;
281 }
282 
283 //-------------------------------------------------------------------
284 HRESULT
285 STDMETHODCALLTYPE
286 CScanningTunner::performDVBTTune(
287     IDVBTuneRequest * pDVBTRequest,
288     IDVBTLocator *pDVBTLocator)
289 {
290     HRESULT hr = S_OK;
291     ULONG Index;
292     IBDA_Topology *pTopo;
293     IUnknown *pNode;
294     IBDA_FrequencyFilter * pFrequency;
295     IBDA_LNBInfo * pLnbInfo;
296     IBDA_DigitalDemodulator *pDigitalDemo;
297     LONG BandWidth;
298     LONG Frequency;
299     LONG SymbolRate;
300     FECMethod InnerFEC, OuterFEC;
301     BinaryConvolutionCodeRate InnerFECRate, OuterFECRate;
302     ModulationType Modulation;
303 
304     pDVBTLocator->get_Bandwidth(&BandWidth);
305     pDVBTLocator->get_CarrierFrequency(&Frequency);
306     pDVBTLocator->get_InnerFEC(&InnerFEC);
307     pDVBTLocator->get_InnerFECRate(&InnerFECRate);
308     pDVBTLocator->get_Modulation(&Modulation);
309     pDVBTLocator->get_OuterFEC(&OuterFEC);
310     pDVBTLocator->get_OuterFECRate(&OuterFECRate);
311     pDVBTLocator->get_SymbolRate(&SymbolRate);
312 
313 
314     WCHAR Buffer[1000];
315     swprintf(Buffer, L"BandWidth %lu Frequency %lu Rate %lu InnerFEC %ld OuterFEC %ld InnerFECRate %ld OuterFECRate %ld Modulation %lu\n",
316              BandWidth, Frequency, SymbolRate, InnerFEC, OuterFEC, InnerFECRate, OuterFECRate, Modulation);
317 
318     OutputDebugStringW(Buffer);
319 
320 
321 
322     for(Index = 0; Index < m_DeviceFilters.size(); Index++)
323     {
324         // get device filter
325         IUnknown * pFilter = m_DeviceFilters[Index];
326 
327         if (!pFilter)
328             continue;
329 
330         hr = pFilter->QueryInterface(IID_IBDA_Topology, (void**)&pTopo);
331         // sanity check
332         assert(hr == NOERROR);
333 
334         pNode = NULL;
335         hr = pTopo->GetControlNode(0, 1, 0, &pNode); //HACK
336 
337         WCHAR Buffer[100];
338         swprintf(Buffer, L"CScanningTunner::performDVBTTune GetControlNode %lx\n", hr);
339         OutputDebugStringW(Buffer);
340 
341         if (FAILED(hr))
342             continue;
343 
344         // sanity check
345         assert(hr == NOERROR);
346         assert(pNode);
347 
348         hr = pNode->QueryInterface(IID_IBDA_FrequencyFilter, (void**)&pFrequency);
349 
350         swprintf(Buffer, L"CScanningTunner::performDVBTTune IID_IBDA_FrequencyFilter hr %lx\n", hr);
351         OutputDebugStringW(Buffer);
352 
353         // sanity check
354         assert(hr == NOERROR);
355 
356         hr = SetFrequency(pFrequency, 1000 /* FIXME */, Frequency, BDA_POLARISATION_NOT_DEFINED /* FIXME */, BDA_RANGE_NOT_SET /* FIXME */, BandWidth);
357 
358         swprintf(Buffer, L"CScanningTunner::performDVBTTune SetFrequency hr %lx\n", hr);
359         OutputDebugStringW(Buffer);
360 
361         //sanity check
362         assert(hr == NOERROR);
363 
364         // release interface
365         pFrequency->Release();
366 
367 
368         hr = pNode->QueryInterface(IID_IBDA_LNBInfo, (void**)&pLnbInfo);
369 
370         swprintf(Buffer, L"CScanningTunner::performDVBTTune IID_IBDA_LNBInfo hr %lx\n", hr);
371         OutputDebugStringW(Buffer);
372 
373         // sanity check
374         assert(hr == NOERROR);
375 
376         hr = SetLnbInfo(pLnbInfo, ULONG_MAX /* FIXME */, ULONG_MAX /* FIXME*/, ULONG_MAX /*FIXME*/);
377 
378 
379         swprintf(Buffer, L"CScanningTunner::performDVBTTune SetLnbInfo hr %lx\n", hr);
380         OutputDebugStringW(Buffer);
381 
382         // sanity check
383         assert(hr == NOERROR);
384 
385         // release interface
386         pLnbInfo->Release();
387 
388         hr = pNode->QueryInterface(IID_IBDA_DigitalDemodulator, (void**)&pDigitalDemo);
389 
390         swprintf(Buffer, L"CScanningTunner::performDVBTTune IID_IBDA_DigitalDemodulator hr %lx\n", hr);
391         OutputDebugStringW(Buffer);
392 
393         // sanity check
394         assert(hr == NOERROR);
395 
396         hr = SetDigitalDemodulator(pDigitalDemo, Modulation, InnerFEC, InnerFECRate, OuterFEC, OuterFECRate, SymbolRate);
397 
398         swprintf(Buffer, L"CScanningTunner::performDVBTTune SetDigitalDemodulator hr %lx\n", hr);
399         OutputDebugStringW(Buffer);
400 
401         // sanity check
402         assert(hr == NOERROR);
403 
404         // release interface
405         pDigitalDemo->Release();
406 
407         // release control node
408         pNode->Release();
409 
410         // release IBDA_Topology;
411         pTopo->Release();
412 
413     }
414     return hr;
415 }
416 
417 
418 
419 HRESULT
420 STDMETHODCALLTYPE
421 CScanningTunner::CheckChanges()
422 {
423     ULONG Index;
424     HRESULT hResult = NOERROR;
425     IBDA_DeviceControl * pDeviceControl;
426 
427     for(Index = 0; Index < m_DeviceFilters.size(); Index++)
428     {
429         // get filter
430         IUnknown * pFilter = m_DeviceFilters[Index];
431 
432         if (!pFilter)
433             continue;
434 
435         // query for IBDA_DeviceControl interface
436         hResult = pFilter->QueryInterface(IID_IBDA_DeviceControl, (void**)&pDeviceControl);
437 
438         // sanity check
439         assert(hResult == NOERROR);
440 
441         //start changes
442         hResult = pDeviceControl->CheckChanges();
443 
444         // fix for unimplemented
445         if (hResult == E_NOTIMPL)
446             hResult = NOERROR;
447 
448         // release interface
449         pDeviceControl->Release();
450 
451         if (FAILED(hResult))
452         {
453             //shouldnt happen
454             break;
455         }
456     }
457     // done
458     return hResult;
459 }
460 
461 HRESULT
462 STDMETHODCALLTYPE
463 CScanningTunner::CommitChanges()
464 {
465     ULONG Index;
466     HRESULT hResult = NOERROR;
467     IBDA_DeviceControl * pDeviceControl;
468 
469     for(Index = 0; Index < m_DeviceFilters.size(); Index++)
470     {
471         // get filter
472         IUnknown * pFilter = m_DeviceFilters[Index];
473 
474         if (!pFilter)
475             continue;
476 
477         // query for IBDA_DeviceControl interface
478         HRESULT hr = pFilter->QueryInterface(IID_IBDA_DeviceControl, (void**)&pDeviceControl);
479 
480         // sanity check
481         assert(hr == NOERROR);
482 
483         //start changes
484         hr = pDeviceControl->CommitChanges();
485 
486         // fix for unimplemented
487         if (hr == E_NOTIMPL)
488             hr = NOERROR;
489 
490         if (FAILED(hr))
491         {
492             pDeviceControl->StartChanges();
493             pDeviceControl->CommitChanges();
494             hResult = E_UNEXPECTED;
495         }
496 
497         // release interface
498         pDeviceControl->Release();
499 
500     }
501 
502     //done
503     return hResult;
504 }
505 
506 HRESULT
507 STDMETHODCALLTYPE
508 CScanningTunner::StartChanges()
509 {
510     ULONG Index;
511     IBDA_DeviceControl * pDeviceControl;
512 
513     for(Index = 0; Index < m_DeviceFilters.size(); Index++)
514     {
515         // get filter
516         IUnknown * pFilter = m_DeviceFilters[Index];
517 
518         if (!pFilter)
519             continue;
520 
521         // query for IBDA_DeviceControl interface
522         HRESULT hr = pFilter->QueryInterface(IID_IBDA_DeviceControl, (void**)&pDeviceControl);
523 
524         // sanity check
525         assert(hr == NOERROR);
526 
527         //start changes
528         hr = pDeviceControl->StartChanges();
529 
530         // release interface
531         pDeviceControl->Release();
532 
533         // fix for unimplemented
534         if (hr == E_NOTIMPL)
535             hr = NOERROR;
536 
537         if (FAILED(hr))
538             return hr;
539 
540     }
541 
542     // now commit the changes
543     for(Index = 0; Index < m_DeviceFilters.size(); Index++)
544     {
545         // get filter
546         IUnknown * pFilter = m_DeviceFilters[Index];
547 
548         if (!pFilter)
549             continue;
550 
551         // query for IBDA_DeviceControl interface
552         HRESULT hr = pFilter->QueryInterface(IID_IBDA_DeviceControl, (void**)&pDeviceControl);
553 
554         // sanity check
555         assert(hr == NOERROR);
556 
557         hr = pDeviceControl->CommitChanges();
558 
559         // release interface
560         pDeviceControl->Release();
561     }
562 
563     // done
564     return NOERROR;
565 }
566 
567 HRESULT
568 STDMETHODCALLTYPE
569 CScanningTunner::SetLnbInfo(
570     IBDA_LNBInfo * pLnbInfo,
571     ULONG ulLOFLow,
572     ULONG ulLOFHigh,
573     ULONG ulSwitchFrequency)
574 {
575     HRESULT hr;
576 
577     hr = pLnbInfo->put_LocalOscillatorFrequencyLowBand(ulLOFLow);
578     if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND) || hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND))
579         hr = NOERROR;
580 
581     if (FAILED(hr))
582         return hr;
583 
584     hr = pLnbInfo->put_LocalOscillatorFrequencyHighBand(ulLOFHigh);
585     if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND) || hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND))
586         hr = NOERROR;
587 
588     if (FAILED(hr))
589         return hr;
590 
591     hr = pLnbInfo->put_HighLowSwitchFrequency(ulSwitchFrequency);
592     if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND) || hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND))
593         hr = NOERROR;
594 
595     return hr;
596 }
597 
598 HRESULT
599 CScanningTunner::SetFrequency(
600     IBDA_FrequencyFilter * pFrequency,
601     ULONG FrequencyMultiplier,
602     ULONG Frequency,
603     Polarisation Polarity,
604     ULONG Range,
605     ULONG Bandwidth)
606 {
607     HRESULT hr;
608 
609     hr = pFrequency->put_FrequencyMultiplier(FrequencyMultiplier);
610     if (FAILED(hr))
611         return hr;
612 
613     hr = pFrequency->put_Frequency(Frequency);
614     if (FAILED(hr))
615         return hr;
616 
617     hr = pFrequency->put_Polarity(Polarity);
618     if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND))
619         hr = NOERROR;
620 
621     if (FAILED(hr))
622         return hr;
623 
624     hr = pFrequency->put_Range(Range);
625     if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND))
626         hr = NOERROR;
627 
628     if (FAILED(hr))
629         return hr;
630 
631     hr = pFrequency->put_Bandwidth(Bandwidth);
632     return hr;
633 }
634 
635 HRESULT
636 STDMETHODCALLTYPE
637 CScanningTunner::SetDigitalDemodulator(
638     IBDA_DigitalDemodulator * pDigitalDemo,
639     ModulationType ModType,
640     FECMethod InnerFEC,
641     BinaryConvolutionCodeRate InnerFECRate,
642     FECMethod OuterFEC,
643     BinaryConvolutionCodeRate OuterFECRate,
644     ULONG SymbolRate)
645 {
646     HRESULT hr;
647 
648     hr = pDigitalDemo->put_ModulationType(&ModType);
649     if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND) || hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND))
650         hr = NOERROR;
651 
652     if (FAILED(hr))
653         return hr;
654 
655     hr = pDigitalDemo->put_InnerFECMethod(&InnerFEC);
656     if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND) || hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND))
657         hr = NOERROR;
658     if (FAILED(hr))
659         return hr;
660 
661     hr = pDigitalDemo->put_InnerFECRate(&InnerFECRate);
662     if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND) || hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND))
663         hr = NOERROR;
664     if (FAILED(hr))
665         return hr;
666 
667     hr = pDigitalDemo->put_OuterFECMethod(&OuterFEC);
668     if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND) || hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND))
669         hr = NOERROR;
670     if (FAILED(hr))
671         return hr;
672 
673     hr = pDigitalDemo->put_OuterFECRate(&OuterFECRate);
674     if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND) || hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND))
675         hr = NOERROR;
676     if (FAILED(hr))
677         return hr;
678 
679     hr = pDigitalDemo->put_SymbolRate(&SymbolRate);
680     if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND) || hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND))
681         hr = NOERROR;
682     if (FAILED(hr))
683         return hr;
684 
685     SpectralInversion Inversion = BDA_SPECTRAL_INVERSION_NOT_DEFINED;
686     hr = pDigitalDemo->put_SpectralInversion(&Inversion);
687     if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND) || hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND))
688         hr = NOERROR;
689 
690     return hr;
691 }
692 
693 
694 HRESULT
695 WINAPI
696 CScanningTunner_fnConstructor(
697     std::vector<IUnknown*> & DeviceFilter,
698     REFIID riid,
699     LPVOID * ppv)
700 {
701     CScanningTunner * handler = new CScanningTunner(DeviceFilter);
702 
703 #ifdef MSDVBNP_TRACE
704     WCHAR Buffer[MAX_PATH];
705     LPOLESTR lpstr;
706     StringFromCLSID(riid, &lpstr);
707     swprintf(Buffer, L"CScanningTunner_fnConstructor riid %s\n", lpstr);
708     OutputDebugStringW(Buffer);
709 #endif
710 
711     if (!handler)
712         return E_OUTOFMEMORY;
713 
714     if (FAILED(handler->QueryInterface(riid, ppv)))
715     {
716         /* not supported */
717         delete handler;
718         return E_NOINTERFACE;
719     }
720 
721     return NOERROR;
722 }