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