win32u: Move NtUserDestroyWindow implementation from user32.

Signed-off-by: Jacek Caban <jacek@codeweavers.com>
Signed-off-by: Huw Davies <huw@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Jacek Caban 2022-03-17 15:29:30 +00:00 committed by Alexandre Julliard
parent 7a7d999d4a
commit 6a5ddbeedc
27 changed files with 440 additions and 345 deletions

View File

@ -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.@)

View File

@ -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 );

View File

@ -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);

View File

@ -360,7 +360,7 @@ static WDML_CONV* WDML_CreateServerConv(WDML_INSTANCE* pInstance, HWND hwndClien
}
else
{
DestroyWindow(hwndServerConv);
NtUserDestroyWindow(hwndServerConv);
}
return pConv;
}

View File

@ -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:

View File

@ -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;
}

View File

@ -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);

View File

@ -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);

View File

@ -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;
}

View File

@ -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 );

View File

@ -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 */

View File

@ -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
*

View File

@ -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)

View File

@ -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();

View File

@ -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.@)
*/

View File

@ -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;

View File

@ -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 );
}

View File

@ -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,

View File

@ -1162,6 +1162,7 @@ static struct unix_funcs unix_funcs =
NtUserCountClipboardFormats,
NtUserDeferWindowPosAndBand,
NtUserDestroyCursor,
NtUserDestroyWindow,
NtUserDrawIconEx,
NtUserEndDeferWindowPosEx,
NtUserEndPaint,

View File

@ -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 );

View File

@ -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

View File

@ -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:

View File

@ -834,7 +834,7 @@
@ stub NtUserDestroyInputContext
@ stub NtUserDestroyMenu
@ stub NtUserDestroyPalmRejectionDelayZone
@ stub NtUserDestroyWindow
@ stdcall NtUserDestroyWindow(long)
@ stub NtUserDisableImmersiveOwner
@ stub NtUserDisableProcessWindowFiltering
@ stub NtUserDisableThreadIme

View File

@ -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;

View File

@ -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:

View File

@ -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 )
{

View File

@ -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 );