[Win32k]
authorJames Tabor <james.tabor@reactos.org>
Tue, 6 May 2014 18:09:07 +0000 (18:09 +0000)
committerJames Tabor <james.tabor@reactos.org>
Tue, 6 May 2014 18:09:07 +0000 (18:09 +0000)
- Utilize the new menu structures and use item array instead of the list method. Make sure your applications Appends are in order (reference Mdi.c). Sync ported more wine code too.
- See CORE-5605, CORE-7447, CORE-7967 (Main Bug), CORE-8098 and CORE-8107

svn path=/trunk/; revision=63179

reactos/win32ss/include/ntuser.h
reactos/win32ss/user/ntuser/accelerator.c
reactos/win32ss/user/ntuser/menu.c
reactos/win32ss/user/ntuser/menu.h
reactos/win32ss/user/ntuser/userfuncs.h
reactos/win32ss/user/ntuser/window.c
reactos/win32ss/user/user32/windows/mdi.c
reactos/win32ss/user/user32/windows/menu.c

index e1ed160..fb39f5a 100644 (file)
@@ -329,7 +329,6 @@ typedef struct tagITEM
     INT cyBmp;     /* Height " */
     //// ReactOS
     UNICODE_STRING lpstr;
-    struct tagITEM *Next;
 } ITEM, *PITEM;
 
 typedef struct tagMENULIST
@@ -369,7 +368,7 @@ typedef struct tagMENU
     DWORD dwArrowsOn:2;       /* Arrows: 0 off, 1 on, 2 to the top, 3 to the bottom. */
     //// ReactOS
     LIST_ENTRY ListEntry;
-    HWND hWnd;           /* Window containing the menu */
+    HWND hWnd;           /* Window containing the menu, use POPUPMENU */
     BOOL TimeToHide;
 } MENU, *PMENU;
 
index f43ee5e..7777c50 100644 (file)
@@ -99,7 +99,7 @@ co_IntTranslateAccelerator(
     /* Check if accelerator is associated with menu command */
     hMenu = (Window->style & WS_CHILD) ? 0 : (HMENU)Window->IDMenu;
     hSubMenu = NULL;
-    MenuObject = IntGetMenuObject(hMenu);
+    MenuObject = UserGetMenuObject(hMenu);
     nPos = pAccel->cmd;
     if (MenuObject)
     {
@@ -113,7 +113,7 @@ co_IntTranslateAccelerator(
         /* Check system menu now */
         hMenu = Window->SystemMenu;
         hSubMenu = hMenu; /* system menu is a popup menu */
-        MenuObject = IntGetMenuObject(hMenu);
+        MenuObject = UserGetMenuObject(hMenu);
         nPos = pAccel->cmd;
         if (MenuObject)
         {
index f4c4e4c..b7d5209 100644 (file)
@@ -11,6 +11,8 @@ DBG_DEFAULT_CHANNEL(UserMenu);
 
 /* INTERNAL ******************************************************************/
 
+BOOL FASTCALL IntSetMenuItemInfo(PMENU, PITEM, PROSMENUITEMINFO, PUNICODE_STRING);
+
 /* maximum allowed depth of any branch in the menu tree.
  * This value is slightly larger than in windows (25) to
  * stay on the safe side. */
@@ -23,16 +25,29 @@ DBG_DEFAULT_CHANNEL(UserMenu);
                  MFT_MENUBARBREAK | MFT_MENUBREAK | MFT_RADIOCHECK | \
                  MFT_RIGHTORDER | MFT_RIGHTJUSTIFY /* same as MF_HELP */ )
 
+#define TYPE_MASK  (MENUITEMINFO_TYPE_MASK | MF_POPUP | MF_SYSMENU)
+
+#define STATE_MASK (~TYPE_MASK)
+
+#define MENUITEMINFO_STATE_MASK (STATE_MASK & ~(MF_BYPOSITION | MF_MOUSESELECT))
+
+#define MII_STATE_MASK (MFS_GRAYED|MFS_CHECKED|MFS_HILITE|MFS_DEFAULT)
+
 /* Maximum number of menu items a menu can contain */
 #define MAX_MENU_ITEMS (0x4000)
 #define MAX_GOINTOSUBMENU (0x10)
 
 #define UpdateMenuItemState(state, change) \
 {\
-  if((change) & MFS_DISABLED) { \
-    (state) |= MFS_DISABLED; \
+  if((change) & MF_GRAYED) { \
+    (state) |= MF_GRAYED; \
+  } else { \
+    (state) &= ~MF_GRAYED; \
+  } /* Separate the two for test_menu_resource_layout.*/ \
+  if((change) & MF_DISABLED) { \
+    (state) |= MF_DISABLED; \
   } else { \
-    (state) &= ~MFS_DISABLED; \
+    (state) &= ~MF_DISABLED; \
   } \
   if((change) & MFS_CHECKED) { \
     (state) |= MFS_CHECKED; \
@@ -56,42 +71,12 @@ DBG_DEFAULT_CHANNEL(UserMenu);
   } \
 }
 
-#define FreeMenuText(Menu,MenuItem) \
-{ \
-  if((MENU_ITEM_TYPE((MenuItem)->fType) == MF_STRING) && \
-           (MenuItem)->lpstr.Length) { \
-    DesktopHeapFree(((PMENU)Menu)->head.rpdesk, (MenuItem)->lpstr.Buffer); \
-  } \
-}
-
-
-PMENU FASTCALL UserGetMenuObject(HMENU hMenu)
-{
-   PMENU Menu;
-
-   if (!hMenu)
-   {
-      EngSetLastError(ERROR_INVALID_MENU_HANDLE);
-      return NULL;
-   }
-
-   Menu = (PMENU)UserGetObject(gHandleTable, hMenu, TYPE_MENU);
-   if (!Menu)
-   {
-      EngSetLastError(ERROR_INVALID_MENU_HANDLE);
-      return NULL;
-   }
-
-   return Menu;
-}
-
-
 #if 0
 void FASTCALL
-DumpMenuItemList(PITEM MenuItem)
+DumpMenuItemList(PMENU Menu, PITEM MenuItem)
 {
-   UINT cnt = 0;
-   while(MenuItem)
+   UINT cnt = 0, i = Menu->cItems;
+   while(i)
    {
       if(MenuItem->lpstr.Length)
          DbgPrint(" %d. %wZ\n", ++cnt, &MenuItem->lpstr);
@@ -132,13 +117,22 @@ DumpMenuItemList(PITEM MenuItem)
       if(MFS_GRAYED & MenuItem->fState)
          DbgPrint("MFS_GRAYED ");
       DbgPrint("\n   wId=%d\n", MenuItem->wID);
-      MenuItem = MenuItem->Next;
+      MenuItem++;
+      i--;
    }
    DbgPrint("Entries: %d\n", cnt);
    return;
 }
 #endif
 
+#define FreeMenuText(Menu,MenuItem) \
+{ \
+  if((MENU_ITEM_TYPE((MenuItem)->fType) == MF_STRING) && \
+           (MenuItem)->lpstr.Length) { \
+    DesktopHeapFree(((PMENU)Menu)->head.rpdesk, (MenuItem)->lpstr.Buffer); \
+  } \
+}
+
 PMENU FASTCALL
 IntGetMenuObject(HMENU hMenu)
 {
@@ -149,64 +143,68 @@ IntGetMenuObject(HMENU hMenu)
    return Menu;
 }
 
-BOOL FASTCALL
-IntFreeMenuItem(PMENU Menu, PITEM MenuItem, BOOL bRecurse)
+PMENU FASTCALL VerifyMenu(PMENU pMenu)
 {
-   FreeMenuText(Menu,MenuItem);
-   if(bRecurse && MenuItem->spSubMenu)
-   {
-      IntDestroyMenuObject(MenuItem->spSubMenu, bRecurse, TRUE);
-   }
-
-   /* Free memory */
-   DesktopHeapFree(Menu->head.rpdesk, MenuItem);
-
-   return TRUE;
-}
+   HMENU hMenu;
+   PITEM pItem;
+   UINT i;
+   if (!pMenu) return NULL;
 
-BOOL FASTCALL
-IntRemoveMenuItem(PMENU Menu, UINT uPosition, UINT uFlags, BOOL bRecurse)
-{
-   PITEM PrevMenuItem, MenuItem = NULL;
-   if(IntGetMenuItemByFlag(Menu, uPosition, uFlags, &Menu, &MenuItem, &PrevMenuItem) > -1)
+   ERR("VerifyMenu 1!\n");
+   _SEH2_TRY
    {
-      if(MenuItem)
+      hMenu = UserHMGetHandle(pMenu);
+      pItem = pMenu->rgItems;
+      if (pItem)
       {
-         if(PrevMenuItem)
-            PrevMenuItem->Next = MenuItem->Next;
-         else
-         {
-            Menu->rgItems = MenuItem->Next;
-         }
-         Menu->cItems--;
-         return IntFreeMenuItem(Menu, MenuItem, bRecurse);
+         i = pItem[0].wID;
+         pItem[0].wID = i;
       }
    }
-   return FALSE;
+   _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+   {
+      ERR("Run away LOOP!\n");
+      _SEH2_YIELD(return NULL);
+   }
+   _SEH2_END
+   ERR("VerifyMenu 2!\n");
+   if ( UserObjectInDestroy(hMenu))
+      return NULL;
+   ERR("VerifyMenu 3!\n");
+   return pMenu;
 }
 
-UINT FASTCALL
-IntDeleteMenuItems(PMENU Menu, BOOL bRecurse)
+BOOL IntDestroyMenu( PMENU pMenu, BOOL bRecurse, BOOL RemoveFromProcess)
 {
-   UINT res = 0;
-   PITEM NextItem;
-   PITEM CurItem = Menu->rgItems;
-   while(CurItem && Menu->cItems)
-   {
-      Menu->cItems--; //// This is the last of this mess~! Removal requires new start up sequence. Do it like windows and wine!
-                      //// wine MENU_CopySysPopup and ReactOS User32LoadSysMenuTemplateForKernel.
-                      ////   SC_CLOSE First       and      SC_CLOSED Last
-                      //// Use menu item blocks not chain.
-                      /// So do it like windows~!
-      NextItem = CurItem->Next;
-      IntFreeMenuItem(Menu, CurItem, bRecurse);
-      CurItem->Next = 0; // mark the item as end of the list!!!
-      CurItem = NextItem;
-      res++;
-   }
-   Menu->cItems = 0;
-   Menu->rgItems = NULL;
-   return res;
+    /* DestroyMenu should not destroy system menu popup owner */
+    if ((pMenu->fFlags & (MNF_POPUP | MNF_SYSSUBMENU)) == MNF_POPUP && pMenu->hWnd)
+    {
+       //PWND pWnd = ValidateHwndNoErr(pMenu->hWnd);
+       ERR("FIXME Pop up menu window thing'ie\n");
+       
+       //co_UserDestroyWindow( pWnd );
+       //pMenu->hWnd = 0;
+    }
+
+    if (pMenu->rgItems) /* recursively destroy submenus */
+    {
+       int i;
+       ITEM *item = pMenu->rgItems;
+       for (i = pMenu->cItems; i > 0; i--, item++)
+       {
+           pMenu->cItems--; //// I hate recursion logic! (jt) 4/2014. See r63028 comment for IntDeleteMenuItems.
+           FreeMenuText(pMenu,item);
+           if (bRecurse && item->spSubMenu)//VerifyMenu(item->spSubMenu))
+           {
+              IntDestroyMenu(item->spSubMenu, bRecurse, RemoveFromProcess);
+              item->spSubMenu = NULL;
+           }
+       }
+       DesktopHeapFree(pMenu->head.rpdesk, pMenu->rgItems );
+       pMenu->rgItems = NULL; 
+       pMenu->cItems = 0; //// What ever~!
+    }
+    return TRUE;
 }
 
 BOOL FASTCALL
@@ -216,24 +214,15 @@ IntDestroyMenuObject(PMENU Menu,
    if(Menu)
    {
       PWND Window;
-      //PWINSTATION_OBJECT WindowStation;
-      //NTSTATUS Status;
-
+      
       /* Remove all menu items */
-      IntDeleteMenuItems(Menu, bRecurse); /* Do not destroy submenus */
+      IntDestroyMenu( Menu, bRecurse, RemoveFromProcess);
 
       if(RemoveFromProcess)
       {
          RemoveEntryList(&Menu->ListEntry);
       }
 
-      /*Status = ObReferenceObjectByHandle(Menu->Process->Win32WindowStation,
-                                         0,
-                                         ExWindowStationObjectType,
-                                         KernelMode,
-                                         (PVOID*)&WindowStation,
-                                         NULL);
-      if(NT_SUCCESS(Status))*/
       if (PsGetCurrentProcessSessionId() == Menu->head.rpdesk->rpwinstaParent->dwSessionId)
       {
          BOOL ret;
@@ -252,55 +241,32 @@ IntDestroyMenuObject(PMENU Menu,
             ret = UserObjectInDestroy(Menu->head.h);
             if (ret && EngGetLastError() == ERROR_INVALID_HANDLE) ret = FALSE;
          }  // See test_subpopup_locked_by_menu tests....
-         //ObDereferenceObject(WindowStation);
          return ret;
       }
    }
    return FALSE;
 }
 
-BOOL IntDestroyMenu( PMENU pMenu, BOOL RemoveFromProcess)
-{
-    /* DestroyMenu should not destroy system menu popup owner */
-    if ((pMenu->fFlags & (MNF_POPUP | MNF_SYSSUBMENU)) == MNF_POPUP )//&& pMenu->hWnd)
-    {
-        //DestroyWindow( pMenu->hWnd );
-        //pMenu->hWnd = 0;
-    }
-
-    if (pMenu->rgItems) /* recursively destroy submenus */
-    {
-        int i;
-        ITEM *item = pMenu->rgItems;
-        for (i = pMenu->cItems; i > 0; i--, item++)
-        {
-            if (item->spSubMenu) IntDestroyMenu(item->spSubMenu, RemoveFromProcess);
-            //FreeMenuText(pMenu,item);
-        }
-        DesktopHeapFree(pMenu->head.rpdesk, pMenu->rgItems );
-    }
-    //IntDestroyMenuObject(pMenu, bRecurse, RemoveFromProcess);
-    return TRUE;
-}
-
 /**********************************************************************
  *             MENU_depth
  *
  * detect if there are loops in the menu tree (or the depth is too large)
  */
-int MENU_depth( PMENU pmenu, int depth)
+int FASTCALL MENU_depth( PMENU pmenu, int depth)
 {
     UINT i;
     ITEM *item;
     int subdepth;
 
+    if (!pmenu) return depth;
+
     depth++;
     if( depth > MAXMENUDEPTH) return depth;
     item = pmenu->rgItems;
     subdepth = depth;
-    for( i = 0; i < pmenu->cItems && subdepth <= MAXMENUDEPTH; i++, item++)
+    for( i = 0; item, i < pmenu->cItems && subdepth <= MAXMENUDEPTH; i++, item++)
     {
-        if( item->spSubMenu)
+        if( item->spSubMenu)//VerifyMenu(item->spSubMenu))
         {
             int bdepth = MENU_depth( item->spSubMenu, depth);
             if( bdepth > subdepth) subdepth = bdepth;
@@ -317,38 +283,29 @@ int MENU_depth( PMENU pmenu, int depth)
  * Find a menu item. Return a pointer on the item, and modifies *hmenu
  * in case the item was in a sub-menu.
  */
-ITEM *MENU_FindItem( PMENU *pmenu, UINT *nPos, UINT wFlags )
+PITEM FASTCALL MENU_FindItem( PMENU *pmenu, UINT *nPos, UINT wFlags )
 {
     MENU *menu = *pmenu;
     ITEM *fallback = NULL;
     UINT fallback_pos = 0;
     UINT i;
-    PITEM pItem;
+
+    if (!menu) return NULL;
 
     if (wFlags & MF_BYPOSITION)
     {
+        if (!menu->cItems) return NULL;
        if (*nPos >= menu->cItems) return NULL;
-       pItem = menu->rgItems;
-       //pItem = &menu->rgItems[*nPos];
-       i = 0;
-        while(pItem) // Do this for now.
-        {
-           if (i < (INT)menu->cItems)
-           {
-              if ( *nPos == i ) return pItem;
-           }
-           pItem = pItem->Next;
-           i++;
-        }      
+       return &menu->rgItems[*nPos];
     }
     else
     {
         PITEM item = menu->rgItems;
-       for (i = 0; item ,i < menu->cItems; i++,  item = item->Next)//, item++)
+       for (i = 0; item, i < menu->cItems; i++, item++)
        {
            if (item->spSubMenu)
            {
-               PMENU psubmenu = item->spSubMenu;
+               PMENU psubmenu = item->spSubMenu;//VerifyMenu(item->spSubMenu);
                PITEM subitem = MENU_FindItem( &psubmenu, nPos, wFlags );
                if (subitem)
                {
@@ -376,20 +333,20 @@ ITEM *MENU_FindItem( PMENU *pmenu, UINT *nPos, UINT wFlags )
     return fallback;
 }
 
-BOOL IntRemoveMenu( PMENU pMenu, UINT nPos, UINT wFlags, BOOL bRecurse )
+BOOL FASTCALL
+IntRemoveMenuItem( PMENU pMenu, UINT nPos, UINT wFlags, BOOL bRecurse )
 {
     PITEM item, NewItems;
 
     TRACE("(menu=%p pos=%04x flags=%04x)\n",pMenu, nPos, wFlags);
     if (!(item = MENU_FindItem( &pMenu, &nPos, wFlags ))) return FALSE;
 
-      /* Remove item */
-
-    //FreeMenuText(pMenu,item);
+    /* Remove item */
 
+    FreeMenuText(pMenu,item);
     if (bRecurse && item->spSubMenu)
     {
-       IntDestroyMenu(item->spSubMenu, TRUE);
+       IntDestroyMenuObject(item->spSubMenu, bRecurse, TRUE);
     }
     ////// Use cAlloced with inc's of 8's....
     if (--pMenu->cItems == 0)
@@ -413,6 +370,100 @@ BOOL IntRemoveMenu( PMENU pMenu, UINT nPos, UINT wFlags, BOOL bRecurse )
     return TRUE;
 }
 
+/**********************************************************************
+ *         MENU_InsertItem
+ *
+ * Insert (allocate) a new item into a menu.
+ */
+ITEM *MENU_InsertItem( PMENU menu, UINT pos, UINT flags, PMENU *submenu, UINT *npos )
+{
+    ITEM *newItems;
+
+    /* Find where to insert new item */
+
+    if (flags & MF_BYPOSITION) {
+        if (pos > menu->cItems)
+            pos = menu->cItems;
+    } else {
+        if (!MENU_FindItem( &menu, &pos, flags ))
+        {
+            if (submenu) *submenu = menu;
+            if (npos) *npos = pos;
+            pos = menu->cItems;
+        }
+    }
+
+    /* Make sure that MDI system buttons stay on the right side.
+     * Note: XP treats only bitmap handles 1 - 6 as "magic" ones
+     * regardless of their id.
+     */
+    while ( pos > 0 &&
+           (INT_PTR)menu->rgItems[pos - 1].hbmp >= (INT_PTR)HBMMENU_SYSTEM &&
+           (INT_PTR)menu->rgItems[pos - 1].hbmp <= (INT_PTR)HBMMENU_MBAR_CLOSE_D)
+        pos--;
+
+    TRACE("inserting at %u flags %x\n", pos, flags);
+
+    /* Create new items array */
+
+    newItems = DesktopHeapAlloc(menu->head.rpdesk, sizeof(ITEM) * (menu->cItems+1) );
+    if (!newItems)
+    {
+        WARN("allocation failed\n" );
+        return NULL;
+    }
+    if (menu->cItems > 0)
+    {
+       /* Copy the old array into the new one */
+       if (pos > 0) RtlCopyMemory( newItems, menu->rgItems, pos * sizeof(ITEM) );
+       if (pos < menu->cItems) RtlCopyMemory( &newItems[pos+1], &menu->rgItems[pos], (menu->cItems-pos)*sizeof(ITEM) );
+       DesktopHeapFree(menu->head.rpdesk, menu->rgItems );
+    }
+    menu->rgItems = newItems;
+    menu->cItems++;
+    RtlZeroMemory( &newItems[pos], sizeof(*newItems) );
+    menu->cyMenu = 0; /* force size recalculate */
+    return &newItems[pos];
+}
+
+BOOL FASTCALL
+IntInsertMenuItem(
+    _In_ PMENU MenuObject,
+    UINT uItem,
+    BOOL fByPosition,
+    PROSMENUITEMINFO ItemInfo,
+    PUNICODE_STRING lpstr)
+{
+   PITEM MenuItem;
+   PMENU SubMenu = NULL;
+
+   NT_ASSERT(MenuObject != NULL);
+
+   if (MAX_MENU_ITEMS <= MenuObject->cItems)
+   {
+      EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
+      return FALSE;
+   }
+
+   SubMenu = MenuObject;
+
+   if(!(MenuItem = MENU_InsertItem( SubMenu, uItem, fByPosition ? MF_BYPOSITION : MF_BYCOMMAND, &SubMenu, &uItem ))) return FALSE;
+   
+   if(!IntSetMenuItemInfo(SubMenu, MenuItem, ItemInfo, lpstr))
+   {
+      IntRemoveMenuItem(SubMenu, uItem, fByPosition ? MF_BYPOSITION : MF_BYCOMMAND, FALSE);
+      return FALSE;
+   }
+
+   /* Force size recalculation! */
+   SubMenu->cyMenu = 0;
+   MenuItem->hbmpChecked = MenuItem->hbmpUnchecked = 0;
+
+   TRACE("IntInsertMenuItemToList = %i %d\n", uItem, (BOOL)((INT)uItem >= 0));
+
+   return TRUE;
+}
+
 PMENU FASTCALL
 IntCreateMenu(PHANDLE Handle, BOOL IsMenuBar)
 {
@@ -460,21 +511,21 @@ BOOL FASTCALL
 IntCloneMenuItems(PMENU Destination, PMENU Source)
 {
    PITEM MenuItem, NewMenuItem = NULL;
-   PITEM Old = NULL;
+   UINT i;
 
    if(!Source->cItems)
       return FALSE;
 
+   NewMenuItem = DesktopHeapAlloc(Destination->head.rpdesk, (Source->cItems+1) * sizeof(ITEM));
+   if(!NewMenuItem) return FALSE;
+
+   RtlZeroMemory(NewMenuItem, (Source->cItems+1) * sizeof(ITEM));
+
+   Destination->rgItems = NewMenuItem;
+
    MenuItem = Source->rgItems;
-   while(MenuItem)
+   for (i = 0; i < Source->cItems; i++, MenuItem++, NewMenuItem++)
    {
-      Old = NewMenuItem;
-      if(NewMenuItem)
-         NewMenuItem->Next = MenuItem;
-      NewMenuItem = DesktopHeapAlloc(Destination->head.rpdesk, sizeof(ITEM));
-      if(!NewMenuItem)
-         break;
-      RtlZeroMemory(NewMenuItem, sizeof(NewMenuItem));
       NewMenuItem->fType = MenuItem->fType;
       NewMenuItem->fState = MenuItem->fState;
       NewMenuItem->wID = MenuItem->wID;
@@ -506,16 +557,7 @@ IntCloneMenuItems(PMENU Destination, PMENU Source)
          NewMenuItem->lpstr.Buffer = MenuItem->lpstr.Buffer;
       }
       NewMenuItem->hbmp = MenuItem->hbmp;
-
-      NewMenuItem->Next = NULL;
-      if(Old)
-         Old->Next = NewMenuItem;
-      else
-         Destination->rgItems = NewMenuItem;
-      Destination->cItems++;
-      MenuItem = MenuItem->Next;
    }
-
    return TRUE;
 }
 
@@ -547,7 +589,7 @@ IntCloneMenu(PMENU Source)
    Menu->spwndNotify = NULL;
    Menu->cyMenu = 0;
    Menu->cxMenu = 0;
-   Menu->cItems = 0;
+   Menu->cItems = Source->cItems;
    Menu->iTop = 0;
    Menu->iMaxTop = 0;
    Menu->cxTextAlign = 0;
@@ -631,21 +673,13 @@ IntSetMenuInfo(PMENU Menu, PROSMENUINFO lpmi)
    {
       int i;
       PITEM item = Menu->rgItems;
-      for ( i = Menu->cItems; i; i--, item = item->Next)
-      {
-         if ( item->spSubMenu )
-         {
-            IntSetMenuInfo( item->spSubMenu, lpmi);
-         }
-      }
-     /* PITEM item = Menu->rgItems;
       for ( i = Menu->cItems; i; i--, item++)
       {
          if ( item->spSubMenu )
          {
             IntSetMenuInfo( item->spSubMenu, lpmi);
          }
-      }*/      
+      }      
    }
    if (sizeof(MENUINFO) < lpmi->cbSize)
    {
@@ -664,117 +698,6 @@ IntSetMenuInfo(PMENU Menu, PROSMENUINFO lpmi)
    return TRUE;
 }
 
-//
-// Old and yeah~..... Why start with a -1 for position search?
-//
-int FASTCALL
-IntGetMenuItemByFlag(PMENU Menu,
-                     UINT uSearchBy,
-                     UINT fFlag,
-                     PMENU *SubMenu,
-                     PITEM *MenuItem,
-                     PITEM *PrevMenuItem)
-{
-   PITEM PrevItem = NULL;
-   PITEM CurItem = Menu->rgItems;
-   int p;
-   int ret;
-
-   if(MF_BYPOSITION & fFlag)
-   {
-      p = uSearchBy;
-      while(CurItem && (p > 0))
-      {
-         PrevItem = CurItem;
-         CurItem = CurItem->Next;
-         p--;
-      }
-      if(CurItem)
-      {
-         if(MenuItem)
-            *MenuItem = CurItem;
-         if(PrevMenuItem)
-            *PrevMenuItem = PrevItem;
-      }
-      else
-      {
-         if(MenuItem)
-            *MenuItem = NULL;
-         if(PrevMenuItem)
-            *PrevMenuItem = NULL; /* ? */
-         return -1;
-      }
-
-      return uSearchBy - p;
-   }
-   else
-   {
-      p = 0;
-      while(CurItem)
-      {
-         if(CurItem->wID == uSearchBy)
-         {
-            if(MenuItem)
-               *MenuItem = CurItem;
-            if(PrevMenuItem)
-               *PrevMenuItem = PrevItem;
-            if(SubMenu)
-                *SubMenu = Menu;
-
-            return p;
-         }
-         else
-         {
-            if(CurItem->spSubMenu)
-            {
-               ret = IntGetMenuItemByFlag(CurItem->spSubMenu, uSearchBy, fFlag, SubMenu, MenuItem, PrevMenuItem);
-               if(ret != -1)
-               {
-                 return ret;
-               }
-            }
-         }
-         PrevItem = CurItem;
-         CurItem = CurItem->Next;
-         p++;
-      }
-   }
-   return -1;
-}
-
-
-int FASTCALL
-IntInsertMenuItemToList(PMENU Menu, PITEM MenuItem, int pos)
-{
-   PITEM CurItem;
-   PITEM LastItem = NULL;
-   UINT npos = 0;
-
-   CurItem = Menu->rgItems;
-   while(CurItem && (pos != 0))
-   {
-      LastItem = CurItem;
-      CurItem = CurItem->Next;
-      pos--;
-      npos++;
-   }
-
-   if(LastItem)
-   {
-      /* Insert the item after LastItem */
-      LastItem->Next = MenuItem;
-   }
-   else
-   {
-      /* Insert at the beginning */
-      Menu->rgItems = MenuItem;
-   }
-   MenuItem->Next = CurItem;
-   Menu->cItems++;
-
-   return npos;
-}
-
 BOOL FASTCALL
 IntGetMenuItemInfo(PMENU Menu, /* UNUSED PARAM!! */
                    PITEM MenuItem, PROSMENUITEMINFO lpmii)
@@ -850,18 +773,17 @@ BOOL FASTCALL
 IntSetMenuItemInfo(PMENU MenuObject, PITEM MenuItem, PROSMENUITEMINFO lpmii, PUNICODE_STRING lpstr)
 {
    PMENU SubMenuObject;
-   UINT fTypeMask = (MFT_BITMAP | MFT_MENUBARBREAK | MFT_MENUBREAK | MFT_OWNERDRAW | MFT_RADIOCHECK | MFT_RIGHTJUSTIFY | MFT_SEPARATOR);
 
    if(!MenuItem || !MenuObject || !lpmii)
    {
       return FALSE;
    }
-   if (lpmii->fType & ~fTypeMask)
+   if ( lpmii->fMask & MIIM_FTYPE )
    {
-     ERR("IntSetMenuItemInfo invalid fType flags %x\n", lpmii->fType & ~fTypeMask);
-     lpmii->fMask &= ~(MIIM_TYPE | MIIM_FTYPE);
+      MenuItem->fType &= ~MENUITEMINFO_TYPE_MASK;
+      MenuItem->fType |= lpmii->fType & MENUITEMINFO_TYPE_MASK;
    }
-   if (lpmii->fMask &  MIIM_TYPE)
+   if (lpmii->fMask & MIIM_TYPE)
    {
       #if 0 //// Done in User32.
       if (lpmii->fMask & ( MIIM_STRING | MIIM_FTYPE | MIIM_BITMAP))
@@ -882,6 +804,7 @@ IntSetMenuItemInfo(PMENU MenuObject, PITEM MenuItem, PROSMENUITEMINFO lpmii, PUN
       {
          FreeMenuText(MenuObject,MenuItem);
          RtlInitUnicodeString(&MenuItem->lpstr, NULL);
+         MenuItem->Xlpstr = NULL;
       }
       if(lpmii->fType & MFT_BITMAP)
       {
@@ -891,25 +814,12 @@ IntSetMenuItemInfo(PMENU MenuObject, PITEM MenuItem, PROSMENUITEMINFO lpmii, PUN
          { /* Win 9x/Me stuff */
            MenuItem->hbmp = (HBITMAP)((ULONG_PTR)(LOWORD(lpmii->dwTypeData)));
          }
+         lpmii->dwTypeData = 0;
       }
-      MenuItem->fType |= lpmii->fType;
-   }
-   if (lpmii->fMask & MIIM_FTYPE )
-   {
-      #if 0 //// ?
-      if(( lpmii->fType & MFT_BITMAP))
-      {
-         ERR("IntSetMenuItemInfo: Can not use FTYPE and MFT_BITMAP.\n");
-         SetLastNtError( ERROR_INVALID_PARAMETER);
-         return FALSE;
-      }
-      #endif
-      MenuItem->fType &= ~MENUITEMINFO_TYPE_MASK;
-      MenuItem->fType |= lpmii->fType & MENUITEMINFO_TYPE_MASK;
    }
    if(lpmii->fMask & MIIM_BITMAP)
    {
-         MenuItem->hbmp = lpmii->hbmpItem;
+      MenuItem->hbmp = lpmii->hbmpItem;
    }
    if(lpmii->fMask & MIIM_CHECKMARKS)
    {
@@ -942,9 +852,14 @@ IntSetMenuItemInfo(PMENU MenuObject, PITEM MenuItem, PROSMENUITEMINFO lpmii, PUN
          SubMenuObject = UserGetMenuObject(lpmii->hSubMenu);
          if (SubMenuObject != NULL)
          {
+            if ( MENU_depth( SubMenuObject, 0) > MAXMENUDEPTH)
+            {
+               ERR( "Loop detected in menu hierarchy or maximum menu depth exceeded!\n");
+               return FALSE;
+            }
             SubMenuObject->fFlags |= MNF_POPUP;
             // Now fix the test_subpopup_locked_by_menu tests....
-            if (MenuItem->spSubMenu) UserDereferenceObject(MenuItem->spSubMenu);
+            if (MenuItem->spSubMenu) IntReleaseMenuObject(MenuItem->spSubMenu);
             MenuItem->spSubMenu = SubMenuObject;
             UserReferenceObject(SubMenuObject);
          }
@@ -956,7 +871,7 @@ IntSetMenuItemInfo(PMENU MenuObject, PITEM MenuItem, PROSMENUITEMINFO lpmii, PUN
       }
       else
       {  // If submenu just dereference it.
-         if (MenuItem->spSubMenu) UserDereferenceObject(MenuItem->spSubMenu);
+         if (MenuItem->spSubMenu) IntReleaseMenuObject(MenuItem->spSubMenu);
          MenuItem->spSubMenu = NULL;
       }
    }
@@ -964,9 +879,12 @@ IntSetMenuItemInfo(PMENU MenuObject, PITEM MenuItem, PROSMENUITEMINFO lpmii, PUN
    if ((lpmii->fMask & MIIM_STRING) ||
       ((lpmii->fMask & MIIM_TYPE) && (MENU_ITEM_TYPE(lpmii->fType) == MF_STRING)))
    {
+      /* free the string when used */
       FreeMenuText(MenuObject,MenuItem);
+      RtlInitUnicodeString(&MenuItem->lpstr, NULL);
+      MenuItem->Xlpstr = NULL;
 
-      if(lpmii->dwTypeData && lpmii->cch)
+      if(lpmii->dwTypeData && lpmii->cch && lpstr && lpstr->Buffer)
       {
          UNICODE_STRING Source;
 
@@ -984,27 +902,15 @@ IntSetMenuItemInfo(PMENU MenuObject, PITEM MenuItem, PROSMENUITEMINFO lpmii, PUN
             MenuItem->cch = MenuItem->lpstr.Length / sizeof(WCHAR);
             MenuItem->Xlpstr = (USHORT*)MenuItem->lpstr.Buffer;
          }
-         else
-         {
-            RtlInitUnicodeString(&MenuItem->lpstr, NULL);
-            MenuItem->Xlpstr = NULL;
-         }
-      }
-      else
-      {
-         if (0 == (MenuObject->fFlags & MNF_SYSDESKMN))
-         {
-            MenuItem->fType |= MF_SEPARATOR;
-         }
-         RtlInitUnicodeString(&MenuItem->lpstr, NULL);
       }
    }
 
-   //if( !MenuItem->lpstr.Buffer && !(MenuItem->fType & MFT_OWNERDRAW) && !MenuItem->hbmp)
-   //   MenuItem->fType |= MFT_SEPARATOR; break system menu.....
-
-   /* Force size recalculation! */
-   MenuObject->cyMenu = 0;
+   if( !(MenuObject->fFlags & MNF_SYSDESKMN) &&
+       !MenuItem->Xlpstr &&
+       !lpmii->dwTypeData &&
+       !(MenuItem->fType & MFT_OWNERDRAW) &&
+       !MenuItem->hbmp)
+      MenuItem->fType |= MFT_SEPARATOR;
 
    if (sizeof(ROSMENUITEMINFO) == lpmii->cbSize)
    {
@@ -1022,130 +928,6 @@ IntSetMenuItemInfo(PMENU MenuObject, PITEM MenuItem, PROSMENUITEMINFO lpmii, PUN
 }
 
 
-/**********************************************************************
- *         MENU_InsertItem
- *
- * Insert (allocate) a new item into a menu.
- */
-ITEM *MENU_InsertItem( PMENU menu, UINT pos, UINT flags )
-{
-    ITEM *newItems;
-
-    /* Find where to insert new item */
-
-    if (flags & MF_BYPOSITION) {
-        if (pos > menu->cItems)
-            pos = menu->cItems;
-    } else {
-        if (!MENU_FindItem( &menu, &pos, flags ))
-            pos = menu->cItems;
-    }
-
-    /* Make sure that MDI system buttons stay on the right side.
-     * Note: XP treats only bitmap handles 1 - 6 as "magic" ones
-     * regardless of their id.
-     */
-    while ( pos > 0 &&
-           (INT_PTR)menu->rgItems[pos - 1].hbmp >= (INT_PTR)HBMMENU_SYSTEM &&
-           (INT_PTR)menu->rgItems[pos - 1].hbmp <= (INT_PTR)HBMMENU_MBAR_CLOSE_D)
-        pos--;
-
-    TRACE("inserting at %u flags %x\n", pos, flags);
-
-    /* Create new items array */
-
-    newItems = DesktopHeapAlloc(menu->head.rpdesk, sizeof(ITEM) * (menu->cItems+1) );
-    if (!newItems)
-    {
-        WARN("allocation failed\n" );
-        return NULL;
-    }
-    if (menu->cItems > 0)
-    {
-       /* Copy the old array into the new one */
-       if (pos > 0) RtlCopyMemory( newItems, menu->rgItems, pos * sizeof(ITEM) );
-       if (pos < menu->cItems) RtlCopyMemory( &newItems[pos+1], &menu->rgItems[pos], (menu->cItems-pos)*sizeof(ITEM) );
-       DesktopHeapFree(menu->head.rpdesk, menu->rgItems );
-    }
-    menu->rgItems = newItems;
-    menu->cItems++;
-    RtlZeroMemory( &newItems[pos], sizeof(*newItems) );
-    menu->cyMenu = 0; /* force size recalculate */
-    return &newItems[pos];
-}
-
-BOOL FASTCALL
-IntInsertMenuItem(
-    _In_ PMENU MenuObject,
-    UINT uItem,
-    BOOL fByPosition,
-    PROSMENUITEMINFO ItemInfo)
-{
-   int pos;
-   PITEM MenuItem;
-   PMENU SubMenu = NULL;
-
-   NT_ASSERT(MenuObject != NULL);
-   //ERR("InsertMenuItem\n");
-   if (MAX_MENU_ITEMS <= MenuObject->cItems)
-   {
-      EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
-      return FALSE;
-   }
-
-   if (fByPosition)
-   {
-      SubMenu = MenuObject;
-      /* calculate position */
-      pos = (int)uItem;
-      if(uItem > MenuObject->cItems)
-      {
-         pos = MenuObject->cItems;
-      }
-   }
-   else
-   {
-      pos = IntGetMenuItemByFlag(MenuObject, uItem, MF_BYCOMMAND, &SubMenu, NULL, NULL);
-   }
-   if (SubMenu == NULL)
-   {
-       /* Default to last position of menu */
-      SubMenu = MenuObject;
-      pos = MenuObject->cItems;
-   }
-
-
-   if (pos < -1)
-   {
-      pos = -1;
-   }
-
-   MenuItem = DesktopHeapAlloc(MenuObject->head.rpdesk, sizeof(ITEM));
-   if (NULL == MenuItem)
-   {
-      EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
-      return FALSE;
-   }
-
-   RtlZeroMemory(MenuItem, sizeof(MenuItem));
-
-   if(!IntSetMenuItemInfo(SubMenu, MenuItem, ItemInfo, NULL))
-   {
-      DesktopHeapFree(MenuObject->head.rpdesk, MenuItem);
-      return FALSE;
-   }
-
-   /* Force size recalculation! */
-   MenuObject->cyMenu = 0;
-   MenuItem->hbmpChecked = MenuItem->hbmpUnchecked = 0;
-
-   pos = IntInsertMenuItemToList(SubMenu, MenuItem, pos);
-
-   TRACE("IntInsertMenuItemToList = %i\n", pos);
-
-   return (pos >= 0);
-}
-
 UINT FASTCALL
 IntEnableMenuItem(PMENU MenuObject, UINT uIDEnableItem, UINT uEnable)
 {
@@ -1173,109 +955,7 @@ IntEnableMenuItem(PMENU MenuObject, UINT uIDEnableItem, UINT uEnable)
    }
    return res;
 }
-#if 0 // Moved to User32.
-DWORD FASTCALL
-IntBuildMenuItemList(PMENU MenuObject, PVOID Buffer, ULONG nMax)
-{
-   DWORD res = 0;
-   ROSMENUITEMINFO mii;
-   PVOID Buf;
-   PITEM CurItem = MenuObject->rgItems;
-   PWCHAR StrOut;
-   NTSTATUS Status;
-   WCHAR NulByte;
 
-   if (0 != nMax)
-   {
-      if (nMax < MenuObject->cItems * sizeof(ROSMENUITEMINFO))
-      {
-         return 0;
-      }
-      StrOut = (PWCHAR)((char *) Buffer + MenuObject->cItems
-                        * sizeof(ROSMENUITEMINFO));
-      nMax -= MenuObject->cItems * sizeof(ROSMENUITEMINFO);
-      Buf = Buffer;
-      mii.cbSize = sizeof(ROSMENUITEMINFO);
-      mii.fMask = 0;
-      NulByte = L'\0';
-
-      while (NULL != CurItem)
-      {
-         mii.cch = CurItem->lpstr.Length / sizeof(WCHAR);
-         mii.dwItemData = CurItem->dwItemData;
-         if (0 != CurItem->lpstr.Length)
-         {
-            mii.dwTypeData = StrOut;
-         }
-         else
-         {
-            mii.dwTypeData = NULL;
-         }
-         mii.fState = CurItem->fState;
-         mii.fType = CurItem->fType;
-         mii.wID = CurItem->wID;
-         mii.hbmpChecked = CurItem->hbmpChecked;
-         mii.hbmpItem = CurItem->hbmp;
-         mii.hbmpUnchecked = CurItem->hbmpUnchecked;
-         mii.hSubMenu = CurItem->spSubMenu ? CurItem->spSubMenu->head.h : NULL;
-         mii.Rect.left   = CurItem->xItem; 
-         mii.Rect.top    = CurItem->yItem; 
-         mii.Rect.right  = CurItem->cxItem; // Do this for now......
-         mii.Rect.bottom = CurItem->cyItem;
-         mii.dxTab = CurItem->dxTab;
-         mii.lpstr = CurItem->lpstr.Buffer; // Can be read from user side!
-         //mii.maxBmpSize.cx = CurItem->cxBmp;
-         //mii.maxBmpSize.cy = CurItem->cyBmp;
-
-         Status = MmCopyToCaller(Buf, &mii, sizeof(ROSMENUITEMINFO));
-         if (! NT_SUCCESS(Status))
-         {
-            SetLastNtError(Status);
-            return 0;
-         }
-         Buf = (PVOID)((ULONG_PTR)Buf + sizeof(ROSMENUITEMINFO));
-
-         if (0 != CurItem->lpstr.Length
-               && (nMax >= CurItem->lpstr.Length + sizeof(WCHAR)))
-         {
-            /* Copy string */
-            Status = MmCopyToCaller(StrOut, CurItem->lpstr.Buffer,
-                                    CurItem->lpstr.Length);
-            if (! NT_SUCCESS(Status))
-            {
-               SetLastNtError(Status);
-               return 0;
-            }
-            StrOut += CurItem->lpstr.Length / sizeof(WCHAR);
-            Status = MmCopyToCaller(StrOut, &NulByte, sizeof(WCHAR));
-            if (! NT_SUCCESS(Status))
-            {
-               SetLastNtError(Status);
-               return 0;
-            }
-            StrOut++;
-            nMax -= CurItem->lpstr.Length + sizeof(WCHAR);
-         }
-         else if (0 != CurItem->lpstr.Length)
-         {
-            break;
-         }
-
-         CurItem = CurItem->Next;
-         res++;
-      }
-   }
-   else
-   {
-      while (NULL != CurItem)
-      {
-         res += sizeof(ROSMENUITEMINFO) + CurItem->lpstr.Length + sizeof(WCHAR);
-         CurItem = CurItem->Next;
-      }
-   }
-   return res;
-}
-#endif
 DWORD FASTCALL
 IntCheckMenuItem(PMENU MenuObject, UINT uIDCheckItem, UINT uCheck)
 {
@@ -1301,32 +981,31 @@ IntHiliteMenuItem(PWND WindowObject,
 
    if (!(MenuItem = MENU_FindItem( &MenuObject, &uItemHilite, uHilite ))) return FALSE;
 
-   if (MenuItem)
+   if (uHilite & MF_HILITE)
    {
-      if (uHilite & MF_HILITE)
-      {
-         MenuItem->fState |= MF_HILITE;
-      }
-      else
-      {
-         MenuItem->fState &= ~MF_HILITE;
-      }
+      MenuItem->fState |= MF_HILITE;
+   }
+   else
+   {
+      MenuItem->fState &= ~MF_HILITE;
    }
    /* FIXME: Update the window's menu */
 
-   return TRUE;
+   return TRUE; // Always returns true!!!!
 }
 
 BOOL FASTCALL
 UserSetMenuDefaultItem(PMENU MenuObject, UINT uItem, UINT fByPos)
 {
-   BOOL ret = FALSE;
+   UINT i;
    PITEM MenuItem = MenuObject->rgItems;
 
-   while(MenuItem)
+   if (!MenuItem) return FALSE;   
+
+   /* reset all default-item flags */
+   for (i = 0; MenuItem, i < MenuObject->cItems; i++, MenuItem++)
    {
-      MenuItem->fState &= ~MFS_DEFAULT;
-      MenuItem = MenuItem->Next;
+       MenuItem->fState &= ~MFS_DEFAULT;
    }
 
    /* no default item */
@@ -1334,90 +1013,59 @@ UserSetMenuDefaultItem(PMENU MenuObject, UINT uItem, UINT fByPos)
    {
       return TRUE;
    }
-
-   if(fByPos)
+   MenuItem = MenuObject->rgItems;
+   if ( fByPos )
    {
-      UINT pos = 0;
-      while(MenuItem)
-      {
-         if(pos == uItem)
-         {
-            MenuItem->fState |= MFS_DEFAULT;
-            ret = TRUE;
-         }
-         else
-         {
-            MenuItem->fState &= ~MFS_DEFAULT;
-         }
-         pos++;
-         MenuItem = MenuItem->Next;
-      }
+      if ( uItem >= MenuObject->cItems ) return FALSE;
+         MenuItem[uItem].fState |= MFS_DEFAULT;
+      return TRUE;
    }
    else
    {
-      while(MenuItem)
+      for (i = 0; MenuItem, i < MenuObject->cItems; i++, MenuItem++)
       {
-         if(!ret && (MenuItem->wID == uItem))
-         {
-            MenuItem->fState |= MFS_DEFAULT;
-            ret = TRUE;
-         }
-         else
-         {
-            MenuItem->fState &= ~MFS_DEFAULT;
-         }
-         MenuItem = MenuItem->Next;
+          if (MenuItem->wID == uItem)
+          {
+             MenuItem->fState |= MFS_DEFAULT;
+             return TRUE;
+          }
       }
+
    }
-   return ret;
+   return FALSE;
 }
 
 
 UINT FASTCALL
-IntGetMenuDefaultItem(PMENU MenuObject, UINT fByPos, UINT gmdiFlags,
-                      DWORD *gismc)
+IntGetMenuDefaultItem(PMENU MenuObject, UINT fByPos, UINT gmdiFlags, DWORD *gismc)
 {
-   UINT x = 0;
-   UINT res = -1;
-   UINT sres;
+   UINT i = 0;
    PITEM MenuItem = MenuObject->rgItems;
 
-   while(MenuItem)
-   {
-      if(MenuItem->fState & MFS_DEFAULT)
-      {
-
-         if(!(gmdiFlags & GMDI_USEDISABLED) && (MenuItem->fState & MFS_DISABLED))
-            break;
+   /* empty menu */
+   if (!MenuItem) return -1;
 
-         if(fByPos)
-            res = x;
-         else
-            res = MenuItem->wID;
-
-         if((*gismc < MAX_GOINTOSUBMENU) && (gmdiFlags & GMDI_GOINTOPOPUPS) &&
-               MenuItem->spSubMenu)
-         {
-
-            if(MenuItem->spSubMenu == MenuObject)
-               break;
-
-            (*gismc)++;
-            sres = IntGetMenuDefaultItem(MenuItem->spSubMenu, fByPos, gmdiFlags, gismc);
-            (*gismc)--;
+   while ( !( MenuItem->fState & MFS_DEFAULT ) )
+   {
+      i++; MenuItem++;
+      if  (i >= MenuObject->cItems ) return -1;
+   }
 
-            if(sres > (UINT)-1)
-               res = sres;
-         }
+   /* default: don't return disabled items */
+   if ( (!(GMDI_USEDISABLED & gmdiFlags)) && (MenuItem->fState & MFS_DISABLED )) return -1;
 
-         break;
-      }
+   /* search rekursiv when needed */
+   if ( (MenuItem->fType & MF_POPUP) && (gmdiFlags & GMDI_GOINTOPOPUPS) && MenuItem->spSubMenu)
+   {
+      UINT ret;
+      (*gismc)++;
+      ret = IntGetMenuDefaultItem( MenuItem->spSubMenu, fByPos, gmdiFlags, gismc );
+      (*gismc)--;
+      if ( -1 != ret ) return ret;
 
-      MenuItem = MenuItem->Next;
-      x++;
+      /* when item not found in submenu, return the popup item */
    }
-
-   return res;
+   return ( fByPos ) ? i : MenuItem->wID;
 }
 
 VOID FASTCALL
@@ -1484,7 +1132,7 @@ IntCleanupMenus(struct _EPROCESS *Process, PPROCESSINFO Win32Process)
    {
       LastHead = Win32Process->MenuListHead.Flink;
       MenuObject = CONTAINING_RECORD(Win32Process->MenuListHead.Flink, MENU, ListEntry);
-      ERR("Menus are stuck on the process list!\n");
+      TRACE("Menus are stuck on the process list!\n");
       IntDestroyMenuObject(MenuObject, FALSE, TRUE);
    }
 
@@ -1631,7 +1279,8 @@ UserInsertMenuItem(
    PMENU Menu,
    UINT uItem,
    BOOL fByPosition,
-   LPCMENUITEMINFOW UnsafeItemInfo)
+   LPCMENUITEMINFOW UnsafeItemInfo,
+   PUNICODE_STRING lpstr)
 {
    NTSTATUS Status;
    ROSMENUITEMINFO ItemInfo;
@@ -1646,7 +1295,7 @@ UserInsertMenuItem(
          EngSetLastError(ERROR_INVALID_PARAMETER);
          return FALSE;
       }
-      return IntInsertMenuItem(Menu, uItem, fByPosition, &ItemInfo);
+      return IntInsertMenuItem(Menu, uItem, fByPosition, &ItemInfo, lpstr);
    }
 
    /* Try to copy without last field (not present in older versions) */
@@ -1659,7 +1308,7 @@ UserInsertMenuItem(
          return FALSE;
       }
       ItemInfo.hbmpItem = (HBITMAP)0;
-      return IntInsertMenuItem(Menu, uItem, fByPosition, &ItemInfo);
+      return IntInsertMenuItem(Menu, uItem, fByPosition, &ItemInfo, lpstr);
    }
 
    SetLastNtError(Status);
@@ -1717,7 +1366,7 @@ UINT FASTCALL IntFindSubMenu(HMENU *hMenu, HMENU hSubTarget )
         return NO_SELECTED_ITEM;
 
     item = menu->rgItems;
-    for (i = 0; i < menu->cItems; i++, item = item->Next)//item++)
+    for (i = 0; i < menu->cItems; i++, item++)
     {
         if (!item->spSubMenu)
            continue;
@@ -1792,7 +1441,8 @@ UserMenuItemInfo(
    UINT Item,
    BOOL ByPosition,
    PROSMENUITEMINFO UnsafeItemInfo,
-   BOOL SetOrGet)
+   BOOL SetOrGet,
+   PUNICODE_STRING lpstr)
 {
    PITEM MenuItem;
    ROSMENUITEMINFO ItemInfo;
@@ -1836,7 +1486,7 @@ UserMenuItemInfo(
 
    if (SetOrGet)
    {
-      Ret = IntSetMenuItemInfo(Menu, MenuItem, &ItemInfo, NULL);
+      Ret = IntSetMenuItemInfo(Menu, MenuItem, &ItemInfo, lpstr);
    }
    else
    {
@@ -1931,7 +1581,6 @@ IntGetMenuItemRect(
 {
    LONG XMove, YMove;
    PITEM MenuItem;
-   //int p = 0;
 
    if (!pWnd)
    {
@@ -2109,7 +1758,6 @@ BOOL FASTCALL UserDestroyMenu(HMENU hMenu)
       return FALSE;
    }
 
-   //if(Menu->Process != PsGetCurrentProcess())
    if (Menu->head.rpdesk != pti->rpdesk)
    {
       EngSetLastError(ERROR_ACCESS_DENIED);
@@ -2277,15 +1925,15 @@ NtUserGetMenuBarInfo(
    //kmbi.fBarFocused = top_popup_hmenu == hMenu;
    if (idItem)
    {
-       PITEM MenuItem;
-       UINT nPos = idItem-1;
+       //PITEM MenuItem;
+       //UINT nPos = idItem-1;
        kmbi.fFocused = Menu->iItem == idItem-1;
-       //if (kmbi->fFocused && (Menu->rgItems[idItem - 1].spSubMenu))
-       MenuItem = MENU_FindItem (&Menu, &nPos, MF_BYPOSITION);
-       if ( MenuItem && kmbi.fFocused && MenuItem->spSubMenu )
+       if (kmbi.fFocused && (Menu->rgItems[idItem - 1].spSubMenu))
+       //MenuItem = MENU_FindItem (&Menu, &nPos, MF_BYPOSITION);
+       //if ( MenuItem && kmbi.fFocused && MenuItem->spSubMenu )
        {
-          //kmbi.hwndMenu = Menu->rgItems[idItem - 1].spSubMenu->hWnd;
-          kmbi.hwndMenu = MenuItem->spSubMenu->hWnd;
+          kmbi.hwndMenu = Menu->rgItems[idItem - 1].spSubMenu->hWnd;
+          //kmbi.hwndMenu = MenuItem->spSubMenu->hWnd;
        }
    }
 /*   else
@@ -2327,6 +1975,7 @@ NtUserGetMenuIndex(
 {
    PMENU Menu, SubMenu;
    PITEM MenuItem;
+   UINT i;
    DECLARE_RETURN(UINT);
 
    TRACE("Enter NtUserGetMenuIndex\n");
@@ -2337,13 +1986,11 @@ NtUserGetMenuIndex(
       RETURN(0xFFFFFFFF);
 
    MenuItem = Menu->rgItems;
-   while(MenuItem)
+   for (i = 0; i < Menu->cItems; i++, MenuItem++)
    {
-      if (MenuItem->spSubMenu == SubMenu)
-         RETURN(MenuItem->wID);
-      MenuItem = MenuItem->Next;
+       if (MenuItem->spSubMenu == SubMenu)
+          RETURN(MenuItem->wID);
    }
-
    RETURN(0xFFFFFFFF);
 
 CLEANUP:
@@ -2507,7 +2154,7 @@ NtUserMenuItemFromPoint(
    Y -= Window->rcWindow.top;
 
    mi = Menu->rgItems;
-   for (i = 0; NULL != mi; i++)//, mi++)
+   for (i = 0; i < Menu->cItems; i++, mi++)
    {
       RECTL Rect;
       Rect.left   = mi->xItem; 
@@ -2519,7 +2166,6 @@ NtUserMenuItemFromPoint(
       {
          break;
       }
-      mi = mi->Next;
    }
 
    RETURN( (mi ? i : NO_SELECTED_ITEM));
@@ -2696,7 +2342,7 @@ NtUserThunkedMenuItemInfo(
       RETURN(FALSE);
    }
 
-   lstrCaption.Buffer = NULL;
+   RtlInitUnicodeString(&lstrCaption, 0);
 
    /* Check if we got a Caption */
    if (lpszCaption && lpszCaption->Buffer)
@@ -2711,12 +2357,11 @@ NtUserThunkedMenuItemInfo(
          SetLastNtError(Status);
          RETURN(FALSE);
       }
-      ///// Now use it!
    }
 
-   if (bInsert) RETURN( UserInsertMenuItem(Menu, uItem, fByPosition, lpmii));
+   if (bInsert) RETURN( UserInsertMenuItem(Menu, uItem, fByPosition, lpmii, &lstrCaption));
 
-   RETURN( UserMenuItemInfo(Menu, uItem, fByPosition, (PROSMENUITEMINFO)lpmii, TRUE));
+   RETURN( UserMenuItemInfo(Menu, uItem, fByPosition, (PROSMENUITEMINFO)lpmii, TRUE, &lstrCaption));
 
 CLEANUP:
    TRACE("Leave NtUserThunkedMenuItemInfo, ret=%i\n",_ret_);
index 9ff6b0c..e583054 100644 (file)
@@ -38,8 +38,7 @@ BOOL FASTCALL
 IntCleanupMenus(struct _EPROCESS *Process, PPROCESSINFO Win32Process);
 
 BOOL FASTCALL
-IntInsertMenuItem(_In_ PMENU MenuObject, UINT uItem, BOOL fByPosition,
-                  PROSMENUITEMINFO ItemInfo);
+IntInsertMenuItem(_In_ PMENU MenuObject, UINT uItem, BOOL fByPosition, PROSMENUITEMINFO ItemInfo, PUNICODE_STRING lpstr);
 
 PMENU FASTCALL
 IntGetSystemMenu(PWND Window, BOOL bRevert, BOOL RetMenu);
@@ -47,4 +46,4 @@ IntGetSystemMenu(PWND Window, BOOL bRevert, BOOL RetMenu);
 UINT FASTCALL IntFindSubMenu(HMENU *hMenu, HMENU hSubTarget );
 UINT FASTCALL IntGetMenuState( HMENU hMenu, UINT uId, UINT uFlags);
 BOOL FASTCALL IntRemoveMenuItem(PMENU Menu, UINT uPosition, UINT uFlags, BOOL bRecurse);
-PITEM MENU_FindItem( PMENU *pmenu, UINT *nPos, UINT wFlags );
+PITEM FASTCALL MENU_FindItem( PMENU *pmenu, UINT *nPos, UINT wFlags );
index 9693508..2e45bc6 100644 (file)
@@ -1,6 +1,9 @@
 #pragma once
 
-PMENU FASTCALL UserGetMenuObject(HMENU hMenu);
+FORCEINLINE PMENU UserGetMenuObject(HMENU hMenu)
+{
+   return ValidateHandle(hMenu, TYPE_MENU);
+}
 
 #define ASSERT_REFS_CO(_obj_) \
 { \
index 6e95a3e..6259742 100644 (file)
@@ -953,6 +953,11 @@ IntGetSystemMenu(PWND Window, BOOL bRevert, BOOL RetMenu)
          SysMenu->fFlags |= MNF_SYSDESKMN;
          SysMenu->hWnd = Window->head.h;
          hNewMenu = co_IntLoadSysMenuTemplate();
+         //if ( Window->ExStyle & WS_EX_MDICHILD )
+         //hNewMenu = co_IntCallLoadMenu( NULL, L"SYSMENUMDI");
+         // else
+         //hNewMenu = co_IntCallLoadMenu( NULL, L"SYSMENU");
+         // Do the rest in here.
          if(!hNewMenu)
          {
             IntReleaseMenuObject(SysMenu);
@@ -985,7 +990,7 @@ IntGetSystemMenu(PWND Window, BOOL bRevert, BOOL RetMenu)
             ItemInfo.dwTypeData = NULL;
             ItemInfo.cch = 0;
             ItemInfo.hSubMenu = NewMenu->head.h;
-            IntInsertMenuItem(SysMenu, (UINT) -1, TRUE, &ItemInfo);
+            IntInsertMenuItem(SysMenu, (UINT) -1, TRUE, &ItemInfo, NULL);
 
             Window->SystemMenu = SysMenu->head.h;
 
index ba844d0..ae86741 100644 (file)
@@ -897,8 +897,11 @@ static BOOL MDI_AugmentFrameMenu( HWND frame, HWND hChild )
     nItems = GetMenuItemCount(menu) - 1;
     iId = GetMenuItemID(menu,nItems) ;
     if (iId == SC_RESTORE || iId == SC_CLOSE)
+    {
+        ERR("system buttons already exist\n");
        return 0;
-
+    }
+//// End
     /* create a copy of sysmenu popup and insert it into frame menu bar */
     if (!(hSysPopup = GetSystemMenu(hChild, FALSE)))
     {
@@ -907,21 +910,14 @@ static BOOL MDI_AugmentFrameMenu( HWND frame, HWND hChild )
     }
 
     AppendMenuW(menu, MF_HELP | MF_BITMAP,
-                SC_MINIMIZE, (LPCWSTR)HBMMENU_MBAR_MINIMIZE ) ;
+                SC_CLOSE, is_close_enabled(hChild, hSysPopup) ?
+                (LPCWSTR)HBMMENU_MBAR_CLOSE : (LPCWSTR)HBMMENU_MBAR_CLOSE_D );
     AppendMenuW(menu, MF_HELP | MF_BITMAP,
                 SC_RESTORE, (LPCWSTR)HBMMENU_MBAR_RESTORE );
     AppendMenuW(menu, MF_HELP | MF_BITMAP,
-                SC_CLOSE, is_close_enabled(hChild, hSysPopup) ?
-                (LPCWSTR)HBMMENU_MBAR_CLOSE : (LPCWSTR)HBMMENU_MBAR_CLOSE_D );
+                SC_MINIMIZE, (LPCWSTR)HBMMENU_MBAR_MINIMIZE ) ;
 
     /* The system menu is replaced by the child icon */
-/*    hIcon = (HICON)GetClassLongPtrW(hChild, GCLP_HICONSM);
-    if (!hIcon)
-        hIcon = (HICON)GetClassLongPtrW(hChild, GCLP_HICON);
-    if (!hIcon)
-        hIcon = LoadIconW(NULL, IDI_APPLICATION);
-*/
-//// End
     hIcon = (HICON)SendMessageW(hChild, WM_GETICON, ICON_SMALL, 0);
     if (!hIcon)
         hIcon = (HICON)SendMessageW(hChild, WM_GETICON, ICON_BIG, 0);
@@ -990,7 +986,10 @@ static BOOL MDI_RestoreFrameMenu( HWND frame, HWND hChild, HBITMAP hBmpClose )
     nItems = GetMenuItemCount(menu) - 1;
     iId = GetMenuItemID(menu,nItems) ;
     if( !(iId == SC_RESTORE || iId == SC_CLOSE) )
+    {
+        ERR("no system buttons then nothing to do\n");
        return 0;
+    }
 
     /*
      * Remove the system menu, If that menu is the icon of the window
@@ -1534,9 +1533,7 @@ LRESULT WINAPI DefMDIChildProcA( HWND hwnd, UINT message,
     case WM_CHILDACTIVATE:
     case WM_SYSCOMMAND:
     case WM_SHOWWINDOW:
-#ifndef __REACTOS__
     case WM_SETVISIBLE:
-#endif
     case WM_SIZE:
     case WM_NEXTMENU:
     case WM_SYSCHAR:
@@ -1613,9 +1610,8 @@ LRESULT WINAPI DefMDIChildProcW( HWND hwnd, UINT message,
         break;
 
     case WM_SHOWWINDOW:
-#ifndef __REACTOS__
     case WM_SETVISIBLE:
-#endif  //// Commented out r57663
+        //// Commented out r57663
         /*if (ci->hwndChildMaximized) ci->mdiFlags &= ~MDIF_NEEDUPDATE;
         else*/ MDI_PostUpdate(client, ci, SB_BOTH+1);
         break;
index 7470a3c..f1ef540 100644 (file)
@@ -15,6 +15,8 @@
 
 LRESULT DefWndNCPaint(HWND hWnd, HRGN hRgn, BOOL Active);
 BOOL WINAPI GdiValidateHandle(HGDIOBJ hobj);
+LRESULT DefWndNCHitTest(HWND hWnd, POINT Point);
+void FASTCALL NcGetSysPopupPos(HWND Wnd, RECT *Rect);
 
 WINE_DEFAULT_DEBUG_CHANNEL(menu);
 
@@ -132,7 +134,23 @@ static SIZE MenuCharSize;
  */
 FORCEINLINE PMENU MENU_GetMenu(HMENU hMenu)
 {
-    return ValidateHandle(hMenu, TYPE_MENU); 
+    return ValidateHandleNoErr(hMenu, TYPE_MENU); 
+}
+
+/***********************************************************************
+ *           get_win_sys_menu
+ *
+ * Get the system menu of a window
+ */
+static HMENU get_win_sys_menu( HWND hwnd )
+{
+    HMENU ret = 0;
+    WND *win = ValidateHwnd( hwnd );
+    if (win)
+    {
+        ret = win->SystemMenu;
+    }
+    return ret;
 }
 
 /***********************************************************************
@@ -154,22 +172,13 @@ ITEM *MENU_FindItem( HMENU *hmenu, UINT *nPos, UINT wFlags )
     {
        if (*nPos >= menu->cItems) return NULL;
        pItem = menu->rgItems ? DesktopPtrToUser(menu->rgItems) : NULL;
-       //pItem = &menu->rgItems[*nPos];
-       i = 0;
-        while(pItem) // Do this for now.
-        {
-           if (i < (INT)menu->cItems)
-           {
-              if ( *nPos == i ) return pItem;
-           }
-           pItem = pItem->Next ? DesktopPtrToUser(pItem->Next) : NULL;
-           i++;
-        }      
+       if (pItem) pItem = &pItem[*nPos];
+       return pItem;
     }
     else
     {
         PITEM item = menu->rgItems ? DesktopPtrToUser(menu->rgItems) : NULL;
-       for (i = 0; item ,i < menu->cItems; i++,  item = item->Next ? DesktopPtrToUser(item->Next) : NULL)//, item++)
+       for (i = 0; item, i < menu->cItems; i++, item++)
        {
            if (item->spSubMenu)
            {
@@ -206,41 +215,33 @@ ITEM *MENU_FindItem( HMENU *hmenu, UINT *nPos, UINT wFlags )
 UINT FASTCALL
 IntGetMenuDefaultItem(PMENU Menu, BOOL fByPos, UINT gmdiFlags, DWORD *gismc)
 {
-   UINT x = 0;
-   UINT res = -1;
-   UINT sres;
+   UINT i = 0;
    PITEM Item = Menu->rgItems ? DesktopPtrToUser(Menu->rgItems) : NULL;
 
-   while(Item)
-   {
-      if (Item->fState & MFS_DEFAULT)
-      {
-         if (!(gmdiFlags & GMDI_USEDISABLED) &&
-             (Item->fState & MFS_DISABLED) )
-            break;
+   /* empty menu */
+   if (!Item) return -1;
 
-         res = fByPos ? x : Item->wID;
+   while ( !( Item->fState & MFS_DEFAULT ) )
+   {
+      i++; Item++;
+      if  (i >= Menu->cItems ) return -1;
+   }
 
-         if ((*gismc < MAX_GOINTOSUBMENU) &&
-             (gmdiFlags & GMDI_GOINTOPOPUPS) &&
-              Item->spSubMenu)
-         {
-            if (DesktopPtrToUser(Item->spSubMenu) == Menu)
-               break;
+   /* default: don't return disabled items */
+   if ( (!(GMDI_USEDISABLED & gmdiFlags)) && (Item->fState & MFS_DISABLED )) return -1;
 
-            (*gismc)++;
-            sres = IntGetMenuDefaultItem( DesktopPtrToUser(Item->spSubMenu), fByPos, gmdiFlags, gismc);
-            (*gismc)--;
+   /* search rekursiv when needed */
+   if ( (Item->fType & MF_POPUP) &&  (gmdiFlags & GMDI_GOINTOPOPUPS) && Item->spSubMenu)
+   {
+      UINT ret;
+      (*gismc)++;
+      ret = IntGetMenuDefaultItem( DesktopPtrToUser(Item->spSubMenu), fByPos, gmdiFlags, gismc );
+      (*gismc)--;
+      if ( -1 != ret ) return ret;
 
-            if(sres > (UINT)-1)
-               res = sres;
-         }
-         break;
-      }
-      Item = Item->Next ? DesktopPtrToUser(Item->Next) : NULL;
-      x++;
+      /* when item not found in submenu, return the popup item */
    }
-   return res;
+   return ( fByPos ) ? i : Item->wID;
 }
 
 static BOOL GetMenuItemInfo_common ( HMENU hmenu,
@@ -256,7 +257,6 @@ static BOOL GetMenuItemInfo_common ( HMENU hmenu,
     if (!pItem)
     {
         SetLastError( ERROR_MENU_ITEM_NOT_FOUND);
-        //SetLastError(ERROR_INVALID_PARAMETER);
         return FALSE;
     }
 
@@ -339,7 +339,7 @@ static BOOL GetMenuItemInfo_common ( HMENU hmenu,
        lpmii->hbmpItem = pItem->hbmp;
 
     if (lpmii->fMask & MIIM_STATE)
-       lpmii->fState = pItem->fState & MII_STATE_MASK; //MENUITEMINFO_STATE_MASK;
+       lpmii->fState = pItem->fState & MENUITEMINFO_STATE_MASK;
 
     if (lpmii->fMask & MIIM_ID)
        lpmii->wID = pItem->wID;
@@ -377,7 +377,7 @@ static BOOL FASTCALL
 MenuGetRosMenuInfo(PROSMENUINFO MenuInfo, HMENU Menu)
 {
   PMENU pMenu;
-  if (!(pMenu = ValidateHandle(Menu, TYPE_MENU))) return FALSE;
+  if (!(pMenu = ValidateHandleNoErr(Menu, TYPE_MENU))) return FALSE;
 
   MenuInfo->hbrBack = pMenu->hbrBack;
   MenuInfo->dwContextHelpID = pMenu->dwContextHelpId;
@@ -518,6 +518,10 @@ MenuSetRosMenuItemInfo(HMENU Menu, UINT Index, PROSMENUITEMINFO ItemInfo)
   {
     ItemInfo->cch = strlenW(ItemInfo->dwTypeData);
   }
+  if (ItemInfo->hSubMenu)
+  {
+     if (!IsMenu(ItemInfo->hSubMenu)) ItemInfo->hSubMenu = NULL;
+  }
   Ret = NtUserThunkedMenuItemInfo(Menu, Index, TRUE, FALSE, (LPMENUITEMINFOW)ItemInfo, NULL);
   return Ret;
 }
@@ -537,139 +541,6 @@ MenuCleanupRosMenuItemInfo(PROSMENUITEMINFO ItemInfo)
   }
 }
 
-DWORD FASTCALL
-IntBuildMenuItemList(PMENU MenuObject, PVOID Buffer, ULONG nMax)
-{
-   DWORD res = 0;
-   ROSMENUITEMINFO mii;
-   PVOID Buf;
-   PITEM CurItem = MenuObject->rgItems ? DesktopPtrToUser(MenuObject->rgItems) : NULL;
-   PWCHAR StrOut;
-   WCHAR NulByte;
-
-   if (0 != nMax)
-   {
-      if (nMax < MenuObject->cItems * sizeof(ROSMENUITEMINFO))
-      {
-         return 0;
-      }
-      StrOut = (PWCHAR)((char *) Buffer + MenuObject->cItems * sizeof(ROSMENUITEMINFO));
-      nMax -= MenuObject->cItems * sizeof(ROSMENUITEMINFO);
-      Buf = Buffer;
-      mii.cbSize = sizeof(ROSMENUITEMINFO);
-      mii.fMask = 0;
-      NulByte = L'\0';
-
-      while (NULL != CurItem)
-      {
-         mii.cch = CurItem->lpstr.Length / sizeof(WCHAR);
-         mii.dwItemData = CurItem->dwItemData;
-         if (0 != CurItem->lpstr.Length)
-         {
-            mii.dwTypeData = StrOut;
-         }
-         else
-         {
-            mii.dwTypeData = NULL;
-         }
-         mii.fState = CurItem->fState;
-         mii.fType = CurItem->fType;
-         mii.wID = CurItem->wID;
-         mii.hbmpChecked = CurItem->hbmpChecked;
-         mii.hbmpItem = CurItem->hbmp;
-         mii.hbmpUnchecked = CurItem->hbmpUnchecked;
-         if (CurItem->spSubMenu)
-         {
-            PMENU pSubMenu = DesktopPtrToUser(CurItem->spSubMenu);
-            HMENU hSubMenu = UserHMGetHandle(pSubMenu);
-            mii.hSubMenu = hSubMenu;
-         }
-         else
-            mii.hSubMenu = NULL;
-         mii.Rect.left   = CurItem->xItem; 
-         mii.Rect.top    = CurItem->yItem; 
-         mii.Rect.right  = CurItem->cxItem; // Do this for now......
-         mii.Rect.bottom = CurItem->cyItem;
-         mii.dxTab = CurItem->dxTab;
-         mii.lpstr = CurItem->lpstr.Buffer; // Can be read from user side!
-         //mii.maxBmpSize.cx = CurItem->cxBmp;
-         //mii.maxBmpSize.cy = CurItem->cyBmp;
-
-         RtlCopyMemory(Buf, &mii, sizeof(ROSMENUITEMINFO));
-         Buf = (PVOID)((ULONG_PTR)Buf + sizeof(ROSMENUITEMINFO));
-
-         if (0 != CurItem->lpstr.Length && (nMax >= CurItem->lpstr.Length + sizeof(WCHAR)))
-         {
-            LPWSTR lpstr = CurItem->lpstr.Buffer ? DesktopPtrToUser(CurItem->lpstr.Buffer) : NULL;
-            if (lpstr)
-            {
-               /* Copy string */
-               RtlCopyMemory(StrOut, lpstr, CurItem->lpstr.Length);
-            
-               StrOut += CurItem->lpstr.Length / sizeof(WCHAR);
-               RtlCopyMemory(StrOut, &NulByte, sizeof(WCHAR));
-               StrOut++;
-               nMax -= CurItem->lpstr.Length + sizeof(WCHAR);
-            }
-         }
-         else if (0 != CurItem->lpstr.Length)
-         {
-            break;
-         }
-
-         CurItem = CurItem->Next ? DesktopPtrToUser(CurItem->Next) : NULL;
-         res++;
-      }
-   }
-   else
-   {
-      while (NULL != CurItem)
-      {
-         res += sizeof(ROSMENUITEMINFO) + CurItem->lpstr.Length + sizeof(WCHAR);
-         CurItem = CurItem->Next ? DesktopPtrToUser(CurItem->Next) : NULL;
-      }
-   }
-   return res;
-}
-
-/***********************************************************************
- *           MenuGetAllRosMenuItemInfo
- *
- * Get full information about all menu items
- */
-static INT FASTCALL
-MenuGetAllRosMenuItemInfo(HMENU Menu, PROSMENUITEMINFO *ItemInfo)
-{
-  DWORD BufSize;
-  PMENU pMenu;
-
-  if (!(pMenu = ValidateHandle(Menu, TYPE_MENU))) return -1;
-
-  BufSize = IntBuildMenuItemList(pMenu, (PVOID)1, 0);
-  if (BufSize == (DWORD) -1 || BufSize == 0)
-  {
-      return -1;
-  }
-  *ItemInfo = HeapAlloc(GetProcessHeap(), 0, BufSize);
-  if (NULL == *ItemInfo)
-  {
-      return -1;
-  }
-
-  return IntBuildMenuItemList(pMenu, (PVOID)*ItemInfo, BufSize);
-}
-
-/***********************************************************************
- *           MenuCleanupAllRosMenuItemInfo
- *
- * Cleanup after use of MenuGetAllRosMenuItemInfo
- */
-static VOID FASTCALL
-MenuCleanupAllRosMenuItemInfo(PROSMENUITEMINFO ItemInfo)
-{
-  HeapFree(GetProcessHeap(), 0, ItemInfo);
-}
-
 /***********************************************************************
  *           MenuInitSysMenuPopup
  *
@@ -718,22 +589,27 @@ void FASTCALL MenuInitSysMenuPopup(HMENU hmenu, DWORD style, DWORD clsStyle, LON
  *     PROSMENUINFO MenuInfo)
  *
  *****************************************************************************/
-static UINT MenuGetStartOfNextColumn(
-    PROSMENUINFO MenuInfo)
+
+static UINT  MENU_GetStartOfNextColumn(
+    HMENU  hMenu )
 {
-    PROSMENUITEMINFO MenuItems;
+    MENU *menu = MENU_GetMenu(hMenu);
+    PITEM pItem;
     UINT i;
 
-    i = MenuInfo->iItem;
-    if ( i == NO_SELECTED_ITEM )
-        return i;
+    if(!menu)
+       return NO_SELECTED_ITEM;
 
-    if (MenuGetAllRosMenuItemInfo(MenuInfo->Self, &MenuItems) <= 0)
-        return NO_SELECTED_ITEM;
+    i = menu->iItem + 1;
+    if( i == NO_SELECTED_ITEM )
+       return i;
 
-    for (i++ ; i < MenuInfo->cItems; i++)
-        if (0 != (MenuItems[i].fType & (MF_MENUBREAK | MF_MENUBARBREAK)))
-            return i;
+    pItem = menu->rgItems ? DesktopPtrToUser(menu->rgItems) : NULL;
+    if (!pItem) return NO_SELECTED_ITEM;
+    for( ; i < menu->cItems; ++i ) {
+       if (pItem[i].fType & (MF_MENUBREAK | MF_MENUBARBREAK))
+           return i;
+    }
 
     return NO_SELECTED_ITEM;
 }
@@ -744,38 +620,36 @@ static UINT MenuGetStartOfNextColumn(
  *     PROSMENUINFO MenuInfo)
  *
  *****************************************************************************/
-
-static UINT FASTCALL MenuGetStartOfPrevColumn(
-    PROSMENUINFO MenuInfo)
+static UINT  MENU_GetStartOfPrevColumn(
+    HMENU  hMenu )
 {
-    PROSMENUITEMINFO MenuItems;
-    UINT i;
+    MENU *menu = MENU_GetMenu(hMenu);
+    UINT  i;
+    PITEM pItem;
 
-    if (!MenuInfo->iItem || MenuInfo->iItem == NO_SELECTED_ITEM)
-        return NO_SELECTED_ITEM;
+    if( !menu )
+       return NO_SELECTED_ITEM;
 
-    if (MenuGetAllRosMenuItemInfo(MenuInfo->Self, &MenuItems) <= 0)
-        return NO_SELECTED_ITEM;
+    if( menu->iItem == 0 || menu->iItem == NO_SELECTED_ITEM )
+       return NO_SELECTED_ITEM;
+
+    pItem = menu->rgItems ? DesktopPtrToUser(menu->rgItems) : NULL;
+    if (!pItem) return NO_SELECTED_ITEM;
 
     /* Find the start of the column */
-    for (i = MenuInfo->iItem;
-         0 != i && 0 == (MenuItems[i].fType & (MF_MENUBREAK | MF_MENUBARBREAK));
-         --i)
-    {
-        ; /* empty */
-    }
 
-    if (i == 0)
-    {
-        MenuCleanupAllRosMenuItemInfo(MenuItems);
-        return NO_SELECTED_ITEM;
-    }
+    for(i = menu->iItem; i != 0 &&
+        !(pItem[i].fType & (MF_MENUBREAK | MF_MENUBARBREAK));
+       --i); /* empty */
 
-    for (--i; 0 != i; --i)
-        if (MenuItems[i].fType & (MF_MENUBREAK | MF_MENUBARBREAK))
-            break;
+    if(i == 0)
+       return NO_SELECTED_ITEM;
+
+    for(--i; i != 0; --i) {
+       if (pItem[i].fType & (MF_MENUBREAK | MF_MENUBARBREAK))
+           break;
+    }
 
-    MenuCleanupAllRosMenuItemInfo(MenuItems);
     TRACE("ret %d.\n", i );
 
     return i;
@@ -870,7 +744,7 @@ static UINT FASTCALL MenuFindSubMenu(HMENU *hmenu, HMENU hSubTarget )
         return NO_SELECTED_ITEM;
 
     item = menu->rgItems ? DesktopPtrToUser(menu->rgItems) : NULL;
-    for (i = 0; i < menu->cItems; i++, item = item->Next ? DesktopPtrToUser(item->Next) : NULL)//item++)
+    for (i = 0; i < menu->cItems; i++, item++)
     {
         if (!item->spSubMenu)
            continue;
@@ -987,58 +861,48 @@ MenuDrawPopupGlyph(HDC dc, LPRECT r, INT_PTR popupMagic, BOOL inactive, BOOL hil
  * Find the menu item selected by a key press.
  * Return item id, -1 if none, -2 if we should close the menu.
  */
-static UINT FASTCALL MenuFindItemByKey(HWND WndOwner, PROSMENUINFO MenuInfo,
+static UINT FASTCALL MENU_FindItemByKey(HWND WndOwner, HMENU hmenu,
                   WCHAR Key, BOOL ForceMenuChar)
 {
-  ROSMENUINFO SysMenuInfo;
-  PROSMENUITEMINFO Items, ItemInfo;
   LRESULT MenuChar;
-  UINT i;
   WORD Flags = 0;
 
-  TRACE("\tlooking for '%c' (0x%02x) in [%p]\n", (char) Key, Key, MenuInfo);
+  TRACE("\tlooking for '%c' (0x%02x) in [%p]\n", (char)Key, Key, hmenu );
 
-  if (NULL == MenuInfo || ! IsMenu(MenuInfo->Self))
-  {
-      if (MenuGetRosMenuInfo(&SysMenuInfo, GetSystemMenu(WndOwner, FALSE)))
-      {
-          MenuInfo = &SysMenuInfo;
-      }
-      else
-      {
-          MenuInfo = NULL;
-      }
-  }
+  if (!IsMenu( hmenu )) hmenu = GetSubMenu( get_win_sys_menu(WndOwner), 0);
+    if (hmenu)
+    {
+       MENU *menu = MENU_GetMenu( hmenu );
+       ITEM *item = menu->rgItems ? DesktopPtrToUser(menu->rgItems) : NULL;
 
-  if (NULL != MenuInfo)
-  {
-      if (MenuGetAllRosMenuItemInfo(MenuInfo->Self, &Items) <= 0)
-      {
-          return -1;
-      }
-      if ( !ForceMenuChar )
-      {
-          ItemInfo = Items;
-          for (i = 0; i < MenuInfo->cItems; i++, ItemInfo++)
-          {
-              if ((ItemInfo->lpstr) && NULL != ItemInfo->dwTypeData)
-              {
-                  WCHAR *p = (WCHAR *) ItemInfo->dwTypeData - 2;
-                  do
-                  {
-                      p = strchrW (p + 2, '&');
-                  }
-                  while (p != NULL && p [1] == '&');
-                  if (p && (toupperW(p[1]) == toupperW(Key))) return i;
-              }
-          }
-      }
+       if( !ForceMenuChar )
+       {
+            UINT i;
+            BOOL cjk = GetSystemMetrics( SM_DBCSENABLED );
+
+            for (i = 0; i < menu->cItems; i++, item++)
+            {
+               LPWSTR text = item->Xlpstr ? DesktopPtrToUser(item->Xlpstr) : NULL;
+               if( text)
+               {
+                   const WCHAR *p = text - 2;
+                   do
+                   {
+                       const WCHAR *q = p + 2;
+                       p = strchrW (q, '&');
+                       if (!p && cjk) p = strchrW (q, '\036'); /* Japanese Win16 */
+                   }
+                   while (p != NULL && p [1] == '&');
+                   if (p && (toupperW(p[1]) == toupperW(Key))) return i;
+               }
+            }
+       }
 
-      Flags |= MenuInfo->fFlags & MNF_POPUP ? MF_POPUP : 0;
-      Flags |= MenuInfo->fFlags & MNF_SYSDESKMN ? MF_SYSMENU : 0;
+      Flags |= menu->fFlags & MNF_POPUP ? MF_POPUP : 0;
+      Flags |= menu->fFlags & MNF_SYSDESKMN ? MF_SYSMENU : 0;
 
       MenuChar = SendMessageW(WndOwner, WM_MENUCHAR,
-                              MAKEWPARAM(Key, Flags), (LPARAM) MenuInfo->Self);
+                              MAKEWPARAM(Key, Flags), (LPARAM) hmenu);
       if (HIWORD(MenuChar) == MNC_EXECUTE) return LOWORD(MenuChar);
       if (HIWORD(MenuChar) == MNC_CLOSE) return (UINT)(-2);
     }
@@ -1530,7 +1394,7 @@ static void FASTCALL MenuMenuBarCalcSize( HDC hdc, LPRECT lprect,
 
     if ((lprect == NULL) || (MenuInfo == NULL)) return;
     if (MenuInfo->cItems == 0) return;
-    TRACE("left=%ld top=%ld right=%ld bottom=%ld\n", lprect->left, lprect->top, lprect->right, lprect->bottom);
+    TRACE("lprect %p %s\n", lprect, wine_dbgstr_rect( lprect));
     MenuInfo->cxMenu = lprect->right - lprect->left;
     MenuInfo->cyMenu = 0;
     maxY = lprect->top + 1;
@@ -1689,7 +1553,6 @@ MENU_DrawScrollArrows(PROSMENUINFO lppop, HDC hdc)
     DeleteDC(hdcMem);
 }
 
-
 /***********************************************************************
  *           MenuDrawMenuItem
  *
@@ -1702,7 +1565,7 @@ static void FASTCALL MenuDrawMenuItem(HWND hWnd, PROSMENUINFO MenuInfo, HWND Wnd
     PWCHAR Text;
     BOOL flat_menu = FALSE;
     int bkgnd;
-    PWND Wnd = ValidateHwnd(hWnd);
+    PWND Wnd = ValidateHwndNoErr(hWnd);
 
     if (!Wnd)
       return;
@@ -1744,6 +1607,7 @@ static void FASTCALL MenuDrawMenuItem(HWND hWnd, PROSMENUINFO MenuInfo, HWND Wnd
         SetBkColor( hdc, GetSysColor( bkgnd ) );
     }
 
+    TRACE("rect=%s\n", wine_dbgstr_rect( &lpitem->Rect));
     rect = lpitem->Rect;
     MENU_AdjustMenuItemRect(MenuInfo, &rect);
 
@@ -1949,7 +1813,7 @@ static void FASTCALL MenuDrawMenuItem(HWND hWnd, PROSMENUINFO MenuInfo, HWND Wnd
                        DT_LEFT | DT_VCENTER | DT_SINGLELINE;
 
         if((MenuInfo->dwStyle & MNS_CHECKORBMP))
-             rect.left += max(0, MenuInfo->cxTextAlign - GetSystemMetrics(SM_CXMENUCHECK));
+             rect.left += max(0, (int)(MenuInfo->cxTextAlign - GetSystemMetrics(SM_CXMENUCHECK)));
         else
              rect.left += MenuInfo->cxTextAlign;
 
@@ -2053,6 +1917,7 @@ static void FASTCALL MenuDrawPopupMenu(HWND hwnd, HDC hdc, HMENU hmenu )
                DrawEdge (hdc, &rect, EDGE_RAISED, BF_RECT);
 
             /* draw menu items */
+            //TRACE("hmenu %p Style %08x\n", hmenu, menu->dwStyle);
             if (MenuGetRosMenuInfo(&MenuInfo, hmenu) && MenuInfo.cItems)
             {
                 UINT u;
@@ -2115,6 +1980,44 @@ UINT MenuDrawMenuBar( HDC hDC, LPRECT lprect, HWND hwnd,
         return DrawMenuBarTemp(hwnd, hDC, lprect, hMenu, NULL);
 }
 
+/***********************************************************************
+ *           MENU_InitPopup
+ *   
+ * Popup menu initialization before WM_ENTERMENULOOP.
+ */
+static BOOL MENU_InitPopup( HWND hwndOwner, HMENU hmenu, UINT flags )
+{
+    MENU *menu;
+    DWORD ex_style = 0;
+    ROSMENUINFO MenuInfo;
+
+    TRACE("owner=%p hmenu=%p\n", hwndOwner, hmenu);
+
+    if (!(menu = MENU_GetMenu( hmenu ))) return FALSE;
+
+    /* store the owner for DrawItem */
+    if (!IsWindow( hwndOwner ))
+    {
+        SetLastError( ERROR_INVALID_WINDOW_HANDLE );
+        return FALSE;
+    }
+    MenuGetRosMenuInfo(&MenuInfo, menu->head.h);
+    //menu->hwndOwner = hwndOwner;
+    MenuInfo.spwndNotify = ValidateHwndNoErr( hwndOwner );
+
+    if (flags & TPM_LAYOUTRTL)
+        ex_style = WS_EX_LAYOUTRTL;
+
+    /* NOTE: In Windows, top menu popup is not owned. */
+    //menu->hWnd = CreateWindowExW( ex_style, WC_MENU, NULL,
+    MenuInfo.Wnd = CreateWindowExW( ex_style, WC_MENU, NULL,
+                                WS_POPUP, 0, 0, 0, 0,
+                                hwndOwner, 0, (HINSTANCE)GetWindowLongPtrW(hwndOwner, GWLP_HINSTANCE),
+                                (LPVOID)hmenu );
+    MenuSetRosMenuInfo(&MenuInfo);
+    if( !menu->hWnd ) return FALSE;
+    return TRUE;
+}
 
 /***********************************************************************
  *           MenuShowPopup
@@ -2130,7 +2033,6 @@ static BOOL FASTCALL MenuShowPopup(HWND hwndOwner, HMENU hmenu, UINT id, UINT fl
     POINT pt;
     HMONITOR monitor;
     MONITORINFO info;
-    DWORD ex_style = 0; 
 
     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);
@@ -2149,15 +2051,9 @@ static BOOL FASTCALL MenuShowPopup(HWND hwndOwner, HMENU hmenu, UINT id, UINT fl
         MenuInfo.iItem = NO_SELECTED_ITEM;
     }
 
-    /* store the owner for DrawItem */
-    if (!IsWindow(hwndOwner))
-    {
-       SetLastError( ERROR_INVALID_WINDOW_HANDLE );
-       return FALSE;
-    }
-    MenuInfo.spwndNotify = ValidateHwndNoErr(hwndOwner);
+    //menu->dwArrowsOn = 0;
+    MenuInfo.dwArrowsOn = 0;
     MenuSetRosMenuInfo(&MenuInfo);
-
     MenuPopupMenuCalcSize(&MenuInfo, hwndOwner);
 
     /* adjust popup menu pos so that it fits within the desktop */
@@ -2173,10 +2069,8 @@ static BOOL FASTCALL MenuShowPopup(HWND hwndOwner, HMENU hmenu, UINT id, UINT fl
     GetMonitorInfoW( monitor, &info );
 
     if (flags & TPM_LAYOUTRTL) 
-    {                               
-        ex_style = WS_EX_LAYOUTRTL; 
         flags ^= TPM_RIGHTALIGN;
-    } 
+
     if( flags & TPM_RIGHTALIGN ) x -= width;
     if( flags & TPM_CENTERALIGN ) x -= width / 2;
 
@@ -2203,24 +2097,18 @@ static BOOL FASTCALL MenuShowPopup(HWND hwndOwner, HMENU hmenu, UINT id, UINT fl
     }
     if( y < info.rcMonitor.top ) y = info.rcMonitor.top;
 
-    /* NOTE: In Windows, top menu popup is not owned. */
-    MenuInfo.Wnd = CreateWindowExW( ex_style, WC_MENU, NULL,
-                                  WS_POPUP, x, y, width, height,
-                                  hwndOwner, 0, (HINSTANCE) GetWindowLongPtrW(hwndOwner, GWLP_HINSTANCE),
-                                 (LPVOID) MenuInfo.Self);
-    if ( !MenuInfo.Wnd || ! MenuSetRosMenuInfo(&MenuInfo)) return FALSE;
     if (!top_popup) {
         top_popup = MenuInfo.Wnd;
         top_popup_hmenu = hmenu;
     }
-
-    IntNotifyWinEvent(EVENT_SYSTEM_MENUPOPUPSTART, MenuInfo.Wnd, OBJID_CLIENT, CHILDID_SELF, 0);
-
     /* Display the window */
 
-    SetWindowPos( MenuInfo.Wnd, HWND_TOPMOST, 0, 0, 0, 0,
-                  SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
+    SetWindowPos( MenuInfo.Wnd, HWND_TOPMOST, x, y, width, height,
+                  SWP_SHOWWINDOW | SWP_NOACTIVATE);
     UpdateWindow( MenuInfo.Wnd );
+
+    IntNotifyWinEvent(EVENT_SYSTEM_MENUPOPUPSTART, MenuInfo.Wnd, OBJID_CLIENT, CHILDID_SELF, 0);
+
     return TRUE;
 }
 
@@ -2426,7 +2314,7 @@ PopupMenuWndProcW(HWND Wnd, UINT Message, WPARAM wParam, LPARAM lParam)
   PWND pWnd;
   PPOPUPMENU pPopupMenu;
 
-  pWnd = ValidateHwnd(Wnd);
+  pWnd = ValidateHwndNoErr(Wnd);
   if (pWnd)
   {
      if (!pWnd->fnid)
@@ -2609,6 +2497,12 @@ PopupMenuWndProcW(HWND Wnd, UINT Message, WPARAM wParam, LPARAM lParam)
         }
       break;
 
+#ifdef __REACTOS__
+    case WM_NCDESTROY:
+      NtUserSetWindowFNID(Wnd, FNID_DESTROY);
+      break;
+#endif
+
     case WM_SHOWWINDOW:
       if (0 != wParam)
         {
@@ -2721,7 +2615,6 @@ static LPCSTR MENU_ParseResource( LPCSTR res, HMENU hMenu)
     return res;
 }
 
-
 /**********************************************************************
  *         MENUEX_ParseResource
  *
@@ -2784,88 +2677,6 @@ static LPCSTR MENUEX_ParseResource(LPCSTR res, HMENU hMenu)
     return res;
 }
 
-NTSTATUS WINAPI
-User32LoadSysMenuTemplateForKernel(PVOID Arguments, ULONG ArgumentLength)
-{
-  HMENU hmenu = LoadMenuW(User32Instance, L"SYSMENU");
-  LRESULT Result = (LRESULT)hmenu;
-  MENUINFO menuinfo = {0};
-  MENUITEMINFOW info = {0};
-
-  // removing space for checkboxes from menu
-  menuinfo.cbSize = sizeof(menuinfo);
-  menuinfo.fMask = MIM_STYLE;
-  GetMenuInfo(hmenu, &menuinfo);
-  menuinfo.dwStyle |= MNS_CHECKORBMP; // test_menu_bmp_and_string MNS_CHECKORBMP
-  SetMenuInfo(hmenu, &menuinfo);
-
-  // adding bitmaps to menu items
-  info.cbSize = sizeof(info);
-  info.fMask |= MIIM_BITMAP;
-  info.hbmpItem = HBMMENU_POPUP_MINIMIZE;
-  SetMenuItemInfoW(hmenu, SC_MINIMIZE, FALSE, &info);
-  info.hbmpItem = HBMMENU_POPUP_RESTORE;
-  SetMenuItemInfoW(hmenu, SC_RESTORE, FALSE, &info);
-  info.hbmpItem = HBMMENU_POPUP_MAXIMIZE;
-  SetMenuItemInfoW(hmenu, SC_MAXIMIZE, FALSE, &info);
-  info.hbmpItem = HBMMENU_POPUP_CLOSE;
-  SetMenuItemInfoW(hmenu, SC_CLOSE, FALSE, &info);
-
-  return(ZwCallbackReturn(&Result, sizeof(LRESULT), STATUS_SUCCESS));
-}
-
-
-BOOL
-MenuInit(VOID)
-{
-  NONCLIENTMETRICSW ncm;
-
-  /* get the menu font */
-  if(!hMenuFont || !hMenuFontBold)
-  {
-    ncm.cbSize = sizeof(ncm);
-    if(!SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0))
-    {
-      ERR("MenuInit(): SystemParametersInfoW(SPI_GETNONCLIENTMETRICS) failed!\n");
-      return FALSE;
-    }
-
-    hMenuFont = CreateFontIndirectW(&ncm.lfMenuFont);
-    if(hMenuFont == NULL)
-    {
-      ERR("MenuInit(): CreateFontIndirectW(hMenuFont) failed!\n");
-      return FALSE;
-    }
-
-    ncm.lfMenuFont.lfWeight = max(ncm.lfMenuFont.lfWeight + 300, 1000);
-    hMenuFontBold = CreateFontIndirectW(&ncm.lfMenuFont);
-    if(hMenuFontBold == NULL)
-    {
-      ERR("MenuInit(): CreateFontIndirectW(hMenuFontBold) failed!\n");
-      DeleteObject(hMenuFont);
-      hMenuFont = NULL;
-      return FALSE;
-    }
-  }
-
-  return TRUE;
-}
-
-VOID
-MenuCleanup(VOID)
-{
-  if (hMenuFont)
-  {
-    DeleteObject(hMenuFont);
-    hMenuFont = NULL;
-  }
-
-  if (hMenuFontBold)
-  {
-    DeleteObject(hMenuFontBold);
-    hMenuFontBold = NULL;
-  }
-}
 
 /***********************************************************************
  *           DrawMenuBarTemp   (USER32.@)
@@ -2943,36 +2754,8 @@ DrawMenuBarTemp(HWND Wnd, HDC DC, LPRECT Rect, HMENU Menu, HFONT Font)
 
   return MenuInfo.cyMenu;
 }
-#if 0
-static BOOL MENU_InitPopup( HWND hwndOwner, HMENU hmenu, UINT flags )
-{
-    POPUPMENU *menu;
-    DWORD ex_style = 0;
-
-    TRACE("owner=%p hmenu=%p\n", hwndOwner, hmenu);
 
-    if (!(menu = MENU_GetMenu( hmenu ))) return FALSE;
-
-    /* store the owner for DrawItem */
-    if (!IsWindow( hwndOwner ))
-    {
-        SetLastError( ERROR_INVALID_WINDOW_HANDLE );
-        return FALSE;
-    }
-    menu->hwndOwner = hwndOwner;
-
-    if (flags & TPM_LAYOUTRTL)
-        ex_style = WS_EX_LAYOUTRTL;
 
-    /* NOTE: In Windows, top menu popup is not owned. */
-    menu->hWnd = CreateWindowExW( ex_style, (LPCWSTR)POPUPMENU_CLASS_ATOM, NULL,
-                                WS_POPUP, 0, 0, 0, 0,
-                                hwndOwner, 0, (HINSTANCE)GetWindowLongPtrW(hwndOwner, GWLP_HINSTANCE),
-                                (LPVOID)hmenu );
-    if( !menu->hWnd ) return FALSE;
-    return TRUE;
-}
-#endif
 /***********************************************************************
  *           MenuShowSubPopup
  *
@@ -2982,7 +2765,6 @@ static BOOL MENU_InitPopup( HWND hwndOwner, HMENU hmenu, UINT flags )
 static HMENU FASTCALL
 MenuShowSubPopup(HWND WndOwner, PROSMENUINFO MenuInfo, BOOL SelectFirst, UINT Flags)
 {
-  extern void FASTCALL NcGetSysPopupPos(HWND Wnd, RECT *Rect);
   RECT Rect;
   ROSMENUITEMINFO ItemInfo;
   ROSMENUINFO SubMenuInfo;
@@ -3100,7 +2882,7 @@ MenuShowSubPopup(HWND WndOwner, PROSMENUINFO MenuInfo, BOOL SelectFirst, UINT Fl
   /* use default alignment for submenus */
   Flags &= ~(TPM_CENTERALIGN | TPM_RIGHTALIGN | TPM_VCENTERALIGN | TPM_BOTTOMALIGN);
 
-  //MENU_InitPopup( WndOwner, ItemInfo.hSubMenu, Flags );
+  MENU_InitPopup( WndOwner, ItemInfo.hSubMenu, Flags );
 
   MenuShowPopup(WndOwner, ItemInfo.hSubMenu, MenuInfo->iItem, Flags,
                 Rect.left, Rect.top, Rect.right, Rect.bottom );
@@ -3124,11 +2906,10 @@ MenuShowSubPopup(HWND WndOwner, PROSMENUINFO MenuInfo, BOOL SelectFirst, UINT Fl
  */
 void MENU_EndMenu( HWND hwnd )
 {
-    ROSMENUINFO MenuInfo;
-    BOOL Ret = FALSE;
-    if (top_popup_hmenu)
-       Ret = MenuGetRosMenuInfo(&MenuInfo, top_popup_hmenu);
-    if (Ret && hwnd == (MenuInfo.spwndNotify ? MenuInfo.spwndNotify->head.h : NULL)) EndMenu();
+    MENU *menu;
+    menu = top_popup_hmenu ? MENU_GetMenu( top_popup_hmenu ) : NULL;
+    if (menu && ( hwnd == menu->hWnd ||  hwnd == (menu->spwndNotify ? menu->spwndNotify->head.h : NULL)) )
+       EndMenu();
 }
 
 /***********************************************************************
@@ -3281,7 +3062,7 @@ MenuExecFocusedItem(MTRACKER *Mt, PROSMENUINFO MenuInfo, UINT Flags)
  * Return TRUE if we can go on with menu tracking.
  */
 static BOOL FASTCALL
-MenuButtonDown(MTRACKER* Mt, HMENU PtMenu, UINT Flags)
+MENU_ButtonDown(MTRACKER* Mt, HMENU PtMenu, UINT Flags)
 {
   int Index;
   ROSMENUINFO MenuInfo;
@@ -3344,7 +3125,7 @@ MenuButtonDown(MTRACKER* Mt, HMENU PtMenu, UINT Flags)
  *
  */
 static INT FASTCALL
-MenuButtonUp(MTRACKER *Mt, HMENU PtMenu, UINT Flags)
+MENU_ButtonUp(MTRACKER *Mt, HMENU PtMenu, UINT Flags)
 {
   INT Id;
   ROSMENUINFO MenuInfo;
@@ -3399,56 +3180,41 @@ MenuButtonUp(MTRACKER *Mt, HMENU PtMenu, UINT Flags)
  * Walks menu chain trying to find a menu pt maps to.
  */
 static HMENU FASTCALL
-MenuPtMenu(HMENU Menu, POINT Pt)
+MENU_PtMenu(HMENU hMenu, POINT pt)
 {
-  extern LRESULT DefWndNCHitTest(HWND hWnd, POINT Point);
-  ROSMENUINFO MenuInfo;
-  ROSMENUITEMINFO ItemInfo;
-  HMENU Ret = NULL;
-  INT Ht;
+  MENU *menu;
+  PITEM pItem;
+  HMENU ret = NULL;
 
-  if (! MenuGetRosMenuInfo(&MenuInfo, Menu))
-    {
-      return NULL;
-    }
+  menu = MENU_GetMenu( hMenu );
+  if (!menu) return NULL;
 
   /* try subpopup first (if any) */
-  if (NO_SELECTED_ITEM != MenuInfo.iItem)
-    {
-      MenuInitRosMenuItemInfo(&ItemInfo);
-      if (MenuGetRosMenuItemInfo(MenuInfo.Self, MenuInfo.iItem, &ItemInfo) &&
-          0 != (ItemInfo.hSubMenu) &&
-          0 != (ItemInfo.fState & MF_MOUSESELECT))
-        {
-          Ret = MenuPtMenu(ItemInfo.hSubMenu, Pt);
-          if (NULL != Ret)
-            {
-              MenuCleanupRosMenuItemInfo(&ItemInfo);
-              return Ret;
-            }
-        }
-      MenuCleanupRosMenuItemInfo(&ItemInfo);
-    }
+  if (menu->iItem != NO_SELECTED_ITEM)
+  {
+     pItem = menu->rgItems ? DesktopPtrToUser(menu->rgItems) : NULL;
+     if ( pItem ) pItem = &pItem[menu->iItem];
+     if ( pItem && pItem->spSubMenu && pItem->fState & MF_MOUSESELECT)
+     {
+        PMENU pSubMenu = DesktopPtrToUser(pItem->spSubMenu);
+        ret = MENU_PtMenu( UserHMGetHandle(pSubMenu), pt);
+     }
+  }
 
   /* check the current window (avoiding WM_HITTEST) */
-  Ht = DefWndNCHitTest(MenuInfo.Wnd, Pt);
-  if (0 != (MenuInfo.fFlags & MNF_POPUP))
-    {
-      if (HTNOWHERE != Ht && HTERROR != Ht)
-        {
-          Ret = Menu;
-        }
-    }
-  else if (HTSYSMENU == Ht)
-    {
-      Ret = NtUserGetSystemMenu(MenuInfo.Wnd, FALSE);
-    }
-  else if (HTMENU == Ht)
-    {
-      Ret = GetMenu(MenuInfo.Wnd);
-    }
-
-  return Ret;
+  if (!ret)
+  {
+     INT ht = DefWndNCHitTest(menu->hWnd, pt);
+     if ( menu->fFlags & MNF_POPUP )
+     {
+        if (ht != HTNOWHERE && ht != HTERROR) ret = hMenu;
+     }
+     else if (ht == HTSYSMENU)
+        ret = NtUserGetSystemMenu(menu->hWnd, FALSE);
+     else if (ht == HTMENU)
+        ret = GetMenu( menu->hWnd );
+  }
+  return ret;
 }
 
 /***********************************************************************
@@ -3513,32 +3279,25 @@ MenuMouseMove(MTRACKER *Mt, HMENU PtMenu, UINT Flags)
  *
  * Return the handle of the selected sub-popup menu (if any).
  */
-static HMENU FASTCALL
-MenuGetSubPopup(HMENU Menu)
+static
+HMENU MENU_GetSubPopup( HMENU hmenu )
 {
-  ROSMENUINFO MenuInfo;
-  ROSMENUITEMINFO ItemInfo;
+    MENU *menu;
+    ITEM *item;
 
-  if (! MenuGetRosMenuInfo(&MenuInfo, Menu)
-      || NO_SELECTED_ITEM == MenuInfo.iItem)
-    {
-      return NULL;
-    }
+    menu = MENU_GetMenu( hmenu );
 
-  MenuInitRosMenuItemInfo(&ItemInfo);
-  if (! MenuGetRosMenuItemInfo(MenuInfo.Self, MenuInfo.iItem, &ItemInfo))
-    {
-      MenuCleanupRosMenuItemInfo(&ItemInfo);
-      return NULL;
-    }
-  if (0 != (ItemInfo.hSubMenu) && 0 != (ItemInfo.fState & MF_MOUSESELECT))
+    if ((!menu) || (menu->iItem == NO_SELECTED_ITEM)) return 0;
+
+    //item = &menu->rgItems[menu->iItem];
+    item = menu->rgItems ? DesktopPtrToUser(menu->rgItems) : NULL;
+    if (item) item = &item[menu->iItem];
+    if (item && (item->spSubMenu) && (item->fState & MF_MOUSESELECT))
     {
-      MenuCleanupRosMenuItemInfo(&ItemInfo);
-      return ItemInfo.hSubMenu;
+       PMENU pSubMenu = DesktopPtrToUser(item->spSubMenu);
+       return UserHMGetHandle(pSubMenu);
     }
-
-  MenuCleanupRosMenuItemInfo(&ItemInfo);
-  return NULL;
+    return 0;
 }
 
 /***********************************************************************
@@ -3726,7 +3485,7 @@ MenuKeyEscape(MTRACKER *Mt, UINT Flags)
           while (MenuTmp != Mt->CurrentMenu)
             {
               MenuPrev = MenuTmp;
-              MenuTmp = MenuGetSubPopup(MenuPrev);
+              MenuTmp = MENU_GetSubPopup(MenuPrev);
             }
 
           if (MenuGetRosMenuInfo(&MenuInfo, MenuPrev))
@@ -3757,13 +3516,8 @@ MenuKeyLeft(MTRACKER* Mt, UINT Flags)
 
   MenuPrev = MenuTmp = Mt->TopMenu;
 
-  if (! MenuGetRosMenuInfo(&MenuInfo, Mt->CurrentMenu))
-    {
-      return;
-    }
-
   /* Try to move 1 column left (if possible) */
-  if ( (PrevCol = MenuGetStartOfPrevColumn(&MenuInfo)) != NO_SELECTED_ITEM)
+  if ( (PrevCol = MENU_GetStartOfPrevColumn(Mt->CurrentMenu)) != NO_SELECTED_ITEM)
   {
      if (MenuGetRosMenuInfo(&MenuInfo, Mt->CurrentMenu))
      {
@@ -3776,7 +3530,7 @@ MenuKeyLeft(MTRACKER* Mt, UINT Flags)
   while (MenuTmp != Mt->CurrentMenu)
     {
       MenuPrev = MenuTmp;
-      MenuTmp = MenuGetSubPopup(MenuPrev);
+      MenuTmp = MENU_GetSubPopup(MenuPrev);
     }
 
   if (! MenuGetRosMenuInfo(&PrevMenuInfo, MenuPrev))
@@ -3844,13 +3598,8 @@ static void FASTCALL MenuKeyRight(MTRACKER *Mt, UINT Flags)
       if (hmenutmp != Mt->CurrentMenu) return;
     }
 
-    if (! MenuGetRosMenuInfo(&CurrentMenuInfo, Mt->CurrentMenu))
-    {
-      return;
-    }
-
     /* Check to see if there's another column */
-    if ( (NextCol = MenuGetStartOfNextColumn(&CurrentMenuInfo)) != NO_SELECTED_ITEM)
+    if ( (NextCol = MENU_GetStartOfNextColumn(Mt->CurrentMenu)) != NO_SELECTED_ITEM)
     {
        TRACE("Going to %d.\n", NextCol);
        if (MenuGetRosMenuInfo(&MenuInfo, Mt->CurrentMenu))
@@ -3899,6 +3648,7 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y,
     MSG msg;
     ROSMENUINFO MenuInfo;
     ROSMENUITEMINFO ItemInfo;
+    PMENU menu;
     BOOL fRemove;
     INT executedMenuId = -1;
     MTRACKER mt;
@@ -3918,12 +3668,10 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y,
 
     if (!IsMenu(hmenu))
     {
-        WARN("Invalid menu handle %p\n", hmenu);
-        SetLastError( ERROR_INVALID_MENU_HANDLE );
+        WARN("Invalid menu handle %p\n", hmenu); // Error already set in IsMenu.
         return FALSE;
     }
 
-    fEndMenu = FALSE;
     if (! MenuGetRosMenuInfo(&MenuInfo, hmenu))
     {
         return FALSE;
@@ -3932,7 +3680,7 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y,
     if (wFlags & TPM_BUTTONDOWN)
     {
         /* Get the result in order to start the tracking or not */
-        fRemove = MenuButtonDown( &mt, hmenu, wFlags );
+        fRemove = MENU_ButtonDown( &mt, hmenu, wFlags );
         fEndMenu = !fRemove;
     }
 
@@ -3943,10 +3691,10 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y,
     NtUserxSetGUIThreadHandle(MSQ_STATE_MENUOWNER, capture_win); // 1
     SetCapture(capture_win);                                          // 2
 
-    while (! fEndMenu)
+    while (!fEndMenu)
     {
         BOOL ErrorExit = FALSE;
-        PMENU menu = ValidateHandle(mt.CurrentMenu, TYPE_MENU);
+        menu = MENU_GetMenu( mt.CurrentMenu );
         if (!menu) /* sometimes happens if I do a window manager close */
            break;
 
@@ -3964,7 +3712,7 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y,
             else
             {
                 /* ReactOS Check */
-                if (!ValidateHwnd(mt.OwnerWnd) || !ValidateHwnd(MenuInfo.Wnd))
+                if (!ValidateHwndNoErr(mt.OwnerWnd) || !ValidateHwndNoErr(MenuInfo.Wnd))
                 {
                    ErrorExit = TRUE; // Do not wait on dead windows, now test_capture_4 works.
                    break;
@@ -4012,14 +3760,13 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y,
             mt.Pt.y = (short)HIWORD(msg.lParam);
 
             /* Find a menu for this mouse event */
-            hmenu = MenuPtMenu(mt.TopMenu, mt.Pt);
+            hmenu = MENU_PtMenu(mt.TopMenu, mt.Pt);
 
             switch(msg.message)
             {
                 /* no WM_NC... messages in captured state */
 
                 case WM_RBUTTONDBLCLK:
-                    ERR("WM_RBUTTONDBLCLK\n");
                 case WM_RBUTTONDOWN:
                      if (!(wFlags & TPM_RIGHTBUTTON)) break;
                     /* fall through */
@@ -4027,7 +3774,7 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y,
                 case WM_LBUTTONDOWN:
                     /* If the message belongs to the menu, removes it from the queue */
                     /* Else, end menu tracking */
-                    fRemove = MenuButtonDown(&mt, hmenu, wFlags);
+                    fRemove = MENU_ButtonDown(&mt, hmenu, wFlags);
                     fEndMenu = !fRemove;
                     break;
 
@@ -4038,7 +3785,7 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y,
                     /* Check if a menu was selected by the mouse */
                     if (hmenu)
                     {
-                        executedMenuId = MenuButtonUp( &mt, hmenu, wFlags);
+                        executedMenuId = MENU_ButtonUp( &mt, hmenu, wFlags);
                         TRACE("executedMenuId %d\n", executedMenuId);
 
                     /* End the loop if executedMenuId is an item ID */
@@ -4080,10 +3827,8 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y,
                     case VK_END:
                         if (MenuGetRosMenuInfo(&MenuInfo, mt.CurrentMenu))
                         {
-                            MenuSelectItem(mt.OwnerWnd, &MenuInfo,
-                                    NO_SELECTED_ITEM, FALSE, 0 );
-                            MenuMoveSelection(mt.OwnerWnd, &MenuInfo,
-                                              VK_HOME == msg.wParam ? ITEM_NEXT : ITEM_PREV);
+                            MenuSelectItem(mt.OwnerWnd, &MenuInfo, NO_SELECTED_ITEM, FALSE, 0 );
+                            MenuMoveSelection(mt.OwnerWnd, &MenuInfo, VK_HOME == msg.wParam ? ITEM_NEXT : ITEM_PREV);
                         }
                         break;
 
@@ -4097,8 +3842,7 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y,
                                     mt.CurrentMenu = MenuShowSubPopup(mt.OwnerWnd, &MenuInfo, TRUE, wFlags);
                             }
                             else      /* otherwise try to move selection */
-                                MenuMoveSelection(mt.OwnerWnd, &MenuInfo,
-                                       (msg.wParam == VK_UP)? ITEM_PREV : ITEM_NEXT );
+                                MenuMoveSelection(mt.OwnerWnd, &MenuInfo, (msg.wParam == VK_UP)? ITEM_PREV : ITEM_NEXT );
                         }
                         break;
 
@@ -4168,14 +3912,12 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y,
                     /* We will find a better way real soon... */
                     if (msg.wParam < 32) break;
 
-                    pos = MenuFindItemByKey(mt.OwnerWnd, &MenuInfo,
-                                          LOWORD(msg.wParam), FALSE);
+                    pos = MENU_FindItemByKey(mt.OwnerWnd, mt.CurrentMenu, LOWORD(msg.wParam), FALSE);
                     if (pos == (UINT)-2) fEndMenu = TRUE;
                     else if (pos == (UINT)-1) MessageBeep(0);
                     else
                     {
-                        MenuSelectItem(mt.OwnerWnd, &MenuInfo, pos,
-                            TRUE, 0);
+                        MenuSelectItem(mt.OwnerWnd, &MenuInfo, pos, TRUE, 0);
                         executedMenuId = MenuExecFocusedItem(&mt, &MenuInfo, wFlags);
                         fEndMenu = (executedMenuId != -2);
                     }
@@ -4259,11 +4001,19 @@ static BOOL FASTCALL MenuInitTracking(HWND hWnd, HMENU hMenu, BOOL bPopup, UINT
      * 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 (MenuGetRosMenuInfo(&MenuInfo, hMenu))
+    if (!bPopup && (MenuGetRosMenuInfo(&MenuInfo, hMenu)))
     {
         MenuInfo.Wnd = hWnd;
         MenuSetRosMenuInfo(&MenuInfo);
     }
+    //if (!bPopup) menu->hWnd = hWnd;
+    if (!top_popup)
+    {
+       top_popup = MenuInfo.Wnd;//menu->hWnd;
+       top_popup_hmenu = hMenu;
+    }
+
+    fEndMenu = FALSE;
 
     /* Send WM_ENTERMENULOOP and WM_INITMENU message only if TPM_NONOTIFY flag is not specified */
     if (!(wFlags & TPM_NONOTIFY))
@@ -4294,6 +4044,7 @@ static BOOL FASTCALL MenuInitTracking(HWND hWnd, HMENU hMenu, BOOL bPopup, UINT
                        CHILDID_SELF, 0);
     return TRUE;
 }
+
 /***********************************************************************
  *           MenuExitTracking
  */
@@ -4337,7 +4088,6 @@ VOID MenuTrackMouseMenuBar( HWND hWnd, ULONG ht, POINT pt)
     }
 }
 
-
 /***********************************************************************
  *           MenuTrackKbdMenuBar
  *
@@ -4373,6 +4123,9 @@ VOID MenuTrackKbdMenuBar(HWND hwnd, UINT wParam, WCHAR wChar)
 
     MenuInitTracking( hwnd, hTrackMenu, FALSE, wFlags );
 
+    /* fetch the window menu again, it may have changed */
+    hTrackMenu = (wParam & HTSYSMENU) ? get_win_sys_menu( hwnd ) : GetMenu( hwnd );
+
     if (! MenuGetRosMenuInfo(&MenuInfo, hTrackMenu))
     {
       goto track_menu;
@@ -4380,7 +4133,7 @@ VOID MenuTrackKbdMenuBar(HWND hwnd, UINT wParam, WCHAR wChar)
 
     if( wChar && wChar != ' ' )
     {
-        uItem = MenuFindItemByKey( hwnd, &MenuInfo, wChar, (wParam & HTSYSMENU) );
+        uItem = MENU_FindItemByKey( hwnd, hTrackMenu, wChar, (wParam & HTSYSMENU) );
         if ( uItem >= (UINT)(-2) )
         {
             if( uItem == (UINT)(-1) ) MessageBeep(0);
@@ -4408,42 +4161,59 @@ track_menu:
 /**********************************************************************
  *           TrackPopupMenuEx   (USER32.@)
  */
-BOOL WINAPI TrackPopupMenuEx( HMENU Menu, UINT Flags, int x, int y,
-                              HWND Wnd, LPTPMPARAMS Tpm)
+BOOL WINAPI TrackPopupMenuEx( HMENU hMenu, UINT wFlags, int x, int y,
+                              HWND hWnd, LPTPMPARAMS lpTpm)
 {
     BOOL ret = FALSE;
-    ROSMENUINFO MenuInfo;
+    MENU *menu;
 
-    if (!IsMenu(Menu))    
+    TRACE("hmenu %p flags %04x (%d,%d) hwnd %p lpTpm %p rect %s\n",
+            hMenu, wFlags, x, y, hWnd, lpTpm,
+            lpTpm ? wine_dbgstr_rect( &lpTpm->rcExclude) : "-" );
+
+    /* Parameter check */
+    /* FIXME: this check is performed several times, here and in the called
+       functions. That could be optimized */
+    if (!(menu = MENU_GetMenu( hMenu )))
     {
       SetLastError( ERROR_INVALID_MENU_HANDLE );
       return FALSE;
     }
 
-    /* ReactOS Check */
-    if (!ValidateHwnd(Wnd))
-    {
-       /* invalid window see wine menu.c test_menu_trackpopupmenu line 3146 */
-       return FALSE;
-    }
-
-    MenuGetRosMenuInfo(&MenuInfo, Menu);
-    if (IsWindow(MenuInfo.Wnd))
+    if (IsWindow(menu->hWnd))
     {
         SetLastError( ERROR_POPUP_ALREADY_ACTIVE );
         return FALSE;
     }
 
-    MenuInitTracking(Wnd, Menu, TRUE, Flags);
+    if (MENU_InitPopup( hWnd, hMenu, wFlags ))
+    {
+       MenuInitTracking(hWnd, hMenu, TRUE, wFlags);
+
+       /* Send WM_INITMENUPOPUP message only if TPM_NONOTIFY flag is not specified */
+       if (!(wFlags & TPM_NONOTIFY))
+           SendMessageW(hWnd, WM_INITMENUPOPUP, (WPARAM) hMenu, 0);
 
-    /* Send WM_INITMENUPOPUP message only if TPM_NONOTIFY flag is not specified */
-    if (!(Flags & TPM_NONOTIFY))
-        SendMessageW(Wnd, WM_INITMENUPOPUP, (WPARAM) Menu, 0);
+       if (MenuShowPopup(hWnd, hMenu, 0, wFlags, x, y, 0, 0 ))
+          ret = MenuTrackMenu(hMenu, wFlags | TPM_POPUPMENU, 0, 0, hWnd,
+                              lpTpm ? &lpTpm->rcExclude : NULL);
+       MenuExitTracking(hWnd, TRUE);
 
-    if (MenuShowPopup(Wnd, Menu, 0, Flags, x, y, 0, 0 ))
-       ret = MenuTrackMenu(Menu, Flags | TPM_POPUPMENU, 0, 0, Wnd,
-                           Tpm ? &Tpm->rcExclude : NULL);
-    MenuExitTracking(Wnd, TRUE);
+       if (menu->hWnd)
+       {
+          ROSMENUINFO MenuInfo;
+          if (IsWindow( menu->hWnd )) // wine hack around this with their destroy function.
+             DestroyWindow( menu->hWnd ); // Fix wrong error return.
+          //menu->hWnd = 0;
+          MenuGetRosMenuInfo(&MenuInfo, menu->head.h);
+          MenuInfo.Wnd = 0;
+          MenuSetRosMenuInfo(&MenuInfo);
+          
+          if (!(wFlags & TPM_NONOTIFY))
+             SendMessageW( hWnd, WM_UNINITMENUPOPUP, (WPARAM)hMenu,
+                                            MAKELPARAM(0, IS_SYSTEM_MENU(menu)) );  
+       }
+    }
     return ret;
 }
 
@@ -4456,164 +4226,63 @@ BOOL WINAPI TrackPopupMenu( HMENU Menu, UINT Flags, int x, int y,
     return TrackPopupMenuEx( Menu, Flags, x, y, Wnd, NULL);
 }
 
-/*
- *  From MSDN:
- *  The MFT_BITMAP, MFT_SEPARATOR, and MFT_STRING values cannot be combined
- *  with one another. Also MFT_OWNERDRAW. Set fMask to MIIM_TYPE to use fType.
- *
- *  Windows 2K/XP: fType is used only if fMask has a value of MIIM_FTYPE.
- *
- *  MIIM_TYPE: Retrieves or sets the fType and dwTypeData members. Windows
- *  2K/XP: MIIM_TYPE is replaced by  MIIM_BITMAP, MIIM_FTYPE, and MIIM_STRING.
- *  MFT_STRING is replaced by MIIM_STRING.
- *  (So, I guess we should use MIIM_STRING only for strings?)
- *
- *  MIIM_FTYPE: Windows 2K/Windows XP: Retrieves or sets the fType member.
- *
- *  Based on wine, SetMenuItemInfo_common:
- *  1) set MIIM_STRING | MIIM_FTYPE | MIIM_BITMAP any one with MIIM_TYPE,
- *     it will result in a error.
- *  2) set menu mask to MIIM_FTYPE and MFT_BITMAP ftype it will result in a error.
- *     These conditions are addressed in Win32k IntSetMenuItemInfo.
+/**********************************************************************
+ *         MENU_mnu2mnuii
  *
+ * Uses flags, id and text ptr, passed by InsertMenu() and
+ * ModifyMenu() to setup a MenuItemInfo structure.
  */
-static
-BOOL
-FASTCALL
-MenuSetItemData(
-  LPMENUITEMINFOW mii,
-  UINT Flags,
-  UINT_PTR IDNewItem,
-  LPCWSTR NewItem,
-  BOOL Unicode)
+static void MENU_mnu2mnuii( UINT flags, UINT_PTR id, LPCWSTR str, LPMENUITEMINFOW pmii, BOOL Unicode)
 {
-/*
- * Let us assume MIIM_FTYPE is set and building a new menu item structure.
- */
-  if(Flags & MF_BITMAP)
-  {
-     mii->fMask |= MIIM_BITMAP;   /* Use the new way of seting hbmpItem.*/
-     mii->hbmpItem = (HBITMAP) NewItem;
-
-     if (Flags & MF_HELP)
-     {
-         /* increase ident */
-         mii->fType |= MF_HELP;
-     }
-  }
-  else if(Flags & MF_OWNERDRAW)
-  {
-    mii->fType |= MFT_OWNERDRAW;
-    mii->fMask |= MIIM_DATA;
-    mii->dwItemData = (DWORD_PTR) NewItem;
-  }
-  else if (Flags & MF_SEPARATOR)
-  {
-    mii->fType |= MFT_SEPARATOR;
-    if (!(Flags & (MF_GRAYED|MF_DISABLED)))
-      Flags |= MF_GRAYED|MF_DISABLED;
-  }
-  else /* Default action MF_STRING. */
-  {
-    /* Item beginning with a backspace is a help item */
-    if (NewItem != NULL)
-    {
-       if (Unicode)
-       {
-          if (*NewItem == '\b')
-          {
-             mii->fType |= MF_HELP;
-             NewItem++;
-          }
-       }
-       else
-       {
-          LPCSTR NewItemA = (LPCSTR) NewItem;
-          if (*NewItemA == '\b')
-          {
-             mii->fType |= MF_HELP;
-             NewItemA++;
-             NewItem = (LPCWSTR) NewItemA;
-          }
-       }
-
-       if (Flags & MF_HELP)
-         mii->fType |= MF_HELP;
-       mii->fMask |= MIIM_STRING;
-       mii->fType |= MFT_STRING; /* Zero */
-       mii->dwTypeData = (LPWSTR)NewItem;
-       if (Unicode)
-         mii->cch = (NULL == NewItem ? 0 : strlenW(NewItem));
-       else
-         mii->cch = (NULL == NewItem ? 0 : strlen((LPCSTR)NewItem));
-    }
-    else
-    {
-      mii->fType |= MFT_SEPARATOR;
-      if (!(Flags & (MF_GRAYED|MF_DISABLED)))
-        Flags |= MF_GRAYED|MF_DISABLED;
-    }
-  }
-
-  if(Flags & MF_RIGHTJUSTIFY) /* Same as MF_HELP */
-  {
-    mii->fType |= MFT_RIGHTJUSTIFY;
-  }
-
-  if(Flags & MF_MENUBREAK)
-  {
-    mii->fType |= MFT_MENUBREAK;
-  }
-  else if(Flags & MF_MENUBARBREAK)
-  {
-    mii->fType |= MFT_MENUBARBREAK;
-  }
-
-  if(Flags & MF_GRAYED || Flags & MF_DISABLED)
-  {
-    if (Flags & MF_GRAYED)
-      mii->fState |= MF_GRAYED;
-
-    if (Flags & MF_DISABLED)
-      mii->fState |= MF_DISABLED;
-
-    mii->fMask |= MIIM_STATE;
-  }
-  else if (Flags & MF_HILITE)
-  {
-    mii->fState |= MF_HILITE;
-    mii->fMask |= MIIM_STATE;
-  }
-  else /* default state */
-  {
-    mii->fState |= MFS_ENABLED;
-    mii->fMask |= MIIM_STATE;
-  }
-
-  if(Flags & MF_POPUP && IsMenu((HMENU)IDNewItem))
-  {
-    mii->fMask |= MIIM_SUBMENU;
-    mii->hSubMenu = (HMENU)IDNewItem;
-  }
-  mii->fMask |= MIIM_ID;
-  mii->wID = (UINT)IDNewItem;
-  return TRUE;
-}
-
-NTSTATUS WINAPI
-User32CallLoadMenuFromKernel(PVOID Arguments, ULONG ArgumentLength)
-{
-  PLOADMENU_CALLBACK_ARGUMENTS Common;
-  LRESULT Result;  
-
-  Common = (PLOADMENU_CALLBACK_ARGUMENTS) Arguments;
-  
-  Result = (LRESULT)LoadMenuW( Common->hModule,
-                               IS_INTRESOURCE(Common->MenuName[0]) ?
-                                  MAKEINTRESOURCE(Common->MenuName[0]) :
-                                        (LPCWSTR)&Common->MenuName);
-
-  return ZwCallbackReturn(&Result, sizeof(LRESULT), STATUS_SUCCESS);
+    RtlZeroMemory( pmii, sizeof( MENUITEMINFOW));
+    pmii->cbSize = sizeof( MENUITEMINFOW);
+    pmii->fMask = MIIM_STATE | MIIM_ID | MIIM_FTYPE;
+    /* setting bitmap clears text and vice versa */
+    if( IS_STRING_ITEM(flags)) {
+        pmii->fMask |= MIIM_STRING | MIIM_BITMAP;
+        if( !str)
+            flags |= MF_SEPARATOR;
+        /* Item beginning with a backspace is a help item */
+        /* FIXME: wrong place, this is only true in win16 */
+        else
+        {
+            if (Unicode)
+           {
+              if (*str == '\b')
+              {
+                flags |= MF_HELP;
+                str++;
+              }
+           }
+           else
+           {
+              LPCSTR NewItemA = (LPCSTR) str;
+              if (*NewItemA == '\b')
+              {
+                 flags |= MF_HELP;
+                 NewItemA++;
+                 str = (LPCWSTR) NewItemA;
+              }
+              TRACE("A cch %d\n",strlen(NewItemA));
+           }
+        }
+        pmii->dwTypeData = (LPWSTR)str;
+    } else if( flags & MFT_BITMAP){
+        pmii->fMask |= MIIM_BITMAP | MIIM_STRING;
+        pmii->hbmpItem = (HBITMAP)str;
+    }
+    if( flags & MF_OWNERDRAW){
+        pmii->fMask |= MIIM_DATA;
+        pmii->dwItemData = (ULONG_PTR) str;
+    }
+    if( flags & MF_POPUP && MENU_GetMenu((HMENU)id)) {
+        pmii->fMask |= MIIM_SUBMENU;
+        pmii->hSubMenu = (HMENU)id;
+    }
+    if( flags & MF_SEPARATOR) flags |= MF_GRAYED | MF_DISABLED;
+    pmii->fState = flags & MENUITEMINFO_STATE_MASK & ~MFS_DEFAULT;
+    pmii->fType = flags & MENUITEMINFO_TYPE_MASK;
+    pmii->wID = (UINT)id;
 }
 
 /**********************************************************************
@@ -4670,6 +4339,104 @@ static BOOL MENU_NormalizeMenuItemInfoStruct( const MENUITEMINFOW *pmii_in,
     return TRUE;
 }
 
+BOOL
+MenuInit(VOID)
+{
+  NONCLIENTMETRICSW ncm;
+
+  /* get the menu font */
+  if(!hMenuFont || !hMenuFontBold)
+  {
+    ncm.cbSize = sizeof(ncm);
+    if(!SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0))
+    {
+      ERR("MenuInit(): SystemParametersInfoW(SPI_GETNONCLIENTMETRICS) failed!\n");
+      return FALSE;
+    }
+
+    hMenuFont = CreateFontIndirectW(&ncm.lfMenuFont);
+    if(hMenuFont == NULL)
+    {
+      ERR("MenuInit(): CreateFontIndirectW(hMenuFont) failed!\n");
+      return FALSE;
+    }
+
+    ncm.lfMenuFont.lfWeight = max(ncm.lfMenuFont.lfWeight + 300, 1000);
+    hMenuFontBold = CreateFontIndirectW(&ncm.lfMenuFont);
+    if(hMenuFontBold == NULL)
+    {
+      ERR("MenuInit(): CreateFontIndirectW(hMenuFontBold) failed!\n");
+      DeleteObject(hMenuFont);
+      hMenuFont = NULL;
+      return FALSE;
+    }
+  }
+
+  return TRUE;
+}
+
+VOID
+MenuCleanup(VOID)
+{
+  if (hMenuFont)
+  {
+    DeleteObject(hMenuFont);
+    hMenuFont = NULL;
+  }
+
+  if (hMenuFontBold)
+  {
+    DeleteObject(hMenuFontBold);
+    hMenuFontBold = NULL;
+  }
+}
+
+NTSTATUS WINAPI
+User32LoadSysMenuTemplateForKernel(PVOID Arguments, ULONG ArgumentLength)
+{
+  HMENU hmenu = LoadMenuW(User32Instance, L"SYSMENU");
+  LRESULT Result = (LRESULT)hmenu;
+  MENUINFO menuinfo = {0};
+  MENUITEMINFOW info = {0};
+
+  // removing space for checkboxes from menu
+  menuinfo.cbSize = sizeof(menuinfo);
+  menuinfo.fMask = MIM_STYLE;
+  GetMenuInfo(hmenu, &menuinfo);
+  menuinfo.dwStyle |= MNS_CHECKORBMP; // test_menu_bmp_and_string MNS_CHECKORBMP
+  SetMenuInfo(hmenu, &menuinfo);
+
+  // adding bitmaps to menu items
+  info.cbSize = sizeof(info);
+  info.fMask |= MIIM_BITMAP;
+  info.hbmpItem = HBMMENU_POPUP_MINIMIZE;
+  SetMenuItemInfoW(hmenu, SC_MINIMIZE, FALSE, &info);
+  info.hbmpItem = HBMMENU_POPUP_RESTORE;
+  SetMenuItemInfoW(hmenu, SC_RESTORE, FALSE, &info);
+  info.hbmpItem = HBMMENU_POPUP_MAXIMIZE;
+  SetMenuItemInfoW(hmenu, SC_MAXIMIZE, FALSE, &info);
+  info.hbmpItem = HBMMENU_POPUP_CLOSE;
+  SetMenuItemInfoW(hmenu, SC_CLOSE, FALSE, &info);
+
+  return(ZwCallbackReturn(&Result, sizeof(LRESULT), STATUS_SUCCESS));
+}
+
+NTSTATUS WINAPI
+User32CallLoadMenuFromKernel(PVOID Arguments, ULONG ArgumentLength)
+{
+  PLOADMENU_CALLBACK_ARGUMENTS Common;
+  LRESULT Result;
+
+  Common = (PLOADMENU_CALLBACK_ARGUMENTS) Arguments;
+
+  Result = (LRESULT)LoadMenuW( Common->hModule,
+                               IS_INTRESOURCE(Common->MenuName[0]) ?
+                                  MAKEINTRESOURCE(Common->MenuName[0]) :
+                                        (LPCWSTR)&Common->MenuName);
+
+  return ZwCallbackReturn(&Result, sizeof(LRESULT), STATUS_SUCCESS);
+}
+
 
 /* FUNCTIONS *****************************************************************/
 
@@ -4682,7 +4449,33 @@ AppendMenuA(HMENU hMenu,
            UINT_PTR uIDNewItem,
            LPCSTR lpNewItem)
 {
-  return(InsertMenuA(hMenu, -1, uFlags | MF_BYPOSITION, uIDNewItem, lpNewItem));
+  MENUITEMINFOW mii;
+  UNICODE_STRING UnicodeString;
+  BOOL res;
+
+  RtlInitUnicodeString(&UnicodeString, 0);
+
+  MENU_mnu2mnuii( uFlags, uIDNewItem, (LPCWSTR)lpNewItem, &mii, FALSE);
+
+  /* copy the text string, it wll be one or the other */
+  if (lpNewItem && mii.fMask & MIIM_STRING && !mii.hbmpItem && mii.dwTypeData)
+  {
+      if (!RtlCreateUnicodeStringFromAsciiz(&UnicodeString, (LPSTR)mii.dwTypeData))
+      {
+        SetLastError (ERROR_NOT_ENOUGH_MEMORY);
+        return FALSE;
+      }
+      mii.dwTypeData = UnicodeString.Buffer;
+      mii.cch = UnicodeString.Length / sizeof(WCHAR);
+  }
+  else
+  {
+      TRACE("AMA Handle bitmaps\n");
+  }
+  ////// Answer a question, why a -1? To hunt for the end of the item list. Get it, to Append?
+  res = NtUserThunkedMenuItemInfo(hMenu, -1, TRUE, TRUE, &mii, &UnicodeString);
+  if ( UnicodeString.Buffer ) RtlFreeUnicodeString ( &UnicodeString );
+  return res;
 }
 
 /*
@@ -4694,7 +4487,23 @@ AppendMenuW(HMENU hMenu,
            UINT_PTR uIDNewItem,
            LPCWSTR lpNewItem)
 {
-  return(InsertMenuW(hMenu, -1, uFlags | MF_BYPOSITION, uIDNewItem, lpNewItem));
+  MENUITEMINFOW mii;
+  UNICODE_STRING MenuText;
+  BOOL res;
+
+  RtlInitUnicodeString(&MenuText, 0);    
+
+  MENU_mnu2mnuii( uFlags, uIDNewItem, lpNewItem, &mii, TRUE);
+
+  /* copy the text string, it wll be one or the other */
+  if (lpNewItem && mii.fMask & MIIM_STRING && !mii.hbmpItem && mii.dwTypeData)
+  {
+    RtlInitUnicodeString(&MenuText, (PWSTR)mii.dwTypeData);
+    mii.dwTypeData = MenuText.Buffer;
+    mii.cch = MenuText.Length / sizeof(WCHAR);
+  }
+  res = NtUserThunkedMenuItemInfo(hMenu, -1, TRUE, TRUE, &mii, &MenuText);
+  return res;
 }
 
 /*
@@ -4720,7 +4529,6 @@ CheckMenuItem(HMENU hmenu,
   return NtUserCheckMenuItem(hmenu, uIDCheckItem, uCheck);
 }
 
-
 /*
  * @implemented
  */
@@ -4855,7 +4663,7 @@ EndMenu(VOID)
       /* don't end up with an orphaned menu */
       PostMessageW( top_popup, WM_CANCELMODE, 0, 0);
   }
-  return TRUE;
+  return fEndMenu;
 }
 
 BOOL WINAPI HiliteMenuItem( HWND hWnd, HMENU hMenu, UINT wItemID,
@@ -4891,7 +4699,6 @@ GetMenu(HWND hWnd)
        return UlongToHandle(Wnd->IDMenu);
 }
 
-
 /*
  * @implemented
  */
@@ -5005,28 +4812,10 @@ UINT WINAPI
 GetMenuItemID(HMENU hMenu,
              int nPos)
 {
-  PMENU pMenu;
-  PITEM pItem;
-  INT i = 0;
-
-  if (!(pMenu = ValidateHandle(hMenu, TYPE_MENU)))
-     return -1;
-
-  pItem = pMenu->rgItems ? DesktopPtrToUser(pMenu->rgItems) : NULL;
-  if ( nPos >= 0 )
-  {
-     //pItem = &menu->rgItems[nPos]; or pItem[nPos]; after dptu.
-     while(pItem) // Do this for now.
-     {
-        if (i < (INT)pMenu->cItems)
-        {
-           if ( nPos == i && !pItem->spSubMenu) return pItem->wID;
-        }
-        pItem = pItem->Next ? DesktopPtrToUser(pItem->Next) : NULL;
-        i++;
-     }
-  }
-  return -1;
+  ITEM * lpmi;
+  if (!(lpmi = MENU_FindItem(&hMenu,(UINT*)&nPos,MF_BYPOSITION))) return -1;
+  if (lpmi->spSubMenu) return -1;
+  return lpmi->wID;
 }
 
 /*
@@ -5096,18 +4885,21 @@ GetMenuState(
   UINT uFlags)
 {
   PITEM pItem;
+  UINT Type = 0;
   TRACE("(menu=%p, id=%04x, flags=%04x);\n", hMenu, uId, uFlags);
   if (!(pItem = MENU_FindItem( &hMenu, &uId, uFlags ))) return -1;
 
+  if (!pItem->Xlpstr && pItem->hbmp) Type = MFT_BITMAP;
+
   if (pItem->spSubMenu)
   {
      PMENU pSubMenu = DesktopPtrToUser(pItem->spSubMenu);
      HMENU hsubmenu = UserHMGetHandle(pSubMenu);
      if (!IsMenu(hsubmenu)) return (UINT)-1;
-     else return (pSubMenu->cItems << 8) | ((pItem->fState|pItem->fType) & 0xff);
+     else return (pSubMenu->cItems << 8) | ((pItem->fState|pItem->fType|Type) & 0xff);
   }
   else
-     return (pItem->fType | pItem->fState);  
+     return (pItem->fType | pItem->fState | Type);  
 }
 
 /*
@@ -5122,18 +4914,6 @@ GetMenuStringA(
   int nMaxCount,
   UINT uFlag)
 {
-/*  MENUITEMINFOA mii;
-  memset( &mii, 0, sizeof(mii) );
-  mii.dwTypeData = lpString;
-  mii.fMask = MIIM_STRING;
-  mii.cbSize = sizeof(MENUITEMINFOA);
-  mii.cch = nMaxCount;
-
-  if(!(GetMenuItemInfoA( hMenu, uIDItem, (BOOL)(MF_BYPOSITION & uFlag),&mii)))
-     return 0;
-  else
-     return mii.cch;
-*/
   ITEM *item;
   LPWSTR text;
   ////// wine Code, seems to be faster.
@@ -5153,7 +4933,7 @@ GetMenuStringA(
   if (!lpString || !nMaxCount) return WideCharToMultiByte( CP_ACP, 0, text, -1, NULL, 0, NULL, NULL );
   if (!WideCharToMultiByte( CP_ACP, 0, text, -1, lpString, nMaxCount, NULL, NULL ))
       lpString[nMaxCount-1] = 0;
-  ERR("returning %s\n", lpString);
+  TRACE("A returning %s\n", lpString);
   return strlen(lpString);
 }
 
@@ -5169,19 +4949,6 @@ GetMenuStringW(
   int nMaxCount,
   UINT uFlag)
 {
-/*  MENUITEMINFOW miiW;
-  memset( &miiW, 0, sizeof(miiW) );
-  miiW.dwTypeData = lpString;
-  miiW.fMask = MIIM_STRING | MIIM_FTYPE;
-  miiW.fType = MFT_STRING;
-  miiW.cbSize = sizeof(MENUITEMINFOW);
-  miiW.cch = nMaxCount;
-
-  if(!(GetMenuItemInfoW( hMenu, uIDItem, (BOOL)(MF_BYPOSITION & uFlag),&miiW)))
-     return 0;
-  else
-     return miiW.cch;
-*/
   ITEM *item;
   LPWSTR text;
 
@@ -5204,7 +4971,7 @@ GetMenuStringW(
       return 0;
   }
   lstrcpynW( lpString, text, nMaxCount );
-  ERR("returning %S\n", lpString);
+  TRACE("W returning %S\n", lpString);
   return strlenW(lpString);
 }
 
@@ -5257,18 +5024,32 @@ InsertMenuA(
   UINT_PTR uIDNewItem,
   LPCSTR lpNewItem)
 {
-  MENUITEMINFOA mii;
-  memset( &mii, 0, sizeof(mii) );
-  mii.cbSize = sizeof(MENUITEMINFOA);
-  mii.fMask = MIIM_FTYPE;
-
-  MenuSetItemData((LPMENUITEMINFOW) &mii,
-                  uFlags,
-                  uIDNewItem,
-                 (LPCWSTR) lpNewItem,
-                  FALSE);
-
-  return InsertMenuItemA(hMenu, uPosition, (BOOL)((MF_BYPOSITION & uFlags) > 0), &mii);
+  MENUITEMINFOW mii;
+  UNICODE_STRING UnicodeString;
+  BOOL res;
+
+  RtlInitUnicodeString(&UnicodeString, 0);
+
+  MENU_mnu2mnuii( uFlags, uIDNewItem, (LPCWSTR)lpNewItem, &mii, FALSE);
+
+  /* copy the text string, it wll be one or the other */
+  if (lpNewItem && mii.fMask & MIIM_STRING && !mii.hbmpItem && mii.dwTypeData)
+  {
+      if (!RtlCreateUnicodeStringFromAsciiz(&UnicodeString, (LPSTR)mii.dwTypeData))
+      {
+        SetLastError (ERROR_NOT_ENOUGH_MEMORY);
+        return FALSE;
+      }
+      mii.dwTypeData = UnicodeString.Buffer;
+      mii.cch = UnicodeString.Length / sizeof(WCHAR);
+  }
+  else
+  {
+      TRACE("Handle bitmaps\n");
+  }
+  res = NtUserThunkedMenuItemInfo(hMenu, uPosition, (BOOL)(uFlags & MF_BYPOSITION), TRUE, &mii, &UnicodeString);
+  if ( UnicodeString.Buffer ) RtlFreeUnicodeString ( &UnicodeString );
+  return res;
 }
 
 /*
@@ -5307,7 +5088,7 @@ InsertMenuItemA(
   }
   else
   {
-      UnicodeString.Buffer = NULL;
+      TRACE("Handle bitmaps\n");
   }
   res = NtUserThunkedMenuItemInfo(hMenu, uItem, fByPosition, TRUE, &mii, &UnicodeString);
   if ( UnicodeString.Buffer ) RtlFreeUnicodeString ( &UnicodeString );
@@ -5365,17 +5146,22 @@ InsertMenuW(
   LPCWSTR lpNewItem)
 {
   MENUITEMINFOW mii;
-  memset( &mii, 0, sizeof(mii) );
-  mii.cbSize = sizeof(MENUITEMINFOW);
-  mii.fMask = MIIM_FTYPE;
+  UNICODE_STRING MenuText;
+  BOOL res;
 
-  MenuSetItemData( &mii,
-                  uFlags,
-                  uIDNewItem,
-                  lpNewItem,
-                  TRUE);
+  RtlInitUnicodeString(&MenuText, 0);    
 
-  return InsertMenuItemW(hMenu, uPosition, (BOOL)((MF_BYPOSITION & uFlags) > 0), &mii);
+  MENU_mnu2mnuii( uFlags, uIDNewItem, lpNewItem, &mii, TRUE);
+
+  /* copy the text string, it wll be one or the other */
+  if (lpNewItem && mii.fMask & MIIM_STRING && !mii.hbmpItem && mii.dwTypeData)
+  {
+    RtlInitUnicodeString(&MenuText, (PWSTR)mii.dwTypeData);
+    mii.dwTypeData = MenuText.Buffer;
+    mii.cch = MenuText.Length / sizeof(WCHAR);
+  }
+  res = NtUserThunkedMenuItemInfo(hMenu, uPosition, (BOOL)(uFlags & MF_BYPOSITION), TRUE, &mii, &MenuText);
+  return res;
 }
 
 /*
@@ -5489,30 +5275,38 @@ MenuItemFromPoint(
 BOOL
 WINAPI
 ModifyMenuA(
-  HMENU hMnu,
+  HMENU hMenu,
   UINT uPosition,
   UINT uFlags,
   UINT_PTR uIDNewItem,
   LPCSTR lpNewItem)
 {
-  MENUITEMINFOA mii;
-  memset( &mii, 0, sizeof(mii) );
-  mii.cbSize = sizeof(MENUITEMINFOA); 
-  mii.fMask = MIIM_FTYPE;
-
-  MenuSetItemData((LPMENUITEMINFOW) &mii,
-                  uFlags,
-                  uIDNewItem,
-                 (LPCWSTR) lpNewItem,
-                  FALSE);
-
-  //if (mii.hSubMenu && (uFlags & MF_POPUP) && (mii.hSubMenu != (HMENU)uIDNewItem))
-  //  NtUserDestroyMenu( mii.hSubMenu );   /* ModifyMenu() spec */
-
-  return SetMenuItemInfoA( hMnu,
-                           uPosition,
-                          (BOOL)(MF_BYPOSITION & uFlags),
-                           &mii);
+  MENUITEMINFOW mii;
+  UNICODE_STRING UnicodeString;
+  BOOL res;
+
+  RtlInitUnicodeString(&UnicodeString, 0);
+
+  MENU_mnu2mnuii( uFlags, uIDNewItem, (LPCWSTR)lpNewItem, &mii, FALSE);
+
+  /* copy the text string, it wll be one or the other */
+  if (lpNewItem && mii.fMask & MIIM_STRING && !mii.hbmpItem && mii.dwTypeData)
+  {
+      if (!RtlCreateUnicodeStringFromAsciiz(&UnicodeString, (LPSTR)mii.dwTypeData))
+      {
+        SetLastError (ERROR_NOT_ENOUGH_MEMORY);
+        return FALSE;
+      }
+      mii.dwTypeData = UnicodeString.Buffer;
+      mii.cch = UnicodeString.Length / sizeof(WCHAR);
+  }
+  else
+  {
+      TRACE("Handle bitmaps\n");
+  }
+  res = NtUserThunkedMenuItemInfo(hMenu, uPosition, (BOOL)(uFlags & MF_BYPOSITION), FALSE, &mii, &UnicodeString);
+  if ( UnicodeString.Buffer ) RtlFreeUnicodeString ( &UnicodeString );
+  return res;
 }
 
 /*
@@ -5521,31 +5315,33 @@ ModifyMenuA(
 BOOL
 WINAPI
 ModifyMenuW(
-  HMENU hMnu,
+  HMENU hMenu,
   UINT uPosition,
   UINT uFlags,
   UINT_PTR uIDNewItem,
   LPCWSTR lpNewItem)
 {
   MENUITEMINFOW mii;
-  memset ( &mii, 0, sizeof(mii) );
-  mii.cbSize = sizeof(MENUITEMINFOW);
-  mii.fMask = MIIM_FTYPE;
-
-  /* Init new data for this menu item */
-  MenuSetItemData( &mii,
-                  uFlags,
-                  uIDNewItem,
-                  lpNewItem,
-                  TRUE);
-
-  //if (mii.hSubMenu && (uFlags & MF_POPUP) && (mii.hSubMenu != (HMENU)uIDNewItem))
-  //  NtUserDestroyMenu( mii.hSubMenu );   /* ModifyMenu() spec */
-
-  return SetMenuItemInfoW( hMnu,
-                           uPosition,
-                           (BOOL)(MF_BYPOSITION & uFlags),
-                           &mii);
+  UNICODE_STRING MenuText;
+  BOOL res;
+
+  RtlInitUnicodeString(&MenuText, 0);    
+
+  MENU_mnu2mnuii( uFlags, uIDNewItem, lpNewItem, &mii, TRUE);
+
+  /* copy the text string, it wll be one or the other */
+  if (lpNewItem && mii.fMask & MIIM_STRING && !mii.hbmpItem && mii.dwTypeData)
+  {
+    RtlInitUnicodeString(&MenuText, (PWSTR)mii.dwTypeData);
+    mii.dwTypeData = MenuText.Buffer;
+    mii.cch = MenuText.Length / sizeof(WCHAR);
+  }
+  else
+  {
+      TRACE("Handle bitmaps\n");
+  }
+  res = NtUserThunkedMenuItemInfo(hMenu, uPosition, (BOOL)(uFlags & MF_BYPOSITION), FALSE, &mii, &MenuText);
+  return res;
 }
 
 /*
@@ -5729,8 +5525,6 @@ NEWTrackPopupMenu(
                                  NULL); // LPTPMPARAMS is null
 }
 
-
-
 /*
  * @unimplemented
  */
@@ -5756,7 +5550,6 @@ MenuWindowProcA(
      return FALSE;
   }
   return NtUserMessageCall(hWnd, Msg, wParam, lParam, Result, FNID_MENU, TRUE);
-
 }
 
 /*