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