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