mfreadwrite/reader: Add missing allocation check (Coverity).
[wine/zf.git] / dlls / quartz / window.c
blob3983d43b08f51e987a9207e39297274f3e80c146
1 /*
2 * Common implementation of IVideoWindow
4 * Copyright 2012 Aric Stewart, CodeWeavers
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.
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.
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
21 #include "quartz_private.h"
23 WINE_DEFAULT_DEBUG_CHANNEL(quartz);
25 static const WCHAR class_name[] = L"wine_quartz_window";
27 static inline struct video_window *impl_from_IVideoWindow(IVideoWindow *iface)
29 return CONTAINING_RECORD(iface, struct video_window, IVideoWindow_iface);
32 static LRESULT CALLBACK WndProcW(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
34 struct video_window *window = (struct video_window *)GetWindowLongPtrW(hwnd, 0);
36 if (!window)
37 return DefWindowProcW(hwnd, message, wparam, lparam);
39 switch (message)
41 case WM_KEYDOWN:
42 case WM_KEYUP:
43 case WM_LBUTTONDBLCLK:
44 case WM_LBUTTONDOWN:
45 case WM_LBUTTONUP:
46 case WM_MBUTTONDBLCLK:
47 case WM_MBUTTONDOWN:
48 case WM_MBUTTONUP:
49 case WM_MOUSEACTIVATE:
50 case WM_MOUSEMOVE:
51 case WM_NCLBUTTONDBLCLK:
52 case WM_NCLBUTTONDOWN:
53 case WM_NCLBUTTONUP:
54 case WM_NCMBUTTONDBLCLK:
55 case WM_NCMBUTTONDOWN:
56 case WM_NCMBUTTONUP:
57 case WM_NCMOUSEMOVE:
58 case WM_NCRBUTTONDBLCLK:
59 case WM_NCRBUTTONDOWN:
60 case WM_NCRBUTTONUP:
61 case WM_RBUTTONDBLCLK:
62 case WM_RBUTTONDOWN:
63 case WM_RBUTTONUP:
64 if (window->hwndDrain)
66 PostMessageW(window->hwndDrain, message, wparam, lparam);
67 return 0;
69 break;
70 case WM_SIZE:
71 if (window->default_dst)
72 GetClientRect(window->hwnd, &window->dst);
73 break;
76 return DefWindowProcW(hwnd, message, wparam, lparam);
79 HRESULT video_window_create_window(struct video_window *window)
81 WNDCLASSW winclass = {0};
83 winclass.lpfnWndProc = WndProcW;
84 winclass.cbWndExtra = sizeof(window);
85 winclass.hbrBackground = GetStockObject(BLACK_BRUSH);
86 winclass.lpszClassName = class_name;
87 if (!RegisterClassW(&winclass) && GetLastError() != ERROR_CLASS_ALREADY_EXISTS)
89 ERR("Unable to register window class: %u\n", GetLastError());
90 return E_FAIL;
93 if (!(window->hwnd = CreateWindowExW(0, class_name, L"ActiveMovie Window",
94 WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
95 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
96 NULL, NULL, NULL, NULL)))
98 ERR("Unable to create window\n");
99 return E_FAIL;
102 SetWindowLongPtrW(window->hwnd, 0, (LONG_PTR)window);
104 return S_OK;
107 HRESULT WINAPI BaseControlWindowImpl_QueryInterface(IVideoWindow *iface, REFIID iid, void **out)
109 struct video_window *window = impl_from_IVideoWindow(iface);
110 return IUnknown_QueryInterface(window->pFilter->outer_unk, iid, out);
113 ULONG WINAPI BaseControlWindowImpl_AddRef(IVideoWindow *iface)
115 struct video_window *window = impl_from_IVideoWindow(iface);
116 return IUnknown_AddRef(window->pFilter->outer_unk);
119 ULONG WINAPI BaseControlWindowImpl_Release(IVideoWindow *iface)
121 struct video_window *window = impl_from_IVideoWindow(iface);
122 return IUnknown_Release(window->pFilter->outer_unk);
125 HRESULT WINAPI BaseControlWindowImpl_GetTypeInfoCount(IVideoWindow *iface, UINT *count)
127 TRACE("iface %p, count %p.\n", iface, count);
128 *count = 1;
129 return S_OK;
132 HRESULT WINAPI BaseControlWindowImpl_GetTypeInfo(IVideoWindow *iface, UINT index,
133 LCID lcid, ITypeInfo **typeinfo)
135 TRACE("iface %p, index %u, lcid %#x, typeinfo %p.\n", iface, index, lcid, typeinfo);
136 return strmbase_get_typeinfo(IVideoWindow_tid, typeinfo);
139 HRESULT WINAPI BaseControlWindowImpl_GetIDsOfNames(IVideoWindow *iface, REFIID iid,
140 LPOLESTR *names, UINT count, LCID lcid, DISPID *ids)
142 ITypeInfo *typeinfo;
143 HRESULT hr;
145 TRACE("iface %p, iid %s, names %p, count %u, lcid %#x, ids %p.\n",
146 iface, debugstr_guid(iid), names, count, lcid, ids);
148 if (SUCCEEDED(hr = strmbase_get_typeinfo(IVideoWindow_tid, &typeinfo)))
150 hr = ITypeInfo_GetIDsOfNames(typeinfo, names, count, ids);
151 ITypeInfo_Release(typeinfo);
153 return hr;
156 HRESULT WINAPI BaseControlWindowImpl_Invoke(IVideoWindow *iface, DISPID id, REFIID iid, LCID lcid,
157 WORD flags, DISPPARAMS *params, VARIANT *result, EXCEPINFO *excepinfo, UINT *error_arg)
159 ITypeInfo *typeinfo;
160 HRESULT hr;
162 TRACE("iface %p, id %d, iid %s, lcid %#x, flags %#x, params %p, result %p, excepinfo %p, error_arg %p.\n",
163 iface, id, debugstr_guid(iid), lcid, flags, params, result, excepinfo, error_arg);
165 if (SUCCEEDED(hr = strmbase_get_typeinfo(IVideoWindow_tid, &typeinfo)))
167 hr = ITypeInfo_Invoke(typeinfo, iface, id, flags, params, result, excepinfo, error_arg);
168 ITypeInfo_Release(typeinfo);
170 return hr;
173 HRESULT WINAPI BaseControlWindowImpl_put_Caption(IVideoWindow *iface, BSTR caption)
175 struct video_window *window = impl_from_IVideoWindow(iface);
177 TRACE("window %p, caption %s.\n", window, debugstr_w(caption));
179 if (!SetWindowTextW(window->hwnd, caption))
180 return E_FAIL;
182 return S_OK;
185 HRESULT WINAPI BaseControlWindowImpl_get_Caption(IVideoWindow *iface, BSTR *caption)
187 struct video_window *window = impl_from_IVideoWindow(iface);
188 WCHAR *str;
189 int len;
191 TRACE("window %p, caption %p.\n", window, caption);
193 *caption = NULL;
195 len = GetWindowTextLengthW(window->hwnd) + 1;
196 if (!(str = heap_alloc(len * sizeof(WCHAR))))
197 return E_OUTOFMEMORY;
199 GetWindowTextW(window->hwnd, str, len);
200 *caption = SysAllocString(str);
201 heap_free(str);
202 return *caption ? S_OK : E_OUTOFMEMORY;
205 HRESULT WINAPI BaseControlWindowImpl_put_WindowStyle(IVideoWindow *iface, LONG style)
207 struct video_window *window = impl_from_IVideoWindow(iface);
209 TRACE("window %p, style %#x.\n", window, style);
211 if (style & (WS_DISABLED|WS_HSCROLL|WS_MAXIMIZE|WS_MINIMIZE|WS_VSCROLL))
212 return E_INVALIDARG;
214 SetWindowLongW(window->hwnd, GWL_STYLE, style);
215 SetWindowPos(window->hwnd, 0, 0, 0, 0, 0,
216 SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
217 return S_OK;
220 HRESULT WINAPI BaseControlWindowImpl_get_WindowStyle(IVideoWindow *iface, LONG *style)
222 struct video_window *window = impl_from_IVideoWindow(iface);
224 TRACE("window %p, style %p.\n", window, style);
226 *style = GetWindowLongW(window->hwnd, GWL_STYLE);
227 return S_OK;
230 HRESULT WINAPI BaseControlWindowImpl_put_WindowStyleEx(IVideoWindow *iface, LONG style)
232 struct video_window *window = impl_from_IVideoWindow(iface);
234 TRACE("window %p, style %#x.\n", window, style);
236 if (!SetWindowLongW(window->hwnd, GWL_EXSTYLE, style))
237 return E_FAIL;
238 return S_OK;
241 HRESULT WINAPI BaseControlWindowImpl_get_WindowStyleEx(IVideoWindow *iface, LONG *style)
243 struct video_window *window = impl_from_IVideoWindow(iface);
245 TRACE("window %p, style %p.\n", window, style);
247 *style = GetWindowLongW(window->hwnd, GWL_EXSTYLE);
248 return S_OK;
251 HRESULT WINAPI BaseControlWindowImpl_put_AutoShow(IVideoWindow *iface, LONG AutoShow)
253 struct video_window *This = impl_from_IVideoWindow(iface);
255 TRACE("(%p/%p)->(%d)\n", This, iface, AutoShow);
257 This->AutoShow = AutoShow;
259 return S_OK;
262 HRESULT WINAPI BaseControlWindowImpl_get_AutoShow(IVideoWindow *iface, LONG *AutoShow)
264 struct video_window *This = impl_from_IVideoWindow(iface);
266 TRACE("(%p/%p)->(%p)\n", This, iface, AutoShow);
268 *AutoShow = This->AutoShow;
270 return S_OK;
273 HRESULT WINAPI BaseControlWindowImpl_put_WindowState(IVideoWindow *iface, LONG state)
275 struct video_window *window = impl_from_IVideoWindow(iface);
277 TRACE("window %p, state %#x.\n", window, state);
279 ShowWindow(window->hwnd, state);
280 return S_OK;
283 HRESULT WINAPI BaseControlWindowImpl_get_WindowState(IVideoWindow *iface, LONG *state)
285 struct video_window *window = impl_from_IVideoWindow(iface);
286 DWORD style;
288 TRACE("window %p, state %p.\n", window, state);
290 style = GetWindowLongPtrW(window->hwnd, GWL_STYLE);
291 if (!(style & WS_VISIBLE))
292 *state = SW_HIDE;
293 else if (style & WS_MINIMIZE)
294 *state = SW_MINIMIZE;
295 else if (style & WS_MAXIMIZE)
296 *state = SW_MAXIMIZE;
297 else
298 *state = SW_SHOW;
300 return S_OK;
303 HRESULT WINAPI BaseControlWindowImpl_put_BackgroundPalette(IVideoWindow *iface, LONG BackgroundPalette)
305 struct video_window *This = impl_from_IVideoWindow(iface);
307 FIXME("(%p/%p)->(%d): stub !!!\n", This, iface, BackgroundPalette);
309 return S_OK;
312 HRESULT WINAPI BaseControlWindowImpl_get_BackgroundPalette(IVideoWindow *iface, LONG *pBackgroundPalette)
314 struct video_window *This = impl_from_IVideoWindow(iface);
316 FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, pBackgroundPalette);
318 return S_OK;
321 HRESULT WINAPI BaseControlWindowImpl_put_Visible(IVideoWindow *iface, LONG visible)
323 struct video_window *window = impl_from_IVideoWindow(iface);
325 TRACE("window %p, visible %d.\n", window, visible);
327 ShowWindow(window->hwnd, visible ? SW_SHOW : SW_HIDE);
328 return S_OK;
331 HRESULT WINAPI BaseControlWindowImpl_get_Visible(IVideoWindow *iface, LONG *visible)
333 struct video_window *window = impl_from_IVideoWindow(iface);
335 TRACE("window %p, visible %p.\n", window, visible);
337 if (!visible)
338 return E_POINTER;
340 *visible = IsWindowVisible(window->hwnd) ? OATRUE : OAFALSE;
341 return S_OK;
344 HRESULT WINAPI BaseControlWindowImpl_put_Left(IVideoWindow *iface, LONG left)
346 struct video_window *window = impl_from_IVideoWindow(iface);
347 RECT rect;
349 TRACE("window %p, left %d.\n", window, left);
351 GetWindowRect(window->hwnd, &rect);
352 if (!SetWindowPos(window->hwnd, NULL, left, rect.top, 0, 0,
353 SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE))
354 return E_FAIL;
356 return S_OK;
359 HRESULT WINAPI BaseControlWindowImpl_get_Left(IVideoWindow *iface, LONG *left)
361 struct video_window *window = impl_from_IVideoWindow(iface);
362 RECT rect;
364 TRACE("window %p, left %p.\n", window, left);
366 GetWindowRect(window->hwnd, &rect);
367 *left = rect.left;
368 return S_OK;
371 HRESULT WINAPI BaseControlWindowImpl_put_Width(IVideoWindow *iface, LONG width)
373 struct video_window *window = impl_from_IVideoWindow(iface);
374 RECT rect;
376 TRACE("window %p, width %d.\n", window, width);
378 GetWindowRect(window->hwnd, &rect);
379 if (!SetWindowPos(window->hwnd, NULL, 0, 0, width, rect.bottom - rect.top,
380 SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOMOVE))
381 return E_FAIL;
383 return S_OK;
386 HRESULT WINAPI BaseControlWindowImpl_get_Width(IVideoWindow *iface, LONG *width)
388 struct video_window *window = impl_from_IVideoWindow(iface);
389 RECT rect;
391 TRACE("window %p, width %p.\n", window, width);
393 GetWindowRect(window->hwnd, &rect);
394 *width = rect.right - rect.left;
395 return S_OK;
398 HRESULT WINAPI BaseControlWindowImpl_put_Top(IVideoWindow *iface, LONG top)
400 struct video_window *window = impl_from_IVideoWindow(iface);
401 RECT rect;
403 TRACE("window %p, top %d.\n", window, top);
405 GetWindowRect(window->hwnd, &rect);
406 if (!SetWindowPos(window->hwnd, NULL, rect.left, top, 0, 0,
407 SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE))
408 return E_FAIL;
410 return S_OK;
413 HRESULT WINAPI BaseControlWindowImpl_get_Top(IVideoWindow *iface, LONG *top)
415 struct video_window *window = impl_from_IVideoWindow(iface);
416 RECT rect;
418 TRACE("window %p, top %p.\n", window, top);
420 GetWindowRect(window->hwnd, &rect);
421 *top = rect.top;
422 return S_OK;
425 HRESULT WINAPI BaseControlWindowImpl_put_Height(IVideoWindow *iface, LONG height)
427 struct video_window *window = impl_from_IVideoWindow(iface);
428 RECT rect;
430 TRACE("window %p, height %d.\n", window, height);
432 GetWindowRect(window->hwnd, &rect);
433 if (!SetWindowPos(window->hwnd, NULL, 0, 0, rect.right - rect.left,
434 height, SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOMOVE))
435 return E_FAIL;
437 return S_OK;
440 HRESULT WINAPI BaseControlWindowImpl_get_Height(IVideoWindow *iface, LONG *height)
442 struct video_window *window = impl_from_IVideoWindow(iface);
443 RECT rect;
445 TRACE("window %p, height %p.\n", window, height);
447 GetWindowRect(window->hwnd, &rect);
448 *height = rect.bottom - rect.top;
449 return S_OK;
452 HRESULT WINAPI BaseControlWindowImpl_put_Owner(IVideoWindow *iface, OAHWND owner)
454 struct video_window *window = impl_from_IVideoWindow(iface);
455 HWND hwnd = window->hwnd;
457 TRACE("window %p, owner %#lx.\n", window, owner);
459 /* Make sure we are marked as WS_CHILD before reparenting ourselves, so that
460 * we do not steal focus. LEGO Island depends on this. */
462 window->hwndOwner = (HWND)owner;
463 if (owner)
464 SetWindowLongPtrW(hwnd, GWL_STYLE, GetWindowLongPtrW(hwnd, GWL_STYLE) | WS_CHILD);
465 else
466 SetWindowLongPtrW(hwnd, GWL_STYLE, GetWindowLongPtrW(hwnd, GWL_STYLE) & ~WS_CHILD);
467 SetParent(hwnd, (HWND)owner);
469 return S_OK;
472 HRESULT WINAPI BaseControlWindowImpl_get_Owner(IVideoWindow *iface, OAHWND *Owner)
474 struct video_window *This = impl_from_IVideoWindow(iface);
476 TRACE("(%p/%p)->(%p)\n", This, iface, Owner);
478 *(HWND*)Owner = This->hwndOwner;
480 return S_OK;
483 HRESULT WINAPI BaseControlWindowImpl_put_MessageDrain(IVideoWindow *iface, OAHWND Drain)
485 struct video_window *This = impl_from_IVideoWindow(iface);
487 TRACE("(%p/%p)->(%08x)\n", This, iface, (DWORD) Drain);
489 This->hwndDrain = (HWND)Drain;
491 return S_OK;
494 HRESULT WINAPI BaseControlWindowImpl_get_MessageDrain(IVideoWindow *iface, OAHWND *Drain)
496 struct video_window *This = impl_from_IVideoWindow(iface);
498 TRACE("(%p/%p)->(%p)\n", This, iface, Drain);
500 *Drain = (OAHWND)This->hwndDrain;
502 return S_OK;
505 HRESULT WINAPI BaseControlWindowImpl_get_BorderColor(IVideoWindow *iface, LONG *Color)
507 struct video_window *This = impl_from_IVideoWindow(iface);
509 FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, Color);
511 return S_OK;
514 HRESULT WINAPI BaseControlWindowImpl_put_BorderColor(IVideoWindow *iface, LONG Color)
516 struct video_window *This = impl_from_IVideoWindow(iface);
518 FIXME("(%p/%p)->(%d): stub !!!\n", This, iface, Color);
520 return S_OK;
523 HRESULT WINAPI BaseControlWindowImpl_get_FullScreenMode(IVideoWindow *iface, LONG *FullScreenMode)
525 TRACE("(%p)->(%p)\n", iface, FullScreenMode);
527 return E_NOTIMPL;
530 HRESULT WINAPI BaseControlWindowImpl_put_FullScreenMode(IVideoWindow *iface, LONG FullScreenMode)
532 TRACE("(%p)->(%d)\n", iface, FullScreenMode);
533 return E_NOTIMPL;
536 HRESULT WINAPI BaseControlWindowImpl_SetWindowForeground(IVideoWindow *iface, LONG focus)
538 struct video_window *window = impl_from_IVideoWindow(iface);
539 UINT flags = SWP_NOMOVE | SWP_NOSIZE;
541 TRACE("window %p, focus %d.\n", window, focus);
543 if (focus != OAFALSE && focus != OATRUE)
544 return E_INVALIDARG;
546 if (!window->pPin->peer)
547 return VFW_E_NOT_CONNECTED;
549 if (!focus)
550 flags |= SWP_NOACTIVATE;
551 SetWindowPos(window->hwnd, HWND_TOP, 0, 0, 0, 0, flags);
553 return S_OK;
556 HRESULT WINAPI BaseControlWindowImpl_SetWindowPosition(IVideoWindow *iface,
557 LONG left, LONG top, LONG width, LONG height)
559 struct video_window *window = impl_from_IVideoWindow(iface);
561 TRACE("window %p, left %d, top %d, width %d, height %d.\n", window, left, top, width, height);
563 if (!SetWindowPos(window->hwnd, NULL, left, top, width, height, SWP_NOACTIVATE | SWP_NOZORDER))
564 return E_FAIL;
565 return S_OK;
568 HRESULT WINAPI BaseControlWindowImpl_GetWindowPosition(IVideoWindow *iface,
569 LONG *left, LONG *top, LONG *width, LONG *height)
571 struct video_window *window = impl_from_IVideoWindow(iface);
572 RECT rect;
574 TRACE("window %p, left %p, top %p, width %p, height %p.\n", window, left, top, width, height);
576 GetWindowRect(window->hwnd, &rect);
577 *left = rect.left;
578 *top = rect.top;
579 *width = rect.right - rect.left;
580 *height = rect.bottom - rect.top;
581 return S_OK;
584 HRESULT WINAPI BaseControlWindowImpl_NotifyOwnerMessage(IVideoWindow *iface,
585 OAHWND hwnd, LONG message, LONG_PTR wparam, LONG_PTR lparam)
587 struct video_window *window = impl_from_IVideoWindow(iface);
589 TRACE("window %p, hwnd %#lx, message %#x, wparam %#lx, lparam %#lx.\n",
590 window, hwnd, message, wparam, lparam);
592 /* That these messages are forwarded, and no others, is stated by the
593 * DirectX documentation, and supported by manual testing. */
594 switch (message)
596 case WM_ACTIVATEAPP:
597 case WM_DEVMODECHANGE:
598 case WM_DISPLAYCHANGE:
599 case WM_PALETTECHANGED:
600 case WM_PALETTEISCHANGING:
601 case WM_QUERYNEWPALETTE:
602 case WM_SYSCOLORCHANGE:
603 SendMessageW(window->hwnd, message, wparam, lparam);
604 break;
607 return S_OK;
610 HRESULT WINAPI BaseControlWindowImpl_GetMinIdealImageSize(IVideoWindow *iface, LONG *width, LONG *height)
612 struct video_window *window = impl_from_IVideoWindow(iface);
613 RECT rect;
615 TRACE("window %p, width %p, height %p.\n", window, width, height);
617 rect = window->ops->get_default_rect(window);
618 *width = rect.right - rect.left;
619 *height = rect.bottom - rect.top;
620 return S_OK;
623 HRESULT WINAPI BaseControlWindowImpl_GetMaxIdealImageSize(IVideoWindow *iface, LONG *width, LONG *height)
625 struct video_window *window = impl_from_IVideoWindow(iface);
626 RECT rect;
628 TRACE("window %p, width %p, height %p.\n", window, width, height);
630 rect = window->ops->get_default_rect(window);
631 *width = rect.right - rect.left;
632 *height = rect.bottom - rect.top;
633 return S_OK;
636 HRESULT WINAPI BaseControlWindowImpl_GetRestorePosition(IVideoWindow *iface, LONG *pLeft, LONG *pTop, LONG *pWidth, LONG *pHeight)
638 struct video_window *This = impl_from_IVideoWindow(iface);
640 FIXME("(%p/%p)->(%p, %p, %p, %p): stub !!!\n", This, iface, pLeft, pTop, pWidth, pHeight);
642 return S_OK;
645 HRESULT WINAPI BaseControlWindowImpl_HideCursor(IVideoWindow *iface, LONG HideCursor)
647 struct video_window *This = impl_from_IVideoWindow(iface);
649 FIXME("(%p/%p)->(%d): stub !!!\n", This, iface, HideCursor);
651 return S_OK;
654 HRESULT WINAPI BaseControlWindowImpl_IsCursorHidden(IVideoWindow *iface, LONG *CursorHidden)
656 struct video_window *This = impl_from_IVideoWindow(iface);
658 FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, CursorHidden);
660 return S_OK;
663 static inline struct video_window *impl_from_IBasicVideo(IBasicVideo *iface)
665 return CONTAINING_RECORD(iface, struct video_window, IBasicVideo_iface);
668 static HRESULT WINAPI basic_video_QueryInterface(IBasicVideo *iface, REFIID iid, void **out)
670 struct video_window *window = impl_from_IBasicVideo(iface);
671 return IUnknown_QueryInterface(window->pFilter->outer_unk, iid, out);
674 static ULONG WINAPI basic_video_AddRef(IBasicVideo *iface)
676 struct video_window *window = impl_from_IBasicVideo(iface);
677 return IUnknown_AddRef(window->pFilter->outer_unk);
680 static ULONG WINAPI basic_video_Release(IBasicVideo *iface)
682 struct video_window *window = impl_from_IBasicVideo(iface);
683 return IUnknown_Release(window->pFilter->outer_unk);
686 static HRESULT WINAPI basic_video_GetTypeInfoCount(IBasicVideo *iface, UINT *count)
688 TRACE("iface %p, count %p.\n", iface, count);
689 *count = 1;
690 return S_OK;
693 static HRESULT WINAPI basic_video_GetTypeInfo(IBasicVideo *iface, UINT index,
694 LCID lcid, ITypeInfo **typeinfo)
696 TRACE("iface %p, index %u, lcid %#x, typeinfo %p.\n", iface, index, lcid, typeinfo);
697 return strmbase_get_typeinfo(IBasicVideo_tid, typeinfo);
700 static HRESULT WINAPI basic_video_GetIDsOfNames(IBasicVideo *iface, REFIID iid,
701 LPOLESTR *names, UINT count, LCID lcid, DISPID *ids)
703 ITypeInfo *typeinfo;
704 HRESULT hr;
706 TRACE("iface %p, iid %s, names %p, count %u, lcid %#x, ids %p.\n",
707 iface, debugstr_guid(iid), names, count, lcid, ids);
709 if (SUCCEEDED(hr = strmbase_get_typeinfo(IBasicVideo_tid, &typeinfo)))
711 hr = ITypeInfo_GetIDsOfNames(typeinfo, names, count, ids);
712 ITypeInfo_Release(typeinfo);
714 return hr;
717 static HRESULT WINAPI basic_video_Invoke(IBasicVideo *iface, DISPID id, REFIID iid, LCID lcid,
718 WORD flags, DISPPARAMS *params, VARIANT *result, EXCEPINFO *excepinfo, UINT *error_arg)
720 ITypeInfo *typeinfo;
721 HRESULT hr;
723 TRACE("iface %p, id %d, iid %s, lcid %#x, flags %#x, params %p, result %p, excepinfo %p, error_arg %p.\n",
724 iface, id, debugstr_guid(iid), lcid, flags, params, result, excepinfo, error_arg);
726 if (SUCCEEDED(hr = strmbase_get_typeinfo(IBasicVideo_tid, &typeinfo)))
728 hr = ITypeInfo_Invoke(typeinfo, iface, id, flags, params, result, excepinfo, error_arg);
729 ITypeInfo_Release(typeinfo);
731 return hr;
734 static const VIDEOINFOHEADER *get_video_format(struct video_window *window)
736 /* Members of VIDEOINFOHEADER up to bmiHeader are identical to those of
737 * VIDEOINFOHEADER2. */
738 return (const VIDEOINFOHEADER *)window->pPin->mt.pbFormat;
741 static const BITMAPINFOHEADER *get_bitmap_header(struct video_window *window)
743 const AM_MEDIA_TYPE *mt = &window->pPin->mt;
744 if (IsEqualGUID(&mt->formattype, &FORMAT_VideoInfo))
745 return &((VIDEOINFOHEADER *)mt->pbFormat)->bmiHeader;
746 else
747 return &((VIDEOINFOHEADER2 *)mt->pbFormat)->bmiHeader;
750 static HRESULT WINAPI basic_video_get_AvgTimePerFrame(IBasicVideo *iface, REFTIME *reftime)
752 struct video_window *window = impl_from_IBasicVideo(iface);
754 if (!reftime)
755 return E_POINTER;
756 if (!window->pPin->peer)
757 return VFW_E_NOT_CONNECTED;
759 TRACE("window %p, reftime %p.\n", window, reftime);
761 *reftime = (double)get_video_format(window)->AvgTimePerFrame / 1e7;
762 return S_OK;
765 static HRESULT WINAPI basic_video_get_BitRate(IBasicVideo *iface, LONG *rate)
767 struct video_window *window = impl_from_IBasicVideo(iface);
769 TRACE("window %p, rate %p.\n", window, rate);
771 if (!rate)
772 return E_POINTER;
773 if (!window->pPin->peer)
774 return VFW_E_NOT_CONNECTED;
776 *rate = get_video_format(window)->dwBitRate;
777 return S_OK;
780 static HRESULT WINAPI basic_video_get_BitErrorRate(IBasicVideo *iface, LONG *rate)
782 struct video_window *window = impl_from_IBasicVideo(iface);
784 TRACE("window %p, rate %p.\n", window, rate);
786 if (!rate)
787 return E_POINTER;
788 if (!window->pPin->peer)
789 return VFW_E_NOT_CONNECTED;
791 *rate = get_video_format(window)->dwBitErrorRate;
792 return S_OK;
795 static HRESULT WINAPI basic_video_get_VideoWidth(IBasicVideo *iface, LONG *width)
797 struct video_window *window = impl_from_IBasicVideo(iface);
799 TRACE("window %p, width %p.\n", window, width);
801 if (!width)
802 return E_POINTER;
804 *width = get_bitmap_header(window)->biWidth;
806 return S_OK;
809 static HRESULT WINAPI basic_video_get_VideoHeight(IBasicVideo *iface, LONG *height)
811 struct video_window *window = impl_from_IBasicVideo(iface);
813 TRACE("window %p, height %p.\n", window, height);
815 if (!height)
816 return E_POINTER;
818 *height = abs(get_bitmap_header(window)->biHeight);
820 return S_OK;
823 static HRESULT WINAPI basic_video_put_SourceLeft(IBasicVideo *iface, LONG left)
825 struct video_window *window = impl_from_IBasicVideo(iface);
827 TRACE("window %p, left %d.\n", window, left);
829 if (left < 0 || window->src.right + left - window->src.left > get_bitmap_header(window)->biWidth)
830 return E_INVALIDARG;
832 OffsetRect(&window->src, left - window->src.left, 0);
833 return S_OK;
836 static HRESULT WINAPI basic_video_get_SourceLeft(IBasicVideo *iface, LONG *left)
838 struct video_window *window = impl_from_IBasicVideo(iface);
840 TRACE("window %p, left %p.\n", window, left);
842 if (!left)
843 return E_POINTER;
845 *left = window->src.left;
846 return S_OK;
849 static HRESULT WINAPI basic_video_put_SourceWidth(IBasicVideo *iface, LONG width)
851 struct video_window *window = impl_from_IBasicVideo(iface);
853 TRACE("window %p, width %d.\n", window, width);
855 if (width <= 0 || window->src.left + width > get_bitmap_header(window)->biWidth)
856 return E_INVALIDARG;
858 window->src.right = window->src.left + width;
859 return S_OK;
862 static HRESULT WINAPI basic_video_get_SourceWidth(IBasicVideo *iface, LONG *width)
864 struct video_window *window = impl_from_IBasicVideo(iface);
866 TRACE("window %p, width %p.\n", window, width);
868 if (!width)
869 return E_POINTER;
871 *width = window->src.right - window->src.left;
872 return S_OK;
875 static HRESULT WINAPI basic_video_put_SourceTop(IBasicVideo *iface, LONG top)
877 struct video_window *window = impl_from_IBasicVideo(iface);
879 TRACE("window %p, top %d.\n", window, top);
881 if (top < 0 || window->src.bottom + top - window->src.top > get_bitmap_header(window)->biHeight)
882 return E_INVALIDARG;
884 OffsetRect(&window->src, 0, top - window->src.top);
885 return S_OK;
888 static HRESULT WINAPI basic_video_get_SourceTop(IBasicVideo *iface, LONG *top)
890 struct video_window *window = impl_from_IBasicVideo(iface);
892 TRACE("window %p, top %p.\n", window, top);
894 if (!top)
895 return E_POINTER;
897 *top = window->src.top;
898 return S_OK;
901 static HRESULT WINAPI basic_video_put_SourceHeight(IBasicVideo *iface, LONG height)
903 struct video_window *window = impl_from_IBasicVideo(iface);
905 TRACE("window %p, height %d.\n", window, height);
907 if (height <= 0 || window->src.top + height > get_bitmap_header(window)->biHeight)
908 return E_INVALIDARG;
910 window->src.bottom = window->src.top + height;
911 return S_OK;
914 static HRESULT WINAPI basic_video_get_SourceHeight(IBasicVideo *iface, LONG *height)
916 struct video_window *window = impl_from_IBasicVideo(iface);
918 TRACE("window %p, height %p\n", window, height);
920 if (!height)
921 return E_POINTER;
923 *height = window->src.bottom - window->src.top;
924 return S_OK;
927 static HRESULT WINAPI basic_video_put_DestinationLeft(IBasicVideo *iface, LONG left)
929 struct video_window *window = impl_from_IBasicVideo(iface);
931 TRACE("window %p, left %d.\n", window, left);
933 window->default_dst = FALSE;
934 OffsetRect(&window->dst, left - window->dst.left, 0);
935 return S_OK;
938 static HRESULT WINAPI basic_video_get_DestinationLeft(IBasicVideo *iface, LONG *left)
940 struct video_window *window = impl_from_IBasicVideo(iface);
942 TRACE("window %p, left %p.\n", window, left);
944 if (!left)
945 return E_POINTER;
947 *left = window->dst.left;
948 return S_OK;
951 static HRESULT WINAPI basic_video_put_DestinationWidth(IBasicVideo *iface, LONG width)
953 struct video_window *window = impl_from_IBasicVideo(iface);
955 TRACE("window %p, width %d.\n", window, width);
957 if (width <= 0)
958 return E_INVALIDARG;
960 window->default_dst = FALSE;
961 window->dst.right = window->dst.left + width;
962 return S_OK;
965 static HRESULT WINAPI basic_video_get_DestinationWidth(IBasicVideo *iface, LONG *width)
967 struct video_window *window = impl_from_IBasicVideo(iface);
969 TRACE("window %p, width %p.\n", window, width);
971 if (!width)
972 return E_POINTER;
974 *width = window->dst.right - window->dst.left;
975 return S_OK;
978 static HRESULT WINAPI basic_video_put_DestinationTop(IBasicVideo *iface, LONG top)
980 struct video_window *window = impl_from_IBasicVideo(iface);
982 TRACE("window %p, top %d.\n", window, top);
984 window->default_dst = FALSE;
985 OffsetRect(&window->dst, 0, top - window->dst.top);
986 return S_OK;
989 static HRESULT WINAPI basic_video_get_DestinationTop(IBasicVideo *iface, LONG *top)
991 struct video_window *window = impl_from_IBasicVideo(iface);
993 TRACE("window %p, top %p.\n", window, top);
995 if (!top)
996 return E_POINTER;
998 *top = window->dst.top;
999 return S_OK;
1002 static HRESULT WINAPI basic_video_put_DestinationHeight(IBasicVideo *iface, LONG height)
1004 struct video_window *window = impl_from_IBasicVideo(iface);
1006 TRACE("window %p, height %d.\n", window, height);
1008 if (height <= 0)
1009 return E_INVALIDARG;
1011 window->default_dst = FALSE;
1012 window->dst.bottom = window->dst.top + height;
1013 return S_OK;
1016 static HRESULT WINAPI basic_video_get_DestinationHeight(IBasicVideo *iface, LONG *height)
1018 struct video_window *window = impl_from_IBasicVideo(iface);
1020 TRACE("window %p, height %p.\n", window, height);
1022 if (!height)
1023 return E_POINTER;
1025 *height = window->dst.bottom - window->dst.top;
1026 return S_OK;
1029 static HRESULT WINAPI basic_video_SetSourcePosition(IBasicVideo *iface,
1030 LONG left, LONG top, LONG width, LONG height)
1032 struct video_window *window = impl_from_IBasicVideo(iface);
1033 const BITMAPINFOHEADER *bitmap_header = get_bitmap_header(window);
1035 TRACE("window %p, left %d, top %d, width %d, height %d.\n", window, left, top, width, height);
1037 if (left < 0 || left + width > bitmap_header->biWidth || width <= 0)
1038 return E_INVALIDARG;
1039 if (top < 0 || top + height > bitmap_header->biHeight || height <= 0)
1040 return E_INVALIDARG;
1042 SetRect(&window->src, left, top, left + width, top + height);
1043 return S_OK;
1046 static HRESULT WINAPI basic_video_GetSourcePosition(IBasicVideo *iface,
1047 LONG *left, LONG *top, LONG *width, LONG *height)
1049 struct video_window *window = impl_from_IBasicVideo(iface);
1051 TRACE("window %p, left %p, top %p, width %p, height %p.\n", window, left, top, width, height);
1053 if (!left || !top || !width || !height)
1054 return E_POINTER;
1056 *left = window->src.left;
1057 *top = window->src.top;
1058 *width = window->src.right - window->src.left;
1059 *height = window->src.bottom - window->src.top;
1060 return S_OK;
1063 static HRESULT WINAPI basic_video_SetDefaultSourcePosition(IBasicVideo *iface)
1065 struct video_window *window = impl_from_IBasicVideo(iface);
1066 const BITMAPINFOHEADER *bitmap_header = get_bitmap_header(window);
1068 TRACE("window %p.\n", window);
1070 SetRect(&window->src, 0, 0, bitmap_header->biWidth, bitmap_header->biHeight);
1071 return S_OK;
1074 static HRESULT WINAPI basic_video_SetDestinationPosition(IBasicVideo *iface,
1075 LONG left, LONG top, LONG width, LONG height)
1077 struct video_window *window = impl_from_IBasicVideo(iface);
1079 TRACE("window %p, left %d, top %d, width %d, height %d.\n", window, left, top, width, height);
1081 if (width <= 0 || height <= 0)
1082 return E_INVALIDARG;
1084 window->default_dst = FALSE;
1085 SetRect(&window->dst, left, top, left + width, top + height);
1086 return S_OK;
1089 static HRESULT WINAPI basic_video_GetDestinationPosition(IBasicVideo *iface,
1090 LONG *left, LONG *top, LONG *width, LONG *height)
1092 struct video_window *window = impl_from_IBasicVideo(iface);
1094 TRACE("window %p, left %p, top %p, width %p, height %p.\n", window, left, top, width, height);
1096 if (!left || !top || !width || !height)
1097 return E_POINTER;
1099 *left = window->dst.left;
1100 *top = window->dst.top;
1101 *width = window->dst.right - window->dst.left;
1102 *height = window->dst.bottom - window->dst.top;
1103 return S_OK;
1106 static HRESULT WINAPI basic_video_SetDefaultDestinationPosition(IBasicVideo *iface)
1108 struct video_window *window = impl_from_IBasicVideo(iface);
1110 TRACE("window %p.\n", window);
1112 window->default_dst = TRUE;
1113 GetClientRect(window->hwnd, &window->dst);
1114 return S_OK;
1117 static HRESULT WINAPI basic_video_GetVideoSize(IBasicVideo *iface, LONG *width, LONG *height)
1119 struct video_window *window = impl_from_IBasicVideo(iface);
1120 const BITMAPINFOHEADER *bitmap_header = get_bitmap_header(window);
1122 TRACE("window %p, width %p, height %p.\n", window, width, height);
1124 if (!width || !height)
1125 return E_POINTER;
1127 *width = bitmap_header->biWidth;
1128 *height = bitmap_header->biHeight;
1129 return S_OK;
1132 static HRESULT WINAPI basic_video_GetVideoPaletteEntries(IBasicVideo *iface,
1133 LONG start, LONG count, LONG *ret_count, LONG *palette)
1135 struct video_window *window = impl_from_IBasicVideo(iface);
1137 FIXME("window %p, start %d, count %d, ret_count %p, palette %p, stub!\n",
1138 window, start, count, ret_count, palette);
1140 if (!ret_count || !palette)
1141 return E_POINTER;
1143 *ret_count = 0;
1144 return VFW_E_NO_PALETTE_AVAILABLE;
1147 static HRESULT WINAPI basic_video_GetCurrentImage(IBasicVideo *iface, LONG *size, LONG *image)
1149 struct video_window *window = impl_from_IBasicVideo(iface);
1151 TRACE("window %p, size %p, image %p.\n", window, size, image);
1153 if (!size || !image)
1154 return E_POINTER;
1156 return window->ops->get_current_image(window, size, image);
1159 static HRESULT WINAPI basic_video_IsUsingDefaultSource(IBasicVideo *iface)
1161 struct video_window *window = impl_from_IBasicVideo(iface);
1162 const BITMAPINFOHEADER *bitmap_header = get_bitmap_header(window);
1164 TRACE("window %p.\n", window);
1166 if (!window->src.left && !window->src.top
1167 && window->src.right == bitmap_header->biWidth
1168 && window->src.bottom == bitmap_header->biHeight)
1169 return S_OK;
1170 return S_FALSE;
1173 static HRESULT WINAPI basic_video_IsUsingDefaultDestination(IBasicVideo *iface)
1175 struct video_window *window = impl_from_IBasicVideo(iface);
1177 TRACE("window %p.\n", window);
1179 return window->default_dst ? S_OK : S_FALSE;
1182 static const IBasicVideoVtbl basic_video_vtbl =
1184 basic_video_QueryInterface,
1185 basic_video_AddRef,
1186 basic_video_Release,
1187 basic_video_GetTypeInfoCount,
1188 basic_video_GetTypeInfo,
1189 basic_video_GetIDsOfNames,
1190 basic_video_Invoke,
1191 basic_video_get_AvgTimePerFrame,
1192 basic_video_get_BitRate,
1193 basic_video_get_BitErrorRate,
1194 basic_video_get_VideoWidth,
1195 basic_video_get_VideoHeight,
1196 basic_video_put_SourceLeft,
1197 basic_video_get_SourceLeft,
1198 basic_video_put_SourceWidth,
1199 basic_video_get_SourceWidth,
1200 basic_video_put_SourceTop,
1201 basic_video_get_SourceTop,
1202 basic_video_put_SourceHeight,
1203 basic_video_get_SourceHeight,
1204 basic_video_put_DestinationLeft,
1205 basic_video_get_DestinationLeft,
1206 basic_video_put_DestinationWidth,
1207 basic_video_get_DestinationWidth,
1208 basic_video_put_DestinationTop,
1209 basic_video_get_DestinationTop,
1210 basic_video_put_DestinationHeight,
1211 basic_video_get_DestinationHeight,
1212 basic_video_SetSourcePosition,
1213 basic_video_GetSourcePosition,
1214 basic_video_SetDefaultSourcePosition,
1215 basic_video_SetDestinationPosition,
1216 basic_video_GetDestinationPosition,
1217 basic_video_SetDefaultDestinationPosition,
1218 basic_video_GetVideoSize,
1219 basic_video_GetVideoPaletteEntries,
1220 basic_video_GetCurrentImage,
1221 basic_video_IsUsingDefaultSource,
1222 basic_video_IsUsingDefaultDestination
1225 void video_window_unregister_class(void)
1227 if (!UnregisterClassW(class_name, NULL) && GetLastError() != ERROR_CLASS_DOES_NOT_EXIST)
1228 ERR("Failed to unregister class, error %u.\n", GetLastError());
1231 void video_window_init(struct video_window *window, const IVideoWindowVtbl *vtbl,
1232 struct strmbase_filter *owner, struct strmbase_pin *pin, const struct video_window_ops *ops)
1234 memset(window, 0, sizeof(*window));
1235 window->ops = ops;
1236 window->IVideoWindow_iface.lpVtbl = vtbl;
1237 window->IBasicVideo_iface.lpVtbl = &basic_video_vtbl;
1238 window->default_dst = TRUE;
1239 window->AutoShow = OATRUE;
1240 window->pFilter = owner;
1241 window->pPin = pin;
1244 void video_window_cleanup(struct video_window *window)
1246 if (window->hwnd)
1248 /* Media Player Classic deadlocks if WM_PARENTNOTIFY is sent, so clear
1249 * the child style first. Just like Windows, we don't actually unparent
1250 * the window, to prevent extra focus events from being generated since
1251 * it would become top-level for a brief period before being destroyed. */
1252 SetWindowLongW(window->hwnd, GWL_STYLE, GetWindowLongW(window->hwnd, GWL_STYLE) & ~WS_CHILD);
1254 SendMessageW(window->hwnd, WM_CLOSE, 0, 0);
1255 window->hwnd = NULL;