[v3 PATCH] user32/menu: Return locked menu data when looking for menu items.
Huw Davies
huw at codeweavers.com
Tue May 8 05:08:12 CDT 2018
On Mon, Apr 30, 2018 at 03:11:25PM +0300, Nikolay Sivov wrote:
> +struct menu_item_desc
> +{
> + MENUITEM *item;
> + POPUPMENU *menu;
> + UINT pos;
> +};
>
> /***********************************************************************
> * MENU_FindItem
> - *
> - * Find a menu item. Return a pointer on the item, and modifies *hmenu
> - * in case the item was in a sub-menu.
> */
> -static MENUITEM *MENU_FindItem( HMENU *hmenu, UINT *nPos, UINT wFlags )
> +static BOOL MENU_FindItem(HMENU hmenu, UINT id, UINT flags, struct menu_item_desc *desc)
I'd have probably used the chance to rename this as find_item() ;-)
I also wondered about having this just return the menu and pos (in
which case it's find_item_pos()) and then either letting the callers
index directly into to the returned menu's items array, or adding a
get_item() that would do that. I suppose though there are enough
callers that want the item, that this combined approach is a good
compromise.
> {
> + UINT fallback_pos = ~0u, i;
> POPUPMENU *menu;
> - MENUITEM *fallback = NULL;
> - UINT fallback_pos = 0;
> - UINT i;
>
> - if ((*hmenu == (HMENU)0xffff) || (!(menu = MENU_GetMenu(*hmenu)))) return NULL;
> - if (wFlags & MF_BYPOSITION)
> + memset(desc, 0, sizeof(*desc));
> +
> + menu = grab_menu_ptr(hmenu);
> + if (!menu)
> + return FALSE;
> +
> + if (flags & MF_BYPOSITION)
> {
> - if (*nPos >= menu->nItems) return NULL;
> - return &menu->items[*nPos];
> + if (id >= menu->nItems)
> + {
> + release_menu_ptr(menu);
> + return FALSE;
> + }
> +
> + desc->menu = menu;
> + desc->item = &menu->items[id];
> + desc->pos = id;
> + return TRUE;
> }
> else
> {
> @@ -612,32 +625,37 @@ static MENUITEM *MENU_FindItem( HMENU *hmenu, UINT *nPos, UINT wFlags )
> {
> if (item->fType & MF_POPUP)
> {
> - HMENU hsubmenu = item->hSubMenu;
> - MENUITEM *subitem = MENU_FindItem( &hsubmenu, nPos, wFlags );
> - if (subitem)
> - {
> - *hmenu = hsubmenu;
> - return subitem;
> - }
> - else if (item->wID == *nPos)
> + if (MENU_FindItem(item->hSubMenu, id, flags, desc))
> + {
> + release_menu_ptr(menu);
> + return TRUE;
> + }
> + else if (item->wID == id)
> {
> /* fallback to this item if nothing else found */
> fallback_pos = i;
> - fallback = item;
> }
> }
> - else if (item->wID == *nPos)
> + else if (item->wID == id)
> {
> - *nPos = i;
> - return item;
> + desc->menu = menu;
> + desc->item = item;
> + desc->pos = i;
> + return TRUE;
> }
> }
> }
>
> - if (fallback)
> - *nPos = fallback_pos;
> + if (fallback_pos != ~0u)
> + {
> + desc->menu = menu;
> + desc->item = &menu->items[fallback_pos];
> + desc->pos = fallback_pos;
> + }
> + else
> + release_menu_ptr(menu);
>
> - return fallback;
> + return fallback_pos != ~0u;
> }
>
> /***********************************************************************
> @@ -2135,28 +2153,34 @@ static void MENU_MoveSelection( HWND hwndOwner, HMENU hmenu, INT offset )
> *
> * Insert (allocate) a new item into a menu.
> */
> -static MENUITEM *MENU_InsertItem( HMENU hMenu, UINT pos, UINT flags )
> +static BOOL MENU_InsertItem(HMENU hMenu, UINT id, UINT flags, struct menu_item_desc *desc)
> {
> + UINT pos = id;
> MENUITEM *newItems;
> POPUPMENU *menu;
>
> - if (!(menu = MENU_GetMenu(hMenu)))
> - return NULL;
> + memset(desc, 0, sizeof(*desc));
>
> /* Find where to insert new item */
> -
> if (flags & MF_BYPOSITION) {
> - if (pos > menu->nItems)
> + menu = grab_menu_ptr(hMenu);
> + if (id > menu->nItems)
> pos = menu->nItems;
> } else {
> - if (!MENU_FindItem( &hMenu, &pos, flags ))
> + struct menu_item_desc item_desc;
> +
> + if (!MENU_FindItem(hMenu, id, flags, &item_desc))
> + {
> + menu = grab_menu_ptr(hMenu);
> pos = menu->nItems;
> - else {
> - if (!(menu = MENU_GetMenu( hMenu )))
> - return NULL;
> }
> + else
> + menu = item_desc.menu;
Shouldn't you use the returned item_desc.pos here?
Also, to simplify things, couldn't the MF_BYPOSITION case just call
MENU_FindItem() too?
Huw.
More information about the wine-devel
mailing list