[KSPROXY]
[reactos.git] / reactos / dll / directx / ksproxy / proxy.cpp
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS WDM Streaming ActiveMovie Proxy
4 * FILE: dll/directx/ksproxy/proxy.cpp
5 * PURPOSE: IKsProxy interface
6 *
7 * PROGRAMMERS: Johannes Anderwald (janderwald@reactos.org)
8 */
9 #include "precomp.h"
10
11 #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 const GUID KSPROPSETID_Clock = {0xDF12A4C0L, 0xAC17, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
18 const GUID KSEVENTSETID_Clock = {0x364D8E20L, 0x62C7, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
19 const GUID KSPROPSETID_Stream = {0x65aaba60L, 0x98ae, 0x11cf, {0xa1, 0x0d, 0x00, 0x20, 0xaf, 0xd1, 0x56, 0xe4}};
20 const GUID IID_IPersist = {0x0000010c, 0x0000, 0x0000, {0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}};
21 #endif
22
23 const GUID IID_IBDA_DeviceControl = {0xFD0A5AF3, 0xB41D, 0x11d2, {0x9C, 0x95, 0x00, 0xC0, 0x4F, 0x79, 0x71, 0xE0}};
24 const GUID IID_IKsAggregateControl = {0x7F40EAC0, 0x3947, 0x11D2, {0x87, 0x4E, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
25 const GUID IID_IKsClockPropertySet = {0x5C5CBD84, 0xE755, 0x11D0, {0xAC, 0x18, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
26 const GUID IID_IKsTopology = {0x28F54683, 0x06FD, 0x11D2, {0xB2, 0x7A, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
27 const GUID IID_IKsClock = {0x877E4351, 0x6FEA, 0x11D0, {0xB8, 0x63, 0x00, 0xAA, 0x00, 0xA2, 0x16, 0xA1}};
28 /*
29 Needs IKsClock, IKsNotifyEvent
30 */
31
32 class CKsProxy : public IBaseFilter,
33 public IAMovieSetup,
34 public IPersistPropertyBag,
35 public IKsObject,
36 public IPersistStream,
37 public IAMDeviceRemoval,
38 public ISpecifyPropertyPages,
39 public IReferenceClock,
40 public IMediaSeeking,
41 public IKsPropertySet,
42 public IKsClock,
43 public IKsClockPropertySet,
44 public IAMFilterMiscFlags,
45 public IKsControl,
46 public IKsTopology,
47 public IKsAggregateControl
48
49 {
50 public:
51 typedef std::vector<IUnknown *>ProxyPluginVector;
52 typedef std::vector<IPin *> PinVector;
53
54 STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
55
56 STDMETHODIMP_(ULONG) AddRef()
57 {
58 InterlockedIncrement(&m_Ref);
59 return m_Ref;
60 }
61 STDMETHODIMP_(ULONG) Release()
62 {
63 InterlockedDecrement(&m_Ref);
64 if (!m_Ref)
65 {
66 delete this;
67 return 0;
68 }
69 return m_Ref;
70 }
71
72 // IBaseFilter methods
73 HRESULT STDMETHODCALLTYPE GetClassID(CLSID *pClassID);
74 HRESULT STDMETHODCALLTYPE Stop( void);
75 HRESULT STDMETHODCALLTYPE Pause( void);
76 HRESULT STDMETHODCALLTYPE Run(REFERENCE_TIME tStart);
77 HRESULT STDMETHODCALLTYPE GetState(DWORD dwMilliSecsTimeout, FILTER_STATE *State);
78 HRESULT STDMETHODCALLTYPE SetSyncSource(IReferenceClock *pClock);
79 HRESULT STDMETHODCALLTYPE GetSyncSource(IReferenceClock **pClock);
80 HRESULT STDMETHODCALLTYPE EnumPins(IEnumPins **ppEnum);
81 HRESULT STDMETHODCALLTYPE FindPin(LPCWSTR Id, IPin **ppPin);
82 HRESULT STDMETHODCALLTYPE QueryFilterInfo(FILTER_INFO *pInfo);
83 HRESULT STDMETHODCALLTYPE JoinFilterGraph(IFilterGraph *pGraph, LPCWSTR pName);
84 HRESULT STDMETHODCALLTYPE QueryVendorInfo(LPWSTR *pVendorInfo);
85
86 //IReferenceClock
87 HRESULT STDMETHODCALLTYPE GetTime(REFERENCE_TIME *pTime);
88 HRESULT STDMETHODCALLTYPE AdviseTime(REFERENCE_TIME baseTime, REFERENCE_TIME streamTime, HEVENT hEvent, DWORD_PTR *pdwAdviseCookie);
89 HRESULT STDMETHODCALLTYPE AdvisePeriodic(REFERENCE_TIME startTime, REFERENCE_TIME periodTime, HSEMAPHORE hSemaphore, DWORD_PTR *pdwAdviseCookie);
90 HRESULT STDMETHODCALLTYPE Unadvise(DWORD_PTR dwAdviseCookie);
91
92 //IMediaSeeking
93 HRESULT STDMETHODCALLTYPE GetCapabilities(DWORD *pCapabilities);
94 HRESULT STDMETHODCALLTYPE CheckCapabilities(DWORD *pCapabilities);
95 HRESULT STDMETHODCALLTYPE IsFormatSupported(const GUID *pFormat);
96 HRESULT STDMETHODCALLTYPE QueryPreferredFormat(GUID *pFormat);
97 HRESULT STDMETHODCALLTYPE GetTimeFormat(GUID *pFormat);
98 HRESULT STDMETHODCALLTYPE IsUsingTimeFormat(const GUID *pFormat);
99 HRESULT STDMETHODCALLTYPE SetTimeFormat(const GUID *pFormat);
100 HRESULT STDMETHODCALLTYPE GetDuration(LONGLONG *pDuration);
101 HRESULT STDMETHODCALLTYPE GetStopPosition(LONGLONG *pStop);
102 HRESULT STDMETHODCALLTYPE GetCurrentPosition(LONGLONG *pCurrent);
103 HRESULT STDMETHODCALLTYPE ConvertTimeFormat(LONGLONG *pTarget, const GUID *pTargetFormat, LONGLONG Source, const GUID *pSourceFormat);
104 HRESULT STDMETHODCALLTYPE SetPositions(LONGLONG *pCurrent, DWORD dwCurrentFlags, LONGLONG *pStop, DWORD dwStopFlags);
105 HRESULT STDMETHODCALLTYPE GetPositions(LONGLONG *pCurrent, LONGLONG *pStop);
106 HRESULT STDMETHODCALLTYPE GetAvailable(LONGLONG *pEarliest, LONGLONG *pLatest);
107 HRESULT STDMETHODCALLTYPE SetRate(double dRate);
108 HRESULT STDMETHODCALLTYPE GetRate(double *pdRate);
109 HRESULT STDMETHODCALLTYPE GetPreroll(LONGLONG *pllPreroll);
110
111 //IKsPropertySet
112 HRESULT STDMETHODCALLTYPE Set(REFGUID guidPropSet, DWORD dwPropID, LPVOID pInstanceData, DWORD cbInstanceData, LPVOID pPropData, DWORD cbPropData);
113 HRESULT STDMETHODCALLTYPE Get(REFGUID guidPropSet, DWORD dwPropID, LPVOID pInstanceData, DWORD cbInstanceData, LPVOID pPropData, DWORD cbPropData, DWORD *pcbReturned);
114 HRESULT STDMETHODCALLTYPE QuerySupported(REFGUID guidPropSet, DWORD dwPropID, DWORD *pTypeSupport);
115
116 //IAMFilterMiscFlags
117 ULONG STDMETHODCALLTYPE GetMiscFlags( void);
118
119 //IKsControl
120 HRESULT STDMETHODCALLTYPE KsProperty(PKSPROPERTY Property, ULONG PropertyLength, LPVOID PropertyData, ULONG DataLength, ULONG* BytesReturned);
121 HRESULT STDMETHODCALLTYPE KsMethod(PKSMETHOD Method, ULONG MethodLength, LPVOID MethodData, ULONG DataLength, ULONG* BytesReturned);
122 HRESULT STDMETHODCALLTYPE KsEvent(PKSEVENT Event, ULONG EventLength, LPVOID EventData, ULONG DataLength, ULONG* BytesReturned);
123
124 //IKsTopolology
125 HRESULT STDMETHODCALLTYPE CreateNodeInstance(ULONG NodeId, ULONG Flags, ACCESS_MASK DesiredAccess, IUnknown* UnkOuter, REFGUID InterfaceId, LPVOID* Interface);
126
127 //IKsAggregateControl
128 HRESULT STDMETHODCALLTYPE KsAddAggregate(IN REFGUID AggregateClass);
129 HRESULT STDMETHODCALLTYPE KsRemoveAggregate(REFGUID AggregateClass);
130
131 //IKsClockPropertySet
132 HRESULT STDMETHODCALLTYPE KsGetTime(LONGLONG* Time);
133 HRESULT STDMETHODCALLTYPE KsSetTime(LONGLONG Time);
134 HRESULT STDMETHODCALLTYPE KsGetPhysicalTime(LONGLONG* Time);
135 HRESULT STDMETHODCALLTYPE KsSetPhysicalTime(LONGLONG Time);
136 HRESULT STDMETHODCALLTYPE KsGetCorrelatedTime(KSCORRELATED_TIME* CorrelatedTime);
137 HRESULT STDMETHODCALLTYPE KsSetCorrelatedTime(KSCORRELATED_TIME* CorrelatedTime);
138 HRESULT STDMETHODCALLTYPE KsGetCorrelatedPhysicalTime(KSCORRELATED_TIME* CorrelatedTime);
139 HRESULT STDMETHODCALLTYPE KsSetCorrelatedPhysicalTime(KSCORRELATED_TIME* CorrelatedTime);
140 HRESULT STDMETHODCALLTYPE KsGetResolution(KSRESOLUTION* Resolution);
141 HRESULT STDMETHODCALLTYPE KsGetState(KSSTATE* State);
142
143
144 //IAMovieSetup methods
145 HRESULT STDMETHODCALLTYPE Register( void);
146 HRESULT STDMETHODCALLTYPE Unregister( void);
147
148 // IPersistPropertyBag methods
149 HRESULT STDMETHODCALLTYPE InitNew( void);
150 HRESULT STDMETHODCALLTYPE Load(IPropertyBag *pPropBag, IErrorLog *pErrorLog);
151 HRESULT STDMETHODCALLTYPE Save(IPropertyBag *pPropBag, BOOL fClearDirty, BOOL fSaveAllProperties);
152
153 // IKsObject
154 HANDLE STDMETHODCALLTYPE KsGetObjectHandle();
155
156 // IKsClock
157 HANDLE STDMETHODCALLTYPE KsGetClockHandle();
158
159 //IAMDeviceRemoval
160 HRESULT STDMETHODCALLTYPE DeviceInfo(CLSID *pclsidInterfaceClass, LPWSTR *pwszSymbolicLink);
161 HRESULT STDMETHODCALLTYPE Reassociate(void);
162 HRESULT STDMETHODCALLTYPE Disassociate( void);
163
164 //IPersistStream
165 HRESULT STDMETHODCALLTYPE IsDirty( void);
166 HRESULT STDMETHODCALLTYPE Load(IStream *pStm);
167 HRESULT STDMETHODCALLTYPE Save(IStream *pStm, BOOL fClearDirty);
168 HRESULT STDMETHODCALLTYPE GetSizeMax(ULARGE_INTEGER *pcbSize);
169
170 // ISpecifyPropertyPages
171 HRESULT STDMETHODCALLTYPE GetPages(CAUUID *pPages);
172
173
174 CKsProxy() : m_Ref(0), m_pGraph(0), m_ReferenceClock((IReferenceClock*)this), m_FilterState(State_Stopped), m_hDevice(0), m_Plugins(), m_Pins(), m_DevicePath(0), m_hClock(0) {};
175 ~CKsProxy()
176 {
177 if (m_hDevice)
178 CloseHandle(m_hDevice);
179 };
180
181 HRESULT STDMETHODCALLTYPE GetSupportedSets(LPGUID * pOutGuid, PULONG NumGuids);
182 HRESULT STDMETHODCALLTYPE LoadProxyPlugins(LPGUID pGuids, ULONG NumGuids);
183 HRESULT STDMETHODCALLTYPE GetNumberOfPins(PULONG NumPins);
184 HRESULT STDMETHODCALLTYPE GetPinInstanceCount(ULONG PinId, PKSPIN_CINSTANCES Instances);
185 HRESULT STDMETHODCALLTYPE GetPinDataflow(ULONG PinId, KSPIN_DATAFLOW * DataFlow);
186 HRESULT STDMETHODCALLTYPE GetPinName(ULONG PinId, KSPIN_DATAFLOW DataFlow, ULONG PinCount, LPWSTR * OutPinName);
187 HRESULT STDMETHODCALLTYPE GetPinCommunication(ULONG PinId, KSPIN_COMMUNICATION * Communication);
188 HRESULT STDMETHODCALLTYPE CreatePins();
189 HRESULT STDMETHODCALLTYPE GetMediaSeekingFormats(PKSMULTIPLE_ITEM *FormatList);
190 HRESULT STDMETHODCALLTYPE CreateClockInstance();
191 HRESULT STDMETHODCALLTYPE PerformClockProperty(ULONG PropertyId, ULONG PropertyFlags, PVOID OutputBuffer, ULONG OutputBufferSize);
192 HRESULT STDMETHODCALLTYPE SetPinState(KSSTATE State);
193
194
195 protected:
196 LONG m_Ref;
197 IFilterGraph *m_pGraph;
198 IReferenceClock * m_ReferenceClock;
199 FILTER_STATE m_FilterState;
200 HANDLE m_hDevice;
201 ProxyPluginVector m_Plugins;
202 PinVector m_Pins;
203 LPWSTR m_DevicePath;
204 CLSID m_DeviceInterfaceGUID;
205 HANDLE m_hClock;
206 };
207
208 HRESULT
209 STDMETHODCALLTYPE
210 CKsProxy::QueryInterface(
211 IN REFIID refiid,
212 OUT PVOID* Output)
213 {
214 *Output = NULL;
215
216 if (IsEqualGUID(refiid, IID_IUnknown) ||
217 IsEqualGUID(refiid, IID_IBaseFilter))
218 {
219 *Output = PVOID(this);
220 reinterpret_cast<IUnknown*>(*Output)->AddRef();
221 return NOERROR;
222 }
223 else if (IsEqualGUID(refiid, IID_IPersistPropertyBag))
224 {
225 *Output = (IPersistPropertyBag*)(this);
226 reinterpret_cast<IPersistPropertyBag*>(*Output)->AddRef();
227 return NOERROR;
228 }
229 else if (IsEqualGUID(refiid, IID_IAMDeviceRemoval))
230 {
231 *Output = (IAMDeviceRemoval*)(this);
232 reinterpret_cast<IAMDeviceRemoval*>(*Output)->AddRef();
233 return NOERROR;
234 }
235 else if (IsEqualGUID(refiid, IID_IPersistStream))
236 {
237 *Output = (IPersistStream*)(this);
238 reinterpret_cast<IPersistStream*>(*Output)->AddRef();
239 return NOERROR;
240 }
241 else if (IsEqualGUID(refiid, IID_IPersist))
242 {
243 *Output = (IPersistStream*)(this);
244 reinterpret_cast<IPersist*>(*Output)->AddRef();
245 return NOERROR;
246 }
247 else if (IsEqualGUID(refiid, IID_IKsObject))
248 {
249 *Output = (IKsObject*)(this);
250 reinterpret_cast<IKsObject*>(*Output)->AddRef();
251 return NOERROR;
252 }
253 else if (IsEqualGUID(refiid, IID_IKsClock))
254 {
255 *Output = (IKsClock*)(this);
256 reinterpret_cast<IKsClock*>(*Output)->AddRef();
257 return NOERROR;
258 }
259 else if (IsEqualGUID(refiid, IID_IReferenceClock))
260 {
261 if (!m_hClock)
262 {
263 HRESULT hr = CreateClockInstance();
264 if (FAILED(hr))
265 return hr;
266 }
267
268 *Output = (IReferenceClock*)(this);
269 reinterpret_cast<IReferenceClock*>(*Output)->AddRef();
270 return NOERROR;
271 }
272 else if (IsEqualGUID(refiid, IID_IMediaSeeking))
273 {
274 *Output = (IMediaSeeking*)(this);
275 reinterpret_cast<IMediaSeeking*>(*Output)->AddRef();
276 return NOERROR;
277 }
278 else if (IsEqualGUID(refiid, IID_IAMFilterMiscFlags))
279 {
280 *Output = (IAMFilterMiscFlags*)(this);
281 reinterpret_cast<IAMFilterMiscFlags*>(*Output)->AddRef();
282 return NOERROR;
283 }
284 else if (IsEqualGUID(refiid, IID_IKsControl))
285 {
286 *Output = (IKsControl*)(this);
287 reinterpret_cast<IKsControl*>(*Output)->AddRef();
288 return NOERROR;
289 }
290 else if (IsEqualGUID(refiid, IID_IKsPropertySet))
291 {
292 *Output = (IKsPropertySet*)(this);
293 reinterpret_cast<IKsPropertySet*>(*Output)->AddRef();
294 return NOERROR;
295 }
296 else if (IsEqualGUID(refiid, IID_IKsTopology))
297 {
298 *Output = (IKsTopology*)(this);
299 reinterpret_cast<IKsTopology*>(*Output)->AddRef();
300 return NOERROR;
301 }
302 else if (IsEqualGUID(refiid, IID_IKsAggregateControl))
303 {
304 *Output = (IKsAggregateControl*)(this);
305 reinterpret_cast<IKsAggregateControl*>(*Output)->AddRef();
306 return NOERROR;
307 }
308 else if (IsEqualGUID(refiid, IID_IKsClockPropertySet))
309 {
310 if (!m_hClock)
311 {
312 HRESULT hr = CreateClockInstance();
313 if (FAILED(hr))
314 return hr;
315 }
316
317 *Output = (IKsClockPropertySet*)(this);
318 reinterpret_cast<IKsClockPropertySet*>(*Output)->AddRef();
319 return NOERROR;
320 }
321 else if (IsEqualGUID(refiid, IID_ISpecifyPropertyPages))
322 {
323 *Output = (ISpecifyPropertyPages*)(this);
324 reinterpret_cast<ISpecifyPropertyPages*>(*Output)->AddRef();
325 return NOERROR;
326 }
327
328 for(ULONG Index = 0; Index < m_Plugins.size(); Index++)
329 {
330 if (m_Pins[Index])
331 {
332 HRESULT hr = m_Plugins[Index]->QueryInterface(refiid, Output);
333 if (SUCCEEDED(hr))
334 {
335 WCHAR Buffer[100];
336 LPOLESTR lpstr;
337 StringFromCLSID(refiid, &lpstr);
338 swprintf(Buffer, L"CKsProxy::QueryInterface plugin %lu supports interface %s\n", Index, lpstr);
339 OutputDebugStringW(Buffer);
340 CoTaskMemFree(lpstr);
341 return hr;
342 }
343 }
344 }
345
346 WCHAR Buffer[MAX_PATH];
347 LPOLESTR lpstr;
348 StringFromCLSID(refiid, &lpstr);
349 swprintf(Buffer, L"CKsProxy::QueryInterface: NoInterface for %s !!!\n", lpstr);
350 OutputDebugStringW(Buffer);
351 CoTaskMemFree(lpstr);
352
353
354 return E_NOINTERFACE;
355 }
356
357 //-------------------------------------------------------------------
358 // ISpecifyPropertyPages
359 //
360
361 HRESULT
362 STDMETHODCALLTYPE
363 CKsProxy::GetPages(CAUUID *pPages)
364 {
365 OutputDebugStringW(L"CKsProxy::GetPages NotImplemented\n");
366
367 if (!pPages)
368 return E_POINTER;
369
370 pPages->cElems = 0;
371 pPages->pElems = NULL;
372
373 return S_OK;
374 }
375
376 //-------------------------------------------------------------------
377 // IKsClockPropertySet interface
378 //
379
380 HRESULT
381 STDMETHODCALLTYPE
382 CKsProxy::CreateClockInstance()
383 {
384 HRESULT hr;
385 HANDLE hPin = INVALID_HANDLE_VALUE;
386 ULONG Index;
387 PIN_DIRECTION PinDir;
388 IKsObject *pObject;
389 KSCLOCK_CREATE ClockCreate;
390
391 // find output pin and handle
392 for(Index = 0; Index < m_Pins.size(); Index++)
393 {
394 //get pin
395 IPin * pin = m_Pins[Index];
396 if (!pin)
397 continue;
398
399 // get direction
400 hr = pin->QueryDirection(&PinDir);
401 if (FAILED(hr))
402 continue;
403
404 // query IKsObject interface
405 hr = pin->QueryInterface(IID_IKsObject, (void**)&pObject);
406 if (FAILED(hr))
407 continue;
408
409
410 // get pin handle
411 hPin = pObject->KsGetObjectHandle();
412
413 //release IKsObject
414 pObject->Release();
415
416 if (hPin != INVALID_HANDLE_VALUE)
417 break;
418 }
419
420 if (hPin == INVALID_HANDLE_VALUE)
421 {
422 // clock can only be instantiated on a pin handle
423 return E_NOTIMPL;
424 }
425
426 if (m_hClock)
427 {
428 // release clock handle
429 CloseHandle(m_hClock);
430 }
431
432 //setup clock create request
433 ClockCreate.CreateFlags = 0;
434
435 // setup clock create request
436 hr = KsCreateClock(hPin, &ClockCreate, &m_hClock); // FIXME KsCreateClock returns NTSTATUS
437 if (SUCCEEDED(hr))
438 {
439 // failed to create clock
440 return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, GetLastError());
441 }
442
443 return S_OK;
444 }
445
446 HRESULT
447 STDMETHODCALLTYPE
448 CKsProxy::PerformClockProperty(
449 ULONG PropertyId,
450 ULONG PropertyFlags,
451 PVOID OutputBuffer,
452 ULONG OutputBufferSize)
453 {
454 KSPROPERTY Property;
455 HRESULT hr;
456 ULONG BytesReturned;
457
458 if (!m_hClock)
459 {
460 // create clock
461 hr = CreateClockInstance();
462 if (FAILED(hr))
463 return hr;
464 }
465
466 // setup request
467 Property.Set = KSPROPSETID_Clock;
468 Property.Id = PropertyId;
469 Property.Flags = PropertyFlags;
470
471 hr = KsSynchronousDeviceControl(m_hClock, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)OutputBuffer, OutputBufferSize, &BytesReturned);
472
473 return hr;
474 }
475
476 HRESULT
477 STDMETHODCALLTYPE
478 CKsProxy::KsGetTime(
479 LONGLONG* Time)
480 {
481 OutputDebugStringW(L"CKsProxy::KsGetTime\n");
482 return PerformClockProperty(KSPROPERTY_CLOCK_TIME, KSPROPERTY_TYPE_GET, (PVOID)Time, sizeof(LONGLONG));
483 }
484
485 HRESULT
486 STDMETHODCALLTYPE
487 CKsProxy::KsSetTime(
488 LONGLONG Time)
489 {
490 OutputDebugStringW(L"CKsProxy::KsSetTime\n");
491 return PerformClockProperty(KSPROPERTY_CLOCK_TIME, KSPROPERTY_TYPE_SET, (PVOID)&Time, sizeof(LONGLONG));
492 }
493
494 HRESULT
495 STDMETHODCALLTYPE
496 CKsProxy::KsGetPhysicalTime(
497 LONGLONG* Time)
498 {
499 OutputDebugStringW(L"CKsProxy::KsGetPhysicalTime\n");
500 return PerformClockProperty(KSPROPERTY_CLOCK_PHYSICALTIME, KSPROPERTY_TYPE_GET, (PVOID)Time, sizeof(LONGLONG));
501 }
502
503 HRESULT
504 STDMETHODCALLTYPE
505 CKsProxy::KsSetPhysicalTime(
506 LONGLONG Time)
507 {
508 OutputDebugStringW(L"CKsProxy::KsSetPhysicalTime NotImplemented\n");
509 return PerformClockProperty(KSPROPERTY_CLOCK_PHYSICALTIME, KSPROPERTY_TYPE_SET, (PVOID)&Time, sizeof(LONGLONG));
510 }
511
512 HRESULT
513 STDMETHODCALLTYPE
514 CKsProxy::KsGetCorrelatedTime(
515 KSCORRELATED_TIME* CorrelatedTime)
516 {
517 OutputDebugStringW(L"CKsProxy::KsGetCorrelatedTime\n");
518 return PerformClockProperty(KSPROPERTY_CLOCK_CORRELATEDTIME, KSPROPERTY_TYPE_GET, (PVOID)CorrelatedTime, sizeof(KSCORRELATED_TIME));
519 }
520
521 HRESULT
522 STDMETHODCALLTYPE
523 CKsProxy::KsSetCorrelatedTime(
524 KSCORRELATED_TIME* CorrelatedTime)
525 {
526 OutputDebugStringW(L"CKsProxy::KsSetCorrelatedTime\n");
527 return PerformClockProperty(KSPROPERTY_CLOCK_CORRELATEDTIME, KSPROPERTY_TYPE_SET, (PVOID)CorrelatedTime, sizeof(KSCORRELATED_TIME));
528 }
529
530 HRESULT
531 STDMETHODCALLTYPE
532 CKsProxy::KsGetCorrelatedPhysicalTime(
533 KSCORRELATED_TIME* CorrelatedTime)
534 {
535 OutputDebugStringW(L"CKsProxy::KsGetCorrelatedPhysicalTime\n");
536 return PerformClockProperty(KSPROPERTY_CLOCK_CORRELATEDPHYSICALTIME, KSPROPERTY_TYPE_GET, (PVOID)CorrelatedTime, sizeof(KSCORRELATED_TIME));
537 }
538
539 HRESULT
540 STDMETHODCALLTYPE
541 CKsProxy::KsSetCorrelatedPhysicalTime(
542 KSCORRELATED_TIME* CorrelatedTime)
543 {
544 OutputDebugStringW(L"CKsProxy::KsSetCorrelatedPhysicalTime\n");
545 return PerformClockProperty(KSPROPERTY_CLOCK_CORRELATEDPHYSICALTIME, KSPROPERTY_TYPE_SET, (PVOID)CorrelatedTime, sizeof(KSCORRELATED_TIME));
546 }
547
548 HRESULT
549 STDMETHODCALLTYPE
550 CKsProxy::KsGetResolution(
551 KSRESOLUTION* Resolution)
552 {
553 OutputDebugStringW(L"CKsProxy::KsGetResolution\n");
554 return PerformClockProperty(KSPROPERTY_CLOCK_RESOLUTION, KSPROPERTY_TYPE_GET, (PVOID)Resolution, sizeof(KSRESOLUTION));
555 }
556
557 HRESULT
558 STDMETHODCALLTYPE
559 CKsProxy::KsGetState(
560 KSSTATE* State)
561 {
562 OutputDebugStringW(L"CKsProxy::KsGetState\n");
563 return PerformClockProperty(KSPROPERTY_CLOCK_STATE, KSPROPERTY_TYPE_GET, (PVOID)State, sizeof(KSSTATE));
564 }
565
566 //-------------------------------------------------------------------
567 // IReferenceClock interface
568 //
569 HRESULT
570 STDMETHODCALLTYPE
571 CKsProxy::GetTime(
572 REFERENCE_TIME *pTime)
573 {
574 HRESULT hr;
575 KSPROPERTY Property;
576 ULONG BytesReturned;
577
578 OutputDebugStringW(L"CKsProxy::GetTime\n");
579
580 if (!pTime)
581 return E_POINTER;
582
583 //
584 //FIXME locks
585 //
586
587 if (!m_hClock)
588 {
589 // create clock
590 hr = CreateClockInstance();
591 if (FAILED(hr))
592 return hr;
593 }
594
595 // setup request
596 Property.Set = KSPROPSETID_Clock;
597 Property.Id = KSPROPERTY_CLOCK_TIME;
598 Property.Flags = KSPROPERTY_TYPE_GET;
599
600 // perform request
601 hr = KsSynchronousDeviceControl(m_hClock, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)pTime, sizeof(REFERENCE_TIME), &BytesReturned);
602
603 // TODO
604 // increment value
605 //
606
607 return hr;
608 }
609
610 HRESULT
611 STDMETHODCALLTYPE
612 CKsProxy::AdviseTime(
613 REFERENCE_TIME baseTime,
614 REFERENCE_TIME streamTime,
615 HEVENT hEvent,
616 DWORD_PTR *pdwAdviseCookie)
617 {
618 HRESULT hr;
619 KSEVENT Property;
620 ULONG BytesReturned;
621 PKSEVENT_TIME_MARK Event;
622
623 OutputDebugStringW(L"CKsProxy::AdviseTime\n");
624
625 //
626 //FIXME locks
627 //
628
629 if (!pdwAdviseCookie)
630 return E_POINTER;
631
632 if (!m_hClock)
633 {
634 // create clock
635 hr = CreateClockInstance();
636 if (FAILED(hr))
637 return hr;
638 }
639
640 // allocate event entry
641 Event = (PKSEVENT_TIME_MARK)CoTaskMemAlloc(sizeof(KSEVENT_TIME_MARK));
642 if (Event)
643 {
644 // setup request
645 Property.Set = KSEVENTSETID_Clock;
646 Property.Id = KSEVENT_CLOCK_POSITION_MARK;
647 Property.Flags = KSEVENT_TYPE_ENABLE;
648
649 Event->EventData.NotificationType = KSEVENTF_EVENT_HANDLE;
650 Event->EventData.EventHandle.Event = (HANDLE)hEvent;
651 Event->EventData.Alignment.Alignment[0] = 0;
652 Event->EventData.Alignment.Alignment[1] = 0;
653 Event->MarkTime = baseTime + streamTime;
654
655 // perform request
656 hr = KsSynchronousDeviceControl(m_hClock, IOCTL_KS_ENABLE_EVENT, (PVOID)&Property, sizeof(KSEVENT), (PVOID)Event, sizeof(KSEVENT_TIME_MARK), &BytesReturned);
657 if (SUCCEEDED(hr))
658 {
659 // store event handle
660 *pdwAdviseCookie = (DWORD_PTR)Event;
661 }
662 else
663 {
664 // failed to enable event
665 CoTaskMemFree(Event);
666 }
667 }
668 else
669 {
670 hr = E_OUTOFMEMORY;
671 }
672
673 return hr;
674 }
675
676 HRESULT
677 STDMETHODCALLTYPE
678 CKsProxy::AdvisePeriodic(
679 REFERENCE_TIME startTime,
680 REFERENCE_TIME periodTime,
681 HSEMAPHORE hSemaphore,
682 DWORD_PTR *pdwAdviseCookie)
683 {
684 HRESULT hr;
685 KSEVENT Property;
686 ULONG BytesReturned;
687 PKSEVENT_TIME_INTERVAL Event;
688
689 OutputDebugStringW(L"CKsProxy::AdvisePeriodic\n");
690
691 //
692 //FIXME locks
693 //
694
695 if (!pdwAdviseCookie)
696 return E_POINTER;
697
698 if (!m_hClock)
699 {
700 // create clock
701 hr = CreateClockInstance();
702 if (FAILED(hr))
703 return hr;
704 }
705
706 // allocate event entry
707 Event = (PKSEVENT_TIME_INTERVAL)CoTaskMemAlloc(sizeof(KSEVENT_TIME_INTERVAL));
708 if (Event)
709 {
710 // setup request
711 Property.Set = KSEVENTSETID_Clock;
712 Property.Id = KSEVENT_CLOCK_INTERVAL_MARK;
713 Property.Flags = KSEVENT_TYPE_ENABLE;
714
715 Event->EventData.NotificationType = KSEVENTF_SEMAPHORE_HANDLE;
716 Event->EventData.SemaphoreHandle.Semaphore = (HANDLE)hSemaphore;
717 Event->EventData.SemaphoreHandle.Reserved = 0;
718 Event->EventData.SemaphoreHandle.Adjustment = 1;
719 Event->TimeBase = startTime;
720 Event->Interval = periodTime;
721
722 // perform request
723 hr = KsSynchronousDeviceControl(m_hClock, IOCTL_KS_ENABLE_EVENT, (PVOID)&Property, sizeof(KSEVENT), (PVOID)Event, sizeof(KSEVENT_TIME_INTERVAL), &BytesReturned);
724 if (SUCCEEDED(hr))
725 {
726 // store event handle
727 *pdwAdviseCookie = (DWORD_PTR)Event;
728 }
729 else
730 {
731 // failed to enable event
732 CoTaskMemFree(Event);
733 }
734 }
735 else
736 {
737 hr = E_OUTOFMEMORY;
738 }
739
740 return hr;
741 }
742
743 HRESULT
744 STDMETHODCALLTYPE
745 CKsProxy::Unadvise(
746 DWORD_PTR dwAdviseCookie)
747 {
748 HRESULT hr;
749 ULONG BytesReturned;
750
751 OutputDebugStringW(L"CKsProxy::Unadvise\n");
752
753 if (m_hClock)
754 {
755 //lets disable the event
756 hr = KsSynchronousDeviceControl(m_hClock, IOCTL_KS_DISABLE_EVENT, (PVOID)dwAdviseCookie, sizeof(KSEVENTDATA), 0, 0, &BytesReturned);
757 if (SUCCEEDED(hr))
758 {
759 // lets free event data
760 CoTaskMemFree((LPVOID)dwAdviseCookie);
761 }
762 }
763 else
764 {
765 // no clock available
766 hr = E_FAIL;
767 }
768
769 return hr;
770 }
771
772 //-------------------------------------------------------------------
773 // IMediaSeeking interface
774 //
775 HRESULT
776 STDMETHODCALLTYPE
777 CKsProxy::GetCapabilities(
778 DWORD *pCapabilities)
779 {
780 KSPROPERTY Property;
781 ULONG BytesReturned, Index;
782 HRESULT hr = S_OK;
783 DWORD TempCaps;
784
785 Property.Set = KSPROPSETID_MediaSeeking;
786 Property.Id = KSPROPERTY_MEDIASEEKING_CAPABILITIES;
787 Property.Flags = KSPROPERTY_TYPE_GET;
788
789 OutputDebugStringW(L"CKsProxy::GetCapabilities\n");
790
791 if (!pCapabilities)
792 return E_POINTER;
793
794
795 *pCapabilities = (KS_SEEKING_CanSeekAbsolute | KS_SEEKING_CanSeekForwards | KS_SEEKING_CanSeekBackwards | KS_SEEKING_CanGetCurrentPos |
796 KS_SEEKING_CanGetStopPos | KS_SEEKING_CanGetDuration | KS_SEEKING_CanPlayBackwards);
797
798 KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&pCapabilities, sizeof(KS_SEEKING_CAPABILITIES), &BytesReturned);
799 // check if plugins support it
800 for(Index = 0; Index < m_Plugins.size(); Index++)
801 {
802 // get plugin
803 IUnknown * Plugin = m_Plugins[Index];
804
805 if (!Plugin)
806 continue;
807
808 // query for IMediaSeeking interface
809 IMediaSeeking *pSeek = NULL;
810 hr = Plugin->QueryInterface(IID_IMediaSeeking, (void**)&pSeek);
811 if (FAILED(hr))
812 {
813 *pCapabilities = 0;
814 return hr;
815 }
816
817 TempCaps = 0;
818 // set time format
819 hr = pSeek->GetCapabilities(&TempCaps);
820 if (SUCCEEDED(hr))
821 {
822 // and with supported flags
823 *pCapabilities = (*pCapabilities & TempCaps);
824 }
825 // release IMediaSeeking interface
826 pSeek->Release();
827 }
828 return hr;
829 }
830
831 HRESULT
832 STDMETHODCALLTYPE
833 CKsProxy::CheckCapabilities(
834 DWORD *pCapabilities)
835 {
836 DWORD Capabilities;
837 HRESULT hr;
838
839 OutputDebugStringW(L"CKsProxy::CheckCapabilities\n");
840
841 if (!pCapabilities)
842 return E_POINTER;
843
844 if (!*pCapabilities)
845 return E_FAIL;
846
847 hr = GetCapabilities(&Capabilities);
848 if (SUCCEEDED(hr))
849 {
850 if ((Capabilities | *pCapabilities) == Capabilities)
851 {
852 // all present
853 return S_OK;
854 }
855
856 Capabilities = (Capabilities & *pCapabilities);
857 if (Capabilities)
858 {
859 // not all present
860 *pCapabilities = Capabilities;
861 return S_FALSE;
862 }
863 // no capabilities are present
864 return E_FAIL;
865 }
866
867 return hr;
868 }
869
870 HRESULT
871 STDMETHODCALLTYPE
872 CKsProxy::GetMediaSeekingFormats(
873 PKSMULTIPLE_ITEM *FormatList)
874 {
875 KSPROPERTY Property;
876 HRESULT hr;
877 ULONG BytesReturned;
878
879 Property.Set = KSPROPSETID_MediaSeeking;
880 Property.Id = KSPROPERTY_MEDIASEEKING_FORMATS;
881 Property.Flags = KSPROPERTY_TYPE_GET;
882
883 // query for format size list
884 hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), NULL, 0, &BytesReturned);
885
886 if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_MORE_DATA))
887 {
888 // allocate format list
889 *FormatList = (PKSMULTIPLE_ITEM)CoTaskMemAlloc(BytesReturned);
890 if (!*FormatList)
891 {
892 // not enough memory
893 return E_OUTOFMEMORY;
894 }
895
896 // get format list
897 hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)*FormatList, BytesReturned, &BytesReturned);
898 if (FAILED(hr))
899 {
900 // failed to query format list
901 CoTaskMemFree(FormatList);
902 }
903 }
904 return hr;
905 }
906
907 HRESULT
908 STDMETHODCALLTYPE
909 CKsProxy::IsFormatSupported(
910 const GUID *pFormat)
911 {
912 PKSMULTIPLE_ITEM FormatList;
913 LPGUID pGuid;
914 ULONG Index;
915 HRESULT hr = S_FALSE;
916
917 WCHAR Buffer[100];
918 LPOLESTR pstr;
919 StringFromCLSID(*pFormat, &pstr);
920 swprintf(Buffer, L"CKsProxy::IsFormatSupported %s\n",pstr);
921 OutputDebugStringW(Buffer);
922
923 if (!pFormat)
924 return E_POINTER;
925
926 // get media formats
927 hr = GetMediaSeekingFormats(&FormatList);
928 if (SUCCEEDED(hr))
929 {
930 swprintf(Buffer, L"CKsProxy::IsFormatSupported NumFormat %lu\n",FormatList->Count);
931 OutputDebugStringW(Buffer);
932
933 //iterate through format list
934 pGuid = (LPGUID)(FormatList + 1);
935 for(Index = 0; Index < FormatList->Count; Index++)
936 {
937 if (IsEqualGUID(*pGuid, *pFormat))
938 {
939 CoTaskMemFree(FormatList);
940 return S_OK;
941 }
942 pGuid++;
943 }
944 // free format list
945 CoTaskMemFree(FormatList);
946 }
947
948 // check if all plugins support it
949 for(Index = 0; Index < m_Plugins.size(); Index++)
950 {
951 // get plugin
952 IUnknown * Plugin = m_Plugins[Index];
953
954 if (!Plugin)
955 continue;
956
957 // query for IMediaSeeking interface
958 IMediaSeeking *pSeek = NULL;
959 hr = Plugin->QueryInterface(IID_IMediaSeeking, (void**)&pSeek);
960 if (FAILED(hr))
961 {
962 // plugin does not support interface
963 hr = S_FALSE;
964 OutputDebugStringW(L"CKsProxy::IsFormatSupported plugin does not support IMediaSeeking interface\n");
965 break;
966 }
967
968 // query if it is supported
969 hr = pSeek->IsFormatSupported(pFormat);
970 // release interface
971 pSeek->Release();
972
973 if (FAILED(hr) || hr == S_FALSE)
974 break;
975 }
976
977 return hr;
978 }
979
980 HRESULT
981 STDMETHODCALLTYPE
982 CKsProxy::QueryPreferredFormat(
983 GUID *pFormat)
984 {
985 PKSMULTIPLE_ITEM FormatList;
986 HRESULT hr;
987 ULONG Index;
988
989 OutputDebugStringW(L"CKsProxy::QueryPreferredFormat\n");
990
991 if (!pFormat)
992 return E_POINTER;
993
994 hr = GetMediaSeekingFormats(&FormatList);
995 if (SUCCEEDED(hr))
996 {
997 if (FormatList->Count)
998 {
999 CopyMemory(pFormat, (FormatList + 1), sizeof(GUID));
1000 CoTaskMemFree(FormatList);
1001 return S_OK;
1002 }
1003 CoTaskMemFree(FormatList);
1004 }
1005 if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND) || hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND))
1006 {
1007 // check if plugins support it
1008 for(Index = 0; Index < m_Plugins.size(); Index++)
1009 {
1010 // get plugin
1011 IUnknown * Plugin = m_Plugins[Index];
1012
1013 if (!Plugin)
1014 continue;
1015
1016 // query for IMediaSeeking interface
1017 IMediaSeeking *pSeek = NULL;
1018 hr = Plugin->QueryInterface(IID_IMediaSeeking, (void**)&pSeek);
1019 if (SUCCEEDED(hr))
1020 {
1021 // get preferred time format
1022 hr = pSeek->QueryPreferredFormat(pFormat);
1023 // release IMediaSeeking interface
1024 pSeek->Release();
1025
1026 if (hr != S_FALSE)
1027 return hr;
1028 }
1029 }
1030 hr = S_FALSE;
1031 }
1032
1033 return hr;
1034 }
1035
1036 HRESULT
1037 STDMETHODCALLTYPE
1038 CKsProxy::GetTimeFormat(
1039 GUID *pFormat)
1040 {
1041 KSPROPERTY Property;
1042 ULONG BytesReturned, Index;
1043 HRESULT hr;
1044
1045 Property.Set = KSPROPSETID_MediaSeeking;
1046 Property.Id = KSPROPERTY_MEDIASEEKING_TIMEFORMAT;
1047 Property.Flags = KSPROPERTY_TYPE_GET;
1048
1049 OutputDebugStringW(L"CKsProxy::GetTimeFormat\n");
1050
1051 hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)pFormat, sizeof(GUID), &BytesReturned);
1052 if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND) || hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND))
1053 {
1054 // check if plugins support it
1055 for(Index = 0; Index < m_Plugins.size(); Index++)
1056 {
1057 hr = E_NOTIMPL;
1058 // get plugin
1059 IUnknown * Plugin = m_Plugins[Index];
1060
1061 if (!Plugin)
1062 continue;
1063
1064 // query for IMediaSeeking interface
1065 IMediaSeeking *pSeek = NULL;
1066 hr = Plugin->QueryInterface(IID_IMediaSeeking, (void**)&pSeek);
1067 if (SUCCEEDED(hr))
1068 {
1069 // set time format
1070 hr = pSeek->GetTimeFormat(pFormat);
1071 // release IMediaSeeking interface
1072 pSeek->Release();
1073
1074 if (hr != S_FALSE)
1075 break;
1076 }
1077 }
1078 }
1079 return hr;
1080 }
1081
1082 HRESULT
1083 STDMETHODCALLTYPE
1084 CKsProxy::IsUsingTimeFormat(
1085 const GUID *pFormat)
1086 {
1087 GUID Format;
1088
1089 OutputDebugStringW(L"CKsProxy::IsUsingTimeFormat\n");
1090
1091 if (FAILED(QueryPreferredFormat(&Format)))
1092 return S_FALSE;
1093
1094 if (IsEqualGUID(Format, *pFormat))
1095 return S_OK;
1096 else
1097 return S_FALSE;
1098 }
1099
1100 HRESULT
1101 STDMETHODCALLTYPE
1102 CKsProxy::SetTimeFormat(
1103 const GUID *pFormat)
1104 {
1105 KSPROPERTY Property;
1106 ULONG BytesReturned, Index;
1107 HRESULT hr;
1108
1109 Property.Set = KSPROPSETID_MediaSeeking;
1110 Property.Id = KSPROPERTY_MEDIASEEKING_TIMEFORMAT;
1111 Property.Flags = KSPROPERTY_TYPE_SET;
1112
1113 OutputDebugStringW(L"CKsProxy::SetTimeFormat\n");
1114
1115 hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)pFormat, sizeof(GUID), &BytesReturned);
1116 if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND) || hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND))
1117 {
1118 // check if plugins support it
1119 for(Index = 0; Index < m_Plugins.size(); Index++)
1120 {
1121 hr = E_NOTIMPL;
1122 // get plugin
1123 IUnknown * Plugin = m_Plugins[Index];
1124
1125 if (!Plugin)
1126 continue;
1127
1128 // query for IMediaSeeking interface
1129 IMediaSeeking *pSeek = NULL;
1130 hr = Plugin->QueryInterface(IID_IMediaSeeking, (void**)&pSeek);
1131 if (FAILED(hr))
1132 {
1133 //not supported
1134 break;
1135 }
1136 // set time format
1137 hr = pSeek->SetTimeFormat(pFormat);
1138 // release IMediaSeeking interface
1139 pSeek->Release();
1140
1141 if (FAILED(hr))
1142 break;
1143 }
1144 }
1145 return hr;
1146 }
1147
1148 HRESULT
1149 STDMETHODCALLTYPE
1150 CKsProxy::GetDuration(
1151 LONGLONG *pDuration)
1152 {
1153 KSPROPERTY Property;
1154 ULONG BytesReturned, Index;
1155 HRESULT hr;
1156
1157 Property.Set = KSPROPSETID_MediaSeeking;
1158 Property.Id = KSPROPERTY_MEDIASEEKING_DURATION;
1159 Property.Flags = KSPROPERTY_TYPE_GET;
1160
1161 OutputDebugStringW(L"CKsProxy::GetDuration\n");
1162
1163 hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)pDuration, sizeof(LONGLONG), &BytesReturned);
1164 if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND) || hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND))
1165 {
1166 // check if plugins support it
1167 for(Index = 0; Index < m_Plugins.size(); Index++)
1168 {
1169 hr = E_NOTIMPL;
1170 // get plugin
1171 IUnknown * Plugin = m_Plugins[Index];
1172
1173 if (!Plugin)
1174 continue;
1175
1176 // query for IMediaSeeking interface
1177 IMediaSeeking *pSeek = NULL;
1178 hr = Plugin->QueryInterface(IID_IMediaSeeking, (void**)&pSeek);
1179 if (SUCCEEDED(hr))
1180 {
1181 // get duration
1182 hr = pSeek->GetStopPosition(pDuration);
1183 // release IMediaSeeking interface
1184 pSeek->Release();
1185
1186 if (hr != S_FALSE) // plugin implements it
1187 break;
1188 }
1189 }
1190 }
1191 return hr;
1192 }
1193
1194 HRESULT
1195 STDMETHODCALLTYPE
1196 CKsProxy::GetStopPosition(
1197 LONGLONG *pStop)
1198 {
1199 KSPROPERTY Property;
1200 ULONG BytesReturned, Index;
1201 HRESULT hr;
1202
1203 Property.Set = KSPROPSETID_MediaSeeking;
1204 Property.Id = KSPROPERTY_MEDIASEEKING_STOPPOSITION;
1205 Property.Flags = KSPROPERTY_TYPE_GET;
1206
1207 OutputDebugStringW(L"CKsProxy::GetStopPosition\n");
1208
1209 hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)pStop, sizeof(LONGLONG), &BytesReturned);
1210 if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND) || hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND))
1211 {
1212 // check if plugins support it
1213 for(Index = 0; Index < m_Plugins.size(); Index++)
1214 {
1215 hr = E_NOTIMPL;
1216 // get plugin
1217 IUnknown * Plugin = m_Plugins[Index];
1218
1219 if (!Plugin)
1220 continue;
1221
1222 // query for IMediaSeeking interface
1223 IMediaSeeking *pSeek = NULL;
1224 hr = Plugin->QueryInterface(IID_IMediaSeeking, (void**)&pSeek);
1225 if (SUCCEEDED(hr))
1226 {
1227 // get stop position
1228 hr = pSeek->GetStopPosition(pStop);
1229 // release IMediaSeeking interface
1230 pSeek->Release();
1231
1232 if (hr != S_FALSE) // plugin implements it
1233 break;
1234 }
1235 }
1236 }
1237 return hr;
1238 }
1239
1240 HRESULT
1241 STDMETHODCALLTYPE
1242 CKsProxy::GetCurrentPosition(
1243 LONGLONG *pCurrent)
1244 {
1245 KSPROPERTY Property;
1246 ULONG BytesReturned, Index;
1247 HRESULT hr;
1248
1249 Property.Set = KSPROPSETID_MediaSeeking;
1250 Property.Id = KSPROPERTY_MEDIASEEKING_POSITION;
1251 Property.Flags = KSPROPERTY_TYPE_GET;
1252
1253 OutputDebugStringW(L"CKsProxy::GetCurrentPosition\n");
1254
1255 hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)pCurrent, sizeof(LONGLONG), &BytesReturned);
1256 if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND) || hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND))
1257 {
1258 // check if plugins support it
1259 for(Index = 0; Index < m_Plugins.size(); Index++)
1260 {
1261 hr = E_NOTIMPL;
1262 // get plugin
1263 IUnknown * Plugin = m_Plugins[Index];
1264
1265 if (!Plugin)
1266 continue;
1267
1268 // query for IMediaSeeking interface
1269 IMediaSeeking *pSeek = NULL;
1270 hr = Plugin->QueryInterface(IID_IMediaSeeking, (void**)&pSeek);
1271 if (SUCCEEDED(hr))
1272 {
1273 // get current position
1274 hr = pSeek->GetCurrentPosition(pCurrent);
1275 // release IMediaSeeking interface
1276 pSeek->Release();
1277
1278 if (hr != S_FALSE) // plugin implements it
1279 break;
1280 }
1281 }
1282 }
1283 return hr;
1284 }
1285
1286 HRESULT
1287 STDMETHODCALLTYPE
1288 CKsProxy::ConvertTimeFormat(
1289 LONGLONG *pTarget,
1290 const GUID *pTargetFormat,
1291 LONGLONG Source,
1292 const GUID *pSourceFormat)
1293 {
1294 KSP_TIMEFORMAT Property;
1295 ULONG BytesReturned, Index;
1296 GUID SourceFormat, TargetFormat;
1297 HRESULT hr;
1298
1299 Property.Property.Set = KSPROPSETID_MediaSeeking;
1300 Property.Property.Id = KSPROPERTY_MEDIASEEKING_CONVERTTIMEFORMAT;
1301 Property.Property.Flags = KSPROPERTY_TYPE_GET;
1302
1303 OutputDebugStringW(L"CKsProxy::ConvertTimeFormat\n");
1304
1305 if (!pTargetFormat)
1306 {
1307 // get current format
1308 hr = GetTimeFormat(&TargetFormat);
1309 if (FAILED(hr))
1310 return hr;
1311
1312 pTargetFormat = &TargetFormat;
1313 }
1314
1315 if (!pSourceFormat)
1316 {
1317 // get current format
1318 hr = GetTimeFormat(&SourceFormat);
1319 if (FAILED(hr))
1320 return hr;
1321
1322 pSourceFormat = &SourceFormat;
1323 }
1324
1325 Property.SourceFormat = *pSourceFormat;
1326 Property.TargetFormat = *pTargetFormat;
1327 Property.Time = Source;
1328
1329
1330 hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSP_TIMEFORMAT), (PVOID)pTarget, sizeof(LONGLONG), &BytesReturned);
1331 if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND) || hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND))
1332 {
1333 //default error
1334 hr = E_NOTIMPL;
1335
1336 // check if plugins support it
1337 for(Index = 0; Index < m_Plugins.size(); Index++)
1338 {
1339 // get plugin
1340 IUnknown * Plugin = m_Plugins[Index];
1341
1342 if (!Plugin)
1343 continue;
1344
1345 // query for IMediaSeeking interface
1346 IMediaSeeking *pSeek = NULL;
1347 hr = Plugin->QueryInterface(IID_IMediaSeeking, (void**)&pSeek);
1348 if (SUCCEEDED(hr))
1349 {
1350 // convert time format
1351 hr = pSeek->ConvertTimeFormat(pTarget, pTargetFormat, Source, pSourceFormat);
1352 // release IMediaSeeking interface
1353 pSeek->Release();
1354
1355 if (hr != S_FALSE) // plugin implements it
1356 break;
1357 }
1358 }
1359 }
1360
1361 return hr;
1362 }
1363
1364 HRESULT
1365 STDMETHODCALLTYPE
1366 CKsProxy::SetPositions(
1367 LONGLONG *pCurrent,
1368 DWORD dwCurrentFlags,
1369 LONGLONG *pStop,
1370 DWORD dwStopFlags)
1371 {
1372 KSPROPERTY Property;
1373 KSPROPERTY_POSITIONS Positions;
1374 ULONG BytesReturned, Index;
1375 HRESULT hr;
1376
1377 Property.Set = KSPROPSETID_MediaSeeking;
1378 Property.Id = KSPROPERTY_MEDIASEEKING_POSITIONS;
1379 Property.Flags = KSPROPERTY_TYPE_SET;
1380
1381 Positions.Current = *pCurrent;
1382 Positions.CurrentFlags = (KS_SEEKING_FLAGS)dwCurrentFlags;
1383 Positions.Stop = *pStop;
1384 Positions.StopFlags = (KS_SEEKING_FLAGS)dwStopFlags;
1385
1386 OutputDebugStringW(L"CKsProxy::SetPositions\n");
1387
1388 hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&Positions, sizeof(KSPROPERTY_POSITIONS), &BytesReturned);
1389 if (SUCCEEDED(hr))
1390 {
1391 if (dwCurrentFlags & AM_SEEKING_ReturnTime)
1392 {
1393 // retrieve current position
1394 hr = GetCurrentPosition(pCurrent);
1395 }
1396
1397 if (SUCCEEDED(hr))
1398 {
1399 if (dwStopFlags & AM_SEEKING_ReturnTime)
1400 {
1401 // retrieve current position
1402 hr = GetStopPosition(pStop);
1403 }
1404 }
1405 return hr;
1406 }
1407 if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND) || hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND))
1408 {
1409 hr = E_NOTIMPL;
1410
1411 // check if plugins support it
1412 for(Index = 0; Index < m_Plugins.size(); Index++)
1413 {
1414 // get plugin
1415 IUnknown * Plugin = m_Plugins[Index];
1416
1417 if (!Plugin)
1418 continue;
1419
1420 // query for IMediaSeeking interface
1421 IMediaSeeking *pSeek = NULL;
1422 hr = Plugin->QueryInterface(IID_IMediaSeeking, (void**)&pSeek);
1423 if (SUCCEEDED(hr))
1424 {
1425 // set positions
1426 hr = pSeek->SetPositions(pCurrent, dwCurrentFlags, pStop, dwStopFlags);
1427 // release IMediaSeeking interface
1428 pSeek->Release();
1429
1430 if (FAILED(hr))
1431 break;
1432 }
1433 }
1434 }
1435
1436 return hr;
1437 }
1438
1439 HRESULT
1440 STDMETHODCALLTYPE
1441 CKsProxy::GetPositions(
1442 LONGLONG *pCurrent,
1443 LONGLONG *pStop)
1444 {
1445 HRESULT hr;
1446
1447 OutputDebugStringW(L"CKsProxy::GetPositions\n");
1448
1449 hr = GetCurrentPosition(pCurrent);
1450 if (SUCCEEDED(hr))
1451 hr = GetStopPosition(pStop);
1452
1453 return hr;
1454 }
1455
1456 HRESULT
1457 STDMETHODCALLTYPE
1458 CKsProxy::GetAvailable(
1459 LONGLONG *pEarliest,
1460 LONGLONG *pLatest)
1461 {
1462 KSPROPERTY Property;
1463 KSPROPERTY_MEDIAAVAILABLE Media;
1464 ULONG BytesReturned, Index;
1465 HRESULT hr;
1466
1467 Property.Set = KSPROPSETID_MediaSeeking;
1468 Property.Id = KSPROPERTY_MEDIASEEKING_AVAILABLE;
1469 Property.Flags = KSPROPERTY_TYPE_GET;
1470
1471 OutputDebugStringW(L"CKsProxy::GetAvailable\n");
1472
1473 hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&Media, sizeof(KSPROPERTY_MEDIAAVAILABLE), &BytesReturned);
1474 if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND) || hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND))
1475 {
1476 // check if plugins support it
1477 for(Index = 0; Index < m_Plugins.size(); Index++)
1478 {
1479 hr = E_NOTIMPL;
1480 // get plugin
1481 IUnknown * Plugin = m_Plugins[Index];
1482
1483 if (!Plugin)
1484 continue;
1485
1486 // query for IMediaSeeking interface
1487 IMediaSeeking *pSeek = NULL;
1488 hr = Plugin->QueryInterface(IID_IMediaSeeking, (void**)&pSeek);
1489 if (SUCCEEDED(hr))
1490 {
1491 // delegate call
1492 hr = pSeek->GetAvailable(pEarliest, pLatest);
1493 // release IMediaSeeking interface
1494 pSeek->Release();
1495
1496 if (hr != S_FALSE) // plugin implements it
1497 break;
1498 }
1499 }
1500 }
1501 else if (SUCCEEDED(hr))
1502 {
1503 *pEarliest = Media.Earliest;
1504 *pLatest = Media.Latest;
1505 }
1506
1507 return hr;
1508 }
1509
1510 HRESULT
1511 STDMETHODCALLTYPE
1512 CKsProxy::SetRate(
1513 double dRate)
1514 {
1515 OutputDebugStringW(L"CKsProxy::SetRate\n");
1516 return E_NOTIMPL;
1517 }
1518
1519 HRESULT
1520 STDMETHODCALLTYPE
1521 CKsProxy::GetRate(
1522 double *pdRate)
1523 {
1524 OutputDebugStringW(L"CKsProxy::GetRate\n");
1525 return E_NOTIMPL;
1526 }
1527
1528 HRESULT
1529 STDMETHODCALLTYPE
1530 CKsProxy::GetPreroll(
1531 LONGLONG *pllPreroll)
1532 {
1533 KSPROPERTY Property;
1534 ULONG BytesReturned, Index;
1535 HRESULT hr;
1536
1537 Property.Set = KSPROPSETID_MediaSeeking;
1538 Property.Id = KSPROPERTY_MEDIASEEKING_PREROLL;
1539 Property.Flags = KSPROPERTY_TYPE_GET;
1540
1541 OutputDebugStringW(L"CKsProxy::GetPreroll\n");
1542
1543 hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)pllPreroll, sizeof(LONGLONG), &BytesReturned);
1544 if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND) || hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND))
1545 {
1546 // check if all plugins support it
1547 for(Index = 0; Index < m_Plugins.size(); Index++)
1548 {
1549 // get plugin
1550 IUnknown * Plugin = m_Plugins[Index];
1551
1552 if (!Plugin)
1553 continue;
1554
1555 // query for IMediaSeeking interface
1556 IMediaSeeking *pSeek = NULL;
1557 hr = Plugin->QueryInterface(IID_IMediaSeeking, (void**)&pSeek);
1558 if (SUCCEEDED(hr))
1559 {
1560 // get preroll
1561 hr = pSeek->GetPreroll(pllPreroll);
1562 // release IMediaSeeking interface
1563 pSeek->Release();
1564
1565 if (hr != S_FALSE) // plugin implements it
1566 break;
1567 }
1568 }
1569 hr = E_NOTIMPL;
1570 }
1571 return hr;
1572 }
1573
1574 //-------------------------------------------------------------------
1575 // IAMFilterMiscFlags interface
1576 //
1577
1578 ULONG
1579 STDMETHODCALLTYPE
1580 CKsProxy::GetMiscFlags()
1581 {
1582 ULONG Index;
1583 ULONG Flags = 0;
1584 HRESULT hr;
1585 PIN_DIRECTION PinDirection;
1586 KSPIN_COMMUNICATION Communication;
1587 WCHAR Buffer[100];
1588
1589 for(Index = 0; Index < m_Pins.size(); Index++)
1590 {
1591 // get current pin
1592 IPin * pin = m_Pins[Index];
1593 // query direction
1594 hr = pin->QueryDirection(&PinDirection);
1595 if (SUCCEEDED(hr))
1596 {
1597 if (PinDirection == PINDIR_INPUT)
1598 {
1599 if (SUCCEEDED(GetPinCommunication(Index, //FIXME verify PinId
1600 &Communication)))
1601 {
1602 if (Communication == KSPIN_COMMUNICATION_NONE || Communication == KSPIN_COMMUNICATION_BRIDGE)
1603 {
1604 Flags |= AM_FILTER_MISC_FLAGS_IS_SOURCE;
1605 }
1606 }
1607 }
1608 }
1609 }
1610
1611 swprintf(Buffer, L"CKsProxy::GetMiscFlags stub Flags %x\n", Flags);
1612 OutputDebugStringW(Buffer);
1613 return Flags;
1614 }
1615
1616 //-------------------------------------------------------------------
1617 // IKsControl
1618 //
1619 HRESULT
1620 STDMETHODCALLTYPE
1621 CKsProxy::KsProperty(
1622 PKSPROPERTY Property,
1623 ULONG PropertyLength,
1624 LPVOID PropertyData,
1625 ULONG DataLength,
1626 ULONG* BytesReturned)
1627 {
1628 assert(m_hDevice != 0);
1629 OutputDebugStringW(L"CKsProxy::KsProperty\n");
1630 return KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)Property, PropertyLength, (PVOID)PropertyData, DataLength, BytesReturned);
1631 }
1632
1633 HRESULT
1634 STDMETHODCALLTYPE
1635 CKsProxy::KsMethod(
1636 PKSMETHOD Method,
1637 ULONG MethodLength,
1638 LPVOID MethodData,
1639 ULONG DataLength,
1640 ULONG* BytesReturned)
1641 {
1642 assert(m_hDevice != 0);
1643 OutputDebugStringW(L"CKsProxy::KsMethod\n");
1644 return KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_METHOD, (PVOID)Method, MethodLength, (PVOID)MethodData, DataLength, BytesReturned);
1645 }
1646
1647 HRESULT
1648 STDMETHODCALLTYPE
1649 CKsProxy::KsEvent(
1650 PKSEVENT Event,
1651 ULONG EventLength,
1652 LPVOID EventData,
1653 ULONG DataLength,
1654 ULONG* BytesReturned)
1655 {
1656 assert(m_hDevice != 0);
1657 OutputDebugStringW(L"CKsProxy::KsEvent\n");
1658 if (EventLength)
1659 return KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_ENABLE_EVENT, (PVOID)Event, EventLength, (PVOID)EventData, DataLength, BytesReturned);
1660 else
1661 return KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_DISABLE_EVENT, (PVOID)Event, EventLength, NULL, 0, BytesReturned);
1662 }
1663
1664
1665 //-------------------------------------------------------------------
1666 // IKsPropertySet
1667 //
1668 HRESULT
1669 STDMETHODCALLTYPE
1670 CKsProxy::Set(
1671 REFGUID guidPropSet,
1672 DWORD dwPropID,
1673 LPVOID pInstanceData,
1674 DWORD cbInstanceData,
1675 LPVOID pPropData,
1676 DWORD cbPropData)
1677 {
1678 ULONG BytesReturned;
1679
1680 OutputDebugStringW(L"CKsProxy::Set\n");
1681
1682 if (cbInstanceData)
1683 {
1684 PKSPROPERTY Property = (PKSPROPERTY)CoTaskMemAlloc(sizeof(KSPROPERTY) + cbInstanceData);
1685 if (!Property)
1686 return E_OUTOFMEMORY;
1687
1688 Property->Set = guidPropSet;
1689 Property->Id = dwPropID;
1690 Property->Flags = KSPROPERTY_TYPE_SET;
1691
1692 CopyMemory((Property+1), pInstanceData, cbInstanceData);
1693
1694 HRESULT hr = KsProperty(Property, sizeof(KSPROPERTY) + cbInstanceData, pPropData, cbPropData, &BytesReturned);
1695 CoTaskMemFree(Property);
1696 return hr;
1697 }
1698 else
1699 {
1700 KSPROPERTY Property;
1701
1702 Property.Set = guidPropSet;
1703 Property.Id = dwPropID;
1704 Property.Flags = KSPROPERTY_TYPE_SET;
1705
1706 HRESULT hr = KsProperty(&Property, sizeof(KSPROPERTY), pPropData, cbPropData, &BytesReturned);
1707 return hr;
1708 }
1709 }
1710
1711 HRESULT
1712 STDMETHODCALLTYPE
1713 CKsProxy::Get(
1714 REFGUID guidPropSet,
1715 DWORD dwPropID,
1716 LPVOID pInstanceData,
1717 DWORD cbInstanceData,
1718 LPVOID pPropData,
1719 DWORD cbPropData,
1720 DWORD *pcbReturned)
1721 {
1722 ULONG BytesReturned;
1723
1724 OutputDebugStringW(L"CKsProxy::Get\n");
1725
1726 if (cbInstanceData)
1727 {
1728 PKSPROPERTY Property = (PKSPROPERTY)CoTaskMemAlloc(sizeof(KSPROPERTY) + cbInstanceData);
1729 if (!Property)
1730 return E_OUTOFMEMORY;
1731
1732 Property->Set = guidPropSet;
1733 Property->Id = dwPropID;
1734 Property->Flags = KSPROPERTY_TYPE_GET;
1735
1736 CopyMemory((Property+1), pInstanceData, cbInstanceData);
1737
1738 HRESULT hr = KsProperty(Property, sizeof(KSPROPERTY) + cbInstanceData, pPropData, cbPropData, &BytesReturned);
1739 CoTaskMemFree(Property);
1740 return hr;
1741 }
1742 else
1743 {
1744 KSPROPERTY Property;
1745
1746 Property.Set = guidPropSet;
1747 Property.Id = dwPropID;
1748 Property.Flags = KSPROPERTY_TYPE_GET;
1749
1750 HRESULT hr = KsProperty(&Property, sizeof(KSPROPERTY), pPropData, cbPropData, &BytesReturned);
1751 return hr;
1752 }
1753 }
1754
1755 HRESULT
1756 STDMETHODCALLTYPE
1757 CKsProxy::QuerySupported(
1758 REFGUID guidPropSet,
1759 DWORD dwPropID,
1760 DWORD *pTypeSupport)
1761 {
1762 KSPROPERTY Property;
1763 ULONG BytesReturned;
1764
1765 OutputDebugStringW(L"CKsProxy::QuerySupported\n");
1766
1767 Property.Set = guidPropSet;
1768 Property.Id = dwPropID;
1769 Property.Flags = KSPROPERTY_TYPE_SETSUPPORT;
1770
1771 return KsProperty(&Property, sizeof(KSPROPERTY), pTypeSupport, sizeof(DWORD), &BytesReturned);
1772 }
1773
1774
1775 //-------------------------------------------------------------------
1776 // IKsTopology interface
1777 //
1778 HRESULT
1779 STDMETHODCALLTYPE
1780 CKsProxy::CreateNodeInstance(
1781 ULONG NodeId,
1782 ULONG Flags,
1783 ACCESS_MASK DesiredAccess,
1784 IUnknown* UnkOuter,
1785 REFGUID InterfaceId,
1786 LPVOID* Interface)
1787 {
1788 HRESULT hr;
1789
1790 OutputDebugStringW(L"CKsProxy::CreateNodeInstance\n");
1791
1792 *Interface = NULL;
1793
1794 if (IsEqualIID(IID_IUnknown, InterfaceId) || !UnkOuter)
1795 {
1796 hr = CKsNode_Constructor(UnkOuter, m_hDevice, NodeId, DesiredAccess, InterfaceId, Interface);
1797 }
1798 else
1799 {
1800 // interface not supported
1801 hr = E_NOINTERFACE;
1802 }
1803
1804 return hr;
1805 }
1806
1807 //-------------------------------------------------------------------
1808 // IKsAggregateControl interface
1809 //
1810 HRESULT
1811 STDMETHODCALLTYPE
1812 CKsProxy::KsAddAggregate(
1813 IN REFGUID AggregateClass)
1814 {
1815 OutputDebugStringW(L"CKsProxy::KsAddAggregate NotImplemented\n");
1816 return E_NOTIMPL;
1817 }
1818
1819 HRESULT
1820 STDMETHODCALLTYPE
1821 CKsProxy::KsRemoveAggregate(
1822 REFGUID AggregateClass)
1823 {
1824 OutputDebugStringW(L"CKsProxy::KsRemoveAggregate NotImplemented\n");
1825 return E_NOTIMPL;
1826 }
1827
1828
1829 //-------------------------------------------------------------------
1830 // IPersistStream interface
1831 //
1832
1833 HRESULT
1834 STDMETHODCALLTYPE
1835 CKsProxy::IsDirty()
1836 {
1837 OutputDebugStringW(L"CKsProxy::IsDirty Notimplemented\n");
1838 DebugBreak();
1839 return E_NOTIMPL;
1840 }
1841
1842 HRESULT
1843 STDMETHODCALLTYPE
1844 CKsProxy::Load(
1845 IStream *pStm)
1846 {
1847 HRESULT hr;
1848 WCHAR Buffer[1000];
1849 AM_MEDIA_TYPE MediaType;
1850 ULONG BytesReturned;
1851 LONG Length;
1852
1853 ULONG PinId;
1854 LPOLESTR pMajor, pSub, pFormat;
1855
1856 OutputDebugStringW(L"CKsProxy::Load\n");
1857
1858 #if 0
1859 ULONG Version = ReadInt(pStm, hr);
1860 if (Version != 1)
1861 return E_FAIL;
1862 #endif
1863
1864 hr = pStm->Read(&Length, sizeof(ULONG), &BytesReturned);
1865 swprintf(Buffer, L"Length hr %x hr length %lu\n", hr, Length);
1866 OutputDebugStringW(Buffer);
1867
1868 do
1869 {
1870 hr = pStm->Read(&PinId, sizeof(ULONG), &BytesReturned);
1871 swprintf(Buffer, L"Read: hr %08x PinId %lx BytesReturned %lu\n", hr, PinId, BytesReturned);
1872 OutputDebugStringW(Buffer);
1873
1874 if (FAILED(hr) || !BytesReturned)
1875 break;
1876
1877 Length -= BytesReturned;
1878
1879 hr = pStm->Read(&MediaType, sizeof(AM_MEDIA_TYPE), &BytesReturned);
1880 if (FAILED(hr) || BytesReturned != sizeof(AM_MEDIA_TYPE))
1881 {
1882 swprintf(Buffer, L"Read failed with %lx\n", hr);
1883 OutputDebugStringW(Buffer);
1884 break;
1885 }
1886
1887
1888 StringFromIID(MediaType.majortype, &pMajor);
1889 StringFromIID(MediaType.subtype , &pSub);
1890 StringFromIID(MediaType.formattype, &pFormat);
1891
1892 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);
1893 OutputDebugStringW(Buffer);
1894
1895 Length -= BytesReturned;
1896
1897
1898 if (MediaType.cbFormat)
1899 {
1900 MediaType.pbFormat = (BYTE*)CoTaskMemAlloc(MediaType.cbFormat);
1901 if (!MediaType.pbFormat)
1902 return E_OUTOFMEMORY;
1903
1904 hr = pStm->Read(&MediaType.pbFormat, sizeof(MediaType.cbFormat), &BytesReturned);
1905 if (FAILED(hr))
1906 {
1907 swprintf(Buffer, L"ReadFormat failed with %lx\n", hr);
1908 OutputDebugStringW(Buffer);
1909 break;
1910 }
1911 Length -= BytesReturned;
1912 }
1913
1914 }while(Length > 0);
1915
1916 DebugBreak();
1917 return S_OK;
1918 }
1919
1920 HRESULT
1921 STDMETHODCALLTYPE
1922 CKsProxy::Save(
1923 IStream *pStm,
1924 BOOL fClearDirty)
1925 {
1926 OutputDebugStringW(L"CKsProxy::Save Notimplemented\n");
1927 return E_NOTIMPL;
1928 }
1929
1930 HRESULT
1931 STDMETHODCALLTYPE
1932 CKsProxy::GetSizeMax(
1933 ULARGE_INTEGER *pcbSize)
1934 {
1935 OutputDebugStringW(L"CKsProxy::GetSizeMax Notimplemented\n");
1936 DebugBreak();
1937 return E_NOTIMPL;
1938 }
1939
1940 //-------------------------------------------------------------------
1941 // IAMDeviceRemoval interface
1942 //
1943
1944 HRESULT
1945 STDMETHODCALLTYPE
1946 CKsProxy::DeviceInfo(CLSID *pclsidInterfaceClass, LPWSTR *pwszSymbolicLink)
1947 {
1948
1949 OutputDebugStringW(L"CKsProxy::DeviceInfo\n");
1950
1951 if (!m_DevicePath)
1952 {
1953 // object not initialized
1954 return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_FILE_NOT_FOUND);
1955 }
1956
1957 // copy device interface guid
1958 CopyMemory(pclsidInterfaceClass, &m_DeviceInterfaceGUID, sizeof(GUID));
1959
1960 if (pwszSymbolicLink)
1961 {
1962 *pwszSymbolicLink = (LPWSTR)CoTaskMemAlloc((wcslen(m_DevicePath)+1) * sizeof(WCHAR));
1963 if (!*pwszSymbolicLink)
1964 return E_OUTOFMEMORY;
1965
1966 wcscpy(*pwszSymbolicLink, m_DevicePath);
1967 }
1968 return S_OK;
1969 }
1970 HRESULT
1971 STDMETHODCALLTYPE
1972 CKsProxy::Reassociate(void)
1973 {
1974 OutputDebugStringW(L"CKsProxy::Reassociate\n");
1975
1976 if (!m_DevicePath || m_hDevice)
1977 {
1978 // file path not available
1979 return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_FILE_NOT_FOUND);
1980 }
1981
1982 m_hDevice = CreateFileW(m_DevicePath, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
1983 if (!m_hDevice)
1984 {
1985 // failed to open device
1986 return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, GetLastError());
1987 }
1988
1989 // success
1990 return NOERROR;
1991 }
1992
1993 HRESULT
1994 STDMETHODCALLTYPE
1995 CKsProxy::Disassociate(void)
1996 {
1997 OutputDebugStringW(L"CKsProxy::Disassociate\n");
1998
1999 if (!m_hDevice)
2000 return E_HANDLE;
2001
2002 CloseHandle(m_hDevice);
2003 m_hDevice = NULL;
2004 return NOERROR;
2005 }
2006
2007 //-------------------------------------------------------------------
2008 // IKsClock interface
2009 //
2010
2011 HANDLE
2012 STDMETHODCALLTYPE
2013 CKsProxy::KsGetClockHandle()
2014 {
2015 OutputDebugStringW(L"CKsProxy::KsGetClockHandle\n");
2016 return m_hClock;
2017 }
2018
2019
2020 //-------------------------------------------------------------------
2021 // IKsObject interface
2022 //
2023
2024 HANDLE
2025 STDMETHODCALLTYPE
2026 CKsProxy::KsGetObjectHandle()
2027 {
2028 OutputDebugStringW(L"CKsProxy::KsGetObjectHandle\n");
2029 return m_hDevice;
2030 }
2031
2032 //-------------------------------------------------------------------
2033 // IPersistPropertyBag interface
2034 //
2035 HRESULT
2036 STDMETHODCALLTYPE
2037 CKsProxy::InitNew( void)
2038 {
2039 OutputDebugStringW(L"CKsProxy::InitNew\n");
2040 return S_OK;
2041 }
2042
2043 HRESULT
2044 STDMETHODCALLTYPE
2045 CKsProxy::GetSupportedSets(
2046 LPGUID * pOutGuid,
2047 PULONG NumGuids)
2048 {
2049 KSPROPERTY Property;
2050 LPGUID pGuid;
2051 ULONG NumProperty = 0;
2052 ULONG NumMethods = 0;
2053 ULONG NumEvents = 0;
2054 ULONG Length;
2055 ULONG BytesReturned;
2056 HRESULT hr;
2057
2058 Property.Set = GUID_NULL;
2059 Property.Id = 0;
2060 Property.Flags = KSPROPERTY_TYPE_SETSUPPORT;
2061
2062 KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), NULL, 0, &NumProperty);
2063 KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_METHOD, (PVOID)&Property, sizeof(KSPROPERTY), NULL, 0, &NumMethods);
2064 KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_ENABLE_EVENT, (PVOID)&Property, sizeof(KSPROPERTY), NULL, 0, &NumEvents);
2065
2066 Length = NumProperty + NumMethods + NumEvents;
2067
2068 // allocate guid buffer
2069 pGuid = (LPGUID)CoTaskMemAlloc(Length);
2070 if (!pGuid)
2071 {
2072 // failed
2073 return E_OUTOFMEMORY;
2074 }
2075
2076 NumProperty /= sizeof(GUID);
2077 NumMethods /= sizeof(GUID);
2078 NumEvents /= sizeof(GUID);
2079
2080 // get all properties
2081 hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)pGuid, Length, &BytesReturned);
2082 if (FAILED(hr))
2083 {
2084 CoTaskMemFree(pGuid);
2085 return E_FAIL;
2086 }
2087 Length -= BytesReturned;
2088
2089 // get all methods
2090 if (Length)
2091 {
2092 hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_METHOD, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&pGuid[NumProperty], Length, &BytesReturned);
2093 if (FAILED(hr))
2094 {
2095 CoTaskMemFree(pGuid);
2096 return E_FAIL;
2097 }
2098 Length -= BytesReturned;
2099 }
2100
2101 // get all events
2102 if (Length)
2103 {
2104 hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_ENABLE_EVENT, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&pGuid[NumProperty+NumMethods], Length, &BytesReturned);
2105 if (FAILED(hr))
2106 {
2107 CoTaskMemFree(pGuid);
2108 return E_FAIL;
2109 }
2110 Length -= BytesReturned;
2111 }
2112
2113 #ifdef KSPROXY_TRACE
2114 WCHAR Buffer[200];
2115 swprintf(Buffer, L"NumProperty %lu NumMethods %lu NumEvents %lu\n", NumProperty, NumMethods, NumEvents);
2116 OutputDebugStringW(Buffer);
2117 #endif
2118
2119 *pOutGuid = pGuid;
2120 *NumGuids = NumProperty+NumEvents+NumMethods;
2121 return S_OK;
2122 }
2123
2124 HRESULT
2125 STDMETHODCALLTYPE
2126 CKsProxy::LoadProxyPlugins(
2127 LPGUID pGuids,
2128 ULONG NumGuids)
2129 {
2130 ULONG Index;
2131 LPOLESTR pStr;
2132 HKEY hKey, hSubKey;
2133 HRESULT hr;
2134 IUnknown * pUnknown;
2135
2136 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\MediaInterfaces", 0, KEY_READ, &hKey) != ERROR_SUCCESS)
2137 {
2138 OutputDebugStringW(L"CKsProxy::LoadProxyPlugins failed to open MediaInterfaces key\n");
2139 return E_FAIL;
2140 }
2141
2142 // enumerate all sets
2143 for(Index = 0; Index < NumGuids; Index++)
2144 {
2145 // convert to string
2146 hr = StringFromCLSID(pGuids[Index], &pStr);
2147 if (FAILED(hr))
2148 return E_FAIL;
2149
2150 // now try open class key
2151 if (RegOpenKeyExW(hKey, pStr, 0, KEY_READ, &hSubKey) != ERROR_SUCCESS)
2152 {
2153 // no plugin for that set exists
2154 CoTaskMemFree(pStr);
2155 continue;
2156 }
2157
2158 // try load plugin
2159 hr = CoCreateInstance(pGuids[Index], (IBaseFilter*)this, CLSCTX_INPROC_SERVER, IID_IUnknown, (void**)&pUnknown);
2160 if (SUCCEEDED(hr))
2161 {
2162 // store plugin
2163 m_Plugins.push_back(pUnknown);
2164 }
2165 // close key
2166 RegCloseKey(hSubKey);
2167 }
2168
2169 // close media interfaces key
2170 RegCloseKey(hKey);
2171 return S_OK;
2172 }
2173
2174 HRESULT
2175 STDMETHODCALLTYPE
2176 CKsProxy::GetNumberOfPins(
2177 PULONG NumPins)
2178 {
2179 KSPROPERTY Property;
2180 ULONG BytesReturned;
2181
2182 // setup request
2183 Property.Set = KSPROPSETID_Pin;
2184 Property.Id = KSPROPERTY_PIN_CTYPES;
2185 Property.Flags = KSPROPERTY_TYPE_GET;
2186
2187 return KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)NumPins, sizeof(ULONG), &BytesReturned);
2188 }
2189
2190 HRESULT
2191 STDMETHODCALLTYPE
2192 CKsProxy::GetPinInstanceCount(
2193 ULONG PinId,
2194 PKSPIN_CINSTANCES Instances)
2195 {
2196 KSP_PIN Property;
2197 ULONG BytesReturned;
2198
2199 // setup request
2200 Property.Property.Set = KSPROPSETID_Pin;
2201 Property.Property.Id = KSPROPERTY_PIN_CINSTANCES;
2202 Property.Property.Flags = KSPROPERTY_TYPE_GET;
2203 Property.PinId = PinId;
2204 Property.Reserved = 0;
2205
2206 return KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSP_PIN), (PVOID)Instances, sizeof(KSPIN_CINSTANCES), &BytesReturned);
2207 }
2208
2209 HRESULT
2210 STDMETHODCALLTYPE
2211 CKsProxy::GetPinCommunication(
2212 ULONG PinId,
2213 KSPIN_COMMUNICATION * Communication)
2214 {
2215 KSP_PIN Property;
2216 ULONG BytesReturned;
2217
2218 // setup request
2219 Property.Property.Set = KSPROPSETID_Pin;
2220 Property.Property.Id = KSPROPERTY_PIN_COMMUNICATION;
2221 Property.Property.Flags = KSPROPERTY_TYPE_GET;
2222 Property.PinId = PinId;
2223 Property.Reserved = 0;
2224
2225 return KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSP_PIN), (PVOID)Communication, sizeof(KSPIN_COMMUNICATION), &BytesReturned);
2226 }
2227
2228 HRESULT
2229 STDMETHODCALLTYPE
2230 CKsProxy::GetPinDataflow(
2231 ULONG PinId,
2232 KSPIN_DATAFLOW * DataFlow)
2233 {
2234 KSP_PIN Property;
2235 ULONG BytesReturned;
2236
2237 // setup request
2238 Property.Property.Set = KSPROPSETID_Pin;
2239 Property.Property.Id = KSPROPERTY_PIN_DATAFLOW;
2240 Property.Property.Flags = KSPROPERTY_TYPE_GET;
2241 Property.PinId = PinId;
2242 Property.Reserved = 0;
2243
2244 return KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSP_PIN), (PVOID)DataFlow, sizeof(KSPIN_DATAFLOW), &BytesReturned);
2245 }
2246
2247 HRESULT
2248 STDMETHODCALLTYPE
2249 CKsProxy::GetPinName(
2250 ULONG PinId,
2251 KSPIN_DATAFLOW DataFlow,
2252 ULONG PinCount,
2253 LPWSTR * OutPinName)
2254 {
2255 KSP_PIN Property;
2256 LPWSTR PinName;
2257 ULONG BytesReturned;
2258 HRESULT hr;
2259 WCHAR Buffer[100];
2260
2261 // setup request
2262 Property.Property.Set = KSPROPSETID_Pin;
2263 Property.Property.Id = KSPROPERTY_PIN_NAME;
2264 Property.Property.Flags = KSPROPERTY_TYPE_GET;
2265 Property.PinId = PinId;
2266 Property.Reserved = 0;
2267
2268 // #1 try get it from pin directly
2269 hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSP_PIN), NULL, 0, &BytesReturned);
2270
2271 if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_MORE_DATA))
2272 {
2273 // allocate pin name
2274 PinName = (LPWSTR)CoTaskMemAlloc(BytesReturned);
2275 if (!PinName)
2276 return E_OUTOFMEMORY;
2277
2278 // retry with allocated buffer
2279 hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSP_PIN), PinName, BytesReturned, &BytesReturned);
2280 if (SUCCEEDED(hr))
2281 {
2282 *OutPinName = PinName;
2283 return hr;
2284 }
2285
2286 //free buffer
2287 CoTaskMemFree(PinName);
2288 }
2289
2290 //
2291 // TODO: retrieve pin name from topology node
2292 //
2293
2294 if (DataFlow == KSPIN_DATAFLOW_IN)
2295 {
2296 swprintf(Buffer, L"Input%lu", PinCount);
2297 }
2298 else
2299 {
2300 swprintf(Buffer, L"Output%lu", PinCount);
2301 }
2302
2303 // allocate pin name
2304 PinName = (LPWSTR)CoTaskMemAlloc((wcslen(Buffer)+1) * sizeof(WCHAR));
2305 if (!PinName)
2306 return E_OUTOFMEMORY;
2307
2308 // copy pin name
2309 wcscpy(PinName, Buffer);
2310
2311 // store result
2312 *OutPinName = PinName;
2313 // done
2314 return S_OK;
2315 }
2316
2317 HRESULT
2318 STDMETHODCALLTYPE
2319 CKsProxy::CreatePins()
2320 {
2321 ULONG NumPins, Index;
2322 KSPIN_CINSTANCES Instances;
2323 KSPIN_DATAFLOW DataFlow;
2324 KSPIN_COMMUNICATION Communication;
2325 HRESULT hr;
2326 WCHAR Buffer[100];
2327 LPWSTR PinName;
2328 IPin * pPin;
2329 ULONG InputPin = 0;
2330 ULONG OutputPin = 0;
2331
2332 // get number of pins
2333 hr = GetNumberOfPins(&NumPins);
2334 if (FAILED(hr))
2335 return hr;
2336
2337 for(Index = 0; Index < NumPins; Index++)
2338 {
2339 // query current instance count
2340 hr = GetPinInstanceCount(Index, &Instances);
2341 if (FAILED(hr))
2342 continue;
2343
2344 // query pin communication;
2345 hr = GetPinCommunication(Index, &Communication);
2346 if (FAILED(hr))
2347 continue;
2348
2349 if (Instances.CurrentCount == Instances.PossibleCount)
2350 {
2351 // already maximum reached for this pin
2352 continue;
2353 }
2354
2355 // get direction of pin
2356 hr = GetPinDataflow(Index, &DataFlow);
2357 if (FAILED(hr))
2358 continue;
2359
2360 if (DataFlow == KSPIN_DATAFLOW_IN)
2361 hr = GetPinName(Index, DataFlow, InputPin, &PinName);
2362 else
2363 hr = GetPinName(Index, DataFlow, OutputPin, &PinName);
2364
2365 if (FAILED(hr))
2366 continue;
2367
2368 // construct the pins
2369 if (DataFlow == KSPIN_DATAFLOW_IN)
2370 {
2371 hr = CInputPin_Constructor((IBaseFilter*)this, PinName, m_hDevice, Index, Communication, IID_IPin, (void**)&pPin);
2372 if (FAILED(hr))
2373 {
2374 CoTaskMemFree(PinName);
2375 continue;
2376 }
2377 InputPin++;
2378 }
2379 else
2380 {
2381 hr = COutputPin_Constructor((IBaseFilter*)this, PinName, Index, Communication, IID_IPin, (void**)&pPin);
2382 if (FAILED(hr))
2383 {
2384 CoTaskMemFree(PinName);
2385 continue;
2386 }
2387 OutputPin++;
2388 }
2389
2390 // store pins
2391 m_Pins.push_back(pPin);
2392
2393 swprintf(Buffer, L"Index %lu DataFlow %lu Name %s\n", Index, DataFlow, PinName);
2394 OutputDebugStringW(Buffer);
2395 }
2396
2397 return S_OK;
2398 }
2399
2400 HRESULT
2401 STDMETHODCALLTYPE
2402 CKsProxy::Load(IPropertyBag *pPropBag, IErrorLog *pErrorLog)
2403 {
2404 HRESULT hr;
2405 WCHAR Buffer[100];
2406 VARIANT varName;
2407 LPGUID pGuid;
2408 ULONG NumGuids = 0;
2409 HDEVINFO hList;
2410 SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;
2411
2412 OutputDebugStringW(L"CKsProxy::Load\n");
2413
2414 // read device path
2415 varName.vt = VT_BSTR;
2416 hr = pPropBag->Read(L"DevicePath", &varName, pErrorLog);
2417
2418 if (FAILED(hr))
2419 {
2420 swprintf(Buffer, L"CKsProxy::Load Read %lx\n", hr);
2421 OutputDebugStringW(Buffer);
2422 return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, GetLastError());
2423 }
2424
2425 OutputDebugStringW(L"DevicePath: ");
2426 OutputDebugStringW(varName.bstrVal);
2427 OutputDebugStringW(L"\n");
2428
2429 // create device list
2430 hList = SetupDiCreateDeviceInfoListExW(NULL, NULL, NULL, NULL);
2431 if (hList == INVALID_HANDLE_VALUE)
2432 {
2433 // failed to create device list
2434 return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, GetLastError());
2435 }
2436
2437 DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
2438 if (!SetupDiOpenDeviceInterfaceW(hList, (PCWSTR)varName.bstrVal, 0, &DeviceInterfaceData))
2439 {
2440 // failed to open device interface
2441 SetupDiDestroyDeviceInfoList(hList);
2442 }
2443
2444 // FIXME handle device interface links(aliases)
2445 CopyMemory(&m_DeviceInterfaceGUID, &DeviceInterfaceData.InterfaceClassGuid, sizeof(GUID));
2446
2447 // close device info list
2448 SetupDiDestroyDeviceInfoList(hList);
2449
2450 // open device
2451 m_hDevice = CreateFileW(varName.bstrVal, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
2452
2453 if (m_hDevice == INVALID_HANDLE_VALUE)
2454 {
2455 // failed to open device
2456 swprintf(Buffer, L"CKsProxy:: failed to open device with %lx\n", GetLastError());
2457 OutputDebugStringW(Buffer);
2458
2459 return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, GetLastError());
2460 }
2461
2462 // store device path
2463 m_DevicePath = varName.bstrVal;
2464
2465 // get all supported sets
2466 hr = GetSupportedSets(&pGuid, &NumGuids);
2467 if (FAILED(hr))
2468 {
2469 CloseHandle(m_hDevice);
2470 m_hDevice = NULL;
2471 return hr;
2472 }
2473
2474 // load all proxy plugins
2475 hr = LoadProxyPlugins(pGuid, NumGuids);
2476 if (FAILED(hr))
2477 {
2478 CloseHandle(m_hDevice);
2479 m_hDevice = NULL;
2480 return hr;
2481 }
2482
2483 // free sets
2484 CoTaskMemFree(pGuid);
2485
2486 // now create the input / output pins
2487 hr = CreatePins();
2488
2489 return hr;
2490 }
2491
2492 HRESULT
2493 STDMETHODCALLTYPE
2494 CKsProxy::Save(IPropertyBag *pPropBag, BOOL fClearDirty, BOOL fSaveAllProperties)
2495 {
2496 OutputDebugStringW(L"CKsProxy::Save\n");
2497 return E_NOTIMPL;
2498 }
2499
2500 //-------------------------------------------------------------------
2501 // IBaseFilter interface
2502 //
2503
2504 HRESULT
2505 STDMETHODCALLTYPE
2506 CKsProxy::GetClassID(
2507 CLSID *pClassID)
2508 {
2509 OutputDebugStringW(L"CKsProxy::GetClassID\n");
2510 CopyMemory(pClassID, &CLSID_Proxy, sizeof(GUID));
2511
2512 return S_OK;
2513 }
2514
2515 HRESULT
2516 STDMETHODCALLTYPE
2517 CKsProxy::Stop()
2518 {
2519 OutputDebugStringW(L"CKsProxy::Stop : NotImplemented\n");
2520 return E_NOTIMPL;
2521 }
2522
2523 HRESULT
2524 STDMETHODCALLTYPE
2525 CKsProxy::Pause()
2526 {
2527 HRESULT hr = S_OK;
2528
2529 OutputDebugStringW(L"CKsProxy::Pause\n");
2530
2531 if (m_FilterState == State_Stopped)
2532 {
2533 hr = SetPinState(KSSTATE_PAUSE);
2534 if (FAILED(hr))
2535 return hr;
2536
2537 }
2538
2539 m_FilterState = State_Paused;
2540 return hr;
2541
2542 }
2543
2544 HRESULT
2545 STDMETHODCALLTYPE
2546 CKsProxy::Run(
2547 REFERENCE_TIME tStart)
2548 {
2549 HRESULT hr;
2550
2551 OutputDebugStringW(L"CKsProxy::Run\n");
2552
2553 if (m_FilterState == State_Stopped)
2554 {
2555 // setting filter state to pause
2556 hr = Pause();
2557 if (FAILED(hr))
2558 return hr;
2559
2560 assert(m_FilterState == State_Paused);
2561 }
2562
2563 hr = SetPinState(KSSTATE_RUN);
2564 if (FAILED(hr))
2565 return hr;
2566
2567 m_FilterState = State_Running;
2568 return hr;
2569 }
2570
2571 HRESULT
2572 STDMETHODCALLTYPE
2573 CKsProxy::SetPinState(
2574 KSSTATE State)
2575 {
2576 HRESULT hr = S_OK;
2577 ULONG Index;
2578 IKsObject *pObject;
2579 ULONG BytesReturned;
2580 KSPROPERTY Property;
2581
2582 Property.Set = KSPROPSETID_Connection;
2583 Property.Id = KSPROPERTY_CONNECTION_STATE;
2584 Property.Flags = KSPROPERTY_TYPE_SET;
2585
2586 // set all pins to running state
2587 for(Index = 0; Index < m_Pins.size(); Index++)
2588 {
2589 IPin * Pin = m_Pins[Index];
2590 if (!Pin)
2591 continue;
2592
2593 //check if the pin is connected
2594 IPin * TempPin;
2595 hr = Pin->ConnectedTo(&TempPin);
2596 if (FAILED(hr))
2597 {
2598 // skip unconnected pins
2599 continue;
2600 }
2601
2602 // release connected pin
2603 TempPin->Release();
2604
2605 //query IKsObject interface
2606 hr = Pin->QueryInterface(IID_IKsObject, (void**)&pObject);
2607
2608 // get pin handle
2609 HANDLE hPin = pObject->KsGetObjectHandle();
2610
2611 // sanity check
2612 assert(hPin && hPin != INVALID_HANDLE_VALUE);
2613
2614 // now set state
2615 hr = KsSynchronousDeviceControl(hPin, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&State, sizeof(KSSTATE), &BytesReturned);
2616
2617 WCHAR Buffer[100];
2618 swprintf(Buffer, L"CKsProxy::SetPinState Index %u State %u hr %lx\n", Index, State, hr);
2619 OutputDebugStringW(Buffer);
2620
2621 if (FAILED(hr))
2622 return hr;
2623 }
2624 return hr;
2625 }
2626
2627 HRESULT
2628 STDMETHODCALLTYPE
2629 CKsProxy::GetState(
2630 DWORD dwMilliSecsTimeout,
2631 FILTER_STATE *State)
2632 {
2633 *State = m_FilterState;
2634 return S_OK;
2635 }
2636
2637 HRESULT
2638 STDMETHODCALLTYPE
2639 CKsProxy::SetSyncSource(
2640 IReferenceClock *pClock)
2641 {
2642 HRESULT hr;
2643 IKsClock *pKsClock;
2644 HANDLE hClock, hPin;
2645 ULONG Index;
2646 IPin * pin;
2647 IKsObject * pObject;
2648 KSPROPERTY Property;
2649 ULONG BytesReturned;
2650 PIN_DIRECTION PinDir;
2651
2652 // Plug In Distributor: IKsClock
2653 OutputDebugStringW(L"CKsProxy::SetSyncSource\n");
2654
2655 // FIXME
2656 // need locks
2657
2658 if (pClock)
2659 {
2660 hr = pClock->QueryInterface(IID_IKsClock, (void**)&pKsClock);
2661 if (FAILED(hr))
2662 {
2663 hr = m_ReferenceClock->QueryInterface(IID_IKsClock, (void**)&pKsClock);
2664 if (FAILED(hr))
2665 return hr;
2666 }
2667
2668 // get clock handle
2669 hClock = pKsClock->KsGetClockHandle();
2670
2671 // release IKsClock interface
2672 pKsClock->Release();
2673 m_hClock = hClock;
2674 }
2675 else
2676 {
2677 // no clock handle
2678 m_hClock = NULL;
2679 }
2680
2681
2682 // distribute clock to all pins
2683 for(Index = 0; Index < m_Pins.size(); Index++)
2684 {
2685 // get current pin
2686 pin = m_Pins[Index];
2687 if (!pin)
2688 continue;
2689
2690 // get IKsObject interface
2691 hr = pin->QueryInterface(IID_IKsObject, (void **)&pObject);
2692 if (SUCCEEDED(hr))
2693 {
2694 // get pin handle
2695 hPin = pObject->KsGetObjectHandle();
2696 if (hPin != INVALID_HANDLE_VALUE && hPin)
2697 {
2698 // set clock
2699 Property.Set = KSPROPSETID_Stream;
2700 Property.Id = KSPROPERTY_STREAM_MASTERCLOCK;
2701 Property.Flags = KSPROPERTY_TYPE_SET;
2702
2703 // set master clock
2704 hr = KsSynchronousDeviceControl(hPin, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&m_hClock, sizeof(HANDLE), &BytesReturned);
2705
2706 if (FAILED(hr))
2707 {
2708 if (hr != MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND) &&
2709 hr != MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND))
2710 {
2711 // failed to set master clock
2712 pObject->Release();
2713 WCHAR Buffer[100];
2714 swprintf(Buffer, L"CKsProxy::SetSyncSource KSPROPERTY_STREAM_MASTERCLOCK failed with %lx\n", hr);
2715 OutputDebugStringW(Buffer);
2716 return hr;
2717 }
2718 }
2719 }
2720 // release IKsObject
2721 pObject->Release();
2722 }
2723
2724 // now get the direction
2725 hr = pin->QueryDirection(&PinDir);
2726 if (SUCCEEDED(hr))
2727 {
2728 if (PinDir == PINDIR_OUTPUT)
2729 {
2730 // notify pin via
2731 //CBaseStreamControl::SetSyncSource(pClock)
2732 }
2733 }
2734 }
2735
2736 if (pClock)
2737 {
2738 pClock->AddRef();
2739 }
2740
2741 if (m_ReferenceClock)
2742 {
2743 m_ReferenceClock->Release();
2744 }
2745
2746 m_ReferenceClock = pClock;
2747 OutputDebugStringW(L"CKsProxy::SetSyncSource done\n");
2748 return S_OK;
2749 }
2750
2751 HRESULT
2752 STDMETHODCALLTYPE
2753 CKsProxy::GetSyncSource(
2754 IReferenceClock **pClock)
2755 {
2756 OutputDebugStringW(L"CKsProxy::GetSyncSource\n");
2757
2758 if (!pClock)
2759 return E_POINTER;
2760
2761 if (m_ReferenceClock)
2762 m_ReferenceClock->AddRef();
2763
2764 *pClock = m_ReferenceClock;
2765 return S_OK;
2766 }
2767
2768 HRESULT
2769 STDMETHODCALLTYPE
2770 CKsProxy::EnumPins(
2771 IEnumPins **ppEnum)
2772 {
2773 OutputDebugStringW(L"CKsProxy::EnumPins\n");
2774 return CEnumPins_fnConstructor(m_Pins, IID_IEnumPins, (void**)ppEnum);
2775 }
2776
2777 HRESULT
2778 STDMETHODCALLTYPE
2779 CKsProxy::FindPin(
2780 LPCWSTR Id, IPin **ppPin)
2781 {
2782 ULONG PinId;
2783
2784 OutputDebugStringW(L"CKsProxy::FindPin\n");
2785
2786 if (!ppPin)
2787 return E_POINTER;
2788
2789 // convert to pin
2790 int ret = swscanf(Id, L"%u", &PinId);
2791
2792 if (!ret || ret == EOF)
2793 {
2794 // invalid id
2795 return VFW_E_NOT_FOUND;
2796 }
2797
2798 if (PinId >= m_Pins.size() || m_Pins[PinId] == NULL)
2799 {
2800 // invalid id
2801 return VFW_E_NOT_FOUND;
2802 }
2803
2804 // found pin
2805 *ppPin = m_Pins[PinId];
2806 m_Pins[PinId]->AddRef();
2807
2808 return S_OK;
2809 }
2810
2811
2812 HRESULT
2813 STDMETHODCALLTYPE
2814 CKsProxy::QueryFilterInfo(
2815 FILTER_INFO *pInfo)
2816 {
2817 if (!pInfo)
2818 return E_POINTER;
2819
2820 OutputDebugStringW(L"CKsProxy::QueryFilterInfo\n");
2821
2822 pInfo->achName[0] = L'\0';
2823 pInfo->pGraph = m_pGraph;
2824
2825 if (m_pGraph)
2826 m_pGraph->AddRef();
2827
2828 return S_OK;
2829 }
2830
2831 HRESULT
2832 STDMETHODCALLTYPE
2833 CKsProxy::JoinFilterGraph(
2834 IFilterGraph *pGraph,
2835 LPCWSTR pName)
2836 {
2837 OutputDebugStringW(L"CKsProxy::JoinFilterGraph\n");
2838
2839 if (pGraph)
2840 {
2841 // joining filter graph
2842 m_pGraph = pGraph;
2843 }
2844 else
2845 {
2846 // leaving graph
2847 m_pGraph = 0;
2848 }
2849
2850 return S_OK;
2851 }
2852
2853
2854 HRESULT
2855 STDMETHODCALLTYPE
2856 CKsProxy::QueryVendorInfo(
2857 LPWSTR *pVendorInfo)
2858 {
2859 OutputDebugStringW(L"CKsProxy::QueryVendorInfo\n");
2860 return StringFromCLSID(CLSID_Proxy, pVendorInfo);
2861 }
2862
2863 //-------------------------------------------------------------------
2864 // IAMovieSetup interface
2865 //
2866
2867 HRESULT
2868 STDMETHODCALLTYPE
2869 CKsProxy::Register()
2870 {
2871 OutputDebugStringW(L"CKsProxy::Register : NotImplemented\n");
2872 return E_NOTIMPL;
2873 }
2874
2875 HRESULT
2876 STDMETHODCALLTYPE
2877 CKsProxy::Unregister()
2878 {
2879 OutputDebugStringW(L"CKsProxy::Unregister : NotImplemented\n");
2880 return E_NOTIMPL;
2881 }
2882
2883 HRESULT
2884 WINAPI
2885 CKsProxy_Constructor(
2886 IUnknown * pUnkOuter,
2887 REFIID riid,
2888 LPVOID * ppv)
2889 {
2890 WCHAR Buffer[100];
2891 LPOLESTR pstr;
2892 StringFromCLSID(riid, &pstr);
2893 swprintf(Buffer, L"CKsProxy_Constructor pUnkOuter %p riid %s\n", pUnkOuter, pstr);
2894 OutputDebugStringW(Buffer);
2895
2896 CKsProxy * handler = new CKsProxy();
2897
2898 if (!handler)
2899 return E_OUTOFMEMORY;
2900
2901 if (FAILED(handler->QueryInterface(riid, ppv)))
2902 {
2903 /* not supported */
2904 delete handler;
2905 return E_NOINTERFACE;
2906 }
2907
2908 return S_OK;
2909 }