[KSPROXY]
[reactos.git] / reactos / dll / directx / ksproxy / proxy.cpp
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS WDM Streaming ActiveMovie Proxy
4 * FILE: dll/directx/ksproxy/proxy.cpp
5 * PURPOSE: IKsProxy interface
6 *
7 * PROGRAMMERS: Johannes Anderwald (janderwald@reactos.org)
8 */
9 #include "precomp.h"
10
11 const GUID IID_IPersistPropertyBag = {0x37D84F60, 0x42CB, 0x11CE, {0x81, 0x35, 0x00, 0xAA, 0x00, 0x4B, 0xB8, 0x51}};
12 const GUID GUID_NULL = {0x00000000L, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
13 const GUID IID_IBDA_DeviceControl = {0xFD0A5AF3, 0xB41D, 0x11d2, {0x9C, 0x95, 0x00, 0xC0, 0x4F, 0x79, 0x71, 0xE0}};
14 /*
15 Needs IKsClock, IKsNotifyEvent
16 */
17
18 class CKsProxy : public IBaseFilter,
19 public IAMovieSetup,
20 public IPersistPropertyBag,
21 public IKsObject
22 /*
23 public IPersistStream,
24 public ISpecifyPropertyPages,
25 public IReferenceClock,
26 public IMediaSeeking,
27 public IKsObject,
28 public IKsPropertySet,
29 public IKsClockPropertySet,
30 public IAMFilterMiscFlags,
31 public IKsControl,
32 public IKsTopology,
33 public IKsAggregateControl,
34 public IAMDeviceRemoval
35 */
36 {
37 public:
38 typedef std::vector<IUnknown *>ProxyPluginVector;
39 typedef std::vector<IPin *> PinVector;
40
41 STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
42
43 STDMETHODIMP_(ULONG) AddRef()
44 {
45 InterlockedIncrement(&m_Ref);
46 return m_Ref;
47 }
48 STDMETHODIMP_(ULONG) Release()
49 {
50 InterlockedDecrement(&m_Ref);
51 if (!m_Ref)
52 {
53 delete this;
54 return 0;
55 }
56 return m_Ref;
57 }
58
59 // IBaseFilter methods
60 HRESULT STDMETHODCALLTYPE GetClassID(CLSID *pClassID);
61 HRESULT STDMETHODCALLTYPE Stop( void);
62 HRESULT STDMETHODCALLTYPE Pause( void);
63 HRESULT STDMETHODCALLTYPE Run(REFERENCE_TIME tStart);
64 HRESULT STDMETHODCALLTYPE GetState(DWORD dwMilliSecsTimeout, FILTER_STATE *State);
65 HRESULT STDMETHODCALLTYPE SetSyncSource(IReferenceClock *pClock);
66 HRESULT STDMETHODCALLTYPE GetSyncSource(IReferenceClock **pClock);
67 HRESULT STDMETHODCALLTYPE EnumPins(IEnumPins **ppEnum);
68 HRESULT STDMETHODCALLTYPE FindPin(LPCWSTR Id, IPin **ppPin);
69 HRESULT STDMETHODCALLTYPE QueryFilterInfo(FILTER_INFO *pInfo);
70 HRESULT STDMETHODCALLTYPE JoinFilterGraph(IFilterGraph *pGraph, LPCWSTR pName);
71 HRESULT STDMETHODCALLTYPE QueryVendorInfo(LPWSTR *pVendorInfo);
72
73 //IAMovieSetup methods
74 HRESULT STDMETHODCALLTYPE Register( void);
75 HRESULT STDMETHODCALLTYPE Unregister( void);
76
77 // IPersistPropertyBag methods
78 HRESULT STDMETHODCALLTYPE InitNew( void);
79 HRESULT STDMETHODCALLTYPE Load(IPropertyBag *pPropBag, IErrorLog *pErrorLog);
80 HRESULT STDMETHODCALLTYPE Save(IPropertyBag *pPropBag, BOOL fClearDirty, BOOL fSaveAllProperties);
81
82 // IKsObject
83 HANDLE STDMETHODCALLTYPE KsGetObjectHandle();
84
85 CKsProxy() : m_Ref(0), m_pGraph(0), m_ReferenceClock(0), m_FilterState(State_Stopped), m_hDevice(0), m_Plugins(), m_Pins() {};
86 virtual ~CKsProxy()
87 {
88 if (m_hDevice)
89 CloseHandle(m_hDevice);
90 };
91
92 HRESULT STDMETHODCALLTYPE GetSupportedSets(LPGUID * pOutGuid, PULONG NumGuids);
93 HRESULT STDMETHODCALLTYPE LoadProxyPlugins(LPGUID pGuids, ULONG NumGuids);
94 HRESULT STDMETHODCALLTYPE GetNumberOfPins(PULONG NumPins);
95 HRESULT STDMETHODCALLTYPE GetPinInstanceCount(ULONG PinId, PKSPIN_CINSTANCES Instances);
96 HRESULT STDMETHODCALLTYPE GetPinDataflow(ULONG PinId, KSPIN_DATAFLOW * DataFlow);
97 HRESULT STDMETHODCALLTYPE GetPinName(ULONG PinId, KSPIN_DATAFLOW DataFlow, ULONG PinCount, LPWSTR * OutPinName);
98 HRESULT STDMETHODCALLTYPE GetPinCommunication(ULONG PinId, KSPIN_COMMUNICATION * Communication);
99 HRESULT STDMETHODCALLTYPE CreatePins();
100 protected:
101 LONG m_Ref;
102 IFilterGraph *m_pGraph;
103 IReferenceClock * m_ReferenceClock;
104 FILTER_STATE m_FilterState;
105 HANDLE m_hDevice;
106 ProxyPluginVector m_Plugins;
107 PinVector m_Pins;
108 };
109
110 HRESULT
111 STDMETHODCALLTYPE
112 CKsProxy::QueryInterface(
113 IN REFIID refiid,
114 OUT PVOID* Output)
115 {
116 *Output = NULL;
117
118 if (IsEqualGUID(refiid, IID_IUnknown) ||
119 IsEqualGUID(refiid, IID_IBaseFilter))
120 {
121 *Output = PVOID(this);
122 reinterpret_cast<IUnknown*>(*Output)->AddRef();
123 return NOERROR;
124 }
125 else if (IsEqualGUID(refiid, IID_IPersistPropertyBag))
126 {
127 *Output = (IPersistPropertyBag*)(this);
128 reinterpret_cast<IPersistPropertyBag*>(*Output)->AddRef();
129 return NOERROR;
130 }
131 if (IsEqualGUID(refiid, IID_IKsObject))
132 {
133 *Output = (IKsObject*)(this);
134 reinterpret_cast<IKsObject*>(*Output)->AddRef();
135 return NOERROR;
136 }
137
138 for(ULONG Index = 0; Index < m_Plugins.size(); Index++)
139 {
140 if (m_Pins[Index])
141 {
142 HRESULT hr = m_Plugins[Index]->QueryInterface(refiid, Output);
143 if (SUCCEEDED(hr))
144 {
145 WCHAR Buffer[100];
146 LPOLESTR lpstr;
147 StringFromCLSID(refiid, &lpstr);
148 swprintf(Buffer, L"CKsProxy::QueryInterface plugin %lu supports interface %s\n", Index, lpstr);
149 OutputDebugStringW(Buffer);
150 CoTaskMemFree(lpstr);
151 return hr;
152 }
153 }
154 }
155
156 WCHAR Buffer[MAX_PATH];
157 LPOLESTR lpstr;
158 StringFromCLSID(refiid, &lpstr);
159 swprintf(Buffer, L"CKsProxy::QueryInterface: NoInterface for %s !!!\n", lpstr);
160 OutputDebugStringW(Buffer);
161 CoTaskMemFree(lpstr);
162
163
164 return E_NOINTERFACE;
165 }
166
167 //-------------------------------------------------------------------
168 // IKsObject interface
169 //
170
171 HANDLE
172 STDMETHODCALLTYPE
173 CKsProxy::KsGetObjectHandle()
174 {
175 return m_hDevice;
176 }
177
178 //-------------------------------------------------------------------
179 // IPersistPropertyBag interface
180 //
181 HRESULT
182 STDMETHODCALLTYPE
183 CKsProxy::InitNew( void)
184 {
185 return S_OK;
186 }
187
188 HRESULT
189 STDMETHODCALLTYPE
190 CKsProxy::GetSupportedSets(
191 LPGUID * pOutGuid,
192 PULONG NumGuids)
193 {
194 KSPROPERTY Property;
195 LPGUID pGuid;
196 ULONG NumProperty = 0;
197 ULONG NumMethods = 0;
198 ULONG NumEvents = 0;
199 ULONG Length;
200 ULONG BytesReturned;
201 HRESULT hr;
202
203 Property.Set = GUID_NULL;
204 Property.Id = 0;
205 Property.Flags = KSPROPERTY_TYPE_SETSUPPORT;
206
207 KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), NULL, 0, &NumProperty);
208 KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_METHOD, (PVOID)&Property, sizeof(KSPROPERTY), NULL, 0, &NumMethods);
209 KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_ENABLE_EVENT, (PVOID)&Property, sizeof(KSPROPERTY), NULL, 0, &NumEvents);
210
211 Length = NumProperty + NumMethods + NumEvents;
212
213 // allocate guid buffer
214 pGuid = (LPGUID)CoTaskMemAlloc(Length);
215 if (!pGuid)
216 {
217 // failed
218 return E_OUTOFMEMORY;
219 }
220
221 NumProperty /= sizeof(GUID);
222 NumMethods /= sizeof(GUID);
223 NumEvents /= sizeof(GUID);
224
225 // get all properties
226 hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)pGuid, Length, &BytesReturned);
227 if (FAILED(hr))
228 {
229 CoTaskMemFree(pGuid);
230 return E_FAIL;
231 }
232 Length -= BytesReturned;
233
234 // get all methods
235 if (Length)
236 {
237 hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_METHOD, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&pGuid[NumProperty], Length, &BytesReturned);
238 if (FAILED(hr))
239 {
240 CoTaskMemFree(pGuid);
241 return E_FAIL;
242 }
243 Length -= BytesReturned;
244 }
245
246 // get all events
247 if (Length)
248 {
249 hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_ENABLE_EVENT, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&pGuid[NumProperty+NumMethods], Length, &BytesReturned);
250 if (FAILED(hr))
251 {
252 CoTaskMemFree(pGuid);
253 return E_FAIL;
254 }
255 Length -= BytesReturned;
256 }
257
258 #ifdef KSPROXY_TRACE
259 WCHAR Buffer[200];
260 swprintf(Buffer, L"NumProperty %lu NumMethods %lu NumEvents %lu\n", NumProperty, NumMethods, NumEvents);
261 OutputDebugStringW(Buffer);
262 #endif
263
264 *pOutGuid = pGuid;
265 *NumGuids = NumProperty+NumEvents+NumMethods;
266 return S_OK;
267 }
268
269 HRESULT
270 STDMETHODCALLTYPE
271 CKsProxy::LoadProxyPlugins(
272 LPGUID pGuids,
273 ULONG NumGuids)
274 {
275 ULONG Index;
276 LPOLESTR pStr;
277 HKEY hKey, hSubKey;
278 HRESULT hr;
279 IUnknown * pUnknown;
280
281 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\MediaInterfaces", 0, KEY_READ, &hKey) != ERROR_SUCCESS)
282 {
283 OutputDebugStringW(L"CKsProxy::LoadProxyPlugins failed to open MediaInterfaces key\n");
284 return E_FAIL;
285 }
286
287 // enumerate all sets
288 for(Index = 0; Index < NumGuids; Index++)
289 {
290 // convert to string
291 hr = StringFromCLSID(pGuids[Index], &pStr);
292 if (FAILED(hr))
293 return E_FAIL;
294
295 // now try open class key
296 if (RegOpenKeyExW(hKey, pStr, 0, KEY_READ, &hSubKey) != ERROR_SUCCESS)
297 {
298 // no plugin for that set exists
299 CoTaskMemFree(pStr);
300 continue;
301 }
302
303 // try load plugin
304 hr = CoCreateInstance(pGuids[Index], (IBaseFilter*)this, CLSCTX_INPROC_SERVER, IID_IUnknown, (void**)&pUnknown);
305 if (SUCCEEDED(hr))
306 {
307 // store plugin
308 m_Plugins.push_back(pUnknown);
309 }
310 // close key
311 RegCloseKey(hSubKey);
312 }
313
314 // close media interfaces key
315 RegCloseKey(hKey);
316 return S_OK;
317 }
318
319 HRESULT
320 STDMETHODCALLTYPE
321 CKsProxy::GetNumberOfPins(
322 PULONG NumPins)
323 {
324 KSPROPERTY Property;
325 ULONG BytesReturned;
326
327 // setup request
328 Property.Set = KSPROPSETID_Pin;
329 Property.Id = KSPROPERTY_PIN_CTYPES;
330 Property.Flags = KSPROPERTY_TYPE_GET;
331
332 return KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)NumPins, sizeof(ULONG), &BytesReturned);
333 }
334
335 HRESULT
336 STDMETHODCALLTYPE
337 CKsProxy::GetPinInstanceCount(
338 ULONG PinId,
339 PKSPIN_CINSTANCES Instances)
340 {
341 KSP_PIN Property;
342 ULONG BytesReturned;
343
344 // setup request
345 Property.Property.Set = KSPROPSETID_Pin;
346 Property.Property.Id = KSPROPERTY_PIN_CINSTANCES;
347 Property.Property.Flags = KSPROPERTY_TYPE_GET;
348 Property.PinId = PinId;
349 Property.Reserved = 0;
350
351 return KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSP_PIN), (PVOID)Instances, sizeof(KSPIN_CINSTANCES), &BytesReturned);
352 }
353
354 HRESULT
355 STDMETHODCALLTYPE
356 CKsProxy::GetPinCommunication(
357 ULONG PinId,
358 KSPIN_COMMUNICATION * Communication)
359 {
360 KSP_PIN Property;
361 ULONG BytesReturned;
362
363 // setup request
364 Property.Property.Set = KSPROPSETID_Pin;
365 Property.Property.Id = KSPROPERTY_PIN_COMMUNICATION;
366 Property.Property.Flags = KSPROPERTY_TYPE_GET;
367 Property.PinId = PinId;
368 Property.Reserved = 0;
369
370 return KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSP_PIN), (PVOID)Communication, sizeof(KSPIN_COMMUNICATION), &BytesReturned);
371 }
372
373 HRESULT
374 STDMETHODCALLTYPE
375 CKsProxy::GetPinDataflow(
376 ULONG PinId,
377 KSPIN_DATAFLOW * DataFlow)
378 {
379 KSP_PIN Property;
380 ULONG BytesReturned;
381
382 // setup request
383 Property.Property.Set = KSPROPSETID_Pin;
384 Property.Property.Id = KSPROPERTY_PIN_DATAFLOW;
385 Property.Property.Flags = KSPROPERTY_TYPE_GET;
386 Property.PinId = PinId;
387 Property.Reserved = 0;
388
389 return KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSP_PIN), (PVOID)DataFlow, sizeof(KSPIN_DATAFLOW), &BytesReturned);
390 }
391
392 HRESULT
393 STDMETHODCALLTYPE
394 CKsProxy::GetPinName(
395 ULONG PinId,
396 KSPIN_DATAFLOW DataFlow,
397 ULONG PinCount,
398 LPWSTR * OutPinName)
399 {
400 KSP_PIN Property;
401 LPWSTR PinName;
402 ULONG BytesReturned;
403 HRESULT hr;
404 WCHAR Buffer[100];
405
406 // setup request
407 Property.Property.Set = KSPROPSETID_Pin;
408 Property.Property.Id = KSPROPERTY_PIN_NAME;
409 Property.Property.Flags = KSPROPERTY_TYPE_GET;
410 Property.PinId = PinId;
411 Property.Reserved = 0;
412
413 // #1 try get it from pin directly
414 hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSP_PIN), NULL, 0, &BytesReturned);
415
416 if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_MORE_DATA))
417 {
418 // allocate pin name
419 PinName = (LPWSTR)CoTaskMemAlloc(BytesReturned);
420 if (!PinName)
421 return E_OUTOFMEMORY;
422
423 // retry with allocated buffer
424 hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSP_PIN), PinName, BytesReturned, &BytesReturned);
425 if (SUCCEEDED(hr))
426 {
427 *OutPinName = PinName;
428 return hr;
429 }
430
431 //free buffer
432 CoTaskMemFree(PinName);
433 }
434
435 //
436 // TODO: retrieve pin name from topology node
437 //
438
439 if (DataFlow == KSPIN_DATAFLOW_IN)
440 {
441 swprintf(Buffer, L"Input%lu", PinCount);
442 }
443 else
444 {
445 swprintf(Buffer, L"Output%lu", PinCount);
446 }
447
448 // allocate pin name
449 PinName = (LPWSTR)CoTaskMemAlloc((wcslen(Buffer)+1) * sizeof(WCHAR));
450 if (!PinName)
451 return E_OUTOFMEMORY;
452
453 // copy pin name
454 wcscpy(PinName, Buffer);
455
456 // store result
457 *OutPinName = PinName;
458 // done
459 return S_OK;
460 }
461
462 HRESULT
463 STDMETHODCALLTYPE
464 CKsProxy::CreatePins()
465 {
466 ULONG NumPins, Index;
467 KSPIN_CINSTANCES Instances;
468 KSPIN_DATAFLOW DataFlow;
469 KSPIN_COMMUNICATION Communication;
470 HRESULT hr;
471 WCHAR Buffer[100];
472 LPWSTR PinName;
473 IPin * pPin;
474 ULONG InputPin = 0;
475 ULONG OutputPin = 0;
476
477 // get number of pins
478 hr = GetNumberOfPins(&NumPins);
479 if (FAILED(hr))
480 return hr;
481
482 for(Index = 0; Index < NumPins; Index++)
483 {
484 // query current instance count
485 hr = GetPinInstanceCount(Index, &Instances);
486 if (FAILED(hr))
487 continue;
488
489 // query pin communication;
490 hr = GetPinCommunication(Index, &Communication);
491 if (FAILED(hr))
492 continue;
493
494 if (Instances.CurrentCount == Instances.PossibleCount)
495 {
496 // already maximum reached for this pin
497 continue;
498 }
499
500 // get direction of pin
501 hr = GetPinDataflow(Index, &DataFlow);
502 if (FAILED(hr))
503 continue;
504
505 if (DataFlow == KSPIN_DATAFLOW_IN)
506 hr = GetPinName(Index, DataFlow, InputPin, &PinName);
507 else
508 hr = GetPinName(Index, DataFlow, OutputPin, &PinName);
509
510 if (FAILED(hr))
511 continue;
512
513 // construct the pins
514 if (DataFlow == KSPIN_DATAFLOW_IN)
515 {
516 hr = CInputPin_Constructor((IBaseFilter*)this, PinName, m_hDevice, Index, Communication, IID_IPin, (void**)&pPin);
517 if (FAILED(hr))
518 {
519 CoTaskMemFree(PinName);
520 continue;
521 }
522 InputPin++;
523 }
524 else
525 {
526 hr = COutputPin_Constructor((IBaseFilter*)this, PinName, IID_IPin, (void**)&pPin);
527 if (FAILED(hr))
528 {
529 CoTaskMemFree(PinName);
530 continue;
531 }
532 OutputPin++;
533 }
534
535 // store pins
536 m_Pins.push_back(pPin);
537
538 swprintf(Buffer, L"Index %lu DataFlow %lu Name %s\n", Index, DataFlow, PinName);
539 OutputDebugStringW(Buffer);
540 }
541
542 return S_OK;
543 }
544
545 HRESULT
546 STDMETHODCALLTYPE
547 CKsProxy::Load(IPropertyBag *pPropBag, IErrorLog *pErrorLog)
548 {
549 HRESULT hr;
550 WCHAR Buffer[100];
551 VARIANT varName;
552 LPGUID pGuid;
553 ULONG NumGuids = 0;
554
555 // read device path
556 varName.vt = VT_BSTR;
557 hr = pPropBag->Read(L"DevicePath", &varName, pErrorLog);
558
559 if (FAILED(hr))
560 {
561 swprintf(Buffer, L"CKsProxy::Load Read %lx\n", hr);
562 OutputDebugStringW(Buffer);
563 return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, GetLastError());
564 }
565
566 // open device
567 m_hDevice = CreateFileW(varName.bstrVal, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
568
569 if (m_hDevice == INVALID_HANDLE_VALUE)
570 {
571 // failed to open device
572 swprintf(Buffer, L"CKsProxy:: failed to open device with %lx\n", GetLastError());
573 OutputDebugStringW(Buffer);
574
575 return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, GetLastError());
576 }
577
578 // get all supported sets
579 hr = GetSupportedSets(&pGuid, &NumGuids);
580 if (FAILED(hr))
581 {
582 CloseHandle(m_hDevice);
583 m_hDevice = NULL;
584 return hr;
585 }
586
587 // load all proxy plugins
588 hr = LoadProxyPlugins(pGuid, NumGuids);
589 if (FAILED(hr))
590 {
591 CloseHandle(m_hDevice);
592 m_hDevice = NULL;
593 return hr;
594 }
595
596 // free sets
597 CoTaskMemFree(pGuid);
598
599 // now create the input / output pins
600 hr = CreatePins();
601
602 return hr;
603 }
604
605 HRESULT
606 STDMETHODCALLTYPE
607 CKsProxy::Save(IPropertyBag *pPropBag, BOOL fClearDirty, BOOL fSaveAllProperties)
608 {
609 return E_NOTIMPL;
610 }
611
612 //-------------------------------------------------------------------
613 // IBaseFilter interface
614 //
615
616 HRESULT
617 STDMETHODCALLTYPE
618 CKsProxy::GetClassID(
619 CLSID *pClassID)
620 {
621 OutputDebugStringW(L"CKsProxy::GetClassID : NotImplemented\n");
622 return E_NOTIMPL;
623 }
624
625 HRESULT
626 STDMETHODCALLTYPE
627 CKsProxy::Stop()
628 {
629 OutputDebugStringW(L"CKsProxy::Stop : NotImplemented\n");
630 return E_NOTIMPL;
631 }
632
633 HRESULT
634 STDMETHODCALLTYPE
635 CKsProxy::Pause()
636 {
637 OutputDebugStringW(L"CKsProxy::Pause : NotImplemented\n");
638 return E_NOTIMPL;
639 }
640
641 HRESULT
642 STDMETHODCALLTYPE
643 CKsProxy::Run(
644 REFERENCE_TIME tStart)
645 {
646 OutputDebugStringW(L"CKsProxy::Run : NotImplemented\n");
647 return E_NOTIMPL;
648 }
649
650 HRESULT
651 STDMETHODCALLTYPE
652 CKsProxy::GetState(
653 DWORD dwMilliSecsTimeout,
654 FILTER_STATE *State)
655 {
656 *State = m_FilterState;
657 return S_OK;
658 }
659
660 HRESULT
661 STDMETHODCALLTYPE
662 CKsProxy::SetSyncSource(
663 IReferenceClock *pClock)
664 {
665 if (pClock)
666 {
667 pClock->AddRef();
668 }
669
670 if (m_ReferenceClock)
671 {
672 m_ReferenceClock->Release();
673 }
674
675 m_ReferenceClock = pClock;
676 return S_OK;
677 }
678
679 HRESULT
680 STDMETHODCALLTYPE
681 CKsProxy::GetSyncSource(
682 IReferenceClock **pClock)
683 {
684 if (!pClock)
685 return E_POINTER;
686
687 if (m_ReferenceClock)
688 m_ReferenceClock->AddRef();
689
690 *pClock = m_ReferenceClock;
691 return S_OK;
692 }
693
694 HRESULT
695 STDMETHODCALLTYPE
696 CKsProxy::EnumPins(
697 IEnumPins **ppEnum)
698 {
699 return CEnumPins_fnConstructor(m_Pins, IID_IEnumPins, (void**)ppEnum);
700 }
701
702 HRESULT
703 STDMETHODCALLTYPE
704 CKsProxy::FindPin(
705 LPCWSTR Id, IPin **ppPin)
706 {
707 ULONG PinId;
708
709 if (!ppPin)
710 return E_POINTER;
711
712 // convert to pin
713 int ret = swscanf(Id, L"%u", &PinId);
714
715 if (!ret || ret == EOF)
716 {
717 // invalid id
718 return VFW_E_NOT_FOUND;
719 }
720
721 if (PinId >= m_Pins.size() || m_Pins[PinId] == NULL)
722 {
723 // invalid id
724 return VFW_E_NOT_FOUND;
725 }
726
727 // found pin
728 *ppPin = m_Pins[PinId];
729 m_Pins[PinId]->AddRef();
730
731 return S_OK;
732 }
733
734
735 HRESULT
736 STDMETHODCALLTYPE
737 CKsProxy::QueryFilterInfo(
738 FILTER_INFO *pInfo)
739 {
740 if (!pInfo)
741 return E_POINTER;
742
743 pInfo->achName[0] = L'\0';
744 pInfo->pGraph = m_pGraph;
745
746 return S_OK;
747 }
748
749 HRESULT
750 STDMETHODCALLTYPE
751 CKsProxy::JoinFilterGraph(
752 IFilterGraph *pGraph,
753 LPCWSTR pName)
754 {
755 if (pGraph)
756 {
757 // joining filter graph
758 m_pGraph = pGraph;
759 }
760 else
761 {
762 // leaving graph
763 m_pGraph = 0;
764 }
765
766 return S_OK;
767 }
768
769
770 HRESULT
771 STDMETHODCALLTYPE
772 CKsProxy::QueryVendorInfo(
773 LPWSTR *pVendorInfo)
774 {
775 OutputDebugStringW(L"CKsProxy::QueryVendorInfo : NotImplemented\n");
776 return E_NOTIMPL;
777 }
778
779 //-------------------------------------------------------------------
780 // IAMovieSetup interface
781 //
782
783 HRESULT
784 STDMETHODCALLTYPE
785 CKsProxy::Register()
786 {
787 OutputDebugStringW(L"CKsProxy::Register : NotImplemented\n");
788 return E_NOTIMPL;
789 }
790
791 HRESULT
792 STDMETHODCALLTYPE
793 CKsProxy::Unregister()
794 {
795 OutputDebugStringW(L"CKsProxy::Unregister : NotImplemented\n");
796 return E_NOTIMPL;
797 }
798
799 HRESULT
800 WINAPI
801 CKsProxy_Constructor(
802 IUnknown * pUnkOuter,
803 REFIID riid,
804 LPVOID * ppv)
805 {
806 WCHAR Buffer[100];
807 LPOLESTR pstr;
808 StringFromCLSID(riid, &pstr);
809 swprintf(Buffer, L"CKsProxy_Constructor pUnkOuter %p riid %s\n", pUnkOuter, pstr);
810 OutputDebugStringW(Buffer);
811
812 CKsProxy * handler = new CKsProxy();
813
814 if (!handler)
815 return E_OUTOFMEMORY;
816
817 if (FAILED(handler->QueryInterface(riid, ppv)))
818 {
819 /* not supported */
820 delete handler;
821 return E_NOINTERFACE;
822 }
823
824 return S_OK;
825 }