urlmon: Fixed protocol tests.
[wine] / dlls / quartz / videorenderer.c
1 /*
2  * Video Renderer (Fullscreen and Windowed using Direct Draw)
3  *
4  * Copyright 2004 Christian Costa
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include "config.h"
22
23 #define NONAMELESSSTRUCT
24 #define NONAMELESSUNION
25 #include "quartz_private.h"
26 #include "control_private.h"
27 #include "pin.h"
28
29 #include "uuids.h"
30 #include "vfwmsgs.h"
31 #include "amvideo.h"
32 #include "windef.h"
33 #include "winbase.h"
34 #include "dshow.h"
35 #include "evcode.h"
36 #include "strmif.h"
37 #include "ddraw.h"
38
39 #include "wine/unicode.h"
40 #include "wine/debug.h"
41
42 WINE_DEFAULT_DEBUG_CHANNEL(quartz);
43
44 static BOOL wnd_class_registered = FALSE;
45
46 static const WCHAR wcsInputPinName[] = {'i','n','p','u','t',' ','p','i','n',0};
47
48 static const IBaseFilterVtbl VideoRenderer_Vtbl;
49 static const IUnknownVtbl IInner_VTable;
50 static const IBasicVideoVtbl IBasicVideo_VTable;
51 static const IVideoWindowVtbl IVideoWindow_VTable;
52 static const IPinVtbl VideoRenderer_InputPin_Vtbl;
53
54 typedef struct VideoRendererImpl
55 {
56     const IBaseFilterVtbl * lpVtbl;
57     const IBasicVideoVtbl * IBasicVideo_vtbl;
58     const IVideoWindowVtbl * IVideoWindow_vtbl;
59     const IUnknownVtbl * IInner_vtbl;
60
61     LONG refCount;
62     CRITICAL_SECTION csFilter;
63     FILTER_STATE state;
64     REFERENCE_TIME rtStreamStart;
65     IReferenceClock * pClock;
66     FILTER_INFO filterInfo;
67
68     InputPin * pInputPin;
69     IPin ** ppPins;
70
71     BOOL init;
72     HANDLE hThread;
73     DWORD ThreadID;
74     HANDLE hEvent;
75     BOOL ThreadResult;
76     HWND hWnd;
77     HWND hWndMsgDrain;
78     BOOL AutoShow;
79     RECT SourceRect;
80     RECT DestRect;
81     RECT WindowPos;
82     long VideoWidth;
83     long VideoHeight;
84     IUnknown * pUnkOuter;
85     BOOL bUnkOuterValid;
86     BOOL bAggregatable;
87 } VideoRendererImpl;
88
89 static LRESULT CALLBACK VideoWndProcA(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
90 {
91     VideoRendererImpl* pVideoRenderer = (VideoRendererImpl*)GetWindowLongA(hwnd, 0);
92     LPRECT lprect = (LPRECT)lParam;
93
94     if (pVideoRenderer && pVideoRenderer->hWndMsgDrain)
95     {
96         switch(uMsg)
97         {
98             case WM_KEYDOWN:
99             case WM_KEYUP:
100             case WM_LBUTTONDBLCLK:
101             case WM_LBUTTONDOWN:
102             case WM_LBUTTONUP:
103             case WM_MBUTTONDBLCLK:
104             case WM_MBUTTONDOWN:
105             case WM_MBUTTONUP:
106             case WM_MOUSEACTIVATE:
107             case WM_MOUSEMOVE:
108             case WM_NCLBUTTONDBLCLK:
109             case WM_NCLBUTTONDOWN:
110             case WM_NCLBUTTONUP:
111             case WM_NCMBUTTONDBLCLK:
112             case WM_NCMBUTTONDOWN:
113             case WM_NCMBUTTONUP:
114             case WM_NCMOUSEMOVE:
115             case WM_NCRBUTTONDBLCLK:
116             case WM_NCRBUTTONDOWN:
117             case WM_NCRBUTTONUP:
118             case WM_RBUTTONDBLCLK:
119             case WM_RBUTTONDOWN:
120             case WM_RBUTTONUP:
121                 PostMessageA(pVideoRenderer->hWndMsgDrain, uMsg, wParam, lParam);
122                 break;
123             default:
124                 break;
125         }
126     }
127
128     switch(uMsg)
129     {
130         case WM_SIZING:
131             /* TRACE("WM_SIZING %d %d %d %d\n", lprect->left, lprect->top, lprect->right, lprect->bottom); */
132             SetWindowPos(hwnd, NULL, lprect->left, lprect->top, lprect->right - lprect->left, lprect->bottom - lprect->top, SWP_NOZORDER);
133             GetClientRect(hwnd, &pVideoRenderer->DestRect);
134             TRACE("WM_SIZING: DestRect=(%d,%d),(%d,%d)\n",
135                 pVideoRenderer->DestRect.left,
136                 pVideoRenderer->DestRect.top,
137                 pVideoRenderer->DestRect.right - pVideoRenderer->DestRect.left,
138                 pVideoRenderer->DestRect.bottom - pVideoRenderer->DestRect.top);
139             return TRUE;
140         case WM_SIZE:
141             TRACE("WM_SIZE %d %d\n", LOWORD(lParam), HIWORD(lParam));
142             GetClientRect(hwnd, &pVideoRenderer->DestRect);
143             TRACE("WM_SIZING: DestRect=(%d,%d),(%d,%d)\n",
144                 pVideoRenderer->DestRect.left,
145                 pVideoRenderer->DestRect.top,
146                 pVideoRenderer->DestRect.right - pVideoRenderer->DestRect.left,
147                 pVideoRenderer->DestRect.bottom - pVideoRenderer->DestRect.top);
148             return TRUE;
149         default:
150             return DefWindowProcA(hwnd, uMsg, wParam, lParam);
151     }
152     return 0;
153 }
154
155 static BOOL CreateRenderingWindow(VideoRendererImpl* This)
156 {
157     WNDCLASSA winclass;
158
159     TRACE("(%p)->()\n", This);
160     
161     winclass.style = 0;
162     winclass.lpfnWndProc = VideoWndProcA;
163     winclass.cbClsExtra = 0;
164     winclass.cbWndExtra = sizeof(VideoRendererImpl*);
165     winclass.hInstance = NULL;
166     winclass.hIcon = NULL;
167     winclass.hCursor = NULL;
168     winclass.hbrBackground = GetStockObject(BLACK_BRUSH);
169     winclass.lpszMenuName = NULL;
170     winclass.lpszClassName = "Wine ActiveMovie Class";
171
172     if (!wnd_class_registered)
173     {
174         if (!RegisterClassA(&winclass))
175         {
176             ERR("Unable to register window %u\n", GetLastError());
177             return FALSE;
178         }
179         wnd_class_registered = TRUE;
180     }
181
182     This->hWnd = CreateWindowExA(0, "Wine ActiveMovie Class", "Wine ActiveMovie Window", WS_SIZEBOX,
183                                  CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL,
184                                  NULL, NULL, NULL);
185
186     if (!This->hWnd)
187     {
188         ERR("Unable to create window\n");
189         return FALSE;
190     }
191
192     SetWindowLongA(This->hWnd, 0, (LONG)This);
193
194     return TRUE;
195 }
196
197 static DWORD WINAPI MessageLoop(LPVOID lpParameter)
198 {
199     VideoRendererImpl* This = (VideoRendererImpl*) lpParameter;
200     MSG msg; 
201     BOOL fGotMessage;
202
203     TRACE("Starting message loop\n");
204
205     if (!CreateRenderingWindow(This))
206     {
207         This->ThreadResult = FALSE;
208         SetEvent(This->hEvent);
209         return 0;
210     }
211
212     This->ThreadResult = TRUE;
213     SetEvent(This->hEvent);
214
215     while ((fGotMessage = GetMessageA(&msg, NULL, 0, 0)) != 0 && fGotMessage != -1) 
216     {
217         TranslateMessage(&msg); 
218         DispatchMessageA(&msg); 
219     }
220
221     TRACE("End of message loop\n");
222
223     return msg.wParam;
224 }
225
226 static BOOL CreateRenderingSubsystem(VideoRendererImpl* This)
227 {
228     This->hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
229     if (!This->hEvent)
230         return FALSE;
231
232     This->hThread = CreateThread(NULL, 0, MessageLoop, (LPVOID)This, 0, &This->ThreadID);
233     if (!This->hThread)
234     {
235         CloseHandle(This->hEvent);
236         return FALSE;
237     }
238
239     WaitForSingleObject(This->hEvent, INFINITE);
240     CloseHandle(This->hEvent);
241
242     if (!This->ThreadResult)
243     {
244         CloseHandle(This->hThread);
245         return FALSE;
246     }
247
248     return TRUE;
249 }
250
251 static const IMemInputPinVtbl MemInputPin_Vtbl = 
252 {
253     MemInputPin_QueryInterface,
254     MemInputPin_AddRef,
255     MemInputPin_Release,
256     MemInputPin_GetAllocator,
257     MemInputPin_NotifyAllocator,
258     MemInputPin_GetAllocatorRequirements,
259     MemInputPin_Receive,
260     MemInputPin_ReceiveMultiple,
261     MemInputPin_ReceiveCanBlock
262 };
263
264 static HRESULT VideoRenderer_InputPin_Construct(const PIN_INFO * pPinInfo, SAMPLEPROC pSampleProc, LPVOID pUserData, QUERYACCEPTPROC pQueryAccept, LPCRITICAL_SECTION pCritSec, IPin ** ppPin)
265 {
266     InputPin * pPinImpl;
267
268     *ppPin = NULL;
269
270     if (pPinInfo->dir != PINDIR_INPUT)
271     {
272         ERR("Pin direction(%x) != PINDIR_INPUT\n", pPinInfo->dir);
273         return E_INVALIDARG;
274     }
275
276     pPinImpl = CoTaskMemAlloc(sizeof(*pPinImpl));
277
278     if (!pPinImpl)
279         return E_OUTOFMEMORY;
280
281     if (SUCCEEDED(InputPin_Init(pPinInfo, pSampleProc, pUserData, pQueryAccept, pCritSec, pPinImpl)))
282     {
283         pPinImpl->pin.lpVtbl = &VideoRenderer_InputPin_Vtbl;
284         pPinImpl->lpVtblMemInput = &MemInputPin_Vtbl;
285
286         *ppPin = (IPin *)(&pPinImpl->pin.lpVtbl);
287         return S_OK;
288     }
289
290     CoTaskMemFree(pPinImpl);
291     return E_FAIL;
292 }
293
294 static DWORD VideoRenderer_SendSampleData(VideoRendererImpl* This, LPBYTE data, DWORD size)
295 {
296     VIDEOINFOHEADER* format;
297     AM_MEDIA_TYPE amt;
298     HRESULT hr = S_OK;
299     DDSURFACEDESC sdesc;
300     int width;
301     int height;
302     LPBYTE palette = NULL;
303     HDC hDC;
304
305     TRACE("%p %p %d\n", This, data, size);
306
307     sdesc.dwSize = sizeof(sdesc);
308     hr = IPin_ConnectionMediaType(This->ppPins[0], &amt);
309     if (FAILED(hr)) {
310         ERR("Unable to retrieve media type\n");
311         return hr;
312     }
313     format = (VIDEOINFOHEADER*)amt.pbFormat;
314
315     TRACE("biSize = %d\n", format->bmiHeader.biSize);
316     TRACE("biWidth = %d\n", format->bmiHeader.biWidth);
317     TRACE("biHeight = %d\n", format->bmiHeader.biHeight);
318     TRACE("biPlanes = %d\n", format->bmiHeader.biPlanes);
319     TRACE("biBitCount = %d\n", format->bmiHeader.biBitCount);
320     TRACE("biCompression = %s\n", debugstr_an((LPSTR)&(format->bmiHeader.biCompression), 4));
321     TRACE("biSizeImage = %d\n", format->bmiHeader.biSizeImage);
322
323     width = format->bmiHeader.biWidth;
324     height = format->bmiHeader.biHeight;
325     palette = ((LPBYTE)&format->bmiHeader) + format->bmiHeader.biSize;
326  
327     if (!This->init)
328     {
329         /* Honor previously set WindowPos */
330         TRACE("WindowPos: %d %d %d %d\n", This->WindowPos.left, This->WindowPos.top, This->WindowPos.right, This->WindowPos.bottom);
331         SetWindowPos(This->hWnd, NULL,
332             This->WindowPos.left,
333             This->WindowPos.top,
334             This->WindowPos.right - This->WindowPos.left,
335             This->WindowPos.bottom - This->WindowPos.top,
336             SWP_NOZORDER|SWP_NOMOVE);
337         GetClientRect(This->hWnd, &This->DestRect);
338         This->init  = TRUE;
339     }
340
341     hDC = GetDC(This->hWnd);
342
343     if (!hDC) {
344         ERR("Cannot get DC from window!\n");
345         return E_FAIL;
346     }
347
348     TRACE("Src Rect: %d %d %d %d\n", This->SourceRect.left, This->SourceRect.top, This->SourceRect.right, This->SourceRect.bottom);
349     TRACE("Dst Rect: %d %d %d %d\n", This->DestRect.left, This->DestRect.top, This->DestRect.right, This->DestRect.bottom);
350
351     StretchDIBits(hDC, This->DestRect.left, This->DestRect.top, This->DestRect.right -This->DestRect.left,
352                   This->DestRect.bottom - This->DestRect.top, This->SourceRect.left, This->SourceRect.top,
353                   This->SourceRect.right - This->SourceRect.left, This->SourceRect.bottom - This->SourceRect.top,
354                   data, (BITMAPINFO*)&format->bmiHeader, DIB_RGB_COLORS, SRCCOPY);
355
356     ReleaseDC(This->hWnd, hDC);
357     
358     if (This->AutoShow)
359         ShowWindow(This->hWnd, SW_SHOW);
360
361     return S_OK;
362 }
363
364 static HRESULT VideoRenderer_Sample(LPVOID iface, IMediaSample * pSample)
365 {
366     VideoRendererImpl *This = (VideoRendererImpl *)iface;
367     LPBYTE pbSrcStream = NULL;
368     long cbSrcStream = 0;
369     REFERENCE_TIME tStart, tStop;
370     HRESULT hr;
371
372     TRACE("%p %p\n", iface, pSample);
373     
374     hr = IMediaSample_GetPointer(pSample, &pbSrcStream);
375     if (FAILED(hr))
376     {
377         ERR("Cannot get pointer to sample data (%x)\n", hr);
378         return hr;
379     }
380
381     hr = IMediaSample_GetTime(pSample, &tStart, &tStop);
382     if (FAILED(hr))
383         ERR("Cannot get sample time (%x)\n", hr);
384
385     cbSrcStream = IMediaSample_GetActualDataLength(pSample);
386
387     TRACE("val %p %ld\n", pbSrcStream, cbSrcStream);
388
389 #if 0 /* For debugging purpose */
390     {
391         int i;
392         for(i = 0; i < cbSrcStream; i++)
393         {
394             if ((i!=0) && !(i%16))
395                 TRACE("\n");
396                 TRACE("%02x ", pbSrcStream[i]);
397         }
398         TRACE("\n");
399     }
400 #endif
401     
402     VideoRenderer_SendSampleData(This, pbSrcStream, cbSrcStream);
403
404     return S_OK;
405 }
406
407 static HRESULT VideoRenderer_QueryAccept(LPVOID iface, const AM_MEDIA_TYPE * pmt)
408 {
409     if (!IsEqualIID(&pmt->majortype, &MEDIATYPE_Video))
410         return S_FALSE;
411
412     if (IsEqualIID(&pmt->subtype, &MEDIASUBTYPE_RGB32) ||
413         IsEqualIID(&pmt->subtype, &MEDIASUBTYPE_RGB24) ||
414         IsEqualIID(&pmt->subtype, &MEDIASUBTYPE_RGB565) ||
415         IsEqualIID(&pmt->subtype, &MEDIASUBTYPE_RGB8))
416     {
417         VideoRendererImpl* This = (VideoRendererImpl*) iface;
418         VIDEOINFOHEADER* format = (VIDEOINFOHEADER*)pmt->pbFormat;
419
420         if (!IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo))
421         {
422             WARN("Format type %s not supported\n", debugstr_guid(&pmt->formattype));
423             return S_FALSE;
424         }
425         This->SourceRect.left = 0;
426         This->SourceRect.top = 0;
427         This->SourceRect.right = This->VideoWidth = format->bmiHeader.biWidth;
428         This->SourceRect.bottom = This->VideoHeight = format->bmiHeader.biHeight;
429         return S_OK;
430     }
431     return S_FALSE;
432 }
433
434 HRESULT VideoRenderer_create(IUnknown * pUnkOuter, LPVOID * ppv)
435 {
436     HRESULT hr;
437     PIN_INFO piInput;
438     VideoRendererImpl * pVideoRenderer;
439
440     TRACE("(%p, %p)\n", pUnkOuter, ppv);
441
442     *ppv = NULL;
443
444     pVideoRenderer = CoTaskMemAlloc(sizeof(VideoRendererImpl));
445     pVideoRenderer->pUnkOuter = pUnkOuter;
446     pVideoRenderer->bUnkOuterValid = FALSE;
447     pVideoRenderer->bAggregatable = FALSE;
448     pVideoRenderer->IInner_vtbl = &IInner_VTable;
449
450     pVideoRenderer->lpVtbl = &VideoRenderer_Vtbl;
451     pVideoRenderer->IBasicVideo_vtbl = &IBasicVideo_VTable;
452     pVideoRenderer->IVideoWindow_vtbl = &IVideoWindow_VTable;
453     
454     pVideoRenderer->refCount = 1;
455     InitializeCriticalSection(&pVideoRenderer->csFilter);
456     pVideoRenderer->csFilter.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": VideoRendererImpl.csFilter");
457     pVideoRenderer->state = State_Stopped;
458     pVideoRenderer->pClock = NULL;
459     pVideoRenderer->init = 0;
460     pVideoRenderer->AutoShow = 1;
461     ZeroMemory(&pVideoRenderer->filterInfo, sizeof(FILTER_INFO));
462
463     pVideoRenderer->ppPins = CoTaskMemAlloc(1 * sizeof(IPin *));
464
465     /* construct input pin */
466     piInput.dir = PINDIR_INPUT;
467     piInput.pFilter = (IBaseFilter *)pVideoRenderer;
468     lstrcpynW(piInput.achName, wcsInputPinName, sizeof(piInput.achName) / sizeof(piInput.achName[0]));
469
470     hr = VideoRenderer_InputPin_Construct(&piInput, VideoRenderer_Sample, (LPVOID)pVideoRenderer, VideoRenderer_QueryAccept, &pVideoRenderer->csFilter, (IPin **)&pVideoRenderer->pInputPin);
471
472     if (SUCCEEDED(hr))
473     {
474         pVideoRenderer->ppPins[0] = (IPin *)pVideoRenderer->pInputPin;
475         *ppv = (LPVOID)pVideoRenderer;
476     }
477     else
478     {
479         CoTaskMemFree(pVideoRenderer->ppPins);
480         pVideoRenderer->csFilter.DebugInfo->Spare[0] = 0;
481         DeleteCriticalSection(&pVideoRenderer->csFilter);
482         CoTaskMemFree(pVideoRenderer);
483     }
484
485     if (!CreateRenderingSubsystem(pVideoRenderer))
486         return E_FAIL;
487     
488     return hr;
489 }
490
491 static HRESULT WINAPI VideoRendererInner_QueryInterface(IUnknown * iface, REFIID riid, LPVOID * ppv)
492 {
493     ICOM_THIS_MULTI(VideoRendererImpl, IInner_vtbl, iface);
494     TRACE("(%p/%p)->(%s, %p)\n", This, iface, qzdebugstr_guid(riid), ppv);
495
496     if (This->bAggregatable)
497         This->bUnkOuterValid = TRUE;
498
499     *ppv = NULL;
500
501     if (IsEqualIID(riid, &IID_IUnknown))
502         *ppv = (LPVOID)&(This->IInner_vtbl);
503     else if (IsEqualIID(riid, &IID_IPersist))
504         *ppv = (LPVOID)This;
505     else if (IsEqualIID(riid, &IID_IMediaFilter))
506         *ppv = (LPVOID)This;
507     else if (IsEqualIID(riid, &IID_IBaseFilter))
508         *ppv = (LPVOID)This;
509     else if (IsEqualIID(riid, &IID_IBasicVideo))
510         *ppv = (LPVOID)&(This->IBasicVideo_vtbl);
511     else if (IsEqualIID(riid, &IID_IVideoWindow))
512         *ppv = (LPVOID)&(This->IVideoWindow_vtbl);
513
514     if (*ppv)
515     {
516         IUnknown_AddRef((IUnknown *)(*ppv));
517         return S_OK;
518     }
519
520     FIXME("No interface for %s!\n", qzdebugstr_guid(riid));
521
522     return E_NOINTERFACE;
523 }
524
525 static ULONG WINAPI VideoRendererInner_AddRef(IUnknown * iface)
526 {
527     ICOM_THIS_MULTI(VideoRendererImpl, IInner_vtbl, iface);
528     ULONG refCount = InterlockedIncrement(&This->refCount);
529
530     TRACE("(%p/%p)->() AddRef from %d\n", This, iface, refCount - 1);
531
532     return refCount;
533 }
534
535 static ULONG WINAPI VideoRendererInner_Release(IUnknown * iface)
536 {
537     ICOM_THIS_MULTI(VideoRendererImpl, IInner_vtbl, iface);
538     ULONG refCount = InterlockedDecrement(&This->refCount);
539
540     TRACE("(%p/%p)->() Release from %d\n", This, iface, refCount + 1);
541
542     if (!refCount)
543     {
544         IPin *pConnectedTo;
545
546         DestroyWindow(This->hWnd);
547         PostThreadMessageA(This->ThreadID, WM_QUIT, 0, 0);
548         WaitForSingleObject(This->hThread, INFINITE);
549         CloseHandle(This->hThread);
550
551         if (This->pClock)
552             IReferenceClock_Release(This->pClock);
553         
554         if (SUCCEEDED(IPin_ConnectedTo(This->ppPins[0], &pConnectedTo)))
555         {
556             IPin_Disconnect(pConnectedTo);
557             IPin_Release(pConnectedTo);
558         }
559         IPin_Disconnect(This->ppPins[0]);
560
561         IPin_Release(This->ppPins[0]);
562         
563         CoTaskMemFree(This->ppPins);
564         This->lpVtbl = NULL;
565         
566         This->csFilter.DebugInfo->Spare[0] = 0;
567         DeleteCriticalSection(&This->csFilter);
568
569         TRACE("Destroying Video Renderer\n");
570         CoTaskMemFree(This);
571         
572         return 0;
573     }
574     else
575         return refCount;
576 }
577
578 static const IUnknownVtbl IInner_VTable =
579 {
580     VideoRendererInner_QueryInterface,
581     VideoRendererInner_AddRef,
582     VideoRendererInner_Release
583 };
584
585 static HRESULT WINAPI VideoRenderer_QueryInterface(IBaseFilter * iface, REFIID riid, LPVOID * ppv)
586 {
587     VideoRendererImpl *This = (VideoRendererImpl *)iface;
588
589     if (This->bAggregatable)
590         This->bUnkOuterValid = TRUE;
591
592     if (This->pUnkOuter)
593     {
594         if (This->bAggregatable)
595             return IUnknown_QueryInterface(This->pUnkOuter, riid, ppv);
596
597         if (IsEqualIID(riid, &IID_IUnknown))
598         {
599             HRESULT hr;
600
601             IUnknown_AddRef((IUnknown *)&(This->IInner_vtbl));
602             hr = IUnknown_QueryInterface((IUnknown *)&(This->IInner_vtbl), riid, ppv);
603             IUnknown_Release((IUnknown *)&(This->IInner_vtbl));
604             This->bAggregatable = TRUE;
605             return hr;
606         }
607
608         *ppv = NULL;
609         return E_NOINTERFACE;
610     }
611
612     return IUnknown_QueryInterface((IUnknown *)&(This->IInner_vtbl), riid, ppv);
613 }
614
615 static ULONG WINAPI VideoRenderer_AddRef(IBaseFilter * iface)
616 {
617     VideoRendererImpl *This = (VideoRendererImpl *)iface;
618
619     if (This->pUnkOuter && This->bUnkOuterValid)
620         return IUnknown_AddRef(This->pUnkOuter);
621     return IUnknown_AddRef((IUnknown *)&(This->IInner_vtbl));
622 }
623
624 static ULONG WINAPI VideoRenderer_Release(IBaseFilter * iface)
625 {
626     VideoRendererImpl *This = (VideoRendererImpl *)iface;
627
628     if (This->pUnkOuter && This->bUnkOuterValid)
629         return IUnknown_Release(This->pUnkOuter);
630     return IUnknown_Release((IUnknown *)&(This->IInner_vtbl));
631 }
632
633 /** IPersist methods **/
634
635 static HRESULT WINAPI VideoRenderer_GetClassID(IBaseFilter * iface, CLSID * pClsid)
636 {
637     VideoRendererImpl *This = (VideoRendererImpl *)iface;
638
639     TRACE("(%p/%p)->(%p)\n", This, iface, pClsid);
640
641     *pClsid = CLSID_VideoRenderer;
642
643     return S_OK;
644 }
645
646 /** IMediaFilter methods **/
647
648 static HRESULT WINAPI VideoRenderer_Stop(IBaseFilter * iface)
649 {
650     VideoRendererImpl *This = (VideoRendererImpl *)iface;
651
652     TRACE("(%p/%p)->()\n", This, iface);
653
654     EnterCriticalSection(&This->csFilter);
655     {
656         This->state = State_Stopped;
657     }
658     LeaveCriticalSection(&This->csFilter);
659     
660     return S_OK;
661 }
662
663 static HRESULT WINAPI VideoRenderer_Pause(IBaseFilter * iface)
664 {
665     VideoRendererImpl *This = (VideoRendererImpl *)iface;
666     
667     TRACE("(%p/%p)->()\n", This, iface);
668
669     EnterCriticalSection(&This->csFilter);
670     {
671         This->state = State_Paused;
672     }
673     LeaveCriticalSection(&This->csFilter);
674
675     return S_OK;
676 }
677
678 static HRESULT WINAPI VideoRenderer_Run(IBaseFilter * iface, REFERENCE_TIME tStart)
679 {
680     VideoRendererImpl *This = (VideoRendererImpl *)iface;
681
682     TRACE("(%p/%p)->(%s)\n", This, iface, wine_dbgstr_longlong(tStart));
683
684     EnterCriticalSection(&This->csFilter);
685     {
686         This->rtStreamStart = tStart;
687         This->state = State_Running;
688     }
689     LeaveCriticalSection(&This->csFilter);
690
691     return S_OK;
692 }
693
694 static HRESULT WINAPI VideoRenderer_GetState(IBaseFilter * iface, DWORD dwMilliSecsTimeout, FILTER_STATE *pState)
695 {
696     VideoRendererImpl *This = (VideoRendererImpl *)iface;
697
698     TRACE("(%p/%p)->(%d, %p)\n", This, iface, dwMilliSecsTimeout, pState);
699
700     EnterCriticalSection(&This->csFilter);
701     {
702         *pState = This->state;
703     }
704     LeaveCriticalSection(&This->csFilter);
705
706     return S_OK;
707 }
708
709 static HRESULT WINAPI VideoRenderer_SetSyncSource(IBaseFilter * iface, IReferenceClock *pClock)
710 {
711     VideoRendererImpl *This = (VideoRendererImpl *)iface;
712
713     TRACE("(%p/%p)->(%p)\n", This, iface, pClock);
714
715     EnterCriticalSection(&This->csFilter);
716     {
717         if (This->pClock)
718             IReferenceClock_Release(This->pClock);
719         This->pClock = pClock;
720         if (This->pClock)
721             IReferenceClock_AddRef(This->pClock);
722     }
723     LeaveCriticalSection(&This->csFilter);
724
725     return S_OK;
726 }
727
728 static HRESULT WINAPI VideoRenderer_GetSyncSource(IBaseFilter * iface, IReferenceClock **ppClock)
729 {
730     VideoRendererImpl *This = (VideoRendererImpl *)iface;
731
732     TRACE("(%p/%p)->(%p)\n", This, iface, ppClock);
733
734     EnterCriticalSection(&This->csFilter);
735     {
736         *ppClock = This->pClock;
737         IReferenceClock_AddRef(This->pClock);
738     }
739     LeaveCriticalSection(&This->csFilter);
740     
741     return S_OK;
742 }
743
744 /** IBaseFilter implementation **/
745
746 static HRESULT WINAPI VideoRenderer_EnumPins(IBaseFilter * iface, IEnumPins **ppEnum)
747 {
748     ENUMPINDETAILS epd;
749     VideoRendererImpl *This = (VideoRendererImpl *)iface;
750
751     TRACE("(%p/%p)->(%p)\n", This, iface, ppEnum);
752
753     epd.cPins = 1; /* input pin */
754     epd.ppPins = This->ppPins;
755     return IEnumPinsImpl_Construct(&epd, ppEnum);
756 }
757
758 static HRESULT WINAPI VideoRenderer_FindPin(IBaseFilter * iface, LPCWSTR Id, IPin **ppPin)
759 {
760     VideoRendererImpl *This = (VideoRendererImpl *)iface;
761
762     TRACE("(%p/%p)->(%p,%p)\n", This, iface, debugstr_w(Id), ppPin);
763
764     FIXME("VideoRenderer::FindPin(...)\n");
765
766     /* FIXME: critical section */
767
768     return E_NOTIMPL;
769 }
770
771 static HRESULT WINAPI VideoRenderer_QueryFilterInfo(IBaseFilter * iface, FILTER_INFO *pInfo)
772 {
773     VideoRendererImpl *This = (VideoRendererImpl *)iface;
774
775     TRACE("(%p/%p)->(%p)\n", This, iface, pInfo);
776
777     strcpyW(pInfo->achName, This->filterInfo.achName);
778     pInfo->pGraph = This->filterInfo.pGraph;
779
780     if (pInfo->pGraph)
781         IFilterGraph_AddRef(pInfo->pGraph);
782     
783     return S_OK;
784 }
785
786 static HRESULT WINAPI VideoRenderer_JoinFilterGraph(IBaseFilter * iface, IFilterGraph *pGraph, LPCWSTR pName)
787 {
788     VideoRendererImpl *This = (VideoRendererImpl *)iface;
789
790     TRACE("(%p/%p)->(%p, %s)\n", This, iface, pGraph, debugstr_w(pName));
791
792     EnterCriticalSection(&This->csFilter);
793     {
794         if (pName)
795             strcpyW(This->filterInfo.achName, pName);
796         else
797             *This->filterInfo.achName = '\0';
798         This->filterInfo.pGraph = pGraph; /* NOTE: do NOT increase ref. count */
799     }
800     LeaveCriticalSection(&This->csFilter);
801
802     return S_OK;
803 }
804
805 static HRESULT WINAPI VideoRenderer_QueryVendorInfo(IBaseFilter * iface, LPWSTR *pVendorInfo)
806 {
807     VideoRendererImpl *This = (VideoRendererImpl *)iface;
808     TRACE("(%p/%p)->(%p)\n", This, iface, pVendorInfo);
809     return E_NOTIMPL;
810 }
811
812 static const IBaseFilterVtbl VideoRenderer_Vtbl =
813 {
814     VideoRenderer_QueryInterface,
815     VideoRenderer_AddRef,
816     VideoRenderer_Release,
817     VideoRenderer_GetClassID,
818     VideoRenderer_Stop,
819     VideoRenderer_Pause,
820     VideoRenderer_Run,
821     VideoRenderer_GetState,
822     VideoRenderer_SetSyncSource,
823     VideoRenderer_GetSyncSource,
824     VideoRenderer_EnumPins,
825     VideoRenderer_FindPin,
826     VideoRenderer_QueryFilterInfo,
827     VideoRenderer_JoinFilterGraph,
828     VideoRenderer_QueryVendorInfo
829 };
830
831 static HRESULT WINAPI VideoRenderer_InputPin_EndOfStream(IPin * iface)
832 {
833     InputPin* This = (InputPin*)iface;
834     IMediaEventSink* pEventSink;
835     HRESULT hr;
836
837     TRACE("(%p/%p)->()\n", This, iface);
838
839     hr = IFilterGraph_QueryInterface(((VideoRendererImpl*)This->pin.pinInfo.pFilter)->filterInfo.pGraph, &IID_IMediaEventSink, (LPVOID*)&pEventSink);
840     if (SUCCEEDED(hr))
841     {
842         hr = IMediaEventSink_Notify(pEventSink, EC_COMPLETE, S_OK, 0);
843         IMediaEventSink_Release(pEventSink);
844     }
845
846     return hr;
847 }
848
849 static const IPinVtbl VideoRenderer_InputPin_Vtbl = 
850 {
851     InputPin_QueryInterface,
852     IPinImpl_AddRef,
853     InputPin_Release,
854     InputPin_Connect,
855     InputPin_ReceiveConnection,
856     IPinImpl_Disconnect,
857     IPinImpl_ConnectedTo,
858     IPinImpl_ConnectionMediaType,
859     IPinImpl_QueryPinInfo,
860     IPinImpl_QueryDirection,
861     IPinImpl_QueryId,
862     IPinImpl_QueryAccept,
863     IPinImpl_EnumMediaTypes,
864     IPinImpl_QueryInternalConnections,
865     VideoRenderer_InputPin_EndOfStream,
866     InputPin_BeginFlush,
867     InputPin_EndFlush,
868     InputPin_NewSegment
869 };
870
871 /*** IUnknown methods ***/
872 static HRESULT WINAPI Basicvideo_QueryInterface(IBasicVideo *iface,
873                                                 REFIID riid,
874                                                 LPVOID*ppvObj) {
875     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
876
877     TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
878
879     return VideoRenderer_QueryInterface((IBaseFilter*)This, riid, ppvObj);
880 }
881
882 static ULONG WINAPI Basicvideo_AddRef(IBasicVideo *iface) {
883     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
884
885     TRACE("(%p/%p)->()\n", This, iface);
886
887     return VideoRenderer_AddRef((IBaseFilter*)This);
888 }
889
890 static ULONG WINAPI Basicvideo_Release(IBasicVideo *iface) {
891     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
892
893     TRACE("(%p/%p)->()\n", This, iface);
894
895     return VideoRenderer_Release((IBaseFilter*)This);
896 }
897
898 /*** IDispatch methods ***/
899 static HRESULT WINAPI Basicvideo_GetTypeInfoCount(IBasicVideo *iface,
900                                                   UINT*pctinfo) {
901     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
902
903     FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, pctinfo);
904
905     return S_OK;
906 }
907
908 static HRESULT WINAPI Basicvideo_GetTypeInfo(IBasicVideo *iface,
909                                              UINT iTInfo,
910                                              LCID lcid,
911                                              ITypeInfo**ppTInfo) {
912     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
913
914     FIXME("(%p/%p)->(%d, %d, %p): stub !!!\n", This, iface, iTInfo, lcid, ppTInfo);
915
916     return S_OK;
917 }
918
919 static HRESULT WINAPI Basicvideo_GetIDsOfNames(IBasicVideo *iface,
920                                                REFIID riid,
921                                                LPOLESTR*rgszNames,
922                                                UINT cNames,
923                                                LCID lcid,
924                                                DISPID*rgDispId) {
925     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
926
927     FIXME("(%p/%p)->(%s (%p), %p, %d, %d, %p): stub !!!\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
928
929     return S_OK;
930 }
931
932 static HRESULT WINAPI Basicvideo_Invoke(IBasicVideo *iface,
933                                         DISPID dispIdMember,
934                                         REFIID riid,
935                                         LCID lcid,
936                                         WORD wFlags,
937                                         DISPPARAMS*pDispParams,
938                                         VARIANT*pVarResult,
939                                         EXCEPINFO*pExepInfo,
940                                         UINT*puArgErr) {
941     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
942
943     FIXME("(%p/%p)->(%d, %s (%p), %d, %04x, %p, %p, %p, %p): stub !!!\n", This, iface, dispIdMember, debugstr_guid(riid), riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
944
945     return S_OK;
946 }
947
948 /*** IBasicVideo methods ***/
949 static HRESULT WINAPI Basicvideo_get_AvgTimePerFrame(IBasicVideo *iface,
950                                                      REFTIME *pAvgTimePerFrame) {
951     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
952
953     FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, pAvgTimePerFrame);
954
955     return S_OK;
956 }
957
958 static HRESULT WINAPI Basicvideo_get_BitRate(IBasicVideo *iface,
959                                              long *pBitRate) {
960     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
961
962     FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, pBitRate);
963
964     return S_OK;
965 }
966
967 static HRESULT WINAPI Basicvideo_get_BitErrorRate(IBasicVideo *iface,
968                                                   long *pBitErrorRate) {
969     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
970
971     FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, pBitErrorRate);
972
973     return S_OK;
974 }
975
976 static HRESULT WINAPI Basicvideo_get_VideoWidth(IBasicVideo *iface,
977                                                 long *pVideoWidth) {
978     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
979
980     TRACE("(%p/%p)->(%p)\n", This, iface, pVideoWidth);
981
982     *pVideoWidth = This->VideoWidth;
983
984     return S_OK;
985 }
986
987 static HRESULT WINAPI Basicvideo_get_VideoHeight(IBasicVideo *iface,
988                                                  long *pVideoHeight) {
989     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
990
991     TRACE("(%p/%p)->(%p)\n", This, iface, pVideoHeight);
992
993     *pVideoHeight = This->VideoHeight;
994
995     return S_OK;
996 }
997
998 static HRESULT WINAPI Basicvideo_put_SourceLeft(IBasicVideo *iface,
999                                                 long SourceLeft) {
1000     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1001
1002     TRACE("(%p/%p)->(%ld)\n", This, iface, SourceLeft);
1003
1004     This->SourceRect.left = SourceLeft;
1005
1006     return S_OK;
1007 }
1008
1009 static HRESULT WINAPI Basicvideo_get_SourceLeft(IBasicVideo *iface,
1010                                                 long *pSourceLeft) {
1011     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1012
1013     TRACE("(%p/%p)->(%p)\n", This, iface, pSourceLeft);
1014
1015     *pSourceLeft = This->SourceRect.left;
1016
1017     return S_OK;
1018 }
1019
1020 static HRESULT WINAPI Basicvideo_put_SourceWidth(IBasicVideo *iface,
1021                                                  long SourceWidth) {
1022     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1023
1024     TRACE("(%p/%p)->(%ld)\n", This, iface, SourceWidth);
1025
1026     This->SourceRect.right = This->SourceRect.left + SourceWidth;
1027
1028     return S_OK;
1029 }
1030
1031 static HRESULT WINAPI Basicvideo_get_SourceWidth(IBasicVideo *iface,
1032                                                  long *pSourceWidth) {
1033     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1034
1035     TRACE("(%p/%p)->(%p)\n", This, iface, pSourceWidth);
1036
1037     *pSourceWidth = This->SourceRect.right - This->SourceRect.left;
1038     
1039     return S_OK;
1040 }
1041
1042 static HRESULT WINAPI Basicvideo_put_SourceTop(IBasicVideo *iface,
1043                                                long SourceTop) {
1044     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1045
1046     TRACE("(%p/%p)->(%ld)\n", This, iface, SourceTop);
1047
1048     This->SourceRect.top = SourceTop;
1049
1050     return S_OK;
1051 }
1052
1053 static HRESULT WINAPI Basicvideo_get_SourceTop(IBasicVideo *iface,
1054                                                long *pSourceTop) {
1055     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1056
1057     TRACE("(%p/%p)->(%p)\n", This, iface, pSourceTop);
1058
1059     *pSourceTop = This->SourceRect.top;
1060
1061     return S_OK;
1062 }
1063
1064 static HRESULT WINAPI Basicvideo_put_SourceHeight(IBasicVideo *iface,
1065                                                   long SourceHeight) {
1066     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1067
1068     TRACE("(%p/%p)->(%ld)\n", This, iface, SourceHeight);
1069
1070     This->SourceRect.bottom = This->SourceRect.top + SourceHeight;
1071
1072     return S_OK;
1073 }
1074
1075 static HRESULT WINAPI Basicvideo_get_SourceHeight(IBasicVideo *iface,
1076                                                   long *pSourceHeight) {
1077     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1078
1079     TRACE("(%p/%p)->(%p)\n", This, iface, pSourceHeight);
1080
1081     *pSourceHeight = This->SourceRect.bottom - This->SourceRect.top;
1082
1083     return S_OK;
1084 }
1085
1086 static HRESULT WINAPI Basicvideo_put_DestinationLeft(IBasicVideo *iface,
1087                                                      long DestinationLeft) {
1088     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1089
1090     TRACE("(%p/%p)->(%ld)\n", This, iface, DestinationLeft);
1091
1092     This->DestRect.left = DestinationLeft;
1093
1094     return S_OK;
1095 }
1096
1097 static HRESULT WINAPI Basicvideo_get_DestinationLeft(IBasicVideo *iface,
1098                                                      long *pDestinationLeft) {
1099     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1100
1101     TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationLeft);
1102
1103     *pDestinationLeft = This->DestRect.left;
1104
1105     return S_OK;
1106 }
1107
1108 static HRESULT WINAPI Basicvideo_put_DestinationWidth(IBasicVideo *iface,
1109                                                       long DestinationWidth) {
1110     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1111
1112     TRACE("(%p/%p)->(%ld)\n", This, iface, DestinationWidth);
1113
1114     This->DestRect.right = This->DestRect.left + DestinationWidth;
1115
1116     return S_OK;
1117 }
1118
1119 static HRESULT WINAPI Basicvideo_get_DestinationWidth(IBasicVideo *iface,
1120                                                       long *pDestinationWidth) {
1121     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1122
1123     TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationWidth);
1124
1125     *pDestinationWidth = This->DestRect.right - This->DestRect.left;
1126
1127     return S_OK;
1128 }
1129
1130 static HRESULT WINAPI Basicvideo_put_DestinationTop(IBasicVideo *iface,
1131                                                     long DestinationTop) {
1132     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1133
1134     TRACE("(%p/%p)->(%ld)\n", This, iface, DestinationTop);
1135
1136     This->DestRect.top = DestinationTop;
1137     
1138     return S_OK;
1139 }
1140
1141 static HRESULT WINAPI Basicvideo_get_DestinationTop(IBasicVideo *iface,
1142                                                     long *pDestinationTop) {
1143     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1144
1145     TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationTop);
1146
1147     *pDestinationTop = This->DestRect.top;
1148
1149     return S_OK;
1150 }
1151
1152 static HRESULT WINAPI Basicvideo_put_DestinationHeight(IBasicVideo *iface,
1153                                                        long DestinationHeight) {
1154     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1155
1156     TRACE("(%p/%p)->(%ld)\n", This, iface, DestinationHeight);
1157
1158     This->DestRect.right = This->DestRect.left + DestinationHeight;
1159
1160     return S_OK;
1161 }
1162
1163 static HRESULT WINAPI Basicvideo_get_DestinationHeight(IBasicVideo *iface,
1164                                                        long *pDestinationHeight) {
1165     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1166
1167     TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationHeight);
1168
1169     *pDestinationHeight = This->DestRect.right - This->DestRect.left;
1170
1171     return S_OK;
1172 }
1173
1174 static HRESULT WINAPI Basicvideo_SetSourcePosition(IBasicVideo *iface,
1175                                                    long Left,
1176                                                    long Top,
1177                                                    long Width,
1178                                                    long Height) {
1179     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1180
1181     TRACE("(%p/%p)->(%ld, %ld, %ld, %ld)\n", This, iface, Left, Top, Width, Height);
1182
1183     This->SourceRect.left = Left;
1184     This->SourceRect.top = Top;
1185     This->SourceRect.right = Left + Width;
1186     This->SourceRect.bottom = Top + Height;
1187     
1188     return S_OK;
1189 }
1190
1191 static HRESULT WINAPI Basicvideo_GetSourcePosition(IBasicVideo *iface,
1192                                                    long *pLeft,
1193                                                    long *pTop,
1194                                                    long *pWidth,
1195                                                    long *pHeight) {
1196     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1197
1198     TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight);
1199
1200     *pLeft = This->SourceRect.left;
1201     *pTop = This->SourceRect.top;
1202     *pWidth = This->SourceRect.right - This->SourceRect.left;
1203     *pHeight = This->SourceRect.bottom - This->SourceRect.top;
1204     
1205     return S_OK;
1206 }
1207
1208 static HRESULT WINAPI Basicvideo_SetDefaultSourcePosition(IBasicVideo *iface) {
1209     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1210
1211     TRACE("(%p/%p)->()\n", This, iface);
1212
1213     This->SourceRect.left = 0;
1214     This->SourceRect.top = 0;
1215     This->SourceRect.right = This->VideoWidth;
1216     This->SourceRect.bottom = This->VideoHeight;
1217
1218     return S_OK;
1219 }
1220
1221 static HRESULT WINAPI Basicvideo_SetDestinationPosition(IBasicVideo *iface,
1222                                                         long Left,
1223                                                         long Top,
1224                                                         long Width,
1225                                                         long Height) {
1226     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1227
1228     TRACE("(%p/%p)->(%ld, %ld, %ld, %ld)\n", This, iface, Left, Top, Width, Height);
1229
1230     This->DestRect.left = Left;
1231     This->DestRect.top = Top;
1232     This->DestRect.right = Left + Width;
1233     This->DestRect.bottom = Top + Height;
1234
1235     return S_OK;
1236 }
1237
1238 static HRESULT WINAPI Basicvideo_GetDestinationPosition(IBasicVideo *iface,
1239                                                         long *pLeft,
1240                                                         long *pTop,
1241                                                         long *pWidth,
1242                                                         long *pHeight) {
1243     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1244
1245     TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight);
1246
1247     *pLeft = This->DestRect.left;
1248     *pTop = This->DestRect.top;
1249     *pWidth = This->DestRect.right - This->DestRect.left;
1250     *pHeight = This->DestRect.bottom - This->DestRect.top;
1251
1252     return S_OK;
1253 }
1254
1255 static HRESULT WINAPI Basicvideo_SetDefaultDestinationPosition(IBasicVideo *iface) {
1256     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1257     RECT rect;
1258
1259     TRACE("(%p/%p)->()\n", This, iface);
1260
1261     if (!GetClientRect(This->hWnd, &rect))
1262         return E_FAIL;
1263     
1264     This->SourceRect.left = 0;
1265     This->SourceRect.top = 0;
1266     This->SourceRect.right = rect.right;
1267     This->SourceRect.bottom = rect.bottom;
1268     
1269     return S_OK;
1270 }
1271
1272 static HRESULT WINAPI Basicvideo_GetVideoSize(IBasicVideo *iface,
1273                                               long *pWidth,
1274                                               long *pHeight) {
1275     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1276
1277     TRACE("(%p/%p)->(%p, %p)\n", This, iface, pWidth, pHeight);
1278
1279     *pWidth = This->VideoWidth;
1280     *pHeight = This->VideoHeight;
1281     
1282     return S_OK;
1283 }
1284
1285 static HRESULT WINAPI Basicvideo_GetVideoPaletteEntries(IBasicVideo *iface,
1286                                                         long StartIndex,
1287                                                         long Entries,
1288                                                         long *pRetrieved,
1289                                                         long *pPalette) {
1290     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1291
1292     FIXME("(%p/%p)->(%ld, %ld, %p, %p): stub !!!\n", This, iface, StartIndex, Entries, pRetrieved, pPalette);
1293
1294     return S_OK;
1295 }
1296
1297 static HRESULT WINAPI Basicvideo_GetCurrentImage(IBasicVideo *iface,
1298                                                  long *pBufferSize,
1299                                                  long *pDIBImage) {
1300     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1301
1302     FIXME("(%p/%p)->(%p, %p): stub !!!\n", This, iface, pBufferSize, pDIBImage);
1303
1304     return S_OK;
1305 }
1306
1307 static HRESULT WINAPI Basicvideo_IsUsingDefaultSource(IBasicVideo *iface) {
1308     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1309
1310     FIXME("(%p/%p)->(): stub !!!\n", This, iface);
1311
1312     return S_OK;
1313 }
1314
1315 static HRESULT WINAPI Basicvideo_IsUsingDefaultDestination(IBasicVideo *iface) {
1316     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1317
1318     FIXME("(%p/%p)->(): stub !!!\n", This, iface);
1319
1320     return S_OK;
1321 }
1322
1323
1324 static const IBasicVideoVtbl IBasicVideo_VTable =
1325 {
1326     Basicvideo_QueryInterface,
1327     Basicvideo_AddRef,
1328     Basicvideo_Release,
1329     Basicvideo_GetTypeInfoCount,
1330     Basicvideo_GetTypeInfo,
1331     Basicvideo_GetIDsOfNames,
1332     Basicvideo_Invoke,
1333     Basicvideo_get_AvgTimePerFrame,
1334     Basicvideo_get_BitRate,
1335     Basicvideo_get_BitErrorRate,
1336     Basicvideo_get_VideoWidth,
1337     Basicvideo_get_VideoHeight,
1338     Basicvideo_put_SourceLeft,
1339     Basicvideo_get_SourceLeft,
1340     Basicvideo_put_SourceWidth,
1341     Basicvideo_get_SourceWidth,
1342     Basicvideo_put_SourceTop,
1343     Basicvideo_get_SourceTop,
1344     Basicvideo_put_SourceHeight,
1345     Basicvideo_get_SourceHeight,
1346     Basicvideo_put_DestinationLeft,
1347     Basicvideo_get_DestinationLeft,
1348     Basicvideo_put_DestinationWidth,
1349     Basicvideo_get_DestinationWidth,
1350     Basicvideo_put_DestinationTop,
1351     Basicvideo_get_DestinationTop,
1352     Basicvideo_put_DestinationHeight,
1353     Basicvideo_get_DestinationHeight,
1354     Basicvideo_SetSourcePosition,
1355     Basicvideo_GetSourcePosition,
1356     Basicvideo_SetDefaultSourcePosition,
1357     Basicvideo_SetDestinationPosition,
1358     Basicvideo_GetDestinationPosition,
1359     Basicvideo_SetDefaultDestinationPosition,
1360     Basicvideo_GetVideoSize,
1361     Basicvideo_GetVideoPaletteEntries,
1362     Basicvideo_GetCurrentImage,
1363     Basicvideo_IsUsingDefaultSource,
1364     Basicvideo_IsUsingDefaultDestination
1365 };
1366
1367
1368 /*** IUnknown methods ***/
1369 static HRESULT WINAPI Videowindow_QueryInterface(IVideoWindow *iface,
1370                                                  REFIID riid,
1371                                                  LPVOID*ppvObj) {
1372     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1373
1374     TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
1375
1376     return VideoRenderer_QueryInterface((IBaseFilter*)This, riid, ppvObj);
1377 }
1378
1379 static ULONG WINAPI Videowindow_AddRef(IVideoWindow *iface) {
1380     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1381
1382     TRACE("(%p/%p)->()\n", This, iface);
1383
1384     return VideoRenderer_AddRef((IBaseFilter*)This);
1385 }
1386
1387 static ULONG WINAPI Videowindow_Release(IVideoWindow *iface) {
1388     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1389
1390     TRACE("(%p/%p)->()\n", This, iface);
1391
1392     return VideoRenderer_Release((IBaseFilter*)This);
1393 }
1394
1395 /*** IDispatch methods ***/
1396 static HRESULT WINAPI Videowindow_GetTypeInfoCount(IVideoWindow *iface,
1397                                                    UINT*pctinfo) {
1398     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1399
1400     FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, pctinfo);
1401
1402     return S_OK;
1403 }
1404
1405 static HRESULT WINAPI Videowindow_GetTypeInfo(IVideoWindow *iface,
1406                                               UINT iTInfo,
1407                                               LCID lcid,
1408                                               ITypeInfo**ppTInfo) {
1409     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1410
1411     FIXME("(%p/%p)->(%d, %d, %p): stub !!!\n", This, iface, iTInfo, lcid, ppTInfo);
1412
1413     return S_OK;
1414 }
1415
1416 static HRESULT WINAPI Videowindow_GetIDsOfNames(IVideoWindow *iface,
1417                                                 REFIID riid,
1418                                                 LPOLESTR*rgszNames,
1419                                                 UINT cNames,
1420                                                 LCID lcid,
1421                                                 DISPID*rgDispId) {
1422     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1423
1424     FIXME("(%p/%p)->(%s (%p), %p, %d, %d, %p): stub !!!\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
1425
1426     return S_OK;
1427 }
1428
1429 static HRESULT WINAPI Videowindow_Invoke(IVideoWindow *iface,
1430                                          DISPID dispIdMember,
1431                                          REFIID riid,
1432                                          LCID lcid,
1433                                          WORD wFlags,
1434                                          DISPPARAMS*pDispParams,
1435                                          VARIANT*pVarResult,
1436                                          EXCEPINFO*pExepInfo,
1437                                          UINT*puArgErr) {
1438     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1439
1440     FIXME("(%p/%p)->(%d, %s (%p), %d, %04x, %p, %p, %p, %p): stub !!!\n", This, iface, dispIdMember, debugstr_guid(riid), riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
1441
1442     return S_OK;
1443 }
1444
1445 /*** IVideoWindow methods ***/
1446 static HRESULT WINAPI Videowindow_put_Caption(IVideoWindow *iface,
1447                                               BSTR strCaption) {
1448     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1449
1450     TRACE("(%p/%p)->(%s (%p))\n", This, iface, debugstr_w(strCaption), strCaption);
1451
1452     if (!SetWindowTextW(This->hWnd, strCaption))
1453         return E_FAIL;
1454
1455     return S_OK;
1456 }
1457
1458 static HRESULT WINAPI Videowindow_get_Caption(IVideoWindow *iface,
1459                                               BSTR *strCaption) {
1460     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1461
1462     TRACE("(%p/%p)->(%p)\n", This, iface, strCaption);
1463
1464     GetWindowTextW(This->hWnd, (LPWSTR)strCaption, 100);
1465
1466     return S_OK;
1467 }
1468
1469 static HRESULT WINAPI Videowindow_put_WindowStyle(IVideoWindow *iface,
1470                                                   long WindowStyle) {
1471     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1472     LONG old;
1473
1474     old = GetWindowLongA(This->hWnd, GWL_STYLE);
1475     
1476     TRACE("(%p/%p)->(%x -> %lx)\n", This, iface, old, WindowStyle);
1477
1478     if (WindowStyle & (WS_DISABLED|WS_HSCROLL|WS_ICONIC|WS_MAXIMIZE|WS_MINIMIZE|WS_VSCROLL))
1479         return E_INVALIDARG;
1480     
1481     SetWindowLongA(This->hWnd, GWL_STYLE, WindowStyle);
1482
1483     return S_OK;
1484 }
1485
1486 static HRESULT WINAPI Videowindow_get_WindowStyle(IVideoWindow *iface,
1487                                                   long *WindowStyle) {
1488     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1489
1490     TRACE("(%p/%p)->(%p)\n", This, iface, WindowStyle);
1491
1492     *WindowStyle = GetWindowLongA(This->hWnd, GWL_STYLE);
1493
1494     return S_OK;
1495 }
1496
1497 static HRESULT WINAPI Videowindow_put_WindowStyleEx(IVideoWindow *iface,
1498                                                     long WindowStyleEx) {
1499     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1500
1501     TRACE("(%p/%p)->(%ld)\n", This, iface, WindowStyleEx);
1502
1503     if (WindowStyleEx & (WS_DISABLED|WS_HSCROLL|WS_ICONIC|WS_MAXIMIZE|WS_MINIMIZE|WS_VSCROLL))
1504         return E_INVALIDARG;
1505
1506     if (!SetWindowLongA(This->hWnd, GWL_EXSTYLE, WindowStyleEx))
1507         return E_FAIL;
1508
1509     return S_OK;
1510 }
1511
1512 static HRESULT WINAPI Videowindow_get_WindowStyleEx(IVideoWindow *iface,
1513                                                     long *WindowStyleEx) {
1514     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1515
1516     TRACE("(%p/%p)->(%p)\n", This, iface, WindowStyleEx);
1517
1518     *WindowStyleEx = GetWindowLongA(This->hWnd, GWL_EXSTYLE);
1519
1520     return S_OK;
1521 }
1522
1523 static HRESULT WINAPI Videowindow_put_AutoShow(IVideoWindow *iface,
1524                                                long AutoShow) {
1525     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1526
1527     TRACE("(%p/%p)->(%ld)\n", This, iface, AutoShow);
1528
1529     This->AutoShow = 1; /* FXIME: Should be AutoShow */;
1530
1531     return S_OK;
1532 }
1533
1534 static HRESULT WINAPI Videowindow_get_AutoShow(IVideoWindow *iface,
1535                                                long *AutoShow) {
1536     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1537
1538     TRACE("(%p/%p)->(%p)\n", This, iface, AutoShow);
1539
1540     *AutoShow = This->AutoShow;
1541
1542     return S_OK;
1543 }
1544
1545 static HRESULT WINAPI Videowindow_put_WindowState(IVideoWindow *iface,
1546                                                   long WindowState) {
1547     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1548
1549     FIXME("(%p/%p)->(%ld): stub !!!\n", This, iface, WindowState);
1550
1551     return S_OK;
1552 }
1553
1554 static HRESULT WINAPI Videowindow_get_WindowState(IVideoWindow *iface,
1555                                                   long *WindowState) {
1556     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1557
1558     FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, WindowState);
1559
1560     return S_OK;
1561 }
1562
1563 static HRESULT WINAPI Videowindow_put_BackgroundPalette(IVideoWindow *iface,
1564                                                         long BackgroundPalette) {
1565     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1566
1567     FIXME("(%p/%p)->(%ld): stub !!!\n", This, iface, BackgroundPalette);
1568
1569     return S_OK;
1570 }
1571
1572 static HRESULT WINAPI Videowindow_get_BackgroundPalette(IVideoWindow *iface,
1573                                                         long *pBackgroundPalette) {
1574     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1575
1576     FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, pBackgroundPalette);
1577
1578     return S_OK;
1579 }
1580
1581 static HRESULT WINAPI Videowindow_put_Visible(IVideoWindow *iface,
1582                                               long Visible) {
1583     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1584
1585     TRACE("(%p/%p)->(%ld)\n", This, iface, Visible);
1586
1587     ShowWindow(This->hWnd, Visible ? SW_SHOW : SW_HIDE);
1588
1589     return S_OK;
1590 }
1591
1592 static HRESULT WINAPI Videowindow_get_Visible(IVideoWindow *iface,
1593                                               long *pVisible) {
1594     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1595
1596     TRACE("(%p/%p)->(%p)\n", This, iface, pVisible);
1597
1598     *pVisible = IsWindowVisible(This->hWnd);
1599
1600     return S_OK;
1601 }
1602
1603 static HRESULT WINAPI Videowindow_put_Left(IVideoWindow *iface,
1604                                            long Left) {
1605     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1606
1607     TRACE("(%p/%p)->(%ld)\n", This, iface, Left);
1608
1609     if (!SetWindowPos(This->hWnd, NULL, Left, This->WindowPos.top, 0, 0, SWP_NOZORDER|SWP_NOSIZE))
1610         return E_FAIL;
1611
1612     This->WindowPos.left = Left;
1613
1614     return S_OK;
1615 }
1616
1617 static HRESULT WINAPI Videowindow_get_Left(IVideoWindow *iface,
1618                                            long *pLeft) {
1619     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1620
1621     TRACE("(%p/%p)->(%p)\n", This, iface, pLeft);
1622
1623     *pLeft = This->WindowPos.left;
1624
1625     return S_OK;
1626 }
1627
1628 static HRESULT WINAPI Videowindow_put_Width(IVideoWindow *iface,
1629                                             long Width) {
1630     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1631
1632     TRACE("(%p/%p)->(%ld)\n", This, iface, Width);
1633
1634     if (!SetWindowPos(This->hWnd, NULL, 0, 0, Width, This->WindowPos.bottom-This->WindowPos.top, SWP_NOZORDER|SWP_NOMOVE))
1635         return E_FAIL;
1636
1637     This->WindowPos.right = This->WindowPos.left + Width;
1638
1639     return S_OK;
1640 }
1641
1642 static HRESULT WINAPI Videowindow_get_Width(IVideoWindow *iface,
1643                                             long *pWidth) {
1644     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1645
1646     TRACE("(%p/%p)->(%p)\n", This, iface, pWidth);
1647
1648     *pWidth = This->WindowPos.right - This->WindowPos.left;
1649
1650     return S_OK;
1651 }
1652
1653 static HRESULT WINAPI Videowindow_put_Top(IVideoWindow *iface,
1654                                           long Top) {
1655     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1656
1657     TRACE("(%p/%p)->(%ld)\n", This, iface, Top);
1658
1659     if (!SetWindowPos(This->hWnd, NULL, This->WindowPos.left, Top, 0, 0, SWP_NOZORDER|SWP_NOSIZE))
1660         return E_FAIL;
1661
1662     This->WindowPos.top = Top;
1663
1664     return S_OK;
1665 }
1666
1667 static HRESULT WINAPI Videowindow_get_Top(IVideoWindow *iface,
1668                                           long *pTop) {
1669     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1670
1671     TRACE("(%p/%p)->(%p)\n", This, iface, pTop);
1672
1673     *pTop = This->WindowPos.top;
1674
1675     return S_OK;
1676 }
1677
1678 static HRESULT WINAPI Videowindow_put_Height(IVideoWindow *iface,
1679                                              long Height) {
1680     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1681
1682     TRACE("(%p/%p)->(%ld)\n", This, iface, Height);
1683
1684     if (!SetWindowPos(This->hWnd, NULL, 0, 0, This->WindowPos.right-This->WindowPos.left, Height, SWP_NOZORDER|SWP_NOMOVE))
1685         return E_FAIL;
1686
1687     This->WindowPos.bottom = This->WindowPos.top + Height;
1688
1689     return S_OK;
1690 }
1691
1692 static HRESULT WINAPI Videowindow_get_Height(IVideoWindow *iface,
1693                                              long *pHeight) {
1694     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1695
1696     TRACE("(%p/%p)->(%p)\n", This, iface, pHeight);
1697
1698     *pHeight = This->WindowPos.bottom - This->WindowPos.top;
1699
1700     return S_OK;
1701 }
1702
1703 static HRESULT WINAPI Videowindow_put_Owner(IVideoWindow *iface,
1704                                             OAHWND Owner) {
1705     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1706
1707     TRACE("(%p/%p)->(%08x)\n", This, iface, (DWORD) Owner);
1708
1709     SetParent(This->hWnd, (HWND)Owner);
1710
1711     return S_OK;
1712 }
1713
1714 static HRESULT WINAPI Videowindow_get_Owner(IVideoWindow *iface,
1715                                             OAHWND *Owner) {
1716     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1717
1718     TRACE("(%p/%p)->(%08x)\n", This, iface, (DWORD) Owner);
1719
1720     *(HWND*)Owner = GetParent(This->hWnd);
1721
1722     return S_OK;
1723 }
1724
1725 static HRESULT WINAPI Videowindow_put_MessageDrain(IVideoWindow *iface,
1726                                                    OAHWND Drain) {
1727     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1728
1729     TRACE("(%p/%p)->(%08x)\n", This, iface, (DWORD) Drain);
1730
1731     This->hWndMsgDrain = (HWND)Drain;
1732
1733     return S_OK;
1734 }
1735
1736 static HRESULT WINAPI Videowindow_get_MessageDrain(IVideoWindow *iface,
1737                                                    OAHWND *Drain) {
1738     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1739
1740     TRACE("(%p/%p)->(%p)\n", This, iface, Drain);
1741
1742     *Drain = (OAHWND)This->hWndMsgDrain;
1743
1744     return S_OK;
1745 }
1746
1747 static HRESULT WINAPI Videowindow_get_BorderColor(IVideoWindow *iface,
1748                                                   long *Color) {
1749     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1750
1751     FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, Color);
1752
1753     return S_OK;
1754 }
1755
1756 static HRESULT WINAPI Videowindow_put_BorderColor(IVideoWindow *iface,
1757                                                   long Color) {
1758     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1759
1760     FIXME("(%p/%p)->(%ld): stub !!!\n", This, iface, Color);
1761
1762     return S_OK;
1763 }
1764
1765 static HRESULT WINAPI Videowindow_get_FullScreenMode(IVideoWindow *iface,
1766                                                      long *FullScreenMode) {
1767     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1768
1769     FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, FullScreenMode);
1770
1771     return S_OK;
1772 }
1773
1774 static HRESULT WINAPI Videowindow_put_FullScreenMode(IVideoWindow *iface,
1775                                                      long FullScreenMode) {
1776     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1777
1778     FIXME("(%p/%p)->(%ld): stub !!!\n", This, iface, FullScreenMode);
1779
1780     return S_OK;
1781 }
1782
1783 static HRESULT WINAPI Videowindow_SetWindowForeground(IVideoWindow *iface,
1784                                                       long Focus) {
1785     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1786     BOOL ret;
1787     IPin* pPin;
1788     HRESULT hr;
1789
1790     TRACE("(%p/%p)->(%ld)\n", This, iface, Focus);
1791
1792     if ((Focus != FALSE) && (Focus != TRUE))
1793         return E_INVALIDARG;
1794
1795     hr = IPin_ConnectedTo(This->ppPins[0], &pPin);
1796     if ((hr != S_OK) || !pPin)
1797         return VFW_E_NOT_CONNECTED;
1798
1799     if (Focus)
1800         ret = SetForegroundWindow(This->hWnd);
1801     else
1802         ret = SetWindowPos(This->hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
1803
1804     if (!ret)
1805         return E_FAIL;
1806
1807     return S_OK;
1808 }
1809
1810 static HRESULT WINAPI Videowindow_NotifyOwnerMessage(IVideoWindow *iface,
1811                                                      OAHWND hwnd,
1812                                                      long uMsg,
1813                                                      LONG_PTR wParam,
1814                                                      LONG_PTR lParam) {
1815     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1816
1817     TRACE("(%p/%p)->(%08x, %ld, %08lx, %08lx)\n", This, iface, (DWORD) hwnd, uMsg, wParam, lParam);
1818
1819     if (!PostMessageA(This->hWnd, uMsg, wParam, lParam))
1820         return E_FAIL;
1821     
1822     return S_OK;
1823 }
1824
1825 static HRESULT WINAPI Videowindow_SetWindowPosition(IVideoWindow *iface,
1826                                                     long Left,
1827                                                     long Top,
1828                                                     long Width,
1829                                                     long Height) {
1830     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1831     
1832     TRACE("(%p/%p)->(%ld, %ld, %ld, %ld)\n", This, iface, Left, Top, Width, Height);
1833
1834     if (!SetWindowPos(This->hWnd, NULL, Left, Top, Width, Height, SWP_NOZORDER))
1835         return E_FAIL;
1836
1837     This->WindowPos.left = Left;
1838     This->WindowPos.top = Top;
1839     This->WindowPos.right = Left + Width;
1840     This->WindowPos.bottom = Top + Height;
1841     
1842     return S_OK;
1843 }
1844
1845 static HRESULT WINAPI Videowindow_GetWindowPosition(IVideoWindow *iface,
1846                                                     long *pLeft,
1847                                                     long *pTop,
1848                                                     long *pWidth,
1849                                                     long *pHeight) {
1850     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1851
1852     TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight);
1853
1854     *pLeft = This->WindowPos.left;
1855     *pTop = This->WindowPos.top;
1856     *pWidth = This->WindowPos.right - This->WindowPos.left;
1857     *pHeight = This->WindowPos.bottom - This->WindowPos.top;
1858
1859     return S_OK;
1860 }
1861
1862 static HRESULT WINAPI Videowindow_GetMinIdealImageSize(IVideoWindow *iface,
1863                                                        long *pWidth,
1864                                                        long *pHeight) {
1865     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1866
1867     FIXME("(%p/%p)->(%p, %p): semi stub !!!\n", This, iface, pWidth, pHeight);
1868
1869     *pWidth = This->VideoWidth;
1870     *pHeight = This->VideoHeight;
1871
1872     return S_OK;
1873 }
1874
1875 static HRESULT WINAPI Videowindow_GetMaxIdealImageSize(IVideoWindow *iface,
1876                                                        long *pWidth,
1877                                                        long *pHeight) {
1878     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1879
1880     FIXME("(%p/%p)->(%p, %p): semi stub !!!\n", This, iface, pWidth, pHeight);
1881
1882     *pWidth = This->VideoWidth;
1883     *pHeight = This->VideoHeight;
1884
1885     return S_OK;
1886 }
1887
1888 static HRESULT WINAPI Videowindow_GetRestorePosition(IVideoWindow *iface,
1889                                                      long *pLeft,
1890                                                      long *pTop,
1891                                                      long *pWidth,
1892                                                      long *pHeight) {
1893     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1894
1895     FIXME("(%p/%p)->(%p, %p, %p, %p): stub !!!\n", This, iface, pLeft, pTop, pWidth, pHeight);
1896
1897     return S_OK;
1898 }
1899
1900 static HRESULT WINAPI Videowindow_HideCursor(IVideoWindow *iface,
1901                                              long HideCursor) {
1902     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1903
1904     FIXME("(%p/%p)->(%ld): stub !!!\n", This, iface, HideCursor);
1905
1906     return S_OK;
1907 }
1908
1909 static HRESULT WINAPI Videowindow_IsCursorHidden(IVideoWindow *iface,
1910                                                  long *CursorHidden) {
1911     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1912
1913     FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, CursorHidden);
1914
1915     return S_OK;
1916 }
1917
1918 static const IVideoWindowVtbl IVideoWindow_VTable =
1919 {
1920     Videowindow_QueryInterface,
1921     Videowindow_AddRef,
1922     Videowindow_Release,
1923     Videowindow_GetTypeInfoCount,
1924     Videowindow_GetTypeInfo,
1925     Videowindow_GetIDsOfNames,
1926     Videowindow_Invoke,
1927     Videowindow_put_Caption,
1928     Videowindow_get_Caption,
1929     Videowindow_put_WindowStyle,
1930     Videowindow_get_WindowStyle,
1931     Videowindow_put_WindowStyleEx,
1932     Videowindow_get_WindowStyleEx,
1933     Videowindow_put_AutoShow,
1934     Videowindow_get_AutoShow,
1935     Videowindow_put_WindowState,
1936     Videowindow_get_WindowState,
1937     Videowindow_put_BackgroundPalette,
1938     Videowindow_get_BackgroundPalette,
1939     Videowindow_put_Visible,
1940     Videowindow_get_Visible,
1941     Videowindow_put_Left,
1942     Videowindow_get_Left,
1943     Videowindow_put_Width,
1944     Videowindow_get_Width,
1945     Videowindow_put_Top,
1946     Videowindow_get_Top,
1947     Videowindow_put_Height,
1948     Videowindow_get_Height,
1949     Videowindow_put_Owner,
1950     Videowindow_get_Owner,
1951     Videowindow_put_MessageDrain,
1952     Videowindow_get_MessageDrain,
1953     Videowindow_get_BorderColor,
1954     Videowindow_put_BorderColor,
1955     Videowindow_get_FullScreenMode,
1956     Videowindow_put_FullScreenMode,
1957     Videowindow_SetWindowForeground,
1958     Videowindow_NotifyOwnerMessage,
1959     Videowindow_SetWindowPosition,
1960     Videowindow_GetWindowPosition,
1961     Videowindow_GetMinIdealImageSize,
1962     Videowindow_GetMaxIdealImageSize,
1963     Videowindow_GetRestorePosition,
1964     Videowindow_HideCursor,
1965     Videowindow_IsCursorHidden
1966 };