Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/user32/menu.c | 544 ++++++++++++++++++++++++++++++---------------
1 file changed, 369 insertions(+), 175 deletions(-)
diff --git a/dlls/user32/menu.c b/dlls/user32/menu.c
index 537c2ebe1a..dcec42cdf2 100644
--- a/dlls/user32/menu.c
+++ b/dlls/user32/menu.c
@@ -592,52 +592,56 @@ static UINT MENU_GetStartOfPrevColumn(
* 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 MENUITEM *MENU_FindItem(POPUPMENU **menu, UINT *nPos, UINT wFlags)
{
- POPUPMENU *menu;
- MENUITEM *fallback = NULL;
- UINT fallback_pos = 0;
- UINT i;
+ UINT fallback_pos = ~0u;
+
+ if (!*menu)
+ return NULL;
- if ((*hmenu == (HMENU)0xffff) || (!(menu = MENU_GetMenu(*hmenu)))) return NULL;
if (wFlags & MF_BYPOSITION)
{
- if (*nPos >= menu->nItems) return NULL;
- return &menu->items[*nPos];
+ if (*nPos >= (*menu)->nItems) return NULL;
+ return &(*menu)->items[*nPos];
}
else
{
- MENUITEM *item = menu->items;
- for (i = 0; i < menu->nItems; i++, item++)
+ MENUITEM *item = (*menu)->items;
+ UINT i;
+
+ for (i = 0; i < (*menu)->nItems; i++, item++)
{
if (item->fType & MF_POPUP)
{
- HMENU hsubmenu = item->hSubMenu;
- MENUITEM *subitem = MENU_FindItem( &hsubmenu, nPos, wFlags );
- if (subitem)
- {
- *hmenu = hsubmenu;
- return subitem;
- }
+ POPUPMENU *submenu = grab_menu_ptr(item->hSubMenu);
+ if (MENU_FindItem(&submenu, nPos, wFlags))
+ {
+ release_menu_ptr(*menu);
+ *menu = submenu;
+ return &(*menu)->items[*nPos];
+ }
else if (item->wID == *nPos)
{
/* fallback to this item if nothing else found */
fallback_pos = i;
- fallback = item;
}
+ release_menu_ptr(submenu);
}
else if (item->wID == *nPos)
{
*nPos = i;
- return item;
+ return &(*menu)->items[*nPos];
}
}
}
- if (fallback)
+ if (fallback_pos != ~0u)
+ {
*nPos = fallback_pos;
+ return &(*menu)->items[*nPos];
+ }
- return fallback;
+ return NULL;
}
/***********************************************************************
@@ -2135,13 +2139,9 @@ 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 MENUITEM *MENU_InsertItem( POPUPMENU *menu, UINT pos, UINT flags )
{
MENUITEM *newItems;
- POPUPMENU *menu;
-
- if (!(menu = MENU_GetMenu(hMenu)))
- return NULL;
/* Find where to insert new item */
@@ -2149,12 +2149,8 @@ static MENUITEM *MENU_InsertItem( HMENU hMenu, UINT pos, UINT flags )
if (pos > menu->nItems)
pos = menu->nItems;
} else {
- if (!MENU_FindItem( &hMenu, &pos, flags ))
+ if (!MENU_FindItem(&menu, &pos, flags))
pos = menu->nItems;
- else {
- if (!(menu = MENU_GetMenu( hMenu )))
- return NULL;
- }
}
/* Make sure that MDI system buttons stay on the right side.
@@ -3706,13 +3702,23 @@ BOOL WINAPI ChangeMenuW( HMENU hMenu, UINT pos, LPCWSTR data,
*/
DWORD WINAPI CheckMenuItem( HMENU hMenu, UINT id, UINT flags )
{
- MENUITEM *item;
- DWORD ret;
+ POPUPMENU *menu;
+ DWORD ret = -1;
+
+ menu = grab_menu_ptr(hMenu);
+ if (menu)
+ {
+ MENUITEM *item;
+
+ if ((item = MENU_FindItem(&menu, &id, flags)))
+ {
+ ret = item->fState & MF_CHECKED;
+ if (flags & MF_CHECKED) item->fState |= MF_CHECKED;
+ else item->fState &= ~MF_CHECKED;
+ }
+ release_menu_ptr(menu);
+ }
- if (!(item = MENU_FindItem( &hMenu, &id, flags ))) return -1;
- ret = item->fState & MF_CHECKED;
- if (flags & MF_CHECKED) item->fState |= MF_CHECKED;
- else item->fState &= ~MF_CHECKED;
return ret;
}
@@ -3726,36 +3732,41 @@ BOOL WINAPI EnableMenuItem( HMENU hMenu, UINT wItemID, UINT wFlags )
MENUITEM *item;
POPUPMENU *menu;
- TRACE("(%p, %04x, %04x) !\n", hMenu, wItemID, wFlags);
+ TRACE("(%p, %04x, %04x)\n", hMenu, wItemID, wFlags);
/* Get the Popupmenu to access the owner menu */
- if (!(menu = MENU_GetMenu(hMenu)))
- return (UINT)-1;
-
- if (!(item = MENU_FindItem( &hMenu, &wItemID, wFlags )))
- return (UINT)-1;
+ menu = grab_menu_ptr(hMenu);
+ if (!(item = MENU_FindItem(&menu, &wItemID, wFlags)))
+ {
+ release_menu_ptr(menu);
+ return (UINT)-1;
+ }
oldflags = item->fState & (MF_GRAYED | MF_DISABLED);
item->fState ^= (oldflags ^ wFlags) & (MF_GRAYED | MF_DISABLED);
/* If the close item in the system menu change update the close button */
- if((item->wID == SC_CLOSE) && (oldflags != wFlags))
+ if ((item->wID == SC_CLOSE) && (oldflags != wFlags) && menu->hSysMenuOwner)
{
- if (menu->hSysMenuOwner != 0)
- {
- RECT rc;
- POPUPMENU* parentMenu;
+ POPUPMENU *parent_menu;
+ HWND hwnd;
+ RECT rc;
- /* Get the parent menu to access*/
- if (!(parentMenu = MENU_GetMenu(menu->hSysMenuOwner)))
- return (UINT)-1;
+ if (!(parent_menu = grab_menu_ptr(menu->hSysMenuOwner)))
+ {
+ release_menu_ptr(menu);
+ return (UINT)-1;
+ }
- /* Refresh the frame to reflect the change */
- WIN_GetRectangles( parentMenu->hWnd, COORDS_CLIENT, &rc, NULL );
- rc.bottom = 0;
- RedrawWindow(parentMenu->hWnd, &rc, 0, RDW_FRAME | RDW_INVALIDATE | RDW_NOCHILDREN);
- }
+ hwnd = parent_menu->hWnd;
+ release_menu_ptr(parent_menu);
+
+ /* Refresh the frame to reflect the change */
+ WIN_GetRectangles(hwnd, COORDS_CLIENT, &rc, NULL);
+ rc.bottom = 0;
+ RedrawWindow(hwnd, &rc, 0, RDW_FRAME | RDW_INVALIDATE | RDW_NOCHILDREN);
}
+ release_menu_ptr(menu);
return oldflags;
}
@@ -3770,21 +3781,39 @@ INT WINAPI GetMenuStringA(
LPSTR str, /* [out] outbuffer. If NULL, func returns entry length*/
INT nMaxSiz, /* [in] length of buffer. if 0, func returns entry len*/
UINT wFlags /* [in] MF_ flags */
-) {
+)
+{
+ POPUPMENU *menu;
MENUITEM *item;
+ INT ret;
TRACE("menu=%p item=%04x ptr=%p len=%d flags=%04x\n", hMenu, wItemID, str, nMaxSiz, wFlags );
+
if (str && nMaxSiz) str[0] = '\0';
- if (!(item = MENU_FindItem( &hMenu, &wItemID, wFlags ))) {
+
+ menu = grab_menu_ptr(hMenu);
+ if (!(item = MENU_FindItem(&menu, &wItemID, wFlags)))
+ {
+ release_menu_ptr(menu);
SetLastError( ERROR_MENU_ITEM_NOT_FOUND);
return 0;
}
- if (!item->text) return 0;
- if (!str || !nMaxSiz) return WideCharToMultiByte( CP_ACP, 0, item->text, -1, NULL, 0, NULL, NULL );
- if (!WideCharToMultiByte( CP_ACP, 0, item->text, -1, str, nMaxSiz, NULL, NULL ))
- str[nMaxSiz-1] = 0;
+
+ if (!item->text)
+ ret = 0;
+ else if (!str || !nMaxSiz)
+ ret = WideCharToMultiByte( CP_ACP, 0, item->text, -1, NULL, 0, NULL, NULL );
+ else
+ {
+ if (!WideCharToMultiByte( CP_ACP, 0, item->text, -1, str, nMaxSiz, NULL, NULL ))
+ str[nMaxSiz-1] = 0;
+ ret = strlen(str);
+ }
+ release_menu_ptr(menu);
+
TRACE("returning %s\n", debugstr_a(str));
- return strlen(str);
+
+ return ret;
}
@@ -3794,22 +3823,38 @@ INT WINAPI GetMenuStringA(
INT WINAPI GetMenuStringW( HMENU hMenu, UINT wItemID,
LPWSTR str, INT nMaxSiz, UINT wFlags )
{
+ POPUPMENU *menu;
MENUITEM *item;
+ INT ret;
TRACE("menu=%p item=%04x ptr=%p len=%d flags=%04x\n", hMenu, wItemID, str, nMaxSiz, wFlags );
+
if (str && nMaxSiz) str[0] = '\0';
- if (!(item = MENU_FindItem( &hMenu, &wItemID, wFlags ))) {
+
+ menu = grab_menu_ptr(hMenu);
+ if (!(item = MENU_FindItem(&menu, &wItemID, wFlags)))
+ {
+ release_menu_ptr(menu);
SetLastError( ERROR_MENU_ITEM_NOT_FOUND);
return 0;
}
- if (!str || !nMaxSiz) return item->text ? strlenW(item->text) : 0;
- if( !(item->text)) {
+
+ if (!str || !nMaxSiz)
+ ret = item->text ? strlenW(item->text) : 0;
+ else if (!(item->text))
+ {
str[0] = 0;
- return 0;
+ ret = 0;
}
- lstrcpynW( str, item->text, nMaxSiz );
+ else
+ {
+ lstrcpynW( str, item->text, nMaxSiz );
+ ret = strlenW(str);
+ }
+ release_menu_ptr(menu);
+
TRACE("returning %s\n", debugstr_w(str));
- return strlenW(str);
+ return ret;
}
@@ -3819,13 +3864,27 @@ INT WINAPI GetMenuStringW( HMENU hMenu, UINT wItemID,
BOOL WINAPI HiliteMenuItem( HWND hWnd, HMENU hMenu, UINT wItemID,
UINT wHilite )
{
- LPPOPUPMENU menu;
+ POPUPMENU *menu;
+ BOOL changed;
+
TRACE("(%p, %p, %04x, %04x);\n", hWnd, hMenu, wItemID, wHilite);
- if (!MENU_FindItem( &hMenu, &wItemID, wHilite )) return FALSE;
- if (!(menu = MENU_GetMenu(hMenu))) return FALSE;
- if (menu->FocusedItem == wItemID) return TRUE;
- MENU_HideSubPopups( hWnd, hMenu, FALSE, 0 );
- MENU_SelectItem( hWnd, hMenu, wItemID, TRUE, 0 );
+
+ menu = grab_menu_ptr(hMenu);
+ if (!MENU_FindItem(&menu, &wItemID, wHilite))
+ {
+ release_menu_ptr(menu);
+ return FALSE;
+ }
+
+ changed = menu->FocusedItem != wItemID;
+ release_menu_ptr(menu);
+
+ if (changed)
+ {
+ MENU_HideSubPopups( hWnd, hMenu, FALSE, 0 );
+ MENU_SelectItem( hWnd, hMenu, wItemID, TRUE, 0 );
+ }
+
return TRUE;
}
@@ -3835,23 +3894,35 @@ BOOL WINAPI HiliteMenuItem( HWND hWnd, HMENU hMenu, UINT wItemID,
*/
UINT WINAPI GetMenuState( HMENU hMenu, UINT wItemID, UINT wFlags )
{
+ POPUPMENU *menu;
MENUITEM *item;
+ UINT state;
+
TRACE("(menu=%p, id=%04x, flags=%04x);\n", hMenu, wItemID, wFlags);
- if (!(item = MENU_FindItem( &hMenu, &wItemID, wFlags ))) return -1;
+
+ menu = grab_menu_ptr(hMenu);
+ if (!(item = MENU_FindItem(&menu, &wItemID, wFlags)))
+ {
+ release_menu_ptr(menu);
+ return -1;
+ }
debug_print_menuitem (" item: ", item, "");
if (item->fType & MF_POPUP)
{
- POPUPMENU *menu = MENU_GetMenu( item->hSubMenu );
- if (!menu) return -1;
- else return (menu->nItems << 8) | ((item->fState|item->fType) & 0xff);
+ POPUPMENU *submenu = grab_menu_ptr(item->hSubMenu);
+ state = submenu ? (submenu->nItems << 8) | ((item->fState | item->fType) & 0xff) : -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. */
- return (item->fType | item->fState);
+ state = (item->fType | item->fState);
}
+ release_menu_ptr(menu);
+
+ return state;
}
@@ -3877,12 +3948,19 @@ INT WINAPI GetMenuItemCount( HMENU hMenu )
*/
UINT WINAPI GetMenuItemID( HMENU hMenu, INT nPos )
{
- MENUITEM * lpmi;
-
- if (!(lpmi = MENU_FindItem(&hMenu,(UINT*)&nPos,MF_BYPOSITION))) return -1;
- if (lpmi->fType & MF_POPUP) return -1;
- return lpmi->wID;
+ POPUPMENU *menu;
+ MENUITEM *item;
+ UINT id;
+ menu = grab_menu_ptr(hMenu);
+ if (!(item = MENU_FindItem(&menu, (UINT *)&nPos, MF_BYPOSITION)))
+ {
+ release_menu_ptr(menu);
+ return -1;
+ }
+ id = item->fType & MF_POPUP ? -1 : item->wID;
+ release_menu_ptr(menu);
+ return id;
}
@@ -3937,6 +4015,8 @@ BOOL WINAPI InsertMenuW( HMENU hMenu, UINT pos, UINT flags,
{
MENUITEM *item;
MENUITEMINFOW mii;
+ POPUPMENU *menu;
+ BOOL ret;
if (IS_STRING_ITEM(flags) && str)
TRACE("hMenu %p, pos %d, flags %08x, id %04lx, str %s\n",
@@ -3944,16 +4024,25 @@ 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 (!(item = MENU_InsertItem( hMenu, pos, flags ))) return FALSE;
- MENU_mnu2mnuii( flags, id, str, &mii);
- if (!(SetMenuItemInfo_common( item, &mii, TRUE)))
+ menu = grab_menu_ptr(hMenu);
+ if (!(item = MENU_InsertItem( menu, pos, flags )))
{
- RemoveMenu( hMenu, pos, flags );
+ release_menu_ptr(menu);
return FALSE;
}
- item->hCheckBit = item->hUnCheckBit = 0;
- return TRUE;
+ MENU_mnu2mnuii( flags, id, str, &mii);
+
+ ret = SetMenuItemInfo_common(item, &mii, TRUE);
+
+ if (ret)
+ item->hCheckBit = item->hUnCheckBit = 0;
+ else
+ RemoveMenu( hMenu, pos, flags );
+
+ release_menu_ptr(menu);
+
+ return ret;
}
@@ -4006,16 +4095,20 @@ BOOL WINAPI AppendMenuW( HMENU hMenu, UINT flags,
*/
BOOL WINAPI RemoveMenu( HMENU hMenu, UINT nPos, UINT wFlags )
{
- LPPOPUPMENU menu;
+ POPUPMENU *menu;
MENUITEM *item;
TRACE("(menu=%p pos=%04x flags=%04x)\n",hMenu, nPos, wFlags);
- if (!(item = MENU_FindItem( &hMenu, &nPos, wFlags ))) return FALSE;
- if (!(menu = MENU_GetMenu(hMenu))) return FALSE;
- /* Remove item */
+ menu = grab_menu_ptr(hMenu);
+ if (!(item = MENU_FindItem(&menu, &nPos, wFlags)))
+ {
+ release_menu_ptr(menu);
+ return FALSE;
+ }
- MENU_FreeItemData( item );
+ /* Remove item */
+ MENU_FreeItemData(item);
if (--menu->nItems == 0)
{
@@ -4035,6 +4128,8 @@ BOOL WINAPI RemoveMenu( HMENU hMenu, UINT nPos, UINT wFlags )
menu->nItems * sizeof(MENUITEM) );
if (new_items) menu->items = new_items;
}
+ release_menu_ptr(menu);
+
return TRUE;
}
@@ -4044,10 +4139,20 @@ BOOL WINAPI RemoveMenu( HMENU hMenu, UINT nPos, UINT wFlags )
*/
BOOL WINAPI DeleteMenu( HMENU hMenu, UINT nPos, UINT wFlags )
{
- MENUITEM *item = MENU_FindItem( &hMenu, &nPos, wFlags );
- if (!item) return FALSE;
+ POPUPMENU *menu;
+ MENUITEM *item;
+
+ menu = grab_menu_ptr(hMenu);
+ if (!(item = MENU_FindItem(&menu, &nPos, wFlags)))
+ {
+ release_menu_ptr(menu);
+ return FALSE;
+ }
+
if (item->fType & MF_POPUP) DestroyMenu( item->hSubMenu );
- /* nPos is now the position of the item */
+ release_menu_ptr(menu);
+
+ /* nPos is now the position of the item */
RemoveMenu( hMenu, nPos, wFlags | MF_BYPOSITION );
return TRUE;
}
@@ -4059,23 +4164,28 @@ BOOL WINAPI DeleteMenu( HMENU hMenu, UINT nPos, UINT wFlags )
BOOL WINAPI ModifyMenuW( HMENU hMenu, UINT pos, UINT flags,
UINT_PTR id, LPCWSTR str )
{
- MENUITEM *item;
MENUITEMINFOW mii;
+ POPUPMENU *menu;
+ MENUITEM *item;
+ 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 (!(item = MENU_FindItem( &hMenu, &pos, flags )))
+ menu = grab_menu_ptr(hMenu);
+ if (!(item = MENU_FindItem(&menu, &pos, flags)))
{
+ release_menu_ptr(menu);
/* workaround for Word 95: pretend that SC_TASKLIST item exists */
- if (pos == SC_TASKLIST && !(flags & MF_BYPOSITION)) return TRUE;
- return FALSE;
+ return pos == SC_TASKLIST && !(flags & MF_BYPOSITION);
}
- MENU_GetMenu(hMenu)->Height = 0; /* force size recalculate */
+ menu->Height = 0; /* force size recalculate */
MENU_mnu2mnuii( flags, id, str, &mii);
- return SetMenuItemInfo_common( item, &mii, TRUE);
+ ret = SetMenuItemInfo_common(item, &mii, TRUE);
+ release_menu_ptr(menu);
+ return ret;
}
@@ -4134,9 +4244,15 @@ DWORD WINAPI GetMenuCheckMarkDimensions(void)
BOOL WINAPI SetMenuItemBitmaps( HMENU hMenu, UINT nPos, UINT wFlags,
HBITMAP hNewUnCheck, HBITMAP hNewCheck)
{
+ POPUPMENU *menu;
MENUITEM *item;
- if (!(item = MENU_FindItem( &hMenu, &nPos, wFlags ))) return FALSE;
+ menu = grab_menu_ptr(hMenu);
+ if (!(item = MENU_FindItem(&menu, &nPos, wFlags)))
+ {
+ release_menu_ptr(menu);
+ return FALSE;
+ }
if (!hNewCheck && !hNewUnCheck)
{
@@ -4148,6 +4264,7 @@ BOOL WINAPI SetMenuItemBitmaps( HMENU hMenu, UINT nPos, UINT wFlags,
item->hUnCheckBit = hNewUnCheck;
item->fState |= MF_USECHECKBITMAPS;
}
+ release_menu_ptr(menu);
return TRUE;
}
@@ -4418,11 +4535,22 @@ BOOL WINAPI SetMenu( HWND hWnd, HMENU hMenu )
*/
HMENU WINAPI GetSubMenu( HMENU hMenu, INT nPos )
{
- MENUITEM * lpmi;
+ HMENU submenu = 0;
+ POPUPMENU *menu;
+ MENUITEM *item;
+
+ menu = grab_menu_ptr(hMenu);
+ if (!(item = MENU_FindItem(&menu, (UINT *)&nPos, MF_BYPOSITION)))
+ {
+ release_menu_ptr(menu);
+ return 0;
+ }
- if (!(lpmi = MENU_FindItem(&hMenu,(UINT*)&nPos,MF_BYPOSITION))) return 0;
- if (!(lpmi->fType & MF_POPUP)) return 0;
- return lpmi->hSubMenu;
+ if (item->fType & MF_POPUP)
+ submenu = item->hSubMenu;
+ release_menu_ptr(menu);
+
+ return submenu;
}
@@ -4631,31 +4759,39 @@ BOOL WINAPI IsMenu(HMENU hmenu)
* GetMenuItemInfo_common
*/
-static BOOL GetMenuItemInfo_common ( HMENU hmenu, UINT item, BOOL bypos,
+static BOOL GetMenuItemInfo_common ( HMENU hmenu, UINT id, BOOL bypos,
LPMENUITEMINFOW lpmii, BOOL unicode)
{
- MENUITEM *menu = MENU_FindItem (&hmenu, &item, bypos ? MF_BYPOSITION : 0);
-
- debug_print_menuitem("GetMenuItemInfo_common: ", menu, "");
+ POPUPMENU *menu;
+ MENUITEM *item;
- if (!menu) {
+ menu = grab_menu_ptr(hmenu);
+ if (!(item = MENU_FindItem(&menu, &id, bypos ? MF_BYPOSITION : 0)))
+ {
+ release_menu_ptr(menu);
SetLastError( ERROR_MENU_ITEM_NOT_FOUND);
return FALSE;
}
- if( lpmii->fMask & MIIM_TYPE) {
- if( lpmii->fMask & ( MIIM_STRING | MIIM_FTYPE | MIIM_BITMAP)) {
- WARN("invalid combination of fMask bits used\n");
- /* this does not happen on Win9x/ME */
- SetLastError( ERROR_INVALID_PARAMETER);
- return FALSE;
- }
- lpmii->fType = menu->fType & MENUITEMINFO_TYPE_MASK;
- if (menu->hbmpItem && !IS_MAGIC_BITMAP(menu->hbmpItem))
+ debug_print_menuitem("GetMenuItemInfo_common: ", item, "");
+
+ if ((lpmii->fMask & MIIM_TYPE) && (lpmii->fMask & (MIIM_STRING | MIIM_FTYPE | MIIM_BITMAP)))
+ {
+ release_menu_ptr(menu);
+ WARN("invalid combination of fMask bits used\n");
+ /* this does not happen on Win9x/ME */
+ SetLastError( ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+
+ if (lpmii->fMask & MIIM_TYPE)
+ {
+ lpmii->fType = item->fType & MENUITEMINFO_TYPE_MASK;
+ if (item->hbmpItem && !IS_MAGIC_BITMAP(item->hbmpItem))
lpmii->fType |= MFT_BITMAP;
- lpmii->hbmpItem = menu->hbmpItem; /* not on Win9x/ME */
+ lpmii->hbmpItem = item->hbmpItem; /* not on Win9x/ME */
if( lpmii->fType & MFT_BITMAP) {
- lpmii->dwTypeData = (LPWSTR) menu->hbmpItem;
+ lpmii->dwTypeData = (LPWSTR)item->hbmpItem;
lpmii->cch = 0;
} else if( lpmii->fType & (MFT_OWNERDRAW | MFT_SEPARATOR)) {
/* this does not happen on Win9x/ME */
@@ -4666,7 +4802,8 @@ static BOOL GetMenuItemInfo_common ( HMENU hmenu, UINT item, BOOL bypos,
/* copy the text string */
if ((lpmii->fMask & (MIIM_TYPE|MIIM_STRING))) {
- if( !menu->text ) {
+ if (!item->text)
+ {
if(lpmii->dwTypeData && lpmii->cch) {
if( unicode)
*((WCHAR *)lpmii->dwTypeData) = 0;
@@ -4678,16 +4815,16 @@ static BOOL GetMenuItemInfo_common ( HMENU hmenu, UINT item, BOOL bypos,
int len;
if (unicode)
{
- len = strlenW(menu->text);
+ len = strlenW(item->text);
if(lpmii->dwTypeData && lpmii->cch)
- lstrcpynW(lpmii->dwTypeData, menu->text, lpmii->cch);
+ lstrcpynW(lpmii->dwTypeData, item->text, lpmii->cch);
}
else
{
- len = WideCharToMultiByte( CP_ACP, 0, menu->text, -1, NULL,
+ len = WideCharToMultiByte( CP_ACP, 0, item->text, -1, NULL,
0, NULL, NULL ) - 1;
if(lpmii->dwTypeData && lpmii->cch)
- if (!WideCharToMultiByte( CP_ACP, 0, menu->text, -1,
+ if (!WideCharToMultiByte( CP_ACP, 0, item->text, -1,
(LPSTR)lpmii->dwTypeData, lpmii->cch, NULL, NULL ))
((LPSTR)lpmii->dwTypeData)[lpmii->cch - 1] = 0;
}
@@ -4706,33 +4843,35 @@ static BOOL GetMenuItemInfo_common ( HMENU hmenu, UINT item, BOOL bypos,
}
if (lpmii->fMask & MIIM_FTYPE)
- lpmii->fType = menu->fType & MENUITEMINFO_TYPE_MASK;
+ lpmii->fType = item->fType & MENUITEMINFO_TYPE_MASK;
if (lpmii->fMask & MIIM_BITMAP)
- lpmii->hbmpItem = menu->hbmpItem;
+ lpmii->hbmpItem = item->hbmpItem;
if (lpmii->fMask & MIIM_STATE)
- lpmii->fState = menu->fState & MENUITEMINFO_STATE_MASK;
+ lpmii->fState = item->fState & MENUITEMINFO_STATE_MASK;
if (lpmii->fMask & MIIM_ID)
- lpmii->wID = menu->wID;
+ lpmii->wID = item->wID;
if (lpmii->fMask & MIIM_SUBMENU)
- lpmii->hSubMenu = menu->hSubMenu;
+ lpmii->hSubMenu = item->hSubMenu;
else {
/* hSubMenu is always cleared
* (not on Win9x/ME ) */
lpmii->hSubMenu = 0;
}
- if (lpmii->fMask & MIIM_CHECKMARKS) {
- lpmii->hbmpChecked = menu->hCheckBit;
- lpmii->hbmpUnchecked = menu->hUnCheckBit;
+ if (lpmii->fMask & MIIM_CHECKMARKS)
+ {
+ lpmii->hbmpChecked = item->hCheckBit;
+ lpmii->hbmpUnchecked = item->hUnCheckBit;
}
if (lpmii->fMask & MIIM_DATA)
- lpmii->dwItemData = menu->dwItemData;
+ lpmii->dwItemData = item->dwItemData;
- return TRUE;
+ release_menu_ptr(menu);
+ return TRUE;
}
/**********************************************************************
@@ -4946,44 +5085,56 @@ static BOOL MENU_NormalizeMenuItemInfoStruct( const MENUITEMINFOW *pmii_in,
/**********************************************************************
* SetMenuItemInfoA (USER32.@)
*/
-BOOL WINAPI SetMenuItemInfoA(HMENU hmenu, UINT item, BOOL bypos,
+BOOL WINAPI SetMenuItemInfoA(HMENU hmenu, UINT id, BOOL bypos,
const MENUITEMINFOA *lpmii)
{
- MENUITEM *menuitem;
MENUITEMINFOW mii;
+ POPUPMENU *menu;
+ MENUITEM *item;
+ BOOL ret;
- TRACE("hmenu %p, item %u, by pos %d, info %p\n", hmenu, item, bypos, lpmii);
+ TRACE("hmenu %p, id %u, by pos %d, info %p\n", hmenu, id, bypos, lpmii);
if (!MENU_NormalizeMenuItemInfoStruct( (const MENUITEMINFOW *)lpmii, &mii )) return FALSE;
- if (!(menuitem = MENU_FindItem( &hmenu, &item, bypos? MF_BYPOSITION : 0 )))
+ menu = grab_menu_ptr(hmenu);
+ if (!(item = MENU_FindItem(&menu, &id, bypos ? MF_BYPOSITION : 0)))
{
+ release_menu_ptr(menu);
/* workaround for Word 95: pretend that SC_TASKLIST item exists */
- if (item == SC_TASKLIST && !bypos) return TRUE;
- return FALSE;
+ return id == SC_TASKLIST && !bypos;
}
- return SetMenuItemInfo_common( menuitem, &mii, FALSE );
+
+ ret = SetMenuItemInfo_common( item, &mii, FALSE );
+ release_menu_ptr(menu);
+ return ret;
}
/**********************************************************************
* SetMenuItemInfoW (USER32.@)
*/
-BOOL WINAPI SetMenuItemInfoW(HMENU hmenu, UINT item, BOOL bypos,
+BOOL WINAPI SetMenuItemInfoW(HMENU hmenu, UINT id, BOOL bypos,
const MENUITEMINFOW *lpmii)
{
- MENUITEM *menuitem;
MENUITEMINFOW mii;
+ POPUPMENU *menu;
+ MENUITEM *item;
+ BOOL ret;
- TRACE("hmenu %p, item %u, by pos %d, info %p\n", hmenu, item, bypos, lpmii);
+ TRACE("hmenu %p, id %u, by pos %d, info %p\n", hmenu, id, bypos, lpmii);
if (!MENU_NormalizeMenuItemInfoStruct( lpmii, &mii )) return FALSE;
- if (!(menuitem = MENU_FindItem( &hmenu, &item, bypos? MF_BYPOSITION : 0 )))
+
+ menu = grab_menu_ptr(hmenu);
+ if (!(item = MENU_FindItem(&menu, &id, bypos ? MF_BYPOSITION : 0)))
{
+ release_menu_ptr(menu);
/* workaround for Word 95: pretend that SC_TASKLIST item exists */
- if (item == SC_TASKLIST && !bypos) return TRUE;
- return FALSE;
+ return id == SC_TASKLIST && !bypos;
}
- return SetMenuItemInfo_common( menuitem, &mii, TRUE );
+ ret = SetMenuItemInfo_common( item, &mii, TRUE );
+ release_menu_ptr(menu);
+ return ret;
}
static BOOL set_menu_default_item(POPUPMENU *menu, UINT uItem, UINT bypos)
@@ -5092,13 +5243,18 @@ BOOL WINAPI InsertMenuItemA(HMENU hMenu, UINT uItem, BOOL bypos,
{
MENUITEM *item;
MENUITEMINFOW mii;
+ POPUPMENU *menu;
+ BOOL ret;
TRACE("hmenu %p, item %04x, by pos %d, info %p\n", hMenu, uItem, bypos, lpmii);
if (!MENU_NormalizeMenuItemInfoStruct( (const MENUITEMINFOW *)lpmii, &mii )) return FALSE;
- item = MENU_InsertItem(hMenu, uItem, bypos ? MF_BYPOSITION : 0 );
- return SetMenuItemInfo_common(item, &mii, FALSE);
+ menu = grab_menu_ptr(hMenu);
+ item = MENU_InsertItem(menu, uItem, bypos ? MF_BYPOSITION : 0 );
+ ret = SetMenuItemInfo_common(item, &mii, FALSE);
+ release_menu_ptr(menu);
+ return ret;
}
@@ -5110,13 +5266,18 @@ BOOL WINAPI InsertMenuItemW(HMENU hMenu, UINT uItem, BOOL bypos,
{
MENUITEM *item;
MENUITEMINFOW mii;
+ POPUPMENU *menu;
+ BOOL ret;
TRACE("hmenu %p, item %04x, by pos %d, info %p\n", hMenu, uItem, bypos, lpmii);
if (!MENU_NormalizeMenuItemInfoStruct( lpmii, &mii )) return FALSE;
- item = MENU_InsertItem(hMenu, uItem, bypos ? MF_BYPOSITION : 0 );
- return SetMenuItemInfo_common(item, &mii, TRUE);
+ menu = grab_menu_ptr(hMenu);
+ item = MENU_InsertItem(menu, uItem, bypos ? MF_BYPOSITION : 0 );
+ ret = SetMenuItemInfo_common(item, &mii, TRUE);
+ release_menu_ptr(menu);
+ return ret;
}
/**********************************************************************
@@ -5130,7 +5291,7 @@ BOOL WINAPI CheckMenuRadioItem(HMENU hMenu,
BOOL done = FALSE;
UINT i;
MENUITEM *mi_first = NULL, *mi_check;
- HMENU m_first, m_check;
+ POPUPMENU *m_first = NULL, *m_check = NULL;
for (i = first; i <= last; i++)
{
@@ -5138,17 +5299,26 @@ BOOL WINAPI CheckMenuRadioItem(HMENU hMenu,
if (!mi_first)
{
- m_first = hMenu;
- mi_first = MENU_FindItem(&m_first, &pos, bypos);
- if (!mi_first) continue;
+ m_first = grab_menu_ptr(hMenu);
+ if (!(mi_first = MENU_FindItem(&m_first, &pos, bypos)))
+ {
+ release_menu_ptr(m_first);
+ m_first = NULL;
+ continue;
+ }
mi_check = mi_first;
- m_check = m_first;
+ m_check = grab_menu_ptr(m_first->obj.handle);
}
else
{
- m_check = hMenu;
- mi_check = MENU_FindItem(&m_check, &pos, bypos);
- if (!mi_check) continue;
+ release_menu_ptr(m_check);
+ m_check = grab_menu_ptr(hMenu);
+ if (!(mi_check = MENU_FindItem(&m_check, &pos, bypos)))
+ {
+ release_menu_ptr(m_check);
+ m_check = NULL;
+ continue;
+ }
}
if (m_first != m_check) continue;
@@ -5166,6 +5336,8 @@ BOOL WINAPI CheckMenuRadioItem(HMENU hMenu,
mi_check->fState &= ~MFS_CHECKED;
}
}
+ release_menu_ptr(m_first);
+ release_menu_ptr(m_check);
return done;
}
@@ -5186,21 +5358,30 @@ BOOL WINAPI GetMenuItemRect(HWND hwnd, HMENU hMenu, UINT uItem, RECT *rect)
TRACE("(%p,%p,%d,%p)\n", hwnd, hMenu, uItem, rect);
- item = MENU_FindItem (&hMenu, &uItem, MF_BYPOSITION);
- if ((rect == NULL) || (item == NULL))
+ if (!rect)
return FALSE;
- menu = MENU_GetMenu(hMenu);
- if (!menu) return FALSE;
+ menu = grab_menu_ptr(hMenu);
+ if (!(item = MENU_FindItem(&menu, &uItem, MF_BYPOSITION)))
+ {
+ release_menu_ptr(menu);
+ return FALSE;
+ }
if (!hwnd) hwnd = menu->hWnd;
- if (!hwnd) return FALSE;
+
+ if (!hwnd)
+ {
+ release_menu_ptr(menu);
+ return FALSE;
+ }
*rect = item->rect;
OffsetRect(rect, menu->items_rect.left, menu->items_rect.top);
- MapWindowPoints(hwnd, 0, (POINT *)rect, 2);
+ release_menu_ptr(menu);
+ MapWindowPoints(hwnd, 0, (POINT *)rect, 2);
return TRUE;
}
@@ -5415,6 +5596,8 @@ static BOOL translate_accelerator( HWND hWnd, UINT message, WPARAM wParam, LPARA
{
HMENU hMenu, hSubMenu, hSysMenu;
UINT uSysStat = (UINT)-1, uStat = (UINT)-1, nPos;
+ POPUPMENU *submenu;
+ BOOL res;
hMenu = (GetWindowLongW( hWnd, GWL_STYLE ) & WS_CHILD) ? 0 : GetMenu(hWnd);
hSysMenu = get_win_sys_menu( hWnd );
@@ -5423,7 +5606,12 @@ static BOOL translate_accelerator( HWND hWnd, UINT message, WPARAM wParam, LPARA
/* 1. in the system menu */
hSubMenu = hSysMenu;
nPos = cmd;
- if(MENU_FindItem(&hSubMenu, &nPos, MF_BYCOMMAND))
+ submenu = grab_menu_ptr(hSubMenu);
+ res = MENU_FindItem(&submenu, &nPos, MF_BYCOMMAND) != NULL;
+ if (res)
+ hSubMenu = submenu->obj.handle;
+ release_menu_ptr(submenu);
+ if (res)
{
if (GetCapture())
mesg = 2;
@@ -5445,7 +5633,13 @@ static BOOL translate_accelerator( HWND hWnd, UINT message, WPARAM wParam, LPARA
{
hSubMenu = hMenu;
nPos = cmd;
- if(MENU_FindItem(&hSubMenu, &nPos, MF_BYCOMMAND))
+
+ submenu = grab_menu_ptr(hSubMenu);
+ res = MENU_FindItem(&submenu, &nPos, MF_BYCOMMAND) != NULL;
+ if (res)
+ hSubMenu = submenu->obj.handle;
+ release_menu_ptr(submenu);
+ if (res)
{
if (GetCapture())
mesg = 2;
--
2.17.0