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