Commit fcdc7db3 authored by Nikolay Sivov's avatar Nikolay Sivov Committed by Alexandre Julliard

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

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