xref: /reactos/dll/directx/ksproxy/input_pin.cpp (revision b09b5584)
1 /*
2  * COPYRIGHT:       See COPYING in the top level directory
3  * PROJECT:         ReactOS WDM Streaming ActiveMovie Proxy
4  * FILE:            dll/directx/ksproxy/input_pin.cpp
5  * PURPOSE:         InputPin of Proxy Filter
6  *
7  * PROGRAMMERS:     Johannes Anderwald (johannes.anderwald@reactos.org)
8  */
9 #include "precomp.h"
10 
11 const GUID IID_IKsPinPipe = {0xe539cd90, 0xa8b4, 0x11d1, {0x81, 0x89, 0x00, 0xa0, 0xc9, 0x06, 0x28, 0x02}};
12 const GUID IID_IKsPinEx   = {0x7bb38260L, 0xd19c, 0x11d2, {0xb3, 0x8a, 0x00, 0xa0, 0xc9, 0x5e, 0xc2, 0x2e}};
13 
14 KSPIN_INTERFACE StandardPinInterface =
15 {
16     {STATIC_KSINTERFACESETID_Standard},
17     KSINTERFACE_STANDARD_STREAMING,
18     0
19 };
20 
21 KSPIN_MEDIUM StandardPinMedium =
22 {
23     {STATIC_KSMEDIUMSETID_Standard},
24     KSMEDIUM_TYPE_ANYINSTANCE,
25     0
26 };
27 
28 class CInputPin : public IPin,
29                   public IKsPropertySet,
30                   public IKsControl,
31                   public IKsObject,
32                   public IKsPinEx,
33                   public IMemInputPin,
34                   public IKsPinPipe,
35                   public IKsPinFactory,
36                   public IStreamBuilder,
37                   public IKsAggregateControl,
38                   public IQualityControl,
39                   public ISpecifyPropertyPages
40 {
41 public:
42     typedef std::vector<IUnknown *>ProxyPluginVector;
43 
44     STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
45 
46     STDMETHODIMP_(ULONG) AddRef()
47     {
48         InterlockedIncrement(&m_Ref);
49         return m_Ref;
50     }
51     STDMETHODIMP_(ULONG) Release()
52     {
53         InterlockedDecrement(&m_Ref);
54         if (!m_Ref)
55         {
56             delete this;
57             return 0;
58         }
59         return m_Ref;
60     }
61 
62     //IKsPinPipe
63     HRESULT STDMETHODCALLTYPE KsGetPinFramingCache(PKSALLOCATOR_FRAMING_EX *FramingEx, PFRAMING_PROP FramingProp, FRAMING_CACHE_OPS Option);
64     HRESULT STDMETHODCALLTYPE KsSetPinFramingCache(PKSALLOCATOR_FRAMING_EX FramingEx, PFRAMING_PROP FramingProp, FRAMING_CACHE_OPS Option);
65     IPin* STDMETHODCALLTYPE KsGetConnectedPin();
66     IKsAllocatorEx* STDMETHODCALLTYPE KsGetPipe(KSPEEKOPERATION Operation);
67     HRESULT STDMETHODCALLTYPE KsSetPipe(IKsAllocatorEx *KsAllocator);
68     ULONG STDMETHODCALLTYPE KsGetPipeAllocatorFlag();
69     HRESULT STDMETHODCALLTYPE KsSetPipeAllocatorFlag(ULONG Flag);
70     GUID STDMETHODCALLTYPE KsGetPinBusCache();
71     HRESULT STDMETHODCALLTYPE KsSetPinBusCache(GUID Bus);
72     PWCHAR STDMETHODCALLTYPE KsGetPinName();
73     PWCHAR STDMETHODCALLTYPE KsGetFilterName();
74 
75     //IPin methods
76     HRESULT STDMETHODCALLTYPE Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt);
77     HRESULT STDMETHODCALLTYPE ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt);
78     HRESULT STDMETHODCALLTYPE Disconnect();
79     HRESULT STDMETHODCALLTYPE ConnectedTo(IPin **pPin);
80     HRESULT STDMETHODCALLTYPE ConnectionMediaType(AM_MEDIA_TYPE *pmt);
81     HRESULT STDMETHODCALLTYPE QueryPinInfo(PIN_INFO *pInfo);
82     HRESULT STDMETHODCALLTYPE QueryDirection(PIN_DIRECTION *pPinDir);
83     HRESULT STDMETHODCALLTYPE QueryId(LPWSTR *Id);
84     HRESULT STDMETHODCALLTYPE QueryAccept(const AM_MEDIA_TYPE *pmt);
85     HRESULT STDMETHODCALLTYPE EnumMediaTypes(IEnumMediaTypes **ppEnum);
86     HRESULT STDMETHODCALLTYPE QueryInternalConnections(IPin **apPin, ULONG *nPin);
87     HRESULT STDMETHODCALLTYPE EndOfStream();
88     HRESULT STDMETHODCALLTYPE BeginFlush();
89     HRESULT STDMETHODCALLTYPE EndFlush();
90     HRESULT STDMETHODCALLTYPE NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate);
91 
92     // ISpecifyPropertyPages
93     HRESULT STDMETHODCALLTYPE GetPages(CAUUID *pPages);
94 
95     //IKsObject methods
96     HANDLE STDMETHODCALLTYPE KsGetObjectHandle();
97 
98     //IKsPropertySet
99     HRESULT STDMETHODCALLTYPE Set(REFGUID guidPropSet, DWORD dwPropID, LPVOID pInstanceData, DWORD cbInstanceData, LPVOID pPropData, DWORD cbPropData);
100     HRESULT STDMETHODCALLTYPE Get(REFGUID guidPropSet, DWORD dwPropID, LPVOID pInstanceData, DWORD cbInstanceData, LPVOID pPropData, DWORD cbPropData, DWORD *pcbReturned);
101     HRESULT STDMETHODCALLTYPE QuerySupported(REFGUID guidPropSet, DWORD dwPropID, DWORD *pTypeSupport);
102 
103     //IKsControl
104     HRESULT STDMETHODCALLTYPE KsProperty(PKSPROPERTY Property, ULONG PropertyLength, LPVOID PropertyData, ULONG DataLength, ULONG* BytesReturned);
105     HRESULT STDMETHODCALLTYPE KsMethod(PKSMETHOD Method, ULONG MethodLength, LPVOID MethodData, ULONG DataLength, ULONG* BytesReturned);
106     HRESULT STDMETHODCALLTYPE KsEvent(PKSEVENT Event, ULONG EventLength, LPVOID EventData, ULONG DataLength, ULONG* BytesReturned);
107 
108     //IKsPin
109     HRESULT STDMETHODCALLTYPE KsQueryMediums(PKSMULTIPLE_ITEM* MediumList);
110     HRESULT STDMETHODCALLTYPE KsQueryInterfaces(PKSMULTIPLE_ITEM* InterfaceList);
111     HRESULT STDMETHODCALLTYPE KsCreateSinkPinHandle(KSPIN_INTERFACE& Interface, KSPIN_MEDIUM& Medium);
112     HRESULT STDMETHODCALLTYPE KsGetCurrentCommunication(KSPIN_COMMUNICATION *Communication, KSPIN_INTERFACE *Interface, KSPIN_MEDIUM *Medium);
113     HRESULT STDMETHODCALLTYPE KsPropagateAcquire();
114     HRESULT STDMETHODCALLTYPE KsDeliver(IMediaSample* Sample, ULONG Flags);
115     HRESULT STDMETHODCALLTYPE KsMediaSamplesCompleted(PKSSTREAM_SEGMENT StreamSegment);
116     IMemAllocator * STDMETHODCALLTYPE KsPeekAllocator(KSPEEKOPERATION Operation);
117     HRESULT STDMETHODCALLTYPE KsReceiveAllocator(IMemAllocator *MemAllocator);
118     HRESULT STDMETHODCALLTYPE KsRenegotiateAllocator();
119     LONG STDMETHODCALLTYPE KsIncrementPendingIoCount();
120     LONG STDMETHODCALLTYPE KsDecrementPendingIoCount();
121     HRESULT STDMETHODCALLTYPE KsQualityNotify(ULONG Proportion, REFERENCE_TIME TimeDelta);
122     // IKsPinEx
123     VOID STDMETHODCALLTYPE KsNotifyError(IMediaSample* Sample, HRESULT hr);
124 
125     //IMemInputPin
126     HRESULT STDMETHODCALLTYPE GetAllocator(IMemAllocator **ppAllocator);
127     HRESULT STDMETHODCALLTYPE NotifyAllocator(IMemAllocator *pAllocator, BOOL bReadOnly);
128     HRESULT STDMETHODCALLTYPE GetAllocatorRequirements(ALLOCATOR_PROPERTIES *pProps);
129     HRESULT STDMETHODCALLTYPE Receive(IMediaSample *pSample);
130     HRESULT STDMETHODCALLTYPE ReceiveMultiple(IMediaSample **pSamples, long nSamples, long *nSamplesProcessed);
131     HRESULT STDMETHODCALLTYPE ReceiveCanBlock( void);
132 
133     //IKsPinFactory
134     HRESULT STDMETHODCALLTYPE KsPinFactory(ULONG* PinFactory);
135 
136     //IStreamBuilder
137     HRESULT STDMETHODCALLTYPE Render(IPin *ppinOut, IGraphBuilder *pGraph);
138     HRESULT STDMETHODCALLTYPE Backout(IPin *ppinOut, IGraphBuilder *pGraph);
139 
140     //IKsAggregateControl
141     HRESULT STDMETHODCALLTYPE KsAddAggregate(IN REFGUID AggregateClass);
142     HRESULT STDMETHODCALLTYPE KsRemoveAggregate(REFGUID AggregateClass);
143 
144     //IQualityControl
145     HRESULT STDMETHODCALLTYPE Notify(IBaseFilter *pSelf, Quality q);
146     HRESULT STDMETHODCALLTYPE SetSink(IQualityControl *piqc);
147 
148     //---------------------------------------------------------------
149     HRESULT STDMETHODCALLTYPE CheckFormat(const AM_MEDIA_TYPE *pmt);
150     HRESULT STDMETHODCALLTYPE CreatePin(const AM_MEDIA_TYPE *pmt);
151     HRESULT STDMETHODCALLTYPE CreatePinHandle(PKSPIN_MEDIUM Medium, PKSPIN_INTERFACE Interface, const AM_MEDIA_TYPE *pmt);
152     HRESULT STDMETHODCALLTYPE GetSupportedSets(LPGUID * pOutGuid, PULONG NumGuids);
153     HRESULT STDMETHODCALLTYPE LoadProxyPlugins(LPGUID pGuids, ULONG NumGuids);
154     CInputPin(IBaseFilter * ParentFilter, LPCWSTR PinName, ULONG PinId, KSPIN_COMMUNICATION Communication);
155     virtual ~CInputPin(){};
156 
157 protected:
158     LONG m_Ref;
159     IBaseFilter * m_ParentFilter;
160     LPCWSTR m_PinName;
161     HANDLE m_hPin;
162     ULONG m_PinId;
163     IMemAllocator * m_MemAllocator;
164     LONG m_IoCount;
165     KSPIN_COMMUNICATION m_Communication;
166     KSPIN_INTERFACE m_Interface;
167     KSPIN_MEDIUM m_Medium;
168     AM_MEDIA_TYPE m_MediaFormat;
169     IPin * m_Pin;
170     BOOL m_ReadOnly;
171     IKsInterfaceHandler * m_InterfaceHandler;
172     IKsAllocatorEx * m_KsAllocatorEx;
173     ULONG m_PipeAllocatorFlag;
174     BOOL m_bPinBusCacheInitialized;
175     GUID m_PinBusCache;
176     LPWSTR m_FilterName;
177     FRAMING_PROP m_FramingProp[4];
178     PKSALLOCATOR_FRAMING_EX m_FramingEx[4];
179     ProxyPluginVector m_Plugins;
180 };
181 
182 CInputPin::CInputPin(
183     IBaseFilter * ParentFilter,
184     LPCWSTR PinName,
185     ULONG PinId,
186     KSPIN_COMMUNICATION Communication) : m_Ref(0),
187                                          m_ParentFilter(ParentFilter),
188                                          m_PinName(PinName),
189                                          m_hPin(INVALID_HANDLE_VALUE),
190                                          m_PinId(PinId),
191                                          m_MemAllocator(0),
192                                          m_IoCount(0),
193                                          m_Communication(Communication),
194                                          m_Pin(0),
195                                          m_ReadOnly(0),
196                                          m_InterfaceHandler(0),
197                                          m_KsAllocatorEx(0),
198                                          m_PipeAllocatorFlag(0),
199                                          m_bPinBusCacheInitialized(0),
200                                          m_FilterName(0),
201                                          m_Plugins()
202 {
203     ZeroMemory(m_FramingProp, sizeof(m_FramingProp));
204     ZeroMemory(m_FramingEx, sizeof(m_FramingEx));
205 
206     HRESULT hr;
207     IKsObject * KsObjectParent;
208     HANDLE hFilter;
209 
210     hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent);
211     assert(hr == S_OK);
212 
213     hFilter = KsObjectParent->KsGetObjectHandle();
214     assert(hFilter);
215 
216     KsObjectParent->Release();
217 
218 
219     ZeroMemory(&m_MediaFormat, sizeof(AM_MEDIA_TYPE));
220     hr = KsGetMediaType(0, &m_MediaFormat, hFilter, m_PinId);
221     assert(hr == S_OK);
222 }
223 
224 HRESULT
225 STDMETHODCALLTYPE
226 CInputPin::QueryInterface(
227     IN  REFIID refiid,
228     OUT PVOID* Output)
229 {
230     WCHAR Buffer[100];
231 
232     *Output = NULL;
233 
234     if (IsEqualGUID(refiid, IID_IUnknown) ||
235         IsEqualGUID(refiid, IID_IPin))
236     {
237         *Output = PVOID(this);
238         reinterpret_cast<IUnknown*>(*Output)->AddRef();
239         return NOERROR;
240     }
241     else if (IsEqualGUID(refiid, IID_IMemInputPin))
242     {
243         if (m_hPin == INVALID_HANDLE_VALUE)
244         {
245             HRESULT hr = CreatePin(&m_MediaFormat);
246             if (FAILED(hr))
247                 return hr;
248         }
249 
250         *Output = (IMemInputPin*)(this);
251         reinterpret_cast<IMemInputPin*>(*Output)->AddRef();
252         return NOERROR;
253     }
254     else if (IsEqualGUID(refiid, IID_IKsObject))
255     {
256         *Output = (IKsObject*)(this);
257         reinterpret_cast<IKsObject*>(*Output)->AddRef();
258         return NOERROR;
259     }
260     else if (IsEqualGUID(refiid, IID_IKsPropertySet))
261     {
262         if (m_hPin == INVALID_HANDLE_VALUE)
263         {
264             HRESULT hr = CreatePin(&m_MediaFormat);
265             if (FAILED(hr))
266                 return hr;
267         }
268 
269         *Output = (IKsPropertySet*)(this);
270         reinterpret_cast<IKsPropertySet*>(*Output)->AddRef();
271         return NOERROR;
272     }
273     else if (IsEqualGUID(refiid, IID_IKsControl))
274     {
275         *Output = (IKsControl*)(this);
276         reinterpret_cast<IKsControl*>(*Output)->AddRef();
277         return NOERROR;
278     }
279     else if (IsEqualGUID(refiid, IID_IKsPin) ||
280              IsEqualGUID(refiid, IID_IKsPinEx))
281     {
282         *Output = (IKsPinEx*)(this);
283         reinterpret_cast<IKsPinEx*>(*Output)->AddRef();
284         return NOERROR;
285     }
286     else if (IsEqualGUID(refiid, IID_IKsPinPipe))
287     {
288         *Output = (IKsPinPipe*)(this);
289         reinterpret_cast<IKsPinPipe*>(*Output)->AddRef();
290         return NOERROR;
291     }
292     else if (IsEqualGUID(refiid, IID_IKsPinFactory))
293     {
294         *Output = (IKsPinFactory*)(this);
295         reinterpret_cast<IKsPinFactory*>(*Output)->AddRef();
296         return NOERROR;
297     }
298 #if 0
299     else if (IsEqualGUID(refiid, IID_IStreamBuilder))
300     {
301         *Output = (IStreamBuilder*)(this);
302         reinterpret_cast<IStreamBuilder*>(*Output)->AddRef();
303         return NOERROR;
304     }
305 #endif
306     else if (IsEqualGUID(refiid, IID_IKsAggregateControl))
307     {
308         *Output = (IKsAggregateControl*)(this);
309         reinterpret_cast<IKsAggregateControl*>(*Output)->AddRef();
310         return NOERROR;
311     }
312     else if (IsEqualGUID(refiid, IID_IQualityControl))
313     {
314         *Output = (IQualityControl*)(this);
315         reinterpret_cast<IQualityControl*>(*Output)->AddRef();
316         return NOERROR;
317     }
318     else if (IsEqualGUID(refiid, IID_ISpecifyPropertyPages))
319     {
320         *Output = (ISpecifyPropertyPages*)(this);
321         reinterpret_cast<ISpecifyPropertyPages*>(*Output)->AddRef();
322         return NOERROR;
323     }
324 
325     LPOLESTR lpstr;
326     StringFromCLSID(refiid, &lpstr);
327     swprintf(Buffer, L"CInputPin::QueryInterface: NoInterface for %s\n", lpstr);
328     OutputDebugStringW(Buffer);
329     CoTaskMemFree(lpstr);
330 
331     return E_NOINTERFACE;
332 }
333 //-------------------------------------------------------------------
334 // IQualityControl interface
335 //
336 HRESULT
337 STDMETHODCALLTYPE
338 CInputPin::Notify(
339     IBaseFilter *pSelf,
340     Quality q)
341 {
342 #ifdef KSPROXY_TRACE
343     OutputDebugStringW(L"CInputPin::Notify NotImplemented\n");
344 #endif
345 
346     return E_NOTIMPL;
347 }
348 
349 HRESULT
350 STDMETHODCALLTYPE
351 CInputPin::SetSink(
352     IQualityControl *piqc)
353 {
354 #ifdef KSPROXY_TRACE
355     OutputDebugStringW(L"CInputPin::SetSink NotImplemented\n");
356 #endif
357 
358     return E_NOTIMPL;
359 }
360 
361 
362 //-------------------------------------------------------------------
363 // IKsAggregateControl interface
364 //
365 HRESULT
366 STDMETHODCALLTYPE
367 CInputPin::KsAddAggregate(
368     IN REFGUID AggregateClass)
369 {
370 #ifdef KSPROXY_TRACE
371     OutputDebugStringW(L"CInputPin::KsAddAggregate NotImplemented\n");
372 #endif
373 
374     return E_NOTIMPL;
375 }
376 
377 HRESULT
378 STDMETHODCALLTYPE
379 CInputPin::KsRemoveAggregate(
380     REFGUID AggregateClass)
381 {
382 #ifdef KSPROXY_TRACE
383     OutputDebugStringW(L"CInputPin::KsRemoveAggregate NotImplemented\n");
384 #endif
385 
386     return E_NOTIMPL;
387 }
388 
389 //-------------------------------------------------------------------
390 // IStreamBuilder
391 //
392 
393 HRESULT
394 STDMETHODCALLTYPE
395 CInputPin::Render(
396     IPin *ppinOut,
397     IGraphBuilder *pGraph)
398 {
399     OutputDebugStringW(L"CInputPin::Render\n");
400     return S_OK;
401 }
402 
403 HRESULT
404 STDMETHODCALLTYPE
405 CInputPin::Backout(
406     IPin *ppinOut,
407     IGraphBuilder *pGraph)
408 {
409 #ifdef KSPROXY_TRACE
410     OutputDebugStringW(L"CInputPin::Backout\n");
411 #endif
412 
413     return S_OK;
414 }
415 
416 //-------------------------------------------------------------------
417 // IKsPinFactory
418 //
419 
420 HRESULT
421 STDMETHODCALLTYPE
422 CInputPin::KsPinFactory(
423     ULONG* PinFactory)
424 {
425 #ifdef KSPROXY_TRACE
426     OutputDebugStringW(L"CInputPin::KsPinFactory\n");
427 #endif
428 
429     *PinFactory = m_PinId;
430     return S_OK;
431 }
432 
433 //-------------------------------------------------------------------
434 // IKsPinPipe
435 //
436 
437 HRESULT
438 STDMETHODCALLTYPE
439 CInputPin::KsGetPinFramingCache(
440     PKSALLOCATOR_FRAMING_EX *FramingEx,
441     PFRAMING_PROP FramingProp,
442     FRAMING_CACHE_OPS Option)
443 {
444     if (Option > Framing_Cache_Write || Option < Framing_Cache_ReadLast)
445     {
446         // invalid argument
447         return E_INVALIDARG;
448     }
449 
450     // get framing properties
451     *FramingProp = m_FramingProp[Option];
452     *FramingEx = m_FramingEx[Option];
453 
454     return NOERROR;
455 }
456 
457 HRESULT
458 STDMETHODCALLTYPE
459 CInputPin::KsSetPinFramingCache(
460     PKSALLOCATOR_FRAMING_EX FramingEx,
461     PFRAMING_PROP FramingProp,
462     FRAMING_CACHE_OPS Option)
463 {
464     ULONG Index;
465     ULONG RefCount = 0;
466 
467     if (m_FramingEx[Option])
468     {
469         for(Index = 1; Index < 4; Index++)
470         {
471             if (m_FramingEx[Index] == m_FramingEx[Option])
472                 RefCount++;
473         }
474 
475         if (RefCount == 1)
476         {
477             // existing framing is only used once
478             CoTaskMemFree(m_FramingEx[Option]);
479         }
480     }
481 
482     // store framing
483     m_FramingEx[Option] = FramingEx;
484     m_FramingProp[Option] = *FramingProp;
485 
486     return S_OK;
487 }
488 
489 IPin*
490 STDMETHODCALLTYPE
491 CInputPin::KsGetConnectedPin()
492 {
493     return m_Pin;
494 }
495 
496 IKsAllocatorEx*
497 STDMETHODCALLTYPE
498 CInputPin::KsGetPipe(
499     KSPEEKOPERATION Operation)
500 {
501     if (Operation == KsPeekOperation_AddRef)
502     {
503         if (m_KsAllocatorEx)
504             m_KsAllocatorEx->AddRef();
505     }
506     return m_KsAllocatorEx;
507 }
508 
509 HRESULT
510 STDMETHODCALLTYPE
511 CInputPin::KsSetPipe(
512     IKsAllocatorEx *KsAllocator)
513 {
514     if (KsAllocator)
515         KsAllocator->AddRef();
516 
517     if (m_KsAllocatorEx)
518         m_KsAllocatorEx->Release();
519 
520     m_KsAllocatorEx = KsAllocator;
521     return NOERROR;
522 }
523 
524 ULONG
525 STDMETHODCALLTYPE
526 CInputPin::KsGetPipeAllocatorFlag()
527 {
528     return m_PipeAllocatorFlag;
529 }
530 
531 
532 HRESULT
533 STDMETHODCALLTYPE
534 CInputPin::KsSetPipeAllocatorFlag(
535     ULONG Flag)
536 {
537     m_PipeAllocatorFlag = Flag;
538     return NOERROR;
539 }
540 
541 GUID
542 STDMETHODCALLTYPE
543 CInputPin::KsGetPinBusCache()
544 {
545     if (!m_bPinBusCacheInitialized)
546     {
547         CopyMemory(&m_PinBusCache, &m_Medium.Set, sizeof(GUID));
548         m_bPinBusCacheInitialized = TRUE;
549     }
550 
551     return m_PinBusCache;
552 }
553 
554 HRESULT
555 STDMETHODCALLTYPE
556 CInputPin::KsSetPinBusCache(
557     GUID Bus)
558 {
559     CopyMemory(&m_PinBusCache, &Bus, sizeof(GUID));
560     return NOERROR;
561 }
562 
563 PWCHAR
564 STDMETHODCALLTYPE
565 CInputPin::KsGetPinName()
566 {
567     return (PWCHAR)m_PinName;
568 }
569 
570 
571 PWCHAR
572 STDMETHODCALLTYPE
573 CInputPin::KsGetFilterName()
574 {
575     return m_FilterName;
576 }
577 
578 //-------------------------------------------------------------------
579 // ISpecifyPropertyPages
580 //
581 
582 HRESULT
583 STDMETHODCALLTYPE
584 CInputPin::GetPages(CAUUID *pPages)
585 {
586     if (!pPages)
587         return E_POINTER;
588 
589     pPages->cElems = 0;
590     pPages->pElems = NULL;
591 
592     return S_OK;
593 }
594 
595 //-------------------------------------------------------------------
596 // IMemInputPin
597 //
598 
599 
600 HRESULT
601 STDMETHODCALLTYPE
602 CInputPin::GetAllocator(IMemAllocator **ppAllocator)
603 {
604 #ifdef KSPROXY_TRACE
605     OutputDebugStringW(L"CInputPin::GetAllocator\n");
606 #endif
607 
608     return VFW_E_NO_ALLOCATOR;
609 }
610 
611 HRESULT
612 STDMETHODCALLTYPE
613 CInputPin::NotifyAllocator(IMemAllocator *pAllocator, BOOL bReadOnly)
614 {
615     HRESULT hr;
616     ALLOCATOR_PROPERTIES Properties;
617 
618     hr = pAllocator->GetProperties(&Properties);
619 
620 #ifdef KSPROXY_TRACE
621     WCHAR Buffer[100];
622     swprintf(Buffer, L"CInputPin::NotifyAllocator hr %lx bReadOnly, %u cbAlign %u cbBuffer %u cbPrefix %u cBuffers %u\n", hr, bReadOnly, Properties.cbAlign, Properties.cbBuffer, Properties.cbPrefix, Properties.cBuffers);
623     OutputDebugStringW(Buffer);
624 #endif
625 
626     if (pAllocator)
627     {
628         pAllocator->AddRef();
629     }
630 
631     if (m_MemAllocator)
632     {
633         m_MemAllocator->Release();
634     }
635 
636     m_MemAllocator = pAllocator;
637     m_ReadOnly = bReadOnly;
638     return NOERROR;
639 }
640 
641 HRESULT
642 STDMETHODCALLTYPE
643 CInputPin::GetAllocatorRequirements(ALLOCATOR_PROPERTIES *pProps)
644 {
645     KSALLOCATOR_FRAMING Framing;
646     KSPROPERTY Property;
647     HRESULT hr;
648     ULONG BytesReturned;
649 
650     Property.Set = KSPROPSETID_Connection;
651     Property.Id = KSPROPERTY_CONNECTION_ALLOCATORFRAMING;
652     Property.Flags = KSPROPERTY_TYPE_SET;
653 
654     hr = KsProperty(&Property, sizeof(KSPROPERTY), (PVOID)&Framing, sizeof(KSALLOCATOR_FRAMING), &BytesReturned);
655     if (SUCCEEDED(hr))
656     {
657         pProps->cBuffers = Framing.Frames;
658         pProps->cbBuffer = Framing.FrameSize;
659         pProps->cbAlign = Framing.FileAlignment;
660         pProps->cbPrefix = 0;
661     }
662     else
663         hr = E_NOTIMPL;
664 
665 #ifdef KSPROXY_TRACE
666     WCHAR Buffer[100];
667     swprintf(Buffer, L"CInputPin::GetAllocatorRequirements hr %lx m_hPin %p cBuffers %u cbBuffer %u cbAlign %u cbPrefix %u\n", hr, m_hPin, pProps->cBuffers, pProps->cbBuffer, pProps->cbAlign, pProps->cbPrefix);
668     OutputDebugStringW(Buffer);
669 #endif
670 
671     return hr;
672 }
673 
674 HRESULT
675 STDMETHODCALLTYPE
676 CInputPin::Receive(IMediaSample *pSample)
677 {
678 #ifdef KSPROXY_TRACE
679     OutputDebugStringW(L"CInputPin::Receive NotImplemented\n");
680 #endif
681 
682     return E_NOTIMPL;
683 }
684 
685 HRESULT
686 STDMETHODCALLTYPE
687 CInputPin::ReceiveMultiple(IMediaSample **pSamples, long nSamples, long *nSamplesProcessed)
688 {
689 #ifdef KSPROXY_TRACE
690     OutputDebugStringW(L"CInputPin::ReceiveMultiple NotImplemented\n");
691 #endif
692 
693     return E_NOTIMPL;
694 }
695 
696 HRESULT
697 STDMETHODCALLTYPE
698 CInputPin::ReceiveCanBlock( void)
699 {
700 #ifdef KSPROXY_TRACE
701     OutputDebugStringW(L"CInputPin::ReceiveCanBlock NotImplemented\n");
702 #endif
703 
704     return S_FALSE;
705 }
706 
707 //-------------------------------------------------------------------
708 // IKsPin
709 //
710 
711 HRESULT
712 STDMETHODCALLTYPE
713 CInputPin::KsQueryMediums(
714     PKSMULTIPLE_ITEM* MediumList)
715 {
716     HRESULT hr;
717     IKsObject * KsObjectParent;
718     HANDLE hFilter;
719 
720     hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent);
721     if (FAILED(hr))
722         return hr;
723 
724     hFilter = KsObjectParent->KsGetObjectHandle();
725 
726     KsObjectParent->Release();
727 
728     if (!hFilter)
729         return E_HANDLE;
730 
731     return KsGetMultiplePinFactoryItems(hFilter, m_PinId, KSPROPERTY_PIN_MEDIUMS, (PVOID*)MediumList);
732 }
733 
734 HRESULT
735 STDMETHODCALLTYPE
736 CInputPin::KsQueryInterfaces(
737     PKSMULTIPLE_ITEM* InterfaceList)
738 {
739     HRESULT hr;
740     IKsObject * KsObjectParent;
741     HANDLE hFilter;
742 
743     hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent);
744     if (FAILED(hr))
745         return hr;
746 
747     hFilter = KsObjectParent->KsGetObjectHandle();
748 
749     KsObjectParent->Release();
750 
751     if (!hFilter)
752         return E_HANDLE;
753 
754     return KsGetMultiplePinFactoryItems(hFilter, m_PinId, KSPROPERTY_PIN_INTERFACES, (PVOID*)InterfaceList);
755 }
756 
757 HRESULT
758 STDMETHODCALLTYPE
759 CInputPin::KsCreateSinkPinHandle(
760     KSPIN_INTERFACE& Interface,
761     KSPIN_MEDIUM& Medium)
762 {
763     return CreatePin(&m_MediaFormat);
764 }
765 
766 HRESULT
767 STDMETHODCALLTYPE
768 CInputPin::KsGetCurrentCommunication(
769     KSPIN_COMMUNICATION *Communication,
770     KSPIN_INTERFACE *Interface,
771     KSPIN_MEDIUM *Medium)
772 {
773     if (Communication)
774     {
775         *Communication = m_Communication;
776     }
777 
778     if (Interface)
779     {
780         if (!m_hPin)
781             return VFW_E_NOT_CONNECTED;
782 
783         CopyMemory(Interface, &m_Interface, sizeof(KSPIN_INTERFACE));
784     }
785 
786     if (Medium)
787     {
788         if (!m_hPin)
789             return VFW_E_NOT_CONNECTED;
790 
791         CopyMemory(Medium, &m_Medium, sizeof(KSPIN_MEDIUM));
792     }
793     return NOERROR;
794 }
795 
796 HRESULT
797 STDMETHODCALLTYPE
798 CInputPin::KsPropagateAcquire()
799 {
800     KSPROPERTY Property;
801     KSSTATE State;
802     ULONG BytesReturned;
803     HRESULT hr;
804 
805     assert(m_hPin != INVALID_HANDLE_VALUE);
806 
807     Property.Set = KSPROPSETID_Connection;
808     Property.Id = KSPROPERTY_CONNECTION_STATE;
809     Property.Flags = KSPROPERTY_TYPE_SET;
810 
811     State = KSSTATE_ACQUIRE;
812 
813     hr = KsProperty(&Property, sizeof(KSPROPERTY), (LPVOID)&State, sizeof(KSSTATE), &BytesReturned);
814 
815     //TODO
816     //propagate to connected pin on the pipe
817 
818     return hr;
819 }
820 
821 HRESULT
822 STDMETHODCALLTYPE
823 CInputPin::KsDeliver(
824     IMediaSample* Sample,
825     ULONG Flags)
826 {
827     return E_FAIL;
828 }
829 
830 HRESULT
831 STDMETHODCALLTYPE
832 CInputPin::KsMediaSamplesCompleted(PKSSTREAM_SEGMENT StreamSegment)
833 {
834     return NOERROR;
835 }
836 
837 IMemAllocator *
838 STDMETHODCALLTYPE
839 CInputPin::KsPeekAllocator(KSPEEKOPERATION Operation)
840 {
841     if (Operation == KsPeekOperation_AddRef)
842     {
843         // add reference on allocator
844         m_MemAllocator->AddRef();
845     }
846 
847     return m_MemAllocator;
848 }
849 
850 HRESULT
851 STDMETHODCALLTYPE
852 CInputPin::KsReceiveAllocator(IMemAllocator *MemAllocator)
853 {
854 
855     if (MemAllocator)
856     {
857         MemAllocator->AddRef();
858     }
859 
860     if (m_MemAllocator)
861     {
862         m_MemAllocator->Release();
863     }
864 
865     m_MemAllocator = MemAllocator;
866     return NOERROR;
867 }
868 
869 HRESULT
870 STDMETHODCALLTYPE
871 CInputPin::KsRenegotiateAllocator()
872 {
873     return E_FAIL;
874 }
875 
876 LONG
877 STDMETHODCALLTYPE
878 CInputPin::KsIncrementPendingIoCount()
879 {
880     return InterlockedIncrement((volatile LONG*)&m_IoCount);
881 }
882 
883 LONG
884 STDMETHODCALLTYPE
885 CInputPin::KsDecrementPendingIoCount()
886 {
887     return InterlockedDecrement((volatile LONG*)&m_IoCount);
888 }
889 
890 HRESULT
891 STDMETHODCALLTYPE
892 CInputPin::KsQualityNotify(
893     ULONG Proportion,
894     REFERENCE_TIME TimeDelta)
895 {
896 #ifdef KSPROXY_TRACE
897     OutputDebugStringW(L"CInputPin::KsQualityNotify NotImplemented\n");
898 #endif
899 
900     return E_NOTIMPL;
901 }
902 
903 //-------------------------------------------------------------------
904 // IKsPinEx
905 //
906 
907 VOID
908 STDMETHODCALLTYPE
909 CInputPin::KsNotifyError(
910     IMediaSample* Sample,
911     HRESULT hr)
912 {
913 #ifdef KSPROXY_TRACE
914     OutputDebugStringW(L"CInputPin::KsNotifyError NotImplemented\n");
915 #endif
916 }
917 
918 
919 //-------------------------------------------------------------------
920 // IKsControl
921 //
922 HRESULT
923 STDMETHODCALLTYPE
924 CInputPin::KsProperty(
925     PKSPROPERTY Property,
926     ULONG PropertyLength,
927     LPVOID PropertyData,
928     ULONG DataLength,
929     ULONG* BytesReturned)
930 {
931     assert(m_hPin != INVALID_HANDLE_VALUE);
932     return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_PROPERTY, (PVOID)Property, PropertyLength, (PVOID)PropertyData, DataLength, BytesReturned);
933 }
934 
935 HRESULT
936 STDMETHODCALLTYPE
937 CInputPin::KsMethod(
938     PKSMETHOD Method,
939     ULONG MethodLength,
940     LPVOID MethodData,
941     ULONG DataLength,
942     ULONG* BytesReturned)
943 {
944     assert(m_hPin != INVALID_HANDLE_VALUE);
945     return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_METHOD, (PVOID)Method, MethodLength, (PVOID)MethodData, DataLength, BytesReturned);
946 }
947 
948 HRESULT
949 STDMETHODCALLTYPE
950 CInputPin::KsEvent(
951     PKSEVENT Event,
952     ULONG EventLength,
953     LPVOID EventData,
954     ULONG DataLength,
955     ULONG* BytesReturned)
956 {
957     assert(m_hPin != INVALID_HANDLE_VALUE);
958 
959     if (EventLength)
960         return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_ENABLE_EVENT, (PVOID)Event, EventLength, (PVOID)EventData, DataLength, BytesReturned);
961     else
962         return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_DISABLE_EVENT, (PVOID)Event, EventLength, NULL, 0, BytesReturned);
963 }
964 
965 
966 //-------------------------------------------------------------------
967 // IKsPropertySet
968 //
969 HRESULT
970 STDMETHODCALLTYPE
971 CInputPin::Set(
972     REFGUID guidPropSet,
973     DWORD dwPropID,
974     LPVOID pInstanceData,
975     DWORD cbInstanceData,
976     LPVOID pPropData,
977     DWORD cbPropData)
978 {
979     ULONG BytesReturned;
980 
981     if (cbInstanceData)
982     {
983         PKSPROPERTY Property = (PKSPROPERTY)CoTaskMemAlloc(sizeof(KSPROPERTY) + cbInstanceData);
984         if (!Property)
985             return E_OUTOFMEMORY;
986 
987         Property->Set = guidPropSet;
988         Property->Id = dwPropID;
989         Property->Flags = KSPROPERTY_TYPE_SET;
990 
991         CopyMemory((Property+1), pInstanceData, cbInstanceData);
992 
993         HRESULT hr = KsProperty(Property, sizeof(KSPROPERTY) + cbInstanceData, pPropData, cbPropData, &BytesReturned);
994         CoTaskMemFree(Property);
995         return hr;
996     }
997     else
998     {
999         KSPROPERTY Property;
1000 
1001         Property.Set = guidPropSet;
1002         Property.Id = dwPropID;
1003         Property.Flags = KSPROPERTY_TYPE_SET;
1004 
1005         HRESULT hr = KsProperty(&Property, sizeof(KSPROPERTY), pPropData, cbPropData, &BytesReturned);
1006         return hr;
1007     }
1008 }
1009 
1010 HRESULT
1011 STDMETHODCALLTYPE
1012 CInputPin::Get(
1013     REFGUID guidPropSet,
1014     DWORD dwPropID,
1015     LPVOID pInstanceData,
1016     DWORD cbInstanceData,
1017     LPVOID pPropData,
1018     DWORD cbPropData,
1019     DWORD *pcbReturned)
1020 {
1021     ULONG BytesReturned;
1022 
1023     if (cbInstanceData)
1024     {
1025         PKSPROPERTY Property = (PKSPROPERTY)CoTaskMemAlloc(sizeof(KSPROPERTY) + cbInstanceData);
1026         if (!Property)
1027             return E_OUTOFMEMORY;
1028 
1029         Property->Set = guidPropSet;
1030         Property->Id = dwPropID;
1031         Property->Flags = KSPROPERTY_TYPE_GET;
1032 
1033         CopyMemory((Property+1), pInstanceData, cbInstanceData);
1034 
1035         HRESULT hr = KsProperty(Property, sizeof(KSPROPERTY) + cbInstanceData, pPropData, cbPropData, &BytesReturned);
1036         CoTaskMemFree(Property);
1037         return hr;
1038     }
1039     else
1040     {
1041         KSPROPERTY Property;
1042 
1043         Property.Set = guidPropSet;
1044         Property.Id = dwPropID;
1045         Property.Flags = KSPROPERTY_TYPE_GET;
1046 
1047         HRESULT hr = KsProperty(&Property, sizeof(KSPROPERTY), pPropData, cbPropData, &BytesReturned);
1048         return hr;
1049     }
1050 }
1051 
1052 HRESULT
1053 STDMETHODCALLTYPE
1054 CInputPin::QuerySupported(
1055     REFGUID guidPropSet,
1056     DWORD dwPropID,
1057     DWORD *pTypeSupport)
1058 {
1059     KSPROPERTY Property;
1060     ULONG BytesReturned;
1061 
1062     Property.Set = guidPropSet;
1063     Property.Id = dwPropID;
1064     Property.Flags = KSPROPERTY_TYPE_SETSUPPORT;
1065 
1066     return KsProperty(&Property, sizeof(KSPROPERTY), pTypeSupport, sizeof(DWORD), &BytesReturned);
1067 }
1068 
1069 
1070 //-------------------------------------------------------------------
1071 // IKsObject
1072 //
1073 HANDLE
1074 STDMETHODCALLTYPE
1075 CInputPin::KsGetObjectHandle()
1076 {
1077     assert(m_hPin);
1078     return m_hPin;
1079 }
1080 
1081 //-------------------------------------------------------------------
1082 // IPin interface
1083 //
1084 HRESULT
1085 STDMETHODCALLTYPE
1086 CInputPin::Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt)
1087 {
1088 #ifdef KSPROXY_TRACE
1089     OutputDebugStringW(L"CInputPin::Connect NotImplemented\n");
1090 #endif
1091     return NOERROR;
1092 }
1093 
1094 HRESULT
1095 STDMETHODCALLTYPE
1096 CInputPin::ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt)
1097 {
1098     HRESULT hr;
1099 
1100     if (m_Pin)
1101     {
1102         // already connected
1103         return VFW_E_ALREADY_CONNECTED;
1104     }
1105 
1106     // first check format
1107     hr = CheckFormat(pmt);
1108     if (FAILED(hr))
1109     {
1110         // format is not supported
1111         return hr;
1112     }
1113 
1114     hr = CreatePin(pmt);
1115     if (FAILED(hr))
1116     {
1117         return hr;
1118     }
1119 
1120     m_Pin = pConnector;
1121     m_Pin->AddRef();
1122 
1123     return S_OK;
1124 }
1125 HRESULT
1126 STDMETHODCALLTYPE
1127 CInputPin::Disconnect( void)
1128 {
1129     if (!m_Pin)
1130     {
1131         // pin was not connected
1132         return S_FALSE;
1133     }
1134 
1135     //FIXME
1136     //check if filter is active
1137 
1138     m_Pin->Release();
1139     m_Pin = NULL;
1140 
1141 #ifdef KSPROXY_TRACE
1142     OutputDebugStringW(L"CInputPin::Disconnect\n");
1143 #endif
1144 
1145     return S_OK;
1146 }
1147 HRESULT
1148 STDMETHODCALLTYPE
1149 CInputPin::ConnectedTo(IPin **pPin)
1150 {
1151     if (!pPin)
1152         return E_POINTER;
1153 
1154     if (m_Pin)
1155     {
1156         // increment reference count
1157         m_Pin->AddRef();
1158         *pPin = m_Pin;
1159         return S_OK;
1160     }
1161 
1162     *pPin = NULL;
1163     return VFW_E_NOT_CONNECTED;
1164 }
1165 HRESULT
1166 STDMETHODCALLTYPE
1167 CInputPin::ConnectionMediaType(AM_MEDIA_TYPE *pmt)
1168 {
1169     if (!m_Pin)
1170         return VFW_E_NOT_CONNECTED;
1171 
1172 #ifdef KSPROXY_TRACE
1173     OutputDebugStringW(L"CInputPin::ConnectionMediaType NotImplemented\n");
1174 #endif
1175 
1176     return E_NOTIMPL;
1177 }
1178 HRESULT
1179 STDMETHODCALLTYPE
1180 CInputPin::QueryPinInfo(PIN_INFO *pInfo)
1181 {
1182     wcscpy(pInfo->achName, m_PinName);
1183     pInfo->dir = PINDIR_INPUT;
1184     pInfo->pFilter = m_ParentFilter;
1185     m_ParentFilter->AddRef();
1186 
1187     return S_OK;
1188 }
1189 HRESULT
1190 STDMETHODCALLTYPE
1191 CInputPin::QueryDirection(PIN_DIRECTION *pPinDir)
1192 {
1193     if (pPinDir)
1194     {
1195         *pPinDir = PINDIR_INPUT;
1196         return S_OK;
1197     }
1198 
1199     return E_POINTER;
1200 }
1201 HRESULT
1202 STDMETHODCALLTYPE
1203 CInputPin::QueryId(LPWSTR *Id)
1204 {
1205     *Id = (LPWSTR)CoTaskMemAlloc((wcslen(m_PinName)+1)*sizeof(WCHAR));
1206     if (!*Id)
1207         return E_OUTOFMEMORY;
1208 
1209     wcscpy(*Id, m_PinName);
1210     return S_OK;
1211 }
1212 
1213 HRESULT
1214 STDMETHODCALLTYPE
1215 CInputPin::QueryAccept(
1216     const AM_MEDIA_TYPE *pmt)
1217 {
1218     return CheckFormat(pmt);
1219 }
1220 HRESULT
1221 STDMETHODCALLTYPE
1222 CInputPin::EnumMediaTypes(IEnumMediaTypes **ppEnum)
1223 {
1224     HRESULT hr;
1225     ULONG MediaTypeCount = 0, Index;
1226     AM_MEDIA_TYPE * MediaTypes;
1227     IKsObject * KsObjectParent;
1228     HANDLE hFilter;
1229 
1230     hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent);
1231     if (FAILED(hr))
1232         return hr;
1233 
1234     hFilter = KsObjectParent->KsGetObjectHandle();
1235 
1236     KsObjectParent->Release();
1237 
1238     if (!hFilter)
1239         return E_HANDLE;
1240 
1241 
1242     // query media type count
1243     hr = KsGetMediaTypeCount(hFilter, m_PinId, &MediaTypeCount);
1244     if (FAILED(hr) || !MediaTypeCount)
1245         return hr;
1246 
1247     // allocate media types
1248     MediaTypes = (AM_MEDIA_TYPE*)CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE) * MediaTypeCount);
1249     if (!MediaTypes)
1250     {
1251         // not enough memory
1252         return E_OUTOFMEMORY;
1253     }
1254 
1255     // zero media types
1256     ZeroMemory(MediaTypes, sizeof(AM_MEDIA_TYPE) * MediaTypeCount);
1257 
1258     for(Index = 0; Index < MediaTypeCount; Index++)
1259     {
1260         // get media type
1261         hr = KsGetMediaType(Index, &MediaTypes[Index], hFilter, m_PinId);
1262         if (FAILED(hr))
1263         {
1264             // failed
1265             CoTaskMemFree(MediaTypes);
1266             return hr;
1267         }
1268     }
1269 
1270     return CEnumMediaTypes_fnConstructor(MediaTypeCount, MediaTypes, IID_IEnumMediaTypes, (void**)ppEnum);
1271 }
1272 
1273 HRESULT
1274 STDMETHODCALLTYPE
1275 CInputPin::QueryInternalConnections(IPin **apPin, ULONG *nPin)
1276 {
1277 #ifdef KSPROXY_TRACE
1278     OutputDebugStringW(L"CInputPin::QueryInternalConnections NotImplemented\n");
1279 #endif
1280     return E_NOTIMPL;
1281 }
1282 HRESULT
1283 STDMETHODCALLTYPE
1284 CInputPin::EndOfStream( void)
1285 {
1286 #ifdef KSPROXY_TRACE
1287     OutputDebugStringW(L"CInputPin::EndOfStream NotImplemented\n");
1288 #endif
1289     return E_NOTIMPL;
1290 }
1291 HRESULT
1292 STDMETHODCALLTYPE
1293 CInputPin::BeginFlush( void)
1294 {
1295 #ifdef KSPROXY_TRACE
1296     OutputDebugStringW(L"CInputPin::BeginFlush NotImplemented\n");
1297 #endif
1298     return E_NOTIMPL;
1299 }
1300 HRESULT
1301 STDMETHODCALLTYPE
1302 CInputPin::EndFlush( void)
1303 {
1304 #ifdef KSPROXY_TRACE
1305     OutputDebugStringW(L"CInputPin::EndFlush NotImplemented\n");
1306 #endif
1307     return E_NOTIMPL;
1308 }
1309 HRESULT
1310 STDMETHODCALLTYPE
1311 CInputPin::NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
1312 {
1313 #ifdef KSPROXY_TRACE
1314     OutputDebugStringW(L"CInputPin::NewSegment NotImplemented\n");
1315 #endif
1316     return E_NOTIMPL;
1317 }
1318 
1319 
1320 //-------------------------------------------------------------------
1321 HRESULT
1322 STDMETHODCALLTYPE
1323 CInputPin::CheckFormat(
1324     const AM_MEDIA_TYPE *pmt)
1325 {
1326     PKSMULTIPLE_ITEM MultipleItem;
1327     PKSDATAFORMAT DataFormat;
1328     HRESULT hr;
1329     IKsObject * KsObjectParent;
1330     HANDLE hFilter;
1331 
1332     if (!pmt)
1333         return E_POINTER;
1334 
1335     hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent);
1336     if (FAILED(hr))
1337         return hr;
1338 
1339     hFilter = KsObjectParent->KsGetObjectHandle();
1340 
1341     KsObjectParent->Release();
1342 
1343     if (!hFilter)
1344         return E_HANDLE;
1345 
1346 
1347     hr = KsGetMultiplePinFactoryItems(hFilter, m_PinId, KSPROPERTY_PIN_DATARANGES, (PVOID*)&MultipleItem);
1348     if (FAILED(hr))
1349         return S_FALSE;
1350 
1351     DataFormat = (PKSDATAFORMAT)(MultipleItem + 1);
1352     for(ULONG Index = 0; Index < MultipleItem->Count; Index++)
1353     {
1354         if (IsEqualGUID(pmt->majortype, DataFormat->MajorFormat) &&
1355             IsEqualGUID(pmt->subtype, DataFormat->SubFormat) &&
1356             IsEqualGUID(pmt->formattype, DataFormat->Specifier))
1357         {
1358             // format is supported
1359             CoTaskMemFree(MultipleItem);
1360 #ifdef KSPROXY_TRACE
1361             OutputDebugStringW(L"CInputPin::CheckFormat format OK\n");
1362 #endif
1363             return S_OK;
1364         }
1365         DataFormat = (PKSDATAFORMAT)((ULONG_PTR)DataFormat + DataFormat->FormatSize);
1366     }
1367     //format is not supported
1368     CoTaskMemFree(MultipleItem);
1369     return S_FALSE;
1370 }
1371 
1372 HRESULT
1373 STDMETHODCALLTYPE
1374 CInputPin::CreatePin(
1375     const AM_MEDIA_TYPE *pmt)
1376 {
1377     PKSMULTIPLE_ITEM MediumList;
1378     PKSMULTIPLE_ITEM InterfaceList;
1379     PKSPIN_MEDIUM Medium;
1380     PKSPIN_INTERFACE Interface;
1381     IKsInterfaceHandler * InterfaceHandler;
1382     HRESULT hr;
1383 
1384     // query for pin medium
1385     hr = KsQueryMediums(&MediumList);
1386     if (FAILED(hr))
1387         return hr;
1388 
1389     // query for pin interface
1390     hr = KsQueryInterfaces(&InterfaceList);
1391     if (FAILED(hr))
1392     {
1393         // failed
1394         CoTaskMemFree(MediumList);
1395         return hr;
1396     }
1397 
1398     if (MediumList->Count)
1399     {
1400         //use first available medium
1401         Medium = (PKSPIN_MEDIUM)(MediumList + 1);
1402     }
1403     else
1404     {
1405         // default to standard medium
1406         Medium = &StandardPinMedium;
1407     }
1408 
1409     if (InterfaceList->Count)
1410     {
1411         //use first available interface
1412         Interface = (PKSPIN_INTERFACE)(InterfaceList + 1);
1413     }
1414     else
1415     {
1416         // default to standard interface
1417         Interface = &StandardPinInterface;
1418     }
1419 
1420     if (m_Communication != KSPIN_COMMUNICATION_BRIDGE && m_Communication != KSPIN_COMMUNICATION_NONE)
1421     {
1422         if (!m_InterfaceHandler)
1423         {
1424             // now load the IKsInterfaceHandler plugin
1425             hr = CoCreateInstance(Interface->Set, NULL, CLSCTX_INPROC_SERVER, IID_IKsInterfaceHandler, (void**)&InterfaceHandler);
1426             if (FAILED(hr))
1427             {
1428                 // failed to load interface handler plugin
1429 #ifdef KSPROXY_TRACE
1430                 OutputDebugStringW(L"CInputPin::CreatePin failed to load InterfaceHandlerPlugin\n");
1431 #endif
1432                 CoTaskMemFree(MediumList);
1433                 CoTaskMemFree(InterfaceList);
1434 
1435                 return hr;
1436             }
1437 
1438             // now set the pin
1439             hr = InterfaceHandler->KsSetPin((IKsPin*)this);
1440             if (FAILED(hr))
1441             {
1442                 // failed to load interface handler plugin
1443 #ifdef KSPROXY_TRACE
1444                 OutputDebugStringW(L"CInputPin::CreatePin failed to initialize InterfaceHandlerPlugin\n");
1445 #endif
1446                 InterfaceHandler->Release();
1447                 CoTaskMemFree(MediumList);
1448                 CoTaskMemFree(InterfaceList);
1449                 return hr;
1450             }
1451 
1452             // store interface handler
1453             m_InterfaceHandler = InterfaceHandler;
1454         }
1455 
1456         // now create pin
1457         hr = CreatePinHandle(Medium, Interface, pmt);
1458         if (FAILED(hr))
1459         {
1460             m_InterfaceHandler->Release();
1461             m_InterfaceHandler = InterfaceHandler;
1462         }
1463     }
1464     else
1465     {
1466 #ifdef KSPROXY_TRACE
1467         WCHAR Buffer[100];
1468         swprintf(Buffer, L"CInputPin::CreatePin unexpected communication %u %s\n", m_Communication, m_PinName);
1469         OutputDebugStringW(Buffer);
1470 #endif
1471         hr = E_FAIL;
1472     }
1473 
1474     // free medium / interface / dataformat
1475     CoTaskMemFree(MediumList);
1476     CoTaskMemFree(InterfaceList);
1477 
1478     return hr;
1479 }
1480 
1481 HRESULT
1482 STDMETHODCALLTYPE
1483 CInputPin::CreatePinHandle(
1484     PKSPIN_MEDIUM Medium,
1485     PKSPIN_INTERFACE Interface,
1486     const AM_MEDIA_TYPE *pmt)
1487 {
1488     PKSPIN_CONNECT PinConnect;
1489     PKSDATAFORMAT DataFormat;
1490     ULONG Length;
1491     HRESULT hr;
1492     IKsObject * KsObjectParent;
1493     HANDLE hFilter;
1494 
1495     if (!pmt)
1496         return E_POINTER;
1497 
1498     hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent);
1499     if (FAILED(hr))
1500         return hr;
1501 
1502     hFilter = KsObjectParent->KsGetObjectHandle();
1503 
1504     KsObjectParent->Release();
1505 
1506     if (!hFilter)
1507         return E_HANDLE;
1508 
1509 
1510     if (m_hPin != INVALID_HANDLE_VALUE)
1511     {
1512         // pin already exists
1513         //CloseHandle(m_hPin);
1514         //m_hPin = INVALID_HANDLE_VALUE;
1515         return S_OK;
1516     }
1517 
1518 
1519     // calc format size
1520     Length = sizeof(KSPIN_CONNECT) + sizeof(KSDATAFORMAT) + pmt->cbFormat;
1521 
1522     // allocate pin connect
1523     PinConnect = (PKSPIN_CONNECT)CoTaskMemAlloc(Length);
1524     if (!PinConnect)
1525     {
1526         // failed
1527         return E_OUTOFMEMORY;
1528     }
1529 
1530     // setup request
1531     CopyMemory(&PinConnect->Interface, Interface, sizeof(KSPIN_INTERFACE));
1532     CopyMemory(&PinConnect->Medium, Medium, sizeof(KSPIN_MEDIUM));
1533     PinConnect->PinId = m_PinId;
1534     PinConnect->PinToHandle = NULL;
1535     PinConnect->Priority.PriorityClass = KSPRIORITY_NORMAL;
1536     PinConnect->Priority.PrioritySubClass = KSPRIORITY_NORMAL;
1537 
1538     // get dataformat offset
1539     DataFormat = (PKSDATAFORMAT)(PinConnect + 1);
1540 
1541     // copy data format
1542     DataFormat->FormatSize = sizeof(KSDATAFORMAT) + pmt->cbFormat;
1543     DataFormat->Flags = 0;
1544     DataFormat->SampleSize = pmt->lSampleSize;
1545     DataFormat->Reserved = 0;
1546     CopyMemory(&DataFormat->MajorFormat, &pmt->majortype, sizeof(GUID));
1547     CopyMemory(&DataFormat->SubFormat,  &pmt->subtype, sizeof(GUID));
1548     CopyMemory(&DataFormat->Specifier, &pmt->formattype, sizeof(GUID));
1549 
1550     if (pmt->cbFormat)
1551     {
1552         // copy extended format
1553         CopyMemory((DataFormat + 1), pmt->pbFormat, pmt->cbFormat);
1554     }
1555 
1556     // create pin
1557     hr = KsCreatePin(hFilter, PinConnect, GENERIC_WRITE, &m_hPin);
1558 
1559     if (SUCCEEDED(hr))
1560     {
1561         // store current interface / medium
1562         CopyMemory(&m_Medium, Medium, sizeof(KSPIN_MEDIUM));
1563         CopyMemory(&m_Interface, Interface, sizeof(KSPIN_INTERFACE));
1564         CopyMemory(&m_MediaFormat, pmt, sizeof(AM_MEDIA_TYPE));
1565 
1566 #ifdef KSPROXY_TRACE
1567         LPOLESTR pMajor, pSub, pFormat;
1568         StringFromIID(m_MediaFormat.majortype, &pMajor);
1569         StringFromIID(m_MediaFormat.subtype , &pSub);
1570         StringFromIID(m_MediaFormat.formattype, &pFormat);
1571 
1572         WCHAR Buffer[200];
1573         swprintf(Buffer, L"CInputPin::CreatePinHandle Major %s SubType %s Format %s pbFormat %p cbFormat %u\n", pMajor, pSub, pFormat, pmt->pbFormat, pmt->cbFormat);
1574         CoTaskMemFree(pMajor);
1575         CoTaskMemFree(pSub);
1576         CoTaskMemFree(pFormat);
1577         OutputDebugStringW(Buffer);
1578 #endif
1579 
1580         if (pmt->cbFormat)
1581         {
1582             m_MediaFormat.pbFormat = (BYTE*)CoTaskMemAlloc(pmt->cbFormat);
1583             if (!m_MediaFormat.pbFormat)
1584             {
1585                 CoTaskMemFree(PinConnect);
1586                 m_MediaFormat.pbFormat = NULL;
1587                 m_MediaFormat.cbFormat = 0;
1588                 return E_OUTOFMEMORY;
1589             }
1590             CopyMemory(m_MediaFormat.pbFormat, pmt->pbFormat, pmt->cbFormat);
1591         }
1592 
1593         LPGUID pGuid;
1594         ULONG NumGuids = 0;
1595 
1596         // get all supported sets
1597         hr = GetSupportedSets(&pGuid, &NumGuids);
1598         if (FAILED(hr))
1599         {
1600 #ifdef KSPROXY_TRACE
1601             OutputDebugStringW(L"CInputPin::CreatePinHandle GetSupportedSets failed\n");
1602 #endif
1603             return hr;
1604         }
1605 
1606         // load all proxy plugins
1607         hr = LoadProxyPlugins(pGuid, NumGuids);
1608         if (FAILED(hr))
1609         {
1610 #ifdef KSPROXY_TRACE
1611             OutputDebugStringW(L"CInputPin::CreatePinHandle LoadProxyPlugins failed\n");
1612 #endif
1613             return hr;
1614         }
1615 
1616         // free sets
1617         CoTaskMemFree(pGuid);
1618 
1619 
1620         //TODO
1621         // connect pin pipes
1622 
1623     }
1624 
1625     // free pin connect
1626      CoTaskMemFree(PinConnect);
1627 
1628     return hr;
1629 }
1630 
1631 HRESULT
1632 STDMETHODCALLTYPE
1633 CInputPin::GetSupportedSets(
1634     LPGUID * pOutGuid,
1635     PULONG NumGuids)
1636 {
1637     KSPROPERTY Property;
1638     LPGUID pGuid;
1639     ULONG NumProperty = 0;
1640     ULONG NumMethods = 0;
1641     ULONG NumEvents = 0;
1642     ULONG Length;
1643     ULONG BytesReturned;
1644     HRESULT hr;
1645 
1646     Property.Set = GUID_NULL;
1647     Property.Id = 0;
1648     Property.Flags = KSPROPERTY_TYPE_SETSUPPORT;
1649 
1650     KsSynchronousDeviceControl(m_hPin, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), NULL, 0, &NumProperty);
1651     KsSynchronousDeviceControl(m_hPin, IOCTL_KS_METHOD, (PVOID)&Property, sizeof(KSPROPERTY), NULL, 0, &NumMethods);
1652     KsSynchronousDeviceControl(m_hPin, IOCTL_KS_ENABLE_EVENT, (PVOID)&Property, sizeof(KSPROPERTY), NULL, 0, &NumEvents);
1653 
1654     Length = NumProperty + NumMethods + NumEvents;
1655 
1656     assert(Length);
1657 
1658     // allocate guid buffer
1659     pGuid = (LPGUID)CoTaskMemAlloc(Length);
1660     if (!pGuid)
1661     {
1662         // failed
1663         return E_OUTOFMEMORY;
1664     }
1665 
1666     NumProperty /= sizeof(GUID);
1667     NumMethods /= sizeof(GUID);
1668     NumEvents /= sizeof(GUID);
1669 
1670 #ifdef KSPROXY_TRACE
1671     WCHAR Buffer[200];
1672     swprintf(Buffer, L"CInputPin::GetSupportedSets NumProperty %lu NumMethods %lu NumEvents %lu\n", NumProperty, NumMethods, NumEvents);
1673     OutputDebugStringW(Buffer);
1674 #endif
1675 
1676     // get all properties
1677     hr = KsSynchronousDeviceControl(m_hPin, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)pGuid, Length, &BytesReturned);
1678     if (FAILED(hr))
1679     {
1680         CoTaskMemFree(pGuid);
1681         return E_FAIL;
1682     }
1683     Length -= BytesReturned;
1684 
1685     // get all methods
1686     if (Length && NumMethods)
1687     {
1688         hr = KsSynchronousDeviceControl(m_hPin, IOCTL_KS_METHOD, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&pGuid[NumProperty], Length, &BytesReturned);
1689         if (FAILED(hr))
1690         {
1691             CoTaskMemFree(pGuid);
1692             return E_FAIL;
1693         }
1694         Length -= BytesReturned;
1695     }
1696 
1697     // get all events
1698     if (Length && NumEvents)
1699     {
1700         hr = KsSynchronousDeviceControl(m_hPin, IOCTL_KS_ENABLE_EVENT, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&pGuid[NumProperty+NumMethods], Length, &BytesReturned);
1701         if (FAILED(hr))
1702         {
1703             CoTaskMemFree(pGuid);
1704             return E_FAIL;
1705         }
1706         Length -= BytesReturned;
1707     }
1708 
1709     *pOutGuid = pGuid;
1710     *NumGuids = NumProperty+NumEvents+NumMethods;
1711     return S_OK;
1712 }
1713 
1714 HRESULT
1715 STDMETHODCALLTYPE
1716 CInputPin::LoadProxyPlugins(
1717     LPGUID pGuids,
1718     ULONG NumGuids)
1719 {
1720     ULONG Index;
1721     LPOLESTR pStr;
1722     HKEY hKey, hSubKey;
1723     HRESULT hr;
1724     IUnknown * pUnknown;
1725 
1726     if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\MediaInterfaces", 0, KEY_READ, &hKey) != ERROR_SUCCESS)
1727     {
1728         OutputDebugStringW(L"CInputPin::LoadProxyPlugins failed to open MediaInterfaces key\n");
1729         return E_FAIL;
1730     }
1731 
1732     // enumerate all sets
1733     for(Index = 0; Index < NumGuids; Index++)
1734     {
1735         // convert to string
1736         hr = StringFromCLSID(pGuids[Index], &pStr);
1737         if (FAILED(hr))
1738             return E_FAIL;
1739 
1740         // now try open class key
1741         if (RegOpenKeyExW(hKey, pStr, 0, KEY_READ, &hSubKey) != ERROR_SUCCESS)
1742         {
1743             // no plugin for that set exists
1744             CoTaskMemFree(pStr);
1745             continue;
1746         }
1747 
1748         // try load plugin
1749         hr = CoCreateInstance(pGuids[Index], (IBaseFilter*)this, CLSCTX_INPROC_SERVER, IID_IUnknown, (void**)&pUnknown);
1750         if (SUCCEEDED(hr))
1751         {
1752             // store plugin
1753             m_Plugins.push_back(pUnknown);
1754         }
1755         // close key
1756         RegCloseKey(hSubKey);
1757     }
1758 
1759     // close media interfaces key
1760     RegCloseKey(hKey);
1761     return S_OK;
1762 }
1763 
1764 HRESULT
1765 WINAPI
1766 CInputPin_Constructor(
1767     IBaseFilter * ParentFilter,
1768     LPCWSTR PinName,
1769     HANDLE hFilter,
1770     ULONG PinId,
1771     KSPIN_COMMUNICATION Communication,
1772     REFIID riid,
1773     LPVOID * ppv)
1774 {
1775     CInputPin * handler = new CInputPin(ParentFilter, PinName, PinId, Communication);
1776 
1777     if (!handler)
1778         return E_OUTOFMEMORY;
1779 
1780     if (FAILED(handler->QueryInterface(riid, ppv)))
1781     {
1782         /* not supported */
1783         delete handler;
1784         return E_NOINTERFACE;
1785     }
1786 
1787     return S_OK;
1788 }
1789