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