[PSDK]
[reactos.git] / reactos / dll / directx / ksproxy / output_pin.cpp
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS WDM Streaming ActiveMovie Proxy
4 * FILE: dll/directx/ksproxy/input_cpp.cpp
5 * PURPOSE: InputPin of Proxy Filter
6 *
7 * PROGRAMMERS: Johannes Anderwald (janderwald@reactos.org)
8 */
9 #include "precomp.h"
10
11 #ifndef _MSC_VER
12 const GUID IID_IKsPinFactory = {0xCD5EBE6BL, 0x8B6E, 0x11D1, {0x8A, 0xE0, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
13 #endif
14
15 class COutputPin : public IPin,
16 public IKsObject,
17 public IKsPropertySet,
18 public IStreamBuilder,
19 public IKsPinFactory,
20 public ISpecifyPropertyPages,
21 // public IKsPinPipe,
22 public IKsControl
23 /*
24 public IQualityControl,
25 public IKsPinEx,
26 public IKsAggregateControl
27 public IMediaSeeking,
28 public IAMStreamConfig,
29 public IMemAllocatorNotifyCallbackTemp
30 */
31 {
32 public:
33 STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
34
35 STDMETHODIMP_(ULONG) AddRef()
36 {
37 InterlockedIncrement(&m_Ref);
38 return m_Ref;
39 }
40 STDMETHODIMP_(ULONG) Release()
41 {
42 InterlockedDecrement(&m_Ref);
43 if (!m_Ref)
44 {
45 //delete this;
46 return 0;
47 }
48 return m_Ref;
49 }
50
51 //IKsPinPipe
52 HRESULT STDMETHODCALLTYPE KsGetPinFramingCache(PKSALLOCATOR_FRAMING_EX *FramingEx, PFRAMING_PROP FramingProp, FRAMING_CACHE_OPS Option);
53 HRESULT STDMETHODCALLTYPE KsSetPinFramingCache(PKSALLOCATOR_FRAMING_EX FramingEx, PFRAMING_PROP FramingProp, FRAMING_CACHE_OPS Option);
54 IPin* STDMETHODCALLTYPE KsGetConnectedPin();
55 IKsAllocatorEx* STDMETHODCALLTYPE KsGetPipe(KSPEEKOPERATION Operation);
56 HRESULT STDMETHODCALLTYPE KsSetPipe(IKsAllocatorEx *KsAllocator);
57 ULONG STDMETHODCALLTYPE KsGetPipeAllocatorFlag();
58 HRESULT STDMETHODCALLTYPE KsSetPipeAllocatorFlag(ULONG Flag);
59 GUID STDMETHODCALLTYPE KsGetPinBusCache();
60 HRESULT STDMETHODCALLTYPE KsSetPinBusCache(GUID Bus);
61 PWCHAR STDMETHODCALLTYPE KsGetPinName();
62 PWCHAR STDMETHODCALLTYPE KsGetFilterName();
63
64 //IPin methods
65 HRESULT STDMETHODCALLTYPE Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt);
66 HRESULT STDMETHODCALLTYPE ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt);
67 HRESULT STDMETHODCALLTYPE Disconnect();
68 HRESULT STDMETHODCALLTYPE ConnectedTo(IPin **pPin);
69 HRESULT STDMETHODCALLTYPE ConnectionMediaType(AM_MEDIA_TYPE *pmt);
70 HRESULT STDMETHODCALLTYPE QueryPinInfo(PIN_INFO *pInfo);
71 HRESULT STDMETHODCALLTYPE QueryDirection(PIN_DIRECTION *pPinDir);
72 HRESULT STDMETHODCALLTYPE QueryId(LPWSTR *Id);
73 HRESULT STDMETHODCALLTYPE QueryAccept(const AM_MEDIA_TYPE *pmt);
74 HRESULT STDMETHODCALLTYPE EnumMediaTypes(IEnumMediaTypes **ppEnum);
75 HRESULT STDMETHODCALLTYPE QueryInternalConnections(IPin **apPin, ULONG *nPin);
76 HRESULT STDMETHODCALLTYPE EndOfStream();
77 HRESULT STDMETHODCALLTYPE BeginFlush();
78 HRESULT STDMETHODCALLTYPE EndFlush();
79 HRESULT STDMETHODCALLTYPE NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate);
80
81 // ISpecifyPropertyPages
82 HRESULT STDMETHODCALLTYPE GetPages(CAUUID *pPages);
83
84 //IKsObject methods
85 HANDLE STDMETHODCALLTYPE KsGetObjectHandle();
86
87 //IKsPropertySet
88 HRESULT STDMETHODCALLTYPE Set(REFGUID guidPropSet, DWORD dwPropID, LPVOID pInstanceData, DWORD cbInstanceData, LPVOID pPropData, DWORD cbPropData);
89 HRESULT STDMETHODCALLTYPE Get(REFGUID guidPropSet, DWORD dwPropID, LPVOID pInstanceData, DWORD cbInstanceData, LPVOID pPropData, DWORD cbPropData, DWORD *pcbReturned);
90 HRESULT STDMETHODCALLTYPE QuerySupported(REFGUID guidPropSet, DWORD dwPropID, DWORD *pTypeSupport);
91
92 //IKsControl
93 HRESULT STDMETHODCALLTYPE KsProperty(PKSPROPERTY Property, ULONG PropertyLength, LPVOID PropertyData, ULONG DataLength, ULONG* BytesReturned);
94 HRESULT STDMETHODCALLTYPE KsMethod(PKSMETHOD Method, ULONG MethodLength, LPVOID MethodData, ULONG DataLength, ULONG* BytesReturned);
95 HRESULT STDMETHODCALLTYPE KsEvent(PKSEVENT Event, ULONG EventLength, LPVOID EventData, ULONG DataLength, ULONG* BytesReturned);
96
97 //IStreamBuilder
98 HRESULT STDMETHODCALLTYPE Render(IPin *ppinOut, IGraphBuilder *pGraph);
99 HRESULT STDMETHODCALLTYPE Backout(IPin *ppinOut, IGraphBuilder *pGraph);
100
101 //IKsPinFactory
102 HRESULT STDMETHODCALLTYPE KsPinFactory(ULONG* PinFactory);
103
104 COutputPin(IBaseFilter * ParentFilter, LPCWSTR PinName, ULONG PinId);
105 virtual ~COutputPin();
106
107 protected:
108 LONG m_Ref;
109 IBaseFilter * m_ParentFilter;
110 LPCWSTR m_PinName;
111 HANDLE m_hPin;
112 ULONG m_PinId;
113 IKsObject * m_KsObjectParent;
114 IPin * m_Pin;
115 };
116
117 COutputPin::~COutputPin()
118 {
119 if (m_KsObjectParent)
120 m_KsObjectParent->Release();
121 }
122
123 COutputPin::COutputPin(
124 IBaseFilter * ParentFilter,
125 LPCWSTR PinName,
126 ULONG PinId) : m_Ref(0), m_ParentFilter(ParentFilter), m_PinName(PinName), m_hPin(INVALID_HANDLE_VALUE), m_PinId(PinId), m_KsObjectParent(0), m_Pin(0)
127 {
128 HRESULT hr;
129
130 hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&m_KsObjectParent);
131 assert(hr == S_OK);
132
133 };
134
135 HRESULT
136 STDMETHODCALLTYPE
137 COutputPin::QueryInterface(
138 IN REFIID refiid,
139 OUT PVOID* Output)
140 {
141 *Output = NULL;
142 if (IsEqualGUID(refiid, IID_IUnknown) ||
143 IsEqualGUID(refiid, IID_IPin))
144 {
145 *Output = PVOID(this);
146 reinterpret_cast<IUnknown*>(*Output)->AddRef();
147 return NOERROR;
148 }
149 else if (IsEqualGUID(refiid, IID_IKsObject))
150 {
151 *Output = (IKsObject*)(this);
152 reinterpret_cast<IKsObject*>(*Output)->AddRef();
153 return NOERROR;
154 }
155 else if (IsEqualGUID(refiid, IID_IKsPropertySet))
156 {
157 *Output = (IKsPropertySet*)(this);
158 reinterpret_cast<IKsPropertySet*>(*Output)->AddRef();
159 return NOERROR;
160 }
161 else if (IsEqualGUID(refiid, IID_IKsControl))
162 {
163 *Output = (IKsControl*)(this);
164 reinterpret_cast<IKsControl*>(*Output)->AddRef();
165 return NOERROR;
166 }
167 else if (IsEqualGUID(refiid, IID_IStreamBuilder))
168 {
169 *Output = (IStreamBuilder*)(this);
170 reinterpret_cast<IStreamBuilder*>(*Output)->AddRef();
171 return NOERROR;
172 }
173 else if (IsEqualGUID(refiid, IID_IKsPinFactory))
174 {
175 *Output = (IKsPinFactory*)(this);
176 reinterpret_cast<IKsPinFactory*>(*Output)->AddRef();
177 return NOERROR;
178 }
179 else if (IsEqualGUID(refiid, IID_ISpecifyPropertyPages))
180 {
181 *Output = (ISpecifyPropertyPages*)(this);
182 reinterpret_cast<ISpecifyPropertyPages*>(*Output)->AddRef();
183 return NOERROR;
184 }
185 else if (IsEqualGUID(refiid, IID_IBaseFilter))
186 {
187 OutputDebugStringW(L"COutputPin::QueryInterface query IID_IBaseFilter\n");
188 DebugBreak();
189 }
190
191 WCHAR Buffer[MAX_PATH];
192 LPOLESTR lpstr;
193 StringFromCLSID(refiid, &lpstr);
194 swprintf(Buffer, L"COutputPin::QueryInterface: NoInterface for %s\n", lpstr);
195 OutputDebugStringW(Buffer);
196 CoTaskMemFree(lpstr);
197
198 return E_NOINTERFACE;
199 }
200
201 //-------------------------------------------------------------------
202 // ISpecifyPropertyPages
203 //
204
205 HRESULT
206 STDMETHODCALLTYPE
207 COutputPin::GetPages(CAUUID *pPages)
208 {
209 OutputDebugStringW(L"COutputPin::GetPages NotImplemented\n");
210
211 if (!pPages)
212 return E_POINTER;
213
214 pPages->cElems = 0;
215 pPages->pElems = NULL;
216
217 return S_OK;
218 }
219
220 //-------------------------------------------------------------------
221 // IKsPinFactory
222 //
223
224 HRESULT
225 STDMETHODCALLTYPE
226 COutputPin::KsPinFactory(
227 ULONG* PinFactory)
228 {
229 *PinFactory = m_PinId;
230 return S_OK;
231 }
232
233
234 //-------------------------------------------------------------------
235 // IStreamBuilder
236 //
237
238 HRESULT
239 STDMETHODCALLTYPE
240 COutputPin::Render(
241 IPin *ppinOut,
242 IGraphBuilder *pGraph)
243 {
244 return S_OK;
245 }
246
247 HRESULT
248 STDMETHODCALLTYPE
249 COutputPin::Backout(
250 IPin *ppinOut,
251 IGraphBuilder *pGraph)
252 {
253 return S_OK;
254 }
255 //-------------------------------------------------------------------
256 // IKsObject
257 //
258 HANDLE
259 STDMETHODCALLTYPE
260 COutputPin::KsGetObjectHandle()
261 {
262 assert(m_hPin);
263 return m_hPin;
264 }
265
266 //-------------------------------------------------------------------
267 // IKsControl
268 //
269 HRESULT
270 STDMETHODCALLTYPE
271 COutputPin::KsProperty(
272 PKSPROPERTY Property,
273 ULONG PropertyLength,
274 LPVOID PropertyData,
275 ULONG DataLength,
276 ULONG* BytesReturned)
277 {
278 assert(m_hPin != 0);
279 return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_PROPERTY, (PVOID)Property, PropertyLength, (PVOID)PropertyData, DataLength, BytesReturned);
280 }
281
282 HRESULT
283 STDMETHODCALLTYPE
284 COutputPin::KsMethod(
285 PKSMETHOD Method,
286 ULONG MethodLength,
287 LPVOID MethodData,
288 ULONG DataLength,
289 ULONG* BytesReturned)
290 {
291 assert(m_hPin != 0);
292 return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_METHOD, (PVOID)Method, MethodLength, (PVOID)MethodData, DataLength, BytesReturned);
293 }
294
295 HRESULT
296 STDMETHODCALLTYPE
297 COutputPin::KsEvent(
298 PKSEVENT Event,
299 ULONG EventLength,
300 LPVOID EventData,
301 ULONG DataLength,
302 ULONG* BytesReturned)
303 {
304 assert(m_hPin != 0);
305
306 if (EventLength)
307 return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_ENABLE_EVENT, (PVOID)Event, EventLength, (PVOID)EventData, DataLength, BytesReturned);
308 else
309 return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_DISABLE_EVENT, (PVOID)Event, EventLength, NULL, 0, BytesReturned);
310 }
311
312
313 //-------------------------------------------------------------------
314 // IKsPropertySet
315 //
316 HRESULT
317 STDMETHODCALLTYPE
318 COutputPin::Set(
319 REFGUID guidPropSet,
320 DWORD dwPropID,
321 LPVOID pInstanceData,
322 DWORD cbInstanceData,
323 LPVOID pPropData,
324 DWORD cbPropData)
325 {
326 ULONG BytesReturned;
327
328 if (cbInstanceData)
329 {
330 PKSPROPERTY Property = (PKSPROPERTY)CoTaskMemAlloc(sizeof(KSPROPERTY) + cbInstanceData);
331 if (!Property)
332 return E_OUTOFMEMORY;
333
334 Property->Set = guidPropSet;
335 Property->Id = dwPropID;
336 Property->Flags = KSPROPERTY_TYPE_SET;
337
338 CopyMemory((Property+1), pInstanceData, cbInstanceData);
339
340 HRESULT hr = KsProperty(Property, sizeof(KSPROPERTY) + cbInstanceData, pPropData, cbPropData, &BytesReturned);
341 CoTaskMemFree(Property);
342 return hr;
343 }
344 else
345 {
346 KSPROPERTY Property;
347
348 Property.Set = guidPropSet;
349 Property.Id = dwPropID;
350 Property.Flags = KSPROPERTY_TYPE_SET;
351
352 HRESULT hr = KsProperty(&Property, sizeof(KSPROPERTY), pPropData, cbPropData, &BytesReturned);
353 return hr;
354 }
355 }
356
357 HRESULT
358 STDMETHODCALLTYPE
359 COutputPin::Get(
360 REFGUID guidPropSet,
361 DWORD dwPropID,
362 LPVOID pInstanceData,
363 DWORD cbInstanceData,
364 LPVOID pPropData,
365 DWORD cbPropData,
366 DWORD *pcbReturned)
367 {
368 ULONG BytesReturned;
369
370 if (cbInstanceData)
371 {
372 PKSPROPERTY Property = (PKSPROPERTY)CoTaskMemAlloc(sizeof(KSPROPERTY) + cbInstanceData);
373 if (!Property)
374 return E_OUTOFMEMORY;
375
376 Property->Set = guidPropSet;
377 Property->Id = dwPropID;
378 Property->Flags = KSPROPERTY_TYPE_GET;
379
380 CopyMemory((Property+1), pInstanceData, cbInstanceData);
381
382 HRESULT hr = KsProperty(Property, sizeof(KSPROPERTY) + cbInstanceData, pPropData, cbPropData, &BytesReturned);
383 CoTaskMemFree(Property);
384 return hr;
385 }
386 else
387 {
388 KSPROPERTY Property;
389
390 Property.Set = guidPropSet;
391 Property.Id = dwPropID;
392 Property.Flags = KSPROPERTY_TYPE_GET;
393
394 HRESULT hr = KsProperty(&Property, sizeof(KSPROPERTY), pPropData, cbPropData, &BytesReturned);
395 return hr;
396 }
397 }
398
399 HRESULT
400 STDMETHODCALLTYPE
401 COutputPin::QuerySupported(
402 REFGUID guidPropSet,
403 DWORD dwPropID,
404 DWORD *pTypeSupport)
405 {
406 KSPROPERTY Property;
407 ULONG BytesReturned;
408
409 Property.Set = guidPropSet;
410 Property.Id = dwPropID;
411 Property.Flags = KSPROPERTY_TYPE_SETSUPPORT;
412
413 return KsProperty(&Property, sizeof(KSPROPERTY), pTypeSupport, sizeof(DWORD), &BytesReturned);
414 }
415
416
417 //-------------------------------------------------------------------
418 // IPin interface
419 //
420 HRESULT
421 STDMETHODCALLTYPE
422 COutputPin::Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt)
423 {
424 AM_MEDIA_TYPE MediaType;
425 HRESULT hr;
426 HANDLE hFilter;
427
428 OutputDebugStringW(L"COutputPin::Connect called\n");
429 if (pmt)
430 {
431 hr = pReceivePin->QueryAccept(pmt);
432 if (FAILED(hr))
433 return hr;
434 }
435 else
436 {
437 // get parent filter handle
438 hFilter = m_KsObjectParent->KsGetObjectHandle();
439
440 // get media type count
441 ZeroMemory(&MediaType, sizeof(AM_MEDIA_TYPE));
442 hr = KsGetMediaType(0, &MediaType, hFilter, m_PinId);
443 if (FAILED(hr))
444 return hr;
445
446 // query accept
447 hr = pReceivePin->QueryAccept(&MediaType);
448 if (FAILED(hr))
449 return hr;
450
451 pmt = &MediaType;
452 }
453
454 //FIXME create pin handle
455
456 // receive connection;
457 hr = pReceivePin->ReceiveConnection((IPin*)this, pmt);
458 if (SUCCEEDED(hr))
459 {
460 // increment reference count
461 pReceivePin->AddRef();
462 m_Pin = pReceivePin;
463 OutputDebugStringW(L"COutputPin::Connect success\n");
464 }
465
466 return hr;
467 }
468
469 HRESULT
470 STDMETHODCALLTYPE
471 COutputPin::ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt)
472 {
473 return E_UNEXPECTED;
474 }
475 HRESULT
476 STDMETHODCALLTYPE
477 COutputPin::Disconnect( void)
478 {
479 if (!m_Pin)
480 {
481 // pin was not connected
482 return S_FALSE;
483 }
484
485 //FIXME
486 //check if filter is active
487
488 m_Pin->Release();
489 m_Pin = NULL;
490
491 OutputDebugStringW(L"COutputPin::Disconnect\n");
492 return S_OK;
493 }
494 HRESULT
495 STDMETHODCALLTYPE
496 COutputPin::ConnectedTo(IPin **pPin)
497 {
498 if (!pPin)
499 return E_POINTER;
500
501 if (m_Pin)
502 {
503 // increment reference count
504 m_Pin->AddRef();
505 *pPin = m_Pin;
506 return S_OK;
507 }
508
509 *pPin = NULL;
510 return VFW_E_NOT_CONNECTED;
511 }
512 HRESULT
513 STDMETHODCALLTYPE
514 COutputPin::ConnectionMediaType(AM_MEDIA_TYPE *pmt)
515 {
516 OutputDebugStringW(L"COutputPin::ConnectionMediaType called\n");
517 return E_NOTIMPL;
518 }
519 HRESULT
520 STDMETHODCALLTYPE
521 COutputPin::QueryPinInfo(PIN_INFO *pInfo)
522 {
523 wcscpy(pInfo->achName, m_PinName);
524 pInfo->dir = PINDIR_OUTPUT;
525 pInfo->pFilter = m_ParentFilter;
526 m_ParentFilter->AddRef();
527
528 return S_OK;
529 }
530 HRESULT
531 STDMETHODCALLTYPE
532 COutputPin::QueryDirection(PIN_DIRECTION *pPinDir)
533 {
534 if (pPinDir)
535 {
536 *pPinDir = PINDIR_OUTPUT;
537 return S_OK;
538 }
539
540 return E_POINTER;
541 }
542 HRESULT
543 STDMETHODCALLTYPE
544 COutputPin::QueryId(LPWSTR *Id)
545 {
546 *Id = (LPWSTR)CoTaskMemAlloc((wcslen(m_PinName)+1)*sizeof(WCHAR));
547 if (!*Id)
548 return E_OUTOFMEMORY;
549
550 wcscpy(*Id, m_PinName);
551 return S_OK;
552 }
553 HRESULT
554 STDMETHODCALLTYPE
555 COutputPin::QueryAccept(const AM_MEDIA_TYPE *pmt)
556 {
557 OutputDebugStringW(L"COutputPin::QueryAccept called\n");
558 return E_NOTIMPL;
559 }
560 HRESULT
561 STDMETHODCALLTYPE
562 COutputPin::EnumMediaTypes(IEnumMediaTypes **ppEnum)
563 {
564 HRESULT hr;
565 ULONG MediaTypeCount = 0, Index;
566 AM_MEDIA_TYPE * MediaTypes;
567 HANDLE hFilter;
568
569 OutputDebugStringW(L"COutputPin::EnumMediaTypes called\n");
570
571 if (!m_KsObjectParent)
572 {
573 // no interface
574 return E_NOINTERFACE;
575 }
576
577 // get parent filter handle
578 hFilter = m_KsObjectParent->KsGetObjectHandle();
579
580 // query media type count
581 hr = KsGetMediaTypeCount(hFilter, m_PinId, &MediaTypeCount);
582 if (FAILED(hr) || !MediaTypeCount)
583 {
584 OutputDebugStringW(L"COutputPin::EnumMediaTypes failed1\n");
585 return hr;
586 }
587
588 // allocate media types
589 MediaTypes = (AM_MEDIA_TYPE*)CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE) * MediaTypeCount);
590 if (!MediaTypes)
591 {
592 // not enough memory
593 OutputDebugStringW(L"COutputPin::EnumMediaTypes CoTaskMemAlloc\n");
594 return E_OUTOFMEMORY;
595 }
596
597 // zero media types
598 ZeroMemory(MediaTypes, sizeof(AM_MEDIA_TYPE) * MediaTypeCount);
599
600 for(Index = 0; Index < MediaTypeCount; Index++)
601 {
602 // get media type
603 hr = KsGetMediaType(Index, &MediaTypes[Index], hFilter, m_PinId);
604 if (FAILED(hr))
605 {
606 // failed
607 CoTaskMemFree(MediaTypes);
608 OutputDebugStringW(L"COutputPin::EnumMediaTypes failed2\n");
609 return hr;
610 }
611 }
612
613 return CEnumMediaTypes_fnConstructor(MediaTypeCount, MediaTypes, IID_IEnumMediaTypes, (void**)ppEnum);
614 }
615 HRESULT
616 STDMETHODCALLTYPE
617 COutputPin::QueryInternalConnections(IPin **apPin, ULONG *nPin)
618 {
619 OutputDebugStringW(L"COutputPin::QueryInternalConnections called\n");
620 return E_NOTIMPL;
621 }
622 HRESULT
623 STDMETHODCALLTYPE
624 COutputPin::EndOfStream( void)
625 {
626 OutputDebugStringW(L"COutputPin::EndOfStream called\n");
627 return E_NOTIMPL;
628 }
629 HRESULT
630 STDMETHODCALLTYPE
631 COutputPin::BeginFlush( void)
632 {
633 OutputDebugStringW(L"COutputPin::BeginFlush called\n");
634 return E_NOTIMPL;
635 }
636 HRESULT
637 STDMETHODCALLTYPE
638 COutputPin::EndFlush( void)
639 {
640 OutputDebugStringW(L"COutputPin::EndFlush called\n");
641 return E_NOTIMPL;
642 }
643 HRESULT
644 STDMETHODCALLTYPE
645 COutputPin::NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
646 {
647 OutputDebugStringW(L"COutputPin::NewSegment called\n");
648 return E_NOTIMPL;
649 }
650
651 HRESULT
652 WINAPI
653 COutputPin_Constructor(
654 IBaseFilter * ParentFilter,
655 LPCWSTR PinName,
656 ULONG PinId,
657 REFIID riid,
658 LPVOID * ppv)
659 {
660 COutputPin * handler = new COutputPin(ParentFilter, PinName, PinId);
661
662 if (!handler)
663 return E_OUTOFMEMORY;
664
665 if (FAILED(handler->QueryInterface(riid, ppv)))
666 {
667 /* not supported */
668 delete handler;
669 return E_NOINTERFACE;
670 }
671
672 return S_OK;
673 }