Wine-devel
Threads by month
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
March 2022
- 80 participants
- 950 discussions
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/winealsa.drv/alsamidi.c | 129 +++++++++++++++++++++++++++++++++
dlls/winealsa.drv/midi.c | 134 ++---------------------------------
2 files changed, 135 insertions(+), 128 deletions(-)
diff --git a/dlls/winealsa.drv/alsamidi.c b/dlls/winealsa.drv/alsamidi.c
index a92c08793af..32c983ba0a3 100644
--- a/dlls/winealsa.drv/alsamidi.c
+++ b/dlls/winealsa.drv/alsamidi.c
@@ -525,6 +525,132 @@ static UINT midi_out_close(WORD dev_id, struct notify_context *notify)
return MMSYSERR_NOERROR;
}
+static UINT midi_out_data(WORD dev_id, UINT data)
+{
+ BYTE evt = LOBYTE(LOWORD(data));
+ BYTE d1 = HIBYTE(LOWORD(data));
+ BYTE d2 = LOBYTE(HIWORD(data));
+ struct midi_dest *dest;
+
+ TRACE("(%04X, %08X);\n", dev_id, data);
+
+ if (dev_id >= num_dests) return MMSYSERR_BADDEVICEID;
+ dest = dests + dev_id;
+
+ if (!dest->bEnabled) return MIDIERR_NODEVICE;
+
+ if (dest->seq == NULL)
+ {
+ WARN("can't play !\n");
+ return MIDIERR_NODEVICE;
+ }
+ switch (dest->caps.wTechnology)
+ {
+ case MOD_SYNTH:
+ case MOD_MIDIPORT:
+ {
+ int handled = 1; /* Assume event is handled */
+ snd_seq_event_t event;
+ snd_seq_ev_clear(&event);
+ snd_seq_ev_set_direct(&event);
+ snd_seq_ev_set_source(&event, dest->port_out);
+ snd_seq_ev_set_subs(&event);
+
+ switch (evt & 0xF0)
+ {
+ case MIDI_CMD_NOTE_OFF:
+ snd_seq_ev_set_noteoff(&event, evt & 0x0F, d1, d2);
+ break;
+ case MIDI_CMD_NOTE_ON:
+ snd_seq_ev_set_noteon(&event, evt & 0x0F, d1, d2);
+ break;
+ case MIDI_CMD_NOTE_PRESSURE:
+ snd_seq_ev_set_keypress(&event, evt & 0x0F, d1, d2);
+ break;
+ case MIDI_CMD_CONTROL:
+ snd_seq_ev_set_controller(&event, evt & 0x0F, d1, d2);
+ break;
+ case MIDI_CMD_BENDER:
+ snd_seq_ev_set_pitchbend(&event, evt & 0x0F, ((WORD)d2 << 7 | (WORD)d1) - 0x2000);
+ break;
+ case MIDI_CMD_PGM_CHANGE:
+ snd_seq_ev_set_pgmchange(&event, evt & 0x0F, d1);
+ break;
+ case MIDI_CMD_CHANNEL_PRESSURE:
+ snd_seq_ev_set_chanpress(&event, evt & 0x0F, d1);
+ break;
+ case MIDI_CMD_COMMON_SYSEX:
+ switch (evt & 0x0F)
+ {
+ case 0x00: /* System Exclusive, don't do it on modData,
+ * should require modLongData*/
+ case 0x04: /* Undefined. */
+ case 0x05: /* Undefined. */
+ case 0x07: /* End of Exclusive. */
+ case 0x09: /* Undefined. */
+ case 0x0D: /* Undefined. */
+ handled = 0;
+ break;
+ case 0x06: /* Tune Request */
+ case 0x08: /* Timing Clock. */
+ case 0x0A: /* Start. */
+ case 0x0B: /* Continue */
+ case 0x0C: /* Stop */
+ case 0x0E: /* Active Sensing. */
+ {
+ snd_midi_event_t *midi_event;
+
+ snd_midi_event_new(1, &midi_event);
+ snd_midi_event_init(midi_event);
+ snd_midi_event_encode_byte(midi_event, evt, &event);
+ snd_midi_event_free(midi_event);
+ break;
+ }
+ case 0x0F: /* Reset */
+ /* snd_seq_ev_set_sysex(&event, 1, &evt);
+ this other way may be better */
+ {
+ BYTE reset_sysex_seq[] = {MIDI_CMD_COMMON_SYSEX, 0x7e, 0x7f, 0x09, 0x01, 0xf7};
+ snd_seq_ev_set_sysex(&event, sizeof(reset_sysex_seq), reset_sysex_seq);
+ break;
+ }
+ case 0x01: /* MTC Quarter frame */
+ case 0x03: /* Song Select. */
+ {
+ BYTE buf[2];
+ buf[0] = evt;
+ buf[1] = d1;
+ snd_seq_ev_set_sysex(&event, sizeof(buf), buf);
+ break;
+ }
+ case 0x02: /* Song Position Pointer. */
+ {
+ BYTE buf[3];
+ buf[0] = evt;
+ buf[1] = d1;
+ buf[2] = d2;
+ snd_seq_ev_set_sysex(&event, sizeof(buf), buf);
+ break;
+ }
+ }
+ break;
+ }
+ if (handled)
+ {
+ seq_lock();
+ snd_seq_event_output_direct(dest->seq, &event);
+ seq_unlock();
+ }
+ break;
+ }
+ default:
+ WARN("Technology not supported (yet) %d !\n", dest->caps.wTechnology);
+ return MMSYSERR_NOTENABLED;
+ }
+
+ return MMSYSERR_NOERROR;
+}
+
NTSTATUS midi_out_message(void *args)
{
struct midi_out_message_params *params = args;
@@ -545,6 +671,9 @@ NTSTATUS midi_out_message(void *args)
case MODM_CLOSE:
*params->err = midi_out_close(params->dev_id, params->notify);
break;
+ case MODM_DATA:
+ *params->err = midi_out_data(params->dev_id, params->param_1);
+ break;
default:
TRACE("Unsupported message\n");
*params->err = MMSYSERR_NOTSUPPORTED;
diff --git a/dlls/winealsa.drv/midi.c b/dlls/winealsa.drv/midi.c
index 5f8d855c9fb..dd2f3cd9040 100644
--- a/dlls/winealsa.drv/midi.c
+++ b/dlls/winealsa.drv/midi.c
@@ -630,128 +630,6 @@ static DWORD modGetDevCaps(WORD wDevID, LPMIDIOUTCAPSW lpCaps, DWORD dwSize)
return MMSYSERR_NOERROR;
}
-/**************************************************************************
- * modData [internal]
- */
-static DWORD modData(WORD wDevID, DWORD dwParam)
-{
- BYTE evt = LOBYTE(LOWORD(dwParam));
- BYTE d1 = HIBYTE(LOWORD(dwParam));
- BYTE d2 = LOBYTE(HIWORD(dwParam));
-
- TRACE("(%04X, %08X);\n", wDevID, dwParam);
-
- if (wDevID >= MODM_NumDevs) return MMSYSERR_BADDEVICEID;
- if (!MidiOutDev[wDevID].bEnabled) return MIDIERR_NODEVICE;
-
- if (MidiOutDev[wDevID].seq == NULL) {
- WARN("can't play !\n");
- return MIDIERR_NODEVICE;
- }
- switch (MidiOutDev[wDevID].caps.wTechnology) {
- case MOD_SYNTH:
- case MOD_MIDIPORT:
- {
- int handled = 1; /* Assume event is handled */
- snd_seq_event_t event;
- snd_seq_ev_clear(&event);
- snd_seq_ev_set_direct(&event);
- snd_seq_ev_set_source(&event, MidiOutDev[wDevID].port_out);
- snd_seq_ev_set_subs(&event);
-
- switch (evt & 0xF0) {
- case MIDI_CMD_NOTE_OFF:
- snd_seq_ev_set_noteoff(&event, evt&0x0F, d1, d2);
- break;
- case MIDI_CMD_NOTE_ON:
- snd_seq_ev_set_noteon(&event, evt&0x0F, d1, d2);
- break;
- case MIDI_CMD_NOTE_PRESSURE:
- snd_seq_ev_set_keypress(&event, evt&0x0F, d1, d2);
- break;
- case MIDI_CMD_CONTROL:
- snd_seq_ev_set_controller(&event, evt&0x0F, d1, d2);
- break;
- case MIDI_CMD_BENDER:
- snd_seq_ev_set_pitchbend(&event, evt&0x0F, ((WORD)d2 << 7 | (WORD)d1) - 0x2000);
- break;
- case MIDI_CMD_PGM_CHANGE:
- snd_seq_ev_set_pgmchange(&event, evt&0x0F, d1);
- break;
- case MIDI_CMD_CHANNEL_PRESSURE:
- snd_seq_ev_set_chanpress(&event, evt&0x0F, d1);
- break;
- case MIDI_CMD_COMMON_SYSEX:
- switch (evt & 0x0F) {
- case 0x00: /* System Exclusive, don't do it on modData,
- * should require modLongData*/
- case 0x04: /* Undefined. */
- case 0x05: /* Undefined. */
- case 0x07: /* End of Exclusive. */
- case 0x09: /* Undefined. */
- case 0x0D: /* Undefined. */
- handled = 0;
- break;
- case 0x06: /* Tune Request */
- case 0x08: /* Timing Clock. */
- case 0x0A: /* Start. */
- case 0x0B: /* Continue */
- case 0x0C: /* Stop */
- case 0x0E: /* Active Sensing. */
- {
- snd_midi_event_t *midi_event;
-
- snd_midi_event_new(1, &midi_event);
- snd_midi_event_init(midi_event);
- snd_midi_event_encode_byte(midi_event, evt, &event);
- snd_midi_event_free(midi_event);
- break;
- }
- case 0x0F: /* Reset */
- /* snd_seq_ev_set_sysex(&event, 1, &evt);
- this other way may be better */
- {
- BYTE reset_sysex_seq[] = {MIDI_CMD_COMMON_SYSEX, 0x7e, 0x7f, 0x09, 0x01, 0xf7};
- snd_seq_ev_set_sysex(&event, sizeof(reset_sysex_seq), reset_sysex_seq);
- }
- break;
- case 0x01: /* MTC Quarter frame */
- case 0x03: /* Song Select. */
- {
- BYTE buf[2];
- buf[0] = evt;
- buf[1] = d1;
- snd_seq_ev_set_sysex(&event, sizeof(buf), buf);
- }
- break;
- case 0x02: /* Song Position Pointer. */
- {
- BYTE buf[3];
- buf[0] = evt;
- buf[1] = d1;
- buf[2] = d2;
- snd_seq_ev_set_sysex(&event, sizeof(buf), buf);
- }
- break;
- }
- break;
- }
- if (handled) {
- seq_lock();
- snd_seq_event_output_direct(MidiOutDev[wDevID].seq, &event);
- seq_unlock();
- }
- }
- break;
- default:
- WARN("Technology not supported (yet) %d !\n",
- MidiOutDev[wDevID].caps.wTechnology);
- return MMSYSERR_NOTENABLED;
- }
-
- return MMSYSERR_NOERROR;
-}
-
/**************************************************************************
* modLongData [internal]
*/
@@ -897,6 +775,8 @@ static DWORD modGetVolume(WORD wDevID, DWORD* lpdwVolume)
*/
static DWORD modReset(WORD wDevID)
{
+ DWORD WINAPI ALSA_modMessage(UINT wDevID, UINT wMsg, DWORD_PTR dwUser,
+ DWORD_PTR dwParam1, DWORD_PTR dwParam2);
unsigned chn;
TRACE("(%04X);\n", wDevID);
@@ -909,10 +789,10 @@ static DWORD modReset(WORD wDevID)
* it's channel dependent...
*/
for (chn = 0; chn < 16; chn++) {
- /* turn off every note */
- modData(wDevID, 0x7800 | MIDI_CMD_CONTROL | chn);
- /* remove sustain on all channels */
- modData(wDevID, (MIDI_CTL_SUSTAIN << 8) | MIDI_CMD_CONTROL | chn);
+ /* turn off every note */
+ ALSA_modMessage(wDevID, MODM_DATA, 0, 0x7800 | MIDI_CMD_CONTROL | chn, 0);
+ /* remove sustain on all channels */
+ ALSA_modMessage(wDevID, MODM_DATA, 0, (MIDI_CTL_SUSTAIN << 8) | MIDI_CMD_CONTROL | chn, 0);
}
/* FIXME: the LongData buffers must also be returned to the app */
return MMSYSERR_NOERROR;
@@ -1006,8 +886,6 @@ DWORD WINAPI ALSA_modMessage(UINT wDevID, UINT wMsg, DWORD_PTR dwUser,
case DRVM_INIT:
ALSA_MidiInit();
return 0;
- case MODM_DATA:
- return modData(wDevID, dwParam1);
case MODM_LONGDATA:
return modLongData(wDevID, (LPMIDIHDR)dwParam1, dwParam2);
case MODM_PREPARE:
--
2.25.1
2
1
supersedes 227544
As described in bugzilla ticket, when calling CreateProcess:
- with "default" console inheritance (no CREATE_NEW_CONSOLE
nor DETACHED_PROCESS flags),
- when parent is not attached to a console
- and when the child's subsystem is CUI
, native behaves as if CREATE_NEW_CONSOLE was passed.
builtin doesn't...
this serie:
- adds a test case for showing the CUI/GUI discrepancies
- fixes kernelbase accordingly
- but also requires to fix all usage of CreateProcess in Wine Code
that would now generate the creation of a console
+ a couple of programs moved into the GUI subsystem (to avoid console
creation on invocation)
+ when looking to the other usage of CreateProcess, I only convinced
myself to adapt one of them
V1 => V2:
- don't mess up with the number of patches in the serie
- no longer modify makedep for creating cui vs gui test executable, but
copy current *_test.exe executable and adapt its subsystem to the need
V2 => V3:
- removed the hacks in wow64 redirect, and let programs/uninstaller and
programs/wusa belong to the GUI subsystem instead
- force console creation for wine initial process when a) none of the unix
fd are attached to a TTY, b) the initial process is in CUI subsystem
V3 => V4:
- included Jacek's comments:
+ removed unneeded casts
+ move CreateProcess change in programs/services into a separate patch
+ I didn't change programs/start as you suggested. Testing on W10 shows
that 'start /b cui.exe' from a cmd prompt just reuses the current
console.
V4 => V5:
- removed patches applied in V4
- added tweaks in start.exe not so create a console when detached
And Marvin will generate errors for Chinese and Japanese VM in console
testing that are independant of this serie.
Signed-off-by: Eric Pouech <eric.pouech(a)gmail.com>
---
Eric Pouech (4):
dlls/kernel32/tests: add some console tests about creating cui vs gui processes
programs/services: start services detached from console
programs/start: force no console creation when using start /exec
dlls/kernelbase: handle corner case in CreateProcess
dlls/kernel32/tests/console.c | 85 +++++++++++++++++++++++++++++++++++
dlls/kernelbase/process.c | 6 ++-
programs/services/services.c | 2 +-
programs/start/start.c | 7 ++-
4 files changed, 96 insertions(+), 4 deletions(-)
2
8
17 Mar '22
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
---
dlls/user32/clipboard.c | 23 ---
dlls/user32/combo.c | 2 +-
dlls/user32/dde_misc.c | 6 +-
dlls/user32/dde_server.c | 2 +-
dlls/user32/defwnd.c | 2 +-
dlls/user32/dialog.c | 4 +-
dlls/user32/driver.c | 7 +-
dlls/user32/mdi.c | 2 +-
dlls/user32/menu.c | 8 +-
dlls/user32/message.c | 2 -
dlls/user32/msgbox.c | 70 ++++----
dlls/user32/painting.c | 12 --
dlls/user32/user32.spec | 2 +-
dlls/user32/user_main.c | 10 ++
dlls/user32/win.c | 248 +--------------------------
dlls/user32/win.h | 1 -
dlls/win32u/clipboard.c | 25 +++
dlls/win32u/driver.c | 1 +
dlls/win32u/gdiobj.c | 1 +
dlls/win32u/message.c | 2 +
dlls/win32u/ntuser_private.h | 4 +
dlls/win32u/sysparams.c | 18 +-
dlls/win32u/win32u.spec | 2 +-
dlls/win32u/win32u_private.h | 6 +
dlls/win32u/window.c | 315 +++++++++++++++++++++++++++++++++++
dlls/win32u/wrappers.c | 6 +
include/ntuser.h | 4 +-
27 files changed, 440 insertions(+), 345 deletions(-)
2
1
[PATCH v2 5/5] win32u: Move GetWindowContextHelpId implementation from user32.
by Huw Davies 17 Mar '22
by Huw Davies 17 Mar '22
17 Mar '22
From: Jacek Caban <jacek(a)codeweavers.com>
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/user32/win.c | 12 +-----------
dlls/win32u/window.c | 18 ++++++++++++++++++
include/ntuser.h | 1 +
3 files changed, 20 insertions(+), 11 deletions(-)
diff --git a/dlls/user32/win.c b/dlls/user32/win.c
index 4d4199c67fc..22227c23280 100644
--- a/dlls/user32/win.c
+++ b/dlls/user32/win.c
@@ -2249,17 +2249,7 @@ BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
*/
DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
{
- DWORD retval;
- WND *wnd = WIN_GetPtr( hwnd );
- if (!wnd || wnd == WND_DESKTOP) return 0;
- if (wnd == WND_OTHER_PROCESS)
- {
- if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
- return 0;
- }
- retval = wnd->helpContext;
- WIN_ReleasePtr( wnd );
- return retval;
+ return NtUserCallHwnd( hwnd, NtUserGetWindowContextHelpId );
}
diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c
index ab69096184c..e513a13b152 100644
--- a/dlls/win32u/window.c
+++ b/dlls/win32u/window.c
@@ -3913,6 +3913,22 @@ BOOL WINAPI NtUserFlashWindowEx( FLASHWINFO *info )
}
}
+/* see GetWindowContextHelpId */
+static DWORD get_window_context_help_id( HWND hwnd )
+{
+ DWORD retval;
+ WND *win = get_win_ptr( hwnd );
+ if (!win || win == WND_DESKTOP) return 0;
+ if (win == WND_OTHER_PROCESS)
+ {
+ if (is_window( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
+ return 0;
+ }
+ retval = win->helpContext;
+ release_win_ptr( win );
+ return retval;
+}
+
/***********************************************************************
* send_destroy_message
*/
@@ -4190,6 +4206,8 @@ ULONG_PTR WINAPI NtUserCallHwnd( HWND hwnd, DWORD code )
return get_dpi_for_window( hwnd );
case NtUserGetParent:
return HandleToUlong( get_parent( hwnd ));
+ case NtUserGetWindowContextHelpId:
+ return get_window_context_help_id( hwnd );
case NtUserGetWindowDpiAwarenessContext:
return (ULONG_PTR)get_window_dpi_awareness_context( hwnd );
case NtUserGetWindowTextLength:
diff --git a/include/ntuser.h b/include/ntuser.h
index 6526d190e28..7bcb91fcc25 100644
--- a/include/ntuser.h
+++ b/include/ntuser.h
@@ -147,6 +147,7 @@ enum
{
NtUserGetDpiForWindow,
NtUserGetParent,
+ NtUserGetWindowContextHelpId,
NtUserGetWindowDpiAwarenessContext,
NtUserGetWindowTextLength,
NtUserIsWindow,
--
2.23.0
1
0
17 Mar '22
From: Jacek Caban <jacek(a)codeweavers.com>
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/user32/combo.c | 4 +-
dlls/user32/defwnd.c | 2 +-
dlls/user32/dialog.c | 6 +-
dlls/user32/driver.c | 8 +-
dlls/user32/mdi.c | 12 +-
dlls/user32/message.c | 21 +-
dlls/user32/nonclient.c | 6 +-
dlls/user32/scroll.c | 2 +-
dlls/user32/user32.spec | 4 +-
dlls/user32/user_main.c | 1 -
dlls/user32/win.c | 10 +-
dlls/user32/win.h | 6 -
dlls/user32/winpos.c | 228 +---------------
dlls/win32u/driver.c | 1 +
dlls/win32u/gdiobj.c | 2 +
dlls/win32u/input.c | 2 +-
dlls/win32u/message.c | 3 +
dlls/win32u/ntuser_private.h | 7 +-
dlls/win32u/win32u.spec | 4 +-
dlls/win32u/win32u_private.h | 4 +
dlls/win32u/window.c | 487 ++++++++++++++++++++++++++++++++++-
dlls/win32u/wrappers.c | 12 +
include/ntuser.h | 1 +
23 files changed, 542 insertions(+), 291 deletions(-)
diff --git a/dlls/user32/combo.c b/dlls/user32/combo.c
index b375de5080c..d9123057295 100644
--- a/dlls/user32/combo.c
+++ b/dlls/user32/combo.c
@@ -1030,7 +1030,7 @@ static void CBRollUp( LPHEADCOMBO lphc, BOOL ok, BOOL bButton )
RECT rect;
lphc->wState &= ~CBF_DROPPED;
- ShowWindow( lphc->hWndLBox, SW_HIDE );
+ NtUserShowWindow( lphc->hWndLBox, SW_HIDE );
if(GetCapture() == lphc->hWndLBox)
{
@@ -1419,7 +1419,7 @@ static void CBResetPos(HEADCOMBO *combo, BOOL redraw)
if (combo->wState & CBF_DROPPED)
{
combo->wState &= ~CBF_DROPPED;
- ShowWindow(combo->hWndLBox, SW_HIDE);
+ NtUserShowWindow( combo->hWndLBox, SW_HIDE );
}
if (redraw && !(combo->wState & CBF_NOREDRAW))
diff --git a/dlls/user32/defwnd.c b/dlls/user32/defwnd.c
index 271644bb953..bd1928412e0 100644
--- a/dlls/user32/defwnd.c
+++ b/dlls/user32/defwnd.c
@@ -562,7 +562,7 @@ static LRESULT DEFWND_DefWinProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPa
}
else pWnd->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
WIN_ReleasePtr( pWnd );
- ShowWindow( hwnd, wParam ? SW_SHOWNOACTIVATE : SW_HIDE );
+ NtUserShowWindow( hwnd, wParam ? SW_SHOWNOACTIVATE : SW_HIDE );
break;
}
diff --git a/dlls/user32/dialog.c b/dlls/user32/dialog.c
index f9d388d0104..a3efd5b6742 100644
--- a/dlls/user32/dialog.c
+++ b/dlls/user32/dialog.c
@@ -702,7 +702,7 @@ static HWND DIALOG_CreateIndirect( HINSTANCE hInst, LPCVOID dlgTemplate,
if (template.style & WS_VISIBLE && !(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE))
{
- ShowWindow( hwnd, SW_SHOWNORMAL ); /* SW_SHOW doesn't always work */
+ NtUserShowWindow( hwnd, SW_SHOWNORMAL ); /* SW_SHOW doesn't always work */
}
return hwnd;
}
@@ -793,7 +793,7 @@ INT DIALOG_DoDialogBox( HWND hwnd, HWND owner )
if (bFirstEmpty)
{
/* ShowWindow the first time the queue goes empty */
- ShowWindow( hwnd, SW_SHOWNORMAL );
+ NtUserShowWindow( hwnd, SW_SHOWNORMAL );
bFirstEmpty = FALSE;
}
if (!(GetWindowLongW( hwnd, GWL_STYLE ) & DS_NOIDLEMSG))
@@ -821,7 +821,7 @@ INT DIALOG_DoDialogBox( HWND hwnd, HWND owner )
if (bFirstEmpty && msg.message == WM_TIMER)
{
- ShowWindow( hwnd, SW_SHOWNORMAL );
+ NtUserShowWindow( hwnd, SW_SHOWNORMAL );
bFirstEmpty = FALSE;
}
}
diff --git a/dlls/user32/driver.c b/dlls/user32/driver.c
index ada0b8ca2f7..25ed33ff073 100644
--- a/dlls/user32/driver.c
+++ b/dlls/user32/driver.c
@@ -95,11 +95,6 @@ static void CDECL nulldrv_SetWindowText( HWND hwnd, LPCWSTR text )
{
}
-static UINT CDECL nulldrv_ShowWindow( HWND hwnd, INT cmd, RECT *rect, UINT swp )
-{
- return ~0; /* use default implementation */
-}
-
static LRESULT CDECL nulldrv_SysCommand( HWND hwnd, WPARAM wparam, LPARAM lparam )
{
return -1;
@@ -184,7 +179,7 @@ static struct user_driver_funcs lazy_load_driver =
nulldrv_SetWindowIcon,
NULL,
nulldrv_SetWindowText,
- nulldrv_ShowWindow,
+ NULL,
nulldrv_SysCommand,
NULL,
NULL,
@@ -222,7 +217,6 @@ void CDECL __wine_set_user_driver( const struct user_driver_funcs *funcs, UINT v
SET_USER_FUNC(MsgWaitForMultipleObjectsEx);
SET_USER_FUNC(SetWindowIcon);
SET_USER_FUNC(SetWindowText);
- SET_USER_FUNC(ShowWindow);
SET_USER_FUNC(SysCommand);
SET_USER_FUNC(WindowPosChanging);
SET_USER_FUNC(WindowPosChanged);
diff --git a/dlls/user32/mdi.c b/dlls/user32/mdi.c
index 3d85487f808..19db8382bd0 100644
--- a/dlls/user32/mdi.c
+++ b/dlls/user32/mdi.c
@@ -514,13 +514,13 @@ static void MDI_SwitchActiveChild( MDICLIENTINFO *ci, HWND hwndTo, BOOL activate
{
/* restore old MDI child */
SendMessageW( hwndPrev, WM_SETREDRAW, FALSE, 0 );
- ShowWindow( hwndPrev, SW_RESTORE );
+ NtUserShowWindow( hwndPrev, SW_RESTORE );
SendMessageW( hwndPrev, WM_SETREDRAW, TRUE, 0 );
/* activate new MDI child */
NtUserSetWindowPos( hwndTo, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE );
/* maximize new MDI child */
- ShowWindow( hwndTo, SW_MAXIMIZE );
+ NtUserShowWindow( hwndTo, SW_MAXIMIZE );
}
/* activate new MDI child */
NtUserSetWindowPos( hwndTo, HWND_TOP, 0, 0, 0, 0,
@@ -547,7 +547,7 @@ static LRESULT MDIDestroyChild( HWND client, MDICLIENTINFO *ci,
MDI_SwitchActiveChild(ci, next, TRUE);
else
{
- ShowWindow(child, SW_HIDE);
+ NtUserShowWindow( child, SW_HIDE );
if (child == ci->hwndChildMaximized)
{
HWND frame = GetParent(client);
@@ -1133,7 +1133,7 @@ LRESULT MDIClientWndProc_common( HWND hwnd, UINT message, WPARAM wParam, LPARAM
return 0;
case WM_MDIMAXIMIZE:
- ShowWindow( (HWND)wParam, SW_MAXIMIZE );
+ NtUserShowWindow( (HWND)wParam, SW_MAXIMIZE );
return 0;
case WM_MDINEXT: /* lParam != 0 means previous window */
@@ -1147,7 +1147,7 @@ LRESULT MDIClientWndProc_common( HWND hwnd, UINT message, WPARAM wParam, LPARAM
}
case WM_MDIRESTORE:
- ShowWindow( (HWND)wParam, SW_SHOWNORMAL );
+ NtUserShowWindow( (HWND)wParam, SW_SHOWNORMAL );
return 0;
case WM_MDISETMENU:
@@ -1518,7 +1518,7 @@ LRESULT WINAPI DefMDIChildProcW( HWND hwnd, UINT message,
SendMessageW( hMaxChild, WM_SETREDRAW, FALSE, 0 );
MDI_RestoreFrameMenu( GetParent(client), hMaxChild );
- ShowWindow( hMaxChild, SW_SHOWNOACTIVATE );
+ NtUserShowWindow( hMaxChild, SW_SHOWNOACTIVATE );
SendMessageW( hMaxChild, WM_SETREDRAW, TRUE, 0 );
}
diff --git a/dlls/user32/message.c b/dlls/user32/message.c
index 0ba540d2e5d..2badec331c1 100644
--- a/dlls/user32/message.c
+++ b/dlls/user32/message.c
@@ -1857,21 +1857,12 @@ static void reply_message( struct received_message_info *info, LRESULT result, B
*/
LRESULT handle_internal_message( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam )
{
- switch(msg)
- {
- case WM_WINE_SHOWWINDOW:
- if (is_desktop_window( hwnd )) return 0;
- return ShowWindow( hwnd, wparam );
- default:
- {
- MSG m;
- m.hwnd = hwnd;
- m.message = msg;
- m.wParam = wparam;
- m.lParam = lparam;
- return NtUserCallOneParam( (UINT_PTR)&m, NtUserHandleInternalMessage );
- }
- }
+ MSG m;
+ m.hwnd = hwnd;
+ m.message = msg;
+ m.wParam = wparam;
+ m.lParam = lparam;
+ return NtUserCallOneParam( (UINT_PTR)&m, NtUserHandleInternalMessage );
}
/* since the WM_DDE_ACK response to a WM_DDE_EXECUTE message should contain the handle
diff --git a/dlls/user32/nonclient.c b/dlls/user32/nonclient.c
index 096674db5f7..a2a49fda27b 100644
--- a/dlls/user32/nonclient.c
+++ b/dlls/user32/nonclient.c
@@ -1557,19 +1557,19 @@ LRESULT NC_HandleSysCommand( HWND hwnd, WPARAM wParam, LPARAM lParam )
case SC_MINIMIZE:
ShowOwnedPopups(hwnd,FALSE);
- ShowWindow( hwnd, SW_MINIMIZE );
+ NtUserShowWindow( hwnd, SW_MINIMIZE );
break;
case SC_MAXIMIZE:
if (IsIconic(hwnd))
ShowOwnedPopups(hwnd,TRUE);
- ShowWindow( hwnd, SW_MAXIMIZE );
+ NtUserShowWindow( hwnd, SW_MAXIMIZE );
break;
case SC_RESTORE:
if (IsIconic(hwnd))
ShowOwnedPopups(hwnd,TRUE);
- ShowWindow( hwnd, SW_RESTORE );
+ NtUserShowWindow( hwnd, SW_RESTORE );
break;
case SC_CLOSE:
diff --git a/dlls/user32/scroll.c b/dlls/user32/scroll.c
index d666707299f..c042b72a344 100644
--- a/dlls/user32/scroll.c
+++ b/dlls/user32/scroll.c
@@ -1973,7 +1973,7 @@ static BOOL SCROLL_ShowScrollBar( HWND hwnd, INT nBar, BOOL fShowH, BOOL fShowV
switch(nBar)
{
case SB_CTL:
- ShowWindow( hwnd, fShowH ? SW_SHOW : SW_HIDE );
+ NtUserShowWindow( hwnd, fShowH ? SW_SHOW : SW_HIDE );
return TRUE;
case SB_BOTH:
diff --git a/dlls/user32/user32.spec b/dlls/user32/user32.spec
index cb18d9415c9..36ec63c21d4 100644
--- a/dlls/user32/user32.spec
+++ b/dlls/user32/user32.spec
@@ -740,8 +740,8 @@
@ stdcall ShowOwnedPopups(long long)
@ stdcall ShowScrollBar(long long long)
@ stub ShowStartGlass
-@ stdcall ShowWindow(long long)
-@ stdcall ShowWindowAsync(long long)
+@ stdcall ShowWindow(long long) NtUserShowWindow
+@ stdcall ShowWindowAsync(long long) NtUserShowWindowAsync
@ stdcall ShutdownBlockReasonCreate(long wstr)
@ stdcall ShutdownBlockReasonDestroy(long)
# @ stub SoftModalMessageBox
diff --git a/dlls/user32/user_main.c b/dlls/user32/user_main.c
index 15293d76c41..5a3db40c93c 100644
--- a/dlls/user32/user_main.c
+++ b/dlls/user32/user_main.c
@@ -166,7 +166,6 @@ static const struct user_callbacks user_funcs =
SendMessageW,
SendNotifyMessageW,
ShowCaret,
- ShowWindow,
WaitForInputIdle,
free_win_ptr,
MENU_IsMenuActive,
diff --git a/dlls/user32/win.c b/dlls/user32/win.c
index b0e6b33eb56..4d4199c67fc 100644
--- a/dlls/user32/win.c
+++ b/dlls/user32/win.c
@@ -1023,10 +1023,10 @@ HWND WIN_CreateWindowEx( CREATESTRUCTW *cs, LPCWSTR className, HINSTANCE module,
{
/* if the new window is maximized don't bother repainting */
SendMessageW( top_child, WM_SETREDRAW, FALSE, 0 );
- ShowWindow( top_child, SW_SHOWNORMAL );
+ NtUserShowWindow( top_child, SW_SHOWNORMAL );
SendMessageW( top_child, WM_SETREDRAW, TRUE, 0 );
}
- else ShowWindow( top_child, SW_SHOWNORMAL );
+ else NtUserShowWindow( top_child, SW_SHOWNORMAL );
}
}
}
@@ -1303,7 +1303,7 @@ HWND WIN_CreateWindowEx( CREATESTRUCTW *cs, LPCWSTR className, HINSTANCE module,
else if (cs->style & WS_MINIMIZE)
sw = SW_SHOWMINIMIZED;
- ShowWindow( hwnd, sw );
+ NtUserShowWindow( hwnd, sw );
if (cs->dwExStyle & WS_EX_MDICHILD)
{
SendMessageW(cs->hwndParent, WM_MDIREFRESHMENU, 0, 0);
@@ -1399,7 +1399,7 @@ HWND WINAPI DECLSPEC_HOTPATCH CreateWindowExW( DWORD exStyle, LPCWSTR className,
BOOL WINAPI CloseWindow( HWND hwnd )
{
if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
- ShowWindow( hwnd, SW_MINIMIZE );
+ NtUserShowWindow( hwnd, SW_MINIMIZE );
return TRUE;
}
@@ -1410,7 +1410,7 @@ BOOL WINAPI CloseWindow( HWND hwnd )
BOOL WINAPI OpenIcon( HWND hwnd )
{
if (!IsIconic( hwnd )) return FALSE;
- ShowWindow( hwnd, SW_SHOWNORMAL );
+ NtUserShowWindow( hwnd, SW_SHOWNORMAL );
return TRUE;
}
diff --git a/dlls/user32/win.h b/dlls/user32/win.h
index 89e91a255f9..79a57de6bb9 100644
--- a/dlls/user32/win.h
+++ b/dlls/user32/win.h
@@ -42,7 +42,6 @@ extern WND *WIN_GetPtr( HWND hwnd ) DECLSPEC_HIDDEN;
extern HWND WIN_GetFullHandle( HWND hwnd ) DECLSPEC_HIDDEN;
extern HWND WIN_IsCurrentProcess( HWND hwnd ) DECLSPEC_HIDDEN;
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 HWND WIN_CreateWindowEx( CREATESTRUCTW *cs, LPCWSTR className, HINSTANCE module, BOOL unicode ) DECLSPEC_HIDDEN;
@@ -94,9 +93,4 @@ static inline void mirror_rect( const RECT *window_rect, RECT *rect )
rect->right = width - tmp;
}
-static inline UINT win_get_flags( HWND hwnd )
-{
- return win_set_flags( hwnd, 0, 0 );
-}
-
#endif /* __WINE_WIN_H */
diff --git a/dlls/user32/winpos.c b/dlls/user32/winpos.c
index 1951f887351..4ba0c47626d 100644
--- a/dlls/user32/winpos.c
+++ b/dlls/user32/winpos.c
@@ -67,7 +67,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(win);
*/
void WINAPI SwitchToThisWindow( HWND hwnd, BOOL alt_tab )
{
- if (IsIconic( hwnd )) ShowWindow( hwnd, SW_RESTORE );
+ if (IsIconic( hwnd )) NtUserShowWindow( hwnd, SW_RESTORE );
else BringWindowToTop( hwnd );
}
@@ -799,228 +799,6 @@ UINT WINPOS_MinMaximize( HWND hwnd, UINT cmd, LPRECT rect )
}
-/***********************************************************************
- * show_window
- *
- * Implementation of ShowWindow and ShowWindowAsync.
- */
-static BOOL show_window( HWND hwnd, INT cmd )
-{
- WND *wndPtr;
- HWND parent;
- DPI_AWARENESS_CONTEXT context;
- LONG style = GetWindowLongW( hwnd, GWL_STYLE );
- BOOL wasVisible = (style & WS_VISIBLE) != 0;
- BOOL showFlag = TRUE;
- RECT newPos = {0, 0, 0, 0};
- UINT new_swp, swp = 0;
-
- TRACE("hwnd=%p, cmd=%d, wasVisible %d\n", hwnd, cmd, wasVisible);
-
- context = SetThreadDpiAwarenessContext( GetWindowDpiAwarenessContext( hwnd ));
-
- switch(cmd)
- {
- case SW_HIDE:
- if (!wasVisible) goto done;
- showFlag = FALSE;
- swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE;
- if (style & WS_CHILD) swp |= SWP_NOACTIVATE | SWP_NOZORDER;
- break;
-
- case SW_SHOWMINNOACTIVE:
- case SW_MINIMIZE:
- case SW_FORCEMINIMIZE: /* FIXME: Does not work if thread is hung. */
- swp |= SWP_NOACTIVATE | SWP_NOZORDER;
- /* fall through */
- case SW_SHOWMINIMIZED:
- swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
- swp |= WINPOS_MinMaximize( hwnd, cmd, &newPos );
- if ((style & WS_MINIMIZE) && wasVisible) goto done;
- break;
-
- case SW_SHOWMAXIMIZED: /* same as SW_MAXIMIZE */
- if (!wasVisible) swp |= SWP_SHOWWINDOW;
- swp |= SWP_FRAMECHANGED;
- swp |= WINPOS_MinMaximize( hwnd, SW_MAXIMIZE, &newPos );
- if ((style & WS_MAXIMIZE) && wasVisible) goto done;
- break;
-
- case SW_SHOWNA:
- swp |= SWP_NOACTIVATE | SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
- if (style & WS_CHILD) swp |= SWP_NOZORDER;
- break;
- case SW_SHOW:
- if (wasVisible) goto done;
- swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
- if (style & WS_CHILD) swp |= SWP_NOACTIVATE | SWP_NOZORDER;
- break;
-
- case SW_SHOWNOACTIVATE:
- swp |= SWP_NOACTIVATE | SWP_NOZORDER;
- /* fall through */
- case SW_RESTORE:
- /* fall through */
- case SW_SHOWNORMAL: /* same as SW_NORMAL: */
- case SW_SHOWDEFAULT: /* FIXME: should have its own handler */
- if (!wasVisible) swp |= SWP_SHOWWINDOW;
- if (style & (WS_MINIMIZE | WS_MAXIMIZE))
- {
- swp |= SWP_FRAMECHANGED;
- swp |= WINPOS_MinMaximize( hwnd, cmd, &newPos );
- }
- else
- {
- if (wasVisible) goto done;
- swp |= SWP_NOSIZE | SWP_NOMOVE;
- }
- if (style & WS_CHILD && !(swp & SWP_STATECHANGED)) swp |= SWP_NOACTIVATE | SWP_NOZORDER;
- break;
- default:
- goto done;
- }
-
- if ((showFlag != wasVisible || cmd == SW_SHOWNA) && cmd != SW_SHOWMAXIMIZED && !(swp & SWP_STATECHANGED))
- {
- SendMessageW( hwnd, WM_SHOWWINDOW, showFlag, 0 );
- if (!IsWindow( hwnd )) goto done;
- }
-
- if (IsRectEmpty( &newPos )) new_swp = swp;
- else if ((new_swp = USER_Driver->pShowWindow( hwnd, cmd, &newPos, swp )) == ~0)
- {
- if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) new_swp = swp;
- else if (IsIconic( hwnd ) && (newPos.left != -32000 || newPos.top != -32000))
- {
- OffsetRect( &newPos, -32000 - newPos.left, -32000 - newPos.top );
- new_swp = swp & ~(SWP_NOMOVE | SWP_NOCLIENTMOVE);
- }
- else new_swp = swp;
- }
- swp = new_swp;
-
- parent = NtUserGetAncestor( hwnd, GA_PARENT );
- if (parent && !IsWindowVisible( parent ) && !(swp & SWP_STATECHANGED))
- {
- /* if parent is not visible simply toggle WS_VISIBLE and return */
- if (showFlag) WIN_SetStyle( hwnd, WS_VISIBLE, 0 );
- else WIN_SetStyle( hwnd, 0, WS_VISIBLE );
- }
- else
- NtUserSetWindowPos( hwnd, HWND_TOP, newPos.left, newPos.top,
- newPos.right - newPos.left, newPos.bottom - newPos.top, swp );
-
- if (cmd == SW_HIDE)
- {
- HWND hFocus;
-
- /* FIXME: This will cause the window to be activated irrespective
- * of whether it is owned by the same thread. Has to be done
- * asynchronously.
- */
-
- if (hwnd == GetActiveWindow())
- WINPOS_ActivateOtherWindow(hwnd);
-
- /* Revert focus to parent */
- hFocus = GetFocus();
- if (hwnd == hFocus)
- {
- HWND parent = NtUserGetAncestor(hwnd, GA_PARENT);
- if (parent == GetDesktopWindow()) parent = 0;
- NtUserSetFocus( parent );
- }
- goto done;
- }
-
- if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) goto done;
-
- if (wndPtr->flags & WIN_NEED_SIZE)
- {
- /* should happen only in CreateWindowEx() */
- int wParam = SIZE_RESTORED;
- RECT client;
- LPARAM lparam;
-
- WIN_GetRectangles( hwnd, COORDS_PARENT, NULL, &client );
- lparam = MAKELONG( client.right - client.left, client.bottom - client.top );
- wndPtr->flags &= ~WIN_NEED_SIZE;
- if (wndPtr->dwStyle & WS_MAXIMIZE) wParam = SIZE_MAXIMIZED;
- else if (wndPtr->dwStyle & WS_MINIMIZE)
- {
- wParam = SIZE_MINIMIZED;
- lparam = 0;
- }
- WIN_ReleasePtr( wndPtr );
-
- SendMessageW( hwnd, WM_SIZE, wParam, lparam );
- SendMessageW( hwnd, WM_MOVE, 0, MAKELONG( client.left, client.top ));
- }
- else WIN_ReleasePtr( wndPtr );
-
- /* if previous state was minimized Windows sets focus to the window */
- if (style & WS_MINIMIZE)
- {
- NtUserSetFocus( hwnd );
- /* Send a WM_ACTIVATE message for a top level window, even if the window is already active */
- if (NtUserGetAncestor( hwnd, GA_ROOT ) == hwnd && !(swp & SWP_NOACTIVATE))
- SendMessageW( hwnd, WM_ACTIVATE, WA_ACTIVE, 0 );
- }
-
-done:
- SetThreadDpiAwarenessContext( context );
- return wasVisible;
-}
-
-
-/***********************************************************************
- * ShowWindowAsync (USER32.@)
- *
- * doesn't wait; returns immediately.
- * used by threads to toggle windows in other (possibly hanging) threads
- */
-BOOL WINAPI ShowWindowAsync( HWND hwnd, INT cmd )
-{
- HWND full_handle;
-
- if (is_broadcast(hwnd))
- {
- SetLastError( ERROR_INVALID_PARAMETER );
- return FALSE;
- }
-
- if ((full_handle = WIN_IsCurrentThread( hwnd )))
- return show_window( full_handle, cmd );
-
- return SendNotifyMessageW( hwnd, WM_WINE_SHOWWINDOW, cmd, 0 );
-}
-
-
-/***********************************************************************
- * ShowWindow (USER32.@)
- */
-BOOL WINAPI ShowWindow( HWND hwnd, INT cmd )
-{
- HWND full_handle;
-
- if (is_broadcast(hwnd))
- {
- SetLastError( ERROR_INVALID_PARAMETER );
- return FALSE;
- }
- if ((full_handle = WIN_IsCurrentThread( hwnd )))
- return show_window( full_handle, cmd );
-
- if ((cmd == SW_HIDE) && !(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE))
- return FALSE;
-
- if ((cmd == SW_SHOW) && (GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE))
- return TRUE;
-
- return SendMessageW( hwnd, WM_WINE_SHOWWINDOW, cmd, 0 );
-}
-
-
/***********************************************************************
* GetInternalWindowPos (USER32.@)
*/
@@ -1190,7 +968,7 @@ static BOOL WINPOS_SetPlacement( HWND hwnd, const WINDOWPLACEMENT *wndpl, UINT f
wp.rcNormalPosition.bottom - wp.rcNormalPosition.top,
SWP_NOZORDER | SWP_NOACTIVATE );
- ShowWindow( hwnd, wndpl->showCmd );
+ NtUserShowWindow( hwnd, wndpl->showCmd );
if (IsIconic( hwnd ))
{
@@ -1237,7 +1015,7 @@ BOOL WINAPI AnimateWindow(HWND hwnd, DWORD dwTime, DWORD dwFlags)
return FALSE;
}
- ShowWindow(hwnd, (dwFlags & AW_HIDE) ? SW_HIDE : ((dwFlags & AW_ACTIVATE) ? SW_SHOW : SW_SHOWNA));
+ NtUserShowWindow( hwnd, (dwFlags & AW_HIDE) ? SW_HIDE : ((dwFlags & AW_ACTIVATE) ? SW_SHOW : SW_SHOWNA) );
return TRUE;
}
diff --git a/dlls/win32u/driver.c b/dlls/win32u/driver.c
index 166c2009dbc..ec8162b0284 100644
--- a/dlls/win32u/driver.c
+++ b/dlls/win32u/driver.c
@@ -1202,6 +1202,7 @@ static const struct user_driver_funcs lazy_load_driver =
.pReleaseDC = nulldrv_ReleaseDC,
.pScrollDC = nulldrv_ScrollDC,
.pSetFocus = nulldrv_SetFocus,
+ .pShowWindow = nulldrv_ShowWindow,
.pUpdateLayeredWindow = loaderdrv_UpdateLayeredWindow,
.pWindowMessage = nulldrv_WindowMessage,
/* system parameters */
diff --git a/dlls/win32u/gdiobj.c b/dlls/win32u/gdiobj.c
index 69607f0e3de..e47271e6108 100644
--- a/dlls/win32u/gdiobj.c
+++ b/dlls/win32u/gdiobj.c
@@ -1210,6 +1210,8 @@ static struct unix_funcs unix_funcs =
NtUserSetWindowRgn,
NtUserSetWindowWord,
NtUserShowCursor,
+ NtUserShowWindow,
+ NtUserShowWindowAsync,
NtUserSystemParametersInfo,
NtUserSystemParametersInfoForDpi,
NtUserToUnicodeEx,
diff --git a/dlls/win32u/input.c b/dlls/win32u/input.c
index bc82d5e17a3..5cd2cdd0970 100644
--- a/dlls/win32u/input.c
+++ b/dlls/win32u/input.c
@@ -1162,7 +1162,7 @@ HWND get_active_window(void)
}
/* see GetFocus */
-static HWND get_focus(void)
+HWND get_focus(void)
{
GUITHREADINFO info;
info.cbSize = sizeof(info);
diff --git a/dlls/win32u/message.c b/dlls/win32u/message.c
index 690de6cdf8a..853182b6e94 100644
--- a/dlls/win32u/message.c
+++ b/dlls/win32u/message.c
@@ -46,6 +46,9 @@ LRESULT handle_internal_message( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpar
case WM_WINE_SETWINDOWPOS:
if (is_desktop_window( hwnd )) return 0;
return set_window_pos( (WINDOWPOS *)lparam, 0, 0 );
+ case WM_WINE_SHOWWINDOW:
+ if (is_desktop_window( hwnd )) return 0;
+ return NtUserShowWindow( hwnd, wparam );
case WM_WINE_SETPARENT:
if (is_desktop_window( hwnd )) return 0;
return HandleToUlong( NtUserSetParent( hwnd, UlongToHandle(wparam) ));
diff --git a/dlls/win32u/ntuser_private.h b/dlls/win32u/ntuser_private.h
index 51f17f63de5..49fd22ca140 100644
--- a/dlls/win32u/ntuser_private.h
+++ b/dlls/win32u/ntuser_private.h
@@ -42,7 +42,6 @@ struct user_callbacks
LRESULT (WINAPI *pSendMessageW)( HWND, UINT, WPARAM, LPARAM );
BOOL (WINAPI *pSendNotifyMessageW)( HWND, UINT, WPARAM, LPARAM );
BOOL (WINAPI *pShowCaret)( HWND hwnd );
- BOOL (WINAPI *pShowWindow)( HWND, INT );
DWORD (WINAPI *pWaitForInputIdle)( HANDLE, DWORD );
void (CDECL *free_win_ptr)( struct tagWND *win );
HWND (CDECL *is_menu_active)(void);
@@ -278,6 +277,12 @@ HANDLE alloc_user_handle( struct user_object *ptr, unsigned int type ) DECLSPEC_
void *free_user_handle( HANDLE handle, unsigned int type ) DECLSPEC_HIDDEN;
void *get_user_handle_ptr( HANDLE handle, unsigned int type ) DECLSPEC_HIDDEN;
void release_user_handle_ptr( void *ptr ) DECLSPEC_HIDDEN;
+UINT win_set_flags( HWND hwnd, UINT set_mask, UINT clear_mask ) DECLSPEC_HIDDEN;
+
+static inline UINT win_get_flags( HWND hwnd )
+{
+ return win_set_flags( hwnd, 0, 0 );
+}
WND *get_win_ptr( HWND hwnd ) DECLSPEC_HIDDEN;
BOOL is_child( HWND parent, HWND child );
diff --git a/dlls/win32u/win32u.spec b/dlls/win32u/win32u.spec
index aacfebd1b15..68348db4033 100644
--- a/dlls/win32u/win32u.spec
+++ b/dlls/win32u/win32u.spec
@@ -1261,8 +1261,8 @@
@ stdcall NtUserShowCursor(long)
@ stub NtUserShowScrollBar
@ stub NtUserShowSystemCursor
-@ stub NtUserShowWindow
-@ stub NtUserShowWindowAsync
+@ stdcall NtUserShowWindow(long long)
+@ stdcall NtUserShowWindowAsync(long long)
@ stub NtUserShutdownBlockReasonCreate
@ stub NtUserShutdownBlockReasonQuery
@ stub NtUserShutdownReasonDestroy
diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h
index 2e8a8e3da8e..361bec31ec8 100644
--- a/dlls/win32u/win32u_private.h
+++ b/dlls/win32u/win32u_private.h
@@ -258,6 +258,8 @@ struct unix_funcs
int (WINAPI *pNtUserSetWindowRgn)( HWND hwnd, HRGN hrgn, BOOL redraw );
WORD (WINAPI *pNtUserSetWindowWord)( HWND hwnd, INT offset, WORD newval );
INT (WINAPI *pNtUserShowCursor)( BOOL show );
+ BOOL (WINAPI *pNtUserShowWindow)( HWND hwnd, INT cmd );
+ BOOL (WINAPI *pNtUserShowWindowAsync)( HWND hwnd, INT cmd );
BOOL (WINAPI *pNtUserSystemParametersInfo)( UINT action, UINT val, PVOID ptr, UINT winini );
BOOL (WINAPI *pNtUserSystemParametersInfoForDpi)( UINT action, UINT val, PVOID ptr,
UINT winini, UINT dpi );
@@ -311,6 +313,7 @@ extern BOOL unhook_windows_hook( INT id, HOOKPROC proc ) DECLSPEC_HIDDEN;
extern LONG global_key_state_counter DECLSPEC_HIDDEN;
extern HWND get_active_window(void) DECLSPEC_HIDDEN;
extern BOOL get_cursor_pos( POINT *pt ) DECLSPEC_HIDDEN;
+extern HWND get_focus(void) DECLSPEC_HIDDEN;
extern DWORD get_input_state(void) DECLSPEC_HIDDEN;
extern BOOL WINAPI release_capture(void) DECLSPEC_HIDDEN;
extern BOOL set_capture_window( HWND hwnd, UINT gui_flags, HWND *prev_ret ) DECLSPEC_HIDDEN;
@@ -353,6 +356,7 @@ 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 BOOL get_client_rect( HWND hwnd, RECT *rect ) 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 1069ace0794..ab69096184c 100644
--- a/dlls/win32u/window.c
+++ b/dlls/win32u/window.c
@@ -916,6 +916,11 @@ BOOL is_iconic( HWND hwnd )
return (get_window_long( hwnd, GWL_STYLE ) & WS_MINIMIZE) != 0;
}
+static BOOL is_zoomed( HWND hwnd )
+{
+ return (get_window_long( hwnd, GWL_STYLE ) & WS_MAXIMIZE) != 0;
+}
+
static LONG_PTR get_window_long_size( HWND hwnd, INT offset, UINT size, BOOL ansi )
{
LONG_PTR retval = 0;
@@ -1655,7 +1660,7 @@ BOOL get_window_rect( HWND hwnd, RECT *rect, UINT dpi )
}
/* see GetClientRect */
-static BOOL get_client_rect( HWND hwnd, RECT *rect )
+BOOL get_client_rect( HWND hwnd, RECT *rect )
{
return get_window_rects( hwnd, COORDS_CLIENT, NULL, rect, get_thread_dpi() );
}
@@ -2174,14 +2179,6 @@ BOOL get_window_placement( HWND hwnd, WINDOWPLACEMENT *placement )
return TRUE;
}
-/*****************************************************************************
- * NtUserShowWindow (win32u.@)
- */
-BOOL WINAPI NtUserShowWindow( HWND hwnd, INT cmd )
-{
- return user_callbacks && user_callbacks->pShowWindow( hwnd, cmd );
-}
-
/*****************************************************************************
* NtUserBuildHwndList (win32u.@)
*/
@@ -3179,7 +3176,7 @@ BOOL WINAPI NtUserEndDeferWindowPosEx( HDWP hdwp, BOOL async )
*
* Set the flags of a window and return the previous value.
*/
-static UINT win_set_flags( HWND hwnd, UINT set_mask, UINT clear_mask )
+UINT win_set_flags( HWND hwnd, UINT set_mask, UINT clear_mask )
{
WND *win = get_win_ptr( hwnd );
UINT ret;
@@ -3361,6 +3358,255 @@ static MINMAXINFO get_min_max_info( HWND hwnd )
return minmax;
}
+static POINT get_first_minimized_child_pos( const RECT *parent, const MINIMIZEDMETRICS *mm,
+ int width, int height )
+{
+ POINT ret;
+
+ if (mm->iArrange & ARW_STARTRIGHT)
+ ret.x = parent->right - mm->iHorzGap - width;
+ else
+ ret.x = parent->left + mm->iHorzGap;
+ if (mm->iArrange & ARW_STARTTOP)
+ ret.y = parent->top + mm->iVertGap;
+ else
+ ret.y = parent->bottom - mm->iVertGap - height;
+
+ return ret;
+}
+
+static void get_next_minimized_child_pos( const RECT *parent, const MINIMIZEDMETRICS *mm,
+ int width, int height, POINT *pos )
+{
+ BOOL next;
+
+ if (mm->iArrange & ARW_UP) /* == ARW_DOWN */
+ {
+ if (mm->iArrange & ARW_STARTTOP)
+ {
+ pos->y += height + mm->iVertGap;
+ if ((next = pos->y + height > parent->bottom))
+ pos->y = parent->top + mm->iVertGap;
+ }
+ else
+ {
+ pos->y -= height + mm->iVertGap;
+ if ((next = pos->y < parent->top))
+ pos->y = parent->bottom - mm->iVertGap - height;
+ }
+
+ if (next)
+ {
+ if (mm->iArrange & ARW_STARTRIGHT)
+ pos->x -= width + mm->iHorzGap;
+ else
+ pos->x += width + mm->iHorzGap;
+ }
+ }
+ else
+ {
+ if (mm->iArrange & ARW_STARTRIGHT)
+ {
+ pos->x -= width + mm->iHorzGap;
+ if ((next = pos->x < parent->left))
+ pos->x = parent->right - mm->iHorzGap - width;
+ }
+ else
+ {
+ pos->x += width + mm->iHorzGap;
+ if ((next = pos->x + width > parent->right))
+ pos->x = parent->left + mm->iHorzGap;
+ }
+
+ if (next)
+ {
+ if (mm->iArrange & ARW_STARTTOP)
+ pos->y += height + mm->iVertGap;
+ else
+ pos->y -= height + mm->iVertGap;
+ }
+ }
+}
+
+static POINT get_minimized_pos( HWND hwnd, POINT pt )
+{
+ RECT rect, parent_rect;
+ HWND parent, child;
+ HRGN hrgn, tmp;
+ MINIMIZEDMETRICS metrics;
+ int width, height;
+
+ parent = NtUserGetAncestor( hwnd, GA_PARENT );
+ if (parent == get_desktop_window())
+ {
+ MONITORINFO mon_info;
+ HMONITOR monitor = monitor_from_window( hwnd, MONITOR_DEFAULTTOPRIMARY, get_thread_dpi() );
+
+ mon_info.cbSize = sizeof( mon_info );
+ get_monitor_info( monitor, &mon_info );
+ parent_rect = mon_info.rcWork;
+ }
+ else get_client_rect( parent, &parent_rect );
+
+ if (pt.x >= parent_rect.left && (pt.x + get_system_metrics( SM_CXMINIMIZED ) < parent_rect.right) &&
+ pt.y >= parent_rect.top && (pt.y + get_system_metrics( SM_CYMINIMIZED ) < parent_rect.bottom))
+ return pt; /* The icon already has a suitable position */
+
+ width = get_system_metrics( SM_CXMINIMIZED );
+ height = get_system_metrics( SM_CYMINIMIZED );
+
+ metrics.cbSize = sizeof(metrics);
+ NtUserSystemParametersInfo( SPI_GETMINIMIZEDMETRICS, sizeof(metrics), &metrics, 0 );
+
+ /* Check if another icon already occupies this spot */
+ /* FIXME: this is completely inefficient */
+
+ hrgn = NtGdiCreateRectRgn( 0, 0, 0, 0 );
+ tmp = NtGdiCreateRectRgn( 0, 0, 0, 0 );
+ for (child = get_window_relative( parent, GW_CHILD );
+ child;
+ child = get_window_relative( child, GW_HWNDNEXT ))
+ {
+ if (child == hwnd) continue;
+ if ((get_window_long( child, GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != (WS_VISIBLE|WS_MINIMIZE))
+ continue;
+ if (get_window_rects( child, COORDS_PARENT, &rect, NULL, get_thread_dpi() ))
+ {
+ NtGdiSetRectRgn( tmp, rect.left, rect.top, rect.right, rect.bottom );
+ NtGdiCombineRgn( hrgn, hrgn, tmp, RGN_OR );
+ }
+ }
+ NtGdiDeleteObjectApp( tmp );
+
+ pt = get_first_minimized_child_pos( &parent_rect, &metrics, width, height );
+ for (;;)
+ {
+ set_rect( &rect, pt.x, pt.y, pt.x + width, pt.y + height );
+ if (!NtGdiRectInRegion( hrgn, &rect ))
+ break;
+
+ get_next_minimized_child_pos( &parent_rect, &metrics, width, height, &pt );
+ }
+
+ NtGdiDeleteObjectApp( hrgn );
+ return pt;
+}
+
+/***********************************************************************
+ * window_min_maximize
+ */
+static UINT window_min_maximize( HWND hwnd, UINT cmd, RECT *rect )
+{
+ UINT swp_flags = 0;
+ LONG old_style;
+ MINMAXINFO minmax;
+ WINDOWPLACEMENT wpl;
+
+ TRACE( "%p %u\n", hwnd, cmd );
+
+ wpl.length = sizeof(wpl);
+ get_window_placement( hwnd, &wpl );
+
+ if (call_hooks( WH_CBT, HCBT_MINMAX, (WPARAM)hwnd, cmd, TRUE ))
+ return SWP_NOSIZE | SWP_NOMOVE;
+
+ if (is_iconic( hwnd ))
+ {
+ switch (cmd)
+ {
+ case SW_SHOWMINNOACTIVE:
+ case SW_SHOWMINIMIZED:
+ case SW_FORCEMINIMIZE:
+ case SW_MINIMIZE:
+ wpl.ptMinPosition = get_minimized_pos( hwnd, wpl.ptMinPosition );
+
+ set_rect( rect, wpl.ptMinPosition.x, wpl.ptMinPosition.y,
+ wpl.ptMinPosition.x + get_system_metrics( SM_CXMINIMIZED ),
+ wpl.ptMinPosition.y + get_system_metrics( SM_CYMINIMIZED ));
+ return SWP_NOSIZE | SWP_NOMOVE;
+ }
+ if (!send_message( hwnd, WM_QUERYOPEN, 0, 0 )) return SWP_NOSIZE | SWP_NOMOVE;
+ swp_flags |= SWP_NOCOPYBITS;
+ }
+
+ switch( cmd )
+ {
+ case SW_SHOWMINNOACTIVE:
+ case SW_SHOWMINIMIZED:
+ case SW_FORCEMINIMIZE:
+ case SW_MINIMIZE:
+ if (is_zoomed( hwnd )) win_set_flags( hwnd, WIN_RESTORE_MAX, 0 );
+ else win_set_flags( hwnd, 0, WIN_RESTORE_MAX );
+
+ if (get_focus() == hwnd)
+ {
+ if (get_window_long( hwnd, GWL_STYLE ) & WS_CHILD)
+ NtUserSetFocus( NtUserGetAncestor( hwnd, GA_PARENT ));
+ else
+ NtUserSetFocus( 0 );
+ }
+
+ old_style = set_window_style( hwnd, WS_MINIMIZE, WS_MAXIMIZE );
+
+ wpl.ptMinPosition = get_minimized_pos( hwnd, wpl.ptMinPosition );
+
+ if (!(old_style & WS_MINIMIZE)) swp_flags |= SWP_STATECHANGED;
+ set_rect( rect, wpl.ptMinPosition.x, wpl.ptMinPosition.y,
+ wpl.ptMinPosition.x + get_system_metrics(SM_CXMINIMIZED),
+ wpl.ptMinPosition.y + get_system_metrics(SM_CYMINIMIZED) );
+ swp_flags |= SWP_NOCOPYBITS;
+ break;
+
+ case SW_MAXIMIZE:
+ old_style = get_window_long( hwnd, GWL_STYLE );
+ if ((old_style & WS_MAXIMIZE) && (old_style & WS_VISIBLE)) return SWP_NOSIZE | SWP_NOMOVE;
+
+ minmax = get_min_max_info( hwnd );
+
+ old_style = set_window_style( hwnd, WS_MAXIMIZE, WS_MINIMIZE );
+ if (old_style & WS_MINIMIZE)
+ win_set_flags( hwnd, WIN_RESTORE_MAX, 0 );
+
+ if (!(old_style & WS_MAXIMIZE)) swp_flags |= SWP_STATECHANGED;
+ set_rect( rect, minmax.ptMaxPosition.x, minmax.ptMaxPosition.y,
+ minmax.ptMaxPosition.x + minmax.ptMaxSize.x,
+ minmax.ptMaxPosition.y + minmax.ptMaxSize.y );
+ break;
+
+ case SW_SHOWNOACTIVATE:
+ win_set_flags( hwnd, 0, WIN_RESTORE_MAX );
+ /* fall through */
+ case SW_SHOWNORMAL:
+ case SW_RESTORE:
+ case SW_SHOWDEFAULT: /* FIXME: should have its own handler */
+ old_style = set_window_style( hwnd, 0, WS_MINIMIZE | WS_MAXIMIZE );
+ if (old_style & WS_MINIMIZE)
+ {
+ if (win_get_flags( hwnd ) & WIN_RESTORE_MAX)
+ {
+ /* Restore to maximized position */
+ minmax = get_min_max_info( hwnd );
+ set_window_style( hwnd, WS_MAXIMIZE, 0 );
+ swp_flags |= SWP_STATECHANGED;
+ set_rect( rect, minmax.ptMaxPosition.x, minmax.ptMaxPosition.y,
+ minmax.ptMaxPosition.x + minmax.ptMaxSize.x,
+ minmax.ptMaxPosition.y + minmax.ptMaxSize.y );
+ break;
+ }
+ }
+ else if (!(old_style & WS_MAXIMIZE)) break;
+
+ swp_flags |= SWP_STATECHANGED;
+
+ /* Restore to normal position */
+
+ *rect = wpl.rcNormalPosition;
+ break;
+ }
+
+ return swp_flags;
+}
+
/*******************************************************************
* update_window_state
*
@@ -3387,6 +3633,227 @@ void update_window_state( HWND hwnd )
set_thread_dpi_awareness_context( context );
}
+/***********************************************************************
+ * show_window
+ *
+ * Implementation of ShowWindow and ShowWindowAsync.
+ */
+static BOOL show_window( HWND hwnd, INT cmd )
+{
+ WND *win;
+ HWND parent;
+ DPI_AWARENESS_CONTEXT context;
+ LONG style = get_window_long( hwnd, GWL_STYLE );
+ BOOL was_visible = (style & WS_VISIBLE) != 0;
+ BOOL show_flag = TRUE;
+ RECT newPos = {0, 0, 0, 0};
+ UINT new_swp, swp = 0;
+
+ TRACE( "hwnd=%p, cmd=%d, was_visible %d\n", hwnd, cmd, was_visible );
+
+ context = set_thread_dpi_awareness_context( get_window_dpi_awareness_context( hwnd ));
+
+ switch(cmd)
+ {
+ case SW_HIDE:
+ if (!was_visible) goto done;
+ show_flag = FALSE;
+ swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE;
+ if (style & WS_CHILD) swp |= SWP_NOACTIVATE | SWP_NOZORDER;
+ break;
+
+ case SW_SHOWMINNOACTIVE:
+ case SW_MINIMIZE:
+ case SW_FORCEMINIMIZE: /* FIXME: Does not work if thread is hung. */
+ swp |= SWP_NOACTIVATE | SWP_NOZORDER;
+ /* fall through */
+ case SW_SHOWMINIMIZED:
+ swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
+ swp |= window_min_maximize( hwnd, cmd, &newPos );
+ if ((style & WS_MINIMIZE) && was_visible) goto done;
+ break;
+
+ case SW_SHOWMAXIMIZED: /* same as SW_MAXIMIZE */
+ if (!was_visible) swp |= SWP_SHOWWINDOW;
+ swp |= SWP_FRAMECHANGED;
+ swp |= window_min_maximize( hwnd, SW_MAXIMIZE, &newPos );
+ if ((style & WS_MAXIMIZE) && was_visible) goto done;
+ break;
+
+ case SW_SHOWNA:
+ swp |= SWP_NOACTIVATE | SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
+ if (style & WS_CHILD) swp |= SWP_NOZORDER;
+ break;
+
+ case SW_SHOW:
+ if (was_visible) goto done;
+ swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
+ if (style & WS_CHILD) swp |= SWP_NOACTIVATE | SWP_NOZORDER;
+ break;
+
+ case SW_SHOWNOACTIVATE:
+ swp |= SWP_NOACTIVATE | SWP_NOZORDER;
+ /* fall through */
+ case SW_RESTORE:
+ /* fall through */
+ case SW_SHOWNORMAL: /* same as SW_NORMAL: */
+ case SW_SHOWDEFAULT: /* FIXME: should have its own handler */
+ if (!was_visible) swp |= SWP_SHOWWINDOW;
+ if (style & (WS_MINIMIZE | WS_MAXIMIZE))
+ {
+ swp |= SWP_FRAMECHANGED;
+ swp |= window_min_maximize( hwnd, cmd, &newPos );
+ }
+ else
+ {
+ if (was_visible) goto done;
+ swp |= SWP_NOSIZE | SWP_NOMOVE;
+ }
+ if (style & WS_CHILD && !(swp & SWP_STATECHANGED)) swp |= SWP_NOACTIVATE | SWP_NOZORDER;
+ break;
+
+ default:
+ goto done;
+ }
+
+ if ((show_flag != was_visible || cmd == SW_SHOWNA) && cmd != SW_SHOWMAXIMIZED && !(swp & SWP_STATECHANGED))
+ {
+ send_message( hwnd, WM_SHOWWINDOW, show_flag, 0 );
+ if (!is_window( hwnd )) goto done;
+ }
+
+ if (IsRectEmpty( &newPos )) new_swp = swp;
+ else if ((new_swp = user_driver->pShowWindow( hwnd, cmd, &newPos, swp )) == ~0)
+ {
+ if (get_window_long( hwnd, GWL_STYLE ) & WS_CHILD) new_swp = swp;
+ else if (is_iconic( hwnd ) && (newPos.left != -32000 || newPos.top != -32000))
+ {
+ offset_rect( &newPos, -32000 - newPos.left, -32000 - newPos.top );
+ new_swp = swp & ~(SWP_NOMOVE | SWP_NOCLIENTMOVE);
+ }
+ else new_swp = swp;
+ }
+ swp = new_swp;
+
+ parent = NtUserGetAncestor( hwnd, GA_PARENT );
+ if (parent && !is_window_visible( parent ) && !(swp & SWP_STATECHANGED))
+ {
+ /* if parent is not visible simply toggle WS_VISIBLE and return */
+ if (show_flag) set_window_style( hwnd, WS_VISIBLE, 0 );
+ else set_window_style( hwnd, 0, WS_VISIBLE );
+ }
+ else
+ NtUserSetWindowPos( hwnd, HWND_TOP, newPos.left, newPos.top,
+ newPos.right - newPos.left, newPos.bottom - newPos.top, swp );
+
+ if (cmd == SW_HIDE)
+ {
+ HWND hFocus;
+
+ /* FIXME: This will cause the window to be activated irrespective
+ * of whether it is owned by the same thread. Has to be done
+ * asynchronously.
+ */
+
+ if (hwnd == get_active_window()) activate_other_window( hwnd );
+
+ /* Revert focus to parent */
+ hFocus = get_focus();
+ if (hwnd == hFocus)
+ {
+ HWND parent = NtUserGetAncestor(hwnd, GA_PARENT);
+ if (parent == get_desktop_window()) parent = 0;
+ NtUserSetFocus(parent);
+ }
+ goto done;
+ }
+
+ if (!(win = get_win_ptr( hwnd )) || win == WND_OTHER_PROCESS) goto done;
+
+ if (win->flags & WIN_NEED_SIZE)
+ {
+ /* should happen only in CreateWindowEx() */
+ int wParam = SIZE_RESTORED;
+ RECT client;
+ LPARAM lparam;
+
+ get_window_rects( hwnd, COORDS_PARENT, NULL, &client, get_thread_dpi() );
+ lparam = MAKELONG( client.right - client.left, client.bottom - client.top );
+ win->flags &= ~WIN_NEED_SIZE;
+ if (win->dwStyle & WS_MAXIMIZE) wParam = SIZE_MAXIMIZED;
+ else if (win->dwStyle & WS_MINIMIZE)
+ {
+ wParam = SIZE_MINIMIZED;
+ lparam = 0;
+ }
+ release_win_ptr( win );
+
+ send_message( hwnd, WM_SIZE, wParam, lparam );
+ send_message( hwnd, WM_MOVE, 0, MAKELONG( client.left, client.top ));
+ }
+ else release_win_ptr( win );
+
+ /* if previous state was minimized Windows sets focus to the window */
+ if (style & WS_MINIMIZE)
+ {
+ NtUserSetFocus( hwnd );
+ /* Send a WM_ACTIVATE message for a top level window, even if the window is already active */
+ if (NtUserGetAncestor( hwnd, GA_ROOT ) == hwnd && !(swp & SWP_NOACTIVATE))
+ send_message( hwnd, WM_ACTIVATE, WA_ACTIVE, 0 );
+ }
+
+done:
+ set_thread_dpi_awareness_context( context );
+ return was_visible;
+}
+
+/***********************************************************************
+ * NtUserShowWindowAsync (win32u.@)
+ *
+ * doesn't wait; returns immediately.
+ * used by threads to toggle windows in other (possibly hanging) threads
+ */
+BOOL WINAPI NtUserShowWindowAsync( HWND hwnd, INT cmd )
+{
+ HWND full_handle;
+
+ if (is_broadcast(hwnd))
+ {
+ SetLastError( ERROR_INVALID_PARAMETER );
+ return FALSE;
+ }
+
+ if ((full_handle = is_current_thread_window( hwnd )))
+ return show_window( full_handle, cmd );
+
+ return NtUserMessageCall( hwnd, WM_WINE_SHOWWINDOW, cmd, 0, 0,
+ FNID_SENDNOTIFYMESSAGE, FALSE );
+}
+
+/***********************************************************************
+ * NtUserShowWindow (win32u.@)
+ */
+BOOL WINAPI NtUserShowWindow( HWND hwnd, INT cmd )
+{
+ HWND full_handle;
+
+ if (is_broadcast(hwnd))
+ {
+ SetLastError( ERROR_INVALID_PARAMETER );
+ return FALSE;
+ }
+ if ((full_handle = is_current_thread_window( hwnd )))
+ return show_window( full_handle, cmd );
+
+ if ((cmd == SW_HIDE) && !(get_window_long( hwnd, GWL_STYLE ) & WS_VISIBLE))
+ return FALSE;
+
+ if ((cmd == SW_SHOW) && (get_window_long( hwnd, GWL_STYLE ) & WS_VISIBLE))
+ return TRUE;
+
+ return send_message( hwnd, WM_WINE_SHOWWINDOW, cmd, 0 );
+}
+
/*******************************************************************
* NtUserFlashWindowEx (win32u.@)
*/
diff --git a/dlls/win32u/wrappers.c b/dlls/win32u/wrappers.c
index da1957c8c88..6cb3a6896b5 100644
--- a/dlls/win32u/wrappers.c
+++ b/dlls/win32u/wrappers.c
@@ -1075,6 +1075,18 @@ INT WINAPI NtUserShowCursor( BOOL show )
return unix_funcs->pNtUserShowCursor( show );
}
+BOOL WINAPI NtUserShowWindowAsync( HWND hwnd, INT cmd )
+{
+ if (!unix_funcs) return FALSE;
+ return unix_funcs->pNtUserShowWindowAsync( hwnd, cmd );
+}
+
+BOOL WINAPI NtUserShowWindow( HWND hwnd, INT cmd )
+{
+ if (!unix_funcs) return FALSE;
+ return unix_funcs->pNtUserShowWindow( hwnd, cmd );
+}
+
BOOL WINAPI NtUserSystemParametersInfo( UINT action, UINT val, PVOID ptr, UINT winini )
{
if (!unix_funcs) return FALSE;
diff --git a/include/ntuser.h b/include/ntuser.h
index 274c0cf31c9..6526d190e28 100644
--- a/include/ntuser.h
+++ b/include/ntuser.h
@@ -422,6 +422,7 @@ HWINEVENTHOOK WINAPI NtUserSetWinEventHook( DWORD event_min, DWORD event_max, HM
DWORD pid, DWORD tid, DWORD flags );
INT WINAPI NtUserShowCursor( BOOL show );
BOOL WINAPI NtUserShowWindow( HWND hwnd, INT cmd );
+BOOL WINAPI NtUserShowWindowAsync( HWND hwnd, INT cmd );
BOOL WINAPI NtUserSystemParametersInfo( UINT action, UINT val, void *ptr, UINT winini );
BOOL WINAPI NtUserSystemParametersInfoForDpi( UINT action, UINT val, PVOID ptr, UINT winini, UINT dpi );
INT WINAPI NtUserToUnicodeEx( UINT virt, UINT scan, const BYTE *state,
--
2.23.0
1
0
17 Mar '22
From: Jacek Caban <jacek(a)codeweavers.com>
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/user32/user_main.c | 1 +
dlls/user32/winpos.c | 92 ++--------------------------------
dlls/win32u/menu.c | 6 +++
dlls/win32u/ntuser_private.h | 1 +
dlls/win32u/win32u_private.h | 3 ++
dlls/win32u/window.c | 97 ++++++++++++++++++++++++++++++++++++
include/ntuser.h | 1 +
7 files changed, 113 insertions(+), 88 deletions(-)
diff --git a/dlls/user32/user_main.c b/dlls/user32/user_main.c
index bc0dec6b579..15293d76c41 100644
--- a/dlls/user32/user_main.c
+++ b/dlls/user32/user_main.c
@@ -154,6 +154,7 @@ static void CDECL free_win_ptr( WND *win )
static const struct user_callbacks user_funcs =
{
+ AdjustWindowRectEx,
CopyImage,
DestroyCaret,
DestroyMenu,
diff --git a/dlls/user32/winpos.c b/dlls/user32/winpos.c
index b3e8aff3cfa..1951f887351 100644
--- a/dlls/user32/winpos.c
+++ b/dlls/user32/winpos.c
@@ -48,8 +48,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(win);
(((style) & WS_THICKFRAME) && \
!(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
-#define EMPTYPOINT(pt) ((pt).x == -1 && (pt).y == -1)
-
#define ON_LEFT_BORDER(hit) \
(((hit) == HTLEFT) || ((hit) == HTTOPLEFT) || ((hit) == HTBOTTOMLEFT))
#define ON_RIGHT_BORDER(hit) \
@@ -548,94 +546,12 @@ static BOOL get_work_rect( HWND hwnd, RECT *rect )
*/
MINMAXINFO WINPOS_GetMinMaxInfo( HWND hwnd )
{
- DPI_AWARENESS_CONTEXT context;
- RECT rc_work, rc_primary;
- MINMAXINFO MinMax;
- INT xinc, yinc;
- LONG style = GetWindowLongW( hwnd, GWL_STYLE );
- LONG adjustedStyle;
- LONG exstyle = GetWindowLongW( hwnd, GWL_EXSTYLE );
- RECT rc;
- WND *win;
-
- context = SetThreadDpiAwarenessContext( GetWindowDpiAwarenessContext( hwnd ));
-
- /* Compute default values */
-
- GetWindowRect(hwnd, &rc);
- MinMax.ptReserved.x = rc.left;
- MinMax.ptReserved.y = rc.top;
-
- if ((style & WS_CAPTION) == WS_CAPTION)
- adjustedStyle = style & ~WS_BORDER; /* WS_CAPTION = WS_DLGFRAME | WS_BORDER */
- else
- adjustedStyle = style;
-
- GetClientRect(NtUserGetAncestor(hwnd,GA_PARENT), &rc);
- AdjustWindowRectEx(&rc, adjustedStyle, ((style & WS_POPUP) && GetMenu(hwnd)), exstyle);
-
- xinc = -rc.left;
- yinc = -rc.top;
-
- MinMax.ptMaxSize.x = rc.right - rc.left;
- MinMax.ptMaxSize.y = rc.bottom - rc.top;
- if (style & (WS_DLGFRAME | WS_BORDER))
- {
- MinMax.ptMinTrackSize.x = GetSystemMetrics(SM_CXMINTRACK);
- MinMax.ptMinTrackSize.y = GetSystemMetrics(SM_CYMINTRACK);
- }
- else
- {
- MinMax.ptMinTrackSize.x = 2 * xinc;
- MinMax.ptMinTrackSize.y = 2 * yinc;
- }
- MinMax.ptMaxTrackSize.x = GetSystemMetrics(SM_CXMAXTRACK);
- MinMax.ptMaxTrackSize.y = GetSystemMetrics(SM_CYMAXTRACK);
- MinMax.ptMaxPosition.x = -xinc;
- MinMax.ptMaxPosition.y = -yinc;
-
- if ((win = WIN_GetPtr( hwnd )) && win != WND_DESKTOP && win != WND_OTHER_PROCESS)
- {
- if (!EMPTYPOINT(win->max_pos)) MinMax.ptMaxPosition = win->max_pos;
- WIN_ReleasePtr( win );
- }
-
- SendMessageW( hwnd, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax );
-
- /* if the app didn't change the values, adapt them for the current monitor */
-
- if (get_work_rect( hwnd, &rc_work ))
- {
- rc_primary = get_primary_monitor_rect();
- if (MinMax.ptMaxSize.x == (rc_primary.right - rc_primary.left) + 2 * xinc &&
- MinMax.ptMaxSize.y == (rc_primary.bottom - rc_primary.top) + 2 * yinc)
- {
- MinMax.ptMaxSize.x = (rc_work.right - rc_work.left) + 2 * xinc;
- MinMax.ptMaxSize.y = (rc_work.bottom - rc_work.top) + 2 * yinc;
- }
- if (MinMax.ptMaxPosition.x == -xinc && MinMax.ptMaxPosition.y == -yinc)
- {
- MinMax.ptMaxPosition.x = rc_work.left - xinc;
- MinMax.ptMaxPosition.y = rc_work.top - yinc;
- }
- }
-
- /* Some sanity checks */
-
- TRACE("%d %d / %d %d / %d %d / %d %d\n",
- MinMax.ptMaxSize.x, MinMax.ptMaxSize.y,
- MinMax.ptMaxPosition.x, MinMax.ptMaxPosition.y,
- MinMax.ptMaxTrackSize.x, MinMax.ptMaxTrackSize.y,
- MinMax.ptMinTrackSize.x, MinMax.ptMinTrackSize.y);
- MinMax.ptMaxTrackSize.x = max( MinMax.ptMaxTrackSize.x,
- MinMax.ptMinTrackSize.x );
- MinMax.ptMaxTrackSize.y = max( MinMax.ptMaxTrackSize.y,
- MinMax.ptMinTrackSize.y );
-
- SetThreadDpiAwarenessContext( context );
- return MinMax;
+ MINMAXINFO info;
+ NtUserCallHwndParam( hwnd, (UINT_PTR)&info, NtUserGetMinMaxInfo );
+ return info;
}
+
static POINT get_first_minimized_child_pos( const RECT *parent, const MINIMIZEDMETRICS *mm,
int width, int height )
{
diff --git a/dlls/win32u/menu.c b/dlls/win32u/menu.c
index 1e8410d347e..921c5752536 100644
--- a/dlls/win32u/menu.c
+++ b/dlls/win32u/menu.c
@@ -106,6 +106,12 @@ BOOL WINAPI NtUserDestroyAcceleratorTable( HACCEL handle )
return TRUE;
}
+/* see GetMenu */
+HMENU get_menu( HWND hwnd )
+{
+ return UlongToHandle( get_window_long( hwnd, GWLP_ID ));
+}
+
/**********************************************************************
* NtUserDestroyMenu (win32u.@)
*/
diff --git a/dlls/win32u/ntuser_private.h b/dlls/win32u/ntuser_private.h
index b3cafe791df..51f17f63de5 100644
--- a/dlls/win32u/ntuser_private.h
+++ b/dlls/win32u/ntuser_private.h
@@ -30,6 +30,7 @@ struct tagWND;
struct user_callbacks
{
+ BOOL (WINAPI *pAdjustWindowRectEx)( RECT *, DWORD, BOOL, DWORD );
HANDLE (WINAPI *pCopyImage)( HANDLE, UINT, INT, INT, UINT );
BOOL (WINAPI *pDestroyCaret)(void);
BOOL (WINAPI *pDestroyMenu)( HMENU );
diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h
index 83b0e093a20..2e8a8e3da8e 100644
--- a/dlls/win32u/win32u_private.h
+++ b/dlls/win32u/win32u_private.h
@@ -316,6 +316,9 @@ extern BOOL WINAPI release_capture(void) DECLSPEC_HIDDEN;
extern BOOL set_capture_window( HWND hwnd, UINT gui_flags, HWND *prev_ret ) DECLSPEC_HIDDEN;
extern BOOL set_foreground_window( HWND hwnd, BOOL mouse ) DECLSPEC_HIDDEN;
+/* menu.c */
+extern HMENU get_menu( HWND hwnd ) DECLSPEC_HIDDEN;
+
/* message.c */
extern BOOL kill_system_timer( HWND hwnd, UINT_PTR id ) DECLSPEC_HIDDEN;
extern LRESULT post_message( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) DECLSPEC_HIDDEN;
diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c
index f8d147b785c..1069ace0794 100644
--- a/dlls/win32u/window.c
+++ b/dlls/win32u/window.c
@@ -3267,6 +3267,100 @@ static void send_parent_notify( HWND hwnd, UINT msg )
}
}
+/*******************************************************************
+ * get_min_max_info
+ *
+ * Get the minimized and maximized information for a window.
+ */
+static MINMAXINFO get_min_max_info( HWND hwnd )
+{
+ LONG style = get_window_long( hwnd, GWL_STYLE );
+ LONG exstyle = get_window_long( hwnd, GWL_EXSTYLE );
+ DPI_AWARENESS_CONTEXT context;
+ RECT rc_work, rc_primary;
+ LONG adjusted_style;
+ MINMAXINFO minmax;
+ INT xinc, yinc;
+ RECT rc;
+ WND *win;
+
+ context = set_thread_dpi_awareness_context( get_window_dpi_awareness_context( hwnd ));
+
+ /* Compute default values */
+
+ get_window_rect( hwnd, &rc, get_thread_dpi() );
+ minmax.ptReserved.x = rc.left;
+ minmax.ptReserved.y = rc.top;
+
+ if ((style & WS_CAPTION) == WS_CAPTION)
+ adjusted_style = style & ~WS_BORDER; /* WS_CAPTION = WS_DLGFRAME | WS_BORDER */
+ else
+ adjusted_style = style;
+
+ get_client_rect( NtUserGetAncestor( hwnd, GA_PARENT ), &rc );
+ if (user_callbacks)
+ user_callbacks->pAdjustWindowRectEx( &rc, adjusted_style,
+ (style & WS_POPUP) && get_menu( hwnd ), exstyle);
+
+ xinc = -rc.left;
+ yinc = -rc.top;
+
+ minmax.ptMaxSize.x = rc.right - rc.left;
+ minmax.ptMaxSize.y = rc.bottom - rc.top;
+ if (style & (WS_DLGFRAME | WS_BORDER))
+ {
+ minmax.ptMinTrackSize.x = get_system_metrics( SM_CXMINTRACK );
+ minmax.ptMinTrackSize.y = get_system_metrics( SM_CYMINTRACK );
+ }
+ else
+ {
+ minmax.ptMinTrackSize.x = 2 * xinc;
+ minmax.ptMinTrackSize.y = 2 * yinc;
+ }
+ minmax.ptMaxTrackSize.x = get_system_metrics( SM_CXMAXTRACK );
+ minmax.ptMaxTrackSize.y = get_system_metrics( SM_CYMAXTRACK );
+ minmax.ptMaxPosition.x = -xinc;
+ minmax.ptMaxPosition.y = -yinc;
+
+ if ((win = get_win_ptr( hwnd )) && win != WND_DESKTOP && win != WND_OTHER_PROCESS)
+ {
+ if (!empty_point( win->max_pos )) minmax.ptMaxPosition = win->max_pos;
+ release_win_ptr( win );
+ }
+
+ send_message( hwnd, WM_GETMINMAXINFO, 0, (LPARAM)&minmax );
+
+ /* if the app didn't change the values, adapt them for the current monitor */
+
+ if (get_work_rect( hwnd, &rc_work ))
+ {
+ rc_primary = get_primary_monitor_rect( get_thread_dpi() );
+ if (minmax.ptMaxSize.x == (rc_primary.right - rc_primary.left) + 2 * xinc &&
+ minmax.ptMaxSize.y == (rc_primary.bottom - rc_primary.top) + 2 * yinc)
+ {
+ minmax.ptMaxSize.x = (rc_work.right - rc_work.left) + 2 * xinc;
+ minmax.ptMaxSize.y = (rc_work.bottom - rc_work.top) + 2 * yinc;
+ }
+ if (minmax.ptMaxPosition.x == -xinc && minmax.ptMaxPosition.y == -yinc)
+ {
+ minmax.ptMaxPosition.x = rc_work.left - xinc;
+ minmax.ptMaxPosition.y = rc_work.top - yinc;
+ }
+ }
+
+ TRACE( "%d %d / %d %d / %d %d / %d %d\n",
+ minmax.ptMaxSize.x, minmax.ptMaxSize.y,
+ minmax.ptMaxPosition.x, minmax.ptMaxPosition.y,
+ minmax.ptMaxTrackSize.x, minmax.ptMaxTrackSize.y,
+ minmax.ptMinTrackSize.x, minmax.ptMinTrackSize.y );
+
+ minmax.ptMaxTrackSize.x = max( minmax.ptMaxTrackSize.x, minmax.ptMinTrackSize.x );
+ minmax.ptMaxTrackSize.y = max( minmax.ptMaxTrackSize.y, minmax.ptMinTrackSize.y );
+
+ set_thread_dpi_awareness_context( context );
+ return minmax;
+}
+
/*******************************************************************
* update_window_state
*
@@ -3671,6 +3765,9 @@ ULONG_PTR WINAPI NtUserCallHwndParam( HWND hwnd, DWORD_PTR param, DWORD code )
return get_class_word( hwnd, param );
case NtUserGetClientRect:
return get_client_rect( hwnd, (RECT *)param );
+ case NtUserGetMinMaxInfo:
+ *(MINMAXINFO *)param = get_min_max_info( hwnd );
+ return 0;
case NtUserGetWindowInfo:
return get_window_info( hwnd, (WINDOWINFO *)param );
case NtUserGetWindowLongA:
diff --git a/include/ntuser.h b/include/ntuser.h
index de958caa735..274c0cf31c9 100644
--- a/include/ntuser.h
+++ b/include/ntuser.h
@@ -167,6 +167,7 @@ enum
NtUserGetClassLongPtrW,
NtUserGetClassWord,
NtUserGetClientRect,
+ NtUserGetMinMaxInfo,
NtUserGetWindowInfo,
NtUserGetWindowLongA,
NtUserGetWindowLongW,
--
2.23.0
1
0
[PATCH v2 2/5] win32u: Move NtUserDestroyWindow implementation from user32.
by Huw Davies 17 Mar '22
by Huw Davies 17 Mar '22
17 Mar '22
From: Jacek Caban <jacek(a)codeweavers.com>
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/user32/clipboard.c | 23 ---
dlls/user32/combo.c | 2 +-
dlls/user32/dde_misc.c | 6 +-
dlls/user32/dde_server.c | 2 +-
dlls/user32/defwnd.c | 2 +-
dlls/user32/dialog.c | 4 +-
dlls/user32/driver.c | 7 +-
dlls/user32/mdi.c | 2 +-
dlls/user32/menu.c | 8 +-
dlls/user32/message.c | 2 -
dlls/user32/msgbox.c | 70 ++++----
dlls/user32/painting.c | 12 --
dlls/user32/user32.spec | 2 +-
dlls/user32/user_main.c | 10 ++
dlls/user32/win.c | 248 +--------------------------
dlls/user32/win.h | 1 -
dlls/win32u/clipboard.c | 25 +++
dlls/win32u/driver.c | 1 +
dlls/win32u/gdiobj.c | 1 +
dlls/win32u/message.c | 2 +
dlls/win32u/ntuser_private.h | 4 +
dlls/win32u/sysparams.c | 18 +-
dlls/win32u/win32u.spec | 2 +-
dlls/win32u/win32u_private.h | 6 +
dlls/win32u/window.c | 315 +++++++++++++++++++++++++++++++++++
dlls/win32u/wrappers.c | 6 +
include/ntuser.h | 4 +-
27 files changed, 440 insertions(+), 345 deletions(-)
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 );
--
2.23.0
1
0
[PATCH v2 1/5] win32u: Move destroy_thread_windows implementation from user32.
by Huw Davies 17 Mar '22
by Huw Davies 17 Mar '22
17 Mar '22
From: Jacek Caban <jacek(a)codeweavers.com>
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/user32/user_main.c | 11 +++++--
dlls/user32/win.c | 56 ------------------------------------
dlls/user32/win.h | 1 -
dlls/win32u/menu.c | 8 ++++++
dlls/win32u/ntuser_private.h | 5 ++--
dlls/win32u/sysparams.c | 5 ++--
dlls/win32u/win32u_private.h | 1 +
dlls/win32u/window.c | 48 ++++++++++++++++++++++++++++++-
include/ntuser.h | 2 +-
9 files changed, 72 insertions(+), 65 deletions(-)
diff --git a/dlls/user32/user_main.c b/dlls/user32/user_main.c
index 8e8c357bdcf..ff9b469dae6 100644
--- a/dlls/user32/user_main.c
+++ b/dlls/user32/user_main.c
@@ -140,9 +140,17 @@ static void CDECL notify_ime( HWND hwnd, UINT param )
if (ime_default) SendMessageW( ime_default, WM_IME_INTERNAL, param, HandleToUlong(hwnd) );
}
+static void CDECL free_win_ptr( WND *win )
+{
+ HeapFree( GetProcessHeap(), 0, win->text );
+ HeapFree( GetProcessHeap(), 0, win->pScroll );
+ HeapFree( GetProcessHeap(), 0, win );
+}
+
static const struct user_callbacks user_funcs =
{
CopyImage,
+ DestroyMenu,
HideCaret,
PostMessageW,
SendInput,
@@ -152,6 +160,7 @@ static const struct user_callbacks user_funcs =
ShowCaret,
ShowWindow,
WaitForInputIdle,
+ free_win_ptr,
notify_ime,
register_builtin_classes,
MSG_SendInternalMessageTimeout,
@@ -222,8 +231,6 @@ static void thread_detach(void)
WDML_NotifyThreadDetach();
NtUserCallNoParam( NtUserThreadDetach );
- destroy_thread_windows();
- CloseHandle( thread_info->server_queue );
HeapFree( GetProcessHeap(), 0, thread_info->wmchar_data );
HeapFree( GetProcessHeap(), 0, thread_info->rawinput );
diff --git a/dlls/user32/win.c b/dlls/user32/win.c
index a21bdc62ed5..b57d6bd7566 100644
--- a/dlls/user32/win.c
+++ b/dlls/user32/win.c
@@ -820,62 +820,6 @@ LRESULT WIN_DestroyWindow( HWND hwnd )
}
-/***********************************************************************
- * next_thread_window
- */
-static WND *next_thread_window( HWND *hwnd )
-{
- return (WND *)NtUserCallOneParam( (UINT_PTR)hwnd, NtUserNextThreadWindow );
-}
-
-
-/***********************************************************************
- * destroy_thread_windows
- *
- * Destroy all window owned by the current thread.
- */
-void destroy_thread_windows(void)
-{
- WND *win, *free_list = NULL, **free_list_ptr = &free_list;
- HWND hwnd = 0;
-
- USER_Lock();
- while ((win = next_thread_window( &hwnd )))
- {
- free_dce( win->dce, win->obj.handle );
- NtUserCallTwoParam( HandleToUlong(hwnd), 0, NtUserSetHandlePtr );
- win->obj.handle = *free_list_ptr;
- free_list_ptr = (WND **)&win->obj.handle;
- }
- if (free_list)
- {
- SERVER_START_REQ( destroy_window )
- {
- req->handle = 0; /* destroy all thread windows */
- wine_server_call( req );
- }
- SERVER_END_REQ;
- }
- USER_Unlock();
-
- while ((win = free_list))
- {
- free_list = win->obj.handle;
- TRACE( "destroying %p\n", win );
-
- if ((win->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD && win->wIDmenu)
- DestroyMenu( UlongToHandle(win->wIDmenu) );
- if (win->hSysMenu) DestroyMenu( win->hSysMenu );
- if (win->surface)
- {
- register_window_surface( win->surface, NULL );
- window_surface_release( win->surface );
- }
- HeapFree( GetProcessHeap(), 0, win );
- }
-}
-
-
/***********************************************************************
* WIN_FixCoordinates
*
diff --git a/dlls/user32/win.h b/dlls/user32/win.h
index 08bb16a0d4a..3e6885ab090 100644
--- a/dlls/user32/win.h
+++ b/dlls/user32/win.h
@@ -46,7 +46,6 @@ extern UINT win_set_flags( HWND hwnd, UINT set_mask, UINT clear_mask ) DECLSPEC_
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 void destroy_thread_windows(void) 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/menu.c b/dlls/win32u/menu.c
index abaca12047f..1e8410d347e 100644
--- a/dlls/win32u/menu.c
+++ b/dlls/win32u/menu.c
@@ -105,3 +105,11 @@ BOOL WINAPI NtUserDestroyAcceleratorTable( HACCEL handle )
free( accel );
return TRUE;
}
+
+/**********************************************************************
+ * NtUserDestroyMenu (win32u.@)
+ */
+BOOL WINAPI NtUserDestroyMenu( HMENU menu )
+{
+ return user_callbacks && user_callbacks->pDestroyMenu( menu );
+}
diff --git a/dlls/win32u/ntuser_private.h b/dlls/win32u/ntuser_private.h
index d6c3e681c2f..aa9b45b1542 100644
--- a/dlls/win32u/ntuser_private.h
+++ b/dlls/win32u/ntuser_private.h
@@ -26,10 +26,12 @@
#include "wine/list.h"
struct dce;
+struct tagWND;
struct user_callbacks
{
HANDLE (WINAPI *pCopyImage)( HANDLE, UINT, INT, INT, UINT );
+ BOOL (WINAPI *pDestroyMenu)( HMENU );
BOOL (WINAPI *pHideCaret)( HWND hwnd );
BOOL (WINAPI *pPostMessageW)( HWND, UINT, WPARAM, LPARAM );
UINT (WINAPI *pSendInput)( UINT count, INPUT *inputs, int size );
@@ -39,6 +41,7 @@ struct user_callbacks
BOOL (WINAPI *pShowCaret)( HWND hwnd );
BOOL (WINAPI *pShowWindow)( HWND, INT );
DWORD (WINAPI *pWaitForInputIdle)( HANDLE, DWORD );
+ void (CDECL *free_win_ptr)( struct tagWND *win );
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 );
@@ -122,8 +125,6 @@ static inline BOOL is_broadcast( HWND hwnd )
return hwnd == HWND_BROADCAST || hwnd == HWND_TOPMOST;
}
-WND *next_thread_window_ptr( HWND *hwnd );
-
#define WM_IME_INTERNAL 0x287
#define IME_INTERNAL_ACTIVATE 0x17
#define IME_INTERNAL_DEACTIVATE 0x18
diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c
index f0ecb3b92bb..d9ddfe3400e 100644
--- a/dlls/win32u/sysparams.c
+++ b/dlls/win32u/sysparams.c
@@ -4599,6 +4599,9 @@ static void thread_detach(void)
free( thread_info->key_state );
thread_info->key_state = 0;
+
+ destroy_thread_windows();
+ NtClose( thread_info->server_queue );
}
/***********************************************************************
@@ -4689,8 +4692,6 @@ ULONG_PTR WINAPI NtUserCallOneParam( ULONG_PTR arg, ULONG code )
case 1: user_unlock(); return 0;
default: user_check_not_lock(); return 0;
}
- case NtUserNextThreadWindow:
- return (UINT_PTR)next_thread_window_ptr( (HWND *)arg );
case NtUserSetCallbacks:
return (UINT_PTR)InterlockedExchangePointer( (void **)&user_callbacks, (void *)arg );
default:
diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h
index 0c4e3b82f0f..516f4540315 100644
--- a/dlls/win32u/win32u_private.h
+++ b/dlls/win32u/win32u_private.h
@@ -343,6 +343,7 @@ extern void erase_now( HWND hwnd, UINT rdw_flags ) DECLSPEC_HIDDEN;
/* window.c */
struct tagWND;
extern HDWP begin_defer_window_pos( INT count ) DECLSPEC_HIDDEN;
+extern void destroy_thread_windows(void) 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 079b4b0695f..a28b6ae9ebf 100644
--- a/dlls/win32u/window.c
+++ b/dlls/win32u/window.c
@@ -141,7 +141,7 @@ void *free_user_handle( HANDLE handle, unsigned int type )
/***********************************************************************
* next_thread_window
*/
-WND *next_thread_window_ptr( HWND *hwnd )
+static WND *next_thread_window_ptr( HWND *hwnd )
{
struct user_object *ptr;
WND *win;
@@ -3259,6 +3259,52 @@ BOOL WINAPI NtUserFlashWindowEx( FLASHWINFO *info )
}
}
+/***********************************************************************
+ * destroy_thread_windows
+ *
+ * Destroy all window owned by the current thread.
+ */
+void destroy_thread_windows(void)
+{
+ WND *win, *free_list = NULL;
+ HWND hwnd = 0;
+
+ user_lock();
+ while ((win = next_thread_window_ptr( &hwnd )))
+ {
+ free_dce( win->dce, win->obj.handle );
+ set_user_handle_ptr( hwnd, NULL );
+ win->obj.handle = free_list;
+ free_list = win;
+ }
+ if (free_list)
+ {
+ SERVER_START_REQ( destroy_window )
+ {
+ req->handle = 0; /* destroy all thread windows */
+ wine_server_call( req );
+ }
+ SERVER_END_REQ;
+ }
+ user_unlock();
+
+ while ((win = free_list))
+ {
+ free_list = win->obj.handle;
+ TRACE( "destroying %p\n", win );
+
+ if ((win->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD && win->wIDmenu)
+ NtUserDestroyMenu( UlongToHandle(win->wIDmenu) );
+ if (win->hSysMenu) NtUserDestroyMenu( win->hSysMenu );
+ if (win->surface)
+ {
+ register_window_surface( win->surface, NULL );
+ window_surface_release( win->surface );
+ }
+ if (user_callbacks) user_callbacks->free_win_ptr( win );
+ }
+}
+
/*****************************************************************************
* NtUserCallHwnd (win32u.@)
*/
diff --git a/include/ntuser.h b/include/ntuser.h
index 5e79083aa01..aeb3e9ae2cc 100644
--- a/include/ntuser.h
+++ b/include/ntuser.h
@@ -119,7 +119,6 @@ enum
NtUserHandleInternalMessage,
NtUserIncrementKeyStateCounter,
NtUserLock,
- NtUserNextThreadWindow,
NtUserSetCallbacks,
};
@@ -302,6 +301,7 @@ HDWP WINAPI NtUserDeferWindowPosAndBand( HDWP hdwp, HWND hwnd, HWND after, IN
INT cx, INT cy, UINT flags, UINT unk1, UINT unk2 );
BOOL WINAPI NtUserDestroyAcceleratorTable( HACCEL handle );
BOOL WINAPI NtUserDestroyCursor( HCURSOR cursor, ULONG arg );
+BOOL WINAPI NtUserDestroyMenu( HMENU menu );
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 );
--
2.23.0
1
0
[PATCH 5/5] win32u: Move GetWindowContextHelpId implementation from user32.
by Jacek Caban 17 Mar '22
by Jacek Caban 17 Mar '22
17 Mar '22
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
---
dlls/user32/win.c | 12 +-----------
dlls/win32u/window.c | 18 ++++++++++++++++++
include/ntuser.h | 1 +
3 files changed, 20 insertions(+), 11 deletions(-)
1
0
17 Mar '22
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
---
dlls/user32/combo.c | 4 +-
dlls/user32/defwnd.c | 2 +-
dlls/user32/dialog.c | 6 +-
dlls/user32/driver.c | 8 +-
dlls/user32/mdi.c | 12 +-
dlls/user32/message.c | 21 +-
dlls/user32/nonclient.c | 6 +-
dlls/user32/scroll.c | 2 +-
dlls/user32/user32.spec | 4 +-
dlls/user32/user_main.c | 1 -
dlls/user32/win.c | 10 +-
dlls/user32/win.h | 6 -
dlls/user32/winpos.c | 228 +---------------
dlls/win32u/driver.c | 1 +
dlls/win32u/gdiobj.c | 2 +
dlls/win32u/input.c | 2 +-
dlls/win32u/message.c | 3 +
dlls/win32u/ntuser_private.h | 7 +-
dlls/win32u/win32u.spec | 4 +-
dlls/win32u/win32u_private.h | 4 +
dlls/win32u/window.c | 485 ++++++++++++++++++++++++++++++++++-
dlls/win32u/wrappers.c | 12 +
include/ntuser.h | 1 +
23 files changed, 540 insertions(+), 291 deletions(-)
1
0