Wine-Devel
By thread
wine-devel@list.winehq.org
By month
Messages by month
- ----- 2026 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 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
May 2022
- 77 participants
- 2907 messages
[PATCH 13/13] win32u: Copy implementation of AdjustWindowRectEx from user32.
by Jacek Caban
From: Jacek Caban <jacek(a)codeweavers.com>
It will be useful for drivers as well.
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
---
dlls/user32/user_main.c | 1 -
dlls/win32u/defwnd.c | 38 ++++++++++++++++++++++++++++++++++++
dlls/win32u/ntuser_private.h | 1 -
dlls/win32u/window.c | 4 +---
4 files changed, 39 insertions(+), 5 deletions(-)
diff --git a/dlls/user32/user_main.c b/dlls/user32/user_main.c
index fa849e9cf2d..b282056d8c8 100644
--- a/dlls/user32/user_main.c
+++ b/dlls/user32/user_main.c
@@ -159,7 +159,6 @@ static void CDECL free_win_ptr( WND *win )
static const struct user_callbacks user_funcs =
{
- AdjustWindowRectEx,
CopyImage,
EndMenu,
ImmProcessKey,
diff --git a/dlls/win32u/defwnd.c b/dlls/win32u/defwnd.c
index 0080d4f7cc6..7455a91980c 100644
--- a/dlls/win32u/defwnd.c
+++ b/dlls/win32u/defwnd.c
@@ -31,6 +31,44 @@
WINE_DEFAULT_DEBUG_CHANNEL(win);
+/***********************************************************************
+ * AdjustWindowRectEx (win32u.so)
+ */
+BOOL WINAPI AdjustWindowRectEx( RECT *rect, DWORD style, BOOL menu, DWORD ex_style )
+{
+ NONCLIENTMETRICSW ncm;
+ int adjust = 0;
+
+ ncm.cbSize = sizeof(ncm);
+ NtUserSystemParametersInfo( SPI_GETNONCLIENTMETRICS, 0, &ncm, 0 );
+
+ if ((ex_style & (WS_EX_STATICEDGE|WS_EX_DLGMODALFRAME)) == WS_EX_STATICEDGE)
+ adjust = 1; /* for the outer frame always present */
+ else if ((ex_style & WS_EX_DLGMODALFRAME) || (style & (WS_THICKFRAME|WS_DLGFRAME)))
+ adjust = 2; /* outer */
+
+ if (style & WS_THICKFRAME)
+ adjust += ncm.iBorderWidth + ncm.iPaddedBorderWidth; /* The resize border */
+
+ if ((style & (WS_BORDER|WS_DLGFRAME)) || (ex_style & WS_EX_DLGMODALFRAME))
+ adjust++; /* The other border */
+
+ InflateRect( rect, adjust, adjust );
+
+ if ((style & WS_CAPTION) == WS_CAPTION)
+ {
+ if (ex_style & WS_EX_TOOLWINDOW)
+ rect->top -= ncm.iSmCaptionHeight + 1;
+ else
+ rect->top -= ncm.iCaptionHeight + 1;
+ }
+ if (menu) rect->top -= ncm.iMenuHeight + 1;
+
+ if (ex_style & WS_EX_CLIENTEDGE)
+ InflateRect( rect, get_system_metrics(SM_CXEDGE), get_system_metrics(SM_CYEDGE) );
+ return TRUE;
+}
+
static BOOL set_window_text( HWND hwnd, const void *text, BOOL ansi )
{
static const WCHAR emptyW[] = { 0 };
diff --git a/dlls/win32u/ntuser_private.h b/dlls/win32u/ntuser_private.h
index c870037f7b3..6e25e0ec0db 100644
--- a/dlls/win32u/ntuser_private.h
+++ b/dlls/win32u/ntuser_private.h
@@ -32,7 +32,6 @@ struct hardware_msg_data;
struct user_callbacks
{
- BOOL (WINAPI *pAdjustWindowRectEx)( RECT *, DWORD, BOOL, DWORD );
HANDLE (WINAPI *pCopyImage)( HANDLE, UINT, INT, INT, UINT );
BOOL (WINAPI *pEndMenu)(void);
BOOL (WINAPI *pImmProcessKey)(HWND, HKL, UINT, LPARAM, DWORD);
diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c
index edafc522d14..9231f98539e 100644
--- a/dlls/win32u/window.c
+++ b/dlls/win32u/window.c
@@ -3683,9 +3683,7 @@ static MINMAXINFO get_min_max_info( HWND hwnd )
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);
+ AdjustWindowRectEx( &rc, adjusted_style, (style & WS_POPUP) && get_menu( hwnd ), exstyle );
xinc = -rc.left;
yinc = -rc.top;
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/18
May 2, 2022
[PATCH 12/13] win32u: Move NtUserSetSystemMenu implementation from user32.
by Jacek Caban
From: Jacek Caban <jacek(a)codeweavers.com>
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
---
dlls/user32/menu.c | 18 ------------------
dlls/user32/user32.spec | 2 +-
dlls/user32/user_main.c | 1 -
dlls/win32u/gdiobj.c | 1 +
dlls/win32u/menu.c | 23 +++++++++++++++--------
dlls/win32u/ntuser_private.h | 1 -
dlls/win32u/win32u.spec | 2 +-
dlls/win32u/win32u_private.h | 1 +
dlls/win32u/wrappers.c | 6 ++++++
9 files changed, 25 insertions(+), 30 deletions(-)
diff --git a/dlls/user32/menu.c b/dlls/user32/menu.c
index 2e9121598fa..64e5d35ba39 100644
--- a/dlls/user32/menu.c
+++ b/dlls/user32/menu.c
@@ -3925,24 +3925,6 @@ HMENU WINAPI CreateMenu(void)
}
-/*******************************************************************
- * SetSystemMenu (USER32.@)
- */
-BOOL WINAPI SetSystemMenu( HWND hwnd, HMENU hMenu )
-{
- WND *wndPtr = WIN_GetPtr( hwnd );
-
- if (wndPtr && wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
- {
- if (wndPtr->hSysMenu) NtUserDestroyMenu( wndPtr->hSysMenu );
- wndPtr->hSysMenu = MENU_GetSysMenu( hwnd, hMenu );
- WIN_ReleasePtr( wndPtr );
- return TRUE;
- }
- return FALSE;
-}
-
-
/**********************************************************************
* GetMenu (USER32.@)
*/
diff --git a/dlls/user32/user32.spec b/dlls/user32/user32.spec
index 8bccdab69c6..1ae27b2482f 100644
--- a/dlls/user32/user32.spec
+++ b/dlls/user32/user32.spec
@@ -707,7 +707,7 @@
@ stdcall SetSysColors(long ptr ptr) NtUserSetSysColors
@ stdcall SetSysColorsTemp(ptr ptr long)
@ stdcall SetSystemCursor(long long)
-@ stdcall SetSystemMenu(long long)
+@ stdcall SetSystemMenu(long long) NtUserSetSystemMenu
@ stdcall SetSystemTimer(long long long ptr)
@ stdcall SetTaskmanWindow (long)
@ stdcall SetThreadDesktop(long) NtUserSetThreadDesktop
diff --git a/dlls/user32/user_main.c b/dlls/user32/user_main.c
index 358177d33d2..fa849e9cf2d 100644
--- a/dlls/user32/user_main.c
+++ b/dlls/user32/user_main.c
@@ -164,7 +164,6 @@ static const struct user_callbacks user_funcs =
EndMenu,
ImmProcessKey,
ImmTranslateMessage,
- SetSystemMenu,
free_win_ptr,
MENU_GetSysMenu,
MENU_IsMenuActive,
diff --git a/dlls/win32u/gdiobj.c b/dlls/win32u/gdiobj.c
index 6cc63800201..f6790690188 100644
--- a/dlls/win32u/gdiobj.c
+++ b/dlls/win32u/gdiobj.c
@@ -1212,6 +1212,7 @@ static struct unix_funcs unix_funcs =
NtUserSetMenu,
NtUserSetParent,
NtUserSetSysColors,
+ NtUserSetSystemMenu,
NtUserSetWindowLong,
NtUserSetWindowLongPtr,
NtUserSetWindowPos,
diff --git a/dlls/win32u/menu.c b/dlls/win32u/menu.c
index 0da21675e68..a6aeae045e2 100644
--- a/dlls/win32u/menu.c
+++ b/dlls/win32u/menu.c
@@ -465,14 +465,6 @@ BOOL WINAPI NtUserDestroyMenu( HMENU handle )
return TRUE;
}
-/*******************************************************************
- * NtUserSetSystemMenu (win32u.@)
- */
-BOOL WINAPI NtUserSetSystemMenu( HWND hwnd, HMENU menu )
-{
- return user_callbacks && user_callbacks->pSetSystemMenu( hwnd, menu );
-}
-
/*******************************************************************
* set_window_menu
*
@@ -1072,6 +1064,21 @@ HMENU WINAPI NtUserGetSystemMenu( HWND hwnd, BOOL revert )
return revert ? 0 : retvalue;
}
+/**********************************************************************
+ * NtUserSetSystemMenu (win32u.@)
+ */
+BOOL WINAPI NtUserSetSystemMenu( HWND hwnd, HMENU menu )
+{
+ WND *win = get_win_ptr( hwnd );
+
+ if (!win || win == WND_OTHER_PROCESS || win == WND_DESKTOP) return FALSE;
+
+ if (win->hSysMenu) NtUserDestroyMenu( win->hSysMenu );
+ win->hSysMenu = user_callbacks ? user_callbacks->get_sys_menu( hwnd, menu ) : NULL;
+ release_win_ptr( win );
+ return TRUE;
+}
+
/**********************************************************************
* NtUserSetMenuDefaultItem (win32u.@)
*/
diff --git a/dlls/win32u/ntuser_private.h b/dlls/win32u/ntuser_private.h
index acc3fdf6290..c870037f7b3 100644
--- a/dlls/win32u/ntuser_private.h
+++ b/dlls/win32u/ntuser_private.h
@@ -37,7 +37,6 @@ struct user_callbacks
BOOL (WINAPI *pEndMenu)(void);
BOOL (WINAPI *pImmProcessKey)(HWND, HKL, UINT, LPARAM, DWORD);
BOOL (WINAPI *pImmTranslateMessage)(HWND, UINT, WPARAM, LPARAM);
- BOOL (WINAPI *pSetSystemMenu)( HWND hwnd, HMENU menu );
void (CDECL *free_win_ptr)( struct tagWND *win );
HMENU (CDECL *get_sys_menu)( HWND hwnd, HMENU popup );
HWND (CDECL *is_menu_active)(void);
diff --git a/dlls/win32u/win32u.spec b/dlls/win32u/win32u.spec
index d94324b1290..d6a51c1d3b9 100644
--- a/dlls/win32u/win32u.spec
+++ b/dlls/win32u/win32u.spec
@@ -1229,7 +1229,7 @@
@ stub NtUserSetShellWindowEx
@ stdcall NtUserSetSysColors(long ptr ptr)
@ stub NtUserSetSystemCursor
-@ stub NtUserSetSystemMenu
+@ stdcall NtUserSetSystemMenu(long long)
@ stdcall -syscall NtUserSetSystemTimer(long long long)
@ stub NtUserSetTargetForResourceBrokering
@ stdcall -syscall NtUserSetThreadDesktop(long)
diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h
index c40d2cb2a6f..ea6d67750b4 100644
--- a/dlls/win32u/win32u_private.h
+++ b/dlls/win32u/win32u_private.h
@@ -282,6 +282,7 @@ struct unix_funcs
BOOL (WINAPI *pNtUserSetMenu)( HWND hwnd, HMENU menu );
HWND (WINAPI *pNtUserSetParent)( HWND hwnd, HWND parent );
BOOL (WINAPI *pNtUserSetSysColors)( INT count, const INT *colors, const COLORREF *values );
+ BOOL (WINAPI *pNtUserSetSystemMenu)( HWND hwnd, HMENU menu );
LONG (WINAPI *pNtUserSetWindowLong)( HWND hwnd, INT offset, LONG newval, BOOL ansi );
LONG_PTR (WINAPI *pNtUserSetWindowLongPtr)( HWND hwnd, INT offset, LONG_PTR newval, BOOL ansi );
BOOL (WINAPI *pNtUserSetWindowPos)( HWND hwnd, HWND after, INT x, INT y, INT cx, INT cy, UINT flags );
diff --git a/dlls/win32u/wrappers.c b/dlls/win32u/wrappers.c
index e3e0781bdde..6219b0fa49c 100644
--- a/dlls/win32u/wrappers.c
+++ b/dlls/win32u/wrappers.c
@@ -1185,6 +1185,12 @@ BOOL WINAPI NtUserSetSysColors( INT count, const INT *colors, const COLORREF *va
return unix_funcs->pNtUserSetSysColors( count, colors, values );
}
+BOOL WINAPI NtUserSetSystemMenu( HWND hwnd, HMENU menu )
+{
+ if (!unix_funcs) return FALSE;
+ return unix_funcs->pNtUserSetSystemMenu( hwnd, menu );
+}
+
LONG WINAPI NtUserSetWindowLong( HWND hwnd, INT offset, LONG newval, BOOL ansi )
{
if (!unix_funcs) return 0;
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/18
May 2, 2022
[PATCH 11/13] win32u: Move NtUserGetSystemMenu implementation from user32.
by Jacek Caban
From: Jacek Caban <jacek(a)codeweavers.com>
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
---
dlls/user32/controls.h | 1 +
dlls/user32/defwnd.c | 6 ++---
dlls/user32/mdi.c | 4 ++--
dlls/user32/menu.c | 45 ++----------------------------------
dlls/user32/nonclient.c | 8 +++----
dlls/user32/user32.spec | 2 +-
dlls/user32/user_main.c | 1 +
dlls/win32u/class.c | 2 +-
dlls/win32u/gdiobj.c | 1 +
dlls/win32u/menu.c | 43 ++++++++++++++++++++++++++++++++++
dlls/win32u/ntuser_private.h | 2 ++
dlls/win32u/win32u.spec | 2 +-
dlls/win32u/win32u_private.h | 1 +
dlls/win32u/wrappers.c | 6 +++++
include/ntuser.h | 1 +
15 files changed, 70 insertions(+), 55 deletions(-)
diff --git a/dlls/user32/controls.h b/dlls/user32/controls.h
index 6e6d7b7d214..1e5b1082d50 100644
--- a/dlls/user32/controls.h
+++ b/dlls/user32/controls.h
@@ -120,6 +120,7 @@ extern void MENU_TrackMouseMenuBar( HWND hwnd, INT ht, POINT pt ) DECLSPEC_HIDDE
extern void MENU_TrackKbdMenuBar( HWND hwnd, UINT wParam, WCHAR wChar ) DECLSPEC_HIDDEN;
extern UINT MENU_DrawMenuBar( HDC hDC, LPRECT lprect, HWND hwnd ) DECLSPEC_HIDDEN;
extern void MENU_EndMenu(HWND) DECLSPEC_HIDDEN;
+extern HMENU MENU_GetSysMenu( HWND hWnd, HMENU hPopupMenu ) DECLSPEC_HIDDEN;
/* nonclient area */
extern LRESULT NC_HandleNCPaint( HWND hwnd , HRGN clip) DECLSPEC_HIDDEN;
diff --git a/dlls/user32/defwnd.c b/dlls/user32/defwnd.c
index a885690ea82..047822d00d6 100644
--- a/dlls/user32/defwnd.c
+++ b/dlls/user32/defwnd.c
@@ -246,16 +246,16 @@ static LRESULT DEFWND_DefWinProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPa
/* Track system popup if click was in the caption area. */
if (hitcode==HTCAPTION || hitcode==HTSYSMENU)
- TrackPopupMenu(GetSystemMenu(hwnd, FALSE),
+ TrackPopupMenu( NtUserGetSystemMenu(hwnd, FALSE),
TPM_LEFTBUTTON | TPM_RIGHTBUTTON,
- pt.x, pt.y, 0, hwnd, NULL);
+ pt.x, pt.y, 0, hwnd, NULL );
}
break;
case WM_POPUPSYSTEMMENU:
/* This is an undocumented message used by the windows taskbar to
display the system menu of windows that belong to other processes. */
- TrackPopupMenu( GetSystemMenu(hwnd, FALSE), TPM_LEFTBUTTON|TPM_RIGHTBUTTON,
+ TrackPopupMenu( NtUserGetSystemMenu(hwnd, FALSE), TPM_LEFTBUTTON|TPM_RIGHTBUTTON,
(short)LOWORD(lParam), (short)HIWORD(lParam), 0, hwnd, NULL );
return 0;
diff --git a/dlls/user32/mdi.c b/dlls/user32/mdi.c
index 1b06143d4cf..e6a391e03c3 100644
--- a/dlls/user32/mdi.c
+++ b/dlls/user32/mdi.c
@@ -217,7 +217,7 @@ static BOOL is_close_enabled(HWND hwnd, HMENU hSysMenu)
{
if (GetClassLongW(hwnd, GCL_STYLE) & CS_NOCLOSE) return FALSE;
- if (!hSysMenu) hSysMenu = GetSystemMenu(hwnd, FALSE);
+ if (!hSysMenu) hSysMenu = NtUserGetSystemMenu( hwnd, FALSE );
if (hSysMenu)
{
UINT state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
@@ -835,7 +835,7 @@ static BOOL MDI_AugmentFrameMenu( HWND frame, HWND hChild )
if (!menu) return FALSE;
/* create a copy of sysmenu popup and insert it into frame menu bar */
- if (!(hSysPopup = GetSystemMenu(hChild, FALSE)))
+ if (!(hSysPopup = NtUserGetSystemMenu( hChild, FALSE )))
{
TRACE("child %p doesn't have a system menu\n", hChild);
return FALSE;
diff --git a/dlls/user32/menu.c b/dlls/user32/menu.c
index 761718182b5..2e9121598fa 100644
--- a/dlls/user32/menu.c
+++ b/dlls/user32/menu.c
@@ -387,7 +387,7 @@ static HMENU MENU_CopySysPopup(BOOL mdi)
* However, the real system menu handle is sometimes seen in the
* WM_MENUSELECT parameters (and Word 6 likes it this way).
*/
-static HMENU MENU_GetSysMenu( HWND hWnd, HMENU hPopupMenu )
+HMENU MENU_GetSysMenu( HWND hWnd, HMENU hPopupMenu )
{
HMENU hMenu;
@@ -3925,47 +3925,6 @@ HMENU WINAPI CreateMenu(void)
}
-/**********************************************************************
- * GetSystemMenu (USER32.@)
- */
-HMENU WINAPI GetSystemMenu( HWND hWnd, BOOL bRevert )
-{
- WND *wndPtr = WIN_GetPtr( hWnd );
- HMENU retvalue = 0;
-
- if (wndPtr == WND_DESKTOP) return 0;
- if (wndPtr == WND_OTHER_PROCESS)
- {
- if (IsWindow( hWnd )) FIXME( "not supported on other process window %p\n", hWnd );
- }
- else if (wndPtr)
- {
- if (wndPtr->hSysMenu && bRevert)
- {
- NtUserDestroyMenu( wndPtr->hSysMenu );
- wndPtr->hSysMenu = 0;
- }
-
- if(!wndPtr->hSysMenu && (wndPtr->dwStyle & WS_SYSMENU) )
- wndPtr->hSysMenu = MENU_GetSysMenu( hWnd, 0 );
-
- if( wndPtr->hSysMenu )
- {
- POPUPMENU *menu;
- retvalue = GetSubMenu(wndPtr->hSysMenu, 0);
-
- /* Store the dummy sysmenu handle to facilitate the refresh */
- /* of the close button if the SC_CLOSE item change */
- menu = MENU_GetMenu(retvalue);
- if ( menu )
- menu->hSysMenuOwner = wndPtr->hSysMenu;
- }
- WIN_ReleasePtr( wndPtr );
- }
- return bRevert ? 0 : retvalue;
-}
-
-
/*******************************************************************
* SetSystemMenu (USER32.@)
*/
@@ -4024,7 +3983,7 @@ BOOL WINAPI GetMenuBarInfo( HWND hwnd, LONG idObject, LONG idItem, PMENUBARINFO
hmenu = GetMenu(hwnd);
break;
case OBJID_SYSMENU:
- hmenu = GetSystemMenu(hwnd, FALSE);
+ hmenu = NtUserGetSystemMenu( hwnd, FALSE );
break;
default:
return FALSE;
diff --git a/dlls/user32/nonclient.c b/dlls/user32/nonclient.c
index a2b5a82a5e6..003ecb7e5e5 100644
--- a/dlls/user32/nonclient.c
+++ b/dlls/user32/nonclient.c
@@ -916,7 +916,7 @@ static void NC_DrawCaption( HDC hdc, RECT *rect, HWND hwnd, DWORD style,
UINT state;
/* Go get the sysmenu */
- hSysMenu = GetSystemMenu(hwnd, FALSE);
+ hSysMenu = NtUserGetSystemMenu(hwnd, FALSE);
state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
/* Draw a grayed close button if disabled or if SC_CLOSE is not there */
@@ -1213,7 +1213,7 @@ static void NC_TrackMinMaxBox( HWND hwnd, WORD wParam )
BOOL pressed = TRUE;
UINT state;
DWORD wndStyle = GetWindowLongW( hwnd, GWL_STYLE);
- HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
+ HMENU hSysMenu = NtUserGetSystemMenu(hwnd, FALSE);
void (*paintButton)(HWND, HDC, BOOL, BOOL);
@@ -1291,7 +1291,7 @@ static void NC_TrackCloseButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
MSG msg;
HDC hdc;
BOOL pressed = TRUE;
- HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
+ HMENU hSysMenu = NtUserGetSystemMenu(hwnd, FALSE);
UINT state;
if(hSysMenu == 0)
@@ -1508,7 +1508,7 @@ LRESULT NC_HandleNCLButtonDblClk( HWND hwnd, WPARAM wParam, LPARAM lParam )
case HTSYSMENU:
{
- HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
+ HMENU hSysMenu = NtUserGetSystemMenu(hwnd, FALSE);
UINT state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
/* If the close item of the sysmenu is disabled or not present do nothing */
diff --git a/dlls/user32/user32.spec b/dlls/user32/user32.spec
index 0697bcfa841..8bccdab69c6 100644
--- a/dlls/user32/user32.spec
+++ b/dlls/user32/user32.spec
@@ -381,7 +381,7 @@
@ stdcall GetSubMenu(long long)
@ stdcall GetSysColor(long)
@ stdcall GetSysColorBrush(long)
-@ stdcall GetSystemMenu(long long)
+@ stdcall GetSystemMenu(long long) NtUserGetSystemMenu
@ stdcall GetSystemMetrics(long)
@ stdcall GetSystemMetricsForDpi(long long)
@ stdcall GetTabbedTextExtentA(long str long long ptr)
diff --git a/dlls/user32/user_main.c b/dlls/user32/user_main.c
index babd5f95e55..358177d33d2 100644
--- a/dlls/user32/user_main.c
+++ b/dlls/user32/user_main.c
@@ -166,6 +166,7 @@ static const struct user_callbacks user_funcs =
ImmTranslateMessage,
SetSystemMenu,
free_win_ptr,
+ MENU_GetSysMenu,
MENU_IsMenuActive,
notify_ime,
post_dde_message,
diff --git a/dlls/win32u/class.c b/dlls/win32u/class.c
index c52fcad6025..64ac48cad19 100644
--- a/dlls/win32u/class.c
+++ b/dlls/win32u/class.c
@@ -66,7 +66,7 @@ static pthread_mutex_t winproc_lock = PTHREAD_MUTEX_INITIALIZER;
static struct list class_list = LIST_INIT( class_list );
-static HINSTANCE user32_module;
+HINSTANCE user32_module = 0;
/* find an existing winproc for a given function and type */
/* FIXME: probably should do something more clever than a linear search */
diff --git a/dlls/win32u/gdiobj.c b/dlls/win32u/gdiobj.c
index ad04ba7ff78..6cc63800201 100644
--- a/dlls/win32u/gdiobj.c
+++ b/dlls/win32u/gdiobj.c
@@ -1176,6 +1176,7 @@ static struct unix_funcs unix_funcs =
NtUserGetMessage,
NtUserGetPriorityClipboardFormat,
NtUserGetQueueStatus,
+ NtUserGetSystemMenu,
NtUserGetUpdateRect,
NtUserGetUpdateRgn,
NtUserGetUpdatedClipboardFormats,
diff --git a/dlls/win32u/menu.c b/dlls/win32u/menu.c
index 67abac37037..0da21675e68 100644
--- a/dlls/win32u/menu.c
+++ b/dlls/win32u/menu.c
@@ -1029,6 +1029,49 @@ static HMENU get_sub_menu( HMENU handle, INT pos )
return submenu;
}
+/**********************************************************************
+ * NtUserGetSystemMenu (win32u.@)
+ */
+HMENU WINAPI NtUserGetSystemMenu( HWND hwnd, BOOL revert )
+{
+ WND *win = get_win_ptr( hwnd );
+ HMENU retvalue = 0;
+
+ if (win == WND_DESKTOP || !win) return 0;
+ if (win == WND_OTHER_PROCESS)
+ {
+ if (is_window( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
+ return 0;
+ }
+
+ if (win->hSysMenu && revert)
+ {
+ NtUserDestroyMenu( win->hSysMenu );
+ win->hSysMenu = 0;
+ }
+
+ if (!win->hSysMenu && (win->dwStyle & WS_SYSMENU) && user_callbacks)
+ win->hSysMenu = user_callbacks->get_sys_menu( hwnd, 0 );
+
+ if (win->hSysMenu)
+ {
+ POPUPMENU *menu;
+ retvalue = get_sub_menu( win->hSysMenu, 0 );
+
+ /* Store the dummy sysmenu handle to facilitate the refresh */
+ /* of the close button if the SC_CLOSE item change */
+ menu = grab_menu_ptr( retvalue );
+ if (menu)
+ {
+ menu->hSysMenuOwner = win->hSysMenu;
+ release_menu_ptr( menu );
+ }
+ }
+
+ release_win_ptr( win );
+ return revert ? 0 : retvalue;
+}
+
/**********************************************************************
* NtUserSetMenuDefaultItem (win32u.@)
*/
diff --git a/dlls/win32u/ntuser_private.h b/dlls/win32u/ntuser_private.h
index 29e6b4eaf3e..acc3fdf6290 100644
--- a/dlls/win32u/ntuser_private.h
+++ b/dlls/win32u/ntuser_private.h
@@ -39,6 +39,7 @@ struct user_callbacks
BOOL (WINAPI *pImmTranslateMessage)(HWND, UINT, WPARAM, LPARAM);
BOOL (WINAPI *pSetSystemMenu)( HWND hwnd, HMENU menu );
void (CDECL *free_win_ptr)( struct tagWND *win );
+ HMENU (CDECL *get_sys_menu)( HWND hwnd, HMENU popup );
HWND (CDECL *is_menu_active)(void);
void (CDECL *notify_ime)( HWND hwnd, UINT param );
BOOL (CDECL *post_dde_message)( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, DWORD dest_tid,
@@ -289,6 +290,7 @@ extern void spy_exit_message( INT flag, HWND hwnd, UINT msg,
LRESULT lreturn, WPARAM wparam, LPARAM lparam ) DECLSPEC_HIDDEN;
/* class.c */
+extern HINSTANCE user32_module DECLSPEC_HIDDEN;
WNDPROC alloc_winproc( WNDPROC func, BOOL ansi ) DECLSPEC_HIDDEN;
WINDOWPROC *get_winproc_ptr( WNDPROC handle ) DECLSPEC_HIDDEN;
BOOL is_winproc_unicode( WNDPROC proc, BOOL def_val ) DECLSPEC_HIDDEN;
diff --git a/dlls/win32u/win32u.spec b/dlls/win32u/win32u.spec
index 43db8421bb8..d94324b1290 100644
--- a/dlls/win32u/win32u.spec
+++ b/dlls/win32u/win32u.spec
@@ -994,7 +994,7 @@
@ stub NtUserGetScrollBarInfo
@ stub NtUserGetSharedWindowData
@ stdcall -syscall NtUserGetSystemDpiForProcess(long)
-@ stub NtUserGetSystemMenu
+@ stdcall NtUserGetSystemMenu(long long)
@ stdcall -syscall NtUserGetThreadDesktop(long)
@ stub NtUserGetThreadState
@ stub NtUserGetTitleBarInfo
diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h
index 5a0787afca7..c40d2cb2a6f 100644
--- a/dlls/win32u/win32u_private.h
+++ b/dlls/win32u/win32u_private.h
@@ -238,6 +238,7 @@ struct unix_funcs
BOOL (WINAPI *pNtUserGetMessage)( MSG *msg, HWND hwnd, UINT first, UINT last );
INT (WINAPI *pNtUserGetPriorityClipboardFormat)( UINT *list, INT count );
DWORD (WINAPI *pNtUserGetQueueStatus)( UINT flags );
+ HMENU (WINAPI *pNtUserGetSystemMenu)( HWND hwnd, BOOL revert );
BOOL (WINAPI *pNtUserGetUpdateRect)( HWND hwnd, RECT *rect, BOOL erase );
INT (WINAPI *pNtUserGetUpdateRgn)( HWND hwnd, HRGN hrgn, BOOL erase );
BOOL (WINAPI *pNtUserGetUpdatedClipboardFormats)( UINT *formats, UINT size, UINT *out_size );
diff --git a/dlls/win32u/wrappers.c b/dlls/win32u/wrappers.c
index 9a87bccbb7a..e3e0781bdde 100644
--- a/dlls/win32u/wrappers.c
+++ b/dlls/win32u/wrappers.c
@@ -951,6 +951,12 @@ BOOL WINAPI NtUserGetMessage( MSG *msg, HWND hwnd, UINT first, UINT last )
return unix_funcs->pNtUserGetMessage( msg, hwnd, first, last );
}
+HMENU WINAPI NtUserGetSystemMenu( HWND hwnd, BOOL revert )
+{
+ if (!unix_funcs) return 0;
+ return unix_funcs->pNtUserGetSystemMenu( hwnd, revert );
+}
+
BOOL WINAPI NtUserGetUpdateRect( HWND hwnd, RECT *rect, BOOL erase )
{
if (!unix_funcs) return FALSE;
diff --git a/include/ntuser.h b/include/ntuser.h
index dfa9f53a187..d11cffb8950 100644
--- a/include/ntuser.h
+++ b/include/ntuser.h
@@ -557,6 +557,7 @@ HANDLE WINAPI NtUserGetProp( HWND hwnd, const WCHAR *str );
ULONG WINAPI NtUserGetProcessDpiAwarenessContext( HANDLE process );
DWORD WINAPI NtUserGetQueueStatus( UINT flags );
ULONG WINAPI NtUserGetSystemDpiForProcess( HANDLE process );
+HMENU WINAPI NtUserGetSystemMenu( HWND hwnd, BOOL revert );
HDESK WINAPI NtUserGetThreadDesktop( DWORD thread );
INT WINAPI NtUserGetUpdateRgn( HWND hwnd, HRGN hrgn, BOOL erase );
BOOL WINAPI NtUserGetUpdatedClipboardFormats( UINT *formats, UINT size, UINT *out_size );
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/18
May 2, 2022
[PATCH 10/13] win32u: Move NtUserDeleteMenu implementation from user32.
by Jacek Caban
From: Jacek Caban <jacek(a)codeweavers.com>
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
---
dlls/user32/mdi.c | 6 +++---
dlls/user32/menu.c | 26 +++-----------------------
dlls/user32/user32.spec | 2 +-
dlls/win32u/menu.c | 19 +++++++++++++++++++
dlls/win32u/syscall.c | 1 +
dlls/win32u/win32u.spec | 2 +-
dlls/wow64win/syscall.h | 1 +
dlls/wow64win/user.c | 9 +++++++++
include/ntuser.h | 1 +
9 files changed, 39 insertions(+), 28 deletions(-)
diff --git a/dlls/user32/mdi.c b/dlls/user32/mdi.c
index b856f054247..1b06143d4cf 100644
--- a/dlls/user32/mdi.c
+++ b/dlls/user32/mdi.c
@@ -945,11 +945,11 @@ static BOOL MDI_RestoreFrameMenu( HWND frame, HWND hChild )
}
/* close */
- DeleteMenu(menu, SC_CLOSE, MF_BYCOMMAND);
+ NtUserDeleteMenu( menu, SC_CLOSE, MF_BYCOMMAND );
/* restore */
- DeleteMenu(menu, SC_RESTORE, MF_BYCOMMAND);
+ NtUserDeleteMenu( menu, SC_RESTORE, MF_BYCOMMAND );
/* minimize */
- DeleteMenu(menu, SC_MINIMIZE, MF_BYCOMMAND);
+ NtUserDeleteMenu( menu, SC_MINIMIZE, MF_BYCOMMAND );
DrawMenuBar(frame);
diff --git a/dlls/user32/menu.c b/dlls/user32/menu.c
index 669d838bf61..761718182b5 100644
--- a/dlls/user32/menu.c
+++ b/dlls/user32/menu.c
@@ -410,7 +410,7 @@ static HMENU MENU_GetSysMenu( HWND hWnd, HMENU hPopupMenu )
if (hPopupMenu)
{
if (GetClassLongW(hWnd, GCL_STYLE) & CS_NOCLOSE)
- DeleteMenu(hPopupMenu, SC_CLOSE, MF_BYCOMMAND);
+ NtUserDeleteMenu( hPopupMenu, SC_CLOSE, MF_BYCOMMAND );
InsertMenuW( hMenu, -1, MF_SYSMENU | MF_POPUP | MF_BYPOSITION,
(UINT_PTR)hPopupMenu, NULL );
@@ -3540,7 +3540,7 @@ BOOL WINAPI ChangeMenuA( HMENU hMenu, UINT pos, LPCSTR data,
TRACE("menu=%p pos=%d data=%p id=%08x flags=%08x\n", hMenu, pos, data, id, flags );
if (flags & MF_APPEND) return AppendMenuA( hMenu, flags & ~MF_APPEND,
id, data );
- if (flags & MF_DELETE) return DeleteMenu(hMenu, pos, flags & ~MF_DELETE);
+ if (flags & MF_DELETE) return NtUserDeleteMenu( hMenu, pos, flags & ~MF_DELETE );
if (flags & MF_CHANGE) return ModifyMenuA(hMenu, pos, flags & ~MF_CHANGE,
id, data );
if (flags & MF_REMOVE) return NtUserRemoveMenu( hMenu,
@@ -3560,7 +3560,7 @@ BOOL WINAPI ChangeMenuW( HMENU hMenu, UINT pos, LPCWSTR data,
TRACE("menu=%p pos=%d data=%p id=%08x flags=%08x\n", hMenu, pos, data, id, flags );
if (flags & MF_APPEND) return AppendMenuW( hMenu, flags & ~MF_APPEND,
id, data );
- if (flags & MF_DELETE) return DeleteMenu(hMenu, pos, flags & ~MF_DELETE);
+ if (flags & MF_DELETE) return NtUserDeleteMenu( hMenu, pos, flags & ~MF_DELETE );
if (flags & MF_CHANGE) return ModifyMenuW(hMenu, pos, flags & ~MF_CHANGE,
id, data );
if (flags & MF_REMOVE) return NtUserRemoveMenu( hMenu,
@@ -3825,26 +3825,6 @@ BOOL WINAPI AppendMenuW( HMENU hMenu, UINT flags,
}
-/**********************************************************************
- * DeleteMenu (USER32.@)
- */
-BOOL WINAPI DeleteMenu( HMENU hMenu, UINT id, UINT flags )
-{
- POPUPMENU *menu;
- UINT pos;
-
- if (!(menu = find_menu_item(hMenu, id, flags, &pos)))
- return FALSE;
-
- if (menu->items[pos].fType & MF_POPUP)
- NtUserDestroyMenu( menu->items[pos].hSubMenu );
-
- NtUserRemoveMenu( menu->obj.handle, pos, flags | MF_BYPOSITION );
- release_menu_ptr(menu);
- return TRUE;
-}
-
-
/*******************************************************************
* ModifyMenuW (USER32.@)
*/
diff --git a/dlls/user32/user32.spec b/dlls/user32/user32.spec
index 26f2d1caf45..0697bcfa841 100644
--- a/dlls/user32/user32.spec
+++ b/dlls/user32/user32.spec
@@ -153,7 +153,7 @@
@ stdcall DefWindowProcA(long long long long)
@ stdcall DefWindowProcW(long long long long)
@ stdcall DeferWindowPos(long long long long long long long long)
-@ stdcall DeleteMenu(long long long)
+@ stdcall DeleteMenu(long long long) NtUserDeleteMenu
@ stdcall DeregisterShellHookWindow (long)
@ stdcall DestroyAcceleratorTable(long) NtUserDestroyAcceleratorTable
@ stdcall DestroyCaret()
diff --git a/dlls/win32u/menu.c b/dlls/win32u/menu.c
index d41aba956f2..67abac37037 100644
--- a/dlls/win32u/menu.c
+++ b/dlls/win32u/menu.c
@@ -976,6 +976,25 @@ BOOL WINAPI NtUserRemoveMenu( HMENU handle, UINT id, UINT flags )
return TRUE;
}
+/**********************************************************************
+ * NtUserDeleteMenu (win32u.@)
+ */
+BOOL WINAPI NtUserDeleteMenu( HMENU handle, UINT id, UINT flags )
+{
+ POPUPMENU *menu;
+ UINT pos;
+
+ if (!(menu = find_menu_item( handle, id, flags, &pos )))
+ return FALSE;
+
+ if (menu->items[pos].fType & MF_POPUP)
+ NtUserDestroyMenu( menu->items[pos].hSubMenu );
+
+ NtUserRemoveMenu( menu->obj.handle, pos, flags | MF_BYPOSITION );
+ release_menu_ptr( menu );
+ return TRUE;
+}
+
/**********************************************************************
* NtUserSetMenuContextHelpId (win32u.@)
*/
diff --git a/dlls/win32u/syscall.c b/dlls/win32u/syscall.c
index f585e90bd4a..488056ef439 100644
--- a/dlls/win32u/syscall.c
+++ b/dlls/win32u/syscall.c
@@ -114,6 +114,7 @@ static void * const syscalls[] =
NtUserCreateAcceleratorTable,
NtUserCreateDesktopEx,
NtUserCreateWindowStation,
+ NtUserDeleteMenu,
NtUserDestroyAcceleratorTable,
NtUserFindExistingCursorIcon,
NtUserFindWindowEx,
diff --git a/dlls/win32u/win32u.spec b/dlls/win32u/win32u.spec
index 483b3d52289..43db8421bb8 100644
--- a/dlls/win32u/win32u.spec
+++ b/dlls/win32u/win32u.spec
@@ -824,7 +824,7 @@
@ stdcall NtUserDeferWindowPosAndBand(long long long long long long long long long long)
@ stub NtUserDelegateCapturePointers
@ stub NtUserDelegateInput
-@ stub NtUserDeleteMenu
+@ stdcall -syscall NtUserDeleteMenu(long long long)
@ stub NtUserDeleteWindowGroup
@ stdcall -syscall NtUserDestroyAcceleratorTable(long)
@ stub NtUserDestroyActivationGroup
diff --git a/dlls/wow64win/syscall.h b/dlls/wow64win/syscall.h
index 776a7e671f6..27ba163408b 100644
--- a/dlls/wow64win/syscall.h
+++ b/dlls/wow64win/syscall.h
@@ -101,6 +101,7 @@
SYSCALL_ENTRY( NtUserCreateAcceleratorTable ) \
SYSCALL_ENTRY( NtUserCreateDesktopEx ) \
SYSCALL_ENTRY( NtUserCreateWindowStation ) \
+ SYSCALL_ENTRY( NtUserDeleteMenu ) \
SYSCALL_ENTRY( NtUserDestroyAcceleratorTable ) \
SYSCALL_ENTRY( NtUserFindExistingCursorIcon ) \
SYSCALL_ENTRY( NtUserFindWindowEx ) \
diff --git a/dlls/wow64win/user.c b/dlls/wow64win/user.c
index 1f287c7631c..d90c4ec2f99 100644
--- a/dlls/wow64win/user.c
+++ b/dlls/wow64win/user.c
@@ -669,6 +669,15 @@ NTSTATUS WINAPI wow64_NtUserCheckMenuItem( UINT *args )
return NtUserCheckMenuItem( handle, id, flags );
}
+NTSTATUS WINAPI wow64_NtUserDeleteMenu( UINT *args )
+{
+ HMENU menu = get_handle( &args );
+ UINT id = get_ulong( &args );
+ UINT flags = get_ulong( &args );
+
+ return NtUserDeleteMenu( menu, id, flags );
+}
+
NTSTATUS WINAPI wow64_NtUserGetMenuItemRect( UINT *args )
{
HWND hwnd = get_handle( &args );
diff --git a/include/ntuser.h b/include/ntuser.h
index 1876b32c84b..dfa9f53a187 100644
--- a/include/ntuser.h
+++ b/include/ntuser.h
@@ -487,6 +487,7 @@ HWINSTA WINAPI NtUserCreateWindowStation( OBJECT_ATTRIBUTES *attr, ACCESS_MASK m
ULONG arg4, ULONG arg5, ULONG arg6, ULONG arg7 );
HDWP WINAPI NtUserDeferWindowPosAndBand( HDWP hdwp, HWND hwnd, HWND after, INT x, INT y,
INT cx, INT cy, UINT flags, UINT unk1, UINT unk2 );
+BOOL WINAPI NtUserDeleteMenu( HMENU menu, UINT id, UINT flags );
BOOL WINAPI NtUserDestroyAcceleratorTable( HACCEL handle );
BOOL WINAPI NtUserDestroyCursor( HCURSOR cursor, ULONG arg );
BOOL WINAPI NtUserDestroyMenu( HMENU menu );
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/18
May 2, 2022
[PATCH 09/13] win32u: Move NtUserTranslateAccelerator from user32.
by Jacek Caban
From: Jacek Caban <jacek(a)codeweavers.com>
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
---
dlls/user32/menu.c | 204 +------------------------
dlls/user32/user32.spec | 2 +-
dlls/win32u/gdiobj.c | 1 +
dlls/win32u/menu.c | 279 +++++++++++++++++++++++++++++++++++
dlls/win32u/win32u.spec | 2 +-
dlls/win32u/win32u_private.h | 1 +
dlls/win32u/wrappers.c | 6 +
7 files changed, 291 insertions(+), 204 deletions(-)
diff --git a/dlls/user32/menu.c b/dlls/user32/menu.c
index 9f51fa555f8..669d838bf61 100644
--- a/dlls/user32/menu.c
+++ b/dlls/user32/menu.c
@@ -56,7 +56,6 @@
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(menu);
-WINE_DECLARE_DEBUG_CHANNEL(accel);
/* internal flags for menu tracking */
@@ -4768,170 +4767,6 @@ DWORD WINAPI CalcMenuBar(HWND hwnd, DWORD left, DWORD right, DWORD top, RECT *re
}
-/**********************************************************************
- * translate_accelerator
- */
-static BOOL translate_accelerator( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam,
- BYTE fVirt, WORD key, WORD cmd )
-{
- INT mask = 0;
- UINT mesg = 0;
-
- if (wParam != key) return FALSE;
-
- if (NtUserGetKeyState(VK_CONTROL) & 0x8000) mask |= FCONTROL;
- if (NtUserGetKeyState(VK_MENU) & 0x8000) mask |= FALT;
- if (NtUserGetKeyState(VK_SHIFT) & 0x8000) mask |= FSHIFT;
-
- if (message == WM_CHAR || message == WM_SYSCHAR)
- {
- if ( !(fVirt & FVIRTKEY) && (mask & FALT) == (fVirt & FALT) )
- {
- TRACE_(accel)("found accel for WM_CHAR: ('%c')\n", LOWORD(wParam) & 0xff);
- goto found;
- }
- }
- else
- {
- if(fVirt & FVIRTKEY)
- {
- TRACE_(accel)("found accel for virt_key %04lx (scan %04x)\n",
- wParam, 0xff & HIWORD(lParam));
-
- if(mask == (fVirt & (FSHIFT | FCONTROL | FALT))) goto found;
- TRACE_(accel)(", but incorrect SHIFT/CTRL/ALT-state\n");
- }
- else
- {
- if (!(lParam & 0x01000000)) /* no special_key */
- {
- if ((fVirt & FALT) && (lParam & 0x20000000))
- { /* ^^ ALT pressed */
- TRACE_(accel)("found accel for Alt-%c\n", LOWORD(wParam) & 0xff);
- goto found;
- }
- }
- }
- }
- return FALSE;
-
- found:
- if (message == WM_KEYUP || message == WM_SYSKEYUP)
- mesg = 1;
- else
- {
- HMENU hMenu, hSubMenu, hSysMenu;
- UINT uSysStat = (UINT)-1, uStat = (UINT)-1, nPos;
- POPUPMENU *menu;
-
- hMenu = (GetWindowLongW( hWnd, GWL_STYLE ) & WS_CHILD) ? 0 : GetMenu(hWnd);
- hSysMenu = get_win_sys_menu( hWnd );
-
- /* find menu item and ask application to initialize it */
- /* 1. in the system menu */
- if ((menu = find_menu_item(hSysMenu, cmd, MF_BYCOMMAND, NULL)))
- {
- hSubMenu = menu->obj.handle;
- release_menu_ptr(menu);
-
- if (GetCapture())
- mesg = 2;
- if (!IsWindowEnabled(hWnd))
- mesg = 3;
- else
- {
- SendMessageW(hWnd, WM_INITMENU, (WPARAM)hSysMenu, 0L);
- if(hSubMenu != hSysMenu)
- {
- nPos = MENU_FindSubMenu(&hSysMenu, hSubMenu);
- TRACE_(accel)("hSysMenu = %p, hSubMenu = %p, nPos = %d\n", hSysMenu, hSubMenu, nPos);
- SendMessageW(hWnd, WM_INITMENUPOPUP, (WPARAM)hSubMenu, MAKELPARAM(nPos, TRUE));
- }
- uSysStat = GetMenuState(GetSubMenu(hSysMenu, 0), cmd, MF_BYCOMMAND);
- }
- }
- else /* 2. in the window's menu */
- {
- if ((menu = find_menu_item(hMenu, cmd, MF_BYCOMMAND, NULL)))
- {
- hSubMenu = menu->obj.handle;
- release_menu_ptr(menu);
-
- if (GetCapture())
- mesg = 2;
- if (!IsWindowEnabled(hWnd))
- mesg = 3;
- else
- {
- SendMessageW(hWnd, WM_INITMENU, (WPARAM)hMenu, 0L);
- if(hSubMenu != hMenu)
- {
- nPos = MENU_FindSubMenu(&hMenu, hSubMenu);
- TRACE_(accel)("hMenu = %p, hSubMenu = %p, nPos = %d\n", hMenu, hSubMenu, nPos);
- SendMessageW(hWnd, WM_INITMENUPOPUP, (WPARAM)hSubMenu, MAKELPARAM(nPos, FALSE));
- }
- uStat = GetMenuState(hMenu, cmd, MF_BYCOMMAND);
- }
- }
- }
-
- if (mesg == 0)
- {
- if (uSysStat != (UINT)-1)
- {
- if (uSysStat & (MF_DISABLED|MF_GRAYED))
- mesg=4;
- else
- mesg=WM_SYSCOMMAND;
- }
- else
- {
- if (uStat != (UINT)-1)
- {
- if (IsIconic(hWnd))
- mesg=5;
- else
- {
- if (uStat & (MF_DISABLED|MF_GRAYED))
- mesg=6;
- else
- mesg=WM_COMMAND;
- }
- }
- else
- mesg=WM_COMMAND;
- }
- }
- }
-
- if( mesg==WM_COMMAND )
- {
- TRACE_(accel)(", sending WM_COMMAND, wParam=%0x\n", 0x10000 | cmd);
- SendMessageW(hWnd, mesg, 0x10000 | cmd, 0L);
- }
- else if( mesg==WM_SYSCOMMAND )
- {
- TRACE_(accel)(", sending WM_SYSCOMMAND, wParam=%0x\n", cmd);
- SendMessageW(hWnd, mesg, cmd, 0x00010000L);
- }
- else
- {
- /* some reasons for NOT sending the WM_{SYS}COMMAND message:
- * #0: unknown (please report!)
- * #1: for WM_KEYUP,WM_SYSKEYUP
- * #2: mouse is captured
- * #3: window is disabled
- * #4: it's a disabled system menu option
- * #5: it's a menu option, but window is iconic
- * #6: it's a menu option, but disabled
- */
- TRACE_(accel)(", but won't send WM_{SYS}COMMAND, reason is #%d\n",mesg);
- if(mesg==0)
- ERR_(accel)(" unknown reason - please report!\n");
- }
- return TRUE;
-}
-
/**********************************************************************
* TranslateAcceleratorA (USER32.@)
* TranslateAccelerator (USER32.@)
@@ -4942,7 +4777,7 @@ INT WINAPI TranslateAcceleratorA( HWND hWnd, HACCEL hAccel, LPMSG msg )
{
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
- return TranslateAcceleratorW( hWnd, hAccel, msg );
+ return NtUserTranslateAccelerator( hWnd, hAccel, msg );
case WM_CHAR:
case WM_SYSCHAR:
@@ -4952,45 +4787,10 @@ INT WINAPI TranslateAcceleratorA( HWND hWnd, HACCEL hAccel, LPMSG msg )
WCHAR wch;
MultiByteToWideChar(CP_ACP, 0, &ch, 1, &wch, 1);
msgW.wParam = MAKEWPARAM(wch, HIWORD(msg->wParam));
- return TranslateAcceleratorW( hWnd, hAccel, &msgW );
+ return NtUserTranslateAccelerator( hWnd, hAccel, &msgW );
}
default:
return 0;
}
}
-
-/**********************************************************************
- * TranslateAcceleratorW (USER32.@)
- */
-INT WINAPI TranslateAcceleratorW( HWND hWnd, HACCEL hAccel, LPMSG msg )
-{
- ACCEL data[32], *ptr = data;
- int i, count;
-
- if (!hWnd) return 0;
-
- if (msg->message != WM_KEYDOWN &&
- msg->message != WM_SYSKEYDOWN &&
- msg->message != WM_CHAR &&
- msg->message != WM_SYSCHAR)
- return 0;
-
- TRACE_(accel)("hAccel %p, hWnd %p, msg->hwnd %p, msg->message %04x, wParam %08lx, lParam %08lx\n",
- hAccel,hWnd,msg->hwnd,msg->message,msg->wParam,msg->lParam);
-
- if (!(count = NtUserCopyAcceleratorTable( hAccel, NULL, 0 ))) return 0;
- if (count > ARRAY_SIZE( data ))
- {
- if (!(ptr = HeapAlloc( GetProcessHeap(), 0, count * sizeof(*ptr) ))) return 0;
- }
- count = NtUserCopyAcceleratorTable( hAccel, ptr, count );
- for (i = 0; i < count; i++)
- {
- if (translate_accelerator( hWnd, msg->message, msg->wParam, msg->lParam,
- ptr[i].fVirt, ptr[i].key, ptr[i].cmd))
- break;
- }
- if (ptr != data) HeapFree( GetProcessHeap(), 0, ptr );
- return (i < count);
-}
diff --git a/dlls/user32/user32.spec b/dlls/user32/user32.spec
index 298a0fa3150..26f2d1caf45 100644
--- a/dlls/user32/user32.spec
+++ b/dlls/user32/user32.spec
@@ -767,7 +767,7 @@
@ stdcall TrackPopupMenuEx(long long long long long ptr)
@ stdcall TranslateAccelerator(long long ptr) TranslateAcceleratorA
@ stdcall TranslateAcceleratorA(long long ptr)
-@ stdcall TranslateAcceleratorW(long long ptr)
+@ stdcall TranslateAcceleratorW(long long ptr) NtUserTranslateAccelerator
@ stdcall TranslateMDISysAccel(long ptr)
@ stdcall TranslateMessage(ptr)
# @ stub TranslateMessageEx
diff --git a/dlls/win32u/gdiobj.c b/dlls/win32u/gdiobj.c
index c5db1bfcc30..ad04ba7ff78 100644
--- a/dlls/win32u/gdiobj.c
+++ b/dlls/win32u/gdiobj.c
@@ -1224,6 +1224,7 @@ static struct unix_funcs unix_funcs =
NtUserSystemParametersInfoForDpi,
NtUserToUnicodeEx,
NtUserTrackMouseEvent,
+ NtUserTranslateAccelerator,
NtUserTranslateMessage,
NtUserUnregisterClass,
NtUserUnregisterHotKey,
diff --git a/dlls/win32u/menu.c b/dlls/win32u/menu.c
index 8544cca47b4..d41aba956f2 100644
--- a/dlls/win32u/menu.c
+++ b/dlls/win32u/menu.c
@@ -235,6 +235,23 @@ static BOOL is_menu( HMENU handle )
return is_menu;
}
+/***********************************************************************
+ * get_win_sys_menu
+ *
+ * Get the system menu of a window
+ */
+static HMENU get_win_sys_menu( HWND hwnd )
+{
+ HMENU ret = 0;
+ WND *win = get_win_ptr( hwnd );
+ if (win && win != WND_OTHER_PROCESS && win != WND_DESKTOP)
+ {
+ ret = win->hSysMenu;
+ release_win_ptr( win );
+ }
+ return ret;
+}
+
static POPUPMENU *find_menu_item( HMENU handle, UINT id, UINT flags, UINT *pos )
{
UINT fallback_pos = ~0u, i;
@@ -346,6 +363,48 @@ static BOOL is_win_menu_disallowed( HWND hwnd )
return (get_window_long(hwnd, GWL_STYLE) & (WS_CHILD | WS_POPUP)) == WS_CHILD;
}
+/***********************************************************************
+ * find_submenu
+ *
+ * Find a Sub menu. Return the position of the submenu, and modifies
+ * *hmenu in case it is found in another sub-menu.
+ * If the submenu cannot be found, NO_SELECTED_ITEM is returned.
+ */
+static UINT find_submenu( HMENU *handle_ptr, HMENU target )
+{
+ POPUPMENU *menu;
+ MENUITEM *item;
+ UINT i;
+
+ if (*handle_ptr == (HMENU)0xffff || !(menu = grab_menu_ptr( *handle_ptr )))
+ return NO_SELECTED_ITEM;
+
+ item = menu->items;
+ for (i = 0; i < menu->nItems; i++, item++)
+ {
+ if(!(item->fType & MF_POPUP)) continue;
+ if (item->hSubMenu == target)
+ {
+ release_menu_ptr( menu );
+ return i;
+ }
+ else
+ {
+ HMENU hsubmenu = item->hSubMenu;
+ UINT pos = find_submenu( &hsubmenu, target );
+ if (pos != NO_SELECTED_ITEM)
+ {
+ *handle_ptr = hsubmenu;
+ release_menu_ptr( menu );
+ return pos;
+ }
+ }
+ }
+
+ release_menu_ptr( menu );
+ return NO_SELECTED_ITEM;
+}
+
/* see GetMenu */
HMENU get_menu( HWND hwnd )
{
@@ -932,6 +991,25 @@ BOOL WINAPI NtUserSetMenuContextHelpId( HMENU handle, DWORD id )
return TRUE;
}
+/* see GetSubMenu */
+static HMENU get_sub_menu( HMENU handle, INT pos )
+{
+ POPUPMENU *menu;
+ HMENU submenu;
+ UINT i;
+
+ if (!(menu = find_menu_item( handle, pos, MF_BYPOSITION, &i )))
+ return 0;
+
+ if (menu->items[i].fType & MF_POPUP)
+ submenu = menu->items[i].hSubMenu;
+ else
+ submenu = 0;
+
+ release_menu_ptr(menu);
+ return submenu;
+}
+
/**********************************************************************
* NtUserSetMenuDefaultItem (win32u.@)
*/
@@ -979,3 +1057,204 @@ BOOL WINAPI NtUserSetMenuDefaultItem( HMENU handle, UINT item, UINT bypos )
release_menu_ptr( menu );
return ret;
}
+
+/**********************************************************************
+ * translate_accelerator
+ */
+static BOOL translate_accelerator( HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam,
+ BYTE virt, WORD key, WORD cmd )
+{
+ INT mask = 0;
+ UINT msg = 0;
+
+ if (wparam != key) return FALSE;
+
+ if (NtUserGetKeyState( VK_CONTROL ) & 0x8000) mask |= FCONTROL;
+ if (NtUserGetKeyState( VK_MENU ) & 0x8000) mask |= FALT;
+ if (NtUserGetKeyState( VK_SHIFT ) & 0x8000) mask |= FSHIFT;
+
+ if (message == WM_CHAR || message == WM_SYSCHAR)
+ {
+ if (!(virt & FVIRTKEY) && (mask & FALT) == (virt & FALT))
+ {
+ TRACE_(accel)( "found accel for WM_CHAR: ('%c')\n", LOWORD(wparam) & 0xff );
+ goto found;
+ }
+ }
+ else
+ {
+ if (virt & FVIRTKEY)
+ {
+ TRACE_(accel)( "found accel for virt_key %04lx (scan %04x)\n",
+ wparam, 0xff & HIWORD(lparam) );
+
+ if (mask == (virt & (FSHIFT | FCONTROL | FALT))) goto found;
+ TRACE_(accel)( ", but incorrect SHIFT/CTRL/ALT-state\n" );
+ }
+ else
+ {
+ if (!(lparam & 0x01000000)) /* no special_key */
+ {
+ if ((virt & FALT) && (lparam & 0x20000000)) /* ALT pressed */
+ {
+ TRACE_(accel)( "found accel for Alt-%c\n", LOWORD(wparam) & 0xff );
+ goto found;
+ }
+ }
+ }
+ }
+ return FALSE;
+
+found:
+ if (message == WM_KEYUP || message == WM_SYSKEYUP)
+ msg = 1;
+ else
+ {
+ HMENU menu_handle, submenu, sys_menu;
+ UINT sys_stat = ~0u, stat = ~0u, pos;
+ POPUPMENU *menu;
+
+ menu_handle = (get_window_long( hwnd, GWL_STYLE ) & WS_CHILD) ? 0 : get_menu(hwnd);
+ sys_menu = get_win_sys_menu( hwnd );
+
+ /* find menu item and ask application to initialize it */
+ /* 1. in the system menu */
+ if ((menu = find_menu_item( sys_menu, cmd, MF_BYCOMMAND, NULL )))
+ {
+ submenu = menu->obj.handle;
+ release_menu_ptr( menu );
+
+ if (get_capture())
+ msg = 2;
+ if (!is_window_enabled( hwnd ))
+ msg = 3;
+ else
+ {
+ send_message( hwnd, WM_INITMENU, (WPARAM)sys_menu, 0 );
+ if (submenu != sys_menu)
+ {
+ pos = find_submenu( &sys_menu, submenu );
+ TRACE_(accel)( "sys_menu = %p, submenu = %p, pos = %d\n",
+ sys_menu, submenu, pos );
+ send_message( hwnd, WM_INITMENUPOPUP, (WPARAM)submenu, MAKELPARAM(pos, TRUE) );
+ }
+ sys_stat = get_menu_state( get_sub_menu( sys_menu, 0 ), cmd, MF_BYCOMMAND );
+ }
+ }
+ else /* 2. in the window's menu */
+ {
+ if ((menu = find_menu_item( menu_handle, cmd, MF_BYCOMMAND, NULL )))
+ {
+ submenu = menu->obj.handle;
+ release_menu_ptr( menu );
+
+ if (get_capture())
+ msg = 2;
+ if (!is_window_enabled( hwnd ))
+ msg = 3;
+ else
+ {
+ send_message( hwnd, WM_INITMENU, (WPARAM)menu_handle, 0 );
+ if(submenu != menu_handle)
+ {
+ pos = find_submenu( &menu_handle, submenu );
+ TRACE_(accel)( "menu_handle = %p, submenu = %p, pos = %d\n",
+ menu_handle, submenu, pos );
+ send_message( hwnd, WM_INITMENUPOPUP, (WPARAM)submenu,
+ MAKELPARAM(pos, FALSE) );
+ }
+ stat = get_menu_state( menu_handle, cmd, MF_BYCOMMAND );
+ }
+ }
+ }
+
+ if (msg == 0)
+ {
+ if (sys_stat != ~0u)
+ {
+ if (sys_stat & (MF_DISABLED|MF_GRAYED))
+ msg = 4;
+ else
+ msg = WM_SYSCOMMAND;
+ }
+ else
+ {
+ if (stat != ~0u)
+ {
+ if (is_iconic( hwnd ))
+ msg = 5;
+ else
+ {
+ if (stat & (MF_DISABLED|MF_GRAYED))
+ msg = 6;
+ else
+ msg = WM_COMMAND;
+ }
+ }
+ else
+ msg = WM_COMMAND;
+ }
+ }
+ }
+
+ if (msg == WM_COMMAND)
+ {
+ TRACE_(accel)( ", sending WM_COMMAND, wparam=%0x\n", 0x10000 | cmd );
+ send_message( hwnd, msg, 0x10000 | cmd, 0 );
+ }
+ else if (msg == WM_SYSCOMMAND)
+ {
+ TRACE_(accel)( ", sending WM_SYSCOMMAND, wparam=%0x\n", cmd );
+ send_message( hwnd, msg, cmd, 0x00010000 );
+ }
+ else
+ {
+ /* some reasons for NOT sending the WM_{SYS}COMMAND message:
+ * #0: unknown (please report!)
+ * #1: for WM_KEYUP,WM_SYSKEYUP
+ * #2: mouse is captured
+ * #3: window is disabled
+ * #4: it's a disabled system menu option
+ * #5: it's a menu option, but window is iconic
+ * #6: it's a menu option, but disabled
+ */
+ TRACE_(accel)( ", but won't send WM_{SYS}COMMAND, reason is #%d\n", msg );
+ if (!msg) ERR_(accel)( " unknown reason\n" );
+ }
+ return TRUE;
+}
+
+/**********************************************************************
+ * NtUserTranslateAccelerator (win32u.@)
+ */
+INT WINAPI NtUserTranslateAccelerator( HWND hwnd, HACCEL accel, MSG *msg )
+{
+ ACCEL data[32], *ptr = data;
+ int i, count;
+
+ if (!hwnd) return 0;
+
+ if (msg->message != WM_KEYDOWN &&
+ msg->message != WM_SYSKEYDOWN &&
+ msg->message != WM_CHAR &&
+ msg->message != WM_SYSCHAR)
+ return 0;
+
+ TRACE_(accel)("accel %p, hwnd %p, msg->hwnd %p, msg->message %04x, wParam %08lx, lParam %08lx\n",
+ accel,hwnd,msg->hwnd,msg->message,msg->wParam,msg->lParam);
+
+ if (!(count = NtUserCopyAcceleratorTable( accel, NULL, 0 ))) return 0;
+ if (count > ARRAY_SIZE( data ))
+ {
+ if (!(ptr = malloc( count * sizeof(*ptr) ))) return 0;
+ }
+ count = NtUserCopyAcceleratorTable( accel, ptr, count );
+ for (i = 0; i < count; i++)
+ {
+ if (translate_accelerator( hwnd, msg->message, msg->wParam, msg->lParam,
+ ptr[i].fVirt, ptr[i].key, ptr[i].cmd))
+ break;
+ }
+ if (ptr != data) free( ptr );
+ return (i < count);
+}
diff --git a/dlls/win32u/win32u.spec b/dlls/win32u/win32u.spec
index 07da23f633a..483b3d52289 100644
--- a/dlls/win32u/win32u.spec
+++ b/dlls/win32u/win32u.spec
@@ -1281,7 +1281,7 @@
@ stub NtUserTrackPopupMenuEx
@ stub NtUserTransformPoint
@ stub NtUserTransformRect
-@ stub NtUserTranslateAccelerator
+@ stdcall NtUserTranslateAccelerator(long long ptr)
@ stdcall NtUserTranslateMessage(ptr long)
@ stub NtUserUndelegateInput
@ stdcall -syscall NtUserUnhookWinEvent(long)
diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h
index 537eec38a34..5a0787afca7 100644
--- a/dlls/win32u/win32u_private.h
+++ b/dlls/win32u/win32u_private.h
@@ -296,6 +296,7 @@ struct unix_funcs
INT (WINAPI *pNtUserToUnicodeEx)( UINT virt, UINT scan, const BYTE *state,
WCHAR *str, int size, UINT flags, HKL layout );
BOOL (WINAPI *pNtUserTrackMouseEvent)( TRACKMOUSEEVENT *info );
+ INT (WINAPI *pNtUserTranslateAccelerator)( HWND hwnd, HACCEL accel, MSG *msg );
BOOL (WINAPI *pNtUserTranslateMessage)( const MSG *msg, UINT flags );
BOOL (WINAPI *pNtUserUnregisterClass)( UNICODE_STRING *name, HINSTANCE instance,
struct client_menu_name *client_menu_name );
diff --git a/dlls/win32u/wrappers.c b/dlls/win32u/wrappers.c
index 05107352dfa..9a87bccbb7a 100644
--- a/dlls/win32u/wrappers.c
+++ b/dlls/win32u/wrappers.c
@@ -1258,6 +1258,12 @@ BOOL WINAPI NtUserTrackMouseEvent( TRACKMOUSEEVENT *info )
return unix_funcs->pNtUserTrackMouseEvent( info );
}
+INT WINAPI NtUserTranslateAccelerator( HWND hwnd, HACCEL accel, MSG *msg )
+{
+ if (!unix_funcs) return 0;
+ return unix_funcs->pNtUserTranslateAccelerator( hwnd, accel, msg );
+}
+
BOOL WINAPI NtUserTranslateMessage( const MSG *msg, UINT flags )
{
if (!unix_funcs) return 0;
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/18
May 2, 2022
[PATCH 08/13] win32u: Move GetMenuItemCount implementation from user32.
by Jacek Caban
From: Jacek Caban <jacek(a)codeweavers.com>
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
---
dlls/user32/menu.c | 12 ++----------
dlls/win32u/menu.c | 14 ++++++++++++++
dlls/win32u/sysparams.c | 3 +++
dlls/win32u/win32u_private.h | 1 +
include/ntuser.h | 6 ++++++
5 files changed, 26 insertions(+), 10 deletions(-)
diff --git a/dlls/user32/menu.c b/dlls/user32/menu.c
index e81fc086918..9f51fa555f8 100644
--- a/dlls/user32/menu.c
+++ b/dlls/user32/menu.c
@@ -3696,17 +3696,9 @@ UINT WINAPI GetMenuState( HMENU menu, UINT item, UINT flags )
/**********************************************************************
* GetMenuItemCount (USER32.@)
*/
-INT WINAPI GetMenuItemCount( HMENU hMenu )
+INT WINAPI GetMenuItemCount( HMENU menu )
{
- POPUPMENU *menu = grab_menu_ptr(hMenu);
- INT count;
-
- if (!menu) return -1;
- count = menu->nItems;
- release_menu_ptr(menu);
-
- TRACE("(%p) returning %d\n", hMenu, count);
- return count;
+ return NtUserGetMenuItemCount( menu );
}
diff --git a/dlls/win32u/menu.c b/dlls/win32u/menu.c
index 0f918a4762d..8544cca47b4 100644
--- a/dlls/win32u/menu.c
+++ b/dlls/win32u/menu.c
@@ -864,6 +864,20 @@ UINT WINAPI NtUserThunkedMenuItemInfo( HMENU handle, UINT pos, UINT flags, UINT
return ret;
}
+/* see GetMenuItemCount */
+INT get_menu_item_count( HMENU handle )
+{
+ POPUPMENU *menu;
+ INT count;
+
+ if (!(menu = grab_menu_ptr( handle ))) return -1;
+ count = menu->nItems;
+ release_menu_ptr(menu);
+
+ TRACE( "(%p) returning %d\n", handle, count );
+ return count;
+}
+
/**********************************************************************
* NtUserRemoveMenu (win32u.@)
*/
diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c
index 3cf03d68399..114016954aa 100644
--- a/dlls/win32u/sysparams.c
+++ b/dlls/win32u/sysparams.c
@@ -4718,6 +4718,9 @@ ULONG_PTR WINAPI NtUserCallOneParam( ULONG_PTR arg, ULONG code )
case NtUserCallOneParam_GetIconParam:
return get_icon_param( UlongToHandle(arg) );
+ case NtUserCallOneParam_GetMenuItemCount:
+ return get_menu_item_count( UlongToHandle(arg) );
+
case NtUserCallOneParam_GetSysColor:
return get_sys_color( arg );
diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h
index caf77590559..537eec38a34 100644
--- a/dlls/win32u/win32u_private.h
+++ b/dlls/win32u/win32u_private.h
@@ -377,6 +377,7 @@ extern HMENU create_menu( BOOL is_popup ) DECLSPEC_HIDDEN;
extern BOOL draw_menu_bar( HWND hwnd ) DECLSPEC_HIDDEN;
extern HMENU get_menu( HWND hwnd ) DECLSPEC_HIDDEN;
extern BOOL get_menu_info( HMENU handle, MENUINFO *info ) DECLSPEC_HIDDEN;
+extern INT get_menu_item_count( HMENU handle ) DECLSPEC_HIDDEN;
extern BOOL set_window_menu( HWND hwnd, HMENU handle ) DECLSPEC_HIDDEN;
/* message.c */
diff --git a/include/ntuser.h b/include/ntuser.h
index 75c16e412c0..1876b32c84b 100644
--- a/include/ntuser.h
+++ b/include/ntuser.h
@@ -704,6 +704,7 @@ enum
NtUserCallOneParam_GetClipCursor,
NtUserCallOneParam_GetCursorPos,
NtUserCallOneParam_GetIconParam,
+ NtUserCallOneParam_GetMenuItemCount,
NtUserCallOneParam_GetPrimaryMonitorRect,
NtUserCallOneParam_GetSysColor,
NtUserCallOneParam_GetSysColorBrush,
@@ -773,6 +774,11 @@ static inline UINT_PTR NtUserGetIconParam( HICON icon )
return NtUserCallOneParam( HandleToUlong(icon), NtUserCallOneParam_GetIconParam );
}
+static inline UINT_PTR NtUserGetMenuItemCount( HMENU menu )
+{
+ return NtUserCallOneParam( HandleToUlong(menu), NtUserCallOneParam_GetMenuItemCount );
+}
+
static inline RECT NtUserGetPrimaryMonitorRect(void)
{
RECT primary;
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/18
May 2, 2022
[PATCH 07/13] win32u: Move GetMenuState implementation from user32.
by Jacek Caban
From: Jacek Caban <jacek(a)codeweavers.com>
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
---
dlls/user32/menu.c | 32 ++------------------------------
dlls/win32u/menu.c | 34 ++++++++++++++++++++++++++++++++++
include/ntuser.h | 2 ++
3 files changed, 38 insertions(+), 30 deletions(-)
diff --git a/dlls/user32/menu.c b/dlls/user32/menu.c
index 5101a095966..e81fc086918 100644
--- a/dlls/user32/menu.c
+++ b/dlls/user32/menu.c
@@ -3687,37 +3687,9 @@ BOOL WINAPI HiliteMenuItem( HWND hWnd, HMENU hMenu, UINT wItemID,
/**********************************************************************
* GetMenuState (USER32.@)
*/
-UINT WINAPI GetMenuState( HMENU hMenu, UINT wItemID, UINT wFlags )
+UINT WINAPI GetMenuState( HMENU menu, UINT item, UINT flags )
{
- POPUPMENU *menu;
- UINT state, pos;
- MENUITEM *item;
-
- TRACE("(menu=%p, id=%04x, flags=%04x);\n", hMenu, wItemID, wFlags);
-
- if (!(menu = find_menu_item(hMenu, wItemID, wFlags, &pos)))
- return -1;
-
- item = &menu->items[pos];
- debug_print_menuitem (" item: ", item, "");
- if (item->fType & MF_POPUP)
- {
- POPUPMENU *submenu = grab_menu_ptr(item->hSubMenu);
- if (submenu)
- state = (submenu->nItems << 8) | ((item->fState | item->fType) & 0xff);
- else
- state = -1;
- release_menu_ptr(submenu);
- }
- else
- {
- /* We used to (from way back then) mask the result to 0xff. */
- /* I don't know why and it seems wrong as the documented */
- /* return flag MF_SEPARATOR is outside that mask. */
- state = (item->fType | item->fState);
- }
- release_menu_ptr(menu);
- return state;
+ return NtUserThunkedMenuItemInfo( menu, item, flags, NtUserGetMenuState, NULL, NULL );
}
diff --git a/dlls/win32u/menu.c b/dlls/win32u/menu.c
index 0d7127fb4c6..0f918a4762d 100644
--- a/dlls/win32u/menu.c
+++ b/dlls/win32u/menu.c
@@ -772,6 +772,37 @@ static BOOL set_menu_item_info( MENUITEM *menu, const MENUITEMINFOW *info )
return TRUE;
}
+/* see GetMenuState */
+static UINT get_menu_state( HMENU handle, UINT item_id, UINT flags )
+{
+ POPUPMENU *menu;
+ UINT state, pos;
+ MENUITEM *item;
+
+ TRACE( "(menu=%p, id=%04x, flags=%04x);\n", handle, item_id, flags );
+
+ if (!(menu = find_menu_item( handle, item_id, flags, &pos )))
+ return -1;
+
+ item = &menu->items[pos];
+ TRACE( " item: %s\n", debugstr_menuitem( item ));
+ if (item->fType & MF_POPUP)
+ {
+ POPUPMENU *submenu = grab_menu_ptr( item->hSubMenu );
+ if (submenu)
+ state = (submenu->nItems << 8) | ((item->fState | item->fType) & 0xff);
+ else
+ state = -1;
+ release_menu_ptr( submenu );
+ }
+ else
+ {
+ state = item->fType | item->fState;
+ }
+ release_menu_ptr(menu);
+ return state;
+}
+
/**********************************************************************
* NtUserThunkedMenuItemInfo (win32u.@)
*/
@@ -822,6 +853,9 @@ UINT WINAPI NtUserThunkedMenuItemInfo( HMENU handle, UINT pos, UINT flags, UINT
release_menu_ptr(menu);
break;
+ case NtUserGetMenuState:
+ return get_menu_state( handle, pos, flags );
+
default:
FIXME( "unsupported method %u\n", method );
return FALSE;
diff --git a/include/ntuser.h b/include/ntuser.h
index 75b9ba7b73c..75c16e412c0 100644
--- a/include/ntuser.h
+++ b/include/ntuser.h
@@ -183,6 +183,8 @@ enum
{
NtUserSetMenuItemInfo,
NtUserInsertMenuItem,
+ /* Wine extensions */
+ NtUserGetMenuState,
};
struct send_message_timeout_params
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/18
May 2, 2022
[PATCH 06/13] win32u/tests: Add NtUserThunkedMenuItemInfo tests.
by Jacek Caban
From: Jacek Caban <jacek(a)codeweavers.com>
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
---
dlls/win32u/tests/win32u.c | 75 ++++++++++++++++++++++++++++++++++++++
1 file changed, 75 insertions(+)
diff --git a/dlls/win32u/tests/win32u.c b/dlls/win32u/tests/win32u.c
index 401913f0aee..03c143cc143 100644
--- a/dlls/win32u/tests/win32u.c
+++ b/dlls/win32u/tests/win32u.c
@@ -505,6 +505,80 @@ static void test_window_text(void)
DestroyWindow( hwnd );
}
+#define test_menu_item_id(a, b, c) test_menu_item_id_(a, b, c, __LINE__)
+static void test_menu_item_id_( HMENU menu, int pos, int expect, int line )
+{
+ MENUITEMINFOW item;
+ BOOL ret;
+
+ item.cbSize = sizeof(item);
+ item.fMask = MIIM_ID;
+ ret = GetMenuItemInfoW( menu, pos, TRUE, &item );
+ ok_(__FILE__,line)( ret, "GetMenuItemInfoW failed: %lu\n", GetLastError() );
+ ok_(__FILE__,line)( item.wID == expect, "got if %d, expected %d\n", item.wID, expect );
+}
+
+static void test_menu(void)
+{
+ MENUITEMINFOW item;
+ HMENU menu;
+ int count;
+ BOOL ret;
+
+ menu = CreateMenu();
+
+ memset( &item, 0, sizeof(item) );
+ item.cbSize = sizeof(item);
+ item.fMask = MIIM_ID;
+ item.wID = 10;
+ ret = NtUserThunkedMenuItemInfo( menu, 0, MF_BYPOSITION, NtUserInsertMenuItem, &item, NULL );
+ ok( ret, "InsertMenuItemW failed: %lu\n", GetLastError() );
+
+ count = GetMenuItemCount( menu );
+ ok( count == 1, "count = %d\n", count );
+
+ item.wID = 20;
+ ret = NtUserThunkedMenuItemInfo( menu, 1, MF_BYPOSITION, NtUserInsertMenuItem, &item, NULL );
+ ok( ret, "InsertMenuItemW failed: %lu\n", GetLastError() );
+
+ count = GetMenuItemCount( menu );
+ ok( count == 2, "count = %d\n", count );
+ test_menu_item_id( menu, 0, 10 );
+ test_menu_item_id( menu, 1, 20 );
+
+ item.wID = 30;
+ ret = NtUserThunkedMenuItemInfo( menu, 1, MF_BYPOSITION, NtUserInsertMenuItem, &item, NULL );
+ ok( ret, "InsertMenuItemW failed: %lu\n", GetLastError() );
+
+ count = GetMenuItemCount( menu );
+ ok( count == 3, "count = %d\n", count );
+ test_menu_item_id( menu, 0, 10 );
+ test_menu_item_id( menu, 1, 30 );
+ test_menu_item_id( menu, 2, 20 );
+
+ item.wID = 50;
+ ret = NtUserThunkedMenuItemInfo( menu, 10, 0, NtUserInsertMenuItem, &item, NULL );
+ ok( ret, "InsertMenuItemW failed: %lu\n", GetLastError() );
+
+ count = GetMenuItemCount( menu );
+ ok( count == 4, "count = %d\n", count );
+ test_menu_item_id( menu, 0, 50 );
+ test_menu_item_id( menu, 1, 10 );
+ test_menu_item_id( menu, 2, 30 );
+ test_menu_item_id( menu, 3, 20 );
+
+ item.wID = 60;
+ ret = NtUserThunkedMenuItemInfo( menu, 1, MF_BYPOSITION, NtUserSetMenuItemInfo, &item, NULL );
+ ok( ret, "InsertMenuItemW failed: %lu\n", GetLastError() );
+
+ count = GetMenuItemCount( menu );
+ ok( count == 4, "count = %d\n", count );
+ test_menu_item_id( menu, 1, 60 );
+
+ ret = NtUserDestroyMenu( menu );
+ ok( ret, "NtUserDestroyMenu failed: %lu\n", GetLastError() );
+}
+
START_TEST(win32u)
{
/* native win32u.dll fails if user32 is not loaded, so make sure it's fully initialized */
@@ -517,6 +591,7 @@ START_TEST(win32u)
test_cursoricon();
test_message_call();
test_window_text();
+ test_menu();
test_NtUserCloseWindowStation();
}
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/18
May 2, 2022
[PATCH 05/13] win32u: Move menu item info management from user32.
by Jacek Caban
From: Jacek Caban <jacek(a)codeweavers.com>
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
---
dlls/user32/controls.h | 1 -
dlls/user32/mdi.c | 4 +-
dlls/user32/menu.c | 324 ++------------------------------
dlls/user32/user32.spec | 2 +-
dlls/user32/user_main.c | 1 -
dlls/win32u/menu.c | 346 ++++++++++++++++++++++++++++++++++-
dlls/win32u/ntuser_private.h | 1 -
dlls/win32u/syscall.c | 2 +
dlls/win32u/win32u.spec | 4 +-
dlls/wow64win/syscall.h | 2 +
dlls/wow64win/user.c | 63 +++++++
include/ntuser.h | 10 +
12 files changed, 444 insertions(+), 316 deletions(-)
diff --git a/dlls/user32/controls.h b/dlls/user32/controls.h
index 5dcdd9bb935..6e6d7b7d214 100644
--- a/dlls/user32/controls.h
+++ b/dlls/user32/controls.h
@@ -120,7 +120,6 @@ extern void MENU_TrackMouseMenuBar( HWND hwnd, INT ht, POINT pt ) DECLSPEC_HIDDE
extern void MENU_TrackKbdMenuBar( HWND hwnd, UINT wParam, WCHAR wChar ) DECLSPEC_HIDDEN;
extern UINT MENU_DrawMenuBar( HDC hDC, LPRECT lprect, HWND hwnd ) DECLSPEC_HIDDEN;
extern void MENU_EndMenu(HWND) DECLSPEC_HIDDEN;
-extern void free_menu_items( void *ptr ) DECLSPEC_HIDDEN;
/* nonclient area */
extern LRESULT NC_HandleNCPaint( HWND hwnd , HRGN clip) DECLSPEC_HIDDEN;
diff --git a/dlls/user32/mdi.c b/dlls/user32/mdi.c
index df470f74762..b856f054247 100644
--- a/dlls/user32/mdi.c
+++ b/dlls/user32/mdi.c
@@ -417,7 +417,7 @@ static LRESULT MDI_RefreshMenu(MDICLIENTINFO *ci)
if (mii.wID == ci->idFirstChild)
{
TRACE("removing %u items including separator\n", count - i);
- while (RemoveMenu(ci->hWindowMenu, i, MF_BYPOSITION))
+ while (NtUserRemoveMenu( ci->hWindowMenu, i, MF_BYPOSITION ))
/* nothing */;
break;
@@ -935,7 +935,7 @@ static BOOL MDI_RestoreFrameMenu( HWND frame, HWND hChild )
TRUE,
&menuInfo);
- RemoveMenu(menu,0,MF_BYPOSITION);
+ NtUserRemoveMenu( menu, 0, MF_BYPOSITION );
if ( (menuInfo.fType & MFT_BITMAP) &&
(LOWORD(menuInfo.dwTypeData)!=0) &&
diff --git a/dlls/user32/menu.c b/dlls/user32/menu.c
index 5e9d8df17f5..5101a095966 100644
--- a/dlls/user32/menu.c
+++ b/dlls/user32/menu.c
@@ -88,11 +88,6 @@ typedef struct
/* Margins for popup menus */
#define MENU_MARGIN 3
-/* maximum allowed depth of any branch in the menu tree.
- * This value is slightly larger than in windows (25) to
- * stay on the safe side. */
-#define MAXMENUDEPTH 30
-
/* (other menu->FocusedItem values give the position of the focused item) */
#define NO_SELECTED_ITEM 0xffff
@@ -127,8 +122,6 @@ static BOOL fEndMenu = FALSE;
DWORD WINAPI DrawMenuBarTemp(HWND hwnd, HDC hDC, LPRECT lprect, HMENU hMenu, HFONT hFont);
-static BOOL SetMenuItemInfo_common( MENUITEM *, const MENUITEMINFOW * );
-
static BOOL is_win_menu_disallowed(HWND hwnd)
{
return (GetWindowLongW(hwnd, GWL_STYLE) & (WS_CHILD | WS_POPUP)) == WS_CHILD;
@@ -623,15 +616,6 @@ static UINT MENU_FindSubMenu( HMENU *hmenu, HMENU hSubTarget )
return NO_SELECTED_ITEM;
}
-/***********************************************************************
- * MENU_FreeItemData
- */
-static void MENU_FreeItemData( MENUITEM* item )
-{
- /* delete text */
- HeapFree( GetProcessHeap(), 0, item->text );
-}
-
/***********************************************************************
* MENU_AdjustMenuItemRect
*
@@ -2078,62 +2062,6 @@ static void MENU_MoveSelection( HWND hwndOwner, HMENU hmenu, INT offset )
}
-/**********************************************************************
- * insert_menu_item
- *
- * Insert (allocate) a new item into a menu.
- */
-static POPUPMENU *insert_menu_item(HMENU hMenu, UINT id, UINT flags, UINT *ret_pos)
-{
- MENUITEM *newItems;
- POPUPMENU *menu;
- UINT pos = id;
-
- /* Find where to insert new item */
- if (!(menu = find_menu_item(hMenu, id, flags, &pos)))
- {
- if (!(menu = grab_menu_ptr(hMenu)))
- return NULL;
- pos = menu->nItems;
- }
-
- /* Make sure that MDI system buttons stay on the right side.
- * Note: XP treats only bitmap handles 1 - 6 as "magic" ones
- * regardless of their id.
- */
- while (pos > 0 && (INT_PTR)menu->items[pos - 1].hbmpItem >= (INT_PTR)HBMMENU_SYSTEM &&
- (INT_PTR)menu->items[pos - 1].hbmpItem <= (INT_PTR)HBMMENU_MBAR_CLOSE_D)
- pos--;
-
- TRACE("inserting at %u flags %x\n", pos, flags);
-
- /* Create new items array */
-
- newItems = HeapAlloc( GetProcessHeap(), 0, sizeof(MENUITEM) * (menu->nItems+1) );
- if (!newItems)
- {
- release_menu_ptr(menu);
- WARN("allocation failed\n" );
- return NULL;
- }
- if (menu->nItems > 0)
- {
- /* Copy the old array into the new one */
- if (pos > 0) memcpy( newItems, menu->items, pos * sizeof(MENUITEM) );
- if (pos < menu->nItems) memcpy( &newItems[pos+1], &menu->items[pos],
- (menu->nItems-pos)*sizeof(MENUITEM) );
- HeapFree( GetProcessHeap(), 0, menu->items );
- }
- menu->items = newItems;
- menu->nItems++;
- memset( &newItems[pos], 0, sizeof(*newItems) );
- menu->Height = 0; /* force size recalculate */
-
- *ret_pos = pos;
- return menu;
-}
-
-
/**********************************************************************
* MENU_ParseResource
*
@@ -3616,9 +3544,9 @@ BOOL WINAPI ChangeMenuA( HMENU hMenu, UINT pos, LPCSTR data,
if (flags & MF_DELETE) return DeleteMenu(hMenu, pos, flags & ~MF_DELETE);
if (flags & MF_CHANGE) return ModifyMenuA(hMenu, pos, flags & ~MF_CHANGE,
id, data );
- if (flags & MF_REMOVE) return RemoveMenu( hMenu,
- flags & MF_BYPOSITION ? pos : id,
- flags & ~MF_REMOVE );
+ if (flags & MF_REMOVE) return NtUserRemoveMenu( hMenu,
+ flags & MF_BYPOSITION ? pos : id,
+ flags & ~MF_REMOVE );
/* Default: MF_INSERT */
return InsertMenuA( hMenu, pos, flags, id, data );
}
@@ -3636,9 +3564,9 @@ BOOL WINAPI ChangeMenuW( HMENU hMenu, UINT pos, LPCWSTR data,
if (flags & MF_DELETE) return DeleteMenu(hMenu, pos, flags & ~MF_DELETE);
if (flags & MF_CHANGE) return ModifyMenuW(hMenu, pos, flags & ~MF_CHANGE,
id, data );
- if (flags & MF_REMOVE) return RemoveMenu( hMenu,
- flags & MF_BYPOSITION ? pos : id,
- flags & ~MF_REMOVE );
+ if (flags & MF_REMOVE) return NtUserRemoveMenu( hMenu,
+ flags & MF_BYPOSITION ? pos : id,
+ flags & ~MF_REMOVE );
/* Default: MF_INSERT */
return InsertMenuW( hMenu, pos, flags, id, data );
}
@@ -3877,10 +3805,6 @@ BOOL WINAPI InsertMenuW( HMENU hMenu, UINT pos, UINT flags,
UINT_PTR id, LPCWSTR str )
{
MENUITEMINFOW mii;
- POPUPMENU *menu;
- MENUITEM *item;
- UINT newpos;
- BOOL ret;
if (IS_STRING_ITEM(flags) && str)
TRACE("hMenu %p, pos %d, flags %08x, id %04lx, str %s\n",
@@ -3888,19 +3812,9 @@ BOOL WINAPI InsertMenuW( HMENU hMenu, UINT pos, UINT flags,
else TRACE("hMenu %p, pos %d, flags %08x, id %04lx, str %p (not a string)\n",
hMenu, pos, flags, id, str );
- if (!(menu = insert_menu_item(hMenu, pos, flags, &newpos)))
- return FALSE;
-
MENU_mnu2mnuii( flags, id, str, &mii);
mii.fMask |= MIIM_CHECKMARKS;
-
- item = &menu->items[newpos];
- ret = SetMenuItemInfo_common( item, &mii );
- if (!ret)
- RemoveMenu( hMenu, pos, flags );
- release_menu_ptr(menu);
-
- return ret;
+ return NtUserThunkedMenuItemInfo( hMenu, pos, flags, NtUserInsertMenuItem, &mii, NULL );
}
@@ -3948,46 +3862,6 @@ BOOL WINAPI AppendMenuW( HMENU hMenu, UINT flags,
}
-/**********************************************************************
- * RemoveMenu (USER32.@)
- */
-BOOL WINAPI RemoveMenu( HMENU hMenu, UINT id, UINT flags )
-{
- POPUPMENU *menu;
- UINT pos;
-
- TRACE("(menu=%p id=%#x flags=%04x)\n", hMenu, id, flags);
-
- if (!(menu = find_menu_item(hMenu, id, flags, &pos)))
- return FALSE;
-
- /* Remove item */
- MENU_FreeItemData( &menu->items[pos] );
-
- if (--menu->nItems == 0)
- {
- HeapFree( GetProcessHeap(), 0, menu->items );
- menu->items = NULL;
- }
- else
- {
- MENUITEM *new_items, *item = &menu->items[pos];
-
- while (pos < menu->nItems)
- {
- *item = *(item+1);
- item++;
- pos++;
- }
- new_items = HeapReAlloc( GetProcessHeap(), 0, menu->items, menu->nItems * sizeof(MENUITEM) );
- if (new_items) menu->items = new_items;
- }
- release_menu_ptr(menu);
-
- return TRUE;
-}
-
-
/**********************************************************************
* DeleteMenu (USER32.@)
*/
@@ -4002,7 +3876,7 @@ BOOL WINAPI DeleteMenu( HMENU hMenu, UINT id, UINT flags )
if (menu->items[pos].fType & MF_POPUP)
NtUserDestroyMenu( menu->items[pos].hSubMenu );
- RemoveMenu(menu->obj.handle, pos, flags | MF_BYPOSITION);
+ NtUserRemoveMenu( menu->obj.handle, pos, flags | MF_BYPOSITION );
release_menu_ptr(menu);
return TRUE;
}
@@ -4015,26 +3889,14 @@ BOOL WINAPI ModifyMenuW( HMENU hMenu, UINT pos, UINT flags,
UINT_PTR id, LPCWSTR str )
{
MENUITEMINFOW mii;
- POPUPMENU *menu;
- UINT item_pos;
- BOOL ret;
if (IS_STRING_ITEM(flags))
TRACE("%p %d %04x %04lx %s\n", hMenu, pos, flags, id, debugstr_w(str) );
else
TRACE("%p %d %04x %04lx %p\n", hMenu, pos, flags, id, str );
- if (!(menu = find_menu_item(hMenu, pos, flags, &item_pos)))
- {
- /* workaround for Word 95: pretend that SC_TASKLIST item exists */
- if (pos == SC_TASKLIST && !(flags & MF_BYPOSITION)) return TRUE;
- return FALSE;
- }
- menu->Height = 0; /* force size recalculate */
MENU_mnu2mnuii( flags, id, str, &mii);
- ret = SetMenuItemInfo_common( &menu->items[item_pos], &mii );
- release_menu_ptr(menu);
- return ret;
+ return NtUserThunkedMenuItemInfo( hMenu, pos, flags, NtUserSetMenuItemInfo, &mii, NULL );
}
@@ -4120,21 +3982,6 @@ HMENU WINAPI CreateMenu(void)
}
-void free_menu_items( void *ptr )
-{
- POPUPMENU *menu = ptr;
- MENUITEM *item = menu->items;
- int i;
-
- for (i = menu->nItems; i > 0; i--, item++)
- {
- if (item->fType & MF_POPUP) NtUserDestroyMenu( item->hSubMenu );
- MENU_FreeItemData( item );
- }
- HeapFree( GetProcessHeap(), 0, menu->items );
-}
-
-
/**********************************************************************
* GetSystemMenu (USER32.@)
*/
@@ -4654,108 +4501,6 @@ BOOL WINAPI GetMenuItemInfoW( HMENU hmenu, UINT item, BOOL bypos,
}
-/**********************************************************************
- * MENU_depth
- *
- * detect if there are loops in the menu tree (or the depth is too large)
- */
-static int MENU_depth( POPUPMENU *pmenu, int depth)
-{
- UINT i;
- MENUITEM *item;
- int subdepth;
-
- depth++;
- if( depth > MAXMENUDEPTH) return depth;
- item = pmenu->items;
- subdepth = depth;
- for( i = 0; i < pmenu->nItems && subdepth <= MAXMENUDEPTH; i++, item++){
- POPUPMENU *psubmenu = item->hSubMenu ? MENU_GetMenu( item->hSubMenu) : NULL;
- if( psubmenu){
- int bdepth = MENU_depth( psubmenu, depth);
- if( bdepth > subdepth) subdepth = bdepth;
- }
- if( subdepth > MAXMENUDEPTH)
- TRACE("<- hmenu %p\n", item->hSubMenu);
- }
- return subdepth;
-}
-
-
-/**********************************************************************
- * SetMenuItemInfo_common
- *
- * Note: does not support the MIIM_TYPE flag. Use the MIIM_FTYPE,
- * MIIM_BITMAP and MIIM_STRING flags instead.
- */
-
-static BOOL SetMenuItemInfo_common( MENUITEM *menu, const MENUITEMINFOW *lpmii )
-{
- if (!menu) return FALSE;
-
- debug_print_menuitem("SetMenuItemInfo_common from: ", menu, "");
-
- if (lpmii->fMask & MIIM_FTYPE ) {
- menu->fType &= ~MENUITEMINFO_TYPE_MASK;
- menu->fType |= lpmii->fType & MENUITEMINFO_TYPE_MASK;
- }
- if (lpmii->fMask & MIIM_STRING ) {
- const WCHAR *text = lpmii->dwTypeData;
- /* free the string when used */
- HeapFree(GetProcessHeap(), 0, menu->text);
- if (!text)
- menu->text = NULL;
- else if ((menu->text = HeapAlloc( GetProcessHeap(), 0, (lstrlenW(text)+1) * sizeof(WCHAR) )))
- lstrcpyW( menu->text, text );
- }
-
- if (lpmii->fMask & MIIM_STATE)
- /* Other menu items having MFS_DEFAULT are not converted
- to normal items */
- menu->fState = lpmii->fState & MENUITEMINFO_STATE_MASK;
-
- if (lpmii->fMask & MIIM_ID)
- menu->wID = lpmii->wID;
-
- if (lpmii->fMask & MIIM_SUBMENU) {
- menu->hSubMenu = lpmii->hSubMenu;
- if (menu->hSubMenu) {
- POPUPMENU *subMenu = MENU_GetMenu(menu->hSubMenu);
- if (subMenu) {
- if( MENU_depth( subMenu, 0) > MAXMENUDEPTH) {
- ERR( "Loop detected in menu hierarchy or maximum menu depth exceeded!\n");
- menu->hSubMenu = 0;
- return FALSE;
- }
- subMenu->wFlags |= MF_POPUP;
- menu->fType |= MF_POPUP;
- } else {
- SetLastError( ERROR_INVALID_PARAMETER);
- return FALSE;
- }
- }
- else
- menu->fType &= ~MF_POPUP;
- }
-
- if (lpmii->fMask & MIIM_CHECKMARKS)
- {
- menu->hCheckBit = lpmii->hbmpChecked;
- menu->hUnCheckBit = lpmii->hbmpUnchecked;
- }
- if (lpmii->fMask & MIIM_DATA)
- menu->dwItemData = lpmii->dwItemData;
-
- if (lpmii->fMask & MIIM_BITMAP)
- menu->hbmpItem = lpmii->hbmpItem;
-
- if( !menu->text && !(menu->fType & MFT_OWNERDRAW) && !menu->hbmpItem)
- menu->fType |= MFT_SEPARATOR;
-
- debug_print_menuitem("SetMenuItemInfo_common to : ", menu, "");
- return TRUE;
-}
-
/**********************************************************************
* MENU_NormalizeMenuItemInfoStruct
*
@@ -4808,8 +4553,6 @@ BOOL WINAPI SetMenuItemInfoA(HMENU hmenu, UINT item, BOOL bypos,
{
WCHAR *strW = NULL;
MENUITEMINFOW mii;
- POPUPMENU *menu;
- UINT pos;
BOOL ret;
TRACE("hmenu %p, item %u, by pos %d, info %p\n", hmenu, item, bypos, lpmii);
@@ -4825,15 +4568,9 @@ BOOL WINAPI SetMenuItemInfoA(HMENU hmenu, UINT item, BOOL bypos,
mii.dwTypeData = strW;
}
- if (!(menu = find_menu_item(hmenu, item, bypos ? MF_BYPOSITION : 0, &pos)))
- {
- /* workaround for Word 95: pretend that SC_TASKLIST item exists */
- HeapFree( GetProcessHeap(), 0, strW );
- if (item == SC_TASKLIST && !bypos) return TRUE;
- return FALSE;
- }
- ret = SetMenuItemInfo_common( &menu->items[pos], &mii );
- release_menu_ptr(menu);
+ ret = NtUserThunkedMenuItemInfo( hmenu, item, bypos ? MF_BYPOSITION : 0,
+ NtUserSetMenuItemInfo, &mii, NULL );
+
HeapFree( GetProcessHeap(), 0, strW );
return ret;
}
@@ -4845,24 +4582,13 @@ BOOL WINAPI SetMenuItemInfoW(HMENU hmenu, UINT item, BOOL bypos,
const MENUITEMINFOW *lpmii)
{
MENUITEMINFOW mii;
- POPUPMENU *menu;
- BOOL ret;
- UINT pos;
TRACE("hmenu %p, item %u, by pos %d, info %p\n", hmenu, item, bypos, lpmii);
if (!MENU_NormalizeMenuItemInfoStruct( lpmii, &mii )) return FALSE;
- if (!(menu = find_menu_item(hmenu, item, bypos ? MF_BYPOSITION : 0, &pos)))
- {
- /* workaround for Word 95: pretend that SC_TASKLIST item exists */
- if (item == SC_TASKLIST && !bypos) return TRUE;
- return FALSE;
- }
-
- ret = SetMenuItemInfo_common(&menu->items[pos], &mii);
- release_menu_ptr(menu);
- return ret;
+ return NtUserThunkedMenuItemInfo( hmenu, item, bypos ? MF_BYPOSITION : 0,
+ NtUserSetMenuItemInfo, &mii, NULL );
}
/**********************************************************************
@@ -4915,8 +4641,6 @@ BOOL WINAPI InsertMenuItemA(HMENU hMenu, UINT uItem, BOOL bypos,
{
WCHAR *strW = NULL;
MENUITEMINFOW mii;
- POPUPMENU *menu;
- UINT pos;
BOOL ret;
TRACE("hmenu %p, item %04x, by pos %d, info %p\n", hMenu, uItem, bypos, lpmii);
@@ -4932,14 +4656,9 @@ BOOL WINAPI InsertMenuItemA(HMENU hMenu, UINT uItem, BOOL bypos,
mii.dwTypeData = strW;
}
- if (!(menu = insert_menu_item(hMenu, uItem, bypos ? MF_BYPOSITION : 0, &pos)))
- {
- HeapFree( GetProcessHeap(), 0, strW );
- return FALSE;
- }
+ ret = NtUserThunkedMenuItemInfo( hMenu, uItem, bypos ? MF_BYPOSITION : 0,
+ NtUserInsertMenuItem, &mii, NULL );
- ret = SetMenuItemInfo_common( &menu->items[pos], &mii );
- release_menu_ptr(menu);
HeapFree( GetProcessHeap(), 0, strW );
return ret;
}
@@ -4952,20 +4671,13 @@ BOOL WINAPI InsertMenuItemW(HMENU hMenu, UINT uItem, BOOL bypos,
const MENUITEMINFOW *lpmii)
{
MENUITEMINFOW mii;
- POPUPMENU *menu;
- UINT pos;
- BOOL ret;
TRACE("hmenu %p, item %04x, by pos %d, info %p\n", hMenu, uItem, bypos, lpmii);
if (!MENU_NormalizeMenuItemInfoStruct( lpmii, &mii )) return FALSE;
- if (!(menu = insert_menu_item(hMenu, uItem, bypos ? MF_BYPOSITION : 0, &pos)))
- return FALSE;
-
- ret = SetMenuItemInfo_common( &menu->items[pos], &mii );
- release_menu_ptr(menu);
- return ret;
+ return NtUserThunkedMenuItemInfo( hMenu, uItem, bypos ? MF_BYPOSITION : 0,
+ NtUserInsertMenuItem, &mii, NULL );
}
/**********************************************************************
diff --git a/dlls/user32/user32.spec b/dlls/user32/user32.spec
index da0b7c5a1ab..298a0fa3150 100644
--- a/dlls/user32/user32.spec
+++ b/dlls/user32/user32.spec
@@ -619,7 +619,7 @@
@ stdcall ReleaseCapture()
@ stdcall ReleaseDC(long long) NtUserReleaseDC
@ stdcall RemoveClipboardFormatListener(long) NtUserRemoveClipboardFormatListener
-@ stdcall RemoveMenu(long long long)
+@ stdcall RemoveMenu(long long long) NtUserRemoveMenu
@ stdcall RemovePropA(long str)
@ stdcall RemovePropW(long wstr)
@ stdcall ReplyMessage(long)
diff --git a/dlls/user32/user_main.c b/dlls/user32/user_main.c
index 1400597eb5d..babd5f95e55 100644
--- a/dlls/user32/user_main.c
+++ b/dlls/user32/user_main.c
@@ -165,7 +165,6 @@ static const struct user_callbacks user_funcs =
ImmProcessKey,
ImmTranslateMessage,
SetSystemMenu,
- free_menu_items,
free_win_ptr,
MENU_IsMenuActive,
notify_ime,
diff --git a/dlls/win32u/menu.c b/dlls/win32u/menu.c
index 5d1a5ec12d6..0d7127fb4c6 100644
--- a/dlls/win32u/menu.c
+++ b/dlls/win32u/menu.c
@@ -39,9 +39,26 @@ struct accelerator
ACCEL table[1];
};
+/* maximum allowed depth of any branch in the menu tree.
+ * This value is slightly larger than in windows (25) to
+ * stay on the safe side. */
+#define MAXMENUDEPTH 30
+
/* (other menu->FocusedItem values give the position of the focused item) */
#define NO_SELECTED_ITEM 0xffff
+/* macro to test that flags do not indicate bitmap, ownerdraw or separator */
+#define IS_STRING_ITEM(flags) (MENU_ITEM_TYPE ((flags)) == MF_STRING)
+#define IS_MAGIC_BITMAP(id) ((id) && ((INT_PTR)(id) < 12) && ((INT_PTR)(id) >= -1))
+
+#define MENUITEMINFO_TYPE_MASK \
+ (MFT_STRING | MFT_BITMAP | MFT_OWNERDRAW | MFT_SEPARATOR | \
+ MFT_MENUBARBREAK | MFT_MENUBREAK | MFT_RADIOCHECK | \
+ MFT_RIGHTORDER | MFT_RIGHTJUSTIFY /* same as MF_HELP */ )
+#define TYPE_MASK (MENUITEMINFO_TYPE_MASK | MF_POPUP | MF_SYSMENU)
+#define STATE_MASK (~TYPE_MASK)
+#define MENUITEMINFO_STATE_MASK (STATE_MASK & ~(MF_BYPOSITION | MF_MOUSESELECT))
+
/**********************************************************************
* NtUserCopyAcceleratorTable (win32u.@)
*/
@@ -111,6 +128,73 @@ BOOL WINAPI NtUserDestroyAcceleratorTable( HACCEL handle )
return TRUE;
}
+#define MENUFLAG(bit,text) \
+ do { \
+ if (flags & (bit)) { flags &= ~(bit); strcat(buf, (text)); } \
+ } while (0)
+
+static const char *debugstr_menuitem( const MENUITEM *item )
+{
+ static const char *const hbmmenus[] = { "HBMMENU_CALLBACK", "", "HBMMENU_SYSTEM",
+ "HBMMENU_MBAR_RESTORE", "HBMMENU_MBAR_MINIMIZE", "UNKNOWN BITMAP", "HBMMENU_MBAR_CLOSE",
+ "HBMMENU_MBAR_CLOSE_D", "HBMMENU_MBAR_MINIMIZE_D", "HBMMENU_POPUP_CLOSE",
+ "HBMMENU_POPUP_RESTORE", "HBMMENU_POPUP_MAXIMIZE", "HBMMENU_POPUP_MINIMIZE" };
+ char buf[256];
+ UINT flags;
+
+ if (!item) return "NULL";
+
+ sprintf( buf, "{ ID=0x%lx", item->wID );
+ if (item->hSubMenu) sprintf( buf + strlen(buf), ", Sub=%p", item->hSubMenu );
+
+ flags = item->fType;
+ if (flags)
+ {
+ strcat( buf, ", fType=" );
+ MENUFLAG( MFT_SEPARATOR, "sep" );
+ MENUFLAG( MFT_OWNERDRAW, "own" );
+ MENUFLAG( MFT_BITMAP, "bit" );
+ MENUFLAG( MF_POPUP, "pop" );
+ MENUFLAG( MFT_MENUBARBREAK, "barbrk" );
+ MENUFLAG( MFT_MENUBREAK, "brk");
+ MENUFLAG( MFT_RADIOCHECK, "radio" );
+ MENUFLAG( MFT_RIGHTORDER, "rorder" );
+ MENUFLAG( MF_SYSMENU, "sys" );
+ MENUFLAG( MFT_RIGHTJUSTIFY, "right" ); /* same as MF_HELP */
+ if (flags) sprintf( buf + strlen(buf), "+0x%x", flags );
+ }
+
+ flags = item->fState;
+ if (flags)
+ {
+ strcat( buf, ", State=" );
+ MENUFLAG( MFS_GRAYED, "grey" );
+ MENUFLAG( MFS_DEFAULT, "default" );
+ MENUFLAG( MFS_DISABLED, "dis" );
+ MENUFLAG( MFS_CHECKED, "check" );
+ MENUFLAG( MFS_HILITE, "hi" );
+ MENUFLAG( MF_USECHECKBITMAPS, "usebit" );
+ MENUFLAG( MF_MOUSESELECT, "mouse" );
+ if (flags) sprintf( buf + strlen(buf), "+0x%x", flags );
+ }
+
+ if (item->hCheckBit) sprintf( buf + strlen(buf), ", Chk=%p", item->hCheckBit );
+ if (item->hUnCheckBit) sprintf( buf + strlen(buf), ", Unc=%p", item->hUnCheckBit );
+ if (item->text) sprintf( buf + strlen(buf), ", Text=%s", debugstr_w(item->text) );
+ if (item->dwItemData) sprintf( buf + strlen(buf), ", ItemData=0x%08lx", item->dwItemData );
+
+ if (item->hbmpItem)
+ {
+ if (IS_MAGIC_BITMAP( item->hbmpItem ))
+ sprintf( buf + strlen(buf), ", hbitmap=%s", hbmmenus[(INT_PTR)item->hbmpItem + 1] );
+ else
+ sprintf( buf + strlen(buf), ", hbitmap=%p", item->hbmpItem );
+ }
+ return wine_dbg_sprintf( "%s }", buf );
+}
+
+#undef MENUFLAG
+
static POPUPMENU *grab_menu_ptr( HMENU handle )
{
POPUPMENU *menu = get_user_handle_ptr( handle, NTUSER_OBJ_MENU );
@@ -210,6 +294,53 @@ static POPUPMENU *find_menu_item( HMENU handle, UINT id, UINT flags, UINT *pos )
return menu;
}
+static POPUPMENU *insert_menu_item( HMENU handle, UINT id, UINT flags, UINT *ret_pos )
+{
+ MENUITEM *new_items;
+ POPUPMENU *menu;
+ UINT pos = id;
+
+ /* Find where to insert new item */
+ if (!(menu = find_menu_item(handle, id, flags, &pos)))
+ {
+ if (!(menu = grab_menu_ptr(handle)))
+ return NULL;
+ pos = menu->nItems;
+ }
+
+ /* Make sure that MDI system buttons stay on the right side.
+ * Note: XP treats only bitmap handles 1 - 6 as "magic" ones
+ * regardless of their id.
+ */
+ while (pos > 0 && (INT_PTR)menu->items[pos - 1].hbmpItem >= (INT_PTR)HBMMENU_SYSTEM &&
+ (INT_PTR)menu->items[pos - 1].hbmpItem <= (INT_PTR)HBMMENU_MBAR_CLOSE_D)
+ pos--;
+
+ TRACE( "inserting at %u flags %x\n", pos, flags );
+
+ new_items = malloc( sizeof(MENUITEM) * (menu->nItems + 1) );
+ if (!new_items)
+ {
+ release_menu_ptr( menu );
+ return NULL;
+ }
+ if (menu->nItems > 0)
+ {
+ /* Copy the old array into the new one */
+ if (pos > 0) memcpy( new_items, menu->items, pos * sizeof(MENUITEM) );
+ if (pos < menu->nItems) memcpy( &new_items[pos + 1], &menu->items[pos],
+ (menu->nItems - pos) * sizeof(MENUITEM) );
+ free( menu->items );
+ }
+ menu->items = new_items;
+ menu->nItems++;
+ memset( &new_items[pos], 0, sizeof(*new_items) );
+ menu->Height = 0; /* force size recalculate */
+
+ *ret_pos = pos;
+ return menu;
+}
+
static BOOL is_win_menu_disallowed( HWND hwnd )
{
return (get_window_long(hwnd, GWL_STYLE) & (WS_CHILD | WS_POPUP)) == WS_CHILD;
@@ -257,8 +388,19 @@ BOOL WINAPI NtUserDestroyMenu( HMENU handle )
menu->hWnd = 0;
}
- if (menu->items && user_callbacks) /* recursively destroy submenus */
- user_callbacks->free_menu_items( menu );
+ /* recursively destroy submenus */
+ if (menu->items)
+ {
+ MENUITEM *item = menu->items;
+ int i;
+
+ for (i = menu->nItems; i > 0; i--, item++)
+ {
+ if (item->fType & MF_POPUP) NtUserDestroyMenu( item->hSubMenu );
+ free( item->text );
+ }
+ free( menu->items );
+ }
free( menu );
return TRUE;
@@ -527,6 +669,206 @@ BOOL get_menu_info( HMENU handle, MENUINFO *info )
return TRUE;
}
+/**********************************************************************
+ * menu_depth
+ *
+ * detect if there are loops in the menu tree (or the depth is too large)
+ */
+static int menu_depth( POPUPMENU *pmenu, int depth)
+{
+ int i, subdepth;
+ MENUITEM *item;
+
+ if (++depth > MAXMENUDEPTH) return depth;
+ item = pmenu->items;
+ subdepth = depth;
+ for (i = 0; i < pmenu->nItems && subdepth <= MAXMENUDEPTH; i++, item++)
+ {
+ POPUPMENU *submenu = item->hSubMenu ? grab_menu_ptr( item->hSubMenu ) : NULL;
+ if (submenu)
+ {
+ int bdepth = menu_depth( submenu, depth);
+ if (bdepth > subdepth) subdepth = bdepth;
+ release_menu_ptr( submenu );
+ }
+ if (subdepth > MAXMENUDEPTH)
+ TRACE( "<- hmenu %p\n", item->hSubMenu );
+ }
+
+ return subdepth;
+}
+
+static BOOL set_menu_item_info( MENUITEM *menu, const MENUITEMINFOW *info )
+{
+ if (!menu) return FALSE;
+
+ TRACE( "%s\n", debugstr_menuitem( menu ));
+
+ if (info->fMask & MIIM_FTYPE )
+ {
+ menu->fType &= ~MENUITEMINFO_TYPE_MASK;
+ menu->fType |= info->fType & MENUITEMINFO_TYPE_MASK;
+ }
+ if (info->fMask & MIIM_STRING )
+ {
+ const WCHAR *text = info->dwTypeData;
+ /* free the string when used */
+ free( menu->text );
+ if (!text)
+ menu->text = NULL;
+ else if ((menu->text = malloc( (lstrlenW(text) + 1) * sizeof(WCHAR) )))
+ lstrcpyW( menu->text, text );
+ }
+
+ if (info->fMask & MIIM_STATE)
+ /* Other menu items having MFS_DEFAULT are not converted
+ to normal items */
+ menu->fState = info->fState & MENUITEMINFO_STATE_MASK;
+
+ if (info->fMask & MIIM_ID)
+ menu->wID = info->wID;
+
+ if (info->fMask & MIIM_SUBMENU)
+ {
+ menu->hSubMenu = info->hSubMenu;
+ if (menu->hSubMenu)
+ {
+ POPUPMENU *submenu = grab_menu_ptr( menu->hSubMenu );
+ if (!submenu)
+ {
+ SetLastError( ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+ if (menu_depth( submenu, 0 ) > MAXMENUDEPTH)
+ {
+ ERR( "Loop detected in menu hierarchy or maximum menu depth exceeded\n" );
+ menu->hSubMenu = 0;
+ release_menu_ptr( submenu );
+ return FALSE;
+ }
+ submenu->wFlags |= MF_POPUP;
+ menu->fType |= MF_POPUP;
+ release_menu_ptr( submenu );
+ }
+ else
+ menu->fType &= ~MF_POPUP;
+ }
+
+ if (info->fMask & MIIM_CHECKMARKS)
+ {
+ menu->hCheckBit = info->hbmpChecked;
+ menu->hUnCheckBit = info->hbmpUnchecked;
+ }
+ if (info->fMask & MIIM_DATA)
+ menu->dwItemData = info->dwItemData;
+
+ if (info->fMask & MIIM_BITMAP)
+ menu->hbmpItem = info->hbmpItem;
+
+ if (!menu->text && !(menu->fType & MFT_OWNERDRAW) && !menu->hbmpItem)
+ menu->fType |= MFT_SEPARATOR;
+
+ TRACE( "to: %s\n", debugstr_menuitem( menu ));
+ return TRUE;
+}
+
+/**********************************************************************
+ * NtUserThunkedMenuItemInfo (win32u.@)
+ */
+UINT WINAPI NtUserThunkedMenuItemInfo( HMENU handle, UINT pos, UINT flags, UINT method,
+ MENUITEMINFOW *info, UNICODE_STRING *str )
+{
+ POPUPMENU *menu;
+ UINT i;
+ BOOL ret;
+
+ switch (method)
+ {
+ case NtUserInsertMenuItem:
+ if (!info || info->cbSize != sizeof(*info))
+ {
+ SetLastError( ERROR_INVALID_PARAMETER );
+ return FALSE;
+ }
+
+ if (!(menu = insert_menu_item( handle, pos, flags, &i )))
+ {
+ /* workaround for Word 95: pretend that SC_TASKLIST item exists */
+ if (pos == SC_TASKLIST && !(flags & MF_BYPOSITION)) return TRUE;
+ return FALSE;
+ }
+
+ ret = set_menu_item_info( &menu->items[i], info );
+ if (!ret) NtUserRemoveMenu( handle, pos, flags );
+ release_menu_ptr(menu);
+ break;
+
+ case NtUserSetMenuItemInfo:
+ if (!info || info->cbSize != sizeof(*info))
+ {
+ SetLastError( ERROR_INVALID_PARAMETER );
+ return FALSE;
+ }
+
+ if (!(menu = find_menu_item( handle, pos, flags, &i )))
+ {
+ /* workaround for Word 95: pretend that SC_TASKLIST item exists */
+ if (pos == SC_TASKLIST && !(flags & MF_BYPOSITION)) return TRUE;
+ return FALSE;
+ }
+
+ ret = set_menu_item_info( &menu->items[i], info );
+ if (ret) menu->Height = 0; /* force size recalculate */
+ release_menu_ptr(menu);
+ break;
+
+ default:
+ FIXME( "unsupported method %u\n", method );
+ return FALSE;
+ }
+
+ return ret;
+}
+
+/**********************************************************************
+ * NtUserRemoveMenu (win32u.@)
+ */
+BOOL WINAPI NtUserRemoveMenu( HMENU handle, UINT id, UINT flags )
+{
+ POPUPMENU *menu;
+ UINT pos;
+
+ TRACE( "(menu=%p id=%#x flags=%04x)\n", handle, id, flags );
+
+ if (!(menu = find_menu_item( handle, id, flags, &pos )))
+ return FALSE;
+
+ /* Remove item */
+ free( menu->items[pos].text );
+
+ if (--menu->nItems == 0)
+ {
+ free( menu->items );
+ menu->items = NULL;
+ }
+ else
+ {
+ MENUITEM *new_items, *item = &menu->items[pos];
+
+ while (pos < menu->nItems)
+ {
+ *item = item[1];
+ item++;
+ pos++;
+ }
+ new_items = realloc( menu->items, menu->nItems * sizeof(MENUITEM) );
+ if (new_items) menu->items = new_items;
+ }
+
+ release_menu_ptr(menu);
+ return TRUE;
+}
+
/**********************************************************************
* NtUserSetMenuContextHelpId (win32u.@)
*/
diff --git a/dlls/win32u/ntuser_private.h b/dlls/win32u/ntuser_private.h
index fe9d7e18bc9..29e6b4eaf3e 100644
--- a/dlls/win32u/ntuser_private.h
+++ b/dlls/win32u/ntuser_private.h
@@ -38,7 +38,6 @@ struct user_callbacks
BOOL (WINAPI *pImmProcessKey)(HWND, HKL, UINT, LPARAM, DWORD);
BOOL (WINAPI *pImmTranslateMessage)(HWND, UINT, WPARAM, LPARAM);
BOOL (WINAPI *pSetSystemMenu)( HWND hwnd, HMENU menu );
- void (CDECL *free_menu_items)( void *ptr );
void (CDECL *free_win_ptr)( struct tagWND *win );
HWND (CDECL *is_menu_active)(void);
void (CDECL *notify_ime)( HWND hwnd, UINT param );
diff --git a/dlls/win32u/syscall.c b/dlls/win32u/syscall.c
index dc58cbe1944..f585e90bd4a 100644
--- a/dlls/win32u/syscall.c
+++ b/dlls/win32u/syscall.c
@@ -156,6 +156,7 @@ static void * const syscalls[] =
NtUserOpenInputDesktop,
NtUserOpenWindowStation,
NtUserRemoveClipboardFormatListener,
+ NtUserRemoveMenu,
NtUserRemoveProp,
NtUserSetKeyboardState,
NtUserSetMenuContextHelpId,
@@ -170,6 +171,7 @@ static void * const syscalls[] =
NtUserSetWinEventHook,
NtUserSetWindowsHookEx,
NtUserThunkedMenuInfo,
+ NtUserThunkedMenuItemInfo,
NtUserUnhookWinEvent,
NtUserUnhookWindowsHookEx,
NtUserWindowFromDC,
diff --git a/dlls/win32u/win32u.spec b/dlls/win32u/win32u.spec
index 208b167229e..07da23f633a 100644
--- a/dlls/win32u/win32u.spec
+++ b/dlls/win32u/win32u.spec
@@ -1147,7 +1147,7 @@
@ stub NtUserRemoteStopScreenUpdates
@ stdcall -syscall NtUserRemoveClipboardFormatListener(long)
@ stub NtUserRemoveInjectionDevice
-@ stub NtUserRemoveMenu
+@ stdcall -syscall NtUserRemoveMenu(long long long)
@ stdcall -syscall NtUserRemoveProp(long wstr)
@ stub NtUserRemoveVisualIdentifier
@ stub NtUserReportInertia
@@ -1275,7 +1275,7 @@
@ stdcall NtUserSystemParametersInfoForDpi(long long ptr long long)
@ stub NtUserTestForInteractiveUser
@ stdcall -syscall NtUserThunkedMenuInfo(long ptr)
-@ stub NtUserThunkedMenuItemInfo
+@ stdcall -syscall NtUserThunkedMenuItemInfo(long long long long ptr ptr)
@ stdcall NtUserToUnicodeEx(long long ptr ptr long long long)
@ stdcall NtUserTrackMouseEvent(ptr)
@ stub NtUserTrackPopupMenuEx
diff --git a/dlls/wow64win/syscall.h b/dlls/wow64win/syscall.h
index 1bfc210eab0..776a7e671f6 100644
--- a/dlls/wow64win/syscall.h
+++ b/dlls/wow64win/syscall.h
@@ -143,6 +143,7 @@
SYSCALL_ENTRY( NtUserOpenInputDesktop ) \
SYSCALL_ENTRY( NtUserOpenWindowStation ) \
SYSCALL_ENTRY( NtUserRemoveClipboardFormatListener ) \
+ SYSCALL_ENTRY( NtUserRemoveMenu ) \
SYSCALL_ENTRY( NtUserRemoveProp ) \
SYSCALL_ENTRY( NtUserSetKeyboardState ) \
SYSCALL_ENTRY( NtUserSetMenuContextHelpId ) \
@@ -157,6 +158,7 @@
SYSCALL_ENTRY( NtUserSetWinEventHook ) \
SYSCALL_ENTRY( NtUserSetWindowsHookEx ) \
SYSCALL_ENTRY( NtUserThunkedMenuInfo ) \
+ SYSCALL_ENTRY( NtUserThunkedMenuItemInfo ) \
SYSCALL_ENTRY( NtUserUnhookWinEvent ) \
SYSCALL_ENTRY( NtUserUnhookWindowsHookEx ) \
SYSCALL_ENTRY( NtUserWindowFromDC )
diff --git a/dlls/wow64win/user.c b/dlls/wow64win/user.c
index 554a6634f0e..1f287c7631c 100644
--- a/dlls/wow64win/user.c
+++ b/dlls/wow64win/user.c
@@ -30,6 +30,22 @@
WINE_DEFAULT_DEBUG_CHANNEL(wow);
+typedef struct
+{
+ UINT cbSize;
+ UINT fMask;
+ UINT fType;
+ UINT fState;
+ UINT wID;
+ UINT32 hSubMenu;
+ UINT32 hbmpChecked;
+ UINT32 hbmpUnchecked;
+ UINT32 dwItemData;
+ UINT32 dwTypeData;
+ UINT cch;
+ UINT32 hbmpItem;
+} MENUITEMINFOW32;
+
NTSTATUS WINAPI wow64_NtUserInitializeClientPfnArrays( UINT *args )
{
FIXME( "\n" );
@@ -708,3 +724,50 @@ NTSTATUS WINAPI wow64_NtUserThunkedMenuInfo( UINT *args )
return NtUserThunkedMenuInfo( menu, info32 ? &info : NULL );
}
+
+NTSTATUS WINAPI wow64_NtUserThunkedMenuItemInfo( UINT *args )
+{
+ HMENU handle = get_handle( &args );
+ UINT pos = get_ulong( &args );
+ UINT flags = get_ulong( &args );
+ UINT method = get_ulong( &args );
+ MENUITEMINFOW32 *info32 = get_ptr( &args );
+ UNICODE_STRING32 *str32 = get_ptr( &args );
+ MENUITEMINFOW info = { sizeof(info) }, *info_ptr;
+ UNICODE_STRING str;
+
+ if (info32)
+ {
+ info.cbSize = sizeof(info);
+ info.fMask = info32->fMask;
+ switch (method)
+ {
+ case NtUserSetMenuItemInfo:
+ case NtUserInsertMenuItem:
+ info.fType = info32->fType;
+ info.fState = info32->fState;
+ info.wID = info32->wID;
+ info.hSubMenu = UlongToHandle( info32->hSubMenu );
+ info.hbmpChecked = UlongToHandle( info32->hbmpUnchecked );
+ info.dwItemData = info32->dwItemData;
+ info.dwTypeData = UlongToPtr( info32->dwTypeData );
+ info.cch = info32->cch;
+ info.hbmpItem = UlongToHandle( info32->hbmpItem );
+ break;
+ }
+ info_ptr = &info;
+ }
+ else info_ptr = NULL;
+
+ return NtUserThunkedMenuItemInfo( handle, pos, flags, method, info_ptr,
+ unicode_str_32to64( &str, str32 ));
+}
+
+NTSTATUS WINAPI wow64_NtUserRemoveMenu( UINT *args )
+{
+ HMENU handle = get_handle( &args );
+ UINT id = get_ulong( &args );
+ UINT flags = get_ulong( &args );
+
+ return NtUserRemoveMenu( handle, id, flags );
+}
diff --git a/include/ntuser.h b/include/ntuser.h
index 58486fcfcb0..75b9ba7b73c 100644
--- a/include/ntuser.h
+++ b/include/ntuser.h
@@ -178,6 +178,13 @@ enum
NtUserSpyExit = 0x0301,
};
+/* NtUserThunkedMenuItemInfo codes */
+enum
+{
+ NtUserSetMenuItemInfo,
+ NtUserInsertMenuItem,
+};
+
struct send_message_timeout_params
{
UINT flags;
@@ -581,6 +588,7 @@ ATOM WINAPI NtUserRegisterClassExWOW( const WNDCLASSEXW *wc, UNICODE_STRING *
BOOL WINAPI NtUserRegisterHotKey( HWND hwnd, INT id, UINT modifiers, UINT vk );
INT WINAPI NtUserReleaseDC( HWND hwnd, HDC hdc );
BOOL WINAPI NtUserRemoveClipboardFormatListener( HWND hwnd );
+BOOL WINAPI NtUserRemoveMenu( HMENU menu, UINT id, UINT flags );
HANDLE WINAPI NtUserRemoveProp( HWND hwnd, const WCHAR *str );
BOOL WINAPI NtUserScrollDC( HDC hdc, INT dx, INT dy, const RECT *scroll, const RECT *clip,
HRGN ret_update_rgn, RECT *update_rect );
@@ -629,6 +637,8 @@ 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 );
BOOL WINAPI NtUserThunkedMenuInfo( HMENU menu, const MENUINFO *info );
+UINT WINAPI NtUserThunkedMenuItemInfo( HMENU menu, UINT pos, UINT flags, UINT method,
+ MENUITEMINFOW *info, UNICODE_STRING *str );
INT WINAPI NtUserToUnicodeEx( UINT virt, UINT scan, const BYTE *state,
WCHAR *str, int size, UINT flags, HKL layout );
BOOL WINAPI NtUserTrackMouseEvent( TRACKMOUSEEVENT *info );
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/18
May 2, 2022
[PATCH 04/13] user32: Perform Unicode conversion in InsertMenuItemA.
by Jacek Caban
From: Jacek Caban <jacek(a)codeweavers.com>
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
---
dlls/user32/menu.c | 58 +++++++++++++++++++++-------------------------
1 file changed, 27 insertions(+), 31 deletions(-)
diff --git a/dlls/user32/menu.c b/dlls/user32/menu.c
index 14ed4cb10e2..5e9d8df17f5 100644
--- a/dlls/user32/menu.c
+++ b/dlls/user32/menu.c
@@ -127,7 +127,7 @@ static BOOL fEndMenu = FALSE;
DWORD WINAPI DrawMenuBarTemp(HWND hwnd, HDC hDC, LPRECT lprect, HMENU hMenu, HFONT hFont);
-static BOOL SetMenuItemInfo_common( MENUITEM *, const MENUITEMINFOW *, BOOL);
+static BOOL SetMenuItemInfo_common( MENUITEM *, const MENUITEMINFOW * );
static BOOL is_win_menu_disallowed(HWND hwnd)
{
@@ -3895,7 +3895,7 @@ BOOL WINAPI InsertMenuW( HMENU hMenu, UINT pos, UINT flags,
mii.fMask |= MIIM_CHECKMARKS;
item = &menu->items[newpos];
- ret = SetMenuItemInfo_common( item, &mii, TRUE);
+ ret = SetMenuItemInfo_common( item, &mii );
if (!ret)
RemoveMenu( hMenu, pos, flags );
release_menu_ptr(menu);
@@ -4032,7 +4032,7 @@ BOOL WINAPI ModifyMenuW( HMENU hMenu, UINT pos, UINT flags,
}
menu->Height = 0; /* force size recalculate */
MENU_mnu2mnuii( flags, id, str, &mii);
- ret = SetMenuItemInfo_common(&menu->items[item_pos], &mii, TRUE);
+ ret = SetMenuItemInfo_common( &menu->items[item_pos], &mii );
release_menu_ptr(menu);
return ret;
}
@@ -4654,26 +4654,6 @@ BOOL WINAPI GetMenuItemInfoW( HMENU hmenu, UINT item, BOOL bypos,
}
-/* set a menu item text from an ANSI or Unicode string */
-static inline void set_menu_item_text( MENUITEM *menu, LPCWSTR text, BOOL unicode )
-{
- if (!text)
- menu->text = NULL;
- else if (unicode)
- {
- if ((menu->text = HeapAlloc( GetProcessHeap(), 0, (lstrlenW(text)+1) * sizeof(WCHAR) )))
- lstrcpyW( menu->text, text );
- }
- else
- {
- LPCSTR str = (LPCSTR)text;
- int len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
- if ((menu->text = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
- MultiByteToWideChar( CP_ACP, 0, str, -1, menu->text, len );
- }
-}
-
-
/**********************************************************************
* MENU_depth
*
@@ -4709,9 +4689,7 @@ static int MENU_depth( POPUPMENU *pmenu, int depth)
* MIIM_BITMAP and MIIM_STRING flags instead.
*/
-static BOOL SetMenuItemInfo_common(MENUITEM * menu,
- const MENUITEMINFOW *lpmii,
- BOOL unicode)
+static BOOL SetMenuItemInfo_common( MENUITEM *menu, const MENUITEMINFOW *lpmii )
{
if (!menu) return FALSE;
@@ -4722,9 +4700,13 @@ static BOOL SetMenuItemInfo_common(MENUITEM * menu,
menu->fType |= lpmii->fType & MENUITEMINFO_TYPE_MASK;
}
if (lpmii->fMask & MIIM_STRING ) {
+ const WCHAR *text = lpmii->dwTypeData;
/* free the string when used */
HeapFree(GetProcessHeap(), 0, menu->text);
- set_menu_item_text( menu, lpmii->dwTypeData, unicode );
+ if (!text)
+ menu->text = NULL;
+ else if ((menu->text = HeapAlloc( GetProcessHeap(), 0, (lstrlenW(text)+1) * sizeof(WCHAR) )))
+ lstrcpyW( menu->text, text );
}
if (lpmii->fMask & MIIM_STATE)
@@ -4850,7 +4832,7 @@ BOOL WINAPI SetMenuItemInfoA(HMENU hmenu, UINT item, BOOL bypos,
if (item == SC_TASKLIST && !bypos) return TRUE;
return FALSE;
}
- ret = SetMenuItemInfo_common(&menu->items[pos], &mii, TRUE);
+ ret = SetMenuItemInfo_common( &menu->items[pos], &mii );
release_menu_ptr(menu);
HeapFree( GetProcessHeap(), 0, strW );
return ret;
@@ -4878,7 +4860,7 @@ BOOL WINAPI SetMenuItemInfoW(HMENU hmenu, UINT item, BOOL bypos,
return FALSE;
}
- ret = SetMenuItemInfo_common(&menu->items[pos], &mii, TRUE);
+ ret = SetMenuItemInfo_common(&menu->items[pos], &mii);
release_menu_ptr(menu);
return ret;
}
@@ -4931,6 +4913,7 @@ UINT WINAPI GetMenuDefaultItem(HMENU hmenu, UINT bypos, UINT flags)
BOOL WINAPI InsertMenuItemA(HMENU hMenu, UINT uItem, BOOL bypos,
const MENUITEMINFOA *lpmii)
{
+ WCHAR *strW = NULL;
MENUITEMINFOW mii;
POPUPMENU *menu;
UINT pos;
@@ -4940,11 +4923,24 @@ BOOL WINAPI InsertMenuItemA(HMENU hMenu, UINT uItem, BOOL bypos,
if (!MENU_NormalizeMenuItemInfoStruct( (const MENUITEMINFOW *)lpmii, &mii )) return FALSE;
+ if ((mii.fMask & MIIM_STRING) && mii.dwTypeData)
+ {
+ const char *str = (const char *)mii.dwTypeData;
+ UINT len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
+ if (!(strW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return FALSE;
+ MultiByteToWideChar( CP_ACP, 0, str, -1, strW, len );
+ mii.dwTypeData = strW;
+ }
+
if (!(menu = insert_menu_item(hMenu, uItem, bypos ? MF_BYPOSITION : 0, &pos)))
+ {
+ HeapFree( GetProcessHeap(), 0, strW );
return FALSE;
+ }
- ret = SetMenuItemInfo_common(&menu->items[pos], &mii, FALSE);
+ ret = SetMenuItemInfo_common( &menu->items[pos], &mii );
release_menu_ptr(menu);
+ HeapFree( GetProcessHeap(), 0, strW );
return ret;
}
@@ -4967,7 +4963,7 @@ BOOL WINAPI InsertMenuItemW(HMENU hMenu, UINT uItem, BOOL bypos,
if (!(menu = insert_menu_item(hMenu, uItem, bypos ? MF_BYPOSITION : 0, &pos)))
return FALSE;
- ret = SetMenuItemInfo_common(&menu->items[pos], &mii, TRUE);
+ ret = SetMenuItemInfo_common( &menu->items[pos], &mii );
release_menu_ptr(menu);
return ret;
}
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/18
May 2, 2022