From d765edc411a6844f6322dd9da280aa0436391828 Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Fri, 18 Mar 2022 14:27:55 +0100 Subject: [PATCH] win32u: Move NtUserCreateWindowEx implementation from user32. Signed-off-by: Jacek Caban Signed-off-by: Huw Davies Signed-off-by: Alexandre Julliard --- dlls/user32/class.c | 11 - dlls/user32/controls.h | 1 - dlls/user32/driver.c | 13 +- dlls/user32/user_main.c | 12 +- dlls/user32/user_private.h | 3 - dlls/user32/win.c | 544 ++--------------------------------- dlls/user32/win.h | 1 - dlls/user32/winpos.c | 176 ------------ dlls/user32/winproc.c | 39 --- dlls/win32u/class.c | 29 ++ dlls/win32u/dce.c | 11 + dlls/win32u/driver.c | 6 + dlls/win32u/gdiobj.c | 1 + dlls/win32u/menu.c | 8 + dlls/win32u/message.c | 19 +- dlls/win32u/ntuser_private.h | 39 +-- dlls/win32u/sysparams.c | 5 +- dlls/win32u/win32u.spec | 2 +- dlls/win32u/win32u_private.h | 10 +- dlls/win32u/window.c | 488 ++++++++++++++++++++++++++++++- dlls/win32u/wrappers.c | 12 + include/ntuser.h | 10 +- 22 files changed, 616 insertions(+), 824 deletions(-) diff --git a/dlls/user32/class.c b/dlls/user32/class.c index bd0943f6366..e2eb60d8bbf 100644 --- a/dlls/user32/class.c +++ b/dlls/user32/class.c @@ -42,8 +42,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(class); static INIT_ONCE init_once = INIT_ONCE_STATIC_INIT; -#define CLASS_OTHER_PROCESS ((CLASS *)1) - static inline const char *debugstr_us( const UNICODE_STRING *us ) { if (!us) return ""; @@ -351,15 +349,6 @@ void register_desktop_class(void) } -/*********************************************************************** - * get_class_winproc - */ -WNDPROC get_class_winproc( CLASS *class ) -{ - return class->winproc; -} - - /*********************************************************************** * RegisterClassA (USER32.@) * diff --git a/dlls/user32/controls.h b/dlls/user32/controls.h index f33bbf35115..574143de438 100644 --- a/dlls/user32/controls.h +++ b/dlls/user32/controls.h @@ -114,7 +114,6 @@ struct tagWND; extern ATOM get_int_atom_value( UNICODE_STRING *name ) DECLSPEC_HIDDEN; extern void register_builtin_classes(void) DECLSPEC_HIDDEN; extern void register_desktop_class(void) DECLSPEC_HIDDEN; -extern WNDPROC get_class_winproc( struct tagCLASS *class ) DECLSPEC_HIDDEN; /* defwnd proc */ extern HBRUSH DEFWND_ControlColor( HDC hDC, UINT ctlType ) DECLSPEC_HIDDEN; diff --git a/dlls/user32/driver.c b/dlls/user32/driver.c index 25ed33ff073..560a1ed0625 100644 --- a/dlls/user32/driver.c +++ b/dlls/user32/driver.c @@ -74,11 +74,6 @@ static void CDECL nulldrv_UpdateClipboard(void) { } -static BOOL CDECL nulldrv_CreateWindow( HWND hwnd ) -{ - return TRUE; -} - static DWORD CDECL nulldrv_MsgWaitForMultipleObjectsEx( DWORD count, const HANDLE *handles, DWORD timeout, DWORD mask, DWORD flags ) { @@ -132,11 +127,6 @@ static void CDECL loaderdrv_UpdateClipboard(void) load_driver()->pUpdateClipboard(); } -static BOOL CDECL loaderdrv_CreateWindow( HWND hwnd ) -{ - return load_driver()->pCreateWindow( hwnd ); -} - static struct user_driver_funcs lazy_load_driver = { { NULL }, @@ -164,7 +154,7 @@ static struct user_driver_funcs lazy_load_driver = NULL, /* windowing functions */ NULL, - loaderdrv_CreateWindow, + NULL, NULL, NULL, NULL, @@ -213,7 +203,6 @@ void CDECL __wine_set_user_driver( const struct user_driver_funcs *funcs, UINT v SET_USER_FUNC(SetCursorPos); SET_USER_FUNC(UpdateClipboard); - SET_USER_FUNC(CreateWindow); SET_USER_FUNC(MsgWaitForMultipleObjectsEx); SET_USER_FUNC(SetWindowIcon); SET_USER_FUNC(SetWindowText); diff --git a/dlls/user32/user_main.c b/dlls/user32/user_main.c index 5a3db40c93c..a7416d4a045 100644 --- a/dlls/user32/user_main.c +++ b/dlls/user32/user_main.c @@ -140,7 +140,12 @@ static void CDECL notify_ime( HWND hwnd, UINT param ) if (ime_default) SendMessageW( ime_default, WM_IME_INTERNAL, param, HandleToUlong(hwnd) ); } -void WINAPI unregister_imm( HWND hwnd ) +static BOOL WINAPI register_imm( HWND hwnd ) +{ + return imm_register_window( hwnd ); +} + +static void WINAPI unregister_imm( HWND hwnd ) { imm_unregister_window( hwnd ); } @@ -149,7 +154,6 @@ static void CDECL free_win_ptr( WND *win ) { HeapFree( GetProcessHeap(), 0, win->text ); HeapFree( GetProcessHeap(), 0, win->pScroll ); - HeapFree( GetProcessHeap(), 0, win ); } static const struct user_callbacks user_funcs = @@ -163,8 +167,10 @@ static const struct user_callbacks user_funcs = PostMessageW, SendInput, SendMessageTimeoutW, + SendMessageA, SendMessageW, SendNotifyMessageW, + SetSystemMenu, ShowCaret, WaitForInputIdle, free_win_ptr, @@ -172,9 +178,11 @@ static const struct user_callbacks user_funcs = notify_ime, register_builtin_classes, MSG_SendInternalMessageTimeout, + MENU_SetMenu, SCROLL_SetStandardScrollPainted, (void *)__wine_set_user_driver, set_window_pos, + register_imm, unregister_imm, }; diff --git a/dlls/user32/user_private.h b/dlls/user32/user_private.h index d512ecb1501..e08dc2d2d89 100644 --- a/dlls/user32/user_private.h +++ b/dlls/user32/user_private.h @@ -128,9 +128,6 @@ extern BOOL USER_IsExitingThread( DWORD tid ) DECLSPEC_HIDDEN; typedef LRESULT (*winproc_callback_t)( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp, LRESULT *result, void *arg ); -extern WNDPROC WINPROC_GetProc( WNDPROC proc, BOOL unicode ) DECLSPEC_HIDDEN; -extern BOOL WINPROC_IsUnicode( WNDPROC proc, BOOL def_val ) DECLSPEC_HIDDEN; - extern LRESULT WINPROC_CallProcAtoW( winproc_callback_t callback, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, LRESULT *result, void *arg, enum wm_char_mapping mapping ) DECLSPEC_HIDDEN; diff --git a/dlls/user32/win.c b/dlls/user32/win.c index db5158c0b6f..6da37261f3c 100644 --- a/dlls/user32/win.c +++ b/dlls/user32/win.c @@ -76,124 +76,6 @@ void *free_user_handle( HANDLE handle, unsigned int type ) } -/*********************************************************************** - * create_window_handle - * - * Create a window handle with the server. - */ -static WND *create_window_handle( HWND parent, HWND owner, UNICODE_STRING *name, - HINSTANCE instance, BOOL unicode, - DWORD style, DWORD ex_style ) -{ - WND *win; - HWND handle = 0, full_parent = 0, full_owner = 0; - struct tagCLASS *class = NULL; - int extra_bytes = 0; - DPI_AWARENESS awareness = GetAwarenessFromDpiAwarenessContext( GetThreadDpiAwarenessContext() ); - UINT dpi = 0; - - SERVER_START_REQ( create_window ) - { - req->parent = wine_server_user_handle( parent ); - req->owner = wine_server_user_handle( owner ); - req->instance = wine_server_client_ptr( instance ); - req->dpi = GetDpiForSystem(); - req->awareness = awareness; - req->style = style; - req->ex_style = ex_style; - if (!(req->atom = get_int_atom_value( name )) && name->Length) - wine_server_add_data( req, name->Buffer, name->Length ); - if (!wine_server_call_err( req )) - { - handle = wine_server_ptr_handle( reply->handle ); - full_parent = wine_server_ptr_handle( reply->parent ); - full_owner = wine_server_ptr_handle( reply->owner ); - extra_bytes = reply->extra; - dpi = reply->dpi; - awareness = reply->awareness; - class = wine_server_get_ptr( reply->class_ptr ); - } - } - SERVER_END_REQ; - - if (!handle) - { - WARN( "error %d creating window\n", GetLastError() ); - return NULL; - } - - if (!(win = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, - sizeof(WND) + extra_bytes - sizeof(win->wExtra) ))) - { - SERVER_START_REQ( destroy_window ) - { - req->handle = wine_server_user_handle( handle ); - wine_server_call( req ); - } - SERVER_END_REQ; - SetLastError( ERROR_NOT_ENOUGH_MEMORY ); - return NULL; - } - - if (!parent) /* if parent is 0 we don't have a desktop window yet */ - { - struct user_thread_info *thread_info = get_user_thread_info(); - - if (name->Buffer == (LPCWSTR)DESKTOP_CLASS_ATOM) - { - if (!thread_info->top_window) thread_info->top_window = full_parent ? full_parent : handle; - else assert( full_parent == thread_info->top_window ); - if (full_parent && !NtUserCallHwnd( thread_info->top_window, NtUserCreateDesktopWindow )) - ERR( "failed to create desktop window\n" ); - register_builtin_classes(); - } - else /* HWND_MESSAGE parent */ - { - if (!thread_info->msg_window && !full_parent) thread_info->msg_window = handle; - } - } - - USER_Lock(); - - win->obj.handle = handle; - win->obj.type = NTUSER_OBJ_WINDOW; - win->parent = full_parent; - win->owner = full_owner; - win->class = class; - win->winproc = get_class_winproc( class ); - win->cbWndExtra = extra_bytes; - win->dpi = dpi; - win->dpi_awareness = awareness; - NtUserCallTwoParam( HandleToUlong(handle), (UINT_PTR)win, NtUserSetHandlePtr ); - if (WINPROC_IsUnicode( win->winproc, unicode )) win->flags |= WIN_ISUNICODE; - return win; -} - - -/*********************************************************************** - * free_window_handle - * - * Free a window handle. - */ -static void free_window_handle( HWND hwnd ) -{ - struct user_object *ptr; - - if ((ptr = get_user_handle_ptr( hwnd, NTUSER_OBJ_WINDOW )) && ptr != OBJ_OTHER_PROCESS) - { - SERVER_START_REQ( destroy_window ) - { - req->handle = wine_server_user_handle( hwnd ); - wine_server_call( req ); - NtUserCallTwoParam( HandleToUlong(hwnd), 0, NtUserSetHandlePtr ); - } - SERVER_END_REQ; - USER_Unlock(); - HeapFree( GetProcessHeap(), 0, ptr ); - } -} - - /******************************************************************* * list_window_children * @@ -242,22 +124,6 @@ static HWND *list_window_children( HDESK desktop, HWND hwnd, UNICODE_STRING *cla } -/******************************************************************* - * send_parent_notify - */ -static void send_parent_notify( HWND hwnd, UINT msg ) -{ - if ((GetWindowLongW( hwnd, GWL_STYLE ) & (WS_CHILD | WS_POPUP)) == WS_CHILD && - !(GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY)) - { - HWND parent = GetParent(hwnd); - if (parent && parent != GetDesktopWindow()) - SendMessageW( parent, WM_PARENTNOTIFY, - MAKEWPARAM( msg, GetWindowLongPtrW( hwnd, GWLP_ID )), (LPARAM)hwnd ); - } -} - - /******************************************************************* * get_hwnd_message_parent * @@ -707,66 +573,6 @@ other_process: } -/*********************************************************************** - * WIN_FixCoordinates - * - * Fix the coordinates - Helper for WIN_CreateWindowEx. - * returns default show mode in sw. - */ -static void WIN_FixCoordinates( CREATESTRUCTW *cs, INT *sw) -{ -#define IS_DEFAULT(x) ((x) == CW_USEDEFAULT || (x) == (SHORT)0x8000) - if (cs->style & (WS_CHILD | WS_POPUP)) - { - if (IS_DEFAULT(cs->x)) cs->x = cs->y = 0; - if (IS_DEFAULT(cs->cx)) cs->cx = cs->cy = 0; - } - else /* overlapped window */ - { - HMONITOR monitor; - MONITORINFO mon_info; - STARTUPINFOW info; - - if (!IS_DEFAULT(cs->x) && !IS_DEFAULT(cs->cx) && !IS_DEFAULT(cs->cy)) return; - - monitor = MonitorFromWindow( cs->hwndParent, MONITOR_DEFAULTTOPRIMARY ); - mon_info.cbSize = sizeof(mon_info); - GetMonitorInfoW( monitor, &mon_info ); - GetStartupInfoW( &info ); - - if (IS_DEFAULT(cs->x)) - { - if (!IS_DEFAULT(cs->y)) *sw = cs->y; - cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : mon_info.rcWork.left; - cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : mon_info.rcWork.top; - } - - if (IS_DEFAULT(cs->cx)) - { - if (info.dwFlags & STARTF_USESIZE) - { - cs->cx = info.dwXSize; - cs->cy = info.dwYSize; - } - else - { - cs->cx = (mon_info.rcWork.right - mon_info.rcWork.left) * 3 / 4 - cs->x; - cs->cy = (mon_info.rcWork.bottom - mon_info.rcWork.top) * 3 / 4 - cs->y; - } - } - /* neither x nor cx are default. Check the y values . - * In the trace we see Outlook and Outlook Express using - * cy set to CW_USEDEFAULT when opening the address book. - */ - else if (IS_DEFAULT(cs->cy)) - { - FIXME("Strange use of CW_USEDEFAULT in nHeight\n"); - cs->cy = (mon_info.rcWork.bottom - mon_info.rcWork.top) * 3 / 4 - cs->y; - } - } -#undef IS_DEFAULT -} - /*********************************************************************** * dump_window_styles */ @@ -885,40 +691,6 @@ static BOOL is_default_coord( int x ) return x == CW_USEDEFAULT || x == 0x8000; } -/*********************************************************************** - * map_dpi_create_struct - */ -static void map_dpi_create_struct( CREATESTRUCTW *cs, UINT dpi_from, UINT dpi_to ) -{ - if (!dpi_from && !dpi_to) return; - if (!dpi_from || !dpi_to) - { - POINT pt = { cs->x, cs->y }; - UINT mon_dpi = get_monitor_dpi( MonitorFromPoint( pt, MONITOR_DEFAULTTONEAREST )); - if (!dpi_from) dpi_from = mon_dpi; - else dpi_to = mon_dpi; - } - if (dpi_from == dpi_to) return; - cs->x = MulDiv( cs->x, dpi_to, dpi_from ); - cs->y = MulDiv( cs->y, dpi_to, dpi_from ); - cs->cx = MulDiv( cs->cx, dpi_to, dpi_from ); - cs->cy = MulDiv( cs->cy, dpi_to, dpi_from ); -} - -/*********************************************************************** - * fix_exstyle - */ -static DWORD fix_exstyle( DWORD style, DWORD exstyle ) -{ - if ((exstyle & WS_EX_DLGMODALFRAME) || - (!(exstyle & WS_EX_STATICEDGE) && - (style & (WS_DLGFRAME | WS_THICKFRAME)))) - exstyle |= WS_EX_WINDOWEDGE; - else - exstyle &= ~WS_EX_WINDOWEDGE; - return exstyle; -} - /*********************************************************************** * WIN_CreateWindowEx * @@ -926,19 +698,14 @@ static DWORD fix_exstyle( DWORD style, DWORD exstyle ) */ HWND WIN_CreateWindowEx( CREATESTRUCTW *cs, LPCWSTR className, HINSTANCE module, BOOL unicode ) { - INT cx, cy, style, ex_style, sw = SW_SHOW; - LRESULT result; - RECT rect; - WND *wndPtr; - HWND hwnd, parent, owner, top_child = 0; - UINT win_dpi, thread_dpi = get_thread_dpi(); - DPI_AWARENESS_CONTEXT context; + HWND hwnd, top_child = 0; MDICREATESTRUCTW mdi_cs; UNICODE_STRING class; CBT_CREATEWNDW cbtc; - CREATESTRUCTW cbcs; + WNDCLASSEXW info; + HMENU menu; - if (!get_class_info( module, className, NULL, &class, FALSE )) return FALSE; + if (!get_class_info( module, className, &info, &class, FALSE )) return FALSE; TRACE("%s %s%s%s ex=%08x style=%08x %d,%d %dx%d parent=%p menu=%p inst=%p params=%p\n", unicode ? debugstr_w(cs->lpszName) : debugstr_a((LPCSTR)cs->lpszName), @@ -1030,300 +797,25 @@ HWND WIN_CreateWindowEx( CREATESTRUCTW *cs, LPCWSTR className, HINSTANCE module, } } - /* Find the parent window */ - - parent = cs->hwndParent; - owner = 0; - - if (cs->hwndParent == HWND_MESSAGE) + /* FIXME: move to win32u */ + if (!cs->hwndParent && className != (const WCHAR *)DESKTOP_CLASS_ATOM && + (IS_INTRESOURCE(className) || wcsicmp( className, L"Message" ))) { - cs->hwndParent = parent = get_hwnd_message_parent(); - } - else if (cs->hwndParent) - { - if ((cs->style & (WS_CHILD|WS_POPUP)) != WS_CHILD) - { - parent = GetDesktopWindow(); - owner = cs->hwndParent; - } - else - { - DWORD parent_style = GetWindowLongW( parent, GWL_EXSTYLE ); - if ((parent_style & WS_EX_LAYOUTRTL) && !(parent_style & WS_EX_NOINHERITLAYOUT)) - cs->dwExStyle |= WS_EX_LAYOUTRTL; - } - } - else - { - if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD) - { - WARN("No parent for child window\n" ); - SetLastError(ERROR_TLW_WITH_WSCHILD); - return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */ - } - - /* are we creating the desktop or HWND_MESSAGE parent itself? */ - if (className != (LPCWSTR)DESKTOP_CLASS_ATOM && - (IS_INTRESOURCE(className) || wcsicmp( className, L"Message" ))) - { - DWORD layout; - GetProcessDefaultLayout( &layout ); - if (layout & LAYOUT_RTL) cs->dwExStyle |= WS_EX_LAYOUTRTL; - parent = GetDesktopWindow(); - } + DWORD layout; + GetProcessDefaultLayout( &layout ); + if (layout & LAYOUT_RTL) cs->dwExStyle |= WS_EX_LAYOUTRTL; } - WIN_FixCoordinates(cs, &sw); /* fix default coordinates */ - cs->dwExStyle = fix_exstyle(cs->style, cs->dwExStyle); + menu = cs->hMenu; + if (!menu && info.lpszMenuName && (cs->style & (WS_CHILD | WS_POPUP)) != WS_CHILD) + menu = LoadMenuW( cs->hInstance, info.lpszMenuName ); - /* Create the window structure */ - - style = cs->style & ~WS_VISIBLE; - ex_style = cs->dwExStyle & ~WS_EX_LAYERED; - if (!(wndPtr = create_window_handle( parent, owner, &class, module, - unicode, style, ex_style ))) - return 0; - hwnd = wndPtr->obj.handle; - - /* Fill the window structure */ - - wndPtr->tid = GetCurrentThreadId(); - wndPtr->hInstance = cs->hInstance; - wndPtr->text = NULL; - wndPtr->dwStyle = style; - wndPtr->dwExStyle = ex_style; - wndPtr->wIDmenu = 0; - wndPtr->helpContext = 0; - wndPtr->pScroll = NULL; - wndPtr->userdata = 0; - wndPtr->hIcon = 0; - wndPtr->hIconSmall = 0; - wndPtr->hIconSmall2 = 0; - wndPtr->hSysMenu = 0; - - wndPtr->min_pos.x = wndPtr->min_pos.y = -1; - wndPtr->max_pos.x = wndPtr->max_pos.y = -1; - SetRect( &wndPtr->normal_rect, cs->x, cs->y, cs->x + cs->cx, cs->y + cs->cy ); - - if (wndPtr->dwStyle & WS_SYSMENU) SetSystemMenu( hwnd, 0 ); - - /* call the WH_CBT hook */ - - WIN_ReleasePtr( wndPtr ); - cbcs = *cs; - cbtc.lpcs = &cbcs; - cbtc.hwndInsertAfter = HWND_TOP; - if (HOOK_CallHooks( WH_CBT, HCBT_CREATEWND, (WPARAM)hwnd, (LPARAM)&cbtc, unicode ) || - !(wndPtr = WIN_GetPtr( hwnd ))) - { - free_window_handle( hwnd ); - return 0; - } - - /* - * Correct the window styles. - * - * It affects only the style loaded into the WIN structure. - */ - - if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD) - { - wndPtr->dwStyle |= WS_CLIPSIBLINGS; - if (!(wndPtr->dwStyle & WS_POPUP)) - wndPtr->dwStyle |= WS_CAPTION; - } - - wndPtr->dwExStyle = cs->dwExStyle; - /* WS_EX_WINDOWEDGE depends on some other styles */ - if ((wndPtr->dwStyle & (WS_DLGFRAME | WS_THICKFRAME)) && - !(wndPtr->dwStyle & (WS_CHILD | WS_POPUP))) - wndPtr->dwExStyle |= WS_EX_WINDOWEDGE; - - if (!(wndPtr->dwStyle & (WS_CHILD | WS_POPUP))) - wndPtr->flags |= WIN_NEED_SIZE; - - SERVER_START_REQ( set_window_info ) - { - req->handle = wine_server_user_handle( hwnd ); - req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE | SET_WIN_UNICODE; - req->style = wndPtr->dwStyle; - req->ex_style = wndPtr->dwExStyle; - req->instance = wine_server_client_ptr( wndPtr->hInstance ); - req->is_unicode = (wndPtr->flags & WIN_ISUNICODE) != 0; - req->extra_offset = -1; - wine_server_call( req ); - } - SERVER_END_REQ; - - /* Set the window menu */ - - if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD) - { - if (cs->hMenu) - { - if (!MENU_SetMenu(hwnd, cs->hMenu)) - { - WIN_ReleasePtr( wndPtr ); - free_window_handle( hwnd ); - return 0; - } - } - else - { - LPCWSTR menuName = (LPCWSTR)GetClassLongPtrW( hwnd, GCLP_MENUNAME ); - if (menuName) - { - cs->hMenu = LoadMenuW( cs->hInstance, menuName ); - if (cs->hMenu) MENU_SetMenu( hwnd, cs->hMenu ); - } - } - } - else SetWindowLongPtrW( hwnd, GWLP_ID, (ULONG_PTR)cs->hMenu ); - - win_dpi = wndPtr->dpi; - WIN_ReleasePtr( wndPtr ); - - if (parent) map_dpi_create_struct( cs, thread_dpi, win_dpi ); - - context = SetThreadDpiAwarenessContext( GetWindowDpiAwarenessContext( hwnd )); - - /* send the WM_GETMINMAXINFO message and fix the size if needed */ - - cx = cs->cx; - cy = cs->cy; - if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD))) - { - MINMAXINFO info = WINPOS_GetMinMaxInfo( hwnd ); - cx = max( min( cx, info.ptMaxTrackSize.x ), info.ptMinTrackSize.x ); - cy = max( min( cy, info.ptMaxTrackSize.y ), info.ptMinTrackSize.y ); - } - - if (cx < 0) cx = 0; - if (cy < 0) cy = 0; - SetRect( &rect, cs->x, cs->y, cs->x + cx, cs->y + cy ); - /* check for wraparound */ - if (cs->x > 0x7fffffff - cx) rect.right = 0x7fffffff; - if (cs->y > 0x7fffffff - cy) rect.bottom = 0x7fffffff; - if (!set_window_pos( hwnd, 0, SWP_NOZORDER | SWP_NOACTIVATE, &rect, &rect, NULL )) goto failed; - - /* send WM_NCCREATE */ - - TRACE( "hwnd %p cs %d,%d %dx%d %s\n", hwnd, cs->x, cs->y, cs->cx, cs->cy, wine_dbgstr_rect(&rect) ); - if (unicode) - result = SendMessageW( hwnd, WM_NCCREATE, 0, (LPARAM)cs ); - else - result = SendMessageA( hwnd, WM_NCCREATE, 0, (LPARAM)cs ); - if (!result) - { - WARN( "%p: aborted by WM_NCCREATE\n", hwnd ); - goto failed; - } - - /* create default IME window */ - - if (imm_register_window && !is_desktop_window( hwnd ) && - parent != get_hwnd_message_parent() && imm_register_window( hwnd )) - { - TRACE("register IME window for %p\n", hwnd); - win_set_flags( hwnd, WIN_HAS_IME_WIN, 0 ); - } - - /* send WM_NCCALCSIZE */ - - if (WIN_GetRectangles( hwnd, COORDS_PARENT, &rect, NULL )) - { - /* yes, even if the CBT hook was called with HWND_TOP */ - HWND insert_after = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) ? HWND_BOTTOM : HWND_TOP; - RECT client_rect = rect; - - /* the rectangle is in screen coords for WM_NCCALCSIZE when wparam is FALSE */ - MapWindowPoints( parent, 0, (POINT *)&client_rect, 2 ); - SendMessageW( hwnd, WM_NCCALCSIZE, FALSE, (LPARAM)&client_rect ); - MapWindowPoints( 0, parent, (POINT *)&client_rect, 2 ); - set_window_pos( hwnd, insert_after, SWP_NOACTIVATE, &rect, &client_rect, NULL ); - } - else goto failed; - - /* send WM_CREATE */ - - if (unicode) - result = SendMessageW( hwnd, WM_CREATE, 0, (LPARAM)cs ); - else - result = SendMessageA( hwnd, WM_CREATE, 0, (LPARAM)cs ); - if (result == -1) goto failed; - - /* call the driver */ - - if (!USER_Driver->pCreateWindow( hwnd )) goto failed; - - NtUserNotifyWinEvent( EVENT_OBJECT_CREATE, hwnd, OBJID_WINDOW, 0 ); - - /* send the size messages */ - - if (!(win_get_flags( hwnd ) & WIN_NEED_SIZE)) - { - WIN_GetRectangles( hwnd, COORDS_PARENT, NULL, &rect ); - SendMessageW( hwnd, WM_SIZE, SIZE_RESTORED, - MAKELONG(rect.right-rect.left, rect.bottom-rect.top)); - SendMessageW( hwnd, WM_MOVE, 0, MAKELONG( rect.left, rect.top ) ); - } - - /* Show the window, maximizing or minimizing if needed */ - - style = WIN_SetStyle( hwnd, 0, WS_MAXIMIZE | WS_MINIMIZE ); - if (style & (WS_MINIMIZE | WS_MAXIMIZE)) - { - RECT newPos; - UINT swFlag = (style & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE; - - swFlag = WINPOS_MinMaximize( hwnd, swFlag, &newPos ); - swFlag |= SWP_FRAMECHANGED; /* Frame always gets changed */ - if (!(style & WS_VISIBLE) || (style & WS_CHILD) || GetActiveWindow()) swFlag |= SWP_NOACTIVATE; - NtUserSetWindowPos( hwnd, 0, newPos.left, newPos.top, newPos.right - newPos.left, - newPos.bottom - newPos.top, swFlag ); - } - - /* Notify the parent window only */ - - send_parent_notify( hwnd, WM_CREATE ); - if (!IsWindow( hwnd )) - { - SetThreadDpiAwarenessContext( context ); - return 0; - } - - if (parent == GetDesktopWindow()) - PostMessageW( parent, WM_PARENTNOTIFY, WM_CREATE, (LPARAM)hwnd ); - - if (cs->style & WS_VISIBLE) - { - if (cs->style & WS_MAXIMIZE) - sw = SW_SHOW; - else if (cs->style & WS_MINIMIZE) - sw = SW_SHOWMINIMIZED; - - NtUserShowWindow( hwnd, sw ); - if (cs->dwExStyle & WS_EX_MDICHILD) - { - SendMessageW(cs->hwndParent, WM_MDIREFRESHMENU, 0, 0); - /* ShowWindow won't activate child windows */ - NtUserSetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE ); - } - } - - /* Call WH_SHELL hook */ - - if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER )) - HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0, TRUE ); - - TRACE("created window %p\n", hwnd); - SetThreadDpiAwarenessContext( context ); + cbtc.lpcs = cs; + hwnd = NtUserCreateWindowEx( cs->dwExStyle, &class, NULL, NULL, cs->style, cs->x, cs->y, + cs->cx, cs->cy, cs->hwndParent, menu, module, + cs->lpCreateParams, 0, &cbtc, 0, !unicode ); + if (!hwnd && menu && menu != cs->hMenu) DestroyMenu( menu ); return hwnd; - -failed: - NtUserCallHwnd( hwnd, NtUserDestroyWindowHandle ); - SetThreadDpiAwarenessContext( context ); - return 0; } diff --git a/dlls/user32/win.h b/dlls/user32/win.h index 79a57de6bb9..b7b8568efdd 100644 --- a/dlls/user32/win.h +++ b/dlls/user32/win.h @@ -66,7 +66,6 @@ extern MINMAXINFO WINPOS_GetMinMaxInfo( HWND hwnd ) DECLSPEC_HIDDEN; extern LONG WINPOS_HandleWindowPosChanging(HWND hwnd, WINDOWPOS *winpos) DECLSPEC_HIDDEN; extern HWND WINPOS_WindowFromPoint( HWND hwndScope, POINT pt, INT *hittest ) DECLSPEC_HIDDEN; extern void WINPOS_ActivateOtherWindow( HWND hwnd ) DECLSPEC_HIDDEN; -extern UINT WINPOS_MinMaximize( HWND hwnd, UINT cmd, LPRECT rect ) DECLSPEC_HIDDEN; extern void WINPOS_SysCommandSizeMove( HWND hwnd, WPARAM wParam ) DECLSPEC_HIDDEN; extern UINT get_monitor_dpi( HMONITOR monitor ) DECLSPEC_HIDDEN; diff --git a/dlls/user32/winpos.c b/dlls/user32/winpos.c index 4ba0c47626d..6c0f49c8753 100644 --- a/dlls/user32/winpos.c +++ b/dlls/user32/winpos.c @@ -622,182 +622,6 @@ static void get_next_minimized_child_pos( const RECT *parent, const MINIMIZEDMET } } -static POINT get_minimized_pos( HWND hwnd, POINT pt ) -{ - RECT rect, rectParent; - HWND parent, child; - HRGN hrgn, tmp; - MINIMIZEDMETRICS metrics; - int width, height; - - parent = NtUserGetAncestor( hwnd, GA_PARENT ); - if (parent == GetDesktopWindow()) - { - MONITORINFO mon_info; - HMONITOR monitor = MonitorFromWindow( hwnd, MONITOR_DEFAULTTOPRIMARY ); - - mon_info.cbSize = sizeof( mon_info ); - GetMonitorInfoW( monitor, &mon_info ); - rectParent = mon_info.rcWork; - } - else GetClientRect( parent, &rectParent ); - - if ((pt.x >= rectParent.left) && (pt.x + GetSystemMetrics( SM_CXMINIMIZED ) < rectParent.right) && - (pt.y >= rectParent.top) && (pt.y + GetSystemMetrics( SM_CYMINIMIZED ) < rectParent.bottom)) - return pt; /* The icon already has a suitable position */ - - width = GetSystemMetrics( SM_CXMINIMIZED ); - height = GetSystemMetrics( SM_CYMINIMIZED ); - - metrics.cbSize = sizeof(metrics); - SystemParametersInfoW( SPI_GETMINIMIZEDMETRICS, sizeof(metrics), &metrics, 0 ); - - /* Check if another icon already occupies this spot */ - /* FIXME: this is completely inefficient */ - - hrgn = CreateRectRgn( 0, 0, 0, 0 ); - tmp = CreateRectRgn( 0, 0, 0, 0 ); - for (child = GetWindow( parent, GW_CHILD ); child; child = GetWindow( child, GW_HWNDNEXT )) - { - if (child == hwnd) continue; - if ((GetWindowLongW( child, GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != (WS_VISIBLE|WS_MINIMIZE)) - continue; - if (WIN_GetRectangles( child, COORDS_PARENT, &rect, NULL )) - { - SetRectRgn( tmp, rect.left, rect.top, rect.right, rect.bottom ); - CombineRgn( hrgn, hrgn, tmp, RGN_OR ); - } - } - DeleteObject( tmp ); - - pt = get_first_minimized_child_pos( &rectParent, &metrics, width, height ); - for (;;) - { - SetRect( &rect, pt.x, pt.y, pt.x + width, pt.y + height ); - if (!RectInRegion( hrgn, &rect )) - break; - - get_next_minimized_child_pos( &rectParent, &metrics, width, height, &pt ); - } - - DeleteObject( hrgn ); - return pt; -} - - -/*********************************************************************** - * WINPOS_MinMaximize - */ -UINT WINPOS_MinMaximize( HWND hwnd, UINT cmd, LPRECT rect ) -{ - UINT swpFlags = 0; - LONG old_style; - MINMAXINFO minmax; - WINDOWPLACEMENT wpl; - - TRACE("%p %u\n", hwnd, cmd ); - - wpl.length = sizeof(wpl); - GetWindowPlacement( hwnd, &wpl ); - - if (HOOK_CallHooks( WH_CBT, HCBT_MINMAX, (WPARAM)hwnd, cmd, TRUE )) - return SWP_NOSIZE | SWP_NOMOVE; - - if (IsIconic( hwnd )) - { - switch (cmd) - { - case SW_SHOWMINNOACTIVE: - case SW_SHOWMINIMIZED: - case SW_FORCEMINIMIZE: - case SW_MINIMIZE: - wpl.ptMinPosition = get_minimized_pos( hwnd, wpl.ptMinPosition ); - - SetRect( rect, wpl.ptMinPosition.x, wpl.ptMinPosition.y, - wpl.ptMinPosition.x + GetSystemMetrics(SM_CXMINIMIZED), - wpl.ptMinPosition.y + GetSystemMetrics(SM_CYMINIMIZED) ); - return SWP_NOSIZE | SWP_NOMOVE; - } - if (!SendMessageW( hwnd, WM_QUERYOPEN, 0, 0 )) return SWP_NOSIZE | SWP_NOMOVE; - swpFlags |= SWP_NOCOPYBITS; - } - - switch( cmd ) - { - case SW_SHOWMINNOACTIVE: - case SW_SHOWMINIMIZED: - case SW_FORCEMINIMIZE: - case SW_MINIMIZE: - if (IsZoomed( hwnd )) win_set_flags( hwnd, WIN_RESTORE_MAX, 0 ); - else win_set_flags( hwnd, 0, WIN_RESTORE_MAX ); - - if (GetFocus() == hwnd) - { - if (GetWindowLongW(hwnd, GWL_STYLE) & WS_CHILD) - NtUserSetFocus( NtUserGetAncestor( hwnd, GA_PARENT )); - else - NtUserSetFocus( 0 ); - } - - old_style = WIN_SetStyle( hwnd, WS_MINIMIZE, WS_MAXIMIZE ); - - wpl.ptMinPosition = get_minimized_pos( hwnd, wpl.ptMinPosition ); - - if (!(old_style & WS_MINIMIZE)) swpFlags |= SWP_STATECHANGED; - SetRect( rect, wpl.ptMinPosition.x, wpl.ptMinPosition.y, - wpl.ptMinPosition.x + GetSystemMetrics(SM_CXMINIMIZED), - wpl.ptMinPosition.y + GetSystemMetrics(SM_CYMINIMIZED) ); - swpFlags |= SWP_NOCOPYBITS; - break; - - case SW_MAXIMIZE: - old_style = GetWindowLongW( hwnd, GWL_STYLE ); - if ((old_style & WS_MAXIMIZE) && (old_style & WS_VISIBLE)) return SWP_NOSIZE | SWP_NOMOVE; - - minmax = WINPOS_GetMinMaxInfo( hwnd ); - - old_style = WIN_SetStyle( hwnd, WS_MAXIMIZE, WS_MINIMIZE ); - if (old_style & WS_MINIMIZE) - win_set_flags( hwnd, WIN_RESTORE_MAX, 0 ); - - if (!(old_style & WS_MAXIMIZE)) swpFlags |= SWP_STATECHANGED; - SetRect( rect, minmax.ptMaxPosition.x, minmax.ptMaxPosition.y, - minmax.ptMaxPosition.x + minmax.ptMaxSize.x, minmax.ptMaxPosition.y + minmax.ptMaxSize.y ); - break; - - case SW_SHOWNOACTIVATE: - win_set_flags( hwnd, 0, WIN_RESTORE_MAX ); - /* fall through */ - case SW_SHOWNORMAL: - case SW_RESTORE: - case SW_SHOWDEFAULT: /* FIXME: should have its own handler */ - old_style = WIN_SetStyle( hwnd, 0, WS_MINIMIZE | WS_MAXIMIZE ); - if (old_style & WS_MINIMIZE) - { - if (win_get_flags( hwnd ) & WIN_RESTORE_MAX) - { - /* Restore to maximized position */ - minmax = WINPOS_GetMinMaxInfo( hwnd ); - WIN_SetStyle( hwnd, WS_MAXIMIZE, 0 ); - swpFlags |= SWP_STATECHANGED; - SetRect( rect, minmax.ptMaxPosition.x, minmax.ptMaxPosition.y, - minmax.ptMaxPosition.x + minmax.ptMaxSize.x, minmax.ptMaxPosition.y + minmax.ptMaxSize.y ); - break; - } - } - else if (!(old_style & WS_MAXIMIZE)) break; - - swpFlags |= SWP_STATECHANGED; - - /* Restore to normal position */ - - *rect = wpl.rcNormalPosition; - break; - } - - return swpFlags; -} - /*********************************************************************** * GetInternalWindowPos (USER32.@) diff --git a/dlls/user32/winproc.c b/dlls/user32/winproc.c index b489dadcda6..1e12efe890b 100644 --- a/dlls/user32/winproc.c +++ b/dlls/user32/winproc.c @@ -161,29 +161,6 @@ static LRESULT call_dialog_proc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp, LRES } -/********************************************************************** - * WINPROC_GetProc - * - * Get a window procedure pointer that can be passed to the Windows program. - */ -WNDPROC WINPROC_GetProc( WNDPROC proc, BOOL unicode ) -{ - WINDOWPROC *ptr = handle_to_proc( proc ); - - if (!ptr || ptr == WINPROC_PROC16) return proc; - if (unicode) - { - if (ptr->procW) return ptr->procW; - return proc; - } - else - { - if (ptr->procA) return ptr->procA; - return proc; - } -} - - /********************************************************************** * WINPROC_AllocProc * @@ -199,22 +176,6 @@ static WNDPROC WINPROC_AllocProc( WNDPROC func, BOOL unicode ) } -/********************************************************************** - * WINPROC_IsUnicode - * - * Return the window procedure type, or the default value if not a winproc handle. - */ -BOOL WINPROC_IsUnicode( WNDPROC proc, BOOL def_val ) -{ - WINDOWPROC *ptr = handle_to_proc( proc ); - - if (!ptr) return def_val; - if (ptr == WINPROC_PROC16) return FALSE; /* 16-bit is always A */ - if (ptr->procA && ptr->procW) return def_val; /* can be both */ - return (ptr->procW != NULL); -} - - /********************************************************************** * WINPROC_TestLBForStr * diff --git a/dlls/win32u/class.c b/dlls/win32u/class.c index 3a4a00de29b..9ac402025b0 100644 --- a/dlls/win32u/class.c +++ b/dlls/win32u/class.c @@ -39,6 +39,27 @@ WINE_DECLARE_DEBUG_CHANNEL(win); #define MAX_WINPROCS 4096 #define WINPROC_PROC16 ((WINDOWPROC *)1) /* placeholder for 16-bit window procs */ +typedef struct tagCLASS +{ + struct list entry; /* Entry in class list */ + UINT style; /* Class style */ + BOOL local; /* Local class? */ + WNDPROC winproc; /* Window procedure */ + INT cbClsExtra; /* Class extra bytes */ + INT cbWndExtra; /* Window extra bytes */ + struct dce *dce; /* Opaque pointer to class DCE */ + UINT_PTR instance; /* Module that created the task */ + HICON hIcon; /* Default icon */ + HICON hIconSm; /* Default small icon */ + HICON hIconSmIntern; /* Internal small icon, derived from hIcon */ + HCURSOR hCursor; /* Default cursor */ + HBRUSH hbrBackground; /* Default background */ + ATOM atomName; /* Name of the class */ + WCHAR name[MAX_ATOM_LEN + 1]; + WCHAR *basename; /* Base name for redirected classes, pointer within 'name'. */ + struct client_menu_name menu_name; /* Default menu name */ +} CLASS; + static WINDOWPROC winproc_array[MAX_WINPROCS]; static UINT winproc_used = NB_BUILTIN_WINPROCS; static pthread_mutex_t winproc_lock = PTHREAD_MUTEX_INITIALIZER; @@ -283,6 +304,14 @@ static CLASS *find_class( HINSTANCE module, UNICODE_STRING *name ) return NULL; } +/*********************************************************************** + * get_class_winproc + */ +WNDPROC get_class_winproc( CLASS *class ) +{ + return class->winproc; +} + /*********************************************************************** * get_class_dce */ diff --git a/dlls/win32u/dce.c b/dlls/win32u/dce.c index 3aea65a9b66..b7075c397fb 100644 --- a/dlls/win32u/dce.c +++ b/dlls/win32u/dce.c @@ -34,6 +34,17 @@ WINE_DEFAULT_DEBUG_CHANNEL(win); +struct dce +{ + struct list entry; /* entry in global DCE list */ + HDC hdc; + HWND hwnd; + HRGN clip_rgn; + DWORD flags; + LONG count; /* usage count; 0 or 1 for cache DCEs, always 1 for window DCEs, + always >= 1 for class DCEs */ +}; + static struct list dce_list = LIST_INIT(dce_list); #define DCE_CACHE_SIZE 64 diff --git a/dlls/win32u/driver.c b/dlls/win32u/driver.c index ec8162b0284..52fd1fdcfa9 100644 --- a/dlls/win32u/driver.c +++ b/dlls/win32u/driver.c @@ -1132,6 +1132,11 @@ static BOOL CDECL loaderdrv_CreateDesktopWindow( HWND hwnd ) return load_driver()->pCreateDesktopWindow( hwnd ); } +static BOOL CDECL loaderdrv_CreateWindow( HWND hwnd ) +{ + return load_driver()->pCreateWindow( hwnd ); +} + static void CDECL loaderdrv_GetDC( HDC hdc, HWND hwnd, HWND top_win, const RECT *win_rect, const RECT *top_rect, DWORD flags ) { @@ -1190,6 +1195,7 @@ static const struct user_driver_funcs lazy_load_driver = .pUpdateDisplayDevices = loaderdrv_UpdateDisplayDevices, /* windowing functions */ .pCreateDesktopWindow = loaderdrv_CreateDesktopWindow, + .pCreateWindow = loaderdrv_CreateWindow, .pDestroyWindow = nulldrv_DestroyWindow, .pFlashWindowEx = loaderdrv_FlashWindowEx, .pGetDC = loaderdrv_GetDC, diff --git a/dlls/win32u/gdiobj.c b/dlls/win32u/gdiobj.c index e47271e6108..09262845866 100644 --- a/dlls/win32u/gdiobj.c +++ b/dlls/win32u/gdiobj.c @@ -1160,6 +1160,7 @@ static struct unix_funcs unix_funcs = NtUserChangeDisplaySettings, NtUserClipCursor, NtUserCountClipboardFormats, + NtUserCreateWindowEx, NtUserDeferWindowPosAndBand, NtUserDestroyCursor, NtUserDestroyWindow, diff --git a/dlls/win32u/menu.c b/dlls/win32u/menu.c index 921c5752536..1889a75b966 100644 --- a/dlls/win32u/menu.c +++ b/dlls/win32u/menu.c @@ -119,3 +119,11 @@ BOOL WINAPI NtUserDestroyMenu( HMENU menu ) { return user_callbacks && user_callbacks->pDestroyMenu( menu ); } + +/******************************************************************* + * NtUserSetSystemMenu (win32u.@) + */ +BOOL WINAPI NtUserSetSystemMenu( HWND hwnd, HMENU menu ) +{ + return user_callbacks && user_callbacks->pSetSystemMenu( hwnd, menu ); +} diff --git a/dlls/win32u/message.c b/dlls/win32u/message.c index 853182b6e94..692e5117b21 100644 --- a/dlls/win32u/message.c +++ b/dlls/win32u/message.c @@ -231,12 +231,23 @@ BOOL kill_system_timer( HWND hwnd, UINT_PTR id ) return ret; } +static BOOL send_window_message( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, + LRESULT *result, BOOL ansi ) +{ + /* FIXME: move implementation from user32 */ + if (!user_callbacks) return FALSE; + *result = ansi + ? user_callbacks->pSendMessageA( hwnd, msg, wparam, lparam ) + : user_callbacks->pSendMessageW( hwnd, msg, wparam, lparam ); + return TRUE; +} + /* see SendMessageW */ LRESULT send_message( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) { - /* FIXME: move implementation from user32 */ - if (!user_callbacks) return 0; - return user_callbacks->pSendMessageW( hwnd, msg, wparam, lparam ); + LRESULT result = 0; + send_window_message( hwnd, msg, wparam, lparam, &result, FALSE ); + return result; } /* see SendNotifyMessageW */ @@ -258,6 +269,8 @@ BOOL WINAPI NtUserMessageCall( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam { switch (type) { + case FNID_SENDMESSAGE: + return send_window_message( hwnd, msg, wparam, lparam, (LRESULT *)result_info, ansi ); case FNID_SENDNOTIFYMESSAGE: return send_notify_message( hwnd, msg, wparam, lparam, ansi ); default: diff --git a/dlls/win32u/ntuser_private.h b/dlls/win32u/ntuser_private.h index 49fd22ca140..7327522eb01 100644 --- a/dlls/win32u/ntuser_private.h +++ b/dlls/win32u/ntuser_private.h @@ -39,8 +39,10 @@ struct user_callbacks BOOL (WINAPI *pPostMessageW)( HWND, UINT, WPARAM, LPARAM ); UINT (WINAPI *pSendInput)( UINT count, INPUT *inputs, int size ); LRESULT (WINAPI *pSendMessageTimeoutW)( HWND, UINT, WPARAM, LPARAM, UINT, UINT, PDWORD_PTR ); + LRESULT (WINAPI *pSendMessageA)( HWND, UINT, WPARAM, LPARAM ); LRESULT (WINAPI *pSendMessageW)( HWND, UINT, WPARAM, LPARAM ); BOOL (WINAPI *pSendNotifyMessageW)( HWND, UINT, WPARAM, LPARAM ); + BOOL (WINAPI *pSetSystemMenu)( HWND hwnd, HMENU menu ); BOOL (WINAPI *pShowCaret)( HWND hwnd ); DWORD (WINAPI *pWaitForInputIdle)( HANDLE, DWORD ); void (CDECL *free_win_ptr)( struct tagWND *win ); @@ -48,11 +50,13 @@ struct user_callbacks void (CDECL *notify_ime)( HWND hwnd, UINT param ); void (CDECL *register_builtin_classes)(void); LRESULT (WINAPI *send_ll_message)( DWORD, DWORD, UINT, WPARAM, LPARAM, UINT, UINT, PDWORD_PTR ); + BOOL (CDECL *set_menu)( HWND hwnd, HMENU menu ); void (WINAPI *set_standard_scroll_painted)( HWND hwnd, INT bar, BOOL visible ); void (CDECL *set_user_driver)( void *, UINT ); BOOL (CDECL *set_window_pos)( HWND hwnd, HWND insert_after, UINT swp_flags, const RECT *window_rect, const RECT *client_rect, const RECT *valid_rects ); + BOOL (WINAPI *register_imm)( HWND hwnd ); void (WINAPI *unregister_imm)( HWND hwnd ); }; @@ -69,7 +73,6 @@ struct user_object HANDLE alloc_user_handle( struct user_object *ptr, unsigned int type ) DECLSPEC_HIDDEN; void *get_user_handle_ptr( HANDLE handle, unsigned int type ) DECLSPEC_HIDDEN; -void set_user_handle_ptr( HANDLE handle, struct user_object *ptr ) DECLSPEC_HIDDEN; void release_user_handle_ptr( void *ptr ) DECLSPEC_HIDDEN; void *free_user_handle( HANDLE handle, unsigned int type ) DECLSPEC_HIDDEN; @@ -210,18 +213,6 @@ typedef struct tagWINDOWPROC #define MAX_ATOM_LEN 255 -/* FIXME: make it private to dce.c */ -struct dce -{ - struct list entry; /* entry in global DCE list */ - HDC hdc; - HWND hwnd; - HRGN clip_rgn; - DWORD flags; - LONG count; /* usage count; 0 or 1 for cache DCEs, always 1 for window DCEs, - always >= 1 for class DCEs */ -}; - /* Built-in class names (see _Undocumented_Windows_ p.418) */ #define POPUPMENU_CLASS_ATOM MAKEINTATOM(32768) /* PopupMenu */ #define DESKTOP_CLASS_ATOM MAKEINTATOM(32769) /* Desktop */ @@ -229,32 +220,12 @@ struct dce #define WINSWITCH_CLASS_ATOM MAKEINTATOM(32771) /* WinSwitch */ #define ICONTITLE_CLASS_ATOM MAKEINTATOM(32772) /* IconTitle */ -typedef struct tagCLASS -{ - struct list entry; /* Entry in class list */ - UINT style; /* Class style */ - BOOL local; /* Local class? */ - WNDPROC winproc; /* Window procedure */ - INT cbClsExtra; /* Class extra bytes */ - INT cbWndExtra; /* Window extra bytes */ - struct client_menu_name menu_name; /* Default menu name */ - struct dce *dce; /* Opaque pointer to class DCE */ - UINT_PTR instance; /* Module that created the task */ - HICON hIcon; /* Default icon */ - HICON hIconSm; /* Default small icon */ - HICON hIconSmIntern; /* Internal small icon, derived from hIcon */ - HCURSOR hCursor; /* Default cursor */ - HBRUSH hbrBackground; /* Default background */ - ATOM atomName; /* Name of the class */ - WCHAR name[MAX_ATOM_LEN + 1]; - WCHAR *basename; /* Base name for redirected classes, pointer within 'name'. */ -} CLASS; - /* class.c */ WNDPROC alloc_winproc( WNDPROC func, BOOL ansi ) DECLSPEC_HIDDEN; WINDOWPROC *get_winproc_ptr( WNDPROC handle ) DECLSPEC_HIDDEN; BOOL is_winproc_unicode( WNDPROC proc, BOOL def_val ) DECLSPEC_HIDDEN; DWORD get_class_long( HWND hwnd, INT offset, BOOL ansi ) DECLSPEC_HIDDEN; +WNDPROC get_class_winproc( struct tagCLASS *class ) DECLSPEC_HIDDEN; ULONG_PTR get_class_long_ptr( HWND hwnd, INT offset, BOOL ansi ) DECLSPEC_HIDDEN; WORD get_class_word( HWND hwnd, INT offset ) DECLSPEC_HIDDEN; ATOM get_int_atom_value( UNICODE_STRING *name ) DECLSPEC_HIDDEN; diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index 0166b64c76a..a3e645519e4 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -1391,7 +1391,7 @@ UINT get_win_monitor_dpi( HWND hwnd ) /********************************************************************** * get_thread_dpi_awareness */ -static DPI_AWARENESS get_thread_dpi_awareness(void) +DPI_AWARENESS get_thread_dpi_awareness(void) { struct user_thread_info *info = get_user_thread_info(); ULONG_PTR context = info->dpi_awareness; @@ -4749,9 +4749,6 @@ ULONG_PTR WINAPI NtUserCallTwoParam( ULONG_PTR arg1, ULONG_PTR arg2, ULONG code case NtUserRegisterWindowSurface: register_window_surface( (struct window_surface *)arg1, (struct window_surface *)arg2 ); return 0; - case NtUserSetHandlePtr: - set_user_handle_ptr( UlongToHandle(arg1), (struct user_object *)arg2 ); - return 0; default: FIXME( "invalid code %u\n", code ); return 0; diff --git a/dlls/win32u/win32u.spec b/dlls/win32u/win32u.spec index 68348db4033..1e1060b4c36 100644 --- a/dlls/win32u/win32u.spec +++ b/dlls/win32u/win32u.spec @@ -814,7 +814,7 @@ @ stub NtUserCreateInputContext @ stub NtUserCreateLocalMemHandle @ stub NtUserCreatePalmRejectionDelayZone -@ stub NtUserCreateWindowEx +@ stdcall NtUserCreateWindowEx(long ptr ptr ptr long long long long long long long long ptr long long long long) @ stub NtUserCreateWindowGroup @ stdcall -syscall NtUserCreateWindowStation(ptr long long long long long long) @ stub NtUserCtxDisplayIOCtl diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h index 361bec31ec8..17933daecd8 100644 --- a/dlls/win32u/win32u_private.h +++ b/dlls/win32u/win32u_private.h @@ -195,6 +195,11 @@ struct unix_funcs DWORD flags, void *lparam ); BOOL (WINAPI *pNtUserClipCursor)( const RECT *rect ); INT (WINAPI *pNtUserCountClipboardFormats)(void); + HWND (WINAPI *pNtUserCreateWindowEx)( DWORD ex_style, UNICODE_STRING *class_name, + UNICODE_STRING *version, UNICODE_STRING *window_name, + DWORD style, INT x, INT y, INT width, INT height, + HWND parent, HMENU menu, HINSTANCE instance, void *params, + DWORD flags, CBT_CREATEWNDW *cbtc, DWORD unk, BOOL ansi ); HDWP (WINAPI *pNtUserDeferWindowPosAndBand)( HDWP hdwp, HWND hwnd, HWND after, INT x, INT y, INT cx, INT cy, UINT flags, UINT unk1, UINT unk2 ); @@ -300,6 +305,7 @@ extern ULONG_PTR set_icon_param( HICON handle, ULONG_PTR param ) DECLSPEC_HIDDEN /* dce.c */ extern struct window_surface dummy_surface DECLSPEC_HIDDEN; +extern void erase_now( HWND hwnd, UINT rdw_flags ) DECLSPEC_HIDDEN; extern void flush_window_surfaces( BOOL idle ) DECLSPEC_HIDDEN; extern void register_window_surface( struct window_surface *old, struct window_surface *new ) DECLSPEC_HIDDEN; @@ -336,6 +342,7 @@ extern RECT get_primary_monitor_rect( UINT dpi ) DECLSPEC_HIDDEN; extern UINT get_system_dpi(void) DECLSPEC_HIDDEN; extern int get_system_metrics( int index ) DECLSPEC_HIDDEN; extern UINT get_thread_dpi(void) DECLSPEC_HIDDEN; +extern DPI_AWARENESS get_thread_dpi_awareness(void) DECLSPEC_HIDDEN; extern RECT get_virtual_screen_rect( UINT dpi ) DECLSPEC_HIDDEN; extern BOOL is_exiting_thread( DWORD tid ) DECLSPEC_HIDDEN; extern POINT map_dpi_point( POINT pt, UINT dpi_from, UINT dpi_to ) DECLSPEC_HIDDEN; @@ -348,9 +355,6 @@ extern void user_lock(void) DECLSPEC_HIDDEN; extern void user_unlock(void) DECLSPEC_HIDDEN; extern void user_check_not_lock(void) DECLSPEC_HIDDEN; -/* windc.c */ -extern void erase_now( HWND hwnd, UINT rdw_flags ) DECLSPEC_HIDDEN; - /* window.c */ struct tagWND; extern HDWP begin_defer_window_pos( INT count ) DECLSPEC_HIDDEN; diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index e513a13b152..b43f8d1d4c3 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -100,7 +100,7 @@ void *get_user_handle_ptr( HANDLE handle, unsigned int type ) /*********************************************************************** * set_user_handle_ptr */ -void set_user_handle_ptr( HANDLE handle, struct user_object *ptr ) +static void set_user_handle_ptr( HANDLE handle, struct user_object *ptr ) { WORD index = USER_HANDLE_TO_INDEX(handle); assert( index < NB_USER_HANDLES ); @@ -3990,6 +3990,7 @@ static void free_window_handle( HWND hwnd ) SERVER_END_REQ; user_unlock(); if (user_callbacks) user_callbacks->free_win_ptr( win ); + free( win ); } } @@ -4192,9 +4193,490 @@ void destroy_thread_windows(void) window_surface_release( win->surface ); } if (user_callbacks) user_callbacks->free_win_ptr( win ); + free( win ); } } +/*********************************************************************** + * create_window_handle + * + * Create a window handle with the server. + */ +static WND *create_window_handle( HWND parent, HWND owner, UNICODE_STRING *name, + HINSTANCE instance, BOOL ansi, + DWORD style, DWORD ex_style ) +{ + DPI_AWARENESS awareness = get_thread_dpi_awareness(); + HWND handle = 0, full_parent = 0, full_owner = 0; + struct tagCLASS *class = NULL; + int extra_bytes = 0; + UINT dpi = 0; + WND *win; + + SERVER_START_REQ( create_window ) + { + req->parent = wine_server_user_handle( parent ); + req->owner = wine_server_user_handle( owner ); + req->instance = wine_server_client_ptr( instance ); + req->dpi = get_system_dpi(); + req->awareness = awareness; + req->style = style; + req->ex_style = ex_style; + if (!(req->atom = get_int_atom_value( name )) && name->Length) + wine_server_add_data( req, name->Buffer, name->Length ); + if (!wine_server_call_err( req )) + { + handle = wine_server_ptr_handle( reply->handle ); + full_parent = wine_server_ptr_handle( reply->parent ); + full_owner = wine_server_ptr_handle( reply->owner ); + extra_bytes = reply->extra; + dpi = reply->dpi; + awareness = reply->awareness; + class = wine_server_get_ptr( reply->class_ptr ); + } + } + SERVER_END_REQ; + + if (!handle) + { + WARN( "error %d creating window\n", GetLastError() ); + return NULL; + } + + if (!(win = calloc( 1, FIELD_OFFSET(WND, wExtra) + extra_bytes ))) + { + SERVER_START_REQ( destroy_window ) + { + req->handle = wine_server_user_handle( handle ); + wine_server_call( req ); + } + SERVER_END_REQ; + SetLastError( ERROR_NOT_ENOUGH_MEMORY ); + return NULL; + } + + if (!parent) /* if parent is 0 we don't have a desktop window yet */ + { + struct user_thread_info *thread_info = get_user_thread_info(); + + if (name->Buffer == (const WCHAR *)DESKTOP_CLASS_ATOM) + { + if (!thread_info->top_window) thread_info->top_window = full_parent ? full_parent : handle; + else assert( full_parent == thread_info->top_window ); + if (full_parent && !user_driver->pCreateDesktopWindow( thread_info->top_window )) + ERR( "failed to create desktop window\n" ); + if (user_callbacks) user_callbacks->register_builtin_classes(); + } + else /* HWND_MESSAGE parent */ + { + if (!thread_info->msg_window && !full_parent) thread_info->msg_window = handle; + } + } + + user_lock(); + + win->obj.handle = handle; + win->obj.type = NTUSER_OBJ_WINDOW; + win->parent = full_parent; + win->owner = full_owner; + win->class = class; + win->winproc = get_class_winproc( class ); + win->cbWndExtra = extra_bytes; + win->dpi = dpi; + win->dpi_awareness = awareness; + set_user_handle_ptr( handle, &win->obj ); + if (is_winproc_unicode( win->winproc, !ansi )) win->flags |= WIN_ISUNICODE; + return win; +} + +static BOOL is_default_coord( int x ) +{ + return x == CW_USEDEFAULT || x == 0x8000; +} + +/*********************************************************************** + * fix_cs_coordinates + * + * Fix the coordinates and return default show mode in sw. + */ +static void fix_cs_coordinates( CREATESTRUCTW *cs, INT *sw ) +{ + if (cs->style & (WS_CHILD | WS_POPUP)) + { + if (is_default_coord(cs->x)) cs->x = cs->y = 0; + if (is_default_coord(cs->cx)) cs->cx = cs->cy = 0; + } + else /* overlapped window */ + { + RTL_USER_PROCESS_PARAMETERS *params = NtCurrentTeb()->Peb->ProcessParameters; + HMONITOR monitor; + MONITORINFO mon_info; + + if (!is_default_coord( cs->x ) && !is_default_coord( cs->cx ) && !is_default_coord( cs->cy )) + return; + + monitor = monitor_from_window( cs->hwndParent, MONITOR_DEFAULTTOPRIMARY, get_thread_dpi() ); + mon_info.cbSize = sizeof(mon_info); + get_monitor_info( monitor, &mon_info ); + + if (is_default_coord( cs->x )) + { + if (!is_default_coord( cs->y )) *sw = cs->y; + cs->x = (params->dwFlags & STARTF_USEPOSITION) ? params->dwX : mon_info.rcWork.left; + cs->y = (params->dwFlags & STARTF_USEPOSITION) ? params->dwY : mon_info.rcWork.top; + } + + if (is_default_coord( cs->cx )) + { + if (params->dwFlags & STARTF_USESIZE) + { + cs->cx = params->dwXSize; + cs->cy = params->dwYSize; + } + else + { + cs->cx = (mon_info.rcWork.right - mon_info.rcWork.left) * 3 / 4 - cs->x; + cs->cy = (mon_info.rcWork.bottom - mon_info.rcWork.top) * 3 / 4 - cs->y; + } + } + /* neither x nor cx are default. Check the y values. + * In the trace we see Outlook and Outlook Express using + * cy set to CW_USEDEFAULT when opening the address book. + */ + else if (is_default_coord( cs->cy )) + { + FIXME( "Strange use of CW_USEDEFAULT in cy\n" ); + cs->cy = (mon_info.rcWork.bottom - mon_info.rcWork.top) * 3 / 4 - cs->y; + } + } +} + +/*********************************************************************** + * map_dpi_create_struct + */ +static void map_dpi_create_struct( CREATESTRUCTW *cs, UINT dpi_from, UINT dpi_to ) +{ + if (!dpi_from && !dpi_to) return; + if (!dpi_from || !dpi_to) + { + POINT pt = { cs->x, cs->y }; + UINT mon_dpi = get_monitor_dpi( monitor_from_point( pt, MONITOR_DEFAULTTONEAREST, dpi_from )); + if (!dpi_from) dpi_from = mon_dpi; + else dpi_to = mon_dpi; + } + if (dpi_from == dpi_to) return; + cs->x = muldiv( cs->x, dpi_to, dpi_from ); + cs->y = muldiv( cs->y, dpi_to, dpi_from ); + cs->cx = muldiv( cs->cx, dpi_to, dpi_from ); + cs->cy = muldiv( cs->cy, dpi_to, dpi_from ); +} + +/*********************************************************************** + * NtUserCreateWindowEx (win32u.@) + */ +HWND WINAPI NtUserCreateWindowEx( DWORD ex_style, UNICODE_STRING *class_name, + UNICODE_STRING *version, UNICODE_STRING *window_name, + DWORD style, INT x, INT y, INT cx, INT cy, + HWND parent, HMENU menu, HINSTANCE instance, void *params, + DWORD flags, CBT_CREATEWNDW *cbtc, DWORD unk, BOOL ansi ) +{ + CREATESTRUCTW cs, *client_cs = cbtc->lpcs; + UINT win_dpi, thread_dpi = get_thread_dpi(); + DPI_AWARENESS_CONTEXT context; + HWND hwnd, owner = 0; + INT sw = SW_SHOW; + LRESULT result; + RECT rect; + WND *win; + + static const WCHAR messageW[] = {'M','e','s','s','a','g','e'}; + + cs.lpCreateParams = params; + cs.hInstance = client_cs->hInstance; /* may be different than instance for win16 */ + cs.hMenu = menu; + cs.hwndParent = parent; + cs.style = style; + cs.dwExStyle = ex_style; + cs.x = x; + cs.y = y; + cs.cx = cx; + cs.cy = cy; + /* We use client_cs to pass original class and name pointers, + * that's probably not how native handles it. */ + cs.lpszName = client_cs->lpszName; + cs.lpszClass = client_cs->lpszClass; + + /* Find the parent window */ + if (parent == HWND_MESSAGE) + { + cs.hwndParent = parent = get_hwnd_message_parent(); + } + else if (parent) + { + if ((cs.style & (WS_CHILD|WS_POPUP)) != WS_CHILD) + { + owner = parent; + parent = get_desktop_window(); + } + else + { + DWORD parent_style = get_window_long( parent, GWL_EXSTYLE ); + if ((parent_style & WS_EX_LAYOUTRTL) && !(parent_style & WS_EX_NOINHERITLAYOUT)) + cs.dwExStyle |= WS_EX_LAYOUTRTL; + } + } + else + { + if ((cs.style & (WS_CHILD|WS_POPUP)) == WS_CHILD) + { + WARN( "No parent for child window\n" ); + SetLastError( ERROR_TLW_WITH_WSCHILD ); + return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */ + } + + /* are we creating the desktop or HWND_MESSAGE parent itself? */ + if (class_name->Buffer != (LPCWSTR)DESKTOP_CLASS_ATOM && + (class_name->Length != sizeof(messageW) || + wcsnicmp( class_name->Buffer, messageW, ARRAYSIZE(messageW) ))) + { + parent = get_desktop_window(); + } + } + + fix_cs_coordinates( &cs, &sw ); + cs.dwExStyle = fix_exstyle( cs.style, cs.dwExStyle ); + + /* Create the window structure */ + + style = cs.style & ~WS_VISIBLE; + ex_style = cs.dwExStyle & ~WS_EX_LAYERED; + if (!(win = create_window_handle( parent, owner, class_name, instance, ansi, style, ex_style ))) + return 0; + hwnd = win->obj.handle; + + /* Fill the window structure */ + + win->tid = GetCurrentThreadId(); + win->hInstance = cs.hInstance; + win->text = NULL; + win->dwStyle = style; + win->dwExStyle = ex_style; + win->wIDmenu = 0; + win->helpContext = 0; + win->pScroll = NULL; + win->userdata = 0; + win->hIcon = 0; + win->hIconSmall = 0; + win->hIconSmall2 = 0; + win->hSysMenu = 0; + + win->min_pos.x = win->min_pos.y = -1; + win->max_pos.x = win->max_pos.y = -1; + SetRect( &win->normal_rect, cs.x, cs.y, cs.x + cs.cx, cs.y + cs.cy ); + + if (win->dwStyle & WS_SYSMENU) NtUserSetSystemMenu( hwnd, 0 ); + + /* call the WH_CBT hook */ + + release_win_ptr( win ); + *client_cs = cs; + cbtc->hwndInsertAfter = HWND_TOP; + if (call_hooks( WH_CBT, HCBT_CREATEWND, (WPARAM)hwnd, (LPARAM)cbtc, !ansi )) + { + free_window_handle( hwnd ); + return 0; + } + if (!(win = get_win_ptr( hwnd ))) return 0; + + /* + * Correct the window styles. + * + * It affects only the style loaded into the WND structure. + */ + + if ((win->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD) + { + win->dwStyle |= WS_CLIPSIBLINGS; + if (!(win->dwStyle & WS_POPUP)) win->dwStyle |= WS_CAPTION; + } + + win->dwExStyle = cs.dwExStyle; + /* WS_EX_WINDOWEDGE depends on some other styles */ + if ((win->dwStyle & (WS_DLGFRAME | WS_THICKFRAME)) && + !(win->dwStyle & (WS_CHILD | WS_POPUP))) + win->dwExStyle |= WS_EX_WINDOWEDGE; + + if (!(win->dwStyle & (WS_CHILD | WS_POPUP))) win->flags |= WIN_NEED_SIZE; + + SERVER_START_REQ( set_window_info ) + { + req->handle = wine_server_user_handle( hwnd ); + req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE | SET_WIN_UNICODE; + req->style = win->dwStyle; + req->ex_style = win->dwExStyle; + req->instance = wine_server_client_ptr( win->hInstance ); + req->is_unicode = (win->flags & WIN_ISUNICODE) != 0; + req->extra_offset = -1; + wine_server_call( req ); + } + SERVER_END_REQ; + + /* Set the window menu */ + + if ((win->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD) + { + if (cs.hMenu && user_callbacks && !user_callbacks->set_menu( hwnd, cs.hMenu )) + { + release_win_ptr( win ); + free_window_handle( hwnd ); + return 0; + } + } + else NtUserSetWindowLongPtr( hwnd, GWLP_ID, (ULONG_PTR)cs.hMenu, FALSE ); + + win_dpi = win->dpi; + release_win_ptr( win ); + + if (parent) map_dpi_create_struct( &cs, thread_dpi, win_dpi ); + + context = set_thread_dpi_awareness_context( get_window_dpi_awareness_context( hwnd )); + + /* send the WM_GETMINMAXINFO message and fix the size if needed */ + + cx = cs.cx; + cy = cs.cy; + if ((cs.style & WS_THICKFRAME) || !(cs.style & (WS_POPUP | WS_CHILD))) + { + MINMAXINFO info = get_min_max_info( hwnd ); + cx = max( min( cx, info.ptMaxTrackSize.x ), info.ptMinTrackSize.x ); + cy = max( min( cy, info.ptMaxTrackSize.y ), info.ptMinTrackSize.y ); + } + + if (cx < 0) cx = 0; + if (cy < 0) cy = 0; + set_rect( &rect, cs.x, cs.y, cs.x + cx, cs.y + cy ); + /* check for wraparound */ + if (cs.x > 0x7fffffff - cx) rect.right = 0x7fffffff; + if (cs.y > 0x7fffffff - cy) rect.bottom = 0x7fffffff; + if (user_callbacks && !user_callbacks->set_window_pos( hwnd, 0, SWP_NOZORDER | SWP_NOACTIVATE, + &rect, &rect, NULL )) goto failed; + + /* send WM_NCCREATE */ + + TRACE( "hwnd %p cs %d,%d %dx%d %s\n", hwnd, cs.x, cs.y, cs.cx, cs.cy, wine_dbgstr_rect(&rect) ); + *client_cs = cs; + if (!NtUserMessageCall( hwnd, WM_NCCREATE, 0, (LPARAM)client_cs, (ULONG_PTR)&result, + FNID_SENDMESSAGE, ansi ) || !result) + { + WARN( "%p: aborted by WM_NCCREATE\n", hwnd ); + goto failed; + } + + /* create default IME window */ + + if (!is_desktop_window( hwnd ) && parent != get_hwnd_message_parent() && + user_callbacks && user_callbacks->register_imm( hwnd )) + { + TRACE( "register IME window for %p\n", hwnd ); + win_set_flags( hwnd, WIN_HAS_IME_WIN, 0 ); + } + + /* send WM_NCCALCSIZE */ + + if (get_window_rects( hwnd, COORDS_PARENT, &rect, NULL, win_dpi )) + { + /* yes, even if the CBT hook was called with HWND_TOP */ + HWND insert_after = (get_window_long( hwnd, GWL_STYLE ) & WS_CHILD) ? HWND_BOTTOM : HWND_TOP; + RECT client_rect = rect; + + /* the rectangle is in screen coords for WM_NCCALCSIZE when wparam is FALSE */ + map_window_points( parent, 0, (POINT *)&client_rect, 2, win_dpi ); + send_message( hwnd, WM_NCCALCSIZE, FALSE, (LPARAM)&client_rect ); + map_window_points( 0, parent, (POINT *)&client_rect, 2, win_dpi ); + user_callbacks->set_window_pos( hwnd, insert_after, SWP_NOACTIVATE, &rect, &client_rect, NULL ); + } + else goto failed; + + /* send WM_CREATE */ + if (!NtUserMessageCall( hwnd, WM_CREATE, 0, (LPARAM)client_cs, (ULONG_PTR)&result, + FNID_SENDMESSAGE, ansi ) || result == -1) goto failed; + cs = *client_cs; + + /* call the driver */ + + if (!user_driver->pCreateWindow( hwnd )) goto failed; + + NtUserNotifyWinEvent( EVENT_OBJECT_CREATE, hwnd, OBJID_WINDOW, 0 ); + + /* send the size messages */ + + if (!(win_get_flags( hwnd ) & WIN_NEED_SIZE)) + { + get_window_rects( hwnd, COORDS_PARENT, NULL, &rect, win_dpi ); + send_message( hwnd, WM_SIZE, SIZE_RESTORED, + MAKELONG(rect.right-rect.left, rect.bottom-rect.top)); + send_message( hwnd, WM_MOVE, 0, MAKELONG( rect.left, rect.top ) ); + } + + /* Show the window, maximizing or minimizing if needed */ + + style = set_window_style( hwnd, 0, WS_MAXIMIZE | WS_MINIMIZE ); + if (style & (WS_MINIMIZE | WS_MAXIMIZE)) + { + RECT new_pos; + UINT sw_flags = (style & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE; + + sw_flags = window_min_maximize( hwnd, sw_flags, &new_pos ); + sw_flags |= SWP_FRAMECHANGED; /* Frame always gets changed */ + if (!(style & WS_VISIBLE) || (style & WS_CHILD) || get_active_window()) + sw_flags |= SWP_NOACTIVATE; + NtUserSetWindowPos( hwnd, 0, new_pos.left, new_pos.top, new_pos.right - new_pos.left, + new_pos.bottom - new_pos.top, sw_flags ); + } + + /* Notify the parent window only */ + + send_parent_notify( hwnd, WM_CREATE ); + if (!is_window( hwnd )) + { + set_thread_dpi_awareness_context( context ); + return 0; + } + + if (parent == get_desktop_window()) + post_message( parent, WM_PARENTNOTIFY, WM_CREATE, (LPARAM)hwnd ); + + if (cs.style & WS_VISIBLE) + { + if (cs.style & WS_MAXIMIZE) + sw = SW_SHOW; + else if (cs.style & WS_MINIMIZE) + sw = SW_SHOWMINIMIZED; + + NtUserShowWindow( hwnd, sw ); + if (cs.dwExStyle & WS_EX_MDICHILD) + { + send_message( cs.hwndParent, WM_MDIREFRESHMENU, 0, 0 ); + /* ShowWindow won't activate child windows */ + NtUserSetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE ); + } + } + + /* Call WH_SHELL hook */ + + if (!(get_window_long( hwnd, GWL_STYLE ) & WS_CHILD) && !get_window_relative( hwnd, GW_OWNER )) + call_hooks( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0, TRUE ); + + TRACE( "created window %p\n", hwnd ); + set_thread_dpi_awareness_context( context ); + return hwnd; + +failed: + destroy_window( hwnd ); + set_thread_dpi_awareness_context( context ); + return 0; +} + /***************************************************************************** * NtUserCallHwnd (win32u.@) */ @@ -4219,10 +4701,6 @@ ULONG_PTR WINAPI NtUserCallHwnd( HWND hwnd, DWORD code ) case NtUserIsWindowVisible: return is_window_visible( hwnd ); /* temporary exports */ - case NtUserCreateDesktopWindow: - return user_driver->pCreateDesktopWindow( hwnd ); - case NtUserDestroyWindowHandle: - return destroy_window( hwnd ); case NtUserGetDummySurface: return (UINT_PTR)&dummy_surface; default: diff --git a/dlls/win32u/wrappers.c b/dlls/win32u/wrappers.c index 6cb3a6896b5..05e200e7403 100644 --- a/dlls/win32u/wrappers.c +++ b/dlls/win32u/wrappers.c @@ -768,6 +768,18 @@ INT WINAPI NtUserCountClipboardFormats(void) return unix_funcs->pNtUserCountClipboardFormats(); } +HWND WINAPI NtUserCreateWindowEx( DWORD ex_style, UNICODE_STRING *class_name, + UNICODE_STRING *version, UNICODE_STRING *window_name, + DWORD style, INT x, INT y, INT width, INT height, + HWND parent, HMENU menu, HINSTANCE instance, void *params, + DWORD flags, CBT_CREATEWNDW *cbtc, DWORD unk, BOOL ansi ) +{ + if (!unix_funcs) return 0; + return unix_funcs->pNtUserCreateWindowEx( ex_style, class_name, version, window_name, + style, x, y, width, height, parent, menu, + instance, params, flags, cbtc, unk, ansi ); +} + HDWP WINAPI NtUserDeferWindowPosAndBand( HDWP hdwp, HWND hwnd, HWND after, INT x, INT y, INT cx, INT cy, UINT flags, UINT unk1, UINT unk2 ) diff --git a/include/ntuser.h b/include/ntuser.h index 7bcb91fcc25..bc5533fbdcd 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -139,7 +139,6 @@ enum NtUserGetHandlePtr, NtUserInvalidateDCE, NtUserRegisterWindowSurface, - NtUserSetHandlePtr, }; /* NtUserCallHwnd codes, not compatible with Windows */ @@ -154,8 +153,6 @@ enum NtUserIsWindowUnicode, NtUserIsWindowVisible, /* temporary exports */ - NtUserCreateDesktopWindow, - NtUserDestroyWindowHandle, NtUserGetDummySurface, }; @@ -193,6 +190,7 @@ enum /* NtUserMessageCall codes */ enum { + FNID_SENDMESSAGE = 0x02b1, FNID_SENDNOTIFYMESSAGE = 0x02b7, }; @@ -298,6 +296,11 @@ HACCEL WINAPI NtUserCreateAcceleratorTable( ACCEL *table, INT count ); HDESK WINAPI NtUserCreateDesktopEx( OBJECT_ATTRIBUTES *attr, UNICODE_STRING *device, DEVMODEW *devmode, DWORD flags, ACCESS_MASK access, ULONG heap_size ); +HWND WINAPI NtUserCreateWindowEx( DWORD ex_style, UNICODE_STRING *class_name, + UNICODE_STRING *version, UNICODE_STRING *window_name, + DWORD style, INT x, INT y, INT cx, INT cy, + HWND parent, HMENU menu, HINSTANCE instance, void *params, + DWORD flags, CBT_CREATEWNDW *cbtc, DWORD unk, BOOL ansi ); HWINSTA WINAPI NtUserCreateWindowStation( OBJECT_ATTRIBUTES *attr, ACCESS_MASK mask, ULONG arg3, ULONG arg4, ULONG arg5, ULONG arg6, ULONG arg7 ); HDWP WINAPI NtUserDeferWindowPosAndBand( HDWP hdwp, HWND hwnd, HWND after, INT x, INT y, @@ -408,6 +411,7 @@ BOOL WINAPI NtUserSetProcessDpiAwarenessContext( ULONG awareness, ULONG unkno BOOL WINAPI NtUserSetProcessWindowStation( HWINSTA handle ); BOOL WINAPI NtUserSetProp( HWND hwnd, const WCHAR *str, HANDLE handle ); BOOL WINAPI NtUserSetSysColors( INT count, const INT *colors, const COLORREF *values ); +BOOL WINAPI NtUserSetSystemMenu( HWND hwnd, HMENU menu ); UINT_PTR WINAPI NtUserSetSystemTimer( HWND hwnd, UINT_PTR id, UINT timeout, TIMERPROC proc ); BOOL WINAPI NtUserSetThreadDesktop( HDESK handle ); UINT_PTR WINAPI NtUserSetTimer( HWND hwnd, UINT_PTR id, UINT timeout, TIMERPROC proc, ULONG tolerance );