win32u: Avoid invalid access when registered device alloc failed. (Coverity).
[wine.git] / dlls / quartz / window.c
blob3e19d9b582e272423ca5dc4e16c22a9d7d1b4fac
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 #define WM_QUARTZ_DESTROY (WM_USER + WM_DESTROY)
25 WINE_DEFAULT_DEBUG_CHANNEL(quartz);
27 static const WCHAR class_name[] = L"wine_quartz_window";
29 static inline struct video_window *impl_from_IVideoWindow(IVideoWindow *iface)
31 return CONTAINING_RECORD(iface, struct video_window, IVideoWindow_iface);
34 static LRESULT CALLBACK WndProcW(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
36 struct video_window *window = (struct video_window *)GetWindowLongPtrW(hwnd, 0);
38 if (!window)
39 return DefWindowProcW(hwnd, message, wparam, lparam);
41 switch (message)
43 case WM_KEYDOWN:
44 case WM_KEYUP:
45 case WM_LBUTTONDBLCLK:
46 case WM_LBUTTONDOWN:
47 case WM_LBUTTONUP:
48 case WM_MBUTTONDBLCLK:
49 case WM_MBUTTONDOWN:
50 case WM_MBUTTONUP:
51 case WM_MOUSEACTIVATE:
52 case WM_MOUSEMOVE:
53 case WM_NCLBUTTONDBLCLK:
54 case WM_NCLBUTTONDOWN:
55 case WM_NCLBUTTONUP:
56 case WM_NCMBUTTONDBLCLK:
57 case WM_NCMBUTTONDOWN:
58 case WM_NCMBUTTONUP:
59 case WM_NCMOUSEMOVE:
60 case WM_NCRBUTTONDBLCLK:
61 case WM_NCRBUTTONDOWN:
62 case WM_NCRBUTTONUP:
63 case WM_RBUTTONDBLCLK:
64 case WM_RBUTTONDOWN:
65 case WM_RBUTTONUP:
66 if (window->hwndDrain)
68 PostMessageW(window->hwndDrain, message, wparam, lparam);
69 return 0;
71 break;
72 case WM_SIZE:
73 if (window->default_dst)
74 GetClientRect(window->hwnd, &window->dst);
75 break;
76 case WM_QUARTZ_DESTROY:
77 DestroyWindow(hwnd);
78 return 0;
79 case WM_CLOSE:
81 IFilterGraph *graph = window->pFilter->graph;
82 IMediaEventSink *event_sink;
83 IVideoWindow_put_Visible(&window->IVideoWindow_iface, OAFALSE);
84 if (graph && SUCCEEDED(IFilterGraph_QueryInterface(graph,
85 &IID_IMediaEventSink,
86 (void **)&event_sink)))
88 IMediaEventSink_Notify(event_sink, EC_USERABORT, 0, 0);
89 IMediaEventSink_Release(event_sink);
91 return 0;
95 return DefWindowProcW(hwnd, message, wparam, lparam);
98 HRESULT video_window_create_window(struct video_window *window)
100 WNDCLASSW winclass = {0};
102 winclass.lpfnWndProc = WndProcW;
103 winclass.cbWndExtra = sizeof(window);
104 winclass.hbrBackground = GetStockObject(BLACK_BRUSH);
105 winclass.lpszClassName = class_name;
106 if (!RegisterClassW(&winclass) && GetLastError() != ERROR_CLASS_ALREADY_EXISTS)
108 ERR("Failed to register class, error %lu.\n", GetLastError());
109 return E_FAIL;
112 if (!(window->hwnd = CreateWindowExW(0, class_name, L"ActiveMovie Window",
113 WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
114 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
115 NULL, NULL, NULL, NULL)))
117 ERR("Unable to create window\n");
118 return E_FAIL;
121 SetWindowLongPtrW(window->hwnd, 0, (LONG_PTR)window);
123 return S_OK;
126 HRESULT WINAPI BaseControlWindowImpl_QueryInterface(IVideoWindow *iface, REFIID iid, void **out)
128 struct video_window *window = impl_from_IVideoWindow(iface);
129 return IUnknown_QueryInterface(window->pFilter->outer_unk, iid, out);
132 ULONG WINAPI BaseControlWindowImpl_AddRef(IVideoWindow *iface)
134 struct video_window *window = impl_from_IVideoWindow(iface);
135 return IUnknown_AddRef(window->pFilter->outer_unk);
138 ULONG WINAPI BaseControlWindowImpl_Release(IVideoWindow *iface)
140 struct video_window *window = impl_from_IVideoWindow(iface);
141 return IUnknown_Release(window->pFilter->outer_unk);
144 HRESULT WINAPI BaseControlWindowImpl_GetTypeInfoCount(IVideoWindow *iface, UINT *count)
146 TRACE("iface %p, count %p.\n", iface, count);
147 *count = 1;
148 return S_OK;
151 HRESULT WINAPI BaseControlWindowImpl_GetTypeInfo(IVideoWindow *iface, UINT index,
152 LCID lcid, ITypeInfo **typeinfo)
154 TRACE("iface %p, index %u, lcid %#lx, typeinfo %p.\n", iface, index, lcid, typeinfo);
155 return strmbase_get_typeinfo(IVideoWindow_tid, typeinfo);
158 HRESULT WINAPI BaseControlWindowImpl_GetIDsOfNames(IVideoWindow *iface, REFIID iid,
159 LPOLESTR *names, UINT count, LCID lcid, DISPID *ids)
161 ITypeInfo *typeinfo;
162 HRESULT hr;
164 TRACE("iface %p, iid %s, names %p, count %u, lcid %#lx, ids %p.\n",
165 iface, debugstr_guid(iid), names, count, lcid, ids);
167 if (SUCCEEDED(hr = strmbase_get_typeinfo(IVideoWindow_tid, &typeinfo)))
169 hr = ITypeInfo_GetIDsOfNames(typeinfo, names, count, ids);
170 ITypeInfo_Release(typeinfo);
172 return hr;
175 HRESULT WINAPI BaseControlWindowImpl_Invoke(IVideoWindow *iface, DISPID id, REFIID iid, LCID lcid,
176 WORD flags, DISPPARAMS *params, VARIANT *result, EXCEPINFO *excepinfo, UINT *error_arg)
178 ITypeInfo *typeinfo;
179 HRESULT hr;
181 TRACE("iface %p, id %ld, iid %s, lcid %#lx, flags %#x, params %p, result %p, excepinfo %p, error_arg %p.\n",
182 iface, id, debugstr_guid(iid), lcid, flags, params, result, excepinfo, error_arg);
184 if (SUCCEEDED(hr = strmbase_get_typeinfo(IVideoWindow_tid, &typeinfo)))
186 hr = ITypeInfo_Invoke(typeinfo, iface, id, flags, params, result, excepinfo, error_arg);
187 ITypeInfo_Release(typeinfo);
189 return hr;
192 HRESULT WINAPI BaseControlWindowImpl_put_Caption(IVideoWindow *iface, BSTR caption)
194 struct video_window *window = impl_from_IVideoWindow(iface);
196 TRACE("window %p, caption %s.\n", window, debugstr_w(caption));
198 if (!SetWindowTextW(window->hwnd, caption))
199 return E_FAIL;
201 return S_OK;
204 HRESULT WINAPI BaseControlWindowImpl_get_Caption(IVideoWindow *iface, BSTR *caption)
206 struct video_window *window = impl_from_IVideoWindow(iface);
207 WCHAR *str;
208 int len;
210 TRACE("window %p, caption %p.\n", window, caption);
212 *caption = NULL;
214 len = GetWindowTextLengthW(window->hwnd) + 1;
215 if (!(str = heap_alloc(len * sizeof(WCHAR))))
216 return E_OUTOFMEMORY;
218 GetWindowTextW(window->hwnd, str, len);
219 *caption = SysAllocString(str);
220 heap_free(str);
221 return *caption ? S_OK : E_OUTOFMEMORY;
224 HRESULT WINAPI BaseControlWindowImpl_put_WindowStyle(IVideoWindow *iface, LONG style)
226 struct video_window *window = impl_from_IVideoWindow(iface);
228 TRACE("window %p, style %#lx.\n", window, style);
230 if (style & (WS_DISABLED|WS_HSCROLL|WS_MAXIMIZE|WS_MINIMIZE|WS_VSCROLL))
231 return E_INVALIDARG;
233 SetWindowLongW(window->hwnd, GWL_STYLE, style);
234 SetWindowPos(window->hwnd, 0, 0, 0, 0, 0,
235 SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
236 return S_OK;
239 HRESULT WINAPI BaseControlWindowImpl_get_WindowStyle(IVideoWindow *iface, LONG *style)
241 struct video_window *window = impl_from_IVideoWindow(iface);
243 TRACE("window %p, style %p.\n", window, style);
245 *style = GetWindowLongW(window->hwnd, GWL_STYLE);
246 return S_OK;
249 HRESULT WINAPI BaseControlWindowImpl_put_WindowStyleEx(IVideoWindow *iface, LONG style)
251 struct video_window *window = impl_from_IVideoWindow(iface);
253 TRACE("window %p, style %#lx.\n", window, style);
255 if (!SetWindowLongW(window->hwnd, GWL_EXSTYLE, style))
256 return E_FAIL;
257 return S_OK;
260 HRESULT WINAPI BaseControlWindowImpl_get_WindowStyleEx(IVideoWindow *iface, LONG *style)
262 struct video_window *window = impl_from_IVideoWindow(iface);
264 TRACE("window %p, style %p.\n", window, style);
266 *style = GetWindowLongW(window->hwnd, GWL_EXSTYLE);
267 return S_OK;
270 HRESULT WINAPI BaseControlWindowImpl_put_AutoShow(IVideoWindow *iface, LONG AutoShow)
272 struct video_window *This = impl_from_IVideoWindow(iface);
274 TRACE("window %p, AutoShow %ld.\n", This, AutoShow);
276 This->AutoShow = AutoShow;
278 return S_OK;
281 HRESULT WINAPI BaseControlWindowImpl_get_AutoShow(IVideoWindow *iface, LONG *AutoShow)
283 struct video_window *This = impl_from_IVideoWindow(iface);
285 TRACE("(%p/%p)->(%p)\n", This, iface, AutoShow);
287 *AutoShow = This->AutoShow;
289 return S_OK;
292 HRESULT WINAPI BaseControlWindowImpl_put_WindowState(IVideoWindow *iface, LONG state)
294 struct video_window *window = impl_from_IVideoWindow(iface);
296 TRACE("window %p, state %ld.\n", window, state);
298 ShowWindow(window->hwnd, state);
299 return S_OK;
302 HRESULT WINAPI BaseControlWindowImpl_get_WindowState(IVideoWindow *iface, LONG *state)
304 struct video_window *window = impl_from_IVideoWindow(iface);
305 DWORD style;
307 TRACE("window %p, state %p.\n", window, state);
309 style = GetWindowLongPtrW(window->hwnd, GWL_STYLE);
310 if (!(style & WS_VISIBLE))
311 *state = SW_HIDE;
312 else if (style & WS_MINIMIZE)
313 *state = SW_MINIMIZE;
314 else if (style & WS_MAXIMIZE)
315 *state = SW_MAXIMIZE;
316 else
317 *state = SW_SHOW;
319 return S_OK;
322 HRESULT WINAPI BaseControlWindowImpl_put_BackgroundPalette(IVideoWindow *iface, LONG BackgroundPalette)
324 struct video_window *This = impl_from_IVideoWindow(iface);
326 FIXME("window %p, palette %ld, stub!\n", This, BackgroundPalette);
328 return S_OK;
331 HRESULT WINAPI BaseControlWindowImpl_get_BackgroundPalette(IVideoWindow *iface, LONG *pBackgroundPalette)
333 struct video_window *This = impl_from_IVideoWindow(iface);
335 FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, pBackgroundPalette);
337 return S_OK;
340 HRESULT WINAPI BaseControlWindowImpl_put_Visible(IVideoWindow *iface, LONG visible)
342 struct video_window *window = impl_from_IVideoWindow(iface);
344 TRACE("window %p, visible %ld.\n", window, visible);
346 ShowWindow(window->hwnd, visible ? SW_SHOW : SW_HIDE);
347 return S_OK;
350 HRESULT WINAPI BaseControlWindowImpl_get_Visible(IVideoWindow *iface, LONG *visible)
352 struct video_window *window = impl_from_IVideoWindow(iface);
354 TRACE("window %p, visible %p.\n", window, visible);
356 if (!visible)
357 return E_POINTER;
359 *visible = IsWindowVisible(window->hwnd) ? OATRUE : OAFALSE;
360 return S_OK;
363 HRESULT WINAPI BaseControlWindowImpl_put_Left(IVideoWindow *iface, LONG left)
365 struct video_window *window = impl_from_IVideoWindow(iface);
366 RECT rect;
368 TRACE("window %p, left %ld.\n", window, left);
370 GetWindowRect(window->hwnd, &rect);
371 if (!SetWindowPos(window->hwnd, NULL, left, rect.top, 0, 0,
372 SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE))
373 return E_FAIL;
375 return S_OK;
378 HRESULT WINAPI BaseControlWindowImpl_get_Left(IVideoWindow *iface, LONG *left)
380 struct video_window *window = impl_from_IVideoWindow(iface);
381 RECT rect;
383 TRACE("window %p, left %p.\n", window, left);
385 GetWindowRect(window->hwnd, &rect);
386 *left = rect.left;
387 return S_OK;
390 HRESULT WINAPI BaseControlWindowImpl_put_Width(IVideoWindow *iface, LONG width)
392 struct video_window *window = impl_from_IVideoWindow(iface);
393 RECT rect;
395 TRACE("window %p, width %ld.\n", window, width);
397 GetWindowRect(window->hwnd, &rect);
398 if (!SetWindowPos(window->hwnd, NULL, 0, 0, width, rect.bottom - rect.top,
399 SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOMOVE))
400 return E_FAIL;
402 return S_OK;
405 HRESULT WINAPI BaseControlWindowImpl_get_Width(IVideoWindow *iface, LONG *width)
407 struct video_window *window = impl_from_IVideoWindow(iface);
408 RECT rect;
410 TRACE("window %p, width %p.\n", window, width);
412 GetWindowRect(window->hwnd, &rect);
413 *width = rect.right - rect.left;
414 return S_OK;
417 HRESULT WINAPI BaseControlWindowImpl_put_Top(IVideoWindow *iface, LONG top)
419 struct video_window *window = impl_from_IVideoWindow(iface);
420 RECT rect;
422 TRACE("window %p, top %ld.\n", window, top);
424 GetWindowRect(window->hwnd, &rect);
425 if (!SetWindowPos(window->hwnd, NULL, rect.left, top, 0, 0,
426 SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE))
427 return E_FAIL;
429 return S_OK;
432 HRESULT WINAPI BaseControlWindowImpl_get_Top(IVideoWindow *iface, LONG *top)
434 struct video_window *window = impl_from_IVideoWindow(iface);
435 RECT rect;
437 TRACE("window %p, top %p.\n", window, top);
439 GetWindowRect(window->hwnd, &rect);
440 *top = rect.top;
441 return S_OK;
444 HRESULT WINAPI BaseControlWindowImpl_put_Height(IVideoWindow *iface, LONG height)
446 struct video_window *window = impl_from_IVideoWindow(iface);
447 RECT rect;
449 TRACE("window %p, height %ld.\n", window, height);
451 GetWindowRect(window->hwnd, &rect);
452 if (!SetWindowPos(window->hwnd, NULL, 0, 0, rect.right - rect.left,
453 height, SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOMOVE))
454 return E_FAIL;
456 return S_OK;
459 HRESULT WINAPI BaseControlWindowImpl_get_Height(IVideoWindow *iface, LONG *height)
461 struct video_window *window = impl_from_IVideoWindow(iface);
462 RECT rect;
464 TRACE("window %p, height %p.\n", window, height);
466 GetWindowRect(window->hwnd, &rect);
467 *height = rect.bottom - rect.top;
468 return S_OK;
471 HRESULT WINAPI BaseControlWindowImpl_put_Owner(IVideoWindow *iface, OAHWND owner)
473 struct video_window *window = impl_from_IVideoWindow(iface);
474 HWND hwnd = window->hwnd;
476 TRACE("window %p, owner %#Ix.\n", window, owner);
478 /* Make sure we are marked as WS_CHILD before reparenting ourselves, so that
479 * we do not steal focus. LEGO Island depends on this. */
481 window->hwndOwner = (HWND)owner;
482 if (owner)
483 SetWindowLongPtrW(hwnd, GWL_STYLE, GetWindowLongPtrW(hwnd, GWL_STYLE) | WS_CHILD);
484 else
485 SetWindowLongPtrW(hwnd, GWL_STYLE, GetWindowLongPtrW(hwnd, GWL_STYLE) & ~WS_CHILD);
486 SetParent(hwnd, (HWND)owner);
488 return S_OK;
491 HRESULT WINAPI BaseControlWindowImpl_get_Owner(IVideoWindow *iface, OAHWND *Owner)
493 struct video_window *This = impl_from_IVideoWindow(iface);
495 TRACE("(%p/%p)->(%p)\n", This, iface, Owner);
497 *(HWND*)Owner = This->hwndOwner;
499 return S_OK;
502 HRESULT WINAPI BaseControlWindowImpl_put_MessageDrain(IVideoWindow *iface, OAHWND Drain)
504 struct video_window *This = impl_from_IVideoWindow(iface);
506 TRACE("window %p, drain %#Ix.\n", This, Drain);
508 This->hwndDrain = (HWND)Drain;
510 return S_OK;
513 HRESULT WINAPI BaseControlWindowImpl_get_MessageDrain(IVideoWindow *iface, OAHWND *Drain)
515 struct video_window *This = impl_from_IVideoWindow(iface);
517 TRACE("(%p/%p)->(%p)\n", This, iface, Drain);
519 *Drain = (OAHWND)This->hwndDrain;
521 return S_OK;
524 HRESULT WINAPI BaseControlWindowImpl_get_BorderColor(IVideoWindow *iface, LONG *Color)
526 struct video_window *This = impl_from_IVideoWindow(iface);
528 FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, Color);
530 return S_OK;
533 HRESULT WINAPI BaseControlWindowImpl_put_BorderColor(IVideoWindow *iface, LONG Color)
535 struct video_window *This = impl_from_IVideoWindow(iface);
537 TRACE("window %p, colour %#lx.\n", This, Color);
539 return S_OK;
542 HRESULT WINAPI BaseControlWindowImpl_get_FullScreenMode(IVideoWindow *iface, LONG *FullScreenMode)
544 TRACE("(%p)->(%p)\n", iface, FullScreenMode);
546 return E_NOTIMPL;
549 HRESULT WINAPI BaseControlWindowImpl_put_FullScreenMode(IVideoWindow *iface, LONG fullscreen)
551 struct video_window *window = impl_from_IVideoWindow(iface);
553 TRACE("window %p, fullscreen %ld.\n", window, fullscreen);
555 return E_NOTIMPL;
558 HRESULT WINAPI BaseControlWindowImpl_SetWindowForeground(IVideoWindow *iface, LONG focus)
560 struct video_window *window = impl_from_IVideoWindow(iface);
561 UINT flags = SWP_NOMOVE | SWP_NOSIZE;
563 TRACE("window %p, focus %ld.\n", window, focus);
565 if (focus != OAFALSE && focus != OATRUE)
566 return E_INVALIDARG;
568 if (!window->pPin->peer)
569 return VFW_E_NOT_CONNECTED;
571 if (!focus)
572 flags |= SWP_NOACTIVATE;
573 SetWindowPos(window->hwnd, HWND_TOP, 0, 0, 0, 0, flags);
575 return S_OK;
578 HRESULT WINAPI BaseControlWindowImpl_SetWindowPosition(IVideoWindow *iface,
579 LONG left, LONG top, LONG width, LONG height)
581 struct video_window *window = impl_from_IVideoWindow(iface);
583 TRACE("window %p, left %ld, top %ld, width %ld, height %ld.\n", window, left, top, width, height);
585 if (!SetWindowPos(window->hwnd, NULL, left, top, width, height, SWP_NOACTIVATE | SWP_NOZORDER))
586 return E_FAIL;
587 return S_OK;
590 HRESULT WINAPI BaseControlWindowImpl_GetWindowPosition(IVideoWindow *iface,
591 LONG *left, LONG *top, LONG *width, LONG *height)
593 struct video_window *window = impl_from_IVideoWindow(iface);
594 RECT rect;
596 TRACE("window %p, left %p, top %p, width %p, height %p.\n", window, left, top, width, height);
598 GetWindowRect(window->hwnd, &rect);
599 *left = rect.left;
600 *top = rect.top;
601 *width = rect.right - rect.left;
602 *height = rect.bottom - rect.top;
603 return S_OK;
606 HRESULT WINAPI BaseControlWindowImpl_NotifyOwnerMessage(IVideoWindow *iface,
607 OAHWND hwnd, LONG message, LONG_PTR wparam, LONG_PTR lparam)
609 struct video_window *window = impl_from_IVideoWindow(iface);
611 TRACE("window %p, hwnd %#Ix, message %#lx, wparam %#Ix, lparam %#Ix.\n",
612 window, hwnd, message, wparam, lparam);
614 /* That these messages are forwarded, and no others, is stated by the
615 * DirectX documentation, and supported by manual testing. */
616 switch (message)
618 case WM_ACTIVATEAPP:
619 case WM_DEVMODECHANGE:
620 case WM_DISPLAYCHANGE:
621 case WM_PALETTECHANGED:
622 case WM_PALETTEISCHANGING:
623 case WM_QUERYNEWPALETTE:
624 case WM_SYSCOLORCHANGE:
625 SendMessageW(window->hwnd, message, wparam, lparam);
626 break;
629 return S_OK;
632 HRESULT WINAPI BaseControlWindowImpl_GetMinIdealImageSize(IVideoWindow *iface, LONG *width, LONG *height)
634 struct video_window *window = impl_from_IVideoWindow(iface);
635 RECT rect;
637 TRACE("window %p, width %p, height %p.\n", window, width, height);
639 rect = window->ops->get_default_rect(window);
640 *width = rect.right - rect.left;
641 *height = rect.bottom - rect.top;
642 return S_OK;
645 HRESULT WINAPI BaseControlWindowImpl_GetMaxIdealImageSize(IVideoWindow *iface, LONG *width, LONG *height)
647 struct video_window *window = impl_from_IVideoWindow(iface);
648 RECT rect;
650 TRACE("window %p, width %p, height %p.\n", window, width, height);
652 rect = window->ops->get_default_rect(window);
653 *width = rect.right - rect.left;
654 *height = rect.bottom - rect.top;
655 return S_OK;
658 HRESULT WINAPI BaseControlWindowImpl_GetRestorePosition(IVideoWindow *iface, LONG *pLeft, LONG *pTop, LONG *pWidth, LONG *pHeight)
660 struct video_window *This = impl_from_IVideoWindow(iface);
662 FIXME("(%p/%p)->(%p, %p, %p, %p): stub !!!\n", This, iface, pLeft, pTop, pWidth, pHeight);
664 return S_OK;
667 HRESULT WINAPI BaseControlWindowImpl_HideCursor(IVideoWindow *iface, LONG hide)
669 struct video_window *window = impl_from_IVideoWindow(iface);
671 FIXME("window %p, hide %ld, stub!\n", window, hide);
673 return S_OK;
676 HRESULT WINAPI BaseControlWindowImpl_IsCursorHidden(IVideoWindow *iface, LONG *CursorHidden)
678 struct video_window *This = impl_from_IVideoWindow(iface);
680 FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, CursorHidden);
682 return S_OK;
685 static inline struct video_window *impl_from_IBasicVideo(IBasicVideo *iface)
687 return CONTAINING_RECORD(iface, struct video_window, IBasicVideo_iface);
690 static HRESULT WINAPI basic_video_QueryInterface(IBasicVideo *iface, REFIID iid, void **out)
692 struct video_window *window = impl_from_IBasicVideo(iface);
693 return IUnknown_QueryInterface(window->pFilter->outer_unk, iid, out);
696 static ULONG WINAPI basic_video_AddRef(IBasicVideo *iface)
698 struct video_window *window = impl_from_IBasicVideo(iface);
699 return IUnknown_AddRef(window->pFilter->outer_unk);
702 static ULONG WINAPI basic_video_Release(IBasicVideo *iface)
704 struct video_window *window = impl_from_IBasicVideo(iface);
705 return IUnknown_Release(window->pFilter->outer_unk);
708 static HRESULT WINAPI basic_video_GetTypeInfoCount(IBasicVideo *iface, UINT *count)
710 TRACE("iface %p, count %p.\n", iface, count);
711 *count = 1;
712 return S_OK;
715 static HRESULT WINAPI basic_video_GetTypeInfo(IBasicVideo *iface, UINT index,
716 LCID lcid, ITypeInfo **typeinfo)
718 TRACE("iface %p, index %u, lcid %#lx, typeinfo %p.\n", iface, index, lcid, typeinfo);
719 return strmbase_get_typeinfo(IBasicVideo_tid, typeinfo);
722 static HRESULT WINAPI basic_video_GetIDsOfNames(IBasicVideo *iface, REFIID iid,
723 LPOLESTR *names, UINT count, LCID lcid, DISPID *ids)
725 ITypeInfo *typeinfo;
726 HRESULT hr;
728 TRACE("iface %p, iid %s, names %p, count %u, lcid %#lx, ids %p.\n",
729 iface, debugstr_guid(iid), names, count, lcid, ids);
731 if (SUCCEEDED(hr = strmbase_get_typeinfo(IBasicVideo_tid, &typeinfo)))
733 hr = ITypeInfo_GetIDsOfNames(typeinfo, names, count, ids);
734 ITypeInfo_Release(typeinfo);
736 return hr;
739 static HRESULT WINAPI basic_video_Invoke(IBasicVideo *iface, DISPID id, REFIID iid, LCID lcid,
740 WORD flags, DISPPARAMS *params, VARIANT *result, EXCEPINFO *excepinfo, UINT *error_arg)
742 ITypeInfo *typeinfo;
743 HRESULT hr;
745 TRACE("iface %p, id %ld, iid %s, lcid %#lx, flags %#x, params %p, result %p, excepinfo %p, error_arg %p.\n",
746 iface, id, debugstr_guid(iid), lcid, flags, params, result, excepinfo, error_arg);
748 if (SUCCEEDED(hr = strmbase_get_typeinfo(IBasicVideo_tid, &typeinfo)))
750 hr = ITypeInfo_Invoke(typeinfo, iface, id, flags, params, result, excepinfo, error_arg);
751 ITypeInfo_Release(typeinfo);
753 return hr;
756 static const VIDEOINFOHEADER *get_video_format(struct video_window *window)
758 /* Members of VIDEOINFOHEADER up to bmiHeader are identical to those of
759 * VIDEOINFOHEADER2. */
760 return (const VIDEOINFOHEADER *)window->pPin->mt.pbFormat;
763 static const BITMAPINFOHEADER *get_bitmap_header(struct video_window *window)
765 const AM_MEDIA_TYPE *mt = &window->pPin->mt;
766 if (IsEqualGUID(&mt->formattype, &FORMAT_VideoInfo))
767 return &((VIDEOINFOHEADER *)mt->pbFormat)->bmiHeader;
768 else
769 return &((VIDEOINFOHEADER2 *)mt->pbFormat)->bmiHeader;
772 static HRESULT WINAPI basic_video_get_AvgTimePerFrame(IBasicVideo *iface, REFTIME *reftime)
774 struct video_window *window = impl_from_IBasicVideo(iface);
776 if (!reftime)
777 return E_POINTER;
778 if (!window->pPin->peer)
779 return VFW_E_NOT_CONNECTED;
781 TRACE("window %p, reftime %p.\n", window, reftime);
783 *reftime = (double)get_video_format(window)->AvgTimePerFrame / 1e7;
784 return S_OK;
787 static HRESULT WINAPI basic_video_get_BitRate(IBasicVideo *iface, LONG *rate)
789 struct video_window *window = impl_from_IBasicVideo(iface);
791 TRACE("window %p, rate %p.\n", window, rate);
793 if (!rate)
794 return E_POINTER;
795 if (!window->pPin->peer)
796 return VFW_E_NOT_CONNECTED;
798 *rate = get_video_format(window)->dwBitRate;
799 return S_OK;
802 static HRESULT WINAPI basic_video_get_BitErrorRate(IBasicVideo *iface, LONG *rate)
804 struct video_window *window = impl_from_IBasicVideo(iface);
806 TRACE("window %p, rate %p.\n", window, rate);
808 if (!rate)
809 return E_POINTER;
810 if (!window->pPin->peer)
811 return VFW_E_NOT_CONNECTED;
813 *rate = get_video_format(window)->dwBitErrorRate;
814 return S_OK;
817 static HRESULT WINAPI basic_video_get_VideoWidth(IBasicVideo *iface, LONG *width)
819 struct video_window *window = impl_from_IBasicVideo(iface);
821 TRACE("window %p, width %p.\n", window, width);
823 if (!width)
824 return E_POINTER;
826 *width = get_bitmap_header(window)->biWidth;
828 return S_OK;
831 static HRESULT WINAPI basic_video_get_VideoHeight(IBasicVideo *iface, LONG *height)
833 struct video_window *window = impl_from_IBasicVideo(iface);
835 TRACE("window %p, height %p.\n", window, height);
837 if (!height)
838 return E_POINTER;
840 *height = abs(get_bitmap_header(window)->biHeight);
842 return S_OK;
845 static HRESULT WINAPI basic_video_put_SourceLeft(IBasicVideo *iface, LONG left)
847 struct video_window *window = impl_from_IBasicVideo(iface);
849 TRACE("window %p, left %ld.\n", window, left);
851 if (left < 0 || window->src.right + left - window->src.left > get_bitmap_header(window)->biWidth)
852 return E_INVALIDARG;
854 OffsetRect(&window->src, left - window->src.left, 0);
855 return S_OK;
858 static HRESULT WINAPI basic_video_get_SourceLeft(IBasicVideo *iface, LONG *left)
860 struct video_window *window = impl_from_IBasicVideo(iface);
862 TRACE("window %p, left %p.\n", window, left);
864 if (!left)
865 return E_POINTER;
867 *left = window->src.left;
868 return S_OK;
871 static HRESULT WINAPI basic_video_put_SourceWidth(IBasicVideo *iface, LONG width)
873 struct video_window *window = impl_from_IBasicVideo(iface);
875 TRACE("window %p, width %ld.\n", window, width);
877 if (width <= 0 || window->src.left + width > get_bitmap_header(window)->biWidth)
878 return E_INVALIDARG;
880 window->src.right = window->src.left + width;
881 return S_OK;
884 static HRESULT WINAPI basic_video_get_SourceWidth(IBasicVideo *iface, LONG *width)
886 struct video_window *window = impl_from_IBasicVideo(iface);
888 TRACE("window %p, width %p.\n", window, width);
890 if (!width)
891 return E_POINTER;
893 *width = window->src.right - window->src.left;
894 return S_OK;
897 static HRESULT WINAPI basic_video_put_SourceTop(IBasicVideo *iface, LONG top)
899 struct video_window *window = impl_from_IBasicVideo(iface);
901 TRACE("window %p, top %ld.\n", window, top);
903 if (top < 0 || window->src.bottom + top - window->src.top > get_bitmap_header(window)->biHeight)
904 return E_INVALIDARG;
906 OffsetRect(&window->src, 0, top - window->src.top);
907 return S_OK;
910 static HRESULT WINAPI basic_video_get_SourceTop(IBasicVideo *iface, LONG *top)
912 struct video_window *window = impl_from_IBasicVideo(iface);
914 TRACE("window %p, top %p.\n", window, top);
916 if (!top)
917 return E_POINTER;
919 *top = window->src.top;
920 return S_OK;
923 static HRESULT WINAPI basic_video_put_SourceHeight(IBasicVideo *iface, LONG height)
925 struct video_window *window = impl_from_IBasicVideo(iface);
927 TRACE("window %p, height %ld.\n", window, height);
929 if (height <= 0 || window->src.top + height > get_bitmap_header(window)->biHeight)
930 return E_INVALIDARG;
932 window->src.bottom = window->src.top + height;
933 return S_OK;
936 static HRESULT WINAPI basic_video_get_SourceHeight(IBasicVideo *iface, LONG *height)
938 struct video_window *window = impl_from_IBasicVideo(iface);
940 TRACE("window %p, height %p\n", window, height);
942 if (!height)
943 return E_POINTER;
945 *height = window->src.bottom - window->src.top;
946 return S_OK;
949 static HRESULT WINAPI basic_video_put_DestinationLeft(IBasicVideo *iface, LONG left)
951 struct video_window *window = impl_from_IBasicVideo(iface);
953 TRACE("window %p, left %ld.\n", window, left);
955 window->default_dst = FALSE;
956 OffsetRect(&window->dst, left - window->dst.left, 0);
957 return S_OK;
960 static HRESULT WINAPI basic_video_get_DestinationLeft(IBasicVideo *iface, LONG *left)
962 struct video_window *window = impl_from_IBasicVideo(iface);
964 TRACE("window %p, left %p.\n", window, left);
966 if (!left)
967 return E_POINTER;
969 *left = window->dst.left;
970 return S_OK;
973 static HRESULT WINAPI basic_video_put_DestinationWidth(IBasicVideo *iface, LONG width)
975 struct video_window *window = impl_from_IBasicVideo(iface);
977 TRACE("window %p, width %ld.\n", window, width);
979 if (width <= 0)
980 return E_INVALIDARG;
982 window->default_dst = FALSE;
983 window->dst.right = window->dst.left + width;
984 return S_OK;
987 static HRESULT WINAPI basic_video_get_DestinationWidth(IBasicVideo *iface, LONG *width)
989 struct video_window *window = impl_from_IBasicVideo(iface);
991 TRACE("window %p, width %p.\n", window, width);
993 if (!width)
994 return E_POINTER;
996 *width = window->dst.right - window->dst.left;
997 return S_OK;
1000 static HRESULT WINAPI basic_video_put_DestinationTop(IBasicVideo *iface, LONG top)
1002 struct video_window *window = impl_from_IBasicVideo(iface);
1004 TRACE("window %p, top %ld.\n", window, top);
1006 window->default_dst = FALSE;
1007 OffsetRect(&window->dst, 0, top - window->dst.top);
1008 return S_OK;
1011 static HRESULT WINAPI basic_video_get_DestinationTop(IBasicVideo *iface, LONG *top)
1013 struct video_window *window = impl_from_IBasicVideo(iface);
1015 TRACE("window %p, top %p.\n", window, top);
1017 if (!top)
1018 return E_POINTER;
1020 *top = window->dst.top;
1021 return S_OK;
1024 static HRESULT WINAPI basic_video_put_DestinationHeight(IBasicVideo *iface, LONG height)
1026 struct video_window *window = impl_from_IBasicVideo(iface);
1028 TRACE("window %p, height %ld.\n", window, height);
1030 if (height <= 0)
1031 return E_INVALIDARG;
1033 window->default_dst = FALSE;
1034 window->dst.bottom = window->dst.top + height;
1035 return S_OK;
1038 static HRESULT WINAPI basic_video_get_DestinationHeight(IBasicVideo *iface, LONG *height)
1040 struct video_window *window = impl_from_IBasicVideo(iface);
1042 TRACE("window %p, height %p.\n", window, height);
1044 if (!height)
1045 return E_POINTER;
1047 *height = window->dst.bottom - window->dst.top;
1048 return S_OK;
1051 static HRESULT WINAPI basic_video_SetSourcePosition(IBasicVideo *iface,
1052 LONG left, LONG top, LONG width, LONG height)
1054 struct video_window *window = impl_from_IBasicVideo(iface);
1055 const BITMAPINFOHEADER *bitmap_header = get_bitmap_header(window);
1057 TRACE("window %p, left %ld, top %ld, width %ld, height %ld.\n", window, left, top, width, height);
1059 if (left < 0 || left + width > bitmap_header->biWidth || width <= 0)
1060 return E_INVALIDARG;
1061 if (top < 0 || top + height > bitmap_header->biHeight || height <= 0)
1062 return E_INVALIDARG;
1064 SetRect(&window->src, left, top, left + width, top + height);
1065 return S_OK;
1068 static HRESULT WINAPI basic_video_GetSourcePosition(IBasicVideo *iface,
1069 LONG *left, LONG *top, LONG *width, LONG *height)
1071 struct video_window *window = impl_from_IBasicVideo(iface);
1073 TRACE("window %p, left %p, top %p, width %p, height %p.\n", window, left, top, width, height);
1075 if (!left || !top || !width || !height)
1076 return E_POINTER;
1078 *left = window->src.left;
1079 *top = window->src.top;
1080 *width = window->src.right - window->src.left;
1081 *height = window->src.bottom - window->src.top;
1082 return S_OK;
1085 static HRESULT WINAPI basic_video_SetDefaultSourcePosition(IBasicVideo *iface)
1087 struct video_window *window = impl_from_IBasicVideo(iface);
1088 const BITMAPINFOHEADER *bitmap_header = get_bitmap_header(window);
1090 TRACE("window %p.\n", window);
1092 SetRect(&window->src, 0, 0, bitmap_header->biWidth, bitmap_header->biHeight);
1093 return S_OK;
1096 static HRESULT WINAPI basic_video_SetDestinationPosition(IBasicVideo *iface,
1097 LONG left, LONG top, LONG width, LONG height)
1099 struct video_window *window = impl_from_IBasicVideo(iface);
1101 TRACE("window %p, left %ld, top %ld, width %ld, height %ld.\n", window, left, top, width, height);
1103 if (width <= 0 || height <= 0)
1104 return E_INVALIDARG;
1106 window->default_dst = FALSE;
1107 SetRect(&window->dst, left, top, left + width, top + height);
1108 return S_OK;
1111 static HRESULT WINAPI basic_video_GetDestinationPosition(IBasicVideo *iface,
1112 LONG *left, LONG *top, LONG *width, LONG *height)
1114 struct video_window *window = impl_from_IBasicVideo(iface);
1116 TRACE("window %p, left %p, top %p, width %p, height %p.\n", window, left, top, width, height);
1118 if (!left || !top || !width || !height)
1119 return E_POINTER;
1121 *left = window->dst.left;
1122 *top = window->dst.top;
1123 *width = window->dst.right - window->dst.left;
1124 *height = window->dst.bottom - window->dst.top;
1125 return S_OK;
1128 static HRESULT WINAPI basic_video_SetDefaultDestinationPosition(IBasicVideo *iface)
1130 struct video_window *window = impl_from_IBasicVideo(iface);
1132 TRACE("window %p.\n", window);
1134 window->default_dst = TRUE;
1135 GetClientRect(window->hwnd, &window->dst);
1136 return S_OK;
1139 static HRESULT WINAPI basic_video_GetVideoSize(IBasicVideo *iface, LONG *width, LONG *height)
1141 struct video_window *window = impl_from_IBasicVideo(iface);
1142 const BITMAPINFOHEADER *bitmap_header = get_bitmap_header(window);
1144 TRACE("window %p, width %p, height %p.\n", window, width, height);
1146 if (!width || !height)
1147 return E_POINTER;
1149 *width = bitmap_header->biWidth;
1150 *height = bitmap_header->biHeight;
1151 return S_OK;
1154 static HRESULT WINAPI basic_video_GetVideoPaletteEntries(IBasicVideo *iface,
1155 LONG start, LONG count, LONG *ret_count, LONG *palette)
1157 struct video_window *window = impl_from_IBasicVideo(iface);
1159 FIXME("window %p, start %ld, count %ld, ret_count %p, palette %p, stub!\n",
1160 window, start, count, ret_count, palette);
1162 if (!ret_count || !palette)
1163 return E_POINTER;
1165 *ret_count = 0;
1166 return VFW_E_NO_PALETTE_AVAILABLE;
1169 static HRESULT WINAPI basic_video_GetCurrentImage(IBasicVideo *iface, LONG *size, LONG *image)
1171 struct video_window *window = impl_from_IBasicVideo(iface);
1173 TRACE("window %p, size %p, image %p.\n", window, size, image);
1175 if (!size || !image)
1176 return E_POINTER;
1178 return window->ops->get_current_image(window, size, image);
1181 static HRESULT WINAPI basic_video_IsUsingDefaultSource(IBasicVideo *iface)
1183 struct video_window *window = impl_from_IBasicVideo(iface);
1184 const BITMAPINFOHEADER *bitmap_header = get_bitmap_header(window);
1186 TRACE("window %p.\n", window);
1188 if (!window->src.left && !window->src.top
1189 && window->src.right == bitmap_header->biWidth
1190 && window->src.bottom == bitmap_header->biHeight)
1191 return S_OK;
1192 return S_FALSE;
1195 static HRESULT WINAPI basic_video_IsUsingDefaultDestination(IBasicVideo *iface)
1197 struct video_window *window = impl_from_IBasicVideo(iface);
1199 TRACE("window %p.\n", window);
1201 return window->default_dst ? S_OK : S_FALSE;
1204 static const IBasicVideoVtbl basic_video_vtbl =
1206 basic_video_QueryInterface,
1207 basic_video_AddRef,
1208 basic_video_Release,
1209 basic_video_GetTypeInfoCount,
1210 basic_video_GetTypeInfo,
1211 basic_video_GetIDsOfNames,
1212 basic_video_Invoke,
1213 basic_video_get_AvgTimePerFrame,
1214 basic_video_get_BitRate,
1215 basic_video_get_BitErrorRate,
1216 basic_video_get_VideoWidth,
1217 basic_video_get_VideoHeight,
1218 basic_video_put_SourceLeft,
1219 basic_video_get_SourceLeft,
1220 basic_video_put_SourceWidth,
1221 basic_video_get_SourceWidth,
1222 basic_video_put_SourceTop,
1223 basic_video_get_SourceTop,
1224 basic_video_put_SourceHeight,
1225 basic_video_get_SourceHeight,
1226 basic_video_put_DestinationLeft,
1227 basic_video_get_DestinationLeft,
1228 basic_video_put_DestinationWidth,
1229 basic_video_get_DestinationWidth,
1230 basic_video_put_DestinationTop,
1231 basic_video_get_DestinationTop,
1232 basic_video_put_DestinationHeight,
1233 basic_video_get_DestinationHeight,
1234 basic_video_SetSourcePosition,
1235 basic_video_GetSourcePosition,
1236 basic_video_SetDefaultSourcePosition,
1237 basic_video_SetDestinationPosition,
1238 basic_video_GetDestinationPosition,
1239 basic_video_SetDefaultDestinationPosition,
1240 basic_video_GetVideoSize,
1241 basic_video_GetVideoPaletteEntries,
1242 basic_video_GetCurrentImage,
1243 basic_video_IsUsingDefaultSource,
1244 basic_video_IsUsingDefaultDestination
1247 void video_window_unregister_class(void)
1249 if (!UnregisterClassW(class_name, NULL) && GetLastError() != ERROR_CLASS_DOES_NOT_EXIST)
1250 ERR("Failed to unregister class, error %lu.\n", GetLastError());
1253 void video_window_init(struct video_window *window, const IVideoWindowVtbl *vtbl,
1254 struct strmbase_filter *owner, struct strmbase_pin *pin, const struct video_window_ops *ops)
1256 memset(window, 0, sizeof(*window));
1257 window->ops = ops;
1258 window->IVideoWindow_iface.lpVtbl = vtbl;
1259 window->IBasicVideo_iface.lpVtbl = &basic_video_vtbl;
1260 window->default_dst = TRUE;
1261 window->AutoShow = OATRUE;
1262 window->pFilter = owner;
1263 window->pPin = pin;
1266 void video_window_cleanup(struct video_window *window)
1268 if (window->hwnd)
1270 /* Media Player Classic deadlocks if WM_PARENTNOTIFY is sent, so clear
1271 * the child style first. Just like Windows, we don't actually unparent
1272 * the window, to prevent extra focus events from being generated since
1273 * it would become top-level for a brief period before being destroyed. */
1274 SetWindowLongW(window->hwnd, GWL_STYLE, GetWindowLongW(window->hwnd, GWL_STYLE) & ~WS_CHILD);
1276 SendMessageW(window->hwnd, WM_QUARTZ_DESTROY, 0, 0);
1277 window->hwnd = NULL;