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; 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.@) * RegisterClipboardFormatW (USER32.@)

View File

@ -173,7 +173,7 @@ static LRESULT COMBO_NCDestroy( LPHEADCOMBO lphc )
TRACE("[%p]: freeing storage\n", lphc->self); TRACE("[%p]: freeing storage\n", lphc->self);
if( (CB_GETTYPE(lphc) != CBS_SIMPLE) && lphc->hWndLBox ) if( (CB_GETTYPE(lphc) != CBS_SIMPLE) && lphc->hWndLBox )
DestroyWindow( lphc->hWndLBox ); NtUserDestroyWindow( lphc->hWndLBox );
SetWindowLongPtrW( lphc->self, 0, 0 ); SetWindowLongPtrW( lphc->self, 0, 0 );
HeapFree( GetProcessHeap(), 0, lphc ); HeapFree( GetProcessHeap(), 0, lphc );

View File

@ -1158,7 +1158,7 @@ BOOL WINAPI DdeUninitialize(DWORD idInst)
*/ */
WDML_FreeAllHSZ(pInstance); WDML_FreeAllHSZ(pInstance);
DestroyWindow(pInstance->hwndEvent); NtUserDestroyWindow( pInstance->hwndEvent );
/* OK now delete the instance handle itself */ /* 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; pPrev->next = pServer->next;
} }
DestroyWindow(pServer->hwndServer); NtUserDestroyWindow(pServer->hwndServer);
WDML_DecHSZ(pInstance, pServer->hszServiceSpec); WDML_DecHSZ(pInstance, pServer->hszServiceSpec);
WDML_DecHSZ(pInstance, pServer->hszService); 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; hWnd = (side == WDML_CLIENT_SIDE) ? pRef->hwndClient : pRef->hwndServer;
SetWindowLongPtrW(hWnd, GWL_WDML_CONVERSATION, 0); 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->hszService);
WDML_DecHSZ(pRef->instance, pRef->hszTopic); WDML_DecHSZ(pRef->instance, pRef->hszTopic);

View File

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

View File

@ -400,7 +400,7 @@ static LRESULT DEFWND_DefWinProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPa
return 0; return 0;
case WM_CLOSE: case WM_CLOSE:
DestroyWindow( hwnd ); NtUserDestroyWindow( hwnd );
return 0; return 0;
case WM_MOUSEACTIVATE: case WM_MOUSEACTIVATE:

View File

@ -707,7 +707,7 @@ static HWND DIALOG_CreateIndirect( HINSTANCE hInst, LPCVOID dlgTemplate,
return hwnd; return hwnd;
} }
if (disabled_owner) EnableWindow( disabled_owner, TRUE ); if (disabled_owner) EnableWindow( disabled_owner, TRUE );
if( IsWindow(hwnd) ) DestroyWindow( hwnd ); if (IsWindow(hwnd)) NtUserDestroyWindow( hwnd );
return 0; return 0;
} }
@ -827,7 +827,7 @@ INT DIALOG_DoDialogBox( HWND hwnd, HWND owner )
} }
} }
retval = dlgInfo->idResult; retval = dlgInfo->idResult;
DestroyWindow( hwnd ); NtUserDestroyWindow( hwnd );
return retval; return retval;
} }

View File

@ -79,10 +79,6 @@ static BOOL CDECL nulldrv_CreateWindow( HWND hwnd )
return TRUE; return TRUE;
} }
static void CDECL nulldrv_DestroyWindow( HWND hwnd )
{
}
static DWORD CDECL nulldrv_MsgWaitForMultipleObjectsEx( DWORD count, const HANDLE *handles, DWORD timeout, static DWORD CDECL nulldrv_MsgWaitForMultipleObjectsEx( DWORD count, const HANDLE *handles, DWORD timeout,
DWORD mask, DWORD flags ) DWORD mask, DWORD flags )
{ {
@ -174,7 +170,7 @@ static struct user_driver_funcs lazy_load_driver =
/* windowing functions */ /* windowing functions */
NULL, NULL,
loaderdrv_CreateWindow, loaderdrv_CreateWindow,
nulldrv_DestroyWindow, NULL,
NULL, NULL,
NULL, NULL,
nulldrv_MsgWaitForMultipleObjectsEx, 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(SetCursorPos);
SET_USER_FUNC(UpdateClipboard); SET_USER_FUNC(UpdateClipboard);
SET_USER_FUNC(CreateWindow); SET_USER_FUNC(CreateWindow);
SET_USER_FUNC(DestroyWindow);
SET_USER_FUNC(MsgWaitForMultipleObjectsEx); SET_USER_FUNC(MsgWaitForMultipleObjectsEx);
SET_USER_FUNC(SetWindowIcon); SET_USER_FUNC(SetWindowIcon);
SET_USER_FUNC(SetWindowText); SET_USER_FUNC(SetWindowText);

View File

@ -580,7 +580,7 @@ static LRESULT MDIDestroyChild( HWND client, MDICLIENTINFO *ci,
{ {
SendMessageW(client, WM_MDIREFRESHMENU, 0, 0); SendMessageW(client, WM_MDIREFRESHMENU, 0, 0);
MDI_PostUpdate(GetParent(child), ci, SB_BOTH+1); MDI_PostUpdate(GetParent(child), ci, SB_BOTH+1);
DestroyWindow(child); NtUserDestroyWindow(child);
} }
TRACE("child destroyed - %p\n", 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; if (!(submenu = MENU_GetMenu( hsubmenu ))) return;
MENU_HideSubPopups( hwndOwner, hsubmenu, FALSE, wFlags ); MENU_HideSubPopups( hwndOwner, hsubmenu, FALSE, wFlags );
MENU_SelectItem( hwndOwner, hsubmenu, NO_SELECTED_ITEM, sendMenuSelect, 0 ); MENU_SelectItem( hwndOwner, hsubmenu, NO_SELECTED_ITEM, sendMenuSelect, 0 );
DestroyWindow( submenu->hWnd ); NtUserDestroyWindow( submenu->hWnd );
submenu->hWnd = 0; submenu->hWnd = 0;
if (!(wFlags & TPM_NONOTIFY)) 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)) if (menu && (menu->wFlags & MF_POPUP))
{ {
DestroyWindow( menu->hWnd ); NtUserDestroyWindow( menu->hWnd );
menu->hWnd = 0; menu->hWnd = 0;
if (!(wFlags & TPM_NONOTIFY)) if (!(wFlags & TPM_NONOTIFY))
@ -3531,7 +3531,7 @@ BOOL WINAPI TrackPopupMenuEx( HMENU hMenu, UINT wFlags, INT x, INT y,
if (menu->hWnd) if (menu->hWnd)
{ {
DestroyWindow( menu->hWnd ); NtUserDestroyWindow( menu->hWnd );
menu->hWnd = 0; menu->hWnd = 0;
if (!(wFlags & TPM_NONOTIFY)) if (!(wFlags & TPM_NONOTIFY))
@ -4269,7 +4269,7 @@ BOOL WINAPI DestroyMenu( HMENU hMenu )
/* DestroyMenu should not destroy system menu popup owner */ /* DestroyMenu should not destroy system menu popup owner */
if ((lppop->wFlags & (MF_POPUP | MF_SYSMENU)) == MF_POPUP && lppop->hWnd) if ((lppop->wFlags & (MF_POPUP | MF_SYSMENU)) == MF_POPUP && lppop->hWnd)
{ {
DestroyWindow( lppop->hWnd ); NtUserDestroyWindow( lppop->hWnd );
lppop->hWnd = 0; lppop->hWnd = 0;
} }

View File

@ -1859,8 +1859,6 @@ LRESULT handle_internal_message( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpar
{ {
switch(msg) switch(msg)
{ {
case WM_WINE_DESTROYWINDOW:
return WIN_DestroyWindow( hwnd );
case WM_WINE_SHOWWINDOW: case WM_WINE_SHOWWINDOW:
if (is_desktop_window( hwnd )) return 0; if (is_desktop_window( hwnd )) return 0;
return ShowWindow( hwnd, wparam ); return ShowWindow( hwnd, wparam );

View File

@ -116,57 +116,57 @@ static void MSGBOX_OnInit(HWND hwnd, LPMSGBOXPARAMSW lpmb)
hItem = 0; hItem = 0;
switch(lpmb->dwStyle & MB_TYPEMASK) { switch(lpmb->dwStyle & MB_TYPEMASK) {
case MB_OK: case MB_OK:
DestroyWindow(GetDlgItem(hwnd, IDCANCEL)); NtUserDestroyWindow(GetDlgItem(hwnd, IDCANCEL));
/* fall through */ /* fall through */
case MB_OKCANCEL: case MB_OKCANCEL:
hItem = GetDlgItem(hwnd, IDOK); hItem = GetDlgItem(hwnd, IDOK);
DestroyWindow(GetDlgItem(hwnd, IDABORT)); NtUserDestroyWindow(GetDlgItem(hwnd, IDABORT));
DestroyWindow(GetDlgItem(hwnd, IDRETRY)); NtUserDestroyWindow(GetDlgItem(hwnd, IDRETRY));
DestroyWindow(GetDlgItem(hwnd, IDIGNORE)); NtUserDestroyWindow(GetDlgItem(hwnd, IDIGNORE));
DestroyWindow(GetDlgItem(hwnd, IDYES)); NtUserDestroyWindow(GetDlgItem(hwnd, IDYES));
DestroyWindow(GetDlgItem(hwnd, IDNO)); NtUserDestroyWindow(GetDlgItem(hwnd, IDNO));
DestroyWindow(GetDlgItem(hwnd, IDTRYAGAIN)); NtUserDestroyWindow(GetDlgItem(hwnd, IDTRYAGAIN));
DestroyWindow(GetDlgItem(hwnd, IDCONTINUE)); NtUserDestroyWindow(GetDlgItem(hwnd, IDCONTINUE));
break; break;
case MB_ABORTRETRYIGNORE: case MB_ABORTRETRYIGNORE:
hItem = GetDlgItem(hwnd, IDABORT); hItem = GetDlgItem(hwnd, IDABORT);
DestroyWindow(GetDlgItem(hwnd, IDOK)); NtUserDestroyWindow(GetDlgItem(hwnd, IDOK));
DestroyWindow(GetDlgItem(hwnd, IDCANCEL)); NtUserDestroyWindow(GetDlgItem(hwnd, IDCANCEL));
DestroyWindow(GetDlgItem(hwnd, IDYES)); NtUserDestroyWindow(GetDlgItem(hwnd, IDYES));
DestroyWindow(GetDlgItem(hwnd, IDNO)); NtUserDestroyWindow(GetDlgItem(hwnd, IDNO));
DestroyWindow(GetDlgItem(hwnd, IDCONTINUE)); NtUserDestroyWindow(GetDlgItem(hwnd, IDCONTINUE));
DestroyWindow(GetDlgItem(hwnd, IDTRYAGAIN)); NtUserDestroyWindow(GetDlgItem(hwnd, IDTRYAGAIN));
break; break;
case MB_YESNO: case MB_YESNO:
DestroyWindow(GetDlgItem(hwnd, IDCANCEL)); NtUserDestroyWindow(GetDlgItem(hwnd, IDCANCEL));
/* fall through */ /* fall through */
case MB_YESNOCANCEL: case MB_YESNOCANCEL:
hItem = GetDlgItem(hwnd, IDYES); hItem = GetDlgItem(hwnd, IDYES);
DestroyWindow(GetDlgItem(hwnd, IDOK)); NtUserDestroyWindow(GetDlgItem(hwnd, IDOK));
DestroyWindow(GetDlgItem(hwnd, IDABORT)); NtUserDestroyWindow(GetDlgItem(hwnd, IDABORT));
DestroyWindow(GetDlgItem(hwnd, IDRETRY)); NtUserDestroyWindow(GetDlgItem(hwnd, IDRETRY));
DestroyWindow(GetDlgItem(hwnd, IDIGNORE)); NtUserDestroyWindow(GetDlgItem(hwnd, IDIGNORE));
DestroyWindow(GetDlgItem(hwnd, IDCONTINUE)); NtUserDestroyWindow(GetDlgItem(hwnd, IDCONTINUE));
DestroyWindow(GetDlgItem(hwnd, IDTRYAGAIN)); NtUserDestroyWindow(GetDlgItem(hwnd, IDTRYAGAIN));
break; break;
case MB_RETRYCANCEL: case MB_RETRYCANCEL:
hItem = GetDlgItem(hwnd, IDRETRY); hItem = GetDlgItem(hwnd, IDRETRY);
DestroyWindow(GetDlgItem(hwnd, IDOK)); NtUserDestroyWindow(GetDlgItem(hwnd, IDOK));
DestroyWindow(GetDlgItem(hwnd, IDABORT)); NtUserDestroyWindow(GetDlgItem(hwnd, IDABORT));
DestroyWindow(GetDlgItem(hwnd, IDIGNORE)); NtUserDestroyWindow(GetDlgItem(hwnd, IDIGNORE));
DestroyWindow(GetDlgItem(hwnd, IDYES)); NtUserDestroyWindow(GetDlgItem(hwnd, IDYES));
DestroyWindow(GetDlgItem(hwnd, IDNO)); NtUserDestroyWindow(GetDlgItem(hwnd, IDNO));
DestroyWindow(GetDlgItem(hwnd, IDCONTINUE)); NtUserDestroyWindow(GetDlgItem(hwnd, IDCONTINUE));
DestroyWindow(GetDlgItem(hwnd, IDTRYAGAIN)); NtUserDestroyWindow(GetDlgItem(hwnd, IDTRYAGAIN));
break; break;
case MB_CANCELTRYCONTINUE: case MB_CANCELTRYCONTINUE:
hItem = GetDlgItem(hwnd, IDCANCEL); hItem = GetDlgItem(hwnd, IDCANCEL);
DestroyWindow(GetDlgItem(hwnd, IDOK)); NtUserDestroyWindow(GetDlgItem(hwnd, IDOK));
DestroyWindow(GetDlgItem(hwnd, IDABORT)); NtUserDestroyWindow(GetDlgItem(hwnd, IDABORT));
DestroyWindow(GetDlgItem(hwnd, IDIGNORE)); NtUserDestroyWindow(GetDlgItem(hwnd, IDIGNORE));
DestroyWindow(GetDlgItem(hwnd, IDYES)); NtUserDestroyWindow(GetDlgItem(hwnd, IDYES));
DestroyWindow(GetDlgItem(hwnd, IDNO)); NtUserDestroyWindow(GetDlgItem(hwnd, IDNO));
DestroyWindow(GetDlgItem(hwnd, IDRETRY)); NtUserDestroyWindow(GetDlgItem(hwnd, IDRETRY));
} }
if (hItem) SetWindowLongW(hItem, GWL_STYLE, GetWindowLongW(hItem, GWL_STYLE) | WS_GROUP); 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 */ /* Remove Help button unless MB_HELP supplied */
if (!(lpmb->dwStyle & MB_HELP)) { if (!(lpmb->dwStyle & MB_HELP)) {
DestroyWindow(GetDlgItem(hwnd, IDHELP)); NtUserDestroyWindow(GetDlgItem(hwnd, IDHELP));
} }
/* Position everything */ /* Position everything */

View File

@ -35,18 +35,6 @@
WINE_DEFAULT_DEBUG_CHANNEL(win); 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 * invalidate_dce
* *

View File

@ -161,7 +161,7 @@
@ stdcall DestroyIcon(long) @ stdcall DestroyIcon(long)
@ stdcall DestroyMenu(long) @ stdcall DestroyMenu(long)
# @ stub DestroyReasons # @ stub DestroyReasons
@ stdcall DestroyWindow(long) @ stdcall DestroyWindow(long) NtUserDestroyWindow
# @ stub DeviceEventWorker # @ stub DeviceEventWorker
@ stdcall DialogBoxIndirectParamA(long ptr long ptr long) @ stdcall DialogBoxIndirectParamA(long ptr long ptr long)
@ stdcall DialogBoxIndirectParamAorW(long ptr long ptr long 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) ); 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 ) static void CDECL free_win_ptr( WND *win )
{ {
HeapFree( GetProcessHeap(), 0, win->text ); HeapFree( GetProcessHeap(), 0, win->text );
@ -150,7 +155,9 @@ static void CDECL free_win_ptr( WND *win )
static const struct user_callbacks user_funcs = static const struct user_callbacks user_funcs =
{ {
CopyImage, CopyImage,
DestroyCaret,
DestroyMenu, DestroyMenu,
EndMenu,
HideCaret, HideCaret,
PostMessageW, PostMessageW,
SendInput, SendInput,
@ -161,12 +168,14 @@ static const struct user_callbacks user_funcs =
ShowWindow, ShowWindow,
WaitForInputIdle, WaitForInputIdle,
free_win_ptr, free_win_ptr,
MENU_IsMenuActive,
notify_ime, notify_ime,
register_builtin_classes, register_builtin_classes,
MSG_SendInternalMessageTimeout, MSG_SendInternalMessageTimeout,
SCROLL_SetStandardScrollPainted, SCROLL_SetStandardScrollPainted,
(void *)__wine_set_user_driver, (void *)__wine_set_user_driver,
set_window_pos, set_window_pos,
unregister_imm,
}; };
static void WINAPI User32CallFreeIcon( ULONG *param, ULONG size ) 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(); struct user_thread_info *thread_info = get_user_thread_info();
exiting_thread_id = GetCurrentThreadId(); exiting_thread_id = GetCurrentThreadId();
NtUserCallNoParam( NtUserExitingThread );
WDML_NotifyThreadDetach(); 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 * 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 * WIN_FixCoordinates
* *
@ -1435,7 +1322,7 @@ HWND WIN_CreateWindowEx( CREATESTRUCTW *cs, LPCWSTR className, HINSTANCE module,
return hwnd; return hwnd;
failed: failed:
WIN_DestroyWindow( hwnd ); NtUserCallHwnd( hwnd, NtUserDestroyWindowHandle );
SetThreadDpiAwarenessContext( context ); SetThreadDpiAwarenessContext( context );
return 0; 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.@) * 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 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 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 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 HWND WIN_CreateWindowEx( CREATESTRUCTW *cs, LPCWSTR className, HINSTANCE module, BOOL unicode ) DECLSPEC_HIDDEN;
extern BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL ) DECLSPEC_HIDDEN; extern BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL ) DECLSPEC_HIDDEN;
extern HWND *WIN_ListChildren( HWND hwnd ) DECLSPEC_HIDDEN; extern HWND *WIN_ListChildren( HWND hwnd ) DECLSPEC_HIDDEN;

View File

@ -288,3 +288,28 @@ BOOL WINAPI NtUserRemoveClipboardFormatListener( HWND hwnd )
SERVER_END_REQ; SERVER_END_REQ;
return ret; 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, .pUpdateDisplayDevices = loaderdrv_UpdateDisplayDevices,
/* windowing functions */ /* windowing functions */
.pCreateDesktopWindow = loaderdrv_CreateDesktopWindow, .pCreateDesktopWindow = loaderdrv_CreateDesktopWindow,
.pDestroyWindow = nulldrv_DestroyWindow,
.pFlashWindowEx = loaderdrv_FlashWindowEx, .pFlashWindowEx = loaderdrv_FlashWindowEx,
.pGetDC = loaderdrv_GetDC, .pGetDC = loaderdrv_GetDC,
.pSetCapture = nulldrv_SetCapture, .pSetCapture = nulldrv_SetCapture,

View File

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

View File

@ -41,6 +41,8 @@ LRESULT handle_internal_message( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpar
{ {
switch(msg) switch(msg)
{ {
case WM_WINE_DESTROYWINDOW:
return destroy_window( hwnd );
case WM_WINE_SETWINDOWPOS: case WM_WINE_SETWINDOWPOS:
if (is_desktop_window( hwnd )) return 0; if (is_desktop_window( hwnd )) return 0;
return set_window_pos( (WINDOWPOS *)lparam, 0, 0 ); return set_window_pos( (WINDOWPOS *)lparam, 0, 0 );

View File

@ -31,7 +31,9 @@ struct tagWND;
struct user_callbacks struct user_callbacks
{ {
HANDLE (WINAPI *pCopyImage)( HANDLE, UINT, INT, INT, UINT ); HANDLE (WINAPI *pCopyImage)( HANDLE, UINT, INT, INT, UINT );
BOOL (WINAPI *pDestroyCaret)(void);
BOOL (WINAPI *pDestroyMenu)( HMENU ); BOOL (WINAPI *pDestroyMenu)( HMENU );
BOOL (WINAPI *pEndMenu)(void);
BOOL (WINAPI *pHideCaret)( HWND hwnd ); BOOL (WINAPI *pHideCaret)( HWND hwnd );
BOOL (WINAPI *pPostMessageW)( HWND, UINT, WPARAM, LPARAM ); BOOL (WINAPI *pPostMessageW)( HWND, UINT, WPARAM, LPARAM );
UINT (WINAPI *pSendInput)( UINT count, INPUT *inputs, int size ); UINT (WINAPI *pSendInput)( UINT count, INPUT *inputs, int size );
@ -42,6 +44,7 @@ struct user_callbacks
BOOL (WINAPI *pShowWindow)( HWND, INT ); BOOL (WINAPI *pShowWindow)( HWND, INT );
DWORD (WINAPI *pWaitForInputIdle)( HANDLE, DWORD ); DWORD (WINAPI *pWaitForInputIdle)( HANDLE, DWORD );
void (CDECL *free_win_ptr)( struct tagWND *win ); void (CDECL *free_win_ptr)( struct tagWND *win );
HWND (CDECL *is_menu_active)(void);
void (CDECL *notify_ime)( HWND hwnd, UINT param ); void (CDECL *notify_ime)( HWND hwnd, UINT param );
void (CDECL *register_builtin_classes)(void); void (CDECL *register_builtin_classes)(void);
LRESULT (WINAPI *send_ll_message)( DWORD, DWORD, UINT, WPARAM, LPARAM, UINT, UINT, PDWORD_PTR ); 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, BOOL (CDECL *set_window_pos)( HWND hwnd, HWND insert_after, UINT swp_flags,
const RECT *window_rect, const RECT *client_rect, const RECT *window_rect, const RECT *client_rect,
const RECT *valid_rects ); const RECT *valid_rects );
void (WINAPI *unregister_imm)( HWND hwnd );
}; };
#define WM_SYSTIMER 0x0118 #define WM_SYSTIMER 0x0118

View File

@ -4591,6 +4591,16 @@ static BOOL message_beep( UINT i )
return TRUE; 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) static void thread_detach(void)
{ {
struct user_thread_info *thread_info = get_user_thread_info(); struct user_thread_info *thread_info = get_user_thread_info();
@ -4602,6 +4612,8 @@ static void thread_detach(void)
destroy_thread_windows(); destroy_thread_windows();
NtClose( thread_info->server_queue ); NtClose( thread_info->server_queue );
exiting_thread_id = 0;
} }
/*********************************************************************** /***********************************************************************
@ -4618,6 +4630,9 @@ ULONG_PTR WINAPI NtUserCallNoParam( ULONG code )
case NtUserReleaseCapture: case NtUserReleaseCapture:
return release_capture(); return release_capture();
/* temporary exports */ /* temporary exports */
case NtUserExitingThread:
exiting_thread_id = GetCurrentThreadId();
return 0;
case NtUserThreadDetach: case NtUserThreadDetach:
thread_detach(); thread_detach();
return 0; 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 )); return HandleToUlong( alloc_user_handle( (struct user_object *)arg1, arg2 ));
case NtUserAllocWinProc: case NtUserAllocWinProc:
return (UINT_PTR)alloc_winproc( (WNDPROC)arg1, arg2 ); return (UINT_PTR)alloc_winproc( (WNDPROC)arg1, arg2 );
case NtUserFreeDCE:
free_dce( (struct dce *)arg1, UlongToHandle(arg2) );
return 0;
case NtUserFreeHandle: case NtUserFreeHandle:
return (UINT_PTR)free_user_handle( UlongToHandle(arg1), arg2 ); return (UINT_PTR)free_user_handle( UlongToHandle(arg1), arg2 );
case NtUserGetHandlePtr: case NtUserGetHandlePtr:

View File

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

View File

@ -199,6 +199,7 @@ struct unix_funcs
INT x, INT y, INT cx, INT cy, INT x, INT y, INT cx, INT cy,
UINT flags, UINT unk1, UINT unk2 ); UINT flags, UINT unk1, UINT unk2 );
BOOL (WINAPI *pNtUserDestroyCursor)( HCURSOR cursor, ULONG arg ); 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, BOOL (WINAPI *pNtUserDrawIconEx)( HDC hdc, INT x0, INT y0, HICON icon, INT width,
INT height, UINT istep, HBRUSH hbr, UINT flags ); INT height, UINT istep, HBRUSH hbr, UINT flags );
BOOL (WINAPI *pNtUserEndDeferWindowPosEx)( HDWP hdwp, BOOL async ); BOOL (WINAPI *pNtUserEndDeferWindowPosEx)( HDWP hdwp, BOOL async );
@ -286,6 +287,9 @@ struct unix_funcs
struct window_surface *surface ); struct window_surface *surface );
}; };
/* clipboard.c */
extern void release_clipboard_owner( HWND hwnd ) DECLSPEC_HIDDEN;
/* cursoricon.c */ /* cursoricon.c */
extern HICON alloc_cursoricon_handle( BOOL is_icon ) DECLSPEC_HIDDEN; extern HICON alloc_cursoricon_handle( BOOL is_icon ) DECLSPEC_HIDDEN;
extern BOOL get_clip_cursor( RECT *rect ) 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 int get_system_metrics( int index ) DECLSPEC_HIDDEN;
extern UINT get_thread_dpi(void) DECLSPEC_HIDDEN; extern UINT get_thread_dpi(void) DECLSPEC_HIDDEN;
extern RECT get_virtual_screen_rect( UINT dpi ) 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 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 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; 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; struct tagWND;
extern HDWP begin_defer_window_pos( INT count ) DECLSPEC_HIDDEN; extern HDWP begin_defer_window_pos( INT count ) DECLSPEC_HIDDEN;
extern void destroy_thread_windows(void) 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 HWND get_desktop_window(void) DECLSPEC_HIDDEN;
extern UINT get_dpi_for_window( HWND hwnd ) DECLSPEC_HIDDEN; extern UINT get_dpi_for_window( HWND hwnd ) DECLSPEC_HIDDEN;
extern HWND get_full_window_handle( 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; 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 * 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_thread_windows
* *
* Destroy all window owned by the current thread. * Destroy all window owned by the current thread.
@ -3329,6 +3642,8 @@ ULONG_PTR WINAPI NtUserCallHwnd( HWND hwnd, DWORD code )
/* temporary exports */ /* temporary exports */
case NtUserCreateDesktopWindow: case NtUserCreateDesktopWindow:
return user_driver->pCreateDesktopWindow( hwnd ); return user_driver->pCreateDesktopWindow( hwnd );
case NtUserDestroyWindowHandle:
return destroy_window( hwnd );
case NtUserGetDummySurface: case NtUserGetDummySurface:
return (UINT_PTR)&dummy_surface; return (UINT_PTR)&dummy_surface;
default: default:

View File

@ -783,6 +783,12 @@ BOOL WINAPI NtUserDestroyCursor( HCURSOR cursor, ULONG arg )
return unix_funcs->pNtUserDestroyCursor( cursor, 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, BOOL WINAPI NtUserDrawIconEx( HDC hdc, INT x0, INT y0, HICON icon, INT width,
INT height, UINT istep, HBRUSH hbr, UINT flags ) INT height, UINT istep, HBRUSH hbr, UINT flags )
{ {

View File

@ -91,6 +91,7 @@ enum
NtUserGetInputState, NtUserGetInputState,
NtUserReleaseCapture, NtUserReleaseCapture,
/* temporary exports */ /* temporary exports */
NtUserExitingThread,
NtUserThreadDetach, NtUserThreadDetach,
}; };
@ -134,7 +135,6 @@ enum
/* temporary exports */ /* temporary exports */
NtUserAllocHandle, NtUserAllocHandle,
NtUserAllocWinProc, NtUserAllocWinProc,
NtUserFreeDCE,
NtUserFreeHandle, NtUserFreeHandle,
NtUserGetHandlePtr, NtUserGetHandlePtr,
NtUserInvalidateDCE, NtUserInvalidateDCE,
@ -154,6 +154,7 @@ enum
NtUserIsWindowVisible, NtUserIsWindowVisible,
/* temporary exports */ /* temporary exports */
NtUserCreateDesktopWindow, NtUserCreateDesktopWindow,
NtUserDestroyWindowHandle,
NtUserGetDummySurface, NtUserGetDummySurface,
}; };
@ -302,6 +303,7 @@ HDWP WINAPI NtUserDeferWindowPosAndBand( HDWP hdwp, HWND hwnd, HWND after, IN
BOOL WINAPI NtUserDestroyAcceleratorTable( HACCEL handle ); BOOL WINAPI NtUserDestroyAcceleratorTable( HACCEL handle );
BOOL WINAPI NtUserDestroyCursor( HCURSOR cursor, ULONG arg ); BOOL WINAPI NtUserDestroyCursor( HCURSOR cursor, ULONG arg );
BOOL WINAPI NtUserDestroyMenu( HMENU menu ); BOOL WINAPI NtUserDestroyMenu( HMENU menu );
BOOL WINAPI NtUserDestroyWindow( HWND hwnd );
BOOL WINAPI NtUserDrawIconEx( HDC hdc, INT x0, INT y0, HICON icon, INT width, BOOL WINAPI NtUserDrawIconEx( HDC hdc, INT x0, INT y0, HICON icon, INT width,
INT height, UINT istep, HBRUSH hbr, UINT flags ); INT height, UINT istep, HBRUSH hbr, UINT flags );
BOOL WINAPI NtUserEndDeferWindowPosEx( HDWP hdwp, BOOL async ); BOOL WINAPI NtUserEndDeferWindowPosEx( HDWP hdwp, BOOL async );