xref: /reactos/sdk/lib/3rdparty/strmbase/pospass.c (revision 10517de5)
1 /*
2  * Filter Seeking and Control Interfaces
3  *
4  * Copyright 2003 Robert Shearman
5  * Copyright 2012 Aric Stewart, CodeWeavers
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21 /* FIXME: critical sections */
22 
23 #define COBJMACROS
24 
25 #include "dshow.h"
26 #include "uuids.h"
27 
28 #include "wine/debug.h"
29 #include "wine/strmbase.h"
30 
31 #include <assert.h>
32 
33 WINE_DEFAULT_DEBUG_CHANNEL(strmbase);
34 
35 static const IMediaSeekingVtbl IMediaSeekingPassThru_Vtbl;
36 static const IMediaPositionVtbl IMediaPositionPassThru_Vtbl;
37 
38 typedef struct PassThruImpl {
39     IUnknown  IUnknown_inner;
40     ISeekingPassThru ISeekingPassThru_iface;
41     IMediaSeeking IMediaSeeking_iface;
42     IMediaPosition IMediaPosition_iface;
43     BaseDispatch baseDispatch;
44 
45     LONG ref;
46     IUnknown * outer_unk;
47     IPin * pin;
48     BOOL bUnkOuterValid;
49     BOOL bAggregatable;
50     BOOL renderer;
51     CRITICAL_SECTION time_cs;
52     BOOL timevalid;
53     REFERENCE_TIME time_earliest;
54 } PassThruImpl;
55 
impl_from_IUnknown_inner(IUnknown * iface)56 static inline PassThruImpl *impl_from_IUnknown_inner(IUnknown *iface)
57 {
58     return CONTAINING_RECORD(iface, PassThruImpl, IUnknown_inner);
59 }
60 
impl_from_ISeekingPassThru(ISeekingPassThru * iface)61 static inline PassThruImpl *impl_from_ISeekingPassThru(ISeekingPassThru *iface)
62 {
63     return CONTAINING_RECORD(iface, PassThruImpl, ISeekingPassThru_iface);
64 }
65 
impl_from_IMediaSeeking(IMediaSeeking * iface)66 static inline PassThruImpl *impl_from_IMediaSeeking(IMediaSeeking *iface)
67 {
68     return CONTAINING_RECORD(iface, PassThruImpl, IMediaSeeking_iface);
69 }
70 
impl_from_IMediaPosition(IMediaPosition * iface)71 static inline PassThruImpl *impl_from_IMediaPosition(IMediaPosition *iface)
72 {
73     return CONTAINING_RECORD(iface, PassThruImpl, IMediaPosition_iface);
74 }
75 
SeekInner_QueryInterface(IUnknown * iface,REFIID riid,LPVOID * ppvObj)76 static HRESULT WINAPI SeekInner_QueryInterface(IUnknown * iface,
77 					  REFIID riid,
78 					  LPVOID *ppvObj) {
79     PassThruImpl *This = impl_from_IUnknown_inner(iface);
80     TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObj);
81 
82     if (This->bAggregatable)
83         This->bUnkOuterValid = TRUE;
84 
85     if (IsEqualGUID(&IID_IUnknown, riid))
86     {
87         *ppvObj = &(This->IUnknown_inner);
88         TRACE("   returning IUnknown interface (%p)\n", *ppvObj);
89     } else if (IsEqualGUID(&IID_ISeekingPassThru, riid)) {
90         *ppvObj = &(This->ISeekingPassThru_iface);
91         TRACE("   returning ISeekingPassThru interface (%p)\n", *ppvObj);
92     } else if (IsEqualGUID(&IID_IMediaSeeking, riid)) {
93         *ppvObj = &(This->IMediaSeeking_iface);
94         TRACE("   returning IMediaSeeking interface (%p)\n", *ppvObj);
95     } else if (IsEqualGUID(&IID_IMediaPosition, riid)) {
96         *ppvObj = &(This->IMediaPosition_iface);
97         TRACE("   returning IMediaPosition interface (%p)\n", *ppvObj);
98     } else {
99         *ppvObj = NULL;
100         FIXME("unknown interface %s\n", debugstr_guid(riid));
101         return E_NOINTERFACE;
102     }
103 
104     IUnknown_AddRef((IUnknown *)(*ppvObj));
105     return S_OK;
106 }
107 
SeekInner_AddRef(IUnknown * iface)108 static ULONG WINAPI SeekInner_AddRef(IUnknown * iface) {
109     PassThruImpl *This = impl_from_IUnknown_inner(iface);
110     ULONG ref = InterlockedIncrement(&This->ref);
111 
112     TRACE("(%p)->(): new ref = %d\n", This, ref);
113 
114     return ref;
115 }
116 
SeekInner_Release(IUnknown * iface)117 static ULONG WINAPI SeekInner_Release(IUnknown * iface) {
118     PassThruImpl *This = impl_from_IUnknown_inner(iface);
119     ULONG ref = InterlockedDecrement(&This->ref);
120 
121     TRACE("(%p)->(): new ref = %d\n", This, ref);
122 
123     if (ref == 0)
124     {
125         BaseDispatch_Destroy(&This->baseDispatch);
126         This->time_cs.DebugInfo->Spare[0] = 0;
127         DeleteCriticalSection(&This->time_cs);
128         CoTaskMemFree(This);
129     }
130     return ref;
131 }
132 
133 static const IUnknownVtbl IInner_VTable =
134 {
135     SeekInner_QueryInterface,
136     SeekInner_AddRef,
137     SeekInner_Release
138 };
139 
140 /* Generic functions for aggregation */
SeekOuter_QueryInterface(PassThruImpl * This,REFIID riid,LPVOID * ppv)141 static HRESULT SeekOuter_QueryInterface(PassThruImpl *This, REFIID riid, LPVOID *ppv)
142 {
143     if (This->bAggregatable)
144         This->bUnkOuterValid = TRUE;
145 
146     if (This->outer_unk)
147     {
148         if (This->bAggregatable)
149             return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
150 
151         if (IsEqualIID(riid, &IID_IUnknown))
152         {
153             HRESULT hr;
154 
155             IUnknown_AddRef(&This->IUnknown_inner);
156             hr = IUnknown_QueryInterface(&This->IUnknown_inner, riid, ppv);
157             IUnknown_Release(&This->IUnknown_inner);
158             This->bAggregatable = TRUE;
159             return hr;
160         }
161 
162         *ppv = NULL;
163         return E_NOINTERFACE;
164     }
165 
166     return IUnknown_QueryInterface(&This->IUnknown_inner, riid, ppv);
167 }
168 
SeekOuter_AddRef(PassThruImpl * This)169 static ULONG SeekOuter_AddRef(PassThruImpl *This)
170 {
171     if (This->outer_unk && This->bUnkOuterValid)
172         return IUnknown_AddRef(This->outer_unk);
173     return IUnknown_AddRef(&This->IUnknown_inner);
174 }
175 
SeekOuter_Release(PassThruImpl * This)176 static ULONG SeekOuter_Release(PassThruImpl *This)
177 {
178     if (This->outer_unk && This->bUnkOuterValid)
179         return IUnknown_Release(This->outer_unk);
180     return IUnknown_Release(&This->IUnknown_inner);
181 }
182 
SeekingPassThru_QueryInterface(ISeekingPassThru * iface,REFIID riid,LPVOID * ppvObj)183 static HRESULT WINAPI SeekingPassThru_QueryInterface(ISeekingPassThru *iface, REFIID riid, LPVOID *ppvObj)
184 {
185     PassThruImpl *This = impl_from_ISeekingPassThru(iface);
186 
187     TRACE("(%p/%p)->(%s, %p)\n", This, iface, debugstr_guid(riid), ppvObj);
188 
189     return SeekOuter_QueryInterface(This, riid, ppvObj);
190 }
191 
SeekingPassThru_AddRef(ISeekingPassThru * iface)192 static ULONG WINAPI SeekingPassThru_AddRef(ISeekingPassThru *iface)
193 {
194     PassThruImpl *This = impl_from_ISeekingPassThru(iface);
195 
196     TRACE("(%p/%p)->()\n", This, iface);
197 
198     return SeekOuter_AddRef(This);
199 }
200 
SeekingPassThru_Release(ISeekingPassThru * iface)201 static ULONG WINAPI SeekingPassThru_Release(ISeekingPassThru *iface)
202 {
203     PassThruImpl *This = impl_from_ISeekingPassThru(iface);
204 
205     TRACE("(%p/%p)->()\n", This, iface);
206 
207     return SeekOuter_Release(This);
208 }
209 
SeekingPassThru_Init(ISeekingPassThru * iface,BOOL renderer,IPin * pin)210 static HRESULT WINAPI SeekingPassThru_Init(ISeekingPassThru *iface, BOOL renderer, IPin *pin)
211 {
212     PassThruImpl *This = impl_from_ISeekingPassThru(iface);
213 
214     TRACE("(%p/%p)->(%d, %p)\n", This, iface, renderer, pin);
215 
216     if (This->pin)
217         FIXME("Re-initializing?\n");
218 
219     This->renderer = renderer;
220     This->pin = pin;
221 
222     return S_OK;
223 }
224 
225 static const ISeekingPassThruVtbl ISeekingPassThru_Vtbl =
226 {
227     SeekingPassThru_QueryInterface,
228     SeekingPassThru_AddRef,
229     SeekingPassThru_Release,
230     SeekingPassThru_Init
231 };
232 
CreatePosPassThru(IUnknown * pUnkOuter,BOOL bRenderer,IPin * pPin,IUnknown ** ppPassThru)233 HRESULT WINAPI CreatePosPassThru(IUnknown* pUnkOuter, BOOL bRenderer, IPin *pPin, IUnknown **ppPassThru)
234 {
235     HRESULT hr;
236     ISeekingPassThru *passthru;
237 
238     hr = CoCreateInstance(&CLSID_SeekingPassThru, pUnkOuter, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void**)ppPassThru);
239     if (FAILED(hr))
240         return hr;
241 
242     IUnknown_QueryInterface(*ppPassThru, &IID_ISeekingPassThru, (void**)&passthru);
243     hr = ISeekingPassThru_Init(passthru, bRenderer, pPin);
244     ISeekingPassThru_Release(passthru);
245 
246     return hr;
247 }
248 
PosPassThru_Construct(IUnknown * pUnkOuter,LPVOID * ppPassThru)249 HRESULT WINAPI PosPassThru_Construct(IUnknown *pUnkOuter, LPVOID *ppPassThru)
250 {
251     PassThruImpl *fimpl;
252 
253     TRACE("(%p,%p)\n", pUnkOuter, ppPassThru);
254 
255     *ppPassThru = fimpl = CoTaskMemAlloc(sizeof(*fimpl));
256     if (!fimpl)
257         return E_OUTOFMEMORY;
258 
259     fimpl->outer_unk = pUnkOuter;
260     fimpl->bUnkOuterValid = FALSE;
261     fimpl->bAggregatable = FALSE;
262     fimpl->IUnknown_inner.lpVtbl = &IInner_VTable;
263     fimpl->ISeekingPassThru_iface.lpVtbl = &ISeekingPassThru_Vtbl;
264     fimpl->IMediaSeeking_iface.lpVtbl = &IMediaSeekingPassThru_Vtbl;
265     fimpl->IMediaPosition_iface.lpVtbl = &IMediaPositionPassThru_Vtbl;
266     fimpl->ref = 1;
267     fimpl->pin = NULL;
268     fimpl->timevalid = FALSE;
269     InitializeCriticalSection(&fimpl->time_cs);
270     fimpl->time_cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": PassThruImpl.time_cs");
271     BaseDispatch_Init(&fimpl->baseDispatch, &IID_IMediaPosition);
272     return S_OK;
273 }
274 
MediaSeekingPassThru_QueryInterface(IMediaSeeking * iface,REFIID riid,LPVOID * ppvObj)275 static HRESULT WINAPI MediaSeekingPassThru_QueryInterface(IMediaSeeking *iface, REFIID riid, LPVOID *ppvObj)
276 {
277     PassThruImpl *This = impl_from_IMediaSeeking(iface);
278 
279     TRACE("(%p/%p)->(%s, %p)\n", This, iface, debugstr_guid(riid), ppvObj);
280 
281     return SeekOuter_QueryInterface(This, riid, ppvObj);
282 }
283 
MediaSeekingPassThru_AddRef(IMediaSeeking * iface)284 static ULONG WINAPI MediaSeekingPassThru_AddRef(IMediaSeeking *iface)
285 {
286     PassThruImpl *This = impl_from_IMediaSeeking(iface);
287 
288     TRACE("(%p/%p)->()\n", iface, This);
289 
290     return SeekOuter_AddRef(This);
291 }
292 
MediaSeekingPassThru_Release(IMediaSeeking * iface)293 static ULONG WINAPI MediaSeekingPassThru_Release(IMediaSeeking *iface)
294 {
295     PassThruImpl *This = impl_from_IMediaSeeking(iface);
296 
297     TRACE("(%p/%p)->()\n", iface, This);
298 
299     return SeekOuter_Release(This);
300 }
301 
get_connected(PassThruImpl * This,REFIID riid,LPVOID * ppvObj)302 static HRESULT get_connected(PassThruImpl *This, REFIID riid, LPVOID *ppvObj) {
303     HRESULT hr;
304     IPin *pin;
305     *ppvObj = NULL;
306     hr = IPin_ConnectedTo(This->pin, &pin);
307     if (FAILED(hr))
308         return VFW_E_NOT_CONNECTED;
309     hr = IPin_QueryInterface(pin, riid, ppvObj);
310     IPin_Release(pin);
311     if (FAILED(hr))
312         hr = E_NOTIMPL;
313     return hr;
314 }
315 
MediaSeekingPassThru_GetCapabilities(IMediaSeeking * iface,DWORD * pCapabilities)316 static HRESULT WINAPI MediaSeekingPassThru_GetCapabilities(IMediaSeeking * iface, DWORD * pCapabilities)
317 {
318     PassThruImpl *This = impl_from_IMediaSeeking(iface);
319     IMediaSeeking *seek;
320     HRESULT hr;
321     TRACE("(%p/%p)->(%p)\n", iface, This, pCapabilities);
322     hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
323     if (SUCCEEDED(hr)) {
324         hr = IMediaSeeking_GetCapabilities(seek, pCapabilities);
325         IMediaSeeking_Release(seek);
326     }
327     else
328         return E_NOTIMPL;
329     return hr;
330 }
331 
MediaSeekingPassThru_CheckCapabilities(IMediaSeeking * iface,DWORD * pCapabilities)332 static HRESULT WINAPI MediaSeekingPassThru_CheckCapabilities(IMediaSeeking * iface, DWORD * pCapabilities)
333 {
334     PassThruImpl *This = impl_from_IMediaSeeking(iface);
335     IMediaSeeking *seek;
336     HRESULT hr;
337     TRACE("(%p/%p)->(%p)\n", iface, This, pCapabilities);
338     hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
339     if (SUCCEEDED(hr)) {
340         hr = IMediaSeeking_CheckCapabilities(seek, pCapabilities);
341         IMediaSeeking_Release(seek);
342     }
343     else
344         return E_NOTIMPL;
345     return hr;
346 }
347 
MediaSeekingPassThru_IsFormatSupported(IMediaSeeking * iface,const GUID * pFormat)348 static HRESULT WINAPI MediaSeekingPassThru_IsFormatSupported(IMediaSeeking * iface, const GUID * pFormat)
349 {
350     PassThruImpl *This = impl_from_IMediaSeeking(iface);
351     IMediaSeeking *seek;
352     HRESULT hr;
353     TRACE("(%p/%p)->(%s)\n", iface, This, debugstr_guid(pFormat));
354     hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
355     if (SUCCEEDED(hr)) {
356         hr = IMediaSeeking_IsFormatSupported(seek, pFormat);
357         IMediaSeeking_Release(seek);
358     }
359     else
360         return E_NOTIMPL;
361     return hr;
362 }
363 
MediaSeekingPassThru_QueryPreferredFormat(IMediaSeeking * iface,GUID * pFormat)364 static HRESULT WINAPI MediaSeekingPassThru_QueryPreferredFormat(IMediaSeeking * iface, GUID * pFormat)
365 {
366     PassThruImpl *This = impl_from_IMediaSeeking(iface);
367     IMediaSeeking *seek;
368     HRESULT hr;
369     TRACE("(%p/%p)->(%p)\n", iface, This, pFormat);
370     hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
371     if (SUCCEEDED(hr)) {
372         hr = IMediaSeeking_QueryPreferredFormat(seek, pFormat);
373         IMediaSeeking_Release(seek);
374     }
375     else
376         return E_NOTIMPL;
377     return hr;
378 }
379 
MediaSeekingPassThru_GetTimeFormat(IMediaSeeking * iface,GUID * pFormat)380 static HRESULT WINAPI MediaSeekingPassThru_GetTimeFormat(IMediaSeeking * iface, GUID * pFormat)
381 {
382     PassThruImpl *This = impl_from_IMediaSeeking(iface);
383     IMediaSeeking *seek;
384     HRESULT hr;
385     TRACE("(%p/%p)->(%p)\n", iface, This, pFormat);
386     hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
387     if (SUCCEEDED(hr)) {
388         hr = IMediaSeeking_GetTimeFormat(seek, pFormat);
389         IMediaSeeking_Release(seek);
390     }
391     else
392         return E_NOTIMPL;
393     return hr;
394 }
395 
MediaSeekingPassThru_IsUsingTimeFormat(IMediaSeeking * iface,const GUID * pFormat)396 static HRESULT WINAPI MediaSeekingPassThru_IsUsingTimeFormat(IMediaSeeking * iface, const GUID * pFormat)
397 {
398     PassThruImpl *This = impl_from_IMediaSeeking(iface);
399     IMediaSeeking *seek;
400     HRESULT hr;
401     TRACE("(%p/%p)->(%s)\n", iface, This, debugstr_guid(pFormat));
402     hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
403     if (SUCCEEDED(hr)) {
404         hr = IMediaSeeking_IsUsingTimeFormat(seek, pFormat);
405         IMediaSeeking_Release(seek);
406     }
407     else
408         return E_NOTIMPL;
409     return hr;
410 }
411 
MediaSeekingPassThru_SetTimeFormat(IMediaSeeking * iface,const GUID * pFormat)412 static HRESULT WINAPI MediaSeekingPassThru_SetTimeFormat(IMediaSeeking * iface, const GUID * pFormat)
413 {
414     PassThruImpl *This = impl_from_IMediaSeeking(iface);
415     IMediaSeeking *seek;
416     HRESULT hr;
417     TRACE("(%p/%p)->(%s)\n", iface, This, debugstr_guid(pFormat));
418     hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
419     if (SUCCEEDED(hr)) {
420         hr = IMediaSeeking_SetTimeFormat(seek, pFormat);
421         IMediaSeeking_Release(seek);
422     }
423     else
424         return E_NOTIMPL;
425     return hr;
426 }
427 
MediaSeekingPassThru_GetDuration(IMediaSeeking * iface,LONGLONG * pDuration)428 static HRESULT WINAPI MediaSeekingPassThru_GetDuration(IMediaSeeking * iface, LONGLONG * pDuration)
429 {
430     PassThruImpl *This = impl_from_IMediaSeeking(iface);
431     IMediaSeeking *seek;
432     HRESULT hr;
433     TRACE("(%p/%p)->(%p)\n", iface, This, pDuration);
434     hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
435     if (SUCCEEDED(hr)) {
436         hr = IMediaSeeking_GetDuration(seek, pDuration);
437         IMediaSeeking_Release(seek);
438     }
439     else
440         return E_NOTIMPL;
441     return hr;
442 }
443 
MediaSeekingPassThru_GetStopPosition(IMediaSeeking * iface,LONGLONG * pStop)444 static HRESULT WINAPI MediaSeekingPassThru_GetStopPosition(IMediaSeeking * iface, LONGLONG * pStop)
445 {
446     PassThruImpl *This = impl_from_IMediaSeeking(iface);
447     IMediaSeeking *seek;
448     HRESULT hr;
449     TRACE("(%p/%p)->(%p)\n", iface, This, pStop);
450     hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
451     if (SUCCEEDED(hr)) {
452         hr = IMediaSeeking_GetStopPosition(seek, pStop);
453         IMediaSeeking_Release(seek);
454     }
455     else
456         return E_NOTIMPL;
457     return hr;
458 }
459 
MediaSeekingPassThru_GetCurrentPosition(IMediaSeeking * iface,LONGLONG * pCurrent)460 static HRESULT WINAPI MediaSeekingPassThru_GetCurrentPosition(IMediaSeeking * iface, LONGLONG * pCurrent)
461 {
462     PassThruImpl *This = impl_from_IMediaSeeking(iface);
463     IMediaSeeking *seek;
464     HRESULT hr = S_OK;
465     TRACE("(%p/%p)->(%p)\n", iface, This, pCurrent);
466     if (!pCurrent)
467         return E_POINTER;
468     EnterCriticalSection(&This->time_cs);
469     if (This->timevalid)
470         *pCurrent = This->time_earliest;
471     else
472         hr = E_FAIL;
473     LeaveCriticalSection(&This->time_cs);
474     if (SUCCEEDED(hr)) {
475         hr = IMediaSeeking_ConvertTimeFormat(iface, pCurrent, NULL, *pCurrent, &TIME_FORMAT_MEDIA_TIME);
476         return hr;
477     }
478     hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
479     if (SUCCEEDED(hr)) {
480         hr = IMediaSeeking_GetCurrentPosition(seek, pCurrent);
481         IMediaSeeking_Release(seek);
482     }
483     else
484         return E_NOTIMPL;
485     return hr;
486 }
487 
MediaSeekingPassThru_ConvertTimeFormat(IMediaSeeking * iface,LONGLONG * pTarget,const GUID * pTargetFormat,LONGLONG Source,const GUID * pSourceFormat)488 static HRESULT WINAPI MediaSeekingPassThru_ConvertTimeFormat(IMediaSeeking * iface, LONGLONG * pTarget, const GUID * pTargetFormat, LONGLONG Source, const GUID * pSourceFormat)
489 {
490     PassThruImpl *This = impl_from_IMediaSeeking(iface);
491     IMediaSeeking *seek;
492     HRESULT hr;
493     TRACE("(%p/%p)->(%p,%s,%x%08x,%s)\n", iface, This, pTarget, debugstr_guid(pTargetFormat), (DWORD)(Source>>32), (DWORD)Source, debugstr_guid(pSourceFormat));
494     hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
495     if (SUCCEEDED(hr)) {
496         hr = IMediaSeeking_ConvertTimeFormat(seek, pTarget, pTargetFormat, Source, pSourceFormat);
497         IMediaSeeking_Release(seek);
498     }
499     else
500         return E_NOTIMPL;
501     return hr;
502 }
503 
MediaSeekingPassThru_SetPositions(IMediaSeeking * iface,LONGLONG * pCurrent,DWORD dwCurrentFlags,LONGLONG * pStop,DWORD dwStopFlags)504 static HRESULT WINAPI MediaSeekingPassThru_SetPositions(IMediaSeeking * iface, LONGLONG * pCurrent, DWORD dwCurrentFlags, LONGLONG * pStop, DWORD dwStopFlags)
505 {
506     PassThruImpl *This = impl_from_IMediaSeeking(iface);
507     IMediaSeeking *seek;
508     HRESULT hr;
509     TRACE("(%p/%p)->(%p,%x,%p,%x)\n", iface, This, pCurrent, dwCurrentFlags, pStop, dwStopFlags);
510     hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
511     if (SUCCEEDED(hr)) {
512         hr = IMediaSeeking_SetPositions(seek, pCurrent, dwCurrentFlags, pStop, dwStopFlags);
513         IMediaSeeking_Release(seek);
514     } else if (hr == VFW_E_NOT_CONNECTED)
515         hr = S_OK;
516     return hr;
517 }
518 
MediaSeekingPassThru_GetPositions(IMediaSeeking * iface,LONGLONG * pCurrent,LONGLONG * pStop)519 static HRESULT WINAPI MediaSeekingPassThru_GetPositions(IMediaSeeking * iface, LONGLONG * pCurrent, LONGLONG * pStop)
520 {
521     PassThruImpl *This = impl_from_IMediaSeeking(iface);
522     IMediaSeeking *seek;
523     HRESULT hr;
524     TRACE("(%p/%p)->(%p, %p)\n", iface, This, pCurrent, pStop);
525     hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
526     if (SUCCEEDED(hr)) {
527         hr = IMediaSeeking_GetPositions(seek, pCurrent, pStop);
528         IMediaSeeking_Release(seek);
529     } else if (hr == VFW_E_NOT_CONNECTED) {
530         *pCurrent = 0;
531         *pStop = 0;
532         hr = S_OK;
533     }
534     return hr;
535 }
536 
MediaSeekingPassThru_GetAvailable(IMediaSeeking * iface,LONGLONG * pEarliest,LONGLONG * pLatest)537 static HRESULT WINAPI MediaSeekingPassThru_GetAvailable(IMediaSeeking * iface, LONGLONG * pEarliest, LONGLONG * pLatest)
538 {
539     PassThruImpl *This = impl_from_IMediaSeeking(iface);
540     IMediaSeeking *seek;
541     HRESULT hr;
542     TRACE("(%p/%p)->(%p,%p)\n", iface, This, pEarliest, pLatest);
543     hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
544     if (SUCCEEDED(hr)) {
545         hr = IMediaSeeking_GetAvailable(seek, pEarliest, pLatest);
546         IMediaSeeking_Release(seek);
547     }
548     else
549         return E_NOTIMPL;
550     return hr;
551 }
552 
MediaSeekingPassThru_SetRate(IMediaSeeking * iface,double dRate)553 static HRESULT WINAPI MediaSeekingPassThru_SetRate(IMediaSeeking * iface, double dRate)
554 {
555     PassThruImpl *This = impl_from_IMediaSeeking(iface);
556     IMediaSeeking *seek;
557     HRESULT hr;
558     TRACE("(%p/%p)->(%e)\n", iface, This, dRate);
559     hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
560     if (SUCCEEDED(hr)) {
561         hr = IMediaSeeking_SetRate(seek, dRate);
562         IMediaSeeking_Release(seek);
563     }
564     else
565         return E_NOTIMPL;
566     return hr;
567 }
568 
MediaSeekingPassThru_GetRate(IMediaSeeking * iface,double * dRate)569 static HRESULT WINAPI MediaSeekingPassThru_GetRate(IMediaSeeking * iface, double * dRate)
570 {
571     PassThruImpl *This = impl_from_IMediaSeeking(iface);
572     IMediaSeeking *seek;
573     HRESULT hr;
574     TRACE("(%p/%p)->(%p)\n", iface, This, dRate);
575     hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
576     if (SUCCEEDED(hr)) {
577         hr = IMediaSeeking_GetRate(seek, dRate);
578         IMediaSeeking_Release(seek);
579     }
580     else
581         return E_NOTIMPL;
582     return hr;
583 }
584 
MediaSeekingPassThru_GetPreroll(IMediaSeeking * iface,LONGLONG * pPreroll)585 static HRESULT WINAPI MediaSeekingPassThru_GetPreroll(IMediaSeeking * iface, LONGLONG * pPreroll)
586 {
587     PassThruImpl *This = impl_from_IMediaSeeking(iface);
588     IMediaSeeking *seek;
589     HRESULT hr;
590     TRACE("(%p)\n", pPreroll);
591     hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
592     if (SUCCEEDED(hr)) {
593         hr = IMediaSeeking_GetPreroll(seek, pPreroll);
594         IMediaSeeking_Release(seek);
595     }
596     else
597         return E_NOTIMPL;
598     return hr;
599 }
600 
RendererPosPassThru_RegisterMediaTime(IUnknown * iface,REFERENCE_TIME start)601 HRESULT WINAPI RendererPosPassThru_RegisterMediaTime(IUnknown *iface, REFERENCE_TIME start)
602 {
603     PassThruImpl *This = impl_from_IUnknown_inner(iface);
604     EnterCriticalSection(&This->time_cs);
605     This->time_earliest = start;
606     This->timevalid = TRUE;
607     LeaveCriticalSection(&This->time_cs);
608     return S_OK;
609 }
610 
RendererPosPassThru_ResetMediaTime(IUnknown * iface)611 HRESULT WINAPI RendererPosPassThru_ResetMediaTime(IUnknown *iface)
612 {
613     PassThruImpl *This = impl_from_IUnknown_inner(iface);
614     EnterCriticalSection(&This->time_cs);
615     This->timevalid = FALSE;
616     LeaveCriticalSection(&This->time_cs);
617     return S_OK;
618 }
619 
RendererPosPassThru_EOS(IUnknown * iface)620 HRESULT WINAPI RendererPosPassThru_EOS(IUnknown *iface)
621 {
622     PassThruImpl *This = impl_from_IUnknown_inner(iface);
623     REFERENCE_TIME time;
624     HRESULT hr;
625     hr = IMediaSeeking_GetStopPosition(&This->IMediaSeeking_iface, &time);
626     EnterCriticalSection(&This->time_cs);
627     if (SUCCEEDED(hr)) {
628         This->timevalid = TRUE;
629         This->time_earliest = time;
630     } else
631         This->timevalid = FALSE;
632     LeaveCriticalSection(&This->time_cs);
633     return hr;
634 }
635 
636 static const IMediaSeekingVtbl IMediaSeekingPassThru_Vtbl =
637 {
638     MediaSeekingPassThru_QueryInterface,
639     MediaSeekingPassThru_AddRef,
640     MediaSeekingPassThru_Release,
641     MediaSeekingPassThru_GetCapabilities,
642     MediaSeekingPassThru_CheckCapabilities,
643     MediaSeekingPassThru_IsFormatSupported,
644     MediaSeekingPassThru_QueryPreferredFormat,
645     MediaSeekingPassThru_GetTimeFormat,
646     MediaSeekingPassThru_IsUsingTimeFormat,
647     MediaSeekingPassThru_SetTimeFormat,
648     MediaSeekingPassThru_GetDuration,
649     MediaSeekingPassThru_GetStopPosition,
650     MediaSeekingPassThru_GetCurrentPosition,
651     MediaSeekingPassThru_ConvertTimeFormat,
652     MediaSeekingPassThru_SetPositions,
653     MediaSeekingPassThru_GetPositions,
654     MediaSeekingPassThru_GetAvailable,
655     MediaSeekingPassThru_SetRate,
656     MediaSeekingPassThru_GetRate,
657     MediaSeekingPassThru_GetPreroll
658 };
659 
MediaPositionPassThru_QueryInterface(IMediaPosition * iface,REFIID riid,LPVOID * ppvObj)660 static HRESULT WINAPI MediaPositionPassThru_QueryInterface(IMediaPosition *iface, REFIID riid, LPVOID *ppvObj)
661 {
662     PassThruImpl *This = impl_from_IMediaPosition(iface);
663 
664     TRACE("(%p/%p)->(%s, %p)\n", This, iface, debugstr_guid(riid), ppvObj);
665 
666     return SeekOuter_QueryInterface(This, riid, ppvObj);
667 }
668 
MediaPositionPassThru_AddRef(IMediaPosition * iface)669 static ULONG WINAPI MediaPositionPassThru_AddRef(IMediaPosition *iface)
670 {
671     PassThruImpl *This = impl_from_IMediaPosition(iface);
672 
673     TRACE("(%p/%p)->()\n", iface, This);
674 
675     return SeekOuter_AddRef(This);
676 }
677 
MediaPositionPassThru_Release(IMediaPosition * iface)678 static ULONG WINAPI MediaPositionPassThru_Release(IMediaPosition *iface)
679 {
680     PassThruImpl *This = impl_from_IMediaPosition(iface);
681 
682     TRACE("(%p/%p)->()\n", iface, This);
683 
684     return SeekOuter_Release(This);
685 }
686 
MediaPositionPassThru_GetTypeInfoCount(IMediaPosition * iface,UINT * pctinfo)687 static HRESULT WINAPI MediaPositionPassThru_GetTypeInfoCount(IMediaPosition *iface, UINT*pctinfo)
688 {
689     PassThruImpl *This = impl_from_IMediaPosition(iface);
690 
691     return BaseDispatchImpl_GetTypeInfoCount(&This->baseDispatch, pctinfo);
692 }
693 
MediaPositionPassThru_GetTypeInfo(IMediaPosition * iface,UINT iTInfo,LCID lcid,ITypeInfo ** ppTInfo)694 static HRESULT WINAPI MediaPositionPassThru_GetTypeInfo(IMediaPosition *iface, UINT iTInfo, LCID lcid, ITypeInfo**ppTInfo)
695 {
696     PassThruImpl *This = impl_from_IMediaPosition(iface);
697 
698     return BaseDispatchImpl_GetTypeInfo(&This->baseDispatch, &IID_NULL, iTInfo, lcid, ppTInfo);
699 }
700 
MediaPositionPassThru_GetIDsOfNames(IMediaPosition * iface,REFIID riid,LPOLESTR * rgszNames,UINT cNames,LCID lcid,DISPID * rgDispId)701 static HRESULT WINAPI MediaPositionPassThru_GetIDsOfNames(IMediaPosition *iface, REFIID riid, LPOLESTR*rgszNames, UINT cNames, LCID lcid, DISPID*rgDispId)
702 {
703     PassThruImpl *This = impl_from_IMediaPosition(iface);
704 
705     return BaseDispatchImpl_GetIDsOfNames(&This->baseDispatch, riid, rgszNames, cNames, lcid, rgDispId);
706 }
707 
MediaPositionPassThru_Invoke(IMediaPosition * iface,DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS * pDispParams,VARIANT * pVarResult,EXCEPINFO * pExepInfo,UINT * puArgErr)708 static HRESULT WINAPI MediaPositionPassThru_Invoke(IMediaPosition *iface, DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS*pDispParams, VARIANT*pVarResult, EXCEPINFO*pExepInfo, UINT*puArgErr)
709 {
710     PassThruImpl *This = impl_from_IMediaPosition(iface);
711     HRESULT hr = S_OK;
712     ITypeInfo *pTypeInfo;
713 
714     hr = BaseDispatchImpl_GetTypeInfo(&This->baseDispatch, riid, 1, lcid, &pTypeInfo);
715     if (SUCCEEDED(hr))
716     {
717         hr = ITypeInfo_Invoke(pTypeInfo, &This->IMediaPosition_iface, dispIdMember, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
718         ITypeInfo_Release(pTypeInfo);
719     }
720 
721     return hr;
722 }
723 
MediaPositionPassThru_get_Duration(IMediaPosition * iface,REFTIME * plength)724 static HRESULT WINAPI MediaPositionPassThru_get_Duration(IMediaPosition *iface, REFTIME *plength)
725 {
726     PassThruImpl *This = impl_from_IMediaPosition(iface);
727     IMediaPosition *pos;
728     HRESULT hr;
729 
730     TRACE("(%p)\n", plength);
731 
732     hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos);
733     if (SUCCEEDED(hr)) {
734         hr = IMediaPosition_get_Duration(pos, plength);
735         IMediaPosition_Release(pos);
736     }
737     else
738         return E_NOTIMPL;
739     return hr;
740 }
741 
MediaPositionPassThru_put_CurrentPosition(IMediaPosition * iface,REFTIME llTime)742 static HRESULT WINAPI MediaPositionPassThru_put_CurrentPosition(IMediaPosition *iface, REFTIME llTime)
743 {
744     PassThruImpl *This = impl_from_IMediaPosition(iface);
745     IMediaPosition *pos;
746     HRESULT hr;
747 
748     TRACE("(%s)\n", wine_dbgstr_longlong(llTime));
749 
750     hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos);
751     if (SUCCEEDED(hr)) {
752         hr = IMediaPosition_put_CurrentPosition(pos, llTime);
753         IMediaPosition_Release(pos);
754     }
755     else
756         return E_NOTIMPL;
757     return hr;
758 }
759 
MediaPositionPassThru_get_CurrentPosition(IMediaPosition * iface,REFTIME * pllTime)760 static HRESULT WINAPI MediaPositionPassThru_get_CurrentPosition(IMediaPosition *iface, REFTIME *pllTime)
761 {
762     PassThruImpl *This = impl_from_IMediaPosition(iface);
763     IMediaPosition *pos;
764     HRESULT hr;
765 
766     TRACE("(%p)\n", pllTime);
767 
768     hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos);
769     if (SUCCEEDED(hr)) {
770         hr = IMediaPosition_get_CurrentPosition(pos, pllTime);
771         IMediaPosition_Release(pos);
772     }
773     else
774         return E_NOTIMPL;
775     return hr;
776 }
777 
MediaPositionPassThru_get_StopTime(IMediaPosition * iface,REFTIME * pllTime)778 static HRESULT WINAPI MediaPositionPassThru_get_StopTime(IMediaPosition *iface, REFTIME *pllTime)
779 {
780     PassThruImpl *This = impl_from_IMediaPosition(iface);
781     IMediaPosition *pos;
782     HRESULT hr;
783 
784     TRACE("(%p)\n", pllTime);
785 
786     hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos);
787     if (SUCCEEDED(hr)) {
788         hr = IMediaPosition_get_StopTime(pos, pllTime);
789         IMediaPosition_Release(pos);
790     }
791     else
792         return E_NOTIMPL;
793     return hr;
794 }
795 
MediaPositionPassThru_put_StopTime(IMediaPosition * iface,REFTIME llTime)796 static HRESULT WINAPI MediaPositionPassThru_put_StopTime(IMediaPosition *iface, REFTIME llTime)
797 {
798     PassThruImpl *This = impl_from_IMediaPosition(iface);
799     IMediaPosition *pos;
800     HRESULT hr;
801 
802     TRACE("(%s)\n", wine_dbgstr_longlong(llTime));
803 
804     hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos);
805     if (SUCCEEDED(hr)) {
806         hr = IMediaPosition_put_StopTime(pos, llTime);
807         IMediaPosition_Release(pos);
808     }
809     else
810         return E_NOTIMPL;
811     return hr;
812 }
813 
MediaPositionPassThru_get_PrerollTime(IMediaPosition * iface,REFTIME * pllTime)814 static HRESULT WINAPI MediaPositionPassThru_get_PrerollTime(IMediaPosition *iface, REFTIME *pllTime)
815 {
816     PassThruImpl *This = impl_from_IMediaPosition(iface);
817     IMediaPosition *pos;
818     HRESULT hr;
819 
820     TRACE("(%p)\n", pllTime);
821 
822     hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos);
823     if (SUCCEEDED(hr)) {
824         hr = IMediaPosition_get_PrerollTime(pos, pllTime);
825         IMediaPosition_Release(pos);
826     }
827     else
828         return E_NOTIMPL;
829     return hr;
830 }
831 
MediaPositionPassThru_put_PrerollTime(IMediaPosition * iface,REFTIME llTime)832 static HRESULT WINAPI MediaPositionPassThru_put_PrerollTime(IMediaPosition *iface, REFTIME llTime)
833 {
834     PassThruImpl *This = impl_from_IMediaPosition(iface);
835     IMediaPosition *pos;
836     HRESULT hr;
837 
838     TRACE("(%s)\n", wine_dbgstr_longlong(llTime));
839 
840     hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos);
841     if (SUCCEEDED(hr)) {
842         hr = IMediaPosition_put_PrerollTime(pos, llTime);
843         IMediaPosition_Release(pos);
844     }
845     else
846         return E_NOTIMPL;
847     return hr;
848 }
849 
MediaPositionPassThru_put_Rate(IMediaPosition * iface,double dRate)850 static HRESULT WINAPI MediaPositionPassThru_put_Rate(IMediaPosition *iface, double dRate)
851 {
852     PassThruImpl *This = impl_from_IMediaPosition(iface);
853     IMediaPosition *pos;
854     HRESULT hr;
855 
856     TRACE("(%f)\n", dRate);
857 
858     hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos);
859     if (SUCCEEDED(hr)) {
860         hr = IMediaPosition_put_Rate(pos, dRate);
861         IMediaPosition_Release(pos);
862     }
863     else
864         return E_NOTIMPL;
865     return hr;
866 }
867 
MediaPositionPassThru_get_Rate(IMediaPosition * iface,double * pdRate)868 static HRESULT WINAPI MediaPositionPassThru_get_Rate(IMediaPosition *iface, double *pdRate)
869 {
870     PassThruImpl *This = impl_from_IMediaPosition(iface);
871     IMediaPosition *pos;
872     HRESULT hr;
873 
874     TRACE("(%p)\n", pdRate);
875 
876     hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos);
877     if (SUCCEEDED(hr)) {
878         hr = IMediaPosition_get_Rate(pos, pdRate);
879         IMediaPosition_Release(pos);
880     }
881     else
882         return E_NOTIMPL;
883     return hr;
884 }
885 
MediaPositionPassThru_CanSeekForward(IMediaPosition * iface,LONG * pCanSeekForward)886 static HRESULT WINAPI MediaPositionPassThru_CanSeekForward(IMediaPosition *iface, LONG *pCanSeekForward)
887 {
888     PassThruImpl *This = impl_from_IMediaPosition(iface);
889     IMediaPosition *pos;
890     HRESULT hr;
891 
892     TRACE("(%p)\n", pCanSeekForward);
893 
894     hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos);
895     if (SUCCEEDED(hr)) {
896         hr = IMediaPosition_CanSeekForward(pos, pCanSeekForward);
897         IMediaPosition_Release(pos);
898     }
899     else
900         return E_NOTIMPL;
901     return hr;
902 }
903 
MediaPositionPassThru_CanSeekBackward(IMediaPosition * iface,LONG * pCanSeekBackward)904 static HRESULT WINAPI MediaPositionPassThru_CanSeekBackward(IMediaPosition *iface, LONG *pCanSeekBackward)
905 {
906     PassThruImpl *This = impl_from_IMediaPosition(iface);
907     IMediaPosition *pos;
908     HRESULT hr;
909 
910     TRACE("(%p)\n", pCanSeekBackward);
911 
912     hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos);
913     if (SUCCEEDED(hr)) {
914         hr = IMediaPosition_CanSeekBackward(pos, pCanSeekBackward);
915         IMediaPosition_Release(pos);
916     }
917     else
918         return E_NOTIMPL;
919     return hr;
920 }
921 
922 static const IMediaPositionVtbl IMediaPositionPassThru_Vtbl =
923 {
924     MediaPositionPassThru_QueryInterface,
925     MediaPositionPassThru_AddRef,
926     MediaPositionPassThru_Release,
927     MediaPositionPassThru_GetTypeInfoCount,
928     MediaPositionPassThru_GetTypeInfo,
929     MediaPositionPassThru_GetIDsOfNames,
930     MediaPositionPassThru_Invoke,
931     MediaPositionPassThru_get_Duration,
932     MediaPositionPassThru_put_CurrentPosition,
933     MediaPositionPassThru_get_CurrentPosition,
934     MediaPositionPassThru_get_StopTime,
935     MediaPositionPassThru_put_StopTime,
936     MediaPositionPassThru_get_PrerollTime,
937     MediaPositionPassThru_put_PrerollTime,
938     MediaPositionPassThru_put_Rate,
939     MediaPositionPassThru_get_Rate,
940     MediaPositionPassThru_CanSeekForward,
941     MediaPositionPassThru_CanSeekBackward
942 };
943