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