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