d613962284386d7bea393b69029e2d486f727f31
[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 #ifndef _MSC_VER
12 const GUID IID_IPersistPropertyBag = {0x37D84F60, 0x42CB, 0x11CE, {0x81, 0x35, 0x00, 0xAA, 0x00, 0x4B, 0xB8, 0x51}};
13 const GUID GUID_NULL = {0x00000000L, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
14 #endif
15
16 const GUID IID_IBDA_DeviceControl = {0xFD0A5AF3, 0xB41D, 0x11d2, {0x9C, 0x95, 0x00, 0xC0, 0x4F, 0x79, 0x71, 0xE0}};
17 const GUID IID_IKsAggregateControl = {0x7F40EAC0, 0x3947, 0x11D2, {0x87, 0x4E, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
18 const GUID IID_IKsClockPropertySet = {0x5C5CBD84, 0xE755, 0x11D0, {0xAC, 0x18, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
19 const GUID IID_IKsTopology = {0x28F54683, 0x06FD, 0x11D2, {0xB2, 0x7A, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
20
21 /*
22 Needs IKsClock, IKsNotifyEvent
23 */
24
25 class CKsProxy : public IBaseFilter,
26 public IAMovieSetup,
27 public IPersistPropertyBag,
28 public IKsObject,
29 public IPersistStream,
30 public IAMDeviceRemoval,
31 public ISpecifyPropertyPages,
32 public IReferenceClock,
33 public IMediaSeeking,
34 public IKsPropertySet,
35 public IKsClockPropertySet,
36 public IAMFilterMiscFlags,
37 public IKsControl,
38 public IKsTopology,
39 public IKsAggregateControl
40
41 {
42 public:
43 typedef std::vector<IUnknown *>ProxyPluginVector;
44 typedef std::vector<IPin *> PinVector;
45
46 STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
47
48 STDMETHODIMP_(ULONG) AddRef()
49 {
50 InterlockedIncrement(&m_Ref);
51 return m_Ref;
52 }
53 STDMETHODIMP_(ULONG) Release()
54 {
55 InterlockedDecrement(&m_Ref);
56 if (!m_Ref)
57 {
58 delete this;
59 return 0;
60 }
61 return m_Ref;
62 }
63
64 // IBaseFilter methods
65 HRESULT STDMETHODCALLTYPE GetClassID(CLSID *pClassID);
66 HRESULT STDMETHODCALLTYPE Stop( void);
67 HRESULT STDMETHODCALLTYPE Pause( void);
68 HRESULT STDMETHODCALLTYPE Run(REFERENCE_TIME tStart);
69 HRESULT STDMETHODCALLTYPE GetState(DWORD dwMilliSecsTimeout, FILTER_STATE *State);
70 HRESULT STDMETHODCALLTYPE SetSyncSource(IReferenceClock *pClock);
71 HRESULT STDMETHODCALLTYPE GetSyncSource(IReferenceClock **pClock);
72 HRESULT STDMETHODCALLTYPE EnumPins(IEnumPins **ppEnum);
73 HRESULT STDMETHODCALLTYPE FindPin(LPCWSTR Id, IPin **ppPin);
74 HRESULT STDMETHODCALLTYPE QueryFilterInfo(FILTER_INFO *pInfo);
75 HRESULT STDMETHODCALLTYPE JoinFilterGraph(IFilterGraph *pGraph, LPCWSTR pName);
76 HRESULT STDMETHODCALLTYPE QueryVendorInfo(LPWSTR *pVendorInfo);
77
78 //IReferenceClock
79 HRESULT STDMETHODCALLTYPE GetTime(REFERENCE_TIME *pTime);
80 HRESULT STDMETHODCALLTYPE AdviseTime(REFERENCE_TIME baseTime, REFERENCE_TIME streamTime, HEVENT hEvent, DWORD_PTR *pdwAdviseCookie);
81 HRESULT STDMETHODCALLTYPE AdvisePeriodic(REFERENCE_TIME startTime, REFERENCE_TIME periodTime, HSEMAPHORE hSemaphore, DWORD_PTR *pdwAdviseCookie);
82 HRESULT STDMETHODCALLTYPE Unadvise(DWORD_PTR dwAdviseCookie);
83
84 //IMediaSeeking
85 HRESULT STDMETHODCALLTYPE GetCapabilities(DWORD *pCapabilities);
86 HRESULT STDMETHODCALLTYPE CheckCapabilities(DWORD *pCapabilities);
87 HRESULT STDMETHODCALLTYPE IsFormatSupported(const GUID *pFormat);
88 HRESULT STDMETHODCALLTYPE QueryPreferredFormat(GUID *pFormat);
89 HRESULT STDMETHODCALLTYPE GetTimeFormat(GUID *pFormat);
90 HRESULT STDMETHODCALLTYPE IsUsingTimeFormat(const GUID *pFormat);
91 HRESULT STDMETHODCALLTYPE SetTimeFormat(const GUID *pFormat);
92 HRESULT STDMETHODCALLTYPE GetDuration(LONGLONG *pDuration);
93 HRESULT STDMETHODCALLTYPE GetStopPosition(LONGLONG *pStop);
94 HRESULT STDMETHODCALLTYPE GetCurrentPosition(LONGLONG *pCurrent);
95 HRESULT STDMETHODCALLTYPE ConvertTimeFormat(LONGLONG *pTarget, const GUID *pTargetFormat, LONGLONG Source, const GUID *pSourceFormat);
96 HRESULT STDMETHODCALLTYPE SetPositions(LONGLONG *pCurrent, DWORD dwCurrentFlags, LONGLONG *pStop, DWORD dwStopFlags);
97 HRESULT STDMETHODCALLTYPE GetPositions(LONGLONG *pCurrent, LONGLONG *pStop);
98 HRESULT STDMETHODCALLTYPE GetAvailable(LONGLONG *pEarliest, LONGLONG *pLatest);
99 HRESULT STDMETHODCALLTYPE SetRate(double dRate);
100 HRESULT STDMETHODCALLTYPE GetRate(double *pdRate);
101 HRESULT STDMETHODCALLTYPE GetPreroll(LONGLONG *pllPreroll);
102
103 //IKsPropertySet
104 HRESULT STDMETHODCALLTYPE Set(REFGUID guidPropSet, DWORD dwPropID, LPVOID pInstanceData, DWORD cbInstanceData, LPVOID pPropData, DWORD cbPropData);
105 HRESULT STDMETHODCALLTYPE Get(REFGUID guidPropSet, DWORD dwPropID, LPVOID pInstanceData, DWORD cbInstanceData, LPVOID pPropData, DWORD cbPropData, DWORD *pcbReturned);
106 HRESULT STDMETHODCALLTYPE QuerySupported(REFGUID guidPropSet, DWORD dwPropID, DWORD *pTypeSupport);
107
108 //IAMFilterMiscFlags
109 ULONG STDMETHODCALLTYPE GetMiscFlags( void);
110
111 //IKsControl
112 HRESULT STDMETHODCALLTYPE KsProperty(PKSPROPERTY Property, ULONG PropertyLength, LPVOID PropertyData, ULONG DataLength, ULONG* BytesReturned);
113 HRESULT STDMETHODCALLTYPE KsMethod(PKSMETHOD Method, ULONG MethodLength, LPVOID MethodData, ULONG DataLength, ULONG* BytesReturned);
114 HRESULT STDMETHODCALLTYPE KsEvent(PKSEVENT Event, ULONG EventLength, LPVOID EventData, ULONG DataLength, ULONG* BytesReturned);
115
116 //IKsTopolology
117 HRESULT STDMETHODCALLTYPE CreateNodeInstance(ULONG NodeId, ULONG Flags, ACCESS_MASK DesiredAccess, IUnknown* UnkOuter, REFGUID InterfaceId, LPVOID* Interface);
118
119 //IKsAggregateControl
120 HRESULT STDMETHODCALLTYPE KsAddAggregate(IN REFGUID AggregateClass);
121 HRESULT STDMETHODCALLTYPE KsRemoveAggregate(REFGUID AggregateClass);
122
123 //IKsClockPropertySet
124 HRESULT STDMETHODCALLTYPE KsGetTime(LONGLONG* Time);
125 HRESULT STDMETHODCALLTYPE KsSetTime(LONGLONG Time);
126 HRESULT STDMETHODCALLTYPE KsGetPhysicalTime(LONGLONG* Time);
127 HRESULT STDMETHODCALLTYPE KsSetPhysicalTime(LONGLONG Time);
128 HRESULT STDMETHODCALLTYPE KsGetCorrelatedTime(KSCORRELATED_TIME* CorrelatedTime);
129 HRESULT STDMETHODCALLTYPE KsSetCorrelatedTime(KSCORRELATED_TIME* CorrelatedTime);
130 HRESULT STDMETHODCALLTYPE KsGetCorrelatedPhysicalTime(KSCORRELATED_TIME* CorrelatedTime);
131 HRESULT STDMETHODCALLTYPE KsSetCorrelatedPhysicalTime(KSCORRELATED_TIME* CorrelatedTime);
132 HRESULT STDMETHODCALLTYPE KsGetResolution(KSRESOLUTION* Resolution);
133 HRESULT STDMETHODCALLTYPE KsGetState(KSSTATE* State);
134
135
136 //IAMovieSetup methods
137 HRESULT STDMETHODCALLTYPE Register( void);
138 HRESULT STDMETHODCALLTYPE Unregister( void);
139
140 // IPersistPropertyBag methods
141 HRESULT STDMETHODCALLTYPE InitNew( void);
142 HRESULT STDMETHODCALLTYPE Load(IPropertyBag *pPropBag, IErrorLog *pErrorLog);
143 HRESULT STDMETHODCALLTYPE Save(IPropertyBag *pPropBag, BOOL fClearDirty, BOOL fSaveAllProperties);
144
145 // IKsObject
146 HANDLE STDMETHODCALLTYPE KsGetObjectHandle();
147
148 //IAMDeviceRemoval
149 HRESULT STDMETHODCALLTYPE DeviceInfo(CLSID *pclsidInterfaceClass, LPWSTR *pwszSymbolicLink);
150 HRESULT STDMETHODCALLTYPE Reassociate(void);
151 HRESULT STDMETHODCALLTYPE Disassociate( void);
152
153 //IPersistStream
154 HRESULT STDMETHODCALLTYPE IsDirty( void);
155 HRESULT STDMETHODCALLTYPE Load(IStream *pStm);
156 HRESULT STDMETHODCALLTYPE Save(IStream *pStm, BOOL fClearDirty);
157 HRESULT STDMETHODCALLTYPE GetSizeMax(ULARGE_INTEGER *pcbSize);
158
159 // ISpecifyPropertyPages
160 HRESULT STDMETHODCALLTYPE GetPages(CAUUID *pPages);
161
162
163 CKsProxy() : m_Ref(0), m_pGraph(0), m_ReferenceClock(0), m_FilterState(State_Stopped), m_hDevice(0), m_Plugins(), m_Pins(), m_DevicePath(0) {};
164 ~CKsProxy()
165 {
166 if (m_hDevice)
167 CloseHandle(m_hDevice);
168 };
169
170 HRESULT STDMETHODCALLTYPE GetSupportedSets(LPGUID * pOutGuid, PULONG NumGuids);
171 HRESULT STDMETHODCALLTYPE LoadProxyPlugins(LPGUID pGuids, ULONG NumGuids);
172 HRESULT STDMETHODCALLTYPE GetNumberOfPins(PULONG NumPins);
173 HRESULT STDMETHODCALLTYPE GetPinInstanceCount(ULONG PinId, PKSPIN_CINSTANCES Instances);
174 HRESULT STDMETHODCALLTYPE GetPinDataflow(ULONG PinId, KSPIN_DATAFLOW * DataFlow);
175 HRESULT STDMETHODCALLTYPE GetPinName(ULONG PinId, KSPIN_DATAFLOW DataFlow, ULONG PinCount, LPWSTR * OutPinName);
176 HRESULT STDMETHODCALLTYPE GetPinCommunication(ULONG PinId, KSPIN_COMMUNICATION * Communication);
177 HRESULT STDMETHODCALLTYPE CreatePins();
178 protected:
179 LONG m_Ref;
180 IFilterGraph *m_pGraph;
181 IReferenceClock * m_ReferenceClock;
182 FILTER_STATE m_FilterState;
183 HANDLE m_hDevice;
184 ProxyPluginVector m_Plugins;
185 PinVector m_Pins;
186 LPWSTR m_DevicePath;
187 CLSID m_DeviceInterfaceGUID;
188 };
189
190 HRESULT
191 STDMETHODCALLTYPE
192 CKsProxy::QueryInterface(
193 IN REFIID refiid,
194 OUT PVOID* Output)
195 {
196 *Output = (PVOID)0xDEADDEAD;//NULL;
197
198 if (IsEqualGUID(refiid, IID_IUnknown) ||
199 IsEqualGUID(refiid, IID_IBaseFilter))
200 {
201 *Output = PVOID(this);
202 reinterpret_cast<IUnknown*>(*Output)->AddRef();
203 return NOERROR;
204 }
205 else if (IsEqualGUID(refiid, IID_IPersistPropertyBag))
206 {
207 *Output = (IPersistPropertyBag*)(this);
208 reinterpret_cast<IPersistPropertyBag*>(*Output)->AddRef();
209 return NOERROR;
210 }
211 else if (IsEqualGUID(refiid, IID_IAMDeviceRemoval))
212 {
213 *Output = (IAMDeviceRemoval*)(this);
214 reinterpret_cast<IAMDeviceRemoval*>(*Output)->AddRef();
215 return NOERROR;
216 }
217 else if (IsEqualGUID(refiid, IID_IPersistStream))
218 {
219 *Output = (IPersistStream*)(this);
220 reinterpret_cast<IPersistStream*>(*Output)->AddRef();
221 return NOERROR;
222 }
223 else if (IsEqualGUID(refiid, IID_IKsObject))
224 {
225 *Output = (IKsObject*)(this);
226 reinterpret_cast<IKsObject*>(*Output)->AddRef();
227 return NOERROR;
228 }
229 else if (IsEqualGUID(refiid, IID_IReferenceClock))
230 {
231 *Output = (IReferenceClock*)(this);
232 reinterpret_cast<IReferenceClock*>(*Output)->AddRef();
233 return NOERROR;
234 }
235 else if (IsEqualGUID(refiid, IID_IMediaSeeking))
236 {
237 *Output = (IMediaSeeking*)(this);
238 reinterpret_cast<IMediaSeeking*>(*Output)->AddRef();
239 return NOERROR;
240 }
241 else if (IsEqualGUID(refiid, IID_IAMFilterMiscFlags))
242 {
243 *Output = (IAMFilterMiscFlags*)(this);
244 reinterpret_cast<IAMFilterMiscFlags*>(*Output)->AddRef();
245 return NOERROR;
246 }
247 else if (IsEqualGUID(refiid, IID_IKsControl))
248 {
249 *Output = (IKsControl*)(this);
250 reinterpret_cast<IKsControl*>(*Output)->AddRef();
251 return NOERROR;
252 }
253 else if (IsEqualGUID(refiid, IID_IKsPropertySet))
254 {
255 *Output = (IKsPropertySet*)(this);
256 reinterpret_cast<IKsPropertySet*>(*Output)->AddRef();
257 return NOERROR;
258 }
259 else if (IsEqualGUID(refiid, IID_IKsTopology))
260 {
261 *Output = (IKsTopology*)(this);
262 reinterpret_cast<IKsTopology*>(*Output)->AddRef();
263 return NOERROR;
264 }
265 else if (IsEqualGUID(refiid, IID_IKsAggregateControl))
266 {
267 *Output = (IKsAggregateControl*)(this);
268 reinterpret_cast<IKsAggregateControl*>(*Output)->AddRef();
269 return NOERROR;
270 }
271 else if (IsEqualGUID(refiid, IID_IKsClockPropertySet))
272 {
273 *Output = (IKsClockPropertySet*)(this);
274 reinterpret_cast<IKsClockPropertySet*>(*Output)->AddRef();
275 return NOERROR;
276 }
277 else if (IsEqualGUID(refiid, IID_ISpecifyPropertyPages))
278 {
279 *Output = (ISpecifyPropertyPages*)(this);
280 reinterpret_cast<ISpecifyPropertyPages*>(*Output)->AddRef();
281 return NOERROR;
282 }
283
284 for(ULONG Index = 0; Index < m_Plugins.size(); Index++)
285 {
286 if (m_Pins[Index])
287 {
288 HRESULT hr = m_Plugins[Index]->QueryInterface(refiid, Output);
289 if (SUCCEEDED(hr))
290 {
291 WCHAR Buffer[100];
292 LPOLESTR lpstr;
293 StringFromCLSID(refiid, &lpstr);
294 swprintf(Buffer, L"CKsProxy::QueryInterface plugin %lu supports interface %s\n", Index, lpstr);
295 OutputDebugStringW(Buffer);
296 CoTaskMemFree(lpstr);
297 return hr;
298 }
299 }
300 }
301
302 WCHAR Buffer[MAX_PATH];
303 LPOLESTR lpstr;
304 StringFromCLSID(refiid, &lpstr);
305 swprintf(Buffer, L"CKsProxy::QueryInterface: NoInterface for %s !!!\n", lpstr);
306 OutputDebugStringW(Buffer);
307 CoTaskMemFree(lpstr);
308
309
310 return E_NOINTERFACE;
311 }
312
313 //-------------------------------------------------------------------
314 // ISpecifyPropertyPages
315 //
316
317 HRESULT
318 STDMETHODCALLTYPE
319 CKsProxy::GetPages(CAUUID *pPages)
320 {
321 OutputDebugStringW(L"CKsProxy::GetPages NotImplemented\n");
322
323 if (!pPages)
324 return E_POINTER;
325
326 pPages->cElems = 0;
327 pPages->pElems = NULL;
328
329 return S_OK;
330 }
331
332 //-------------------------------------------------------------------
333 // IKsClockPropertySet interface
334 //
335 HRESULT
336 STDMETHODCALLTYPE
337 CKsProxy::KsGetTime(
338 LONGLONG* Time)
339 {
340 OutputDebugStringW(L"CKsProxy::KsGetTime NotImplemented\n");
341 return E_NOTIMPL;
342 }
343
344 HRESULT
345 STDMETHODCALLTYPE
346 CKsProxy::KsSetTime(
347 LONGLONG Time)
348 {
349 OutputDebugStringW(L"CKsProxy::KsSetTime NotImplemented\n");
350 return E_NOTIMPL;
351 }
352
353 HRESULT
354 STDMETHODCALLTYPE
355 CKsProxy::KsGetPhysicalTime(
356 LONGLONG* Time)
357 {
358 OutputDebugStringW(L"CKsProxy::KsGetPhysicalTime NotImplemented\n");
359 return E_NOTIMPL;
360 }
361
362 HRESULT
363 STDMETHODCALLTYPE
364 CKsProxy::KsSetPhysicalTime(
365 LONGLONG Time)
366 {
367 OutputDebugStringW(L"CKsProxy::KsSetPhysicalTime NotImplemented\n");
368 return E_NOTIMPL;
369 }
370
371 HRESULT
372 STDMETHODCALLTYPE
373 CKsProxy::KsGetCorrelatedTime(
374 KSCORRELATED_TIME* CorrelatedTime)
375 {
376 OutputDebugStringW(L"CKsProxy::KsGetCorrelatedTime NotImplemented\n");
377 return E_NOTIMPL;
378 }
379
380 HRESULT
381 STDMETHODCALLTYPE
382 CKsProxy::KsSetCorrelatedTime(
383 KSCORRELATED_TIME* CorrelatedTime)
384 {
385 OutputDebugStringW(L"CKsProxy::KsSetCorrelatedTime NotImplemented\n");
386 return E_NOTIMPL;
387 }
388
389 HRESULT
390 STDMETHODCALLTYPE
391 CKsProxy::KsGetCorrelatedPhysicalTime(
392 KSCORRELATED_TIME* CorrelatedTime)
393 {
394 OutputDebugStringW(L"CKsProxy::KsGetCorrelatedPhysicalTime NotImplemented\n");
395 return E_NOTIMPL;
396 }
397
398 HRESULT
399 STDMETHODCALLTYPE
400 CKsProxy::KsSetCorrelatedPhysicalTime(
401 KSCORRELATED_TIME* CorrelatedTime)
402 {
403 OutputDebugStringW(L"CKsProxy::KsSetCorrelatedPhysicalTime NotImplemented\n");
404 return E_NOTIMPL;
405 }
406
407 HRESULT
408 STDMETHODCALLTYPE
409 CKsProxy::KsGetResolution(
410 KSRESOLUTION* Resolution)
411 {
412 OutputDebugStringW(L"CKsProxy::KsGetResolution NotImplemented\n");
413 return E_NOTIMPL;
414 }
415
416 HRESULT
417 STDMETHODCALLTYPE
418 CKsProxy::KsGetState(
419 KSSTATE* State)
420 {
421 OutputDebugStringW(L"CKsProxy::KsGetState NotImplemented\n");
422 return E_NOTIMPL;
423 }
424
425 //-------------------------------------------------------------------
426 // IReferenceClock interface
427 //
428 HRESULT
429 STDMETHODCALLTYPE
430 CKsProxy::GetTime(
431 REFERENCE_TIME *pTime)
432 {
433 OutputDebugStringW(L"CKsProxy::GetTime NotImplemented\n");
434 return E_NOTIMPL;
435 }
436
437 HRESULT
438 STDMETHODCALLTYPE
439 CKsProxy::AdviseTime(
440 REFERENCE_TIME baseTime,
441 REFERENCE_TIME streamTime,
442 HEVENT hEvent,
443 DWORD_PTR *pdwAdviseCookie)
444 {
445 OutputDebugStringW(L"CKsProxy::AdviseTime NotImplemented\n");
446 return E_NOTIMPL;
447 }
448
449 HRESULT
450 STDMETHODCALLTYPE
451 CKsProxy::AdvisePeriodic(
452 REFERENCE_TIME startTime,
453 REFERENCE_TIME periodTime,
454 HSEMAPHORE hSemaphore,
455 DWORD_PTR *pdwAdviseCookie)
456 {
457 OutputDebugStringW(L"CKsProxy::AdvisePeriodic NotImplemented\n");
458 return E_NOTIMPL;
459 }
460
461 HRESULT
462 STDMETHODCALLTYPE
463 CKsProxy::Unadvise(
464 DWORD_PTR dwAdviseCookie)
465 {
466 OutputDebugStringW(L"CKsProxy::Unadvise NotImplemented\n");
467 return E_NOTIMPL;
468 }
469
470 //-------------------------------------------------------------------
471 // IMediaSeeking interface
472 //
473 HRESULT
474 STDMETHODCALLTYPE
475 CKsProxy::GetCapabilities(
476 DWORD *pCapabilities)
477 {
478 OutputDebugStringW(L"CKsProxy::GetCapabilities NotImplemented\n");
479 return E_NOTIMPL;
480 }
481
482 HRESULT
483 STDMETHODCALLTYPE
484 CKsProxy::CheckCapabilities(
485 DWORD *pCapabilities)
486 {
487 OutputDebugStringW(L"CKsProxy::CheckCapabilities NotImplemented\n");
488 return E_NOTIMPL;
489 }
490
491 HRESULT
492 STDMETHODCALLTYPE
493 CKsProxy::IsFormatSupported(
494 const GUID *pFormat)
495 {
496 KSPROPERTY Property;
497 PKSMULTIPLE_ITEM FormatList;
498 LPGUID pGuid;
499 ULONG Index;
500 HRESULT hr = S_FALSE;
501 ULONG BytesReturned;
502
503 OutputDebugStringW(L"CKsProxy::IsFormatSupported\n");
504
505 if (!pFormat)
506 return E_POINTER;
507
508 Property.Set = KSPROPSETID_MediaSeeking;
509 Property.Id = KSPROPERTY_MEDIASEEKING_FORMATS;
510 Property.Flags = KSPROPERTY_TYPE_GET;
511
512 // query for format size list
513 hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), NULL, 0, &BytesReturned);
514
515 if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_MORE_DATA))
516 {
517 // allocate format list
518 FormatList = (PKSMULTIPLE_ITEM)CoTaskMemAlloc(BytesReturned);
519 if (!FormatList)
520 {
521 // not enough memory
522 return E_OUTOFMEMORY;
523 }
524
525 // get format list
526 hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)FormatList, BytesReturned, &BytesReturned);
527 if (FAILED(hr))
528 {
529 // failed to query format list
530 CoTaskMemFree(FormatList);
531 return hr;
532 }
533
534 //iterate through format list
535 pGuid = (LPGUID)(FormatList + 1);
536 for(Index = 0; Index < FormatList->Count; Index++)
537 {
538 if (IsEqualGUID(*pGuid, *pFormat))
539 {
540 OutputDebugStringW(L"CKsProxy::IsFormatSupported found format\n");
541 CoTaskMemFree(FormatList);
542 return S_OK;
543 }
544 pGuid++;
545 }
546
547 OutputDebugStringW(L"CKsProxy::IsFormatSupported FormatNotFound\n");
548 // free format list
549 CoTaskMemFree(FormatList);
550 }
551
552 // check if all plugins support it
553 for(Index = 0; Index < m_Plugins.size(); Index++)
554 {
555 // get plugin
556 IUnknown * Plugin = m_Plugins[Index];
557
558 if (!Plugin)
559 continue;
560
561 // query for IMediaSeeking interface
562 IMediaSeeking *pSeek = NULL;
563 hr = Plugin->QueryInterface(IID_IMediaSeeking, (void**)&pSeek);
564 if (FAILED(hr))
565 {
566 // plugin does not support interface
567 hr = S_FALSE;
568 OutputDebugStringW(L"CKsProxy::IsFormatSupported plugin does not support IMediaSeeking interface\n");
569 break;
570 }
571
572 // query if it is supported
573 hr = pSeek->IsFormatSupported(pFormat);
574 // release interface
575 pSeek->Release();
576
577 if (FAILED(hr) || hr == S_FALSE)
578 break;
579 }
580
581 return hr;
582 }
583
584 HRESULT
585 STDMETHODCALLTYPE
586 CKsProxy::QueryPreferredFormat(
587 GUID *pFormat)
588 {
589 OutputDebugStringW(L"CKsProxy::QueryPreferredFormat NotImplemented\n");
590 return E_NOTIMPL;
591 }
592
593 HRESULT
594 STDMETHODCALLTYPE
595 CKsProxy::GetTimeFormat(
596 GUID *pFormat)
597 {
598 OutputDebugStringW(L"CKsProxy::GetTimeFormat NotImplemented\n");
599 return E_NOTIMPL;
600 }
601
602 HRESULT
603 STDMETHODCALLTYPE
604 CKsProxy::IsUsingTimeFormat(
605 const GUID *pFormat)
606 {
607 OutputDebugStringW(L"CKsProxy::IsUsingTimeFormat NotImplemented\n");
608 return E_NOTIMPL;
609 }
610
611 HRESULT
612 STDMETHODCALLTYPE
613 CKsProxy::SetTimeFormat(
614 const GUID *pFormat)
615 {
616 OutputDebugStringW(L"CKsProxy::SetTimeFormat NotImplemented\n");
617 return E_NOTIMPL;
618 }
619
620 HRESULT
621 STDMETHODCALLTYPE
622 CKsProxy::GetDuration(
623 LONGLONG *pDuration)
624 {
625 OutputDebugStringW(L"CKsProxy::GetDuration NotImplemented\n");
626 return E_NOTIMPL;
627 }
628
629 HRESULT
630 STDMETHODCALLTYPE
631 CKsProxy::GetStopPosition(
632 LONGLONG *pStop)
633 {
634 OutputDebugStringW(L"CKsProxy::GetStopPosition NotImplemented\n");
635 return E_NOTIMPL;
636 }
637
638 HRESULT
639 STDMETHODCALLTYPE
640 CKsProxy::GetCurrentPosition(
641 LONGLONG *pCurrent)
642 {
643 OutputDebugStringW(L"CKsProxy::GetCurrentPosition NotImplemented\n");
644 return E_NOTIMPL;
645 }
646
647 HRESULT
648 STDMETHODCALLTYPE
649 CKsProxy::ConvertTimeFormat(
650 LONGLONG *pTarget,
651 const GUID *pTargetFormat,
652 LONGLONG Source,
653 const GUID *pSourceFormat)
654 {
655 OutputDebugStringW(L"CKsProxy::ConvertTimeFormat NotImplemented\n");
656 return E_NOTIMPL;
657 }
658
659 HRESULT
660 STDMETHODCALLTYPE
661 CKsProxy::SetPositions(
662 LONGLONG *pCurrent,
663 DWORD dwCurrentFlags,
664 LONGLONG *pStop,
665 DWORD dwStopFlags)
666 {
667 OutputDebugStringW(L"CKsProxy::SetPositions NotImplemented\n");
668 return E_NOTIMPL;
669 }
670
671 HRESULT
672 STDMETHODCALLTYPE
673 CKsProxy::GetPositions(
674 LONGLONG *pCurrent,
675 LONGLONG *pStop)
676 {
677 OutputDebugStringW(L"CKsProxy::GetPositions NotImplemented\n");
678 return E_NOTIMPL;
679 }
680
681 HRESULT
682 STDMETHODCALLTYPE
683 CKsProxy::GetAvailable(
684 LONGLONG *pEarliest,
685 LONGLONG *pLatest)
686 {
687 OutputDebugStringW(L"CKsProxy::GetAvailable NotImplemented\n");
688 return E_NOTIMPL;
689 }
690
691 HRESULT
692 STDMETHODCALLTYPE
693 CKsProxy::SetRate(
694 double dRate)
695 {
696 OutputDebugStringW(L"CKsProxy::SetRate NotImplemented\n");
697 return E_NOTIMPL;
698 }
699
700 HRESULT
701 STDMETHODCALLTYPE
702 CKsProxy::GetRate(
703 double *pdRate)
704 {
705 OutputDebugStringW(L"CKsProxy::GetRate NotImplemented\n");
706 return E_NOTIMPL;
707 }
708
709 HRESULT
710 STDMETHODCALLTYPE
711 CKsProxy::GetPreroll(
712 LONGLONG *pllPreroll)
713 {
714 OutputDebugStringW(L"CKsProxy::GetPreroll NotImplemented\n");
715 return E_NOTIMPL;
716 }
717
718 //-------------------------------------------------------------------
719 // IAMFilterMiscFlags interface
720 //
721
722 ULONG
723 STDMETHODCALLTYPE
724 CKsProxy::GetMiscFlags()
725 {
726 ULONG Index;
727 ULONG Flags = 0;
728 HRESULT hr;
729 PIN_DIRECTION PinDirection;
730 KSPIN_COMMUNICATION Communication;
731
732 for(Index = 0; Index < m_Pins.size(); Index++)
733 {
734 // get current pin
735 IPin * pin = m_Pins[Index];
736 // query direction
737 hr = pin->QueryDirection(&PinDirection);
738 if (SUCCEEDED(hr))
739 {
740 if (PinDirection == PINDIR_INPUT)
741 {
742 if (SUCCEEDED(GetPinCommunication(Index, //FIXME verify PinId
743 &Communication)))
744 {
745 if (Communication == KSPIN_COMMUNICATION_NONE || Communication == KSPIN_COMMUNICATION_BRIDGE)
746 {
747 Flags |= AM_FILTER_MISC_FLAGS_IS_SOURCE;
748 }
749 }
750 }
751 }
752 }
753
754 OutputDebugStringW(L"CKsProxy::GetMiscFlags stub\n");
755 return Flags;
756 }
757
758 //-------------------------------------------------------------------
759 // IKsControl
760 //
761 HRESULT
762 STDMETHODCALLTYPE
763 CKsProxy::KsProperty(
764 PKSPROPERTY Property,
765 ULONG PropertyLength,
766 LPVOID PropertyData,
767 ULONG DataLength,
768 ULONG* BytesReturned)
769 {
770 assert(m_hDevice != 0);
771 return KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)Property, PropertyLength, (PVOID)PropertyData, DataLength, BytesReturned);
772 }
773
774 HRESULT
775 STDMETHODCALLTYPE
776 CKsProxy::KsMethod(
777 PKSMETHOD Method,
778 ULONG MethodLength,
779 LPVOID MethodData,
780 ULONG DataLength,
781 ULONG* BytesReturned)
782 {
783 assert(m_hDevice != 0);
784 return KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_METHOD, (PVOID)Method, MethodLength, (PVOID)MethodData, DataLength, BytesReturned);
785 }
786
787 HRESULT
788 STDMETHODCALLTYPE
789 CKsProxy::KsEvent(
790 PKSEVENT Event,
791 ULONG EventLength,
792 LPVOID EventData,
793 ULONG DataLength,
794 ULONG* BytesReturned)
795 {
796 assert(m_hDevice != 0);
797
798 if (EventLength)
799 return KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_ENABLE_EVENT, (PVOID)Event, EventLength, (PVOID)EventData, DataLength, BytesReturned);
800 else
801 return KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_DISABLE_EVENT, (PVOID)Event, EventLength, NULL, 0, BytesReturned);
802 }
803
804
805 //-------------------------------------------------------------------
806 // IKsPropertySet
807 //
808 HRESULT
809 STDMETHODCALLTYPE
810 CKsProxy::Set(
811 REFGUID guidPropSet,
812 DWORD dwPropID,
813 LPVOID pInstanceData,
814 DWORD cbInstanceData,
815 LPVOID pPropData,
816 DWORD cbPropData)
817 {
818 ULONG BytesReturned;
819
820 if (cbInstanceData)
821 {
822 PKSPROPERTY Property = (PKSPROPERTY)CoTaskMemAlloc(sizeof(KSPROPERTY) + cbInstanceData);
823 if (!Property)
824 return E_OUTOFMEMORY;
825
826 Property->Set = guidPropSet;
827 Property->Id = dwPropID;
828 Property->Flags = KSPROPERTY_TYPE_SET;
829
830 CopyMemory((Property+1), pInstanceData, cbInstanceData);
831
832 HRESULT hr = KsProperty(Property, sizeof(KSPROPERTY) + cbInstanceData, pPropData, cbPropData, &BytesReturned);
833 CoTaskMemFree(Property);
834 return hr;
835 }
836 else
837 {
838 KSPROPERTY Property;
839
840 Property.Set = guidPropSet;
841 Property.Id = dwPropID;
842 Property.Flags = KSPROPERTY_TYPE_SET;
843
844 HRESULT hr = KsProperty(&Property, sizeof(KSPROPERTY), pPropData, cbPropData, &BytesReturned);
845 return hr;
846 }
847 }
848
849 HRESULT
850 STDMETHODCALLTYPE
851 CKsProxy::Get(
852 REFGUID guidPropSet,
853 DWORD dwPropID,
854 LPVOID pInstanceData,
855 DWORD cbInstanceData,
856 LPVOID pPropData,
857 DWORD cbPropData,
858 DWORD *pcbReturned)
859 {
860 ULONG BytesReturned;
861
862 if (cbInstanceData)
863 {
864 PKSPROPERTY Property = (PKSPROPERTY)CoTaskMemAlloc(sizeof(KSPROPERTY) + cbInstanceData);
865 if (!Property)
866 return E_OUTOFMEMORY;
867
868 Property->Set = guidPropSet;
869 Property->Id = dwPropID;
870 Property->Flags = KSPROPERTY_TYPE_GET;
871
872 CopyMemory((Property+1), pInstanceData, cbInstanceData);
873
874 HRESULT hr = KsProperty(Property, sizeof(KSPROPERTY) + cbInstanceData, pPropData, cbPropData, &BytesReturned);
875 CoTaskMemFree(Property);
876 return hr;
877 }
878 else
879 {
880 KSPROPERTY Property;
881
882 Property.Set = guidPropSet;
883 Property.Id = dwPropID;
884 Property.Flags = KSPROPERTY_TYPE_GET;
885
886 HRESULT hr = KsProperty(&Property, sizeof(KSPROPERTY), pPropData, cbPropData, &BytesReturned);
887 return hr;
888 }
889 }
890
891 HRESULT
892 STDMETHODCALLTYPE
893 CKsProxy::QuerySupported(
894 REFGUID guidPropSet,
895 DWORD dwPropID,
896 DWORD *pTypeSupport)
897 {
898 KSPROPERTY Property;
899 ULONG BytesReturned;
900
901 Property.Set = guidPropSet;
902 Property.Id = dwPropID;
903 Property.Flags = KSPROPERTY_TYPE_SETSUPPORT;
904
905 return KsProperty(&Property, sizeof(KSPROPERTY), pTypeSupport, sizeof(DWORD), &BytesReturned);
906 }
907
908
909 //-------------------------------------------------------------------
910 // IKsTopology interface
911 //
912 HRESULT
913 STDMETHODCALLTYPE
914 CKsProxy::CreateNodeInstance(
915 ULONG NodeId,
916 ULONG Flags,
917 ACCESS_MASK DesiredAccess,
918 IUnknown* UnkOuter,
919 REFGUID InterfaceId,
920 LPVOID* Interface)
921 {
922 OutputDebugStringW(L"CKsProxy::CreateNodeInstance NotImplemented\n");
923 return E_NOTIMPL;
924 }
925
926 //-------------------------------------------------------------------
927 // IKsAggregateControl interface
928 //
929 HRESULT
930 STDMETHODCALLTYPE
931 CKsProxy::KsAddAggregate(
932 IN REFGUID AggregateClass)
933 {
934 OutputDebugStringW(L"CKsProxy::KsAddAggregate NotImplemented\n");
935 return E_NOTIMPL;
936 }
937
938 HRESULT
939 STDMETHODCALLTYPE
940 CKsProxy::KsRemoveAggregate(
941 REFGUID AggregateClass)
942 {
943 OutputDebugStringW(L"CKsProxy::KsRemoveAggregate NotImplemented\n");
944 return E_NOTIMPL;
945 }
946
947
948 //-------------------------------------------------------------------
949 // IPersistStream interface
950 //
951
952 HRESULT
953 STDMETHODCALLTYPE
954 CKsProxy::IsDirty()
955 {
956 OutputDebugStringW(L"CKsProxy::IsDirty Notimplemented\n");
957 DebugBreak();
958 return E_NOTIMPL;
959 }
960
961 HRESULT
962 STDMETHODCALLTYPE
963 CKsProxy::Load(
964 IStream *pStm)
965 {
966 HRESULT hr;
967 WCHAR Buffer[1000];
968 AM_MEDIA_TYPE MediaType;
969 ULONG BytesReturned;
970 LONG Length;
971
972 ULONG PinId;
973 LPOLESTR pMajor, pSub, pFormat;
974
975 OutputDebugStringW(L"CKsProxy::Load\n");
976
977 #if 0
978 ULONG Version = ReadInt(pStm, hr);
979 if (Version != 1)
980 return E_FAIL;
981 #endif
982
983 hr = pStm->Read(&Length, sizeof(ULONG), &BytesReturned);
984 swprintf(Buffer, L"Length hr %x hr length %lu\n", hr, Length);
985 OutputDebugStringW(Buffer);
986
987 do
988 {
989 hr = pStm->Read(&PinId, sizeof(ULONG), &BytesReturned);
990 swprintf(Buffer, L"Read: hr %08x PinId %lx BytesReturned %lu\n", hr, PinId, BytesReturned);
991 OutputDebugStringW(Buffer);
992
993 if (FAILED(hr) || !BytesReturned)
994 break;
995
996 Length -= BytesReturned;
997
998 hr = pStm->Read(&MediaType, sizeof(AM_MEDIA_TYPE), &BytesReturned);
999 if (FAILED(hr) || BytesReturned != sizeof(AM_MEDIA_TYPE))
1000 {
1001 swprintf(Buffer, L"Read failed with %lx\n", hr);
1002 OutputDebugStringW(Buffer);
1003 break;
1004 }
1005
1006
1007 StringFromIID(MediaType.majortype, &pMajor);
1008 StringFromIID(MediaType.subtype , &pSub);
1009 StringFromIID(MediaType.formattype, &pFormat);
1010
1011 swprintf(Buffer, L"BytesReturned %lu majortype %s subtype %s bFixedSizeSamples %u bTemporalCompression %u lSampleSize %u formattype %s, pUnk %p cbFormat %u pbFormat %p\n", BytesReturned, pMajor, pSub, MediaType.bFixedSizeSamples, MediaType.bTemporalCompression, MediaType.lSampleSize, pFormat, MediaType.pUnk, MediaType.cbFormat, MediaType.pbFormat);
1012 OutputDebugStringW(Buffer);
1013
1014 Length -= BytesReturned;
1015
1016
1017 if (MediaType.cbFormat)
1018 {
1019 MediaType.pbFormat = (BYTE*)CoTaskMemAlloc(MediaType.cbFormat);
1020 if (!MediaType.pbFormat)
1021 return E_OUTOFMEMORY;
1022
1023 hr = pStm->Read(&MediaType.pbFormat, sizeof(MediaType.cbFormat), &BytesReturned);
1024 if (FAILED(hr))
1025 {
1026 swprintf(Buffer, L"ReadFormat failed with %lx\n", hr);
1027 OutputDebugStringW(Buffer);
1028 break;
1029 }
1030 Length -= BytesReturned;
1031 }
1032
1033 }while(Length > 0);
1034
1035 DebugBreak();
1036 return S_OK;
1037 }
1038
1039 HRESULT
1040 STDMETHODCALLTYPE
1041 CKsProxy::Save(
1042 IStream *pStm,
1043 BOOL fClearDirty)
1044 {
1045 OutputDebugStringW(L"CKsProxy::Save Notimplemented\n");
1046 return E_NOTIMPL;
1047 }
1048
1049 HRESULT
1050 STDMETHODCALLTYPE
1051 CKsProxy::GetSizeMax(
1052 ULARGE_INTEGER *pcbSize)
1053 {
1054 OutputDebugStringW(L"CKsProxy::GetSizeMax Notimplemented\n");
1055 DebugBreak();
1056 return E_NOTIMPL;
1057 }
1058
1059 //-------------------------------------------------------------------
1060 // IAMDeviceRemoval interface
1061 //
1062
1063 HRESULT
1064 STDMETHODCALLTYPE
1065 CKsProxy::DeviceInfo(CLSID *pclsidInterfaceClass, LPWSTR *pwszSymbolicLink)
1066 {
1067 if (!m_DevicePath)
1068 {
1069 // object not initialized
1070 return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_FILE_NOT_FOUND);
1071 }
1072
1073 // copy device interface guid
1074 CopyMemory(pclsidInterfaceClass, &m_DeviceInterfaceGUID, sizeof(GUID));
1075
1076 if (pwszSymbolicLink)
1077 {
1078 *pwszSymbolicLink = (LPWSTR)CoTaskMemAlloc((wcslen(m_DevicePath)+1) * sizeof(WCHAR));
1079 if (!*pwszSymbolicLink)
1080 return E_OUTOFMEMORY;
1081
1082 wcscpy(*pwszSymbolicLink, m_DevicePath);
1083 }
1084 return S_OK;
1085 }
1086 HRESULT
1087 STDMETHODCALLTYPE
1088 CKsProxy::Reassociate(void)
1089 {
1090 if (!m_DevicePath || m_hDevice)
1091 {
1092 // file path not available
1093 return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_FILE_NOT_FOUND);
1094 }
1095
1096 m_hDevice = CreateFileW(m_DevicePath, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
1097 if (!m_hDevice)
1098 {
1099 // failed to open device
1100 return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, GetLastError());
1101 }
1102
1103 // success
1104 return NOERROR;
1105 }
1106
1107 HRESULT
1108 STDMETHODCALLTYPE
1109 CKsProxy::Disassociate(void)
1110 {
1111 if (!m_hDevice)
1112 return E_HANDLE;
1113
1114 CloseHandle(m_hDevice);
1115 m_hDevice = NULL;
1116 return NOERROR;
1117 }
1118
1119
1120
1121
1122 //-------------------------------------------------------------------
1123 // IKsObject interface
1124 //
1125
1126 HANDLE
1127 STDMETHODCALLTYPE
1128 CKsProxy::KsGetObjectHandle()
1129 {
1130 return m_hDevice;
1131 }
1132
1133 //-------------------------------------------------------------------
1134 // IPersistPropertyBag interface
1135 //
1136 HRESULT
1137 STDMETHODCALLTYPE
1138 CKsProxy::InitNew( void)
1139 {
1140 return S_OK;
1141 }
1142
1143 HRESULT
1144 STDMETHODCALLTYPE
1145 CKsProxy::GetSupportedSets(
1146 LPGUID * pOutGuid,
1147 PULONG NumGuids)
1148 {
1149 KSPROPERTY Property;
1150 LPGUID pGuid;
1151 ULONG NumProperty = 0;
1152 ULONG NumMethods = 0;
1153 ULONG NumEvents = 0;
1154 ULONG Length;
1155 ULONG BytesReturned;
1156 HRESULT hr;
1157
1158 Property.Set = GUID_NULL;
1159 Property.Id = 0;
1160 Property.Flags = KSPROPERTY_TYPE_SETSUPPORT;
1161
1162 KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), NULL, 0, &NumProperty);
1163 KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_METHOD, (PVOID)&Property, sizeof(KSPROPERTY), NULL, 0, &NumMethods);
1164 KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_ENABLE_EVENT, (PVOID)&Property, sizeof(KSPROPERTY), NULL, 0, &NumEvents);
1165
1166 Length = NumProperty + NumMethods + NumEvents;
1167
1168 // allocate guid buffer
1169 pGuid = (LPGUID)CoTaskMemAlloc(Length);
1170 if (!pGuid)
1171 {
1172 // failed
1173 return E_OUTOFMEMORY;
1174 }
1175
1176 NumProperty /= sizeof(GUID);
1177 NumMethods /= sizeof(GUID);
1178 NumEvents /= sizeof(GUID);
1179
1180 // get all properties
1181 hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)pGuid, Length, &BytesReturned);
1182 if (FAILED(hr))
1183 {
1184 CoTaskMemFree(pGuid);
1185 return E_FAIL;
1186 }
1187 Length -= BytesReturned;
1188
1189 // get all methods
1190 if (Length)
1191 {
1192 hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_METHOD, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&pGuid[NumProperty], Length, &BytesReturned);
1193 if (FAILED(hr))
1194 {
1195 CoTaskMemFree(pGuid);
1196 return E_FAIL;
1197 }
1198 Length -= BytesReturned;
1199 }
1200
1201 // get all events
1202 if (Length)
1203 {
1204 hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_ENABLE_EVENT, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&pGuid[NumProperty+NumMethods], Length, &BytesReturned);
1205 if (FAILED(hr))
1206 {
1207 CoTaskMemFree(pGuid);
1208 return E_FAIL;
1209 }
1210 Length -= BytesReturned;
1211 }
1212
1213 #ifdef KSPROXY_TRACE
1214 WCHAR Buffer[200];
1215 swprintf(Buffer, L"NumProperty %lu NumMethods %lu NumEvents %lu\n", NumProperty, NumMethods, NumEvents);
1216 OutputDebugStringW(Buffer);
1217 #endif
1218
1219 *pOutGuid = pGuid;
1220 *NumGuids = NumProperty+NumEvents+NumMethods;
1221 return S_OK;
1222 }
1223
1224 HRESULT
1225 STDMETHODCALLTYPE
1226 CKsProxy::LoadProxyPlugins(
1227 LPGUID pGuids,
1228 ULONG NumGuids)
1229 {
1230 ULONG Index;
1231 LPOLESTR pStr;
1232 HKEY hKey, hSubKey;
1233 HRESULT hr;
1234 IUnknown * pUnknown;
1235
1236 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\MediaInterfaces", 0, KEY_READ, &hKey) != ERROR_SUCCESS)
1237 {
1238 OutputDebugStringW(L"CKsProxy::LoadProxyPlugins failed to open MediaInterfaces key\n");
1239 return E_FAIL;
1240 }
1241
1242 // enumerate all sets
1243 for(Index = 0; Index < NumGuids; Index++)
1244 {
1245 // convert to string
1246 hr = StringFromCLSID(pGuids[Index], &pStr);
1247 if (FAILED(hr))
1248 return E_FAIL;
1249
1250 // now try open class key
1251 if (RegOpenKeyExW(hKey, pStr, 0, KEY_READ, &hSubKey) != ERROR_SUCCESS)
1252 {
1253 // no plugin for that set exists
1254 CoTaskMemFree(pStr);
1255 continue;
1256 }
1257
1258 // try load plugin
1259 hr = CoCreateInstance(pGuids[Index], (IBaseFilter*)this, CLSCTX_INPROC_SERVER, IID_IUnknown, (void**)&pUnknown);
1260 if (SUCCEEDED(hr))
1261 {
1262 // store plugin
1263 m_Plugins.push_back(pUnknown);
1264 }
1265 // close key
1266 RegCloseKey(hSubKey);
1267 }
1268
1269 // close media interfaces key
1270 RegCloseKey(hKey);
1271 return S_OK;
1272 }
1273
1274 HRESULT
1275 STDMETHODCALLTYPE
1276 CKsProxy::GetNumberOfPins(
1277 PULONG NumPins)
1278 {
1279 KSPROPERTY Property;
1280 ULONG BytesReturned;
1281
1282 // setup request
1283 Property.Set = KSPROPSETID_Pin;
1284 Property.Id = KSPROPERTY_PIN_CTYPES;
1285 Property.Flags = KSPROPERTY_TYPE_GET;
1286
1287 return KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)NumPins, sizeof(ULONG), &BytesReturned);
1288 }
1289
1290 HRESULT
1291 STDMETHODCALLTYPE
1292 CKsProxy::GetPinInstanceCount(
1293 ULONG PinId,
1294 PKSPIN_CINSTANCES Instances)
1295 {
1296 KSP_PIN Property;
1297 ULONG BytesReturned;
1298
1299 // setup request
1300 Property.Property.Set = KSPROPSETID_Pin;
1301 Property.Property.Id = KSPROPERTY_PIN_CINSTANCES;
1302 Property.Property.Flags = KSPROPERTY_TYPE_GET;
1303 Property.PinId = PinId;
1304 Property.Reserved = 0;
1305
1306 return KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSP_PIN), (PVOID)Instances, sizeof(KSPIN_CINSTANCES), &BytesReturned);
1307 }
1308
1309 HRESULT
1310 STDMETHODCALLTYPE
1311 CKsProxy::GetPinCommunication(
1312 ULONG PinId,
1313 KSPIN_COMMUNICATION * Communication)
1314 {
1315 KSP_PIN Property;
1316 ULONG BytesReturned;
1317
1318 // setup request
1319 Property.Property.Set = KSPROPSETID_Pin;
1320 Property.Property.Id = KSPROPERTY_PIN_COMMUNICATION;
1321 Property.Property.Flags = KSPROPERTY_TYPE_GET;
1322 Property.PinId = PinId;
1323 Property.Reserved = 0;
1324
1325 return KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSP_PIN), (PVOID)Communication, sizeof(KSPIN_COMMUNICATION), &BytesReturned);
1326 }
1327
1328 HRESULT
1329 STDMETHODCALLTYPE
1330 CKsProxy::GetPinDataflow(
1331 ULONG PinId,
1332 KSPIN_DATAFLOW * DataFlow)
1333 {
1334 KSP_PIN Property;
1335 ULONG BytesReturned;
1336
1337 // setup request
1338 Property.Property.Set = KSPROPSETID_Pin;
1339 Property.Property.Id = KSPROPERTY_PIN_DATAFLOW;
1340 Property.Property.Flags = KSPROPERTY_TYPE_GET;
1341 Property.PinId = PinId;
1342 Property.Reserved = 0;
1343
1344 return KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSP_PIN), (PVOID)DataFlow, sizeof(KSPIN_DATAFLOW), &BytesReturned);
1345 }
1346
1347 HRESULT
1348 STDMETHODCALLTYPE
1349 CKsProxy::GetPinName(
1350 ULONG PinId,
1351 KSPIN_DATAFLOW DataFlow,
1352 ULONG PinCount,
1353 LPWSTR * OutPinName)
1354 {
1355 KSP_PIN Property;
1356 LPWSTR PinName;
1357 ULONG BytesReturned;
1358 HRESULT hr;
1359 WCHAR Buffer[100];
1360
1361 // setup request
1362 Property.Property.Set = KSPROPSETID_Pin;
1363 Property.Property.Id = KSPROPERTY_PIN_NAME;
1364 Property.Property.Flags = KSPROPERTY_TYPE_GET;
1365 Property.PinId = PinId;
1366 Property.Reserved = 0;
1367
1368 // #1 try get it from pin directly
1369 hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSP_PIN), NULL, 0, &BytesReturned);
1370
1371 if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_MORE_DATA))
1372 {
1373 // allocate pin name
1374 PinName = (LPWSTR)CoTaskMemAlloc(BytesReturned);
1375 if (!PinName)
1376 return E_OUTOFMEMORY;
1377
1378 // retry with allocated buffer
1379 hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSP_PIN), PinName, BytesReturned, &BytesReturned);
1380 if (SUCCEEDED(hr))
1381 {
1382 *OutPinName = PinName;
1383 return hr;
1384 }
1385
1386 //free buffer
1387 CoTaskMemFree(PinName);
1388 }
1389
1390 //
1391 // TODO: retrieve pin name from topology node
1392 //
1393
1394 if (DataFlow == KSPIN_DATAFLOW_IN)
1395 {
1396 swprintf(Buffer, L"Input%lu", PinCount);
1397 }
1398 else
1399 {
1400 swprintf(Buffer, L"Output%lu", PinCount);
1401 }
1402
1403 // allocate pin name
1404 PinName = (LPWSTR)CoTaskMemAlloc((wcslen(Buffer)+1) * sizeof(WCHAR));
1405 if (!PinName)
1406 return E_OUTOFMEMORY;
1407
1408 // copy pin name
1409 wcscpy(PinName, Buffer);
1410
1411 // store result
1412 *OutPinName = PinName;
1413 // done
1414 return S_OK;
1415 }
1416
1417 HRESULT
1418 STDMETHODCALLTYPE
1419 CKsProxy::CreatePins()
1420 {
1421 ULONG NumPins, Index;
1422 KSPIN_CINSTANCES Instances;
1423 KSPIN_DATAFLOW DataFlow;
1424 KSPIN_COMMUNICATION Communication;
1425 HRESULT hr;
1426 WCHAR Buffer[100];
1427 LPWSTR PinName;
1428 IPin * pPin;
1429 ULONG InputPin = 0;
1430 ULONG OutputPin = 0;
1431
1432 // get number of pins
1433 hr = GetNumberOfPins(&NumPins);
1434 if (FAILED(hr))
1435 return hr;
1436
1437 for(Index = 0; Index < NumPins; Index++)
1438 {
1439 // query current instance count
1440 hr = GetPinInstanceCount(Index, &Instances);
1441 if (FAILED(hr))
1442 continue;
1443
1444 // query pin communication;
1445 hr = GetPinCommunication(Index, &Communication);
1446 if (FAILED(hr))
1447 continue;
1448
1449 if (Instances.CurrentCount == Instances.PossibleCount)
1450 {
1451 // already maximum reached for this pin
1452 continue;
1453 }
1454
1455 // get direction of pin
1456 hr = GetPinDataflow(Index, &DataFlow);
1457 if (FAILED(hr))
1458 continue;
1459
1460 if (DataFlow == KSPIN_DATAFLOW_IN)
1461 hr = GetPinName(Index, DataFlow, InputPin, &PinName);
1462 else
1463 hr = GetPinName(Index, DataFlow, OutputPin, &PinName);
1464
1465 if (FAILED(hr))
1466 continue;
1467
1468 // construct the pins
1469 if (DataFlow == KSPIN_DATAFLOW_IN)
1470 {
1471 hr = CInputPin_Constructor((IBaseFilter*)this, PinName, m_hDevice, Index, Communication, IID_IPin, (void**)&pPin);
1472 if (FAILED(hr))
1473 {
1474 CoTaskMemFree(PinName);
1475 continue;
1476 }
1477 InputPin++;
1478 }
1479 else
1480 {
1481 hr = COutputPin_Constructor((IBaseFilter*)this, PinName, Index, IID_IPin, (void**)&pPin);
1482 if (FAILED(hr))
1483 {
1484 CoTaskMemFree(PinName);
1485 continue;
1486 }
1487 OutputPin++;
1488 }
1489
1490 // store pins
1491 m_Pins.push_back(pPin);
1492
1493 swprintf(Buffer, L"Index %lu DataFlow %lu Name %s\n", Index, DataFlow, PinName);
1494 OutputDebugStringW(Buffer);
1495 }
1496
1497 return S_OK;
1498 }
1499
1500 HRESULT
1501 STDMETHODCALLTYPE
1502 CKsProxy::Load(IPropertyBag *pPropBag, IErrorLog *pErrorLog)
1503 {
1504 HRESULT hr;
1505 WCHAR Buffer[100];
1506 VARIANT varName;
1507 LPGUID pGuid;
1508 ULONG NumGuids = 0;
1509 HDEVINFO hList;
1510 SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;
1511
1512
1513 // read device path
1514 varName.vt = VT_BSTR;
1515 hr = pPropBag->Read(L"DevicePath", &varName, pErrorLog);
1516
1517 if (FAILED(hr))
1518 {
1519 swprintf(Buffer, L"CKsProxy::Load Read %lx\n", hr);
1520 OutputDebugStringW(Buffer);
1521 return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, GetLastError());
1522 }
1523
1524 // create device list
1525 hList = SetupDiCreateDeviceInfoListExW(NULL, NULL, NULL, NULL);
1526 if (hList == INVALID_HANDLE_VALUE)
1527 {
1528 // failed to create device list
1529 return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, GetLastError());
1530 }
1531
1532 DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
1533 if (!SetupDiOpenDeviceInterfaceW(hList, (PCWSTR)varName.bstrVal, 0, &DeviceInterfaceData))
1534 {
1535 // failed to open device interface
1536 SetupDiDestroyDeviceInfoList(hList);
1537 }
1538
1539 // FIXME handle device interface links(aliases)
1540 CopyMemory(&m_DeviceInterfaceGUID, &DeviceInterfaceData.InterfaceClassGuid, sizeof(GUID));
1541
1542 // close device info list
1543 SetupDiDestroyDeviceInfoList(hList);
1544
1545 // open device
1546 m_hDevice = CreateFileW(varName.bstrVal, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
1547
1548 if (m_hDevice == INVALID_HANDLE_VALUE)
1549 {
1550 // failed to open device
1551 swprintf(Buffer, L"CKsProxy:: failed to open device with %lx\n", GetLastError());
1552 OutputDebugStringW(Buffer);
1553
1554 return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, GetLastError());
1555 }
1556
1557 // store device path
1558 m_DevicePath = varName.bstrVal;
1559
1560 // get all supported sets
1561 hr = GetSupportedSets(&pGuid, &NumGuids);
1562 if (FAILED(hr))
1563 {
1564 CloseHandle(m_hDevice);
1565 m_hDevice = NULL;
1566 return hr;
1567 }
1568
1569 // load all proxy plugins
1570 hr = LoadProxyPlugins(pGuid, NumGuids);
1571 if (FAILED(hr))
1572 {
1573 CloseHandle(m_hDevice);
1574 m_hDevice = NULL;
1575 return hr;
1576 }
1577
1578 // free sets
1579 CoTaskMemFree(pGuid);
1580
1581 // now create the input / output pins
1582 hr = CreatePins();
1583
1584 return hr;
1585 }
1586
1587 HRESULT
1588 STDMETHODCALLTYPE
1589 CKsProxy::Save(IPropertyBag *pPropBag, BOOL fClearDirty, BOOL fSaveAllProperties)
1590 {
1591 return E_NOTIMPL;
1592 }
1593
1594 //-------------------------------------------------------------------
1595 // IBaseFilter interface
1596 //
1597
1598 HRESULT
1599 STDMETHODCALLTYPE
1600 CKsProxy::GetClassID(
1601 CLSID *pClassID)
1602 {
1603 OutputDebugStringW(L"CKsProxy::GetClassID : NotImplemented\n");
1604 return E_NOTIMPL;
1605 }
1606
1607 HRESULT
1608 STDMETHODCALLTYPE
1609 CKsProxy::Stop()
1610 {
1611 OutputDebugStringW(L"CKsProxy::Stop : NotImplemented\n");
1612 return E_NOTIMPL;
1613 }
1614
1615 HRESULT
1616 STDMETHODCALLTYPE
1617 CKsProxy::Pause()
1618 {
1619 OutputDebugStringW(L"CKsProxy::Pause : NotImplemented\n");
1620 return E_NOTIMPL;
1621 }
1622
1623 HRESULT
1624 STDMETHODCALLTYPE
1625 CKsProxy::Run(
1626 REFERENCE_TIME tStart)
1627 {
1628 OutputDebugStringW(L"CKsProxy::Run : NotImplemented\n");
1629 return E_NOTIMPL;
1630 }
1631
1632 HRESULT
1633 STDMETHODCALLTYPE
1634 CKsProxy::GetState(
1635 DWORD dwMilliSecsTimeout,
1636 FILTER_STATE *State)
1637 {
1638 *State = m_FilterState;
1639 return S_OK;
1640 }
1641
1642 HRESULT
1643 STDMETHODCALLTYPE
1644 CKsProxy::SetSyncSource(
1645 IReferenceClock *pClock)
1646 {
1647 if (pClock)
1648 {
1649 pClock->AddRef();
1650 }
1651
1652 if (m_ReferenceClock)
1653 {
1654 m_ReferenceClock->Release();
1655 }
1656
1657 m_ReferenceClock = pClock;
1658 return S_OK;
1659 }
1660
1661 HRESULT
1662 STDMETHODCALLTYPE
1663 CKsProxy::GetSyncSource(
1664 IReferenceClock **pClock)
1665 {
1666 if (!pClock)
1667 return E_POINTER;
1668
1669 if (m_ReferenceClock)
1670 m_ReferenceClock->AddRef();
1671
1672 *pClock = m_ReferenceClock;
1673 return S_OK;
1674 }
1675
1676 HRESULT
1677 STDMETHODCALLTYPE
1678 CKsProxy::EnumPins(
1679 IEnumPins **ppEnum)
1680 {
1681 return CEnumPins_fnConstructor(m_Pins, IID_IEnumPins, (void**)ppEnum);
1682 }
1683
1684 HRESULT
1685 STDMETHODCALLTYPE
1686 CKsProxy::FindPin(
1687 LPCWSTR Id, IPin **ppPin)
1688 {
1689 ULONG PinId;
1690
1691 if (!ppPin)
1692 return E_POINTER;
1693
1694 // convert to pin
1695 int ret = swscanf(Id, L"%u", &PinId);
1696
1697 if (!ret || ret == EOF)
1698 {
1699 // invalid id
1700 return VFW_E_NOT_FOUND;
1701 }
1702
1703 if (PinId >= m_Pins.size() || m_Pins[PinId] == NULL)
1704 {
1705 // invalid id
1706 return VFW_E_NOT_FOUND;
1707 }
1708
1709 // found pin
1710 *ppPin = m_Pins[PinId];
1711 m_Pins[PinId]->AddRef();
1712
1713 return S_OK;
1714 }
1715
1716
1717 HRESULT
1718 STDMETHODCALLTYPE
1719 CKsProxy::QueryFilterInfo(
1720 FILTER_INFO *pInfo)
1721 {
1722 if (!pInfo)
1723 return E_POINTER;
1724
1725 pInfo->achName[0] = L'\0';
1726 pInfo->pGraph = m_pGraph;
1727
1728 return S_OK;
1729 }
1730
1731 HRESULT
1732 STDMETHODCALLTYPE
1733 CKsProxy::JoinFilterGraph(
1734 IFilterGraph *pGraph,
1735 LPCWSTR pName)
1736 {
1737 if (pGraph)
1738 {
1739 // joining filter graph
1740 m_pGraph = pGraph;
1741 }
1742 else
1743 {
1744 // leaving graph
1745 m_pGraph = 0;
1746 }
1747
1748 return S_OK;
1749 }
1750
1751
1752 HRESULT
1753 STDMETHODCALLTYPE
1754 CKsProxy::QueryVendorInfo(
1755 LPWSTR *pVendorInfo)
1756 {
1757 OutputDebugStringW(L"CKsProxy::QueryVendorInfo : NotImplemented\n");
1758 return E_NOTIMPL;
1759 }
1760
1761 //-------------------------------------------------------------------
1762 // IAMovieSetup interface
1763 //
1764
1765 HRESULT
1766 STDMETHODCALLTYPE
1767 CKsProxy::Register()
1768 {
1769 OutputDebugStringW(L"CKsProxy::Register : NotImplemented\n");
1770 return E_NOTIMPL;
1771 }
1772
1773 HRESULT
1774 STDMETHODCALLTYPE
1775 CKsProxy::Unregister()
1776 {
1777 OutputDebugStringW(L"CKsProxy::Unregister : NotImplemented\n");
1778 return E_NOTIMPL;
1779 }
1780
1781 HRESULT
1782 WINAPI
1783 CKsProxy_Constructor(
1784 IUnknown * pUnkOuter,
1785 REFIID riid,
1786 LPVOID * ppv)
1787 {
1788 WCHAR Buffer[100];
1789 LPOLESTR pstr;
1790 StringFromCLSID(riid, &pstr);
1791 swprintf(Buffer, L"CKsProxy_Constructor pUnkOuter %p riid %s\n", pUnkOuter, pstr);
1792 OutputDebugStringW(Buffer);
1793
1794 CKsProxy * handler = new CKsProxy();
1795
1796 if (!handler)
1797 return E_OUTOFMEMORY;
1798
1799 if (FAILED(handler->QueryInterface(riid, ppv)))
1800 {
1801 /* not supported */
1802 delete handler;
1803 return E_NOINTERFACE;
1804 }
1805
1806 return S_OK;
1807 }