From: Jacek Caban jacek@codeweavers.com
Signed-off-by: Jacek Caban jacek@codeweavers.com --- dlls/user32/menu.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-)
diff --git a/dlls/user32/menu.c b/dlls/user32/menu.c index cc6c5c953e9..cf68aaff31b 100644 --- a/dlls/user32/menu.c +++ b/dlls/user32/menu.c @@ -4482,19 +4482,16 @@ HMENU WINAPI LoadMenuIndirectA( LPCVOID template ) /********************************************************************** * IsMenu (USER32.@) */ -BOOL WINAPI IsMenu(HMENU hmenu) +BOOL WINAPI IsMenu( HMENU menu ) { - POPUPMENU *menu; - BOOL is_menu; - - menu = grab_menu_ptr(hmenu); - is_menu = menu != NULL; - release_menu_ptr(menu); + MENUINFO info;
- if (!is_menu) - SetLastError(ERROR_INVALID_MENU_HANDLE); + info.cbSize = sizeof(info); + info.fMask = 0; + if (GetMenuInfo( menu, &info )) return TRUE;
- return is_menu; + SetLastError(ERROR_INVALID_MENU_HANDLE); + return FALSE; }
/**********************************************************************
From: Jacek Caban jacek@codeweavers.com
Signed-off-by: Jacek Caban jacek@codeweavers.com --- dlls/user32/menu.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/dlls/user32/menu.c b/dlls/user32/menu.c index cf68aaff31b..6336355691d 100644 --- a/dlls/user32/menu.c +++ b/dlls/user32/menu.c @@ -3892,12 +3892,11 @@ BOOL WINAPI InsertMenuW( HMENU hMenu, UINT pos, UINT flags, return FALSE;
MENU_mnu2mnuii( flags, id, str, &mii); + mii.fMask |= MIIM_CHECKMARKS;
item = &menu->items[newpos]; ret = SetMenuItemInfo_common( item, &mii, TRUE); - if (ret) - item->hCheckBit = item->hUnCheckBit = 0; - else + if (!ret) RemoveMenu( hMenu, pos, flags ); release_menu_ptr(menu);
From: Jacek Caban jacek@codeweavers.com
Signed-off-by: Jacek Caban jacek@codeweavers.com --- dlls/user32/menu.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/dlls/user32/menu.c b/dlls/user32/menu.c index 6336355691d..14ed4cb10e2 100644 --- a/dlls/user32/menu.c +++ b/dlls/user32/menu.c @@ -4824,6 +4824,7 @@ static BOOL MENU_NormalizeMenuItemInfoStruct( const MENUITEMINFOW *pmii_in, BOOL WINAPI SetMenuItemInfoA(HMENU hmenu, UINT item, BOOL bypos, const MENUITEMINFOA *lpmii) { + WCHAR *strW = NULL; MENUITEMINFOW mii; POPUPMENU *menu; UINT pos; @@ -4833,14 +4834,25 @@ BOOL WINAPI SetMenuItemInfoA(HMENU hmenu, UINT item, 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 = 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, FALSE); + ret = SetMenuItemInfo_common(&menu->items[pos], &mii, TRUE); release_menu_ptr(menu); + HeapFree( GetProcessHeap(), 0, strW ); return ret; }
From: Jacek Caban jacek@codeweavers.com
Signed-off-by: Jacek Caban jacek@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; }
From: Jacek Caban jacek@codeweavers.com
Signed-off-by: Jacek Caban jacek@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 );
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=113920
Your paranoid android.
=== debian11 (32 bit WoW report) ===
user32: menu.c:2324: Test failed: test 25
From: Jacek Caban jacek@codeweavers.com
Signed-off-by: Jacek Caban jacek@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(); }
From: Jacek Caban jacek@codeweavers.com
Signed-off-by: Jacek Caban jacek@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
From: Jacek Caban jacek@codeweavers.com
Signed-off-by: Jacek Caban jacek@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;
From: Jacek Caban jacek@codeweavers.com
Signed-off-by: Jacek Caban jacek@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;
From: Jacek Caban jacek@codeweavers.com
Signed-off-by: Jacek Caban jacek@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 );
From: Jacek Caban jacek@codeweavers.com
Signed-off-by: Jacek Caban jacek@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 );
From: Jacek Caban jacek@codeweavers.com
Signed-off-by: Jacek Caban jacek@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;
From: Jacek Caban jacek@codeweavers.com
It will be useful for drivers as well.
Signed-off-by: Jacek Caban jacek@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;