diff --git a/dlls/user32/clipboard.c b/dlls/user32/clipboard.c index 1a69421ea17..b45ddf9c7c0 100644 --- a/dlls/user32/clipboard.c +++ b/dlls/user32/clipboard.c @@ -616,29 +616,6 @@ static HANDLE render_synthesized_format( UINT format, UINT from ) return data; } -/************************************************************************** - * CLIPBOARD_ReleaseOwner - */ -void CLIPBOARD_ReleaseOwner( HWND hwnd ) -{ - HWND viewer = 0, owner = 0; - - SendMessageW( hwnd, WM_RENDERALLFORMATS, 0, 0 ); - - SERVER_START_REQ( release_clipboard ) - { - req->owner = wine_server_user_handle( hwnd ); - if (!wine_server_call( req )) - { - viewer = wine_server_ptr_handle( reply->viewer ); - owner = wine_server_ptr_handle( reply->owner ); - } - } - SERVER_END_REQ; - - if (viewer) SendNotifyMessageW( viewer, WM_DRAWCLIPBOARD, (WPARAM)owner, 0 ); -} - /************************************************************************** * RegisterClipboardFormatW (USER32.@) diff --git a/dlls/user32/combo.c b/dlls/user32/combo.c index 77cb24be064..b375de5080c 100644 --- a/dlls/user32/combo.c +++ b/dlls/user32/combo.c @@ -173,7 +173,7 @@ static LRESULT COMBO_NCDestroy( LPHEADCOMBO lphc ) TRACE("[%p]: freeing storage\n", lphc->self); if( (CB_GETTYPE(lphc) != CBS_SIMPLE) && lphc->hWndLBox ) - DestroyWindow( lphc->hWndLBox ); + NtUserDestroyWindow( lphc->hWndLBox ); SetWindowLongPtrW( lphc->self, 0, 0 ); HeapFree( GetProcessHeap(), 0, lphc ); diff --git a/dlls/user32/dde_misc.c b/dlls/user32/dde_misc.c index 41181d099cc..7bc1656432e 100644 --- a/dlls/user32/dde_misc.c +++ b/dlls/user32/dde_misc.c @@ -1158,7 +1158,7 @@ BOOL WINAPI DdeUninitialize(DWORD idInst) */ WDML_FreeAllHSZ(pInstance); - DestroyWindow(pInstance->hwndEvent); + NtUserDestroyWindow( pInstance->hwndEvent ); /* OK now delete the instance handle itself */ @@ -1711,7 +1711,7 @@ void WDML_RemoveServer(WDML_INSTANCE* pInstance, HSZ hszService, HSZ hszTopic) pPrev->next = pServer->next; } - DestroyWindow(pServer->hwndServer); + NtUserDestroyWindow(pServer->hwndServer); WDML_DecHSZ(pInstance, pServer->hszServiceSpec); WDML_DecHSZ(pInstance, pServer->hszService); @@ -2105,7 +2105,7 @@ void WDML_RemoveConv(WDML_CONV* pRef, WDML_SIDE side) hWnd = (side == WDML_CLIENT_SIDE) ? pRef->hwndClient : pRef->hwndServer; SetWindowLongPtrW(hWnd, GWL_WDML_CONVERSATION, 0); - DestroyWindow((side == WDML_CLIENT_SIDE) ? pRef->hwndClient : pRef->hwndServer); + NtUserDestroyWindow((side == WDML_CLIENT_SIDE) ? pRef->hwndClient : pRef->hwndServer); WDML_DecHSZ(pRef->instance, pRef->hszService); WDML_DecHSZ(pRef->instance, pRef->hszTopic); diff --git a/dlls/user32/dde_server.c b/dlls/user32/dde_server.c index 3867e0f014b..26494b835e5 100644 --- a/dlls/user32/dde_server.c +++ b/dlls/user32/dde_server.c @@ -360,7 +360,7 @@ static WDML_CONV* WDML_CreateServerConv(WDML_INSTANCE* pInstance, HWND hwndClien } else { - DestroyWindow(hwndServerConv); + NtUserDestroyWindow(hwndServerConv); } return pConv; } diff --git a/dlls/user32/defwnd.c b/dlls/user32/defwnd.c index f78236cb194..271644bb953 100644 --- a/dlls/user32/defwnd.c +++ b/dlls/user32/defwnd.c @@ -400,7 +400,7 @@ static LRESULT DEFWND_DefWinProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPa return 0; case WM_CLOSE: - DestroyWindow( hwnd ); + NtUserDestroyWindow( hwnd ); return 0; case WM_MOUSEACTIVATE: diff --git a/dlls/user32/dialog.c b/dlls/user32/dialog.c index e6e5b91587c..f9d388d0104 100644 --- a/dlls/user32/dialog.c +++ b/dlls/user32/dialog.c @@ -707,7 +707,7 @@ static HWND DIALOG_CreateIndirect( HINSTANCE hInst, LPCVOID dlgTemplate, return hwnd; } if (disabled_owner) EnableWindow( disabled_owner, TRUE ); - if( IsWindow(hwnd) ) DestroyWindow( hwnd ); + if (IsWindow(hwnd)) NtUserDestroyWindow( hwnd ); return 0; } @@ -827,7 +827,7 @@ INT DIALOG_DoDialogBox( HWND hwnd, HWND owner ) } } retval = dlgInfo->idResult; - DestroyWindow( hwnd ); + NtUserDestroyWindow( hwnd ); return retval; } diff --git a/dlls/user32/driver.c b/dlls/user32/driver.c index 72ea5ad17bd..ada0b8ca2f7 100644 --- a/dlls/user32/driver.c +++ b/dlls/user32/driver.c @@ -79,10 +79,6 @@ static BOOL CDECL nulldrv_CreateWindow( HWND hwnd ) return TRUE; } -static void CDECL nulldrv_DestroyWindow( HWND hwnd ) -{ -} - static DWORD CDECL nulldrv_MsgWaitForMultipleObjectsEx( DWORD count, const HANDLE *handles, DWORD timeout, DWORD mask, DWORD flags ) { @@ -174,7 +170,7 @@ static struct user_driver_funcs lazy_load_driver = /* windowing functions */ NULL, loaderdrv_CreateWindow, - nulldrv_DestroyWindow, + NULL, NULL, NULL, nulldrv_MsgWaitForMultipleObjectsEx, @@ -223,7 +219,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(DestroyWindow); SET_USER_FUNC(MsgWaitForMultipleObjectsEx); SET_USER_FUNC(SetWindowIcon); SET_USER_FUNC(SetWindowText); diff --git a/dlls/user32/mdi.c b/dlls/user32/mdi.c index 6bab3e96adf..3d85487f808 100644 --- a/dlls/user32/mdi.c +++ b/dlls/user32/mdi.c @@ -580,7 +580,7 @@ static LRESULT MDIDestroyChild( HWND client, MDICLIENTINFO *ci, { SendMessageW(client, WM_MDIREFRESHMENU, 0, 0); MDI_PostUpdate(GetParent(child), ci, SB_BOTH+1); - DestroyWindow(child); + NtUserDestroyWindow(child); } TRACE("child destroyed - %p\n", child); diff --git a/dlls/user32/menu.c b/dlls/user32/menu.c index 1d680009747..113e6103cd9 100644 --- a/dlls/user32/menu.c +++ b/dlls/user32/menu.c @@ -2333,7 +2333,7 @@ static void MENU_HideSubPopups( HWND hwndOwner, HMENU hmenu, if (!(submenu = MENU_GetMenu( hsubmenu ))) return; MENU_HideSubPopups( hwndOwner, hsubmenu, FALSE, wFlags ); MENU_SelectItem( hwndOwner, hsubmenu, NO_SELECTED_ITEM, sendMenuSelect, 0 ); - DestroyWindow( submenu->hWnd ); + NtUserDestroyWindow( submenu->hWnd ); submenu->hWnd = 0; if (!(wFlags & TPM_NONOTIFY)) @@ -3319,7 +3319,7 @@ static BOOL MENU_TrackMenu( HMENU hmenu, UINT wFlags, INT x, INT y, if (menu && (menu->wFlags & MF_POPUP)) { - DestroyWindow( menu->hWnd ); + NtUserDestroyWindow( menu->hWnd ); menu->hWnd = 0; if (!(wFlags & TPM_NONOTIFY)) @@ -3531,7 +3531,7 @@ BOOL WINAPI TrackPopupMenuEx( HMENU hMenu, UINT wFlags, INT x, INT y, if (menu->hWnd) { - DestroyWindow( menu->hWnd ); + NtUserDestroyWindow( menu->hWnd ); menu->hWnd = 0; if (!(wFlags & TPM_NONOTIFY)) @@ -4269,7 +4269,7 @@ BOOL WINAPI DestroyMenu( HMENU hMenu ) /* DestroyMenu should not destroy system menu popup owner */ if ((lppop->wFlags & (MF_POPUP | MF_SYSMENU)) == MF_POPUP && lppop->hWnd) { - DestroyWindow( lppop->hWnd ); + NtUserDestroyWindow( lppop->hWnd ); lppop->hWnd = 0; } diff --git a/dlls/user32/message.c b/dlls/user32/message.c index 365f703c56e..0ba540d2e5d 100644 --- a/dlls/user32/message.c +++ b/dlls/user32/message.c @@ -1859,8 +1859,6 @@ LRESULT handle_internal_message( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpar { switch(msg) { - case WM_WINE_DESTROYWINDOW: - return WIN_DestroyWindow( hwnd ); case WM_WINE_SHOWWINDOW: if (is_desktop_window( hwnd )) return 0; return ShowWindow( hwnd, wparam ); diff --git a/dlls/user32/msgbox.c b/dlls/user32/msgbox.c index 195bab2384b..c74d33092f0 100644 --- a/dlls/user32/msgbox.c +++ b/dlls/user32/msgbox.c @@ -116,57 +116,57 @@ static void MSGBOX_OnInit(HWND hwnd, LPMSGBOXPARAMSW lpmb) hItem = 0; switch(lpmb->dwStyle & MB_TYPEMASK) { case MB_OK: - DestroyWindow(GetDlgItem(hwnd, IDCANCEL)); + NtUserDestroyWindow(GetDlgItem(hwnd, IDCANCEL)); /* fall through */ case MB_OKCANCEL: hItem = GetDlgItem(hwnd, IDOK); - DestroyWindow(GetDlgItem(hwnd, IDABORT)); - DestroyWindow(GetDlgItem(hwnd, IDRETRY)); - DestroyWindow(GetDlgItem(hwnd, IDIGNORE)); - DestroyWindow(GetDlgItem(hwnd, IDYES)); - DestroyWindow(GetDlgItem(hwnd, IDNO)); - DestroyWindow(GetDlgItem(hwnd, IDTRYAGAIN)); - DestroyWindow(GetDlgItem(hwnd, IDCONTINUE)); + NtUserDestroyWindow(GetDlgItem(hwnd, IDABORT)); + NtUserDestroyWindow(GetDlgItem(hwnd, IDRETRY)); + NtUserDestroyWindow(GetDlgItem(hwnd, IDIGNORE)); + NtUserDestroyWindow(GetDlgItem(hwnd, IDYES)); + NtUserDestroyWindow(GetDlgItem(hwnd, IDNO)); + NtUserDestroyWindow(GetDlgItem(hwnd, IDTRYAGAIN)); + NtUserDestroyWindow(GetDlgItem(hwnd, IDCONTINUE)); break; case MB_ABORTRETRYIGNORE: hItem = GetDlgItem(hwnd, IDABORT); - DestroyWindow(GetDlgItem(hwnd, IDOK)); - DestroyWindow(GetDlgItem(hwnd, IDCANCEL)); - DestroyWindow(GetDlgItem(hwnd, IDYES)); - DestroyWindow(GetDlgItem(hwnd, IDNO)); - DestroyWindow(GetDlgItem(hwnd, IDCONTINUE)); - DestroyWindow(GetDlgItem(hwnd, IDTRYAGAIN)); + NtUserDestroyWindow(GetDlgItem(hwnd, IDOK)); + NtUserDestroyWindow(GetDlgItem(hwnd, IDCANCEL)); + NtUserDestroyWindow(GetDlgItem(hwnd, IDYES)); + NtUserDestroyWindow(GetDlgItem(hwnd, IDNO)); + NtUserDestroyWindow(GetDlgItem(hwnd, IDCONTINUE)); + NtUserDestroyWindow(GetDlgItem(hwnd, IDTRYAGAIN)); break; case MB_YESNO: - DestroyWindow(GetDlgItem(hwnd, IDCANCEL)); + NtUserDestroyWindow(GetDlgItem(hwnd, IDCANCEL)); /* fall through */ case MB_YESNOCANCEL: hItem = GetDlgItem(hwnd, IDYES); - DestroyWindow(GetDlgItem(hwnd, IDOK)); - DestroyWindow(GetDlgItem(hwnd, IDABORT)); - DestroyWindow(GetDlgItem(hwnd, IDRETRY)); - DestroyWindow(GetDlgItem(hwnd, IDIGNORE)); - DestroyWindow(GetDlgItem(hwnd, IDCONTINUE)); - DestroyWindow(GetDlgItem(hwnd, IDTRYAGAIN)); + NtUserDestroyWindow(GetDlgItem(hwnd, IDOK)); + NtUserDestroyWindow(GetDlgItem(hwnd, IDABORT)); + NtUserDestroyWindow(GetDlgItem(hwnd, IDRETRY)); + NtUserDestroyWindow(GetDlgItem(hwnd, IDIGNORE)); + NtUserDestroyWindow(GetDlgItem(hwnd, IDCONTINUE)); + NtUserDestroyWindow(GetDlgItem(hwnd, IDTRYAGAIN)); break; case MB_RETRYCANCEL: hItem = GetDlgItem(hwnd, IDRETRY); - DestroyWindow(GetDlgItem(hwnd, IDOK)); - DestroyWindow(GetDlgItem(hwnd, IDABORT)); - DestroyWindow(GetDlgItem(hwnd, IDIGNORE)); - DestroyWindow(GetDlgItem(hwnd, IDYES)); - DestroyWindow(GetDlgItem(hwnd, IDNO)); - DestroyWindow(GetDlgItem(hwnd, IDCONTINUE)); - DestroyWindow(GetDlgItem(hwnd, IDTRYAGAIN)); + NtUserDestroyWindow(GetDlgItem(hwnd, IDOK)); + NtUserDestroyWindow(GetDlgItem(hwnd, IDABORT)); + NtUserDestroyWindow(GetDlgItem(hwnd, IDIGNORE)); + NtUserDestroyWindow(GetDlgItem(hwnd, IDYES)); + NtUserDestroyWindow(GetDlgItem(hwnd, IDNO)); + NtUserDestroyWindow(GetDlgItem(hwnd, IDCONTINUE)); + NtUserDestroyWindow(GetDlgItem(hwnd, IDTRYAGAIN)); break; case MB_CANCELTRYCONTINUE: hItem = GetDlgItem(hwnd, IDCANCEL); - DestroyWindow(GetDlgItem(hwnd, IDOK)); - DestroyWindow(GetDlgItem(hwnd, IDABORT)); - DestroyWindow(GetDlgItem(hwnd, IDIGNORE)); - DestroyWindow(GetDlgItem(hwnd, IDYES)); - DestroyWindow(GetDlgItem(hwnd, IDNO)); - DestroyWindow(GetDlgItem(hwnd, IDRETRY)); + NtUserDestroyWindow(GetDlgItem(hwnd, IDOK)); + NtUserDestroyWindow(GetDlgItem(hwnd, IDABORT)); + NtUserDestroyWindow(GetDlgItem(hwnd, IDIGNORE)); + NtUserDestroyWindow(GetDlgItem(hwnd, IDYES)); + NtUserDestroyWindow(GetDlgItem(hwnd, IDNO)); + NtUserDestroyWindow(GetDlgItem(hwnd, IDRETRY)); } if (hItem) SetWindowLongW(hItem, GWL_STYLE, GetWindowLongW(hItem, GWL_STYLE) | WS_GROUP); @@ -202,7 +202,7 @@ static void MSGBOX_OnInit(HWND hwnd, LPMSGBOXPARAMSW lpmb) /* Remove Help button unless MB_HELP supplied */ if (!(lpmb->dwStyle & MB_HELP)) { - DestroyWindow(GetDlgItem(hwnd, IDHELP)); + NtUserDestroyWindow(GetDlgItem(hwnd, IDHELP)); } /* Position everything */ diff --git a/dlls/user32/painting.c b/dlls/user32/painting.c index 8722cb68f12..ee9d23b1f71 100644 --- a/dlls/user32/painting.c +++ b/dlls/user32/painting.c @@ -35,18 +35,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(win); -/*********************************************************************** - * free_dce - * - * Free a class or window DCE. - */ -void free_dce( struct dce *dce, HWND hwnd ) -{ - /* FIXME: move callers to win32u */ - NtUserCallTwoParam( (UINT_PTR)dce, HandleToUlong(hwnd), NtUserFreeDCE ); -} - - /*********************************************************************** * invalidate_dce * diff --git a/dlls/user32/user32.spec b/dlls/user32/user32.spec index 7c27d9400db..cb18d9415c9 100644 --- a/dlls/user32/user32.spec +++ b/dlls/user32/user32.spec @@ -161,7 +161,7 @@ @ stdcall DestroyIcon(long) @ stdcall DestroyMenu(long) # @ stub DestroyReasons -@ stdcall DestroyWindow(long) +@ stdcall DestroyWindow(long) NtUserDestroyWindow # @ stub DeviceEventWorker @ stdcall DialogBoxIndirectParamA(long ptr long ptr long) @ stdcall DialogBoxIndirectParamAorW(long ptr long ptr long long) diff --git a/dlls/user32/user_main.c b/dlls/user32/user_main.c index ff9b469dae6..bc0dec6b579 100644 --- a/dlls/user32/user_main.c +++ b/dlls/user32/user_main.c @@ -140,6 +140,11 @@ 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 ) +{ + imm_unregister_window( hwnd ); +} + static void CDECL free_win_ptr( WND *win ) { HeapFree( GetProcessHeap(), 0, win->text ); @@ -150,7 +155,9 @@ static void CDECL free_win_ptr( WND *win ) static const struct user_callbacks user_funcs = { CopyImage, + DestroyCaret, DestroyMenu, + EndMenu, HideCaret, PostMessageW, SendInput, @@ -161,12 +168,14 @@ static const struct user_callbacks user_funcs = ShowWindow, WaitForInputIdle, free_win_ptr, + MENU_IsMenuActive, notify_ime, register_builtin_classes, MSG_SendInternalMessageTimeout, SCROLL_SetStandardScrollPainted, (void *)__wine_set_user_driver, set_window_pos, + unregister_imm, }; static void WINAPI User32CallFreeIcon( ULONG *param, ULONG size ) @@ -227,6 +236,7 @@ static void thread_detach(void) struct user_thread_info *thread_info = get_user_thread_info(); exiting_thread_id = GetCurrentThreadId(); + NtUserCallNoParam( NtUserExitingThread ); WDML_NotifyThreadDetach(); diff --git a/dlls/user32/win.c b/dlls/user32/win.c index b57d6bd7566..b0e6b33eb56 100644 --- a/dlls/user32/win.c +++ b/dlls/user32/win.c @@ -558,38 +558,6 @@ HWND WIN_GetFullHandle( HWND hwnd ) } -/*********************************************************************** - * WIN_SetOwner - * - * Change the owner of a window. - */ -static HWND WIN_SetOwner( HWND hwnd, HWND owner ) -{ - WND *win = WIN_GetPtr( hwnd ); - HWND ret = 0; - - if (!win || win == WND_DESKTOP) return 0; - if (win == WND_OTHER_PROCESS) - { - if (IsWindow(hwnd)) ERR( "cannot set owner %p on other process window %p\n", owner, hwnd ); - return 0; - } - SERVER_START_REQ( set_window_owner ) - { - req->handle = wine_server_user_handle( hwnd ); - req->owner = wine_server_user_handle( owner ); - if (!wine_server_call( req )) - { - win->owner = wine_server_ptr_handle( reply->full_owner ); - ret = wine_server_ptr_handle( reply->prev_owner ); - } - } - SERVER_END_REQ; - WIN_ReleasePtr( win ); - return ret; -} - - /*********************************************************************** * WIN_SetStyle * @@ -739,87 +707,6 @@ other_process: } -/*********************************************************************** - * WIN_DestroyWindow - * - * Destroy storage associated to a window. "Internals" p.358 - */ -LRESULT WIN_DestroyWindow( HWND hwnd ) -{ - WND *wndPtr; - HWND *list; - HMENU menu = 0, sys_menu; - struct window_surface *surface; - - TRACE("%p\n", hwnd ); - - /* destroy default IME window */ - if (win_set_flags( hwnd, 0, WIN_HAS_IME_WIN ) & WIN_HAS_IME_WIN) - { - TRACE("unregister IME window for %p\n", hwnd); - imm_unregister_window( hwnd ); - } - - /* free child windows */ - if ((list = WIN_ListChildren( hwnd ))) - { - int i; - for (i = 0; list[i]; i++) - { - if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] ); - else SendNotifyMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 ); - } - HeapFree( GetProcessHeap(), 0, list ); - } - - /* Unlink now so we won't bother with the children later on */ - SERVER_START_REQ( set_parent ) - { - req->handle = wine_server_user_handle( hwnd ); - req->parent = 0; - wine_server_call( req ); - } - SERVER_END_REQ; - - /* - * Send the WM_NCDESTROY to the window being destroyed. - */ - SendMessageW( hwnd, WM_NCDESTROY, 0, 0 ); - - /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */ - - /* free resources associated with the window */ - - if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0; - if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD) - menu = (HMENU)wndPtr->wIDmenu; - sys_menu = wndPtr->hSysMenu; - free_dce( wndPtr->dce, hwnd ); - wndPtr->dce = NULL; - HeapFree( GetProcessHeap(), 0, wndPtr->text ); - wndPtr->text = NULL; - HeapFree( GetProcessHeap(), 0, wndPtr->pScroll ); - wndPtr->pScroll = NULL; - DestroyIcon( wndPtr->hIconSmall2 ); - surface = wndPtr->surface; - wndPtr->surface = NULL; - WIN_ReleasePtr( wndPtr ); - - if (menu) DestroyMenu( menu ); - if (sys_menu) DestroyMenu( sys_menu ); - if (surface) - { - register_window_surface( surface, NULL ); - window_surface_release( surface ); - } - - USER_Driver->pDestroyWindow( hwnd ); - - free_window_handle( hwnd ); - return 0; -} - - /*********************************************************************** * WIN_FixCoordinates * @@ -1435,7 +1322,7 @@ HWND WIN_CreateWindowEx( CREATESTRUCTW *cs, LPCWSTR className, HINSTANCE module, return hwnd; failed: - WIN_DestroyWindow( hwnd ); + NtUserCallHwnd( hwnd, NtUserDestroyWindowHandle ); SetThreadDpiAwarenessContext( context ); return 0; } @@ -1506,139 +1393,6 @@ HWND WINAPI DECLSPEC_HOTPATCH CreateWindowExW( DWORD exStyle, LPCWSTR className, } -/*********************************************************************** - * WIN_SendDestroyMsg - */ -static void WIN_SendDestroyMsg( HWND hwnd ) -{ - GUITHREADINFO info; - - info.cbSize = sizeof(info); - if (NtUserGetGUIThreadInfo( GetCurrentThreadId(), &info )) - { - if (hwnd == info.hwndCaret) DestroyCaret(); - if (hwnd == info.hwndActive) WINPOS_ActivateOtherWindow( hwnd ); - } - - if (hwnd == NtUserGetClipboardOwner()) CLIPBOARD_ReleaseOwner( hwnd ); - - /* - * Send the WM_DESTROY to the window. - */ - SendMessageW( hwnd, WM_DESTROY, 0, 0); - - /* - * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow - * make sure that the window still exists when we come back. - */ - if (IsWindow(hwnd)) - { - HWND* pWndArray; - int i; - - if (!(pWndArray = WIN_ListChildren( hwnd ))) return; - - for (i = 0; pWndArray[i]; i++) - { - if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] ); - } - HeapFree( GetProcessHeap(), 0, pWndArray ); - } - else - WARN("\tdestroyed itself while in WM_DESTROY!\n"); -} - - -/*********************************************************************** - * DestroyWindow (USER32.@) - */ -BOOL WINAPI DestroyWindow( HWND hwnd ) -{ - BOOL is_child; - - if (!(hwnd = WIN_IsCurrentThread( hwnd )) || is_desktop_window( hwnd )) - { - SetLastError( ERROR_ACCESS_DENIED ); - return FALSE; - } - - TRACE("(%p)\n", hwnd); - - /* Call hooks */ - - if (HOOK_CallHooks( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0, TRUE )) return FALSE; - - if (MENU_IsMenuActive() == hwnd) - EndMenu(); - - is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0; - - if (is_child) - { - if (!USER_IsExitingThread( GetCurrentThreadId() )) - send_parent_notify( hwnd, WM_DESTROY ); - } - else if (!GetWindow( hwnd, GW_OWNER )) - { - HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L, TRUE ); - /* FIXME: clean up palette - see "Internals" p.352 */ - } - - if (!IsWindow(hwnd)) return TRUE; - - /* Hide the window */ - if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE) - { - /* Only child windows receive WM_SHOWWINDOW in DestroyWindow() */ - if (is_child) - ShowWindow( hwnd, SW_HIDE ); - else - NtUserSetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | - SWP_NOZORDER | SWP_NOACTIVATE | SWP_HIDEWINDOW ); - } - - if (!IsWindow(hwnd)) return TRUE; - - /* Recursively destroy owned windows */ - - if (!is_child) - { - for (;;) - { - int i; - BOOL got_one = FALSE; - HWND *list = WIN_ListChildren( GetDesktopWindow() ); - if (list) - { - for (i = 0; list[i]; i++) - { - if (GetWindow( list[i], GW_OWNER ) != hwnd) continue; - if (WIN_IsCurrentThread( list[i] )) - { - DestroyWindow( list[i] ); - got_one = TRUE; - continue; - } - WIN_SetOwner( list[i], 0 ); - } - HeapFree( GetProcessHeap(), 0, list ); - } - if (!got_one) break; - } - } - - /* Send destroy messages */ - - WIN_SendDestroyMsg( hwnd ); - if (!IsWindow( hwnd )) return TRUE; - - /* Destroy the window storage */ - - WIN_DestroyWindow( hwnd ); - return TRUE; -} - - /*********************************************************************** * CloseWindow (USER32.@) */ diff --git a/dlls/user32/win.h b/dlls/user32/win.h index 3e6885ab090..89e91a255f9 100644 --- a/dlls/user32/win.h +++ b/dlls/user32/win.h @@ -45,7 +45,6 @@ extern HWND WIN_IsCurrentThread( HWND hwnd ) DECLSPEC_HIDDEN; extern UINT win_set_flags( HWND hwnd, UINT set_mask, UINT clear_mask ) DECLSPEC_HIDDEN; extern ULONG WIN_SetStyle( HWND hwnd, ULONG set_bits, ULONG clear_bits ) DECLSPEC_HIDDEN; extern BOOL WIN_GetRectangles( HWND hwnd, enum coords_relative relative, RECT *rectWindow, RECT *rectClient ) DECLSPEC_HIDDEN; -extern LRESULT WIN_DestroyWindow( HWND hwnd ) DECLSPEC_HIDDEN; extern HWND WIN_CreateWindowEx( CREATESTRUCTW *cs, LPCWSTR className, HINSTANCE module, BOOL unicode ) DECLSPEC_HIDDEN; extern BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL ) DECLSPEC_HIDDEN; extern HWND *WIN_ListChildren( HWND hwnd ) DECLSPEC_HIDDEN; diff --git a/dlls/win32u/clipboard.c b/dlls/win32u/clipboard.c index e132f981344..585a2aae631 100644 --- a/dlls/win32u/clipboard.c +++ b/dlls/win32u/clipboard.c @@ -288,3 +288,28 @@ BOOL WINAPI NtUserRemoveClipboardFormatListener( HWND hwnd ) SERVER_END_REQ; return ret; } + +/************************************************************************** + * release_clipboard_owner + */ +void release_clipboard_owner( HWND hwnd ) +{ + HWND viewer = 0, owner = 0; + + send_message( hwnd, WM_RENDERALLFORMATS, 0, 0 ); + + SERVER_START_REQ( release_clipboard ) + { + req->owner = wine_server_user_handle( hwnd ); + if (!wine_server_call( req )) + { + viewer = wine_server_ptr_handle( reply->viewer ); + owner = wine_server_ptr_handle( reply->owner ); + } + } + SERVER_END_REQ; + + if (viewer) + NtUserMessageCall( viewer, WM_DRAWCLIPBOARD, (WPARAM)owner, 0, + 0, FNID_SENDNOTIFYMESSAGE, FALSE ); +} diff --git a/dlls/win32u/driver.c b/dlls/win32u/driver.c index afe44e1c4a3..166c2009dbc 100644 --- a/dlls/win32u/driver.c +++ b/dlls/win32u/driver.c @@ -1190,6 +1190,7 @@ static const struct user_driver_funcs lazy_load_driver = .pUpdateDisplayDevices = loaderdrv_UpdateDisplayDevices, /* windowing functions */ .pCreateDesktopWindow = loaderdrv_CreateDesktopWindow, + .pDestroyWindow = nulldrv_DestroyWindow, .pFlashWindowEx = loaderdrv_FlashWindowEx, .pGetDC = loaderdrv_GetDC, .pSetCapture = nulldrv_SetCapture, diff --git a/dlls/win32u/gdiobj.c b/dlls/win32u/gdiobj.c index adb162ab7ff..69607f0e3de 100644 --- a/dlls/win32u/gdiobj.c +++ b/dlls/win32u/gdiobj.c @@ -1162,6 +1162,7 @@ static struct unix_funcs unix_funcs = NtUserCountClipboardFormats, NtUserDeferWindowPosAndBand, NtUserDestroyCursor, + NtUserDestroyWindow, NtUserDrawIconEx, NtUserEndDeferWindowPosEx, NtUserEndPaint, diff --git a/dlls/win32u/message.c b/dlls/win32u/message.c index d00178e6aa4..690de6cdf8a 100644 --- a/dlls/win32u/message.c +++ b/dlls/win32u/message.c @@ -41,6 +41,8 @@ LRESULT handle_internal_message( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpar { switch(msg) { + case WM_WINE_DESTROYWINDOW: + return destroy_window( hwnd ); case WM_WINE_SETWINDOWPOS: if (is_desktop_window( hwnd )) return 0; return set_window_pos( (WINDOWPOS *)lparam, 0, 0 ); diff --git a/dlls/win32u/ntuser_private.h b/dlls/win32u/ntuser_private.h index aa9b45b1542..b3cafe791df 100644 --- a/dlls/win32u/ntuser_private.h +++ b/dlls/win32u/ntuser_private.h @@ -31,7 +31,9 @@ struct tagWND; struct user_callbacks { HANDLE (WINAPI *pCopyImage)( HANDLE, UINT, INT, INT, UINT ); + BOOL (WINAPI *pDestroyCaret)(void); BOOL (WINAPI *pDestroyMenu)( HMENU ); + BOOL (WINAPI *pEndMenu)(void); BOOL (WINAPI *pHideCaret)( HWND hwnd ); BOOL (WINAPI *pPostMessageW)( HWND, UINT, WPARAM, LPARAM ); UINT (WINAPI *pSendInput)( UINT count, INPUT *inputs, int size ); @@ -42,6 +44,7 @@ struct user_callbacks BOOL (WINAPI *pShowWindow)( HWND, INT ); DWORD (WINAPI *pWaitForInputIdle)( HANDLE, DWORD ); void (CDECL *free_win_ptr)( struct tagWND *win ); + HWND (CDECL *is_menu_active)(void); 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 ); @@ -50,6 +53,7 @@ struct user_callbacks 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 ); + void (WINAPI *unregister_imm)( HWND hwnd ); }; #define WM_SYSTIMER 0x0118 diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index d9ddfe3400e..0166b64c76a 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -4591,6 +4591,16 @@ static BOOL message_beep( UINT i ) return TRUE; } +static DWORD exiting_thread_id; + +/********************************************************************** + * is_exiting_thread + */ +BOOL is_exiting_thread( DWORD tid ) +{ + return tid == exiting_thread_id; +} + static void thread_detach(void) { struct user_thread_info *thread_info = get_user_thread_info(); @@ -4602,6 +4612,8 @@ static void thread_detach(void) destroy_thread_windows(); NtClose( thread_info->server_queue ); + + exiting_thread_id = 0; } /*********************************************************************** @@ -4618,6 +4630,9 @@ ULONG_PTR WINAPI NtUserCallNoParam( ULONG code ) case NtUserReleaseCapture: return release_capture(); /* temporary exports */ + case NtUserExitingThread: + exiting_thread_id = GetCurrentThreadId(); + return 0; case NtUserThreadDetach: thread_detach(); return 0; @@ -4724,9 +4739,6 @@ ULONG_PTR WINAPI NtUserCallTwoParam( ULONG_PTR arg1, ULONG_PTR arg2, ULONG code return HandleToUlong( alloc_user_handle( (struct user_object *)arg1, arg2 )); case NtUserAllocWinProc: return (UINT_PTR)alloc_winproc( (WNDPROC)arg1, arg2 ); - case NtUserFreeDCE: - free_dce( (struct dce *)arg1, UlongToHandle(arg2) ); - return 0; case NtUserFreeHandle: return (UINT_PTR)free_user_handle( UlongToHandle(arg1), arg2 ); case NtUserGetHandlePtr: diff --git a/dlls/win32u/win32u.spec b/dlls/win32u/win32u.spec index 96d8d4833b0..aacfebd1b15 100644 --- a/dlls/win32u/win32u.spec +++ b/dlls/win32u/win32u.spec @@ -834,7 +834,7 @@ @ stub NtUserDestroyInputContext @ stub NtUserDestroyMenu @ stub NtUserDestroyPalmRejectionDelayZone -@ stub NtUserDestroyWindow +@ stdcall NtUserDestroyWindow(long) @ stub NtUserDisableImmersiveOwner @ stub NtUserDisableProcessWindowFiltering @ stub NtUserDisableThreadIme diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h index 516f4540315..83b0e093a20 100644 --- a/dlls/win32u/win32u_private.h +++ b/dlls/win32u/win32u_private.h @@ -199,6 +199,7 @@ struct unix_funcs INT x, INT y, INT cx, INT cy, UINT flags, UINT unk1, UINT unk2 ); BOOL (WINAPI *pNtUserDestroyCursor)( HCURSOR cursor, ULONG arg ); + BOOL (WINAPI *pNtUserDestroyWindow)( HWND hwnd ); BOOL (WINAPI *pNtUserDrawIconEx)( HDC hdc, INT x0, INT y0, HICON icon, INT width, INT height, UINT istep, HBRUSH hbr, UINT flags ); BOOL (WINAPI *pNtUserEndDeferWindowPosEx)( HDWP hdwp, BOOL async ); @@ -286,6 +287,9 @@ struct unix_funcs struct window_surface *surface ); }; +/* clipboard.c */ +extern void release_clipboard_owner( HWND hwnd ) DECLSPEC_HIDDEN; + /* cursoricon.c */ extern HICON alloc_cursoricon_handle( BOOL is_icon ) DECLSPEC_HIDDEN; extern BOOL get_clip_cursor( RECT *rect ) DECLSPEC_HIDDEN; @@ -327,6 +331,7 @@ 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 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; extern RECT map_dpi_rect( RECT rect, UINT dpi_from, UINT dpi_to ) DECLSPEC_HIDDEN; extern HMONITOR monitor_from_point( POINT pt, DWORD flags, UINT dpi ) DECLSPEC_HIDDEN; @@ -344,6 +349,7 @@ extern void erase_now( HWND hwnd, UINT rdw_flags ) DECLSPEC_HIDDEN; struct tagWND; extern HDWP begin_defer_window_pos( INT count ) DECLSPEC_HIDDEN; extern void destroy_thread_windows(void) DECLSPEC_HIDDEN; +extern LRESULT destroy_window( HWND hwnd ) DECLSPEC_HIDDEN; extern HWND get_desktop_window(void) DECLSPEC_HIDDEN; extern UINT get_dpi_for_window( HWND hwnd ) DECLSPEC_HIDDEN; extern HWND get_full_window_handle( HWND hwnd ) DECLSPEC_HIDDEN; diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index a28b6ae9ebf..f8d147b785c 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -3174,6 +3174,99 @@ BOOL WINAPI NtUserEndDeferWindowPosEx( HDWP hdwp, BOOL async ) return TRUE; } +/*********************************************************************** + * win_set_flags + * + * Set the flags of a window and return the previous value. + */ +static UINT win_set_flags( HWND hwnd, UINT set_mask, UINT clear_mask ) +{ + WND *win = get_win_ptr( hwnd ); + UINT ret; + + if (!win || win == WND_OTHER_PROCESS || win == WND_DESKTOP) return 0; + ret = win->flags; + win->flags = (ret & ~clear_mask) | set_mask; + release_win_ptr( win ); + return ret; +} + +/******************************************************************* + * can_activate_window + * + * Check if we can activate the specified window. + */ +static BOOL can_activate_window( HWND hwnd ) +{ + LONG style; + + if (!hwnd) return FALSE; + style = get_window_long( hwnd, GWL_STYLE ); + if (!(style & WS_VISIBLE)) return FALSE; + if ((style & (WS_POPUP|WS_CHILD)) == WS_CHILD) return FALSE; + return !(style & WS_DISABLED); +} + +/******************************************************************* + * activate_other_window + * + * Activates window other than hwnd. + */ +static void activate_other_window( HWND hwnd ) +{ + HWND hwnd_to, fg; + + if ((get_window_long( hwnd, GWL_STYLE ) & WS_POPUP) && + (hwnd_to = get_window_relative( hwnd, GW_OWNER ))) + { + hwnd_to = NtUserGetAncestor( hwnd_to, GA_ROOT ); + if (can_activate_window( hwnd_to )) goto done; + } + + hwnd_to = hwnd; + for (;;) + { + if (!(hwnd_to = get_window_relative( hwnd_to, GW_HWNDNEXT ))) break; + if (can_activate_window( hwnd_to )) goto done; + } + + hwnd_to = get_window_relative( get_desktop_window(), GW_CHILD ); + for (;;) + { + if (hwnd_to == hwnd) + { + hwnd_to = 0; + break; + } + if (can_activate_window( hwnd_to )) goto done; + if (!(hwnd_to = get_window_relative( hwnd_to, GW_HWNDNEXT ))) break; + } + + done: + fg = NtUserGetForegroundWindow(); + TRACE( "win = %p fg = %p\n", hwnd_to, fg ); + if (!fg || hwnd == fg) + { + if (set_foreground_window( hwnd_to, FALSE )) return; + } + if (NtUserSetActiveWindow( hwnd_to )) NtUserSetActiveWindow( 0 ); +} + +/******************************************************************* + * send_parent_notify + */ +static void send_parent_notify( HWND hwnd, UINT msg ) +{ + if ((get_window_long( hwnd, GWL_STYLE ) & (WS_CHILD | WS_POPUP)) == WS_CHILD && + !(get_window_long( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY)) + { + HWND parent = get_parent( hwnd ); + if (parent && parent != get_desktop_window()) + send_message( parent, WM_PARENTNOTIFY, + MAKEWPARAM( msg, get_window_long( hwnd, GWLP_ID )), (LPARAM)hwnd ); + } +} + /******************************************************************* * update_window_state * @@ -3260,6 +3353,226 @@ BOOL WINAPI NtUserFlashWindowEx( FLASHWINFO *info ) } /*********************************************************************** + * send_destroy_message + */ +static void send_destroy_message( HWND hwnd ) +{ + GUITHREADINFO info; + + info.cbSize = sizeof(info); + if (NtUserGetGUIThreadInfo( GetCurrentThreadId(), &info )) + { + if (hwnd == info.hwndCaret && user_callbacks) user_callbacks->pDestroyCaret(); + if (hwnd == info.hwndActive) activate_other_window( hwnd ); + } + + if (hwnd == NtUserGetClipboardOwner()) release_clipboard_owner( hwnd ); + + send_message( hwnd, WM_DESTROY, 0, 0); + + /* + * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow + * make sure that the window still exists when we come back. + */ + if (is_window(hwnd)) + { + HWND *children; + int i; + + if (!(children = list_window_children( 0, hwnd, NULL, 0 ))) return; + + for (i = 0; children[i]; i++) + { + if (is_window( children[i] )) send_destroy_message( children[i] ); + } + free( children ); + } + else + WARN( "\tdestroyed itself while in WM_DESTROY!\n" ); +} + +/*********************************************************************** + * free_window_handle + * + * Free a window handle. + */ +static void free_window_handle( HWND hwnd ) +{ + WND *win; + + TRACE( "\n" ); + + if ((win = get_user_handle_ptr( hwnd, NTUSER_OBJ_WINDOW )) && win != OBJ_OTHER_PROCESS) + { + SERVER_START_REQ( destroy_window ) + { + req->handle = wine_server_user_handle( hwnd ); + wine_server_call( req ); + set_user_handle_ptr( hwnd, NULL ); + } + SERVER_END_REQ; + user_unlock(); + if (user_callbacks) user_callbacks->free_win_ptr( win ); + } +} + +/*********************************************************************** + * destroy_window + */ +LRESULT destroy_window( HWND hwnd ) +{ + struct window_surface *surface; + HMENU menu = 0, sys_menu; + WND *win; + HWND *children; + + TRACE( "%p\n", hwnd ); + + /* destroy default IME window */ + if (win_set_flags( hwnd, 0, WIN_HAS_IME_WIN ) & WIN_HAS_IME_WIN) + { + TRACE("unregister IME window for %p\n", hwnd); + if (user_callbacks) user_callbacks->unregister_imm( hwnd ); + } + + /* free child windows */ + if ((children = list_window_children( 0, hwnd, NULL, 0 ))) + { + int i; + for (i = 0; children[i]; i++) + { + if (is_current_thread_window( children[i] )) + destroy_window( children[i] ); + else + NtUserMessageCall( children[i], WM_WINE_DESTROYWINDOW, 0, 0, + 0, FNID_SENDNOTIFYMESSAGE, FALSE ); + } + free( children ); + } + + /* Unlink now so we won't bother with the children later on */ + SERVER_START_REQ( set_parent ) + { + req->handle = wine_server_user_handle( hwnd ); + req->parent = 0; + wine_server_call( req ); + } + SERVER_END_REQ; + + send_message( hwnd, WM_NCDESTROY, 0, 0 ); + + /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */ + + /* free resources associated with the window */ + + if (!(win = get_win_ptr( hwnd )) || win == WND_OTHER_PROCESS) return 0; + if ((win->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD) + menu = (HMENU)win->wIDmenu; + sys_menu = win->hSysMenu; + free_dce( win->dce, hwnd ); + win->dce = NULL; + NtUserDestroyCursor( win->hIconSmall2, 0 ); + surface = win->surface; + win->surface = NULL; + release_win_ptr( win ); + + NtUserDestroyMenu( menu ); + NtUserDestroyMenu( sys_menu ); + if (surface) + { + register_window_surface( surface, NULL ); + window_surface_release( surface ); + } + + user_driver->pDestroyWindow( hwnd ); + + free_window_handle( hwnd ); + return 0; +} + +/*********************************************************************** + * NtUserDestroyWindow (win32u.@) + */ +BOOL WINAPI NtUserDestroyWindow( HWND hwnd ) +{ + BOOL is_child; + + if (!(hwnd = is_current_thread_window( hwnd )) || is_desktop_window( hwnd )) + { + SetLastError( ERROR_ACCESS_DENIED ); + return FALSE; + } + + TRACE( "(%p)\n", hwnd ); + + if (call_hooks( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0, TRUE )) return FALSE; + + if (user_callbacks && user_callbacks->is_menu_active() == hwnd) + user_callbacks->pEndMenu(); + + is_child = (get_window_long( hwnd, GWL_STYLE ) & WS_CHILD) != 0; + + if (is_child) + { + if (!is_exiting_thread( GetCurrentThreadId() )) + send_parent_notify( hwnd, WM_DESTROY ); + } + else if (!get_window_relative( hwnd, GW_OWNER )) + { + call_hooks( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L, TRUE ); + /* FIXME: clean up palette - see "Internals" p.352 */ + } + + if (!is_window( hwnd )) return TRUE; + + /* Hide the window */ + if (get_window_long( hwnd, GWL_STYLE ) & WS_VISIBLE) + { + /* Only child windows receive WM_SHOWWINDOW in DestroyWindow() */ + if (is_child) + NtUserShowWindow( hwnd, SW_HIDE ); + else + NtUserSetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | + SWP_NOZORDER | SWP_NOACTIVATE | SWP_HIDEWINDOW ); + } + + if (!is_window( hwnd )) return TRUE; + + /* Recursively destroy child windows */ + if (!is_child) + { + for (;;) + { + BOOL got_one = FALSE; + HWND *children; + unsigned int i; + + if (!(children = list_window_children( 0, get_desktop_window(), NULL, 0 ))) break; + + for (i = 0; children[i]; i++) + { + if (get_window_relative( children[i], GW_OWNER ) != hwnd) continue; + if (is_current_thread_window( children[i] )) + { + NtUserDestroyWindow( children[i] ); + got_one = TRUE; + continue; + } + set_window_owner( children[i], 0 ); + } + free( children ); + if (!got_one) break; + } + } + + send_destroy_message( hwnd ); + if (!is_window( hwnd )) return TRUE; + + destroy_window( hwnd ); + return TRUE; +} + +/***************************************************************************** * destroy_thread_windows * * Destroy all window owned by the current thread. @@ -3329,6 +3642,8 @@ ULONG_PTR WINAPI NtUserCallHwnd( HWND hwnd, DWORD code ) /* 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 258483ad8de..da1957c8c88 100644 --- a/dlls/win32u/wrappers.c +++ b/dlls/win32u/wrappers.c @@ -783,6 +783,12 @@ BOOL WINAPI NtUserDestroyCursor( HCURSOR cursor, ULONG arg ) return unix_funcs->pNtUserDestroyCursor( cursor, arg ); } +BOOL WINAPI NtUserDestroyWindow( HWND hwnd ) +{ + if (!unix_funcs) return FALSE; + return unix_funcs->pNtUserDestroyWindow( hwnd ); +} + BOOL WINAPI NtUserDrawIconEx( HDC hdc, INT x0, INT y0, HICON icon, INT width, INT height, UINT istep, HBRUSH hbr, UINT flags ) { diff --git a/include/ntuser.h b/include/ntuser.h index aeb3e9ae2cc..de958caa735 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -91,6 +91,7 @@ enum NtUserGetInputState, NtUserReleaseCapture, /* temporary exports */ + NtUserExitingThread, NtUserThreadDetach, }; @@ -134,7 +135,6 @@ enum /* temporary exports */ NtUserAllocHandle, NtUserAllocWinProc, - NtUserFreeDCE, NtUserFreeHandle, NtUserGetHandlePtr, NtUserInvalidateDCE, @@ -154,6 +154,7 @@ enum NtUserIsWindowVisible, /* temporary exports */ NtUserCreateDesktopWindow, + NtUserDestroyWindowHandle, NtUserGetDummySurface, }; @@ -302,6 +303,7 @@ HDWP WINAPI NtUserDeferWindowPosAndBand( HDWP hdwp, HWND hwnd, HWND after, IN BOOL WINAPI NtUserDestroyAcceleratorTable( HACCEL handle ); BOOL WINAPI NtUserDestroyCursor( HCURSOR cursor, ULONG arg ); BOOL WINAPI NtUserDestroyMenu( HMENU menu ); +BOOL WINAPI NtUserDestroyWindow( HWND hwnd ); BOOL WINAPI NtUserDrawIconEx( HDC hdc, INT x0, INT y0, HICON icon, INT width, INT height, UINT istep, HBRUSH hbr, UINT flags ); BOOL WINAPI NtUserEndDeferWindowPosEx( HDWP hdwp, BOOL async );