user32/menu: Hold a reference to menu data for calls with menu handles on input.

Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Nikolay Sivov 2018-04-16 14:12:12 +03:00 committed by Alexandre Julliard
parent 210cefd23d
commit fcdc7db390
1 changed files with 127 additions and 70 deletions

View File

@ -98,6 +98,7 @@ typedef struct {
UINT nScrollPos; /* Current scroll position */
UINT nTotalHeight; /* Total height of menu items inside menu */
RECT items_rect; /* Rectangle within which the items lie. Excludes margins and scroll arrows */
LONG refcount;
/* ------------ MENUINFO members ------ */
DWORD dwStyle; /* Extended menu style */
UINT cyMax; /* max height of the whole menu, 0 is screen height */
@ -299,6 +300,32 @@ static POPUPMENU *MENU_GetMenu(HMENU hMenu)
return menu;
}
static POPUPMENU *grab_menu_ptr(HMENU hMenu)
{
POPUPMENU *menu = get_user_handle_ptr( hMenu, USER_MENU );
if (menu == OBJ_OTHER_PROCESS)
{
WARN("other process menu %p?\n", hMenu);
return NULL;
}
if (menu)
menu->refcount++;
else
WARN("invalid menu handle=%p\n", hMenu);
return menu;
}
static void release_menu_ptr(POPUPMENU *menu)
{
if (menu)
{
menu->refcount--;
release_user_handle_ptr(menu);
}
}
/***********************************************************************
* get_win_sys_menu
*
@ -3830,10 +3857,15 @@ UINT WINAPI GetMenuState( HMENU hMenu, UINT wItemID, UINT wFlags )
*/
INT WINAPI GetMenuItemCount( HMENU hMenu )
{
LPPOPUPMENU menu = MENU_GetMenu(hMenu);
POPUPMENU *menu = grab_menu_ptr(hMenu);
INT count;
if (!menu) return -1;
TRACE("(%p) returning %d\n", hMenu, menu->nItems );
return menu->nItems;
count = menu->nItems;
release_menu_ptr(menu);
TRACE("(%p) returning %d\n", hMenu, count);
return count;
}
@ -4127,6 +4159,7 @@ HMENU WINAPI CreateMenu(void)
if (!(menu = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*menu) ))) return 0;
menu->FocusedItem = NO_SELECTED_ITEM;
menu->refcount = 1;
if (!(hMenu = alloc_user_handle( &menu->obj, USER_MENU ))) HeapFree( GetProcessHeap(), 0, menu );
@ -4349,14 +4382,14 @@ BOOL MENU_SetMenu( HWND hWnd, HMENU hMenu )
if (GetCapture() == hWnd)
set_capture_window( 0, GUI_INMENUMODE, NULL ); /* release the capture */
if (hMenu != 0)
if (hMenu)
{
LPPOPUPMENU lpmenu;
POPUPMENU *menu;
if (!(lpmenu = MENU_GetMenu(hMenu))) return FALSE;
lpmenu->hWnd = hWnd;
lpmenu->Height = 0; /* Make sure we recalculate the size */
if (!(menu = grab_menu_ptr(hMenu))) return FALSE;
menu->hWnd = hWnd;
menu->Height = 0; /* Make sure we recalculate the size */
release_menu_ptr(menu);
}
SetWindowLongPtrW( hWnd, GWLP_ID, (LONG_PTR)hMenu );
return TRUE;
@ -4395,7 +4428,6 @@ HMENU WINAPI GetSubMenu( HMENU hMenu, INT nPos )
*/
BOOL WINAPI DrawMenuBar( HWND hWnd )
{
LPPOPUPMENU lppop;
HMENU hMenu;
if (!IsWindow( hWnd ))
@ -4403,9 +4435,15 @@ BOOL WINAPI DrawMenuBar( HWND hWnd )
if (!WIN_ALLOWED_MENU(GetWindowLongW( hWnd, GWL_STYLE )))
return TRUE;
if ((hMenu = GetMenu( hWnd )) && (lppop = MENU_GetMenu( hMenu ))) {
lppop->Height = 0; /* Make sure we call MENU_MenuBarCalcSize */
lppop->hwndOwner = hWnd;
if ((hMenu = GetMenu( hWnd )))
{
POPUPMENU *menu = grab_menu_ptr(hMenu);
if (menu)
{
menu->Height = 0; /* Make sure we call MENU_MenuBarCalcSize */
menu->hwndOwner = hWnd;
release_menu_ptr(menu);
}
}
return SetWindowPos( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
@ -4573,14 +4611,17 @@ HMENU WINAPI LoadMenuIndirectA( LPCVOID template )
*/
BOOL WINAPI IsMenu(HMENU hmenu)
{
LPPOPUPMENU menu = MENU_GetMenu(hmenu);
POPUPMENU *menu;
BOOL is_menu;
if (!menu)
{
menu = grab_menu_ptr(hmenu);
is_menu = menu != NULL;
release_menu_ptr(menu);
if (!is_menu)
SetLastError(ERROR_INVALID_MENU_HANDLE);
return FALSE;
}
return TRUE;
return is_menu;
}
/**********************************************************************
@ -4942,53 +4983,60 @@ BOOL WINAPI SetMenuItemInfoW(HMENU hmenu, UINT item, BOOL bypos,
return SetMenuItemInfo_common( menuitem, &mii, TRUE );
}
static BOOL set_menu_default_item(POPUPMENU *menu, UINT uItem, UINT bypos)
{
unsigned int i;
MENUITEM *item;
/* reset all default-item flags */
item = menu->items;
for (i = 0; i < menu->nItems; i++, item++)
{
item->fState &= ~MFS_DEFAULT;
}
/* no default item */
if (-1 == uItem)
return TRUE;
item = menu->items;
if ( bypos )
{
if ( uItem >= menu->nItems ) return FALSE;
item[uItem].fState |= MFS_DEFAULT;
return TRUE;
}
else
{
for (i = 0; i < menu->nItems; i++, item++)
{
if (item->wID == uItem)
{
item->fState |= MFS_DEFAULT;
return TRUE;
}
}
}
return FALSE;
}
/**********************************************************************
* SetMenuDefaultItem (USER32.@)
*
*/
BOOL WINAPI SetMenuDefaultItem(HMENU hmenu, UINT uItem, UINT bypos)
{
UINT i;
POPUPMENU *menu;
MENUITEM *item;
POPUPMENU *menu;
BOOL ret;
TRACE("(%p,%d,%d)\n", hmenu, uItem, bypos);
TRACE("(%p,%d,%d)\n", hmenu, uItem, bypos);
if (!(menu = MENU_GetMenu(hmenu))) return FALSE;
if (!(menu = grab_menu_ptr(hmenu))) return FALSE;
ret = set_menu_default_item(menu, uItem, bypos);
release_menu_ptr(menu);
/* reset all default-item flags */
item = menu->items;
for (i = 0; i < menu->nItems; i++, item++)
{
item->fState &= ~MFS_DEFAULT;
}
/* no default item */
if ( -1 == uItem)
{
return TRUE;
}
item = menu->items;
if ( bypos )
{
if ( uItem >= menu->nItems ) return FALSE;
item[uItem].fState |= MFS_DEFAULT;
return TRUE;
}
else
{
for (i = 0; i < menu->nItems; i++, item++)
{
if (item->wID == uItem)
{
item->fState |= MFS_DEFAULT;
return TRUE;
}
}
}
return FALSE;
return ret;
}
/**********************************************************************
@ -5213,13 +5261,13 @@ BOOL WINAPI SetMenuInfo (HMENU hMenu, LPCMENUINFO lpmi)
*
*/
BOOL WINAPI GetMenuInfo (HMENU hMenu, LPMENUINFO lpmi)
{ POPUPMENU *menu;
{
POPUPMENU *menu;
TRACE("(%p %p)\n", hMenu, lpmi);
if (lpmi && (lpmi->cbSize == sizeof( MENUINFO)) && (menu = MENU_GetMenu(hMenu)))
if (lpmi && (lpmi->cbSize == sizeof(MENUINFO)) && (menu = grab_menu_ptr(hMenu)))
{
if (lpmi->fMask & MIM_BACKGROUND)
lpmi->hbrBack = menu->hbrBack;
@ -5235,6 +5283,7 @@ BOOL WINAPI GetMenuInfo (HMENU hMenu, LPMENUINFO lpmi)
if (lpmi->fMask & MIM_STYLE)
lpmi->dwStyle = menu->dwStyle;
release_menu_ptr(menu);
return TRUE;
}
SetLastError( ERROR_INVALID_PARAMETER);
@ -5247,14 +5296,15 @@ BOOL WINAPI GetMenuInfo (HMENU hMenu, LPMENUINFO lpmi)
*/
BOOL WINAPI SetMenuContextHelpId( HMENU hMenu, DWORD dwContextHelpID)
{
LPPOPUPMENU menu;
POPUPMENU *menu;
TRACE("(%p 0x%08x)\n", hMenu, dwContextHelpID);
if ((menu = MENU_GetMenu(hMenu)))
if ((menu = grab_menu_ptr(hMenu)))
{
menu->dwContextHelpID = dwContextHelpID;
return TRUE;
menu->dwContextHelpID = dwContextHelpID;
release_menu_ptr(menu);
return TRUE;
}
return FALSE;
}
@ -5265,15 +5315,18 @@ BOOL WINAPI SetMenuContextHelpId( HMENU hMenu, DWORD dwContextHelpID)
*/
DWORD WINAPI GetMenuContextHelpId( HMENU hMenu )
{
LPPOPUPMENU menu;
DWORD help_id = 0;
POPUPMENU *menu;
TRACE("(%p)\n", hMenu);
if ((menu = MENU_GetMenu(hMenu)))
if ((menu = grab_menu_ptr(hMenu)))
{
return menu->dwContextHelpID;
help_id = menu->dwContextHelpID;
release_menu_ptr(menu);
}
return 0;
return help_id;
}
/**********************************************************************
@ -5281,12 +5334,16 @@ DWORD WINAPI GetMenuContextHelpId( HMENU hMenu )
*/
INT WINAPI MenuItemFromPoint(HWND hWnd, HMENU hMenu, POINT ptScreen)
{
POPUPMENU *menu = MENU_GetMenu(hMenu);
POPUPMENU *menu = grab_menu_ptr(hMenu);
UINT pos;
/*FIXME: Do we have to handle hWnd here? */
if (!menu) return -1;
if (MENU_FindItemByCoords( menu, ptScreen, &pos ) != ht_item) return -1;
if (MENU_FindItemByCoords( menu, ptScreen, &pos ) != ht_item)
pos = -1;
release_menu_ptr(menu);
return pos;
}