
user: use server calls to manage menu info server-side


Thomas Kho

---

 dlls/user/menu.c       |  482 ++++++++++++++++++++++++++++++++++--------------
 dlls/user/tests/menu.c |   22 +-
 2 files changed, 352 insertions(+), 152 deletions(-)

diff --git a/dlls/user/menu.c b/dlls/user/menu.c
index bc1db93..aa0a3aa 100644
--- a/dlls/user/menu.c
+++ b/dlls/user/menu.c
@@ -6,6 +6,7 @@
  * Copyright 1997 Morten Welinder
  * Copyright 2005 Maxime Bellengé
  * Copyright 2006 Phil Krylov
+ * Copyright 2006 Google (Thomas Kho)
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -285,17 +286,85 @@ static void do_debug_print_menuitem(cons
 /***********************************************************************
  *           MENU_GetMenu
  *
- * Validate the given menu handle and returns the menu structure pointer.
+ * Get a local copy of menu for given hMenu
  */
-static POPUPMENU *MENU_GetMenu(HMENU hMenu)
+static NTSTATUS MENU_GetMenu(HMENU hMenu, POPUPMENU *menu)
 {
-    POPUPMENU *menu = USER_HEAP_LIN_ADDR(hMenu);
-    if (!menu || menu->wMagic != MENU_MAGIC)
+    NTSTATUS ret;
+    SERVER_START_REQ( get_menu_info )
     {
-        WARN("invalid menu handle=%p, ptr=%p, magic=%x\n", hMenu, menu, menu? menu->wMagic:0);
-        menu = NULL;
+        req->handle = hMenu;
+        if ((ret = wine_server_call_err( req )))
+            WARN("error hMenu=0x%x, status=%ld\n", (unsigned) hMenu, ret);
+        else if (menu)
+        {
+            menu->wFlags = reply->flags;
+            menu->Width = reply->width;
+            menu->Height = reply->height;
+            menu->nItems = reply->nitems;
+            menu->hWnd = reply->hwnd;
+            menu->items = reply->items;
+            menu->FocusedItem = reply->focuseditem;
+            menu->hwndOwner = reply->hwndowner;
+            menu->bTimeToHide = reply->timetohide;
+            menu->bScrolling = reply->scrolling;
+            menu->nScrollPos = reply->scrollpos;
+            menu->nTotalHeight = reply->totalheight;
+
+            menu->dwStyle = reply->style;
+            menu->cyMax = reply->cymax;
+            menu->hbrBack = reply->back;
+            menu->dwContextHelpID = reply->contexthelpid;
+            menu->dwMenuData = reply->menudata;
+            menu->hSysMenuOwner = reply->sysmenuowner;
+            menu->maxBmpSize.cx = reply->maxbmpsize.x;
+            menu->maxBmpSize.cy = reply->maxbmpsize.y;
+        }
     }
-    return menu;
+    SERVER_END_REQ;
+    return ret;
+}
+
+/***********************************************************************
+ *           MENU_UpdateMenu
+ *
+ * Update specific fields in server's copy of menu
+ */
+static NTSTATUS MENU_UpdateMenu(HMENU hMenu, POPUPMENU *menu, unsigned int mask)
+{
+    NTSTATUS ret = STATUS_INVALID_HANDLE;
+    SERVER_START_REQ( set_menu_info )
+    {
+        req->handle = hMenu;
+        req->mask = mask;
+
+        req->flags = menu->wFlags;
+        req->width = menu->Width;
+        req->height = menu->Height;
+        req->nitems = menu->nItems;
+        req->hwnd = menu->hWnd;
+        req->items = menu->items;
+        req->focuseditem = menu->FocusedItem;
+        req->hwndowner = menu->hwndOwner;
+        req->timetohide = menu->bTimeToHide;
+        req->scrolling = menu->bScrolling;
+        req->scrollpos = menu->nScrollPos;
+        req->totalheight = menu->nTotalHeight;
+
+        req->style = menu->dwStyle;
+        req->cymax = menu->cyMax;
+        req->back = menu->hbrBack;
+        req->contexthelpid = menu->dwContextHelpID;
+        req->menudata = menu->dwMenuData;
+        req->sysmenuowner = menu->hSysMenuOwner;
+        req->maxbmpsize.x = menu->maxBmpSize.cx;
+        req->maxbmpsize.y = menu->maxBmpSize.cy;
+
+        if ((ret = wine_server_call_err( req )))
+            WARN("error hMenu=0x%x, status=%ld\n", (unsigned) hMenu, ret);
+    }
+    SERVER_END_REQ;
+    return ret;
 }
 
 /***********************************************************************
@@ -416,8 +485,11 @@ static HMENU MENU_CopySysPopup(void)
     HMENU hMenu = LoadMenuW(user32_module, sysmenuW);
 
     if( hMenu ) {
-        POPUPMENU* menu = MENU_GetMenu(hMenu);
+        POPUPMENU tmpmenu;
+        POPUPMENU* menu = &tmpmenu;
+        MENU_GetMenu(hMenu, menu);
         menu->wFlags |= MF_SYSMENU | MF_POPUP;
+        MENU_UpdateMenu(hMenu, menu, SET_MI_FLAGS);
 	SetMenuDefaultItem(hMenu, SC_CLOSE, FALSE);
     }
     else
@@ -445,9 +517,12 @@ HMENU MENU_GetSysMenu( HWND hWnd, HMENU 
     TRACE("loading system menu, hWnd %p, hPopupMenu %p\n", hWnd, hPopupMenu);
     if ((hMenu = CreateMenu()))
     {
-	POPUPMENU *menu = MENU_GetMenu(hMenu);
+        POPUPMENU tmpmenu;
+        POPUPMENU *menu = &tmpmenu;
+        MENU_GetMenu(hMenu, menu);
 	menu->wFlags = MF_SYSMENU;
 	menu->hWnd = WIN_GetFullHandle( hWnd );
+        MENU_UpdateMenu(hMenu, menu, SET_MI_FLAGS|SET_MI_HWND);
 	TRACE("hWnd %p (hMenu %p)\n", menu->hWnd, hMenu);
 
 	if (!hPopupMenu)
@@ -461,9 +536,14 @@ HMENU MENU_GetSysMenu( HWND hWnd, HMENU 
 	    InsertMenuW( hMenu, -1, MF_SYSMENU | MF_POPUP | MF_BYPOSITION,
                          (UINT_PTR)hPopupMenu, NULL );
 
+            MENU_GetMenu(hMenu, menu);
             menu->items[0].fType = MF_SYSMENU | MF_POPUP;
             menu->items[0].fState = 0;
-            if ((menu = MENU_GetMenu(hPopupMenu))) menu->wFlags |= MF_SYSMENU;
+            if (!MENU_GetMenu(hPopupMenu, menu))
+            {
+                menu->wFlags |= MF_SYSMENU;
+                MENU_UpdateMenu(hPopupMenu, menu, SET_MI_FLAGS);
+            }
 
 	    TRACE("hMenu=%p (hPopup %p)\n", hMenu, hPopupMenu );
 	    return hMenu;
@@ -512,10 +592,11 @@ static void MENU_InitSysMenuPopup( HMENU
 static UINT  MENU_GetStartOfNextColumn(
     HMENU  hMenu )
 {
-    POPUPMENU *menu = MENU_GetMenu(hMenu);
+    POPUPMENU tmpmenu;
+    POPUPMENU *menu = &tmpmenu;
     UINT i;
 
-    if(!menu)
+    if(MENU_GetMenu(hMenu, menu))
 	return NO_SELECTED_ITEM;
 
     i = menu->FocusedItem + 1;
@@ -541,10 +622,11 @@ static UINT  MENU_GetStartOfNextColumn(
 static UINT  MENU_GetStartOfPrevColumn(
     HMENU  hMenu )
 {
-    POPUPMENU *menu = MENU_GetMenu(hMenu);
+    POPUPMENU tmpmenu;
+    POPUPMENU *menu = &tmpmenu;
     UINT  i;
 
-    if( !menu )
+    if( MENU_GetMenu(hMenu, menu) )
 	return NO_SELECTED_ITEM;
 
     if( menu->FocusedItem == 0 || menu->FocusedItem == NO_SELECTED_ITEM )
@@ -579,12 +661,14 @@ static UINT  MENU_GetStartOfPrevColumn(
  */
 static MENUITEM *MENU_FindItem( HMENU *hmenu, UINT *nPos, UINT wFlags )
 {
-    POPUPMENU *menu;
+    POPUPMENU tmpmenu;
+    POPUPMENU *menu = &tmpmenu;
     MENUITEM *fallback = NULL;
     UINT fallback_pos = 0;
     UINT i;
 
-    if ((*hmenu == (HMENU)0xffff) || (!(menu = MENU_GetMenu(*hmenu)))) return NULL;
+    if ((*hmenu == (HMENU)0xffff) || (MENU_GetMenu(*hmenu, menu)))
+        return NULL;
     if (wFlags & MF_BYPOSITION)
     {
 	if (*nPos >= menu->nItems) return NULL;
@@ -634,11 +718,12 @@ static MENUITEM *MENU_FindItem( HMENU *h
  */
 UINT MENU_FindSubMenu( HMENU *hmenu, HMENU hSubTarget )
 {
-    POPUPMENU *menu;
+    POPUPMENU tmpmenu;
+    POPUPMENU *menu = &tmpmenu;
     UINT i;
     MENUITEM *item;
     if (((*hmenu)==(HMENU)0xffff) ||
-            (!(menu = MENU_GetMenu(*hmenu))))
+            (MENU_GetMenu(*hmenu, menu)))
         return NO_SELECTED_ITEM;
     item = menu->items;
     for (i = 0; i < menu->nItems; i++, item++) {
@@ -737,9 +822,12 @@ static UINT MENU_FindItemByKey( HWND hwn
 
     if (hmenu)
     {
-	POPUPMENU *menu = MENU_GetMenu( hmenu );
-	MENUITEM *item = menu->items;
+        POPUPMENU tmpmenu;
+        POPUPMENU *menu = &tmpmenu;
+	MENUITEM *item;
 	LRESULT menuchar;
+        MENU_GetMenu(hmenu, menu);
+        item = menu->items;
 
 	if( !forceMenuChar )
 	{
@@ -1337,7 +1425,8 @@ static void MENU_DrawMenuItem( HWND hwnd
     BOOL flat_menu = FALSE;
     int bkgnd;
     UINT arrow_bitmap_width = 0, arrow_bitmap_height = 0;
-    POPUPMENU *menu = MENU_GetMenu(hmenu);
+    POPUPMENU tmpmenu;
+    POPUPMENU *menu = &tmpmenu;
     RECT bmprc;
 
     debug_print_menuitem("MENU_DrawMenuItem: ", lpitem, "");
@@ -1385,7 +1474,8 @@ static void MENU_DrawMenuItem( HWND hwnd
 
     TRACE("rect=%s\n", wine_dbgstr_rect( &lpitem->rect));
     rect = lpitem->rect;
-    MENU_AdjustMenuItemRect(MENU_GetMenu(hmenu), &rect);
+    MENU_GetMenu(hmenu, menu);
+    MENU_AdjustMenuItemRect(menu, &rect);
 
     if (lpitem->fType & MF_OWNERDRAW)
     {
@@ -1693,7 +1783,8 @@ static void MENU_DrawPopupMenu( HWND hwn
 	hPrevPen = SelectObject( hdc, GetStockObject( NULL_PEN ) );
 	if( hPrevPen )
 	{
-	    POPUPMENU *menu;
+            POPUPMENU tmpmenu;
+	    POPUPMENU *menu = &tmpmenu;
 	    BOOL flat_menu = FALSE;
 
 	    SystemParametersInfoW (SPI_GETFLATMENU, 0, &flat_menu, 0);
@@ -1702,7 +1793,7 @@ static void MENU_DrawPopupMenu( HWND hwn
 	    else
 		DrawEdge (hdc, &rect, EDGE_RAISED, BF_RECT);
 
-            if( (menu = MENU_GetMenu( hmenu )))
+            if( (!MENU_GetMenu( hmenu, menu )))
             {
                 /* draw menu items */
                 if( menu->nItems)
@@ -1735,12 +1826,12 @@ static void MENU_DrawPopupMenu( HWND hwn
 UINT MENU_DrawMenuBar( HDC hDC, LPRECT lprect, HWND hwnd,
                          BOOL suppress_draw)
 {
-    LPPOPUPMENU lppop;
+    POPUPMENU tmppop;
+    LPPOPUPMENU lppop = &tmppop;
     HFONT hfontOld = 0;
     HMENU hMenu = GetMenu(hwnd);
 
-    lppop = MENU_GetMenu( hMenu );
-    if (lppop == NULL || lprect == NULL)
+    if (MENU_GetMenu(hMenu, lppop) || lprect == NULL)
     {
         return GetSystemMetrics(SM_CYMENU);
     }
@@ -1750,7 +1841,10 @@ UINT MENU_DrawMenuBar( HDC hDC, LPRECT l
 	hfontOld = SelectObject( hDC, get_menu_font(FALSE));
 
 	if (lppop->Height == 0)
+        {
 		MENU_MenuBarCalcSize(hDC, lprect, lppop, hwnd);
+                MENU_UpdateMenu(hMenu, lppop, SET_MI_MAXBMPSIZE);
+        }
 
 	lprect->bottom = lprect->top + lppop->Height;
 
@@ -1770,17 +1864,19 @@ UINT MENU_DrawMenuBar( HDC hDC, LPRECT l
 static BOOL MENU_ShowPopup( HWND hwndOwner, HMENU hmenu, UINT id,
                               INT x, INT y, INT xanchor, INT yanchor )
 {
-    POPUPMENU *menu;
+    POPUPMENU tmpmenu;
+    POPUPMENU *menu = &tmpmenu;
     UINT width, height;
 
     TRACE("owner=%p hmenu=%p id=0x%04x x=0x%04x y=0x%04x xa=0x%04x ya=0x%04x\n",
           hwndOwner, hmenu, id, x, y, xanchor, yanchor);
 
-    if (!(menu = MENU_GetMenu( hmenu ))) return FALSE;
+    if (MENU_GetMenu( hmenu, menu )) return FALSE;
     if (menu->FocusedItem != NO_SELECTED_ITEM)
     {
 	menu->items[menu->FocusedItem].fState &= ~(MF_HILITE|MF_MOUSESELECT);
 	menu->FocusedItem = NO_SELECTED_ITEM;
+        MENU_UpdateMenu(hmenu, menu, SET_MI_FOCUSITEM);
     }
 
     /* store the owner for DrawItem */
@@ -1788,6 +1884,7 @@ static BOOL MENU_ShowPopup( HWND hwndOwn
 
     menu->nScrollPos = 0;
     MENU_PopupMenuCalcSize( menu, hwndOwner );
+    MENU_UpdateMenu(hmenu, menu, SET_MI_WIDTH|SET_MI_HEIGHT|SET_MI_MAXBMPSIZE|SET_MI_TOTALHEIGHT|SET_MI_SCROLLING|SET_MI_SCROLLPOS|SET_MI_OWNER);
 
     /* adjust popup menu pos so that it fits within the desktop */
 
@@ -1819,6 +1916,7 @@ static BOOL MENU_ShowPopup( HWND hwndOwn
                                 WS_POPUP, x, y, width, height,
                                 hwndOwner, 0, (HINSTANCE)GetWindowLongPtrW(hwndOwner, GWLP_HINSTANCE),
                                 (LPVOID)hmenu );
+    MENU_UpdateMenu( hmenu, menu, SET_MI_HWND );
     if( !menu->hWnd ) return FALSE;
     if (!top_popup) top_popup = menu->hWnd;
 
@@ -1878,13 +1976,14 @@ MENU_EnsureMenuItemVisible(LPPOPUPMENU l
 static void MENU_SelectItem( HWND hwndOwner, HMENU hmenu, UINT wIndex,
                              BOOL sendMenuSelect, HMENU topmenu )
 {
-    LPPOPUPMENU lppop;
+    POPUPMENU tmppop;
+    LPPOPUPMENU lppop = &tmppop;
     HDC hdc;
 
     TRACE("owner=%p menu=%p index=0x%04x select=0x%04x\n", hwndOwner, hmenu, wIndex, sendMenuSelect);
 
-    lppop = MENU_GetMenu( hmenu );
-    if ((!lppop) || (!lppop->nItems) || (!lppop->hWnd)) return;
+    if (MENU_GetMenu( hmenu, lppop ) || (!lppop->nItems)
+        || (!lppop->hWnd)) return;
 
     if (lppop->FocusedItem == wIndex) return;
     if (lppop->wFlags & MF_POPUP) hdc = GetDC( lppop->hWnd );
@@ -1904,6 +2003,7 @@ static void MENU_SelectItem( HWND hwndOw
 
       /* Highlight new item (if any) */
     lppop->FocusedItem = wIndex;
+    MENU_UpdateMenu(hmenu, lppop, SET_MI_FOCUSITEM);
     if (lppop->FocusedItem != NO_SELECTED_ITEM)
     {
         if(!(lppop->items[wIndex].fType & MF_SEPARATOR)) {
@@ -1926,8 +2026,11 @@ static void MENU_SelectItem( HWND hwndOw
         if(topmenu){
             int pos;
             if((pos=MENU_FindSubMenu(&topmenu, hmenu))!=NO_SELECTED_ITEM){
-                POPUPMENU *ptm = MENU_GetMenu( topmenu );
-                MENUITEM *ip = &ptm->items[pos];
+                POPUPMENU tmpptm;
+                POPUPMENU *ptm = &tmpptm;
+                MENUITEM *ip;
+                MENU_GetMenu( topmenu, ptm );
+                ip = &ptm->items[pos];
                 SendMessageW( hwndOwner, WM_MENUSELECT, MAKELONG(pos,
                          ip->fType | ip->fState |
                          (ptm->wFlags & MF_SYSMENU)), (LPARAM)topmenu);
@@ -1948,12 +2051,12 @@ static void MENU_SelectItem( HWND hwndOw
 static void MENU_MoveSelection( HWND hwndOwner, HMENU hmenu, INT offset )
 {
     INT i;
-    POPUPMENU *menu;
+    POPUPMENU tmpmenu;
+    POPUPMENU *menu = &tmpmenu;
 
     TRACE("hwnd=%p hmenu=%p off=0x%04x\n", hwndOwner, hmenu, offset);
 
-    menu = MENU_GetMenu( hmenu );
-    if ((!menu) || (!menu->items)) return;
+    if ((MENU_GetMenu(hmenu, menu)) || (!menu->items)) return;
 
     if ( menu->FocusedItem != NO_SELECTED_ITEM )
     {
@@ -2031,8 +2134,13 @@ static BOOL MENU_SetItemData( MENUITEM *
 
     if (flags & MF_POPUP)
     {
-	POPUPMENU *menu = MENU_GetMenu((HMENU)id);
-        if (menu) menu->wFlags |= MF_POPUP;
+        POPUPMENU tmpmenu;
+        POPUPMENU *menu = &tmpmenu;
+        if (!MENU_GetMenu((HMENU)id, menu))
+        {
+            menu->wFlags |= MF_POPUP;
+            MENU_UpdateMenu((HMENU)id, menu, SET_MI_FLAGS);
+        }
 	else
         {
             item->wID = 0;
@@ -2069,9 +2177,10 @@ static BOOL MENU_SetItemData( MENUITEM *
 static MENUITEM *MENU_InsertItem( HMENU hMenu, UINT pos, UINT flags )
 {
     MENUITEM *newItems;
-    POPUPMENU *menu;
+    POPUPMENU tmpmenu;
+    POPUPMENU *menu = &tmpmenu;
 
-    if (!(menu = MENU_GetMenu(hMenu)))
+    if (MENU_GetMenu(hMenu, menu))
         return NULL;
 
     /* Find where to insert new item */
@@ -2083,7 +2192,7 @@ static MENUITEM *MENU_InsertItem( HMENU 
         if (!MENU_FindItem( &hMenu, &pos, flags ))
             pos = menu->nItems;
         else {
-            if (!(menu = MENU_GetMenu( hMenu )))
+            if (MENU_GetMenu(hMenu, menu))
                 return NULL;
         }
     }
@@ -2108,6 +2217,7 @@ static MENUITEM *MENU_InsertItem( HMENU 
     menu->nItems++;
     memset( &newItems[pos], 0, sizeof(*newItems) );
     menu->Height = 0; /* force size recalculate */
+    MENU_UpdateMenu(hMenu, menu, SET_MI_ITEMS|SET_MI_NITEMS|SET_MI_HEIGHT);
     return &newItems[pos];
 }
 
@@ -2225,12 +2335,12 @@ static LPCSTR MENUEX_ParseResource( LPCS
  */
 static HMENU MENU_GetSubPopup( HMENU hmenu )
 {
-    POPUPMENU *menu;
+    POPUPMENU tmpmenu;
+    POPUPMENU *menu = &tmpmenu;
     MENUITEM *item;
 
-    menu = MENU_GetMenu( hmenu );
-
-    if ((!menu) || (menu->FocusedItem == NO_SELECTED_ITEM)) return 0;
+    if (MENU_GetMenu( hmenu, menu )
+        || (menu->FocusedItem == NO_SELECTED_ITEM)) return 0;
 
     item = &menu->items[menu->FocusedItem];
     if ((item->fType & MF_POPUP) && (item->fState & MF_MOUSESELECT))
@@ -2247,14 +2357,16 @@ static HMENU MENU_GetSubPopup( HMENU hme
 static void MENU_HideSubPopups( HWND hwndOwner, HMENU hmenu,
                                 BOOL sendMenuSelect )
 {
-    POPUPMENU *menu = MENU_GetMenu( hmenu );
+    POPUPMENU tmpmenu;
+    POPUPMENU *menu = &tmpmenu;
 
     TRACE("owner=%p hmenu=%p 0x%04x\n", hwndOwner, hmenu, sendMenuSelect);
 
-    if (menu && top_popup)
+    if (!MENU_GetMenu( hmenu, menu ) && top_popup)
     {
 	HMENU hsubmenu;
-	POPUPMENU *submenu;
+        POPUPMENU tmpsubmenu;
+	POPUPMENU *submenu = &tmpsubmenu;
 	MENUITEM *item;
 
 	if (menu->FocusedItem != NO_SELECTED_ITEM)
@@ -2266,11 +2378,12 @@ static void MENU_HideSubPopups( HWND hwn
 	    hsubmenu = item->hSubMenu;
 	} else return;
 
-	submenu = MENU_GetMenu( hsubmenu );
+        MENU_GetMenu( hsubmenu, submenu );
 	MENU_HideSubPopups( hwndOwner, hsubmenu, FALSE );
 	MENU_SelectItem( hwndOwner, hsubmenu, NO_SELECTED_ITEM, sendMenuSelect, 0 );
         DestroyWindow( submenu->hWnd );
         submenu->hWnd = 0;
+        MENU_UpdateMenu(hsubmenu, submenu, SET_MI_HWND);
     }
 }
 
@@ -2285,13 +2398,14 @@ static HMENU MENU_ShowSubPopup( HWND hwn
                                   BOOL selectFirst, UINT wFlags )
 {
     RECT rect;
-    POPUPMENU *menu;
+    POPUPMENU tmpmenu;
+    POPUPMENU *menu = &tmpmenu;
     MENUITEM *item;
     HDC hdc;
 
     TRACE("owner=%p hmenu=%p 0x%04x\n", hwndOwner, hmenu, selectFirst);
 
-    if (!(menu = MENU_GetMenu( hmenu ))) return hmenu;
+    if (MENU_GetMenu( hmenu, menu )) return hmenu;
 
     if (menu->FocusedItem == NO_SELECTED_ITEM) return hmenu;
 
@@ -2388,9 +2502,12 @@ HWND MENU_IsMenuActive(void)
  */
 static HMENU MENU_PtMenu( HMENU hMenu, POINT pt )
 {
-   POPUPMENU *menu = MENU_GetMenu( hMenu );
-   UINT item = menu->FocusedItem;
+   POPUPMENU tmpmenu;
+   POPUPMENU *menu = &tmpmenu;
+   UINT item;
    HMENU ret;
+   MENU_GetMenu( hMenu, menu );
+   item = menu->FocusedItem;
 
    /* try subpopup first (if any) */
    ret = (item != NO_SELECTED_ITEM &&
@@ -2426,11 +2543,12 @@ static HMENU MENU_PtMenu( HMENU hMenu, P
 static INT MENU_ExecFocusedItem( MTRACKER* pmt, HMENU hMenu, UINT wFlags )
 {
     MENUITEM *item;
-    POPUPMENU *menu = MENU_GetMenu( hMenu );
+    POPUPMENU tmpmenu;
+    POPUPMENU *menu = &tmpmenu;
 
     TRACE("%p hmenu=%p\n", pmt, hMenu);
 
-    if (!menu || !menu->nItems ||
+    if (MENU_GetMenu( hMenu, menu ) || !menu->nItems ||
 	(menu->FocusedItem == NO_SELECTED_ITEM)) return -1;
 
     item = &menu->items[menu->FocusedItem];
@@ -2476,8 +2594,10 @@ static INT MENU_ExecFocusedItem( MTRACKE
  */
 static void MENU_SwitchTracking( MTRACKER* pmt, HMENU hPtMenu, UINT id )
 {
-    POPUPMENU *ptmenu = MENU_GetMenu( hPtMenu );
-    POPUPMENU *topmenu = MENU_GetMenu( pmt->hTopMenu );
+    POPUPMENU tmpptmenu, tmptopmenu;
+    POPUPMENU *ptmenu = &tmpptmenu, *topmenu = &tmptopmenu;
+    MENU_GetMenu( hPtMenu, ptmenu );
+    MENU_GetMenu( pmt->hTopMenu, topmenu );
 
     TRACE("%p hmenu=%p 0x%04x\n", pmt, hPtMenu, id);
 
@@ -2506,8 +2626,10 @@ static BOOL MENU_ButtonDown( MTRACKER* p
     if (hPtMenu)
     {
 	UINT id = 0;
-	POPUPMENU *ptmenu = MENU_GetMenu( hPtMenu );
+        POPUPMENU tmpptmenu;
+        POPUPMENU *ptmenu = &tmpptmenu;
 	MENUITEM *item;
+        MENU_GetMenu( hPtMenu, ptmenu );
 
 	if( IS_SYSTEM_MENU(ptmenu) )
 	    item = ptmenu->items;
@@ -2547,8 +2669,10 @@ static INT MENU_ButtonUp( MTRACKER* pmt,
     if (hPtMenu)
     {
 	UINT id = 0;
-	POPUPMENU *ptmenu = MENU_GetMenu( hPtMenu );
 	MENUITEM *item;
+        POPUPMENU tmpptmenu;
+        POPUPMENU *ptmenu = &tmpptmenu;
+        MENU_GetMenu( hPtMenu, ptmenu );
 
         if( IS_SYSTEM_MENU(ptmenu) )
             item = ptmenu->items;
@@ -2570,6 +2694,7 @@ static INT MENU_ButtonUp( MTRACKER* pmt,
 		return 0;
 	}
 	ptmenu->bTimeToHide = TRUE;
+        MENU_UpdateMenu( hPtMenu, ptmenu, SET_MI_TIMETOHIDE );
     }
     return -1;
 }
@@ -2583,11 +2708,12 @@ static INT MENU_ButtonUp( MTRACKER* pmt,
 static BOOL MENU_MouseMove( MTRACKER* pmt, HMENU hPtMenu, UINT wFlags )
 {
     UINT id = NO_SELECTED_ITEM;
-    POPUPMENU *ptmenu = NULL;
+    POPUPMENU tmpptmenu;
+    POPUPMENU *ptmenu = &tmpptmenu;
 
     if( hPtMenu )
     {
-	ptmenu = MENU_GetMenu( hPtMenu );
+        MENU_GetMenu( hPtMenu, ptmenu );
         if( IS_SYSTEM_MENU(ptmenu) )
 	    id = 0;
         else
@@ -2640,7 +2766,9 @@ static void MENU_SetCapture( HWND hwnd )
  */
 static LRESULT MENU_DoNextMenu( MTRACKER* pmt, UINT vk )
 {
-    POPUPMENU *menu = MENU_GetMenu( pmt->hTopMenu );
+    POPUPMENU tmpmenu;
+    POPUPMENU *menu = &tmpmenu;
+    MENU_GetMenu( pmt->hTopMenu, menu );
 
     if( (vk == VK_LEFT &&  menu->FocusedItem == 0 ) ||
         (vk == VK_RIGHT && menu->FocusedItem == menu->nItems - 1))
@@ -2670,7 +2798,7 @@ static LRESULT MENU_DoNextMenu( MTRACKER
 
 	        if( vk == VK_LEFT )
 	        {
-		    menu = MENU_GetMenu( hNewMenu );
+                    MENU_GetMenu( hNewMenu, menu );
 		    id = menu->nItems - 1;
 	        }
 	    }
@@ -2779,7 +2907,9 @@ static BOOL MENU_KeyEscape(MTRACKER* pmt
 
     if (pmt->hCurrentMenu != pmt->hTopMenu)
     {
-        POPUPMENU *menu = MENU_GetMenu(pmt->hCurrentMenu);
+        POPUPMENU tmpmenu;
+        POPUPMENU *menu = &tmpmenu;
+        MENU_GetMenu(pmt->hCurrentMenu, menu);
 
         if (menu->wFlags & MF_POPUP)
         {
@@ -2810,12 +2940,13 @@ static BOOL MENU_KeyEscape(MTRACKER* pmt
  */
 static void MENU_KeyLeft( MTRACKER* pmt, UINT wFlags )
 {
-    POPUPMENU *menu;
+    POPUPMENU tmpmenu;
+    POPUPMENU *menu = &tmpmenu;
     HMENU hmenutmp, hmenuprev;
     UINT  prevcol;
 
     hmenuprev = hmenutmp = pmt->hTopMenu;
-    menu = MENU_GetMenu( hmenutmp );
+    MENU_GetMenu( hmenutmp, menu );
 
     /* Try to move 1 column left (if possible) */
     if( (prevcol = MENU_GetStartOfPrevColumn( pmt->hCurrentMenu )) !=
@@ -2864,12 +2995,15 @@ static void MENU_KeyLeft( MTRACKER* pmt,
 static void MENU_KeyRight( MTRACKER* pmt, UINT wFlags )
 {
     HMENU hmenutmp;
-    POPUPMENU *menu = MENU_GetMenu( pmt->hTopMenu );
+    POPUPMENU tmpmenu, tmpcurmenu;
+    POPUPMENU *menu = &tmpmenu, *curmenu = &tmpcurmenu;
     UINT  nextcol;
+    MENU_GetMenu( pmt->hTopMenu, menu);
 
+    MENU_GetMenu(pmt->hCurrentMenu, curmenu);
     TRACE("MENU_KeyRight called, cur %p (%s), top %p (%s).\n",
           pmt->hCurrentMenu,
-          debugstr_w((MENU_GetMenu(pmt->hCurrentMenu))->items[0].text),
+          debugstr_w(curmenu->items[0].text),
           pmt->hTopMenu, debugstr_w(menu->items[0].text) );
 
     if ( (menu->wFlags & MF_POPUP) || (pmt->hCurrentMenu != pmt->hTopMenu))
@@ -2920,7 +3054,8 @@ static BOOL MENU_TrackMenu( HMENU hmenu,
                             HWND hwnd, const RECT *lprect )
 {
     MSG msg;
-    POPUPMENU *menu;
+    POPUPMENU tmpmenu;
+    POPUPMENU *menu = &tmpmenu;
     BOOL fRemove;
     INT executedMenuId = -1;
     MTRACKER mt;
@@ -2937,7 +3072,7 @@ static BOOL MENU_TrackMenu( HMENU hmenu,
           hmenu, wFlags, x, y, hwnd, wine_dbgstr_rect( lprect));
 
     fEndMenu = FALSE;
-    if (!(menu = MENU_GetMenu( hmenu )))
+    if (MENU_GetMenu( hmenu, menu ))
     {
         WARN("Invalid menu handle %p\n", hmenu);
         SetLastError(ERROR_INVALID_MENU_HANDLE);
@@ -2957,9 +3092,11 @@ static BOOL MENU_TrackMenu( HMENU hmenu,
 
     while (!fEndMenu)
     {
-	menu = MENU_GetMenu( mt.hCurrentMenu );
-	if (!menu) /* sometimes happens if I do a window manager close */
+	if (MENU_GetMenu( mt.hCurrentMenu, menu ))
+        {
+            /* sometimes happens if I do a window manager close */
 	    break;
+        }
 
 	/* we have to keep the message in the queue until it's
 	 * clear that menu loop is not over yet. */
@@ -3087,7 +3224,7 @@ static BOOL MENU_TrackMenu( HMENU hmenu,
 		case VK_UP:
 		case VK_DOWN: /* If on menu bar, pull-down the menu */
 
-		    menu = MENU_GetMenu( mt.hCurrentMenu );
+		    MENU_GetMenu( mt.hCurrentMenu, menu );
 		    if (!(menu->wFlags & MF_POPUP))
 			mt.hCurrentMenu = MENU_ShowSubPopup(mt.hOwnerWnd, mt.hTopMenu, TRUE, wFlags);
 		    else      /* otherwise try to move selection */
@@ -3184,23 +3321,28 @@ static BOOL MENU_TrackMenu( HMENU hmenu,
        check for this first.  */
     if( IsMenu( mt.hTopMenu ) )
     {
-	menu = MENU_GetMenu( mt.hTopMenu );
+        int ret = MENU_GetMenu( mt.hTopMenu, menu );
 
         if( IsWindow( mt.hOwnerWnd ) )
         {
 	    MENU_HideSubPopups( mt.hOwnerWnd, mt.hTopMenu, FALSE );
 
-	    if (menu && (menu->wFlags & MF_POPUP))
+	    if (!ret && (menu->wFlags & MF_POPUP))
 	    {
                 DestroyWindow( menu->hWnd );
                 menu->hWnd = 0;
+                MENU_UpdateMenu(mt.hTopMenu, menu, SET_MI_HWND);
 	    }
 	    MENU_SelectItem( mt.hOwnerWnd, mt.hTopMenu, NO_SELECTED_ITEM, FALSE, 0 );
 	    SendMessageW( mt.hOwnerWnd, WM_MENUSELECT, MAKELONG(0,0xffff), 0 );
         }
 
         /* Reset the variable for hiding menu */
-        if( menu ) menu->bTimeToHide = FALSE;
+        if( !ret )
+        {
+            menu->bTimeToHide = FALSE;
+            MENU_UpdateMenu(mt.hTopMenu, menu, SET_MI_TIMETOHIDE);
+        }
     }
 
     /* The return value is only used by TrackPopupMenu */
@@ -3214,7 +3356,8 @@ static BOOL MENU_TrackMenu( HMENU hmenu,
  */
 static BOOL MENU_InitTracking(HWND hWnd, HMENU hMenu, BOOL bPopup, UINT wFlags)
 {
-    POPUPMENU *menu;
+    POPUPMENU tmpmenu;
+    POPUPMENU *menu = &tmpmenu;
     
     TRACE("hwnd=%p hmenu=%p\n", hWnd, hMenu);
 
@@ -3238,7 +3381,11 @@ static BOOL MENU_InitTracking(HWND hWnd,
      * It also enables menus to be displayed in more than one window,
      * but there are some bugs left that need to be fixed in this case.
      */
-    if ((menu = MENU_GetMenu( hMenu ))) menu->hWnd = hWnd;
+    if (!MENU_GetMenu( hMenu, menu ))
+    {
+        menu->hWnd = hWnd;
+        MENU_UpdateMenu( hMenu, menu, SET_MI_HWND );
+    }
     
     return TRUE;
 }
@@ -3451,16 +3598,18 @@ UINT MENU_GetMenuBarHeight( HWND hwnd, U
 {
     HDC hdc;
     RECT rectBar;
-    LPPOPUPMENU lppop;
+    POPUPMENU tmppop;
+    LPPOPUPMENU lppop = &tmppop;
 
     TRACE("HWND %p, width %d, at (%d, %d).\n", hwnd, menubarWidth, orgX, orgY );
 
-    if (!(lppop = MENU_GetMenu( GetMenu(hwnd) ))) return 0;
+    if (MENU_GetMenu( GetMenu(hwnd), lppop )) return 0;
 
     hdc = GetDCEx( hwnd, 0, DCX_CACHE | DCX_WINDOW );
     SelectObject( hdc, get_menu_font(FALSE));
     SetRect(&rectBar, orgX, orgY, orgX+menubarWidth, orgY+GetSystemMetrics(SM_CYMENU));
     MENU_MenuBarCalcSize( hdc, &rectBar, lppop, hwnd );
+    MENU_UpdateMenu( GetMenu(hwnd), lppop, SET_MI_WIDTH|SET_MI_HEIGHT|SET_MI_MAXBMPSIZE|SET_MI_TOTALHEIGHT|SET_MI_SCROLLING);
     ReleaseDC( hwnd, hdc );
     return lppop->Height;
 }
@@ -3530,12 +3679,13 @@ BOOL WINAPI EnableMenuItem( HMENU hMenu,
 {
     UINT    oldflags;
     MENUITEM *item;
-    POPUPMENU *menu;
+    POPUPMENU tmpmenu;
+    POPUPMENU *menu = &tmpmenu;
 
     TRACE("(%p, %04x, %04x) !\n", hMenu, wItemID, wFlags);
 
     /* Get the Popupmenu to access the owner menu */
-    if (!(menu = MENU_GetMenu(hMenu)))
+    if (MENU_GetMenu(hMenu, menu))
 	return (UINT)-1;
 
     if (!(item = MENU_FindItem( &hMenu, &wItemID, wFlags )))
@@ -3550,10 +3700,11 @@ BOOL WINAPI EnableMenuItem( HMENU hMenu,
 	if (menu->hSysMenuOwner != 0)
 	{
             RECT rc;
-	    POPUPMENU* parentMenu;
+            POPUPMENU tmpparentMenu;
+	    POPUPMENU *parentMenu = &tmpparentMenu;
 
 	    /* Get the parent menu to access*/
-	    if (!(parentMenu = MENU_GetMenu(menu->hSysMenuOwner)))
+	    if (MENU_GetMenu(menu->hSysMenuOwner, parentMenu))
 		return (UINT)-1;
 
             /* Refresh the frame to reflect the change */
@@ -3625,10 +3776,11 @@ INT WINAPI GetMenuStringW( HMENU hMenu, 
 BOOL WINAPI HiliteMenuItem( HWND hWnd, HMENU hMenu, UINT wItemID,
                                 UINT wHilite )
 {
-    LPPOPUPMENU menu;
+    POPUPMENU tmpmenu;
+    LPPOPUPMENU menu = &tmpmenu;
     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_GetMenu(hMenu, menu)) return FALSE;
     if (menu->FocusedItem == wItemID) return TRUE;
     MENU_HideSubPopups( hWnd, hMenu, FALSE );
     MENU_SelectItem( hWnd, hMenu, wItemID, TRUE, 0 );
@@ -3647,8 +3799,9 @@ UINT WINAPI GetMenuState( HMENU hMenu, U
     debug_print_menuitem ("  item: ", item, "");
     if (item->fType & MF_POPUP)
     {
-	POPUPMENU *menu = MENU_GetMenu( item->hSubMenu );
-	if (!menu) return -1;
+        POPUPMENU tmpmenu;
+	POPUPMENU *menu = &tmpmenu;
+        if (MENU_GetMenu( item->hSubMenu, menu )) return -1;
 	else return (menu->nItems << 8) | ((item->fState|item->fType) & 0xff);
     }
     else
@@ -3666,8 +3819,9 @@ UINT WINAPI GetMenuState( HMENU hMenu, U
  */
 INT WINAPI GetMenuItemCount( HMENU hMenu )
 {
-    LPPOPUPMENU	menu = MENU_GetMenu(hMenu);
-    if (!menu) return -1;
+    POPUPMENU tmpmenu;
+    LPPOPUPMENU menu = &tmpmenu;
+    if (MENU_GetMenu(hMenu, menu)) return -1;
     TRACE("(%p) returning %d\n", hMenu, menu->nItems );
     return menu->nItems;
 }
@@ -3710,7 +3864,13 @@ BOOL WINAPI InsertMenuW( HMENU hMenu, UI
     }
 
     if (flags & MF_POPUP)  /* Set the MF_POPUP flag on the popup-menu */
-	(MENU_GetMenu((HMENU)id))->wFlags |= MF_POPUP;
+    {
+        POPUPMENU tmpmenu;
+        POPUPMENU *menu = &tmpmenu;
+        MENU_GetMenu((HMENU)id, menu);
+        menu->wFlags |= MF_POPUP;
+        MENU_UpdateMenu((HMENU)id, menu, SET_MI_FLAGS);
+    }
 
     item->hCheckBit = item->hUnCheckBit = 0;
     return TRUE;
@@ -3766,12 +3926,13 @@ BOOL WINAPI AppendMenuW( HMENU hMenu, UI
  */
 BOOL WINAPI RemoveMenu( HMENU hMenu, UINT nPos, UINT wFlags )
 {
-    LPPOPUPMENU	menu;
+    POPUPMENU tmpmenu;
+    LPPOPUPMENU menu = &tmpmenu;
     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;
+    if (MENU_GetMenu(hMenu, menu)) return FALSE;
 
       /* Remove item */
 
@@ -3793,6 +3954,7 @@ BOOL WINAPI RemoveMenu( HMENU hMenu, UIN
         menu->items = HeapReAlloc( GetProcessHeap(), 0, menu->items,
                                    menu->nItems * sizeof(MENUITEM) );
     }
+    MENU_UpdateMenu(hMenu, menu, SET_MI_NITEMS|SET_MI_ITEMS);
     return TRUE;
 }
 
@@ -3818,6 +3980,8 @@ BOOL WINAPI ModifyMenuW( HMENU hMenu, UI
                          UINT_PTR id, LPCWSTR str )
 {
     MENUITEM *item;
+    POPUPMENU tmpmenu;
+    POPUPMENU *menu = &tmpmenu;
 
     if (IS_STRING_ITEM(flags))
         TRACE("%p %d %04x %04x %s\n", hMenu, pos, flags, id, debugstr_w(str) );
@@ -3825,7 +3989,9 @@ BOOL WINAPI ModifyMenuW( HMENU hMenu, UI
         TRACE("%p %d %04x %04x %p\n", hMenu, pos, flags, id, str );
 
     if (!(item = MENU_FindItem( &hMenu, &pos, flags ))) return FALSE;
-    MENU_GetMenu(hMenu)->Height = 0; /* force size recalculate */
+    MENU_GetMenu(hMenu, menu);
+    menu->Height = 0; /* force size recalculate */
+    MENU_UpdateMenu(hMenu, menu, SET_MI_HEIGHT);
     return MENU_SetItemData( item, flags, id, str );
 }
 
@@ -3860,12 +4026,14 @@ BOOL WINAPI ModifyMenuA( HMENU hMenu, UI
 HMENU WINAPI CreatePopupMenu(void)
 {
     HMENU hmenu;
-    POPUPMENU *menu;
+    POPUPMENU tmpmenu;
+    POPUPMENU *menu = &tmpmenu;
 
     if (!(hmenu = CreateMenu())) return 0;
-    menu = MENU_GetMenu( hmenu );
+    MENU_GetMenu(hmenu, menu);
     menu->wFlags |= MF_POPUP;
     menu->bTimeToHide = FALSE;
+    MENU_UpdateMenu(hmenu, menu, SET_MI_FLAGS|SET_MI_TIMETOHIDE);
     return hmenu;
 }
 
@@ -3910,15 +4078,14 @@ BOOL WINAPI SetMenuItemBitmaps( HMENU hM
  */
 HMENU WINAPI CreateMenu(void)
 {
-    HMENU hMenu;
-    LPPOPUPMENU menu;
-    if (!(hMenu = USER_HEAP_ALLOC( sizeof(POPUPMENU) ))) return 0;
-    menu = (LPPOPUPMENU) USER_HEAP_LIN_ADDR(hMenu);
-
-    ZeroMemory(menu, sizeof(POPUPMENU));
-    menu->wMagic = MENU_MAGIC;
-    menu->FocusedItem = NO_SELECTED_ITEM;
-    menu->bTimeToHide = FALSE;
+    HMENU hMenu = 0;
+
+    SERVER_START_REQ( create_menu )
+    {
+        if (!wine_server_call_err( req ))
+            hMenu = reply->handle;
+    }
+    SERVER_END_REQ;
 
     TRACE("return %p\n", hMenu );
 
@@ -3931,12 +4098,12 @@ HMENU WINAPI CreateMenu(void)
  */
 BOOL WINAPI DestroyMenu( HMENU hMenu )
 {
-    LPPOPUPMENU lppop = MENU_GetMenu(hMenu);
+    POPUPMENU tmppop;
+    LPPOPUPMENU lppop = &tmppop;
 
     TRACE("(%p)\n", hMenu);
 
-
-    if (!lppop) return FALSE;
+    if (MENU_GetMenu(hMenu, lppop)) return FALSE;
 
     lppop->wMagic = 0;  /* Mark it as destroyed */
 
@@ -3958,7 +4125,15 @@ BOOL WINAPI DestroyMenu( HMENU hMenu )
         }
         HeapFree( GetProcessHeap(), 0, lppop->items );
     }
-    USER_HEAP_FREE( hMenu );
+
+    SERVER_START_REQ( destroy_menu )
+    {
+        req->handle = hMenu;
+        if (!wine_server_call_err( req ))
+        {
+        }
+    }
+    SERVER_END_REQ;
     return TRUE;
 }
 
@@ -3989,14 +4164,17 @@ HMENU WINAPI GetSystemMenu( HWND hWnd, B
 
 	if( wndPtr->hSysMenu )
         {
-	    POPUPMENU *menu;
+            POPUPMENU tmpmenu;
+	    POPUPMENU *menu = &tmpmenu;
 	    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 )
+            if (!MENU_GetMenu(retvalue, menu))
+            {
 	       menu->hSysMenuOwner = wndPtr->hSysMenu;
+               MENU_UpdateMenu(retvalue, menu, SET_MI_OWNER);
+            }
         }
         WIN_ReleasePtr( wndPtr );
     }
@@ -4064,12 +4242,14 @@ BOOL MENU_SetMenu( HWND hWnd, HMENU hMen
 
     if (hMenu != 0)
     {
-        LPPOPUPMENU lpmenu;
+        POPUPMENU tmpmenu;
+        LPPOPUPMENU lpmenu = &tmpmenu;
 
-        if (!(lpmenu = MENU_GetMenu(hMenu))) return FALSE;
+        if (MENU_GetMenu(hMenu, lpmenu)) return FALSE;
 
         lpmenu->hWnd = hWnd;
         lpmenu->Height = 0;  /* Make sure we recalculate the size */
+        MENU_UpdateMenu(hMenu, lpmenu, SET_MI_HWND|SET_MI_HEIGHT);
     }
     SetWindowLongPtrW( hWnd, GWLP_ID, (LONG_PTR)hMenu );
     return TRUE;
@@ -4108,15 +4288,17 @@ HMENU WINAPI GetSubMenu( HMENU hMenu, IN
  */
 BOOL WINAPI DrawMenuBar( HWND hWnd )
 {
-    LPPOPUPMENU lppop;
+    POPUPMENU tmppop;
+    LPPOPUPMENU lppop = &tmppop;
     HMENU hMenu = GetMenu(hWnd);
 
     if (!WIN_ALLOWED_MENU(GetWindowLongW( hWnd, GWL_STYLE )))
         return FALSE;
-    if (!hMenu || !(lppop = MENU_GetMenu( hMenu ))) return FALSE;
+    if (!hMenu || MENU_GetMenu( hMenu, lppop )) return FALSE;
 
     lppop->Height = 0; /* Make sure we call MENU_MenuBarCalcSize */
     lppop->hwndOwner = hWnd;
+    MENU_UpdateMenu( hMenu, lppop, SET_MI_HEIGHT|SET_MI_OWNER );
     SetWindowPos( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
                   SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED );
     return TRUE;
@@ -4133,7 +4315,8 @@ BOOL WINAPI DrawMenuBar( HWND hWnd )
  */
 DWORD WINAPI DrawMenuBarTemp(HWND hwnd, HDC hDC, LPRECT lprect, HMENU hMenu, HFONT hFont)
 {
-    LPPOPUPMENU lppop;
+    POPUPMENU tmppop;
+    LPPOPUPMENU lppop = &tmppop;
     UINT i,retvalue;
     HFONT hfontOld = 0;
     BOOL flat_menu = FALSE;
@@ -4146,8 +4329,7 @@ DWORD WINAPI DrawMenuBarTemp(HWND hwnd, 
     if (!hFont)
         hFont = get_menu_font(FALSE);
 
-    lppop = MENU_GetMenu( hMenu );
-    if (lppop == NULL || lprect == NULL)
+    if (MENU_GetMenu(hMenu, lppop) || lprect == NULL)
     {
         retvalue = GetSystemMetrics(SM_CYMENU);
         goto END;
@@ -4158,7 +4340,10 @@ DWORD WINAPI DrawMenuBarTemp(HWND hwnd, 
     hfontOld = SelectObject( hDC, hFont);
 
     if (lppop->Height == 0)
+    {
         MENU_MenuBarCalcSize(hDC, lprect, lppop, hwnd);
+        MENU_UpdateMenu(hMenu, lppop, SET_MI_MAXBMPSIZE);
+    }
 
     lprect->bottom = lprect->top + lppop->Height;
 
@@ -4346,9 +4531,9 @@ HMENU WINAPI LoadMenuIndirectA( LPCVOID 
  */
 BOOL WINAPI IsMenu(HMENU hmenu)
 {
-    LPPOPUPMENU menu = MENU_GetMenu(hmenu);
-
-    if (!menu)
+    POPUPMENU menu;
+    
+    if (MENU_GetMenu(hmenu, &menu))
     {
         SetLastError(ERROR_INVALID_MENU_HANDLE);
         return FALSE;
@@ -4583,9 +4768,12 @@ static BOOL SetMenuItemInfo_common(MENUI
     if (lpmii->fMask & MIIM_SUBMENU) {
 	menu->hSubMenu = lpmii->hSubMenu;
 	if (menu->hSubMenu) {
-	    POPUPMENU *subMenu = MENU_GetMenu(menu->hSubMenu);
-	    if (subMenu) {
+            POPUPMENU tmpsubMenu;
+            POPUPMENU *subMenu = &tmpsubMenu;
+            if (!MENU_GetMenu(menu->hSubMenu, subMenu))
+            {
 		subMenu->wFlags |= MF_POPUP;
+                MENU_UpdateMenu(menu->hSubMenu, subMenu, SET_MI_FLAGS);
 		menu->fType |= MF_POPUP;
 	    }
 	    else {
@@ -4664,12 +4852,13 @@ BOOL WINAPI SetMenuItemInfoW(HMENU hmenu
 BOOL WINAPI SetMenuDefaultItem(HMENU hmenu, UINT uItem, UINT bypos)
 {
 	UINT i;
-	POPUPMENU *menu;
+        POPUPMENU tmpmenu;
+	POPUPMENU *menu = &tmpmenu;
 	MENUITEM *item;
 
 	TRACE("(%p,%d,%d)\n", hmenu, uItem, bypos);
 
-	if (!(menu = MENU_GetMenu(hmenu))) return FALSE;
+	if (MENU_GetMenu(hmenu, menu)) return FALSE;
 
 	/* reset all default-item flags */
 	item = menu->items;
@@ -4711,13 +4900,14 @@ BOOL WINAPI SetMenuDefaultItem(HMENU hme
  */
 UINT WINAPI GetMenuDefaultItem(HMENU hmenu, UINT bypos, UINT flags)
 {
-	POPUPMENU *menu;
+	POPUPMENU tmpmenu;
+	POPUPMENU *menu = &tmpmenu;
 	MENUITEM * item;
 	UINT i = 0;
 
 	TRACE("(%p,%d,%d)\n", hmenu, bypos, flags);
 
-	if (!(menu = MENU_GetMenu(hmenu))) return -1;
+	if (MENU_GetMenu(hmenu, menu)) return -1;
 
 	/* find default item */
 	item = menu->items;
@@ -4841,7 +5031,8 @@ BOOL WINAPI CheckMenuRadioItem(HMENU hMe
 BOOL WINAPI GetMenuItemRect (HWND hwnd, HMENU hMenu, UINT uItem,
 				 LPRECT rect)
 {
-     POPUPMENU *itemMenu;
+     POPUPMENU tmpitemMenu;
+     POPUPMENU *itemMenu = &tmpitemMenu;
      MENUITEM *item;
      HWND referenceHwnd;
 
@@ -4852,8 +5043,7 @@ BOOL WINAPI GetMenuItemRect (HWND hwnd, 
 
      if(!hwnd)
      {
-	 itemMenu = MENU_GetMenu(hMenu);
-	 if (itemMenu == NULL)
+         if (MENU_GetMenu(hMenu, itemMenu))
 	     return FALSE;
 
 	 if(itemMenu->hWnd == 0)
@@ -4881,11 +5071,12 @@ BOOL WINAPI GetMenuItemRect (HWND hwnd, 
  */
 BOOL WINAPI SetMenuInfo (HMENU hMenu, LPCMENUINFO lpmi)
 {
-    POPUPMENU *menu;
+    POPUPMENU tmpmenu;
+    POPUPMENU *menu = &tmpmenu;
 
     TRACE("(%p %p)\n", hMenu, lpmi);
 
-    if (lpmi && (lpmi->cbSize==sizeof(MENUINFO)) && (menu = MENU_GetMenu(hMenu)))
+    if (lpmi && (lpmi->cbSize==sizeof(MENUINFO)) && !MENU_GetMenu(hMenu, menu))
     {
 
 	if (lpmi->fMask & MIM_BACKGROUND)
@@ -4909,6 +5100,10 @@ BOOL WINAPI SetMenuInfo (HMENU hMenu, LP
 	    if (menu->dwStyle & MNS_NOTIFYBYPOS) FIXME("MNS_NOTIFYBYPOS partially implemented\n");
 	}
 
+        MENU_UpdateMenu(hMenu, menu, lpmi->fMask
+                        & (MIM_BACKGROUND|MIM_HELPID|MIM_MAXHEIGHT
+                           |MIM_MENUDATA|MIM_STYLE));
+
 	return TRUE;
     }
     return FALSE;
@@ -4922,11 +5117,13 @@ BOOL WINAPI SetMenuInfo (HMENU hMenu, LP
  *
  */
 BOOL WINAPI GetMenuInfo (HMENU hMenu, LPMENUINFO lpmi)
-{   POPUPMENU *menu;
+{
+    POPUPMENU tmpmenu;
+    POPUPMENU *menu = &tmpmenu;
 
     TRACE("(%p %p)\n", hMenu, lpmi);
 
-    if (lpmi && (menu = MENU_GetMenu(hMenu)))
+    if (lpmi && !MENU_GetMenu(hMenu, menu))
     {
 
 	if (lpmi->fMask & MIM_BACKGROUND)
@@ -4955,11 +5152,12 @@ BOOL WINAPI GetMenuInfo (HMENU hMenu, LP
  */
 BOOL WINAPI SetMenuContextHelpId( HMENU hMenu, DWORD dwContextHelpID)
 {
-    LPPOPUPMENU menu;
+    POPUPMENU tmpmenu;
+    LPPOPUPMENU menu = &tmpmenu;
 
     TRACE("(%p 0x%08lx)\n", hMenu, dwContextHelpID);
 
-    if ((menu = MENU_GetMenu(hMenu)))
+    if (!MENU_GetMenu(hMenu, menu))
     {
 	menu->dwContextHelpID = dwContextHelpID;
 	return TRUE;
@@ -4973,11 +5171,12 @@ BOOL WINAPI SetMenuContextHelpId( HMENU 
  */
 DWORD WINAPI GetMenuContextHelpId( HMENU hMenu )
 {
-    LPPOPUPMENU menu;
+    POPUPMENU tmpmenu;
+    LPPOPUPMENU menu = &tmpmenu;
 
     TRACE("(%p)\n", hMenu);
 
-    if ((menu = MENU_GetMenu(hMenu)))
+    if (!MENU_GetMenu(hMenu, menu))
     {
 	return menu->dwContextHelpID;
     }
@@ -4989,11 +5188,12 @@ DWORD WINAPI GetMenuContextHelpId( HMENU
  */
 INT WINAPI MenuItemFromPoint(HWND hWnd, HMENU hMenu, POINT ptScreen)
 {
-    POPUPMENU *menu = MENU_GetMenu(hMenu);
+    POPUPMENU tmpmenu;
+    POPUPMENU *menu = &tmpmenu;
     UINT pos;
 
     /*FIXME: Do we have to handle hWnd here? */
-    if (!menu) return -1;
+    if (MENU_GetMenu(hMenu, menu)) return -1;
     if (!MENU_FindItemByCoords(menu, ptScreen, &pos)) return -1;
     return pos;
 }
diff --git a/dlls/user/tests/menu.c b/dlls/user/tests/menu.c
index 10a29a8..e715ae6 100644
--- a/dlls/user/tests/menu.c
+++ b/dlls/user/tests/menu.c
@@ -1709,17 +1709,17 @@ static void test_menu_remote_process()
     ok ((int) hMenu, "GetMenu failed\n");
     nMenu = GetMenuItemCount(hMenu);
     /* notepad.exe menus slightly differ in Wine and Windows */
-    todo_wine ok(nMenu == 4 || nMenu == 5, "nMenu = %d, error=%ld\n", nMenu,
+    ok(nMenu == 4 || nMenu == 5, "nMenu = %d, error=%ld\n", nMenu,
        GetLastError());
 
     memset(&mii, 0, sizeof(mii));
     mii.cbSize = sizeof(MENUITEMINFO);
     mii.fMask = MIIM_STRING;
     mii.dwTypeData = NULL;
-    todo_wine ok (GetMenuItemInfo(hMenu, 0, TRUE, &mii),
+    ok (GetMenuItemInfo(hMenu, 0, TRUE, &mii),
         "error=%ld\n", GetLastError());
     mii.dwTypeData = malloc(++mii.cch);
-    todo_wine ok (GetMenuItemInfo(hMenu, 0, TRUE, &mii),
+    ok (GetMenuItemInfo(hMenu, 0, TRUE, &mii),
         "error=%ld, dwTypeData='%s'\n", GetLastError(), mii.dwTypeData);
     todo_wine ok (mii.dwTypeData && !strcmp(mii.dwTypeData, "&File"),
         "error=%ld, dwTypeData='%s'\n", GetLastError(), mii.dwTypeData);
@@ -1728,30 +1728,30 @@ static void test_menu_remote_process()
     mii.cbSize = sizeof(MENUITEMINFO);
     mii.fMask = MIIM_STRING;
     mii.dwTypeData = "&New File Menu";
-    todo_wine ok (SetMenuItemInfo(hMenu, 0, TRUE, &mii), "error=%ld\n",
-         GetLastError());
+    ok (SetMenuItemInfo(hMenu, 0, TRUE, &mii), "error=%ld\n",
+        GetLastError());
     DrawMenuBar(hNotepad);
 
     memset(&mii, 0, sizeof(mii));
     mii.cbSize = sizeof(MENUITEMINFO);
     mii.fMask = MIIM_STRING;
     mii.dwTypeData = NULL;
-    todo_wine ok (GetMenuItemInfo(hMenu, 0, TRUE, &mii),
+    ok (GetMenuItemInfo(hMenu, 0, TRUE, &mii),
         "error=%ld\n", GetLastError());
     mii.dwTypeData = malloc(++mii.cch);
-    todo_wine ok (GetMenuItemInfo(hMenu, 0, TRUE, &mii),
+    ok (GetMenuItemInfo(hMenu, 0, TRUE, &mii),
         "error=%ld, dwTypeData='%s'\n", GetLastError(), mii.dwTypeData);
-    todo_wine ok (mii.dwTypeData && !strcmp(mii.dwTypeData, "&New File Menu"),
+    ok (mii.dwTypeData && !strcmp(mii.dwTypeData, "&New File Menu"),
         "error=%ld, dwTypeData='%s'\n", GetLastError(), mii.dwTypeData);
     free(mii.dwTypeData);
 
     mi.cbSize = sizeof(MENUINFO);
     mi.fMask = MIM_MENUDATA;
-    todo_wine ok (GetMenuInfo(hMenu, &mi), "error=%ld\n", GetLastError());
+    ok (GetMenuInfo(hMenu, &mi), "error=%ld\n", GetLastError());
     oldMenuData = mi.dwMenuData;
     mi.dwMenuData = !mi.dwMenuData;
-    todo_wine ok (SetMenuInfo(hMenu, &mi), "error=%ld\n", GetLastError());
-    todo_wine ok (GetMenuInfo(hMenu, &mi), "error=%ld\n", GetLastError());
+    ok (SetMenuInfo(hMenu, &mi), "error=%ld\n", GetLastError());
+    ok (GetMenuInfo(hMenu, &mi), "error=%ld\n", GetLastError());
     ok (oldMenuData != mi.dwMenuData, "oldMenuData=%ld, dwMenuData=%ld\n",
         oldMenuData, mi.dwMenuData);
 


