[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(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 OutputDebugStringW(L"CKsProxy::SetRate\n");
1513 return E_NOTIMPL;
1514 }
1515
1516 HRESULT
1517 STDMETHODCALLTYPE
1518 CKsProxy::GetRate(
1519 double *pdRate)
1520 {
1521 OutputDebugStringW(L"CKsProxy::GetRate\n");
1522 return E_NOTIMPL;
1523 }
1524
1525 HRESULT
1526 STDMETHODCALLTYPE
1527 CKsProxy::GetPreroll(
1528 LONGLONG *pllPreroll)
1529 {
1530 KSPROPERTY Property;
1531 ULONG BytesReturned, Index;
1532 HRESULT hr;
1533
1534 Property.Set = KSPROPSETID_MediaSeeking;
1535 Property.Id = KSPROPERTY_MEDIASEEKING_PREROLL;
1536 Property.Flags = KSPROPERTY_TYPE_GET;
1537
1538 OutputDebugStringW(L"CKsProxy::GetPreroll\n");
1539
1540 hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)pllPreroll, sizeof(LONGLONG), &BytesReturned);
1541 if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND) || hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND))
1542 {
1543 // check if all plugins support it
1544 for(Index = 0; Index < m_Plugins.size(); Index++)
1545 {
1546 // get plugin
1547 IUnknown * Plugin = m_Plugins[Index];
1548
1549 if (!Plugin)
1550 continue;
1551
1552 // query for IMediaSeeking interface
1553 IMediaSeeking *pSeek = NULL;
1554 hr = Plugin->QueryInterface(IID_IMediaSeeking, (void**)&pSeek);
1555 if (SUCCEEDED(hr))
1556 {
1557 // get preroll
1558 hr = pSeek->GetPreroll(pllPreroll);
1559 // release IMediaSeeking interface
1560 pSeek->Release();
1561
1562 if (hr != S_FALSE) // plugin implements it
1563 break;
1564 }
1565 }
1566 hr = E_NOTIMPL;
1567 }
1568 return hr;
1569 }
1570
1571 //-------------------------------------------------------------------
1572 // IAMFilterMiscFlags interface
1573 //
1574
1575 ULONG
1576 STDMETHODCALLTYPE
1577 CKsProxy::GetMiscFlags()
1578 {
1579 ULONG Index;
1580 ULONG Flags = 0;
1581 HRESULT hr;
1582 PIN_DIRECTION PinDirection;
1583 KSPIN_COMMUNICATION Communication;
1584
1585 for(Index = 0; Index < m_Pins.size(); Index++)
1586 {
1587 // get current pin
1588 IPin * pin = m_Pins[Index];
1589 // query direction
1590 hr = pin->QueryDirection(&PinDirection);
1591 if (SUCCEEDED(hr))
1592 {
1593 if (PinDirection == PINDIR_INPUT)
1594 {
1595 if (SUCCEEDED(GetPinCommunication(Index, //FIXME verify PinId
1596 &Communication)))
1597 {
1598 if (Communication == KSPIN_COMMUNICATION_NONE || Communication == KSPIN_COMMUNICATION_BRIDGE)
1599 {
1600 Flags |= AM_FILTER_MISC_FLAGS_IS_SOURCE;
1601 }
1602 }
1603 }
1604 }
1605 }
1606
1607 OutputDebugStringW(L"CKsProxy::GetMiscFlags stub\n");
1608 return Flags;
1609 }
1610
1611 //-------------------------------------------------------------------
1612 // IKsControl
1613 //
1614 HRESULT
1615 STDMETHODCALLTYPE
1616 CKsProxy::KsProperty(
1617 PKSPROPERTY Property,
1618 ULONG PropertyLength,
1619 LPVOID PropertyData,
1620 ULONG DataLength,
1621 ULONG* BytesReturned)
1622 {
1623 assert(m_hDevice != 0);
1624 OutputDebugStringW(L"CKsProxy::KsProperty\n");
1625 return KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)Property, PropertyLength, (PVOID)PropertyData, DataLength, BytesReturned);
1626 }
1627
1628 HRESULT
1629 STDMETHODCALLTYPE
1630 CKsProxy::KsMethod(
1631 PKSMETHOD Method,
1632 ULONG MethodLength,
1633 LPVOID MethodData,
1634 ULONG DataLength,
1635 ULONG* BytesReturned)
1636 {
1637 assert(m_hDevice != 0);
1638 OutputDebugStringW(L"CKsProxy::KsMethod\n");
1639 return KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_METHOD, (PVOID)Method, MethodLength, (PVOID)MethodData, DataLength, BytesReturned);
1640 }
1641
1642 HRESULT
1643 STDMETHODCALLTYPE
1644 CKsProxy::KsEvent(
1645 PKSEVENT Event,
1646 ULONG EventLength,
1647 LPVOID EventData,
1648 ULONG DataLength,
1649 ULONG* BytesReturned)
1650 {
1651 assert(m_hDevice != 0);
1652 OutputDebugStringW(L"CKsProxy::KsEvent\n");
1653 if (EventLength)
1654 return KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_ENABLE_EVENT, (PVOID)Event, EventLength, (PVOID)EventData, DataLength, BytesReturned);
1655 else
1656 return KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_DISABLE_EVENT, (PVOID)Event, EventLength, NULL, 0, BytesReturned);
1657 }
1658
1659
1660 //-------------------------------------------------------------------
1661 // IKsPropertySet
1662 //
1663 HRESULT
1664 STDMETHODCALLTYPE
1665 CKsProxy::Set(
1666 REFGUID guidPropSet,
1667 DWORD dwPropID,
1668 LPVOID pInstanceData,
1669 DWORD cbInstanceData,
1670 LPVOID pPropData,
1671 DWORD cbPropData)
1672 {
1673 ULONG BytesReturned;
1674
1675 OutputDebugStringW(L"CKsProxy::Set\n");
1676
1677 if (cbInstanceData)
1678 {
1679 PKSPROPERTY Property = (PKSPROPERTY)CoTaskMemAlloc(sizeof(KSPROPERTY) + cbInstanceData);
1680 if (!Property)
1681 return E_OUTOFMEMORY;
1682
1683 Property->Set = guidPropSet;
1684 Property->Id = dwPropID;
1685 Property->Flags = KSPROPERTY_TYPE_SET;
1686
1687 CopyMemory((Property+1), pInstanceData, cbInstanceData);
1688
1689 HRESULT hr = KsProperty(Property, sizeof(KSPROPERTY) + cbInstanceData, pPropData, cbPropData, &BytesReturned);
1690 CoTaskMemFree(Property);
1691 return hr;
1692 }
1693 else
1694 {
1695 KSPROPERTY Property;
1696
1697 Property.Set = guidPropSet;
1698 Property.Id = dwPropID;
1699 Property.Flags = KSPROPERTY_TYPE_SET;
1700
1701 HRESULT hr = KsProperty(&Property, sizeof(KSPROPERTY), pPropData, cbPropData, &BytesReturned);
1702 return hr;
1703 }
1704 }
1705
1706 HRESULT
1707 STDMETHODCALLTYPE
1708 CKsProxy::Get(
1709 REFGUID guidPropSet,
1710 DWORD dwPropID,
1711 LPVOID pInstanceData,
1712 DWORD cbInstanceData,
1713 LPVOID pPropData,
1714 DWORD cbPropData,
1715 DWORD *pcbReturned)
1716 {
1717 ULONG BytesReturned;
1718
1719 OutputDebugStringW(L"CKsProxy::Get\n");
1720
1721 if (cbInstanceData)
1722 {
1723 PKSPROPERTY Property = (PKSPROPERTY)CoTaskMemAlloc(sizeof(KSPROPERTY) + cbInstanceData);
1724 if (!Property)
1725 return E_OUTOFMEMORY;
1726
1727 Property->Set = guidPropSet;
1728 Property->Id = dwPropID;
1729 Property->Flags = KSPROPERTY_TYPE_GET;
1730
1731 CopyMemory((Property+1), pInstanceData, cbInstanceData);
1732
1733 HRESULT hr = KsProperty(Property, sizeof(KSPROPERTY) + cbInstanceData, pPropData, cbPropData, &BytesReturned);
1734 CoTaskMemFree(Property);
1735 return hr;
1736 }
1737 else
1738 {
1739 KSPROPERTY Property;
1740
1741 Property.Set = guidPropSet;
1742 Property.Id = dwPropID;
1743 Property.Flags = KSPROPERTY_TYPE_GET;
1744
1745 HRESULT hr = KsProperty(&Property, sizeof(KSPROPERTY), pPropData, cbPropData, &BytesReturned);
1746 return hr;
1747 }
1748 }
1749
1750 HRESULT
1751 STDMETHODCALLTYPE
1752 CKsProxy::QuerySupported(
1753 REFGUID guidPropSet,
1754 DWORD dwPropID,
1755 DWORD *pTypeSupport)
1756 {
1757 KSPROPERTY Property;
1758 ULONG BytesReturned;
1759
1760 OutputDebugStringW(L"CKsProxy::QuerySupported\n");
1761
1762 Property.Set = guidPropSet;
1763 Property.Id = dwPropID;
1764 Property.Flags = KSPROPERTY_TYPE_SETSUPPORT;
1765
1766 return KsProperty(&Property, sizeof(KSPROPERTY), pTypeSupport, sizeof(DWORD), &BytesReturned);
1767 }
1768
1769
1770 //-------------------------------------------------------------------
1771 // IKsTopology interface
1772 //
1773 HRESULT
1774 STDMETHODCALLTYPE
1775 CKsProxy::CreateNodeInstance(
1776 ULONG NodeId,
1777 ULONG Flags,
1778 ACCESS_MASK DesiredAccess,
1779 IUnknown* UnkOuter,
1780 REFGUID InterfaceId,
1781 LPVOID* Interface)
1782 {
1783 HRESULT hr;
1784
1785 OutputDebugStringW(L"CKsProxy::CreateNodeInstance\n");
1786
1787 *Interface = NULL;
1788
1789 if (IsEqualIID(IID_IUnknown, InterfaceId) || !UnkOuter)
1790 {
1791 hr = CKsNode_Constructor(UnkOuter, m_hDevice, NodeId, DesiredAccess, InterfaceId, Interface);
1792 }
1793 else
1794 {
1795 // interface not supported
1796 hr = E_NOINTERFACE;
1797 }
1798
1799 return hr;
1800 }
1801
1802 //-------------------------------------------------------------------
1803 // IKsAggregateControl interface
1804 //
1805 HRESULT
1806 STDMETHODCALLTYPE
1807 CKsProxy::KsAddAggregate(
1808 IN REFGUID AggregateClass)
1809 {
1810 OutputDebugStringW(L"CKsProxy::KsAddAggregate NotImplemented\n");
1811 return E_NOTIMPL;
1812 }
1813
1814 HRESULT
1815 STDMETHODCALLTYPE
1816 CKsProxy::KsRemoveAggregate(
1817 REFGUID AggregateClass)
1818 {
1819 OutputDebugStringW(L"CKsProxy::KsRemoveAggregate NotImplemented\n");
1820 return E_NOTIMPL;
1821 }
1822
1823
1824 //-------------------------------------------------------------------
1825 // IPersistStream interface
1826 //
1827
1828 HRESULT
1829 STDMETHODCALLTYPE
1830 CKsProxy::IsDirty()
1831 {
1832 OutputDebugStringW(L"CKsProxy::IsDirty Notimplemented\n");
1833 DebugBreak();
1834 return E_NOTIMPL;
1835 }
1836
1837 HRESULT
1838 STDMETHODCALLTYPE
1839 CKsProxy::Load(
1840 IStream *pStm)
1841 {
1842 HRESULT hr;
1843 WCHAR Buffer[1000];
1844 AM_MEDIA_TYPE MediaType;
1845 ULONG BytesReturned;
1846 LONG Length;
1847
1848 ULONG PinId;
1849 LPOLESTR pMajor, pSub, pFormat;
1850
1851 OutputDebugStringW(L"CKsProxy::Load\n");
1852
1853 #if 0
1854 ULONG Version = ReadInt(pStm, hr);
1855 if (Version != 1)
1856 return E_FAIL;
1857 #endif
1858
1859 hr = pStm->Read(&Length, sizeof(ULONG), &BytesReturned);
1860 swprintf(Buffer, L"Length hr %x hr length %lu\n", hr, Length);
1861 OutputDebugStringW(Buffer);
1862
1863 do
1864 {
1865 hr = pStm->Read(&PinId, sizeof(ULONG), &BytesReturned);
1866 swprintf(Buffer, L"Read: hr %08x PinId %lx BytesReturned %lu\n", hr, PinId, BytesReturned);
1867 OutputDebugStringW(Buffer);
1868
1869 if (FAILED(hr) || !BytesReturned)
1870 break;
1871
1872 Length -= BytesReturned;
1873
1874 hr = pStm->Read(&MediaType, sizeof(AM_MEDIA_TYPE), &BytesReturned);
1875 if (FAILED(hr) || BytesReturned != sizeof(AM_MEDIA_TYPE))
1876 {
1877 swprintf(Buffer, L"Read failed with %lx\n", hr);
1878 OutputDebugStringW(Buffer);
1879 break;
1880 }
1881
1882
1883 StringFromIID(MediaType.majortype, &pMajor);
1884 StringFromIID(MediaType.subtype , &pSub);
1885 StringFromIID(MediaType.formattype, &pFormat);
1886
1887 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);
1888 OutputDebugStringW(Buffer);
1889
1890 Length -= BytesReturned;
1891
1892
1893 if (MediaType.cbFormat)
1894 {
1895 MediaType.pbFormat = (BYTE*)CoTaskMemAlloc(MediaType.cbFormat);
1896 if (!MediaType.pbFormat)
1897 return E_OUTOFMEMORY;
1898
1899 hr = pStm->Read(&MediaType.pbFormat, sizeof(MediaType.cbFormat), &BytesReturned);
1900 if (FAILED(hr))
1901 {
1902 swprintf(Buffer, L"ReadFormat failed with %lx\n", hr);
1903 OutputDebugStringW(Buffer);
1904 break;
1905 }
1906 Length -= BytesReturned;
1907 }
1908
1909 }while(Length > 0);
1910
1911 DebugBreak();
1912 return S_OK;
1913 }
1914
1915 HRESULT
1916 STDMETHODCALLTYPE
1917 CKsProxy::Save(
1918 IStream *pStm,
1919 BOOL fClearDirty)
1920 {
1921 OutputDebugStringW(L"CKsProxy::Save Notimplemented\n");
1922 return E_NOTIMPL;
1923 }
1924
1925 HRESULT
1926 STDMETHODCALLTYPE
1927 CKsProxy::GetSizeMax(
1928 ULARGE_INTEGER *pcbSize)
1929 {
1930 OutputDebugStringW(L"CKsProxy::GetSizeMax Notimplemented\n");
1931 DebugBreak();
1932 return E_NOTIMPL;
1933 }
1934
1935 //-------------------------------------------------------------------
1936 // IAMDeviceRemoval interface
1937 //
1938
1939 HRESULT
1940 STDMETHODCALLTYPE
1941 CKsProxy::DeviceInfo(CLSID *pclsidInterfaceClass, LPWSTR *pwszSymbolicLink)
1942 {
1943
1944 OutputDebugStringW(L"CKsProxy::DeviceInfo\n");
1945
1946 if (!m_DevicePath)
1947 {
1948 // object not initialized
1949 return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_FILE_NOT_FOUND);
1950 }
1951
1952 // copy device interface guid
1953 CopyMemory(pclsidInterfaceClass, &m_DeviceInterfaceGUID, sizeof(GUID));
1954
1955 if (pwszSymbolicLink)
1956 {
1957 *pwszSymbolicLink = (LPWSTR)CoTaskMemAlloc((wcslen(m_DevicePath)+1) * sizeof(WCHAR));
1958 if (!*pwszSymbolicLink)
1959 return E_OUTOFMEMORY;
1960
1961 wcscpy(*pwszSymbolicLink, m_DevicePath);
1962 }
1963 return S_OK;
1964 }
1965 HRESULT
1966 STDMETHODCALLTYPE
1967 CKsProxy::Reassociate(void)
1968 {
1969 OutputDebugStringW(L"CKsProxy::Reassociate\n");
1970
1971 if (!m_DevicePath || m_hDevice)
1972 {
1973 // file path not available
1974 return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_FILE_NOT_FOUND);
1975 }
1976
1977 m_hDevice = CreateFileW(m_DevicePath, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
1978 if (!m_hDevice)
1979 {
1980 // failed to open device
1981 return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, GetLastError());
1982 }
1983
1984 // success
1985 return NOERROR;
1986 }
1987
1988 HRESULT
1989 STDMETHODCALLTYPE
1990 CKsProxy::Disassociate(void)
1991 {
1992 OutputDebugStringW(L"CKsProxy::Disassociate\n");
1993
1994 if (!m_hDevice)
1995 return E_HANDLE;
1996
1997 CloseHandle(m_hDevice);
1998 m_hDevice = NULL;
1999 return NOERROR;
2000 }
2001
2002 //-------------------------------------------------------------------
2003 // IKsClock interface
2004 //
2005
2006 HANDLE
2007 STDMETHODCALLTYPE
2008 CKsProxy::KsGetClockHandle()
2009 {
2010 OutputDebugStringW(L"CKsProxy::KsGetClockHandle\n");
2011 return m_hClock;
2012 }
2013
2014
2015 //-------------------------------------------------------------------
2016 // IKsObject interface
2017 //
2018
2019 HANDLE
2020 STDMETHODCALLTYPE
2021 CKsProxy::KsGetObjectHandle()
2022 {
2023 OutputDebugStringW(L"CKsProxy::KsGetObjectHandle\n");
2024 return m_hDevice;
2025 }
2026
2027 //-------------------------------------------------------------------
2028 // IPersistPropertyBag interface
2029 //
2030 HRESULT
2031 STDMETHODCALLTYPE
2032 CKsProxy::InitNew( void)
2033 {
2034 OutputDebugStringW(L"CKsProxy::InitNew\n");
2035 return S_OK;
2036 }
2037
2038 HRESULT
2039 STDMETHODCALLTYPE
2040 CKsProxy::GetSupportedSets(
2041 LPGUID * pOutGuid,
2042 PULONG NumGuids)
2043 {
2044 KSPROPERTY Property;
2045 LPGUID pGuid;
2046 ULONG NumProperty = 0;
2047 ULONG NumMethods = 0;
2048 ULONG NumEvents = 0;
2049 ULONG Length;
2050 ULONG BytesReturned;
2051 HRESULT hr;
2052
2053 Property.Set = GUID_NULL;
2054 Property.Id = 0;
2055 Property.Flags = KSPROPERTY_TYPE_SETSUPPORT;
2056
2057 KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), NULL, 0, &NumProperty);
2058 KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_METHOD, (PVOID)&Property, sizeof(KSPROPERTY), NULL, 0, &NumMethods);
2059 KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_ENABLE_EVENT, (PVOID)&Property, sizeof(KSPROPERTY), NULL, 0, &NumEvents);
2060
2061 Length = NumProperty + NumMethods + NumEvents;
2062
2063 // allocate guid buffer
2064 pGuid = (LPGUID)CoTaskMemAlloc(Length);
2065 if (!pGuid)
2066 {
2067 // failed
2068 return E_OUTOFMEMORY;
2069 }
2070
2071 NumProperty /= sizeof(GUID);
2072 NumMethods /= sizeof(GUID);
2073 NumEvents /= sizeof(GUID);
2074
2075 // get all properties
2076 hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)pGuid, Length, &BytesReturned);
2077 if (FAILED(hr))
2078 {
2079 CoTaskMemFree(pGuid);
2080 return E_FAIL;
2081 }
2082 Length -= BytesReturned;
2083
2084 // get all methods
2085 if (Length)
2086 {
2087 hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_METHOD, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&pGuid[NumProperty], Length, &BytesReturned);
2088 if (FAILED(hr))
2089 {
2090 CoTaskMemFree(pGuid);
2091 return E_FAIL;
2092 }
2093 Length -= BytesReturned;
2094 }
2095
2096 // get all events
2097 if (Length)
2098 {
2099 hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_ENABLE_EVENT, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&pGuid[NumProperty+NumMethods], Length, &BytesReturned);
2100 if (FAILED(hr))
2101 {
2102 CoTaskMemFree(pGuid);
2103 return E_FAIL;
2104 }
2105 Length -= BytesReturned;
2106 }
2107
2108 #ifdef KSPROXY_TRACE
2109 WCHAR Buffer[200];
2110 swprintf(Buffer, L"NumProperty %lu NumMethods %lu NumEvents %lu\n", NumProperty, NumMethods, NumEvents);
2111 OutputDebugStringW(Buffer);
2112 #endif
2113
2114 *pOutGuid = pGuid;
2115 *NumGuids = NumProperty+NumEvents+NumMethods;
2116 return S_OK;
2117 }
2118
2119 HRESULT
2120 STDMETHODCALLTYPE
2121 CKsProxy::LoadProxyPlugins(
2122 LPGUID pGuids,
2123 ULONG NumGuids)
2124 {
2125 ULONG Index;
2126 LPOLESTR pStr;
2127 HKEY hKey, hSubKey;
2128 HRESULT hr;
2129 IUnknown * pUnknown;
2130
2131 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\MediaInterfaces", 0, KEY_READ, &hKey) != ERROR_SUCCESS)
2132 {
2133 OutputDebugStringW(L"CKsProxy::LoadProxyPlugins failed to open MediaInterfaces key\n");
2134 return E_FAIL;
2135 }
2136
2137 // enumerate all sets
2138 for(Index = 0; Index < NumGuids; Index++)
2139 {
2140 // convert to string
2141 hr = StringFromCLSID(pGuids[Index], &pStr);
2142 if (FAILED(hr))
2143 return E_FAIL;
2144
2145 // now try open class key
2146 if (RegOpenKeyExW(hKey, pStr, 0, KEY_READ, &hSubKey) != ERROR_SUCCESS)
2147 {
2148 // no plugin for that set exists
2149 CoTaskMemFree(pStr);
2150 continue;
2151 }
2152
2153 // try load plugin
2154 hr = CoCreateInstance(pGuids[Index], (IBaseFilter*)this, CLSCTX_INPROC_SERVER, IID_IUnknown, (void**)&pUnknown);
2155 if (SUCCEEDED(hr))
2156 {
2157 // store plugin
2158 m_Plugins.push_back(pUnknown);
2159 }
2160 // close key
2161 RegCloseKey(hSubKey);
2162 }
2163
2164 // close media interfaces key
2165 RegCloseKey(hKey);
2166 return S_OK;
2167 }
2168
2169 HRESULT
2170 STDMETHODCALLTYPE
2171 CKsProxy::GetNumberOfPins(
2172 PULONG NumPins)
2173 {
2174 KSPROPERTY Property;
2175 ULONG BytesReturned;
2176
2177 // setup request
2178 Property.Set = KSPROPSETID_Pin;
2179 Property.Id = KSPROPERTY_PIN_CTYPES;
2180 Property.Flags = KSPROPERTY_TYPE_GET;
2181
2182 return KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)NumPins, sizeof(ULONG), &BytesReturned);
2183 }
2184
2185 HRESULT
2186 STDMETHODCALLTYPE
2187 CKsProxy::GetPinInstanceCount(
2188 ULONG PinId,
2189 PKSPIN_CINSTANCES Instances)
2190 {
2191 KSP_PIN Property;
2192 ULONG BytesReturned;
2193
2194 // setup request
2195 Property.Property.Set = KSPROPSETID_Pin;
2196 Property.Property.Id = KSPROPERTY_PIN_CINSTANCES;
2197 Property.Property.Flags = KSPROPERTY_TYPE_GET;
2198 Property.PinId = PinId;
2199 Property.Reserved = 0;
2200
2201 return KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSP_PIN), (PVOID)Instances, sizeof(KSPIN_CINSTANCES), &BytesReturned);
2202 }
2203
2204 HRESULT
2205 STDMETHODCALLTYPE
2206 CKsProxy::GetPinCommunication(
2207 ULONG PinId,
2208 KSPIN_COMMUNICATION * Communication)
2209 {
2210 KSP_PIN Property;
2211 ULONG BytesReturned;
2212
2213 // setup request
2214 Property.Property.Set = KSPROPSETID_Pin;
2215 Property.Property.Id = KSPROPERTY_PIN_COMMUNICATION;
2216 Property.Property.Flags = KSPROPERTY_TYPE_GET;
2217 Property.PinId = PinId;
2218 Property.Reserved = 0;
2219
2220 return KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSP_PIN), (PVOID)Communication, sizeof(KSPIN_COMMUNICATION), &BytesReturned);
2221 }
2222
2223 HRESULT
2224 STDMETHODCALLTYPE
2225 CKsProxy::GetPinDataflow(
2226 ULONG PinId,
2227 KSPIN_DATAFLOW * DataFlow)
2228 {
2229 KSP_PIN Property;
2230 ULONG BytesReturned;
2231
2232 // setup request
2233 Property.Property.Set = KSPROPSETID_Pin;
2234 Property.Property.Id = KSPROPERTY_PIN_DATAFLOW;
2235 Property.Property.Flags = KSPROPERTY_TYPE_GET;
2236 Property.PinId = PinId;
2237 Property.Reserved = 0;
2238
2239 return KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSP_PIN), (PVOID)DataFlow, sizeof(KSPIN_DATAFLOW), &BytesReturned);
2240 }
2241
2242 HRESULT
2243 STDMETHODCALLTYPE
2244 CKsProxy::GetPinName(
2245 ULONG PinId,
2246 KSPIN_DATAFLOW DataFlow,
2247 ULONG PinCount,
2248 LPWSTR * OutPinName)
2249 {
2250 KSP_PIN Property;
2251 LPWSTR PinName;
2252 ULONG BytesReturned;
2253 HRESULT hr;
2254 WCHAR Buffer[100];
2255
2256 // setup request
2257 Property.Property.Set = KSPROPSETID_Pin;
2258 Property.Property.Id = KSPROPERTY_PIN_NAME;
2259 Property.Property.Flags = KSPROPERTY_TYPE_GET;
2260 Property.PinId = PinId;
2261 Property.Reserved = 0;
2262
2263 // #1 try get it from pin directly
2264 hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSP_PIN), NULL, 0, &BytesReturned);
2265
2266 if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_MORE_DATA))
2267 {
2268 // allocate pin name
2269 PinName = (LPWSTR)CoTaskMemAlloc(BytesReturned);
2270 if (!PinName)
2271 return E_OUTOFMEMORY;
2272
2273 // retry with allocated buffer
2274 hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSP_PIN), PinName, BytesReturned, &BytesReturned);
2275 if (SUCCEEDED(hr))
2276 {
2277 *OutPinName = PinName;
2278 return hr;
2279 }
2280
2281 //free buffer
2282 CoTaskMemFree(PinName);
2283 }
2284
2285 //
2286 // TODO: retrieve pin name from topology node
2287 //
2288
2289 if (DataFlow == KSPIN_DATAFLOW_IN)
2290 {
2291 swprintf(Buffer, L"Input%lu", PinCount);
2292 }
2293 else
2294 {
2295 swprintf(Buffer, L"Output%lu", PinCount);
2296 }
2297
2298 // allocate pin name
2299 PinName = (LPWSTR)CoTaskMemAlloc((wcslen(Buffer)+1) * sizeof(WCHAR));
2300 if (!PinName)
2301 return E_OUTOFMEMORY;
2302
2303 // copy pin name
2304 wcscpy(PinName, Buffer);
2305
2306 // store result
2307 *OutPinName = PinName;
2308 // done
2309 return S_OK;
2310 }
2311
2312 HRESULT
2313 STDMETHODCALLTYPE
2314 CKsProxy::CreatePins()
2315 {
2316 ULONG NumPins, Index;
2317 KSPIN_CINSTANCES Instances;
2318 KSPIN_DATAFLOW DataFlow;
2319 KSPIN_COMMUNICATION Communication;
2320 HRESULT hr;
2321 WCHAR Buffer[100];
2322 LPWSTR PinName;
2323 IPin * pPin;
2324 ULONG InputPin = 0;
2325 ULONG OutputPin = 0;
2326
2327 // get number of pins
2328 hr = GetNumberOfPins(&NumPins);
2329 if (FAILED(hr))
2330 return hr;
2331
2332 for(Index = 0; Index < NumPins; Index++)
2333 {
2334 // query current instance count
2335 hr = GetPinInstanceCount(Index, &Instances);
2336 if (FAILED(hr))
2337 continue;
2338
2339 // query pin communication;
2340 hr = GetPinCommunication(Index, &Communication);
2341 if (FAILED(hr))
2342 continue;
2343
2344 if (Instances.CurrentCount == Instances.PossibleCount)
2345 {
2346 // already maximum reached for this pin
2347 continue;
2348 }
2349
2350 // get direction of pin
2351 hr = GetPinDataflow(Index, &DataFlow);
2352 if (FAILED(hr))
2353 continue;
2354
2355 if (DataFlow == KSPIN_DATAFLOW_IN)
2356 hr = GetPinName(Index, DataFlow, InputPin, &PinName);
2357 else
2358 hr = GetPinName(Index, DataFlow, OutputPin, &PinName);
2359
2360 if (FAILED(hr))
2361 continue;
2362
2363 // construct the pins
2364 if (DataFlow == KSPIN_DATAFLOW_IN)
2365 {
2366 hr = CInputPin_Constructor((IBaseFilter*)this, PinName, m_hDevice, Index, Communication, IID_IPin, (void**)&pPin);
2367 if (FAILED(hr))
2368 {
2369 CoTaskMemFree(PinName);
2370 continue;
2371 }
2372 InputPin++;
2373 }
2374 else
2375 {
2376 hr = COutputPin_Constructor((IBaseFilter*)this, PinName, Index, IID_IPin, (void**)&pPin);
2377 if (FAILED(hr))
2378 {
2379 CoTaskMemFree(PinName);
2380 continue;
2381 }
2382 OutputPin++;
2383 }
2384
2385 // store pins
2386 m_Pins.push_back(pPin);
2387
2388 swprintf(Buffer, L"Index %lu DataFlow %lu Name %s\n", Index, DataFlow, PinName);
2389 OutputDebugStringW(Buffer);
2390 }
2391
2392 return S_OK;
2393 }
2394
2395 HRESULT
2396 STDMETHODCALLTYPE
2397 CKsProxy::Load(IPropertyBag *pPropBag, IErrorLog *pErrorLog)
2398 {
2399 HRESULT hr;
2400 WCHAR Buffer[100];
2401 VARIANT varName;
2402 LPGUID pGuid;
2403 ULONG NumGuids = 0;
2404 HDEVINFO hList;
2405 SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;
2406
2407 OutputDebugStringW(L"CKsProxy::Load\n");
2408
2409 // read device path
2410 varName.vt = VT_BSTR;
2411 hr = pPropBag->Read(L"DevicePath", &varName, pErrorLog);
2412
2413 if (FAILED(hr))
2414 {
2415 swprintf(Buffer, L"CKsProxy::Load Read %lx\n", hr);
2416 OutputDebugStringW(Buffer);
2417 return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, GetLastError());
2418 }
2419
2420 OutputDebugStringW(L"DevicePath: ");
2421 OutputDebugStringW(varName.bstrVal);
2422 OutputDebugStringW(L"\n");
2423
2424 // create device list
2425 hList = SetupDiCreateDeviceInfoListExW(NULL, NULL, NULL, NULL);
2426 if (hList == INVALID_HANDLE_VALUE)
2427 {
2428 // failed to create device list
2429 return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, GetLastError());
2430 }
2431
2432 DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
2433 if (!SetupDiOpenDeviceInterfaceW(hList, (PCWSTR)varName.bstrVal, 0, &DeviceInterfaceData))
2434 {
2435 // failed to open device interface
2436 SetupDiDestroyDeviceInfoList(hList);
2437 }
2438
2439 // FIXME handle device interface links(aliases)
2440 CopyMemory(&m_DeviceInterfaceGUID, &DeviceInterfaceData.InterfaceClassGuid, sizeof(GUID));
2441
2442 // close device info list
2443 SetupDiDestroyDeviceInfoList(hList);
2444
2445 // open device
2446 m_hDevice = CreateFileW(varName.bstrVal, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
2447
2448 if (m_hDevice == INVALID_HANDLE_VALUE)
2449 {
2450 // failed to open device
2451 swprintf(Buffer, L"CKsProxy:: failed to open device with %lx\n", GetLastError());
2452 OutputDebugStringW(Buffer);
2453
2454 return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, GetLastError());
2455 }
2456
2457 // store device path
2458 m_DevicePath = varName.bstrVal;
2459
2460 // get all supported sets
2461 hr = GetSupportedSets(&pGuid, &NumGuids);
2462 if (FAILED(hr))
2463 {
2464 CloseHandle(m_hDevice);
2465 m_hDevice = NULL;
2466 return hr;
2467 }
2468
2469 // load all proxy plugins
2470 hr = LoadProxyPlugins(pGuid, NumGuids);
2471 if (FAILED(hr))
2472 {
2473 CloseHandle(m_hDevice);
2474 m_hDevice = NULL;
2475 return hr;
2476 }
2477
2478 // free sets
2479 CoTaskMemFree(pGuid);
2480
2481 // now create the input / output pins
2482 hr = CreatePins();
2483
2484 return hr;
2485 }
2486
2487 HRESULT
2488 STDMETHODCALLTYPE
2489 CKsProxy::Save(IPropertyBag *pPropBag, BOOL fClearDirty, BOOL fSaveAllProperties)
2490 {
2491 OutputDebugStringW(L"CKsProxy::Save\n");
2492 return E_NOTIMPL;
2493 }
2494
2495 //-------------------------------------------------------------------
2496 // IBaseFilter interface
2497 //
2498
2499 HRESULT
2500 STDMETHODCALLTYPE
2501 CKsProxy::GetClassID(
2502 CLSID *pClassID)
2503 {
2504 OutputDebugStringW(L"CKsProxy::GetClassID\n");
2505 CopyMemory(pClassID, &CLSID_Proxy, sizeof(GUID));
2506
2507 return S_OK;
2508 }
2509
2510 HRESULT
2511 STDMETHODCALLTYPE
2512 CKsProxy::Stop()
2513 {
2514 OutputDebugStringW(L"CKsProxy::Stop : NotImplemented\n");
2515 return E_NOTIMPL;
2516 }
2517
2518 HRESULT
2519 STDMETHODCALLTYPE
2520 CKsProxy::Pause()
2521 {
2522 OutputDebugStringW(L"CKsProxy::Pause : NotImplemented\n");
2523 return E_NOTIMPL;
2524 }
2525
2526 HRESULT
2527 STDMETHODCALLTYPE
2528 CKsProxy::Run(
2529 REFERENCE_TIME tStart)
2530 {
2531 OutputDebugStringW(L"CKsProxy::Run : NotImplemented\n");
2532 return E_NOTIMPL;
2533 }
2534
2535 HRESULT
2536 STDMETHODCALLTYPE
2537 CKsProxy::GetState(
2538 DWORD dwMilliSecsTimeout,
2539 FILTER_STATE *State)
2540 {
2541 *State = m_FilterState;
2542 return S_OK;
2543 }
2544
2545 HRESULT
2546 STDMETHODCALLTYPE
2547 CKsProxy::SetSyncSource(
2548 IReferenceClock *pClock)
2549 {
2550 HRESULT hr;
2551 IKsClock *pKsClock;
2552 HANDLE hClock, hPin;
2553 ULONG Index;
2554 IPin * pin;
2555 IKsObject * pObject;
2556 KSPROPERTY Property;
2557 ULONG BytesReturned;
2558 PIN_DIRECTION PinDir;
2559
2560 // Plug In Distributor: IKsClock
2561 OutputDebugStringW(L"CKsProxy::SetSyncSource\n");
2562
2563 // FIXME
2564 // need locks
2565
2566 if (!pClock)
2567 return E_POINTER;
2568
2569 hr = pClock->QueryInterface(IID_IKsClock, (void**)&pKsClock);
2570 if (FAILED(hr))
2571 return hr;
2572
2573 // get clock handle
2574 hClock = pKsClock->KsGetClockHandle();
2575 if (!hClock || hClock == INVALID_HANDLE_VALUE)
2576 {
2577 // failed
2578 pKsClock->Release();
2579 return E_FAIL;
2580 }
2581
2582 // distribute clock to all pins
2583 for(Index = 0; Index < m_Pins.size(); Index++)
2584 {
2585 // get current pin
2586 pin = m_Pins[Index];
2587 if (!pin)
2588 continue;
2589
2590 // get IKsObject interface
2591 hr = pin->QueryInterface(IID_IKsObject, (void **)&pObject);
2592 if (SUCCEEDED(hr))
2593 {
2594 // get pin handle
2595 hPin = pObject->KsGetObjectHandle();
2596 if (hPin != INVALID_HANDLE_VALUE && hPin)
2597 {
2598 // set clock
2599 Property.Set = KSPROPSETID_Stream;
2600 Property.Id = KSPROPERTY_STREAM_MASTERCLOCK;
2601 Property.Flags = KSPROPERTY_TYPE_SET;
2602
2603 // set master clock
2604 hr = KsSynchronousDeviceControl(hPin, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)hClock, sizeof(HANDLE), &BytesReturned);
2605
2606 if (FAILED(hr))
2607 {
2608 if (hr != MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND) &&
2609 hr != MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND))
2610 {
2611 // failed to set master clock
2612 pKsClock->Release();
2613 pObject->Release();
2614 return hr;
2615 }
2616 }
2617 }
2618 // release IKsObject
2619 pObject->Release();
2620 }
2621
2622 // now get the direction
2623 hr = pin->QueryDirection(&PinDir);
2624 if (SUCCEEDED(hr))
2625 {
2626 if (PinDir == PINDIR_OUTPUT)
2627 {
2628 // notify pin via
2629 //CBaseStreamControl::SetSyncSource(pClock)
2630 }
2631 }
2632 }
2633
2634 if (pClock)
2635 {
2636 pClock->AddRef();
2637 }
2638
2639 if (m_ReferenceClock)
2640 {
2641 m_ReferenceClock->Release();
2642 }
2643
2644 m_ReferenceClock = pClock;
2645 return S_OK;
2646 }
2647
2648 HRESULT
2649 STDMETHODCALLTYPE
2650 CKsProxy::GetSyncSource(
2651 IReferenceClock **pClock)
2652 {
2653 OutputDebugStringW(L"CKsProxy::GetSyncSource\n");
2654
2655 if (!pClock)
2656 return E_POINTER;
2657
2658 if (m_ReferenceClock)
2659 m_ReferenceClock->AddRef();
2660
2661 *pClock = m_ReferenceClock;
2662 return S_OK;
2663 }
2664
2665 HRESULT
2666 STDMETHODCALLTYPE
2667 CKsProxy::EnumPins(
2668 IEnumPins **ppEnum)
2669 {
2670 OutputDebugStringW(L"CKsProxy::EnumPins\n");
2671 return CEnumPins_fnConstructor(m_Pins, IID_IEnumPins, (void**)ppEnum);
2672 }
2673
2674 HRESULT
2675 STDMETHODCALLTYPE
2676 CKsProxy::FindPin(
2677 LPCWSTR Id, IPin **ppPin)
2678 {
2679 ULONG PinId;
2680
2681 OutputDebugStringW(L"CKsProxy::FindPin\n");
2682
2683 if (!ppPin)
2684 return E_POINTER;
2685
2686 // convert to pin
2687 int ret = swscanf(Id, L"%u", &PinId);
2688
2689 if (!ret || ret == EOF)
2690 {
2691 // invalid id
2692 return VFW_E_NOT_FOUND;
2693 }
2694
2695 if (PinId >= m_Pins.size() || m_Pins[PinId] == NULL)
2696 {
2697 // invalid id
2698 return VFW_E_NOT_FOUND;
2699 }
2700
2701 // found pin
2702 *ppPin = m_Pins[PinId];
2703 m_Pins[PinId]->AddRef();
2704
2705 return S_OK;
2706 }
2707
2708
2709 HRESULT
2710 STDMETHODCALLTYPE
2711 CKsProxy::QueryFilterInfo(
2712 FILTER_INFO *pInfo)
2713 {
2714 if (!pInfo)
2715 return E_POINTER;
2716
2717 OutputDebugStringW(L"CKsProxy::QueryFilterInfo\n");
2718
2719 pInfo->achName[0] = L'\0';
2720 pInfo->pGraph = m_pGraph;
2721
2722 if (m_pGraph)
2723 m_pGraph->AddRef();
2724
2725 return S_OK;
2726 }
2727
2728 HRESULT
2729 STDMETHODCALLTYPE
2730 CKsProxy::JoinFilterGraph(
2731 IFilterGraph *pGraph,
2732 LPCWSTR pName)
2733 {
2734 OutputDebugStringW(L"CKsProxy::JoinFilterGraph\n");
2735
2736 if (pGraph)
2737 {
2738 // joining filter graph
2739 m_pGraph = pGraph;
2740 }
2741 else
2742 {
2743 // leaving graph
2744 m_pGraph = 0;
2745 }
2746
2747 return S_OK;
2748 }
2749
2750
2751 HRESULT
2752 STDMETHODCALLTYPE
2753 CKsProxy::QueryVendorInfo(
2754 LPWSTR *pVendorInfo)
2755 {
2756 OutputDebugStringW(L"CKsProxy::QueryVendorInfo\n");
2757 return StringFromCLSID(CLSID_Proxy, pVendorInfo);
2758 }
2759
2760 //-------------------------------------------------------------------
2761 // IAMovieSetup interface
2762 //
2763
2764 HRESULT
2765 STDMETHODCALLTYPE
2766 CKsProxy::Register()
2767 {
2768 OutputDebugStringW(L"CKsProxy::Register : NotImplemented\n");
2769 return E_NOTIMPL;
2770 }
2771
2772 HRESULT
2773 STDMETHODCALLTYPE
2774 CKsProxy::Unregister()
2775 {
2776 OutputDebugStringW(L"CKsProxy::Unregister : NotImplemented\n");
2777 return E_NOTIMPL;
2778 }
2779
2780 HRESULT
2781 WINAPI
2782 CKsProxy_Constructor(
2783 IUnknown * pUnkOuter,
2784 REFIID riid,
2785 LPVOID * ppv)
2786 {
2787 WCHAR Buffer[100];
2788 LPOLESTR pstr;
2789 StringFromCLSID(riid, &pstr);
2790 swprintf(Buffer, L"CKsProxy_Constructor pUnkOuter %p riid %s\n", pUnkOuter, pstr);
2791 OutputDebugStringW(Buffer);
2792
2793 CKsProxy * handler = new CKsProxy();
2794
2795 if (!handler)
2796 return E_OUTOFMEMORY;
2797
2798 if (FAILED(handler->QueryInterface(riid, ppv)))
2799 {
2800 /* not supported */
2801 delete handler;
2802 return E_NOINTERFACE;
2803 }
2804
2805 return S_OK;
2806 }