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