[EXPLORER-NEW]
[reactos.git] / win32ss / user / ntuser / menu.c
index bcec29d..bb93bfa 100644 (file)
@@ -11,16 +11,43 @@ 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. */
+#define MAXMENUDEPTH 30
+
+#define MNS_STYLE_MASK (MNS_NOCHECK|MNS_MODELESS|MNS_DRAGDROP|MNS_AUTODISMISS|MNS_NOTIFYBYPOS|MNS_CHECKORBMP)
+
+#define MENUITEMINFO_TYPE_MASK \
+                (MFT_STRING | MFT_BITMAP | MFT_OWNERDRAW | MFT_SEPARATOR | \
+                 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) &= ~MFS_DISABLED; \
+    (state) &= ~MF_GRAYED; \
+  } /* Separate the two for test_menu_resource_layout.*/ \
+  if((change) & MF_DISABLED) { \
+    (state) |= MF_DISABLED; \
+  } else { \
+    (state) &= ~MF_DISABLED; \
   } \
   if((change) & MFS_CHECKED) { \
     (state) |= MFS_CHECKED; \
@@ -44,47 +71,17 @@ DBG_DEFAULT_CHANNEL(UserMenu);
   } \
 }
 
-#define FreeMenuText(MenuItem) \
-{ \
-  if((MENU_ITEM_TYPE((MenuItem)->fType) == MF_STRING) && \
-           (MenuItem)->Text.Length) { \
-    ExFreePoolWithTag((MenuItem)->Text.Buffer, TAG_STRING); \
-  } \
-}
-
-
-PMENU_OBJECT FASTCALL UserGetMenuObject(HMENU hMenu)
-{
-   PMENU_OBJECT Menu;
-
-   if (!hMenu)
-   {
-      EngSetLastError(ERROR_INVALID_MENU_HANDLE);
-      return NULL;
-   }
-
-   Menu = (PMENU_OBJECT)UserGetObject(gHandleTable, hMenu, TYPE_MENU);
-   if (!Menu)
-   {
-      EngSetLastError(ERROR_INVALID_MENU_HANDLE);
-      return NULL;
-   }
-
-   return Menu;
-}
-
-
 #if 0
 void FASTCALL
-DumpMenuItemList(PMENU_ITEM MenuItem)
+DumpMenuItemList(PMENU Menu, PITEM MenuItem)
 {
-   UINT cnt = 0;
-   while(MenuItem)
+   UINT cnt = 0, i = Menu->cItems;
+   while(i)
    {
-      if(MenuItem->Text.Length)
-         DbgPrint(" %d. %wZ\n", ++cnt, &MenuItem->Text);
+      if(MenuItem->lpstr.Length)
+         DbgPrint(" %d. %wZ\n", ++cnt, &MenuItem->lpstr);
       else
-         DbgPrint(" %d. NO TEXT dwTypeData==%d\n", ++cnt, (DWORD)MenuItem->Text.Buffer);
+         DbgPrint(" %d. NO TEXT dwTypeData==%d\n", ++cnt, (DWORD)MenuItem->lpstr.Buffer);
       DbgPrint("   fType=");
       if(MFT_BITMAP & MenuItem->fType)
          DbgPrint("MFT_BITMAP ");
@@ -120,278 +117,495 @@ DumpMenuItemList(PMENU_ITEM 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
 
-PMENU_OBJECT FASTCALL
+#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)
 {
-   PMENU_OBJECT Menu = UserGetMenuObject(hMenu);
+   PMENU Menu = UserGetMenuObject(hMenu);
    if (Menu)
       Menu->head.cLockObj++;
 
    return Menu;
 }
 
-BOOL FASTCALL
-IntFreeMenuItem(PMENU_OBJECT Menu, PMENU_ITEM MenuItem, BOOL bRecurse)
+PMENU FASTCALL VerifyMenu(PMENU pMenu)
 {
-   FreeMenuText(MenuItem);
-   if(bRecurse && MenuItem->hSubMenu)
+   HMENU hMenu;
+   PITEM pItem;
+   UINT i;
+   if (!pMenu) return NULL;
+
+   _SEH2_TRY
    {
-      PMENU_OBJECT SubMenu;
-      SubMenu = UserGetMenuObject(MenuItem->hSubMenu );
-      if(SubMenu)
+      hMenu = UserHMGetHandle(pMenu);
+      pItem = pMenu->rgItems;
+      if (pItem)
       {
-         IntDestroyMenuObject(SubMenu, bRecurse, TRUE);
+         i = pItem[0].wID;
+         pItem[0].wID = i;
       }
    }
+   _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+   {
+      ERR("Run away LOOP!\n");
+      _SEH2_YIELD(return NULL);
+   }
+   _SEH2_END
 
-   /* Free memory */
-   ExFreePoolWithTag(MenuItem, TAG_MENUITEM);
+   if ( UserObjectInDestroy(hMenu))
+   {
+      ERR("Menu is marked for destruction!\n");
+      return NULL;
+   }
 
-   return TRUE;
+   return pMenu;
 }
 
-BOOL FASTCALL
-IntRemoveMenuItem(PMENU_OBJECT Menu, UINT uPosition, UINT uFlags,
-                  BOOL bRecurse)
+BOOL IntDestroyMenu( PMENU pMenu, BOOL bRecurse)
 {
-   PMENU_ITEM PrevMenuItem, MenuItem;
-   if(IntGetMenuItemByFlag(Menu, uPosition, uFlags, &Menu, &MenuItem,
-                           &PrevMenuItem) > -1)
-   {
-      if(MenuItem)
-      {
-         if(PrevMenuItem)
-            PrevMenuItem->Next = MenuItem->Next;
-         else
-         {
-            Menu->MenuItemList = MenuItem->Next;
-         }
-         Menu->MenuInfo.MenuItemCount--;
-         return IntFreeMenuItem(Menu, MenuItem, bRecurse);
-      }
-   }
-   return FALSE;
+    PMENU SubMenu;
+
+    if (pMenu->rgItems) /* recursively destroy submenus */
+    {
+       int i;
+       ITEM *item = pMenu->rgItems;
+       for (i = pMenu->cItems; i > 0; i--, item++)
+       {
+           SubMenu = item->spSubMenu;
+           item->spSubMenu = NULL;
+
+           /* Remove Item Text */
+           FreeMenuText(pMenu,item);
+
+           /* Remove Item Bitmap and set it for this process */
+           if (item->hbmp && !(item->fState & MFS_HBMMENUBMP))
+           {
+              GreSetObjectOwner(item->hbmp, GDI_OBJ_HMGR_POWNED);
+              item->hbmp = NULL;
+           }
+
+           /* Remove Item submenu */
+           if (bRecurse && SubMenu)//VerifyMenu(SubMenu))
+           {
+              /* Release submenu since it was referenced when inserted */
+              IntReleaseMenuObject(SubMenu);
+              IntDestroyMenuObject(SubMenu, bRecurse);
+           }
+       }
+       /* Free the Item */
+       DesktopHeapFree(pMenu->head.rpdesk, pMenu->rgItems );
+       pMenu->rgItems = NULL; 
+       pMenu->cItems = 0;
+    }
+    return TRUE;
 }
 
-UINT FASTCALL
-IntDeleteMenuItems(PMENU_OBJECT Menu, BOOL bRecurse)
+/* Callback for the object manager */
+BOOLEAN
+UserDestroyMenuObject(PVOID Object)
 {
-   UINT res = 0;
-   PMENU_ITEM NextItem;
-   PMENU_ITEM CurItem = Menu->MenuItemList;
-   while(CurItem)
-   {
-      NextItem = CurItem->Next;
-      IntFreeMenuItem(Menu, CurItem, bRecurse);
-      CurItem = NextItem;
-      res++;
-   }
-   Menu->MenuInfo.MenuItemCount = 0;
-   Menu->MenuItemList = NULL;
-   return res;
+    return IntDestroyMenuObject(Object, TRUE);
 }
 
 BOOL FASTCALL
-IntDestroyMenuObject(PMENU_OBJECT Menu,
-                     BOOL bRecurse, BOOL RemoveFromProcess)
+IntDestroyMenuObject(PMENU Menu, BOOL bRecurse)
 {
    if(Menu)
    {
       PWND Window;
-      PWINSTATION_OBJECT WindowStation;
-      NTSTATUS Status;
 
       /* Remove all menu items */
-      IntDeleteMenuItems(Menu, bRecurse); /* Do not destroy submenus */
-
-      if(RemoveFromProcess)
-      {
-         RemoveEntryList(&Menu->ListEntry);
-      }
+      IntDestroyMenu( Menu, bRecurse);
 
-      Status = ObReferenceObjectByHandle(Menu->Process->Win32WindowStation,
-                                         0,
-                                         ExWindowStationObjectType,
-                                         KernelMode,
-                                         (PVOID*)&WindowStation,
-                                         NULL);
-      if(NT_SUCCESS(Status))
+      if (PsGetCurrentProcessSessionId() == Menu->head.rpdesk->rpwinstaParent->dwSessionId)
       {
          BOOL ret;
-         if (Menu->MenuInfo.Wnd)
+         if (Menu->hWnd)
          {
-            Window = UserGetWindowObject(Menu->MenuInfo.Wnd);
+            Window = UserGetWindowObject(Menu->hWnd);
             if (Window)
             {
                Window->IDMenu = 0;
+
+               /* DestroyMenu should not destroy system menu popup owner */
+               if ((Menu->fFlags & (MNF_POPUP | MNF_SYSSUBMENU)) == MNF_POPUP)
+               {
+                  // Should we check it to see if it has Class?
+                  ERR("FIXME Pop up menu window thing'ie\n");
+                  //co_UserDestroyWindow( Window );
+                  //Menu->hWnd = 0;
+               }
             }
          }
-//         UserDereferenceObject(Menu);
-         ret = UserDeleteObject(Menu->MenuInfo.Self, TYPE_MENU);
-         ObDereferenceObject(WindowStation);
+         ret = UserDeleteObject(Menu->head.h, TYPE_MENU);
+         if (!ret)
+         {  // Make sure it is really dead or just marked for deletion.
+            ret = UserObjectInDestroy(Menu->head.h);
+            if (ret && EngGetLastError() == ERROR_INVALID_HANDLE) ret = FALSE;
+         }  // See test_subpopup_locked_by_menu tests....
          return ret;
       }
    }
    return FALSE;
 }
 
-PMENU_OBJECT FASTCALL
-IntCreateMenu(PHANDLE Handle, BOOL IsMenuBar)
+/**********************************************************************
+ *             MENU_depth
+ *
+ * detect if there are loops in the menu tree (or the depth is too large)
+ */
+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; item, i < pmenu->cItems && subdepth <= MAXMENUDEPTH; i++, item++)
+    {
+        if( item->spSubMenu)//VerifyMenu(item->spSubMenu))
+        {
+            int bdepth = MENU_depth( item->spSubMenu, depth);
+            if( bdepth > subdepth) subdepth = bdepth;
+        }
+        if( subdepth > MAXMENUDEPTH)
+            TRACE("<- hmenu %p\n", item->spSubMenu);
+    }
+    return subdepth;
+}
+
+/***********************************************************************
+ *           MENU_FindItem
+ *
+ * Find a menu item. Return a pointer on the item, and modifies *hmenu
+ * in case the item was in a sub-menu.
+ */
+PITEM FASTCALL MENU_FindItem( PMENU *pmenu, UINT *nPos, UINT wFlags )
+{
+    MENU *menu = *pmenu;
+    ITEM *fallback = NULL;
+    UINT fallback_pos = 0;
+    UINT i;
+
+    if (!menu) return NULL;
+
+    if (wFlags & MF_BYPOSITION)
+    {
+        if (!menu->cItems) return NULL;
+       if (*nPos >= menu->cItems) return NULL;
+       return &menu->rgItems[*nPos];
+    }
+    else
+    {
+        PITEM item = menu->rgItems;
+       for (i = 0; item, i < menu->cItems; i++, item++)
+       {
+           if (item->spSubMenu)
+           {
+               PMENU psubmenu = item->spSubMenu;//VerifyMenu(item->spSubMenu);
+               PITEM subitem = MENU_FindItem( &psubmenu, nPos, wFlags );
+               if (subitem)
+               {
+                   *pmenu = psubmenu;
+                   return subitem;
+               }
+               else if (item->wID == *nPos)
+               {
+                   /* fallback to this item if nothing else found */
+                   fallback_pos = i;
+                   fallback = item;
+               }
+           }
+           else if (item->wID == *nPos)
+           {
+               *nPos = i;
+               return item;
+           }
+       }
+    }
+
+    if (fallback)
+        *nPos = fallback_pos;
+
+    return fallback;
+}
+
+BOOL FASTCALL
+IntRemoveMenuItem( PMENU pMenu, UINT nPos, UINT wFlags, BOOL bRecurse )
+{
+    PITEM item;
+
+    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);
+    if (bRecurse && item->spSubMenu)
+    {
+       IntDestroyMenuObject(item->spSubMenu, bRecurse);
+    }
+    ////// Use cAlloced with inc's of 8's....
+    if (--pMenu->cItems == 0)
+    {
+        DesktopHeapFree(pMenu->head.rpdesk, pMenu->rgItems );
+        pMenu->rgItems = NULL;
+    }
+    else
+    {
+       while(nPos < pMenu->cItems)
+       {
+           *item = *(item+1);
+           item++;
+           nPos++;
+       }
+       pMenu->rgItems = DesktopHeapReAlloc(pMenu->head.rpdesk, pMenu->rgItems, pMenu->cItems * sizeof(ITEM));
+    }
+    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(
+    _Out_ PHANDLE Handle,
+    _In_ BOOL IsMenuBar,
+    _In_ PDESKTOP Desktop,
+    _In_ PPROCESSINFO ppi)
 {
-   PMENU_OBJECT Menu;
-   PPROCESSINFO CurrentWin32Process;
+   PMENU Menu;
 
-   Menu = (PMENU_OBJECT)UserCreateObject( gHandleTable,
-                                          NULL,
-                                          NULL,
+   Menu = (PMENU)UserCreateObject( gHandleTable,
+                                          Desktop,
+                                          ppi->ptiList,
                                           Handle,
                                           TYPE_MENU,
-                                          sizeof(MENU_OBJECT));
+                                          sizeof(MENU));
    if(!Menu)
    {
       *Handle = 0;
       return NULL;
    }
 
-   Menu->Process = PsGetCurrentProcess();
-   Menu->RtoL = FALSE; /* Default */
-   Menu->MenuInfo.cbSize = sizeof(MENUINFO); /* Not used */
-   Menu->MenuInfo.fMask = 0; /* Not used */
-   Menu->MenuInfo.dwStyle = 0; /* FIXME */
-   Menu->MenuInfo.cyMax = 0; /* Default */
-   Menu->MenuInfo.hbrBack = NULL; /* No brush */
-   Menu->MenuInfo.dwContextHelpID = 0; /* Default */
-   Menu->MenuInfo.dwMenuData = 0; /* Default */
-   Menu->MenuInfo.Self = *Handle;
-   Menu->MenuInfo.FocusedItem = NO_SELECTED_ITEM;
-   Menu->MenuInfo.Flags = (IsMenuBar ? 0 : MF_POPUP);
-   Menu->MenuInfo.Wnd = NULL;
-   Menu->MenuInfo.WndOwner = NULL;
-   Menu->MenuInfo.Height = 0;
-   Menu->MenuInfo.Width = 0;
-   Menu->MenuInfo.TimeToHide = FALSE;
-
-   Menu->MenuInfo.MenuItemCount = 0;
-   Menu->MenuItemList = NULL;
-
-   /* Insert menu item into process menu handle list */
-   CurrentWin32Process = PsGetCurrentProcessWin32Process();
-   InsertTailList(&CurrentWin32Process->MenuListHead, &Menu->ListEntry);
+   Menu->cyMax = 0; /* Default */
+   Menu->hbrBack = NULL; /* No brush */
+   Menu->dwContextHelpId = 0; /* Default */
+   Menu->dwMenuData = 0; /* Default */
+   Menu->iItem = NO_SELECTED_ITEM; // Focused item
+   Menu->fFlags = (IsMenuBar ? 0 : MNF_POPUP);
+   Menu->spwndNotify = NULL;
+   Menu->cyMenu = 0; // Height
+   Menu->cxMenu = 0; // Width
+   Menu->cItems = 0; // Item count
+   Menu->iTop = 0;
+   Menu->iMaxTop = 0;
+   Menu->cxTextAlign = 0;
+   Menu->rgItems = NULL;
+
+   Menu->hWnd = NULL;
+   Menu->TimeToHide = FALSE;
 
    return Menu;
 }
 
 BOOL FASTCALL
-IntCloneMenuItems(PMENU_OBJECT Destination, PMENU_OBJECT Source)
+IntCloneMenuItems(PMENU Destination, PMENU Source)
 {
-   PMENU_ITEM MenuItem, NewMenuItem = NULL;
-   PMENU_ITEM Old = NULL;
+   PITEM MenuItem, NewMenuItem = NULL;
+   UINT i;
 
-   if(!Source->MenuInfo.MenuItemCount)
+   if(!Source->cItems)
       return FALSE;
 
-   MenuItem = Source->MenuItemList;
-   while(MenuItem)
+   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;
+   for (i = 0; i < Source->cItems; i++, MenuItem++, NewMenuItem++)
    {
-      Old = NewMenuItem;
-      if(NewMenuItem)
-         NewMenuItem->Next = MenuItem;
-      NewMenuItem = ExAllocatePoolWithTag(PagedPool, sizeof(MENU_ITEM), TAG_MENUITEM);
-      if(!NewMenuItem)
-         break;
       NewMenuItem->fType = MenuItem->fType;
       NewMenuItem->fState = MenuItem->fState;
       NewMenuItem->wID = MenuItem->wID;
-      NewMenuItem->hSubMenu = MenuItem->hSubMenu;
+      NewMenuItem->spSubMenu = MenuItem->spSubMenu;
       NewMenuItem->hbmpChecked = MenuItem->hbmpChecked;
       NewMenuItem->hbmpUnchecked = MenuItem->hbmpUnchecked;
       NewMenuItem->dwItemData = MenuItem->dwItemData;
-      if((MENU_ITEM_TYPE(NewMenuItem->fType) == MF_STRING))
+      if (MenuItem->lpstr.Length)
       {
-         if(MenuItem->Text.Length)
+         NewMenuItem->lpstr.Length = 0;
+         NewMenuItem->lpstr.MaximumLength = MenuItem->lpstr.MaximumLength;
+         NewMenuItem->lpstr.Buffer = DesktopHeapAlloc(Destination->head.rpdesk, MenuItem->lpstr.MaximumLength);
+         if (!NewMenuItem->lpstr.Buffer)
          {
-            NewMenuItem->Text.Length = 0;
-            NewMenuItem->Text.MaximumLength = MenuItem->Text.MaximumLength;
-            NewMenuItem->Text.Buffer = (PWSTR)ExAllocatePoolWithTag(PagedPool, MenuItem->Text.MaximumLength, TAG_STRING);
-            if(!NewMenuItem->Text.Buffer)
-            {
-               ExFreePoolWithTag(NewMenuItem, TAG_MENUITEM);
-               break;
-            }
-            RtlCopyUnicodeString(&NewMenuItem->Text, &MenuItem->Text);
-         }
-         else
-         {
-            NewMenuItem->Text.Buffer = MenuItem->Text.Buffer;
+             DesktopHeapFree(Destination->head.rpdesk, NewMenuItem);
+             break;
          }
+         RtlCopyUnicodeString(&NewMenuItem->lpstr, &MenuItem->lpstr);
+         NewMenuItem->lpstr.Buffer[MenuItem->lpstr.Length / sizeof(WCHAR)] = 0;
+         NewMenuItem->Xlpstr = NewMenuItem->lpstr.Buffer;
       }
       else
       {
-         NewMenuItem->Text.Buffer = MenuItem->Text.Buffer;
+         NewMenuItem->lpstr.Buffer = MenuItem->lpstr.Buffer;
+         NewMenuItem->Xlpstr = NewMenuItem->lpstr.Buffer;
       }
-      NewMenuItem->hbmpItem = MenuItem->hbmpItem;
-
-      NewMenuItem->Next = NULL;
-      if(Old)
-         Old->Next = NewMenuItem;
-      else
-         Destination->MenuItemList = NewMenuItem;
-      Destination->MenuInfo.MenuItemCount++;
-      MenuItem = MenuItem->Next;
+      NewMenuItem->hbmp = MenuItem->hbmp;
    }
-
    return TRUE;
 }
 
-PMENU_OBJECT FASTCALL
-IntCloneMenu(PMENU_OBJECT Source)
+PMENU FASTCALL
+IntCloneMenu(PMENU Source)
 {
-   PPROCESSINFO CurrentWin32Process;
    HANDLE hMenu;
-   PMENU_OBJECT Menu;
+   PMENU Menu;
 
    if(!Source)
       return NULL;
 
-   Menu = (PMENU_OBJECT)UserCreateObject( gHandleTable,
-                                          NULL,
-                                          NULL,
-                                          &hMenu,
-                                          TYPE_MENU,
-                                          sizeof(MENU_OBJECT));
+   /* A menu is valid process wide. We can pass to the object manager any thread ptr */
+   Menu = (PMENU)UserCreateObject( gHandleTable,
+                                   Source->head.rpdesk,
+                                   ((PPROCESSINFO)Source->head.hTaskWow)->ptiList,
+                                   &hMenu,
+                                   TYPE_MENU,
+                                   sizeof(MENU));
    if(!Menu)
       return NULL;
 
-   Menu->Process = PsGetCurrentProcess();
-   Menu->RtoL = Source->RtoL;
-   Menu->MenuInfo.cbSize = sizeof(MENUINFO); /* Not used */
-   Menu->MenuInfo.fMask = Source->MenuInfo.fMask;
-   Menu->MenuInfo.dwStyle = Source->MenuInfo.dwStyle;
-   Menu->MenuInfo.cyMax = Source->MenuInfo.cyMax;
-   Menu->MenuInfo.hbrBack = Source->MenuInfo.hbrBack;
-   Menu->MenuInfo.dwContextHelpID = Source->MenuInfo.dwContextHelpID;
-   Menu->MenuInfo.dwMenuData = Source->MenuInfo.dwMenuData;
-   Menu->MenuInfo.Self = hMenu;
-   Menu->MenuInfo.FocusedItem = NO_SELECTED_ITEM;
-   Menu->MenuInfo.Wnd = NULL;
-   Menu->MenuInfo.WndOwner = NULL;
-   Menu->MenuInfo.Height = 0;
-   Menu->MenuInfo.Width = 0;
-   Menu->MenuInfo.TimeToHide = FALSE;
-
-   Menu->MenuInfo.MenuItemCount = 0;
-   Menu->MenuItemList = NULL;
-
-   /* Insert menu item into process menu handle list */
-   CurrentWin32Process = PsGetCurrentProcessWin32Process();
-   InsertTailList(&CurrentWin32Process->MenuListHead, &Menu->ListEntry);
+   Menu->fFlags = Source->fFlags;
+   Menu->cyMax = Source->cyMax;
+   Menu->hbrBack = Source->hbrBack;
+   Menu->dwContextHelpId = Source->dwContextHelpId;
+   Menu->dwMenuData = Source->dwMenuData;
+   Menu->iItem = NO_SELECTED_ITEM;
+   Menu->spwndNotify = NULL;
+   Menu->cyMenu = 0;
+   Menu->cxMenu = 0;
+   Menu->cItems = Source->cItems;
+   Menu->iTop = 0;
+   Menu->iMaxTop = 0;
+   Menu->cxTextAlign = 0;
+   Menu->rgItems = NULL;
+
+   Menu->hWnd = NULL;
+   Menu->TimeToHide = FALSE;
 
    IntCloneMenuItems(Menu, Source);
 
@@ -399,194 +613,99 @@ IntCloneMenu(PMENU_OBJECT Source)
 }
 
 BOOL FASTCALL
-IntSetMenuFlagRtoL(PMENU_OBJECT Menu)
+IntSetMenuFlagRtoL(PMENU Menu)
 {
-   Menu->RtoL = TRUE;
+   Menu->fFlags |= MNF_RTOL;
    return TRUE;
 }
 
 BOOL FASTCALL
-IntSetMenuContextHelpId(PMENU_OBJECT Menu, DWORD dwContextHelpId)
+IntSetMenuContextHelpId(PMENU Menu, DWORD dwContextHelpId)
 {
-   Menu->MenuInfo.dwContextHelpID = dwContextHelpId;
+   Menu->dwContextHelpId = dwContextHelpId;
    return TRUE;
 }
 
 BOOL FASTCALL
-IntGetMenuInfo(PMENU_OBJECT Menu, PROSMENUINFO lpmi)
+IntGetMenuInfo(PMENU Menu, PROSMENUINFO lpmi)
 {
    if(lpmi->fMask & MIM_BACKGROUND)
-      lpmi->hbrBack = Menu->MenuInfo.hbrBack;
+      lpmi->hbrBack = Menu->hbrBack;
    if(lpmi->fMask & MIM_HELPID)
-      lpmi->dwContextHelpID = Menu->MenuInfo.dwContextHelpID;
+      lpmi->dwContextHelpID = Menu->dwContextHelpId;
    if(lpmi->fMask & MIM_MAXHEIGHT)
-      lpmi->cyMax = Menu->MenuInfo.cyMax;
+      lpmi->cyMax = Menu->cyMax;
    if(lpmi->fMask & MIM_MENUDATA)
-      lpmi->dwMenuData = Menu->MenuInfo.dwMenuData;
+      lpmi->dwMenuData = Menu->dwMenuData;
    if(lpmi->fMask & MIM_STYLE)
-      lpmi->dwStyle = Menu->MenuInfo.dwStyle;
+      lpmi->dwStyle = Menu->fFlags & MNS_STYLE_MASK;
+
    if (sizeof(MENUINFO) < lpmi->cbSize)
    {
-      RtlCopyMemory((char *) lpmi + sizeof(MENUINFO),
-                    (char *) &Menu->MenuInfo + sizeof(MENUINFO),
-                    lpmi->cbSize - sizeof(MENUINFO));
-   }
-   if (sizeof(ROSMENUINFO) == lpmi->cbSize)
-   {
-     lpmi->maxBmpSize.cx = Menu->MenuInfo.maxBmpSize.cx;
-     lpmi->maxBmpSize.cy = Menu->MenuInfo.maxBmpSize.cy;
+     lpmi->cItems = Menu->cItems;
+
+     lpmi->iItem = Menu->iItem;
+     lpmi->cxMenu = Menu->cxMenu;
+     lpmi->cyMenu = Menu->cyMenu;
+     lpmi->spwndNotify = Menu->spwndNotify;
+     lpmi->cxTextAlign = Menu->cxTextAlign;
+     lpmi->iTop = Menu->iMaxTop;
+     lpmi->iMaxTop = Menu->iMaxTop;
+     lpmi->dwArrowsOn = Menu->dwArrowsOn;
+
+     lpmi->fFlags = Menu->fFlags;
+     lpmi->Self = Menu->head.h;
+     lpmi->TimeToHide = Menu->TimeToHide;
+     lpmi->Wnd = Menu->hWnd;
    }
    return TRUE;
 }
 
 BOOL FASTCALL
-IntSetMenuInfo(PMENU_OBJECT Menu, PROSMENUINFO lpmi)
+IntSetMenuInfo(PMENU Menu, PROSMENUINFO lpmi)
 {
    if(lpmi->fMask & MIM_BACKGROUND)
-      Menu->MenuInfo.hbrBack = lpmi->hbrBack;
+      Menu->hbrBack = lpmi->hbrBack;
    if(lpmi->fMask & MIM_HELPID)
-      Menu->MenuInfo.dwContextHelpID = lpmi->dwContextHelpID;
+      Menu->dwContextHelpId = lpmi->dwContextHelpID;
    if(lpmi->fMask & MIM_MAXHEIGHT)
-      Menu->MenuInfo.cyMax = lpmi->cyMax;
+      Menu->cyMax = lpmi->cyMax;
    if(lpmi->fMask & MIM_MENUDATA)
-      Menu->MenuInfo.dwMenuData = lpmi->dwMenuData;
+      Menu->dwMenuData = lpmi->dwMenuData;
    if(lpmi->fMask & MIM_STYLE)
-      Menu->MenuInfo.dwStyle = lpmi->dwStyle;
+      Menu->fFlags ^= (Menu->fFlags ^ lpmi->dwStyle) & MNS_STYLE_MASK;
    if(lpmi->fMask & MIM_APPLYTOSUBMENUS)
    {
-      /* FIXME */
-   }
-   if (sizeof(MENUINFO) < lpmi->cbSize)
-   {
-      Menu->MenuInfo.FocusedItem = lpmi->FocusedItem;
-      Menu->MenuInfo.Height = lpmi->Height;
-      Menu->MenuInfo.Width = lpmi->Width;
-      Menu->MenuInfo.Wnd = lpmi->Wnd;
-      Menu->MenuInfo.WndOwner = lpmi->WndOwner;
-      Menu->MenuInfo.TimeToHide = lpmi->TimeToHide;
-   }
-   if (sizeof(ROSMENUINFO) == lpmi->cbSize)
-   {
-     Menu->MenuInfo.maxBmpSize.cx = lpmi->maxBmpSize.cx;
-     Menu->MenuInfo.maxBmpSize.cy = lpmi->maxBmpSize.cy;
-   }
-   return TRUE;
-}
-
-
-int FASTCALL
-IntGetMenuItemByFlag(PMENU_OBJECT Menu, UINT uSearchBy, UINT fFlag,
-                     PMENU_OBJECT *SubMenu, PMENU_ITEM *MenuItem,
-                     PMENU_ITEM *PrevMenuItem)
-{
-   PMENU_ITEM PrevItem = NULL;
-   PMENU_ITEM CurItem = Menu->MenuItemList;
-   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)
+      int i;
+      PITEM item = Menu->rgItems;
+      for ( i = Menu->cItems; i; i--, item++)
       {
-         if(CurItem->wID == uSearchBy)
-         {
-            if(MenuItem)
-               *MenuItem = CurItem;
-            if(PrevMenuItem)
-               *PrevMenuItem = PrevItem;
-            if(SubMenu)
-                *SubMenu = Menu;
-
-            return p;
-         }
-         else
+         if ( item->spSubMenu )
          {
-            if(CurItem->fType & MF_POPUP)
-            {
-               PMENU_OBJECT NewMenu = UserGetMenuObject(CurItem->hSubMenu);
-               if(NewMenu)
-               {
-                   ret = IntGetMenuItemByFlag(NewMenu, uSearchBy, fFlag,
-                                              SubMenu, MenuItem, PrevMenuItem);
-                   if(ret != -1)
-                   {
-                      return ret;
-                   }
-               }
-            }
+            IntSetMenuInfo( item->spSubMenu, lpmi);
          }
-         PrevItem = CurItem;
-         CurItem = CurItem->Next;
-         p++;
-      }
+      }      
    }
-   return -1;
-}
-
-
-int FASTCALL
-IntInsertMenuItemToList(PMENU_OBJECT Menu, PMENU_ITEM MenuItem, int pos)
-{
-   PMENU_ITEM CurItem;
-   PMENU_ITEM LastItem = NULL;
-   UINT npos = 0;
-
-   CurItem = Menu->MenuItemList;
-   while(CurItem && (pos != 0))
+   if (sizeof(MENUINFO) < lpmi->cbSize)
    {
-      LastItem = CurItem;
-      CurItem = CurItem->Next;
-      pos--;
-      npos++;
-   }
+      Menu->iItem = lpmi->iItem;
+      Menu->cyMenu = lpmi->cyMenu;
+      Menu->cxMenu = lpmi->cxMenu;
+      Menu->spwndNotify = lpmi->spwndNotify;
+      Menu->cxTextAlign = lpmi->cxTextAlign;
+      Menu->iTop = lpmi->iTop;
+      Menu->iMaxTop = lpmi->iMaxTop;
+      Menu->dwArrowsOn = lpmi->dwArrowsOn;
 
-   if(LastItem)
-   {
-      /* Insert the item after LastItem */
-      LastItem->Next = MenuItem;
-   }
-   else
-   {
-      /* Insert at the beginning */
-      Menu->MenuItemList = MenuItem;
+      Menu->TimeToHide = lpmi->TimeToHide;
+      Menu->hWnd = lpmi->Wnd;
    }
-   MenuItem->Next = CurItem;
-   Menu->MenuInfo.MenuItemCount++;
-
-   return npos;
+   return TRUE;
 }
 
 BOOL FASTCALL
-IntGetMenuItemInfo(PMENU_OBJECT Menu, /* UNUSED PARAM!! */
-                   PMENU_ITEM MenuItem, PROSMENUITEMINFO lpmii)
+IntGetMenuItemInfo(PMENU Menu, /* UNUSED PARAM!! */
+                   PITEM MenuItem, PROSMENUITEMINFO lpmii)
 {
    NTSTATUS Status;
 
@@ -596,7 +715,7 @@ IntGetMenuItemInfo(PMENU_OBJECT Menu, /* UNUSED PARAM!! */
    }
    if(lpmii->fMask & MIIM_BITMAP)
    {
-      lpmii->hbmpItem = MenuItem->hbmpItem;
+      lpmii->hbmpItem = MenuItem->hbmp;
    }
    if(lpmii->fMask & MIIM_CHECKMARKS)
    {
@@ -617,7 +736,7 @@ IntGetMenuItemInfo(PMENU_OBJECT Menu, /* UNUSED PARAM!! */
    }
    if(lpmii->fMask & MIIM_SUBMENU)
    {
-      lpmii->hSubMenu = MenuItem->hSubMenu;
+      lpmii->hSubMenu = MenuItem->spSubMenu ? MenuItem->spSubMenu->head.h : NULL;
    }
 
    if ((lpmii->fMask & MIIM_STRING) ||
@@ -625,13 +744,13 @@ IntGetMenuItemInfo(PMENU_OBJECT Menu, /* UNUSED PARAM!! */
    {
       if (lpmii->dwTypeData == NULL)
       {
-         lpmii->cch = MenuItem->Text.Length / sizeof(WCHAR);
+         lpmii->cch = MenuItem->lpstr.Length / sizeof(WCHAR);
       }
       else
-      {
-         Status = MmCopyToCaller(lpmii->dwTypeData, MenuItem->Text.Buffer,
+      {  //// lpmii->lpstr can be read in user mode!!!!
+         Status = MmCopyToCaller(lpmii->dwTypeData, MenuItem->lpstr.Buffer,
                                  min(lpmii->cch * sizeof(WCHAR),
-                                     MenuItem->Text.MaximumLength));
+                                     MenuItem->lpstr.MaximumLength));
          if (! NT_SUCCESS(Status))
          {
             SetLastNtError(Status);
@@ -642,38 +761,46 @@ IntGetMenuItemInfo(PMENU_OBJECT Menu, /* UNUSED PARAM!! */
 
    if (sizeof(ROSMENUITEMINFO) == lpmii->cbSize)
    {
-      lpmii->Rect = MenuItem->Rect;
+      lpmii->Rect.left   = MenuItem->xItem; 
+      lpmii->Rect.top    = MenuItem->yItem; 
+      lpmii->Rect.right  = MenuItem->cxItem; // Do this for now......
+      lpmii->Rect.bottom = MenuItem->cyItem;
       lpmii->dxTab = MenuItem->dxTab;
-      lpmii->lpstr = MenuItem->Text.Buffer; // Use DesktopHeap!
+      lpmii->lpstr = MenuItem->lpstr.Buffer;
+      lpmii->maxBmpSize.cx = MenuItem->cxBmp;
+      lpmii->maxBmpSize.cy = MenuItem->cyBmp;
    }
 
    return TRUE;
 }
 
 BOOL FASTCALL
-IntSetMenuItemInfo(PMENU_OBJECT MenuObject, PMENU_ITEM MenuItem, PROSMENUITEMINFO lpmii)
+IntSetMenuItemInfo(PMENU MenuObject, PITEM MenuItem, PROSMENUITEMINFO lpmii, PUNICODE_STRING lpstr)
 {
-   PMENU_OBJECT SubMenuObject;
-   UINT fTypeMask = (MFT_BITMAP | MFT_MENUBARBREAK | MFT_MENUBREAK | MFT_OWNERDRAW | MFT_RADIOCHECK | MFT_RIGHTJUSTIFY | MFT_SEPARATOR | MF_POPUP);
+   PMENU SubMenuObject;
+   BOOL circref = FALSE;
 
    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))
       {
          ERR("IntSetMenuItemInfo: Invalid combination of fMask bits used\n");
+         KeRosDumpStackFrames(NULL, 20);
          /* This does not happen on Win9x/ME */
          SetLastNtError( ERROR_INVALID_PARAMETER);
          return FALSE;
       }
+      #endif
       /*
        * Delete the menu item type when changing type from
        * MF_STRING.
@@ -681,33 +808,28 @@ IntSetMenuItemInfo(PMENU_OBJECT MenuObject, PMENU_ITEM MenuItem, PROSMENUITEMINF
       if (MenuItem->fType != lpmii->fType &&
             MENU_ITEM_TYPE(MenuItem->fType) == MFT_STRING)
       {
-         FreeMenuText(MenuItem);
-         RtlInitUnicodeString(&MenuItem->Text, NULL);
+         FreeMenuText(MenuObject,MenuItem);
+         RtlInitUnicodeString(&MenuItem->lpstr, NULL);
+         MenuItem->Xlpstr = NULL;
       }
       if(lpmii->fType & MFT_BITMAP)
       {
          if(lpmii->hbmpItem)
-           MenuItem->hbmpItem = lpmii->hbmpItem;
+           MenuItem->hbmp = lpmii->hbmpItem;
          else
          { /* Win 9x/Me stuff */
-           MenuItem->hbmpItem = (HBITMAP)((ULONG_PTR)(LOWORD(lpmii->dwTypeData)));
+           MenuItem->hbmp = (HBITMAP)((ULONG_PTR)(LOWORD(lpmii->dwTypeData)));
          }
+         lpmii->dwTypeData = 0;
       }
-      MenuItem->fType |= lpmii->fType;
-   }
-   if (lpmii->fMask & MIIM_FTYPE )
-   {
-      if(( lpmii->fType & MFT_BITMAP))
-      {
-         ERR("IntSetMenuItemInfo: Can not use FTYPE and MFT_BITMAP.\n");
-         SetLastNtError( ERROR_INVALID_PARAMETER);
-         return FALSE;
-      }
-      MenuItem->fType |= lpmii->fType; /* Need to save all the flags, this fixed MFT_RIGHTJUSTIFY */
    }
    if(lpmii->fMask & MIIM_BITMAP)
    {
-         MenuItem->hbmpItem = lpmii->hbmpItem;
+      MenuItem->hbmp = lpmii->hbmpItem;
+      if (MenuItem->hbmp <= HBMMENU_POPUP_MINIMIZE && MenuItem->hbmp >= HBMMENU_CALLBACK)
+         MenuItem->fState |= MFS_HBMMENUBMP;
+      else
+         MenuItem->fState &= ~MFS_HBMMENUBMP; 
    }
    if(lpmii->fMask & MIIM_CHECKMARKS)
    {
@@ -734,321 +856,157 @@ IntSetMenuItemInfo(PMENU_OBJECT MenuObject, PMENU_ITEM MenuItem, PROSMENUITEMINF
 
    if(lpmii->fMask & MIIM_SUBMENU)
    {
-      MenuItem->hSubMenu = lpmii->hSubMenu;
-      /* Make sure the submenu is marked as a popup menu */
-      if (MenuItem->hSubMenu)
+      if (lpmii->hSubMenu)
       {
-         SubMenuObject = UserGetMenuObject(MenuItem->hSubMenu);
-         if (SubMenuObject != NULL)
+         SubMenuObject = UserGetMenuObject(lpmii->hSubMenu);
+         if ( SubMenuObject && !(UserObjectInDestroy(lpmii->hSubMenu)) )
          {
-            SubMenuObject->MenuInfo.Flags |= MF_POPUP;
-            MenuItem->fType |= MF_POPUP;
+            //// wine Bug 12171 : Adding Popup Menu to itself! Could create endless loops.
+            //// CORE-7967.
+            if (MenuObject == SubMenuObject)
+            {
+               HANDLE hMenu;
+               ERR("Pop Up Menu Double Trouble!\n");
+               SubMenuObject = IntCreateMenu(&hMenu,
+                   FALSE,
+                   MenuObject->head.rpdesk,
+                   (PPROCESSINFO)MenuObject->head.hTaskWow); // It will be marked.
+               if (!SubMenuObject) return FALSE;
+               IntReleaseMenuObject(SubMenuObject); // This will be referenced again after insertion.
+               circref = TRUE;
+            }
+            if ( MENU_depth( SubMenuObject, 0) > MAXMENUDEPTH )
+            {
+               ERR( "Loop detected in menu hierarchy or maximum menu depth exceeded!\n");
+               if (circref) IntDestroyMenuObject(SubMenuObject, FALSE);
+               return FALSE;
+            }
+            /* Make sure the submenu is marked as a popup menu */
+            SubMenuObject->fFlags |= MNF_POPUP;
+            // Now fix the test_subpopup_locked_by_menu tests....
+            if (MenuItem->spSubMenu) IntReleaseMenuObject(MenuItem->spSubMenu);
+            MenuItem->spSubMenu = SubMenuObject;
+            UserReferenceObject(SubMenuObject);
          }
          else
          {
-            MenuItem->fType &= ~MF_POPUP;
+            EngSetLastError( ERROR_INVALID_PARAMETER);
+            return FALSE;
          }
       }
       else
-      {
-         MenuItem->fType &= ~MF_POPUP;
+      {  // If submenu just dereference it.
+         if (MenuItem->spSubMenu) IntReleaseMenuObject(MenuItem->spSubMenu);
+         MenuItem->spSubMenu = NULL;
       }
    }
 
    if ((lpmii->fMask & MIIM_STRING) ||
       ((lpmii->fMask & MIIM_TYPE) && (MENU_ITEM_TYPE(lpmii->fType) == MF_STRING)))
    {
-      FreeMenuText(MenuItem);
+      /* 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;
 
-         Source.Length =
-            Source.MaximumLength = lpmii->cch * sizeof(WCHAR);
+         Source.Length = Source.MaximumLength = lpmii->cch * sizeof(WCHAR);
          Source.Buffer = lpmii->dwTypeData;
 
-         MenuItem->Text.Buffer = (PWSTR)ExAllocatePoolWithTag(
-                                    PagedPool, Source.Length + sizeof(WCHAR), TAG_STRING);
-         if(MenuItem->Text.Buffer != NULL)
-         {
-            MenuItem->Text.Length = 0;
-            MenuItem->Text.MaximumLength = Source.Length + sizeof(WCHAR);
-            RtlCopyUnicodeString(&MenuItem->Text, &Source);
-            MenuItem->Text.Buffer[MenuItem->Text.Length / sizeof(WCHAR)] = 0;
-         }
-         else
-         {
-            RtlInitUnicodeString(&MenuItem->Text, NULL);
-         }
-      }
-      else
-      {
-         if (0 == (MenuObject->MenuInfo.Flags & MF_SYSMENU))
+         MenuItem->lpstr.Buffer = DesktopHeapAlloc( MenuObject->head.rpdesk, Source.Length + sizeof(WCHAR));
+         if(MenuItem->lpstr.Buffer != NULL)
          {
-            MenuItem->fType |= MF_SEPARATOR;
+            MenuItem->lpstr.Length = 0;
+            MenuItem->lpstr.MaximumLength = Source.Length + sizeof(WCHAR);
+            RtlCopyUnicodeString(&MenuItem->lpstr, &Source);
+            MenuItem->lpstr.Buffer[MenuItem->lpstr.Length / sizeof(WCHAR)] = 0;
+
+            MenuItem->cch = MenuItem->lpstr.Length / sizeof(WCHAR);
+            MenuItem->Xlpstr = (USHORT*)MenuItem->lpstr.Buffer;
          }
-         RtlInitUnicodeString(&MenuItem->Text, NULL);
       }
    }
 
+   if( !(MenuObject->fFlags & MNF_SYSMENU) &&
+       !MenuItem->Xlpstr &&
+       !lpmii->dwTypeData &&
+       !(MenuItem->fType & MFT_OWNERDRAW) &&
+       !MenuItem->hbmp)
+      MenuItem->fType |= MFT_SEPARATOR;
+
    if (sizeof(ROSMENUITEMINFO) == lpmii->cbSize)
    {
-      MenuItem->Rect = lpmii->Rect;
+      MenuItem->xItem  = lpmii->Rect.left; 
+      MenuItem->yItem  = lpmii->Rect.top; 
+      MenuItem->cxItem = lpmii->Rect.right; // Do this for now......
+      MenuItem->cyItem = lpmii->Rect.bottom;
       MenuItem->dxTab = lpmii->dxTab;
-      lpmii->lpstr = MenuItem->Text.Buffer; /* Use DesktopHeap! Send back new allocated string or zero */
+      lpmii->lpstr = MenuItem->lpstr.Buffer; /* Send back new allocated string or zero */
+      MenuItem->cxBmp = lpmii->maxBmpSize.cx;
+      MenuItem->cyBmp = lpmii->maxBmpSize.cy;
    }
 
    return TRUE;
 }
 
-BOOL FASTCALL
-IntInsertMenuItem(
-    _In_ PMENU_OBJECT MenuObject,
-    UINT uItem,
-    BOOL fByPosition,
-    PROSMENUITEMINFO ItemInfo)
+
+UINT FASTCALL
+IntEnableMenuItem(PMENU MenuObject, UINT uIDEnableItem, UINT uEnable)
 {
-   int pos;
-   PMENU_ITEM MenuItem;
-   PMENU_OBJECT SubMenu = NULL;
+   PITEM MenuItem;
+   UINT res;
 
-   NT_ASSERT(MenuObject != NULL);
+   if (!(MenuItem = MENU_FindItem( &MenuObject, &uIDEnableItem, uEnable ))) return (UINT)-1;
 
-   if (MAX_MENU_ITEMS <= MenuObject->MenuInfo.MenuItemCount)
-   {
-      EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
-      return FALSE;
-   }
+   res = MenuItem->fState & (MF_GRAYED | MF_DISABLED);
+
+   MenuItem->fState ^= (res ^ uEnable) & (MF_GRAYED | MF_DISABLED);
 
-   if (fByPosition)
+   /* If the close item in the system menu change update the close button */
+   if((MenuItem->wID == SC_CLOSE) && (res != uEnable))
    {
-      SubMenu = MenuObject;
-      /* calculate position */
-      pos = (int)uItem;
-      if(uItem > MenuObject->MenuInfo.MenuItemCount)
-      {
-         pos = MenuObject->MenuInfo.MenuItemCount;
-      }
-   }
-   else
-   {
-      pos = IntGetMenuItemByFlag(MenuObject, uItem, MF_BYCOMMAND, &SubMenu, NULL, NULL);
-   }
-   if (SubMenu == NULL)
-   {
-       /* Default to last position of menu */
-      SubMenu = MenuObject;
-      pos = MenuObject->MenuInfo.MenuItemCount;
-   }
-
-
-   if (pos < -1)
-   {
-      pos = -1;
-   }
-
-   MenuItem = ExAllocatePoolWithTag(PagedPool, sizeof(MENU_ITEM), TAG_MENUITEM);
-   if (NULL == MenuItem)
-   {
-      EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
-      return FALSE;
-   }
-
-   MenuItem->fType = MFT_STRING;
-   MenuItem->fState = MFS_ENABLED | MFS_UNCHECKED;
-   MenuItem->wID = 0;
-   MenuItem->hSubMenu = (HMENU)0;
-   MenuItem->hbmpChecked = (HBITMAP)0;
-   MenuItem->hbmpUnchecked = (HBITMAP)0;
-   MenuItem->dwItemData = 0;
-   RtlInitUnicodeString(&MenuItem->Text, NULL);
-   MenuItem->hbmpItem = (HBITMAP)0;
-
-   if(!IntSetMenuItemInfo(SubMenu, MenuItem, ItemInfo))
-   {
-      ExFreePoolWithTag(MenuItem, TAG_MENUITEM);
-      return FALSE;
-   }
-
-   /* Force size recalculation! */
-   MenuObject->MenuInfo.Height = 0;
-
-   pos = IntInsertMenuItemToList(SubMenu, MenuItem, pos);
-
-   TRACE("IntInsertMenuItemToList = %i\n", pos);
-
-   return (pos >= 0);
-}
-
-UINT FASTCALL
-IntEnableMenuItem(PMENU_OBJECT MenuObject, UINT uIDEnableItem, UINT uEnable)
-{
-   PMENU_ITEM MenuItem;
-   UINT res = IntGetMenuItemByFlag(MenuObject, uIDEnableItem, uEnable, NULL, &MenuItem, NULL);
-   if(!MenuItem || (res == (UINT)-1))
-   {
-      return (UINT)-1;
-   }
-
-   res = MenuItem->fState & (MF_GRAYED | MF_DISABLED);
+       if (MenuObject->fFlags & MNF_SYSSUBMENU && MenuObject->spwndNotify != 0)
+       {
+            RECTL rc = MenuObject->spwndNotify->rcWindow;
 
-   if(uEnable & MF_DISABLED)
-   {
-      MenuItem->fState |= MF_DISABLED;
-      MenuItem->fState |= uEnable & MF_GRAYED;
-   }
-   else
-   {
-      if(uEnable & MF_GRAYED)
-      {
-         MenuItem->fState |= (MF_GRAYED | MF_DISABLED);
-      }
-      else
-      {
-         MenuItem->fState &= ~(MF_DISABLED | MF_GRAYED);
-      }
+            /* Refresh the frame to reflect the change */
+            IntMapWindowPoints(0, MenuObject->spwndNotify, (POINT *)&rc, 2);
+            rc.bottom = 0;
+            co_UserRedrawWindow(MenuObject->spwndNotify, &rc, 0, RDW_FRAME | RDW_INVALIDATE | RDW_NOCHILDREN);
+       }
    }
-
    return res;
 }
 
-
 DWORD FASTCALL
-IntBuildMenuItemList(PMENU_OBJECT MenuObject, PVOID Buffer, ULONG nMax)
+IntCheckMenuItem(PMENU MenuObject, UINT uIDCheckItem, UINT uCheck)
 {
-   DWORD res = 0;
-   ROSMENUITEMINFO mii;
-   PVOID Buf;
-   PMENU_ITEM CurItem = MenuObject->MenuItemList;
-   PWCHAR StrOut;
-   NTSTATUS Status;
-   WCHAR NulByte;
+   PITEM MenuItem;
+   DWORD res;
 
-   if (0 != nMax)
-   {
-      if (nMax < MenuObject->MenuInfo.MenuItemCount * sizeof(ROSMENUITEMINFO))
-      {
-         return 0;
-      }
-      StrOut = (PWCHAR)((char *) Buffer + MenuObject->MenuInfo.MenuItemCount
-                        * sizeof(ROSMENUITEMINFO));
-      nMax -= MenuObject->MenuInfo.MenuItemCount * sizeof(ROSMENUITEMINFO);
-      Buf = Buffer;
-      mii.cbSize = sizeof(ROSMENUITEMINFO);
-      mii.fMask = 0;
-      NulByte = L'\0';
-
-      while (NULL != CurItem)
-      {
-         mii.cch = CurItem->Text.Length / sizeof(WCHAR);
-         mii.dwItemData = CurItem->dwItemData;
-         if (0 != CurItem->Text.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->hbmpItem;
-         mii.hbmpUnchecked = CurItem->hbmpUnchecked;
-         mii.hSubMenu = CurItem->hSubMenu;
-         mii.Rect = CurItem->Rect;
-         mii.dxTab = CurItem->dxTab;
-         mii.lpstr = CurItem->Text.Buffer; // Use DesktopHeap!
-
-         Status = MmCopyToCaller(Buf, &mii, sizeof(ROSMENUITEMINFO));
-         if (! NT_SUCCESS(Status))
-         {
-            SetLastNtError(Status);
-            return 0;
-         }
-         Buf = (PVOID)((ULONG_PTR)Buf + sizeof(ROSMENUITEMINFO));
+   if (!(MenuItem = MENU_FindItem( &MenuObject, &uIDCheckItem, uCheck ))) return -1;
 
-         if (0 != CurItem->Text.Length
-               && (nMax >= CurItem->Text.Length + sizeof(WCHAR)))
-         {
-            /* Copy string */
-            Status = MmCopyToCaller(StrOut, CurItem->Text.Buffer,
-                                    CurItem->Text.Length);
-            if (! NT_SUCCESS(Status))
-            {
-               SetLastNtError(Status);
-               return 0;
-            }
-            StrOut += CurItem->Text.Length / sizeof(WCHAR);
-            Status = MmCopyToCaller(StrOut, &NulByte, sizeof(WCHAR));
-            if (! NT_SUCCESS(Status))
-            {
-               SetLastNtError(Status);
-               return 0;
-            }
-            StrOut++;
-            nMax -= CurItem->Text.Length + sizeof(WCHAR);
-         }
-         else if (0 != CurItem->Text.Length)
-         {
-            break;
-         }
+   res = (DWORD)(MenuItem->fState & MF_CHECKED);
 
-         CurItem = CurItem->Next;
-         res++;
-      }
-   }
-   else
-   {
-      while (NULL != CurItem)
-      {
-         res += sizeof(ROSMENUITEMINFO) + CurItem->Text.Length + sizeof(WCHAR);
-         CurItem = CurItem->Next;
-      }
-   }
+   MenuItem->fState ^= (res ^ uCheck) & MF_CHECKED;
 
    return res;
 }
 
-
-DWORD FASTCALL
-IntCheckMenuItem(PMENU_OBJECT MenuObject, UINT uIDCheckItem, UINT uCheck)
-{
-   PMENU_ITEM MenuItem;
-   int res = -1;
-
-   if((IntGetMenuItemByFlag(MenuObject, uIDCheckItem, uCheck, NULL, &MenuItem, NULL) < 0) || !MenuItem)
-   {
-      return -1;
-   }
-
-   res = (DWORD)(MenuItem->fState & MF_CHECKED);
-   if(uCheck & MF_CHECKED)
-   {
-      MenuItem->fState |= MF_CHECKED;
-   }
-   else
-   {
-      MenuItem->fState &= ~MF_CHECKED;
-   }
-
-   return (DWORD)res;
-}
-
 BOOL FASTCALL
-IntHiliteMenuItem(PWND WindowObject, PMENU_OBJECT MenuObject,
-                  UINT uItemHilite, UINT uHilite)
+IntHiliteMenuItem(PWND WindowObject,
+                  PMENU MenuObject,
+                  UINT uItemHilite,
+                  UINT uHilite)
 {
-   PMENU_ITEM MenuItem;
-   BOOL res = IntGetMenuItemByFlag(MenuObject, uItemHilite, uHilite, NULL, &MenuItem, NULL);
-   if(!MenuItem || !res)
-   {
-      return FALSE;
-   }
+   PITEM MenuItem;
 
-   if(uHilite & MF_HILITE)
+   if (!(MenuItem = MENU_FindItem( &MenuObject, &uItemHilite, uHilite ))) return FALSE;
+
+   if (uHilite & MF_HILITE)
    {
       MenuItem->fState |= MF_HILITE;
    }
@@ -1056,117 +1014,87 @@ IntHiliteMenuItem(PWND WindowObject, PMENU_OBJECT MenuObject,
    {
       MenuItem->fState &= ~MF_HILITE;
    }
-
    /* FIXME: Update the window's menu */
 
-   return TRUE;
+   return TRUE; // Always returns true!!!!
 }
 
 BOOL FASTCALL
-UserSetMenuDefaultItem(PMENU_OBJECT MenuObject, UINT uItem, UINT fByPos)
+UserSetMenuDefaultItem(PMENU MenuObject, UINT uItem, UINT fByPos)
 {
-   BOOL ret = FALSE;
-   PMENU_ITEM MenuItem = MenuObject->MenuItemList;
+   UINT i;
+   PITEM MenuItem = MenuObject->rgItems;
+
+   if (!MenuItem) return FALSE;   
+
+   /* reset all default-item flags */
+   for (i = 0; MenuItem, i < MenuObject->cItems; i++, MenuItem++)
+   {
+       MenuItem->fState &= ~MFS_DEFAULT;
+   }
 
+   /* no default item */
    if(uItem == (UINT)-1)
    {
-      while(MenuItem)
-      {
-         MenuItem->fState &= ~MFS_DEFAULT;
-         MenuItem = MenuItem->Next;
-      }
       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_OBJECT MenuObject, UINT fByPos, UINT gmdiFlags,
-                      DWORD *gismc)
+IntGetMenuDefaultItem(PMENU MenuObject, UINT fByPos, UINT gmdiFlags, DWORD *gismc)
 {
-   UINT x = 0;
-   UINT res = -1;
-   UINT sres;
-   PMENU_OBJECT SubMenuObject;
-   PMENU_ITEM MenuItem = MenuObject->MenuItemList;
-
-   while(MenuItem)
-   {
-      if(MenuItem->fState & MFS_DEFAULT)
-      {
-
-         if(!(gmdiFlags & GMDI_USEDISABLED) && (MenuItem->fState & MFS_DISABLED))
-            break;
+   UINT i = 0;
+   PITEM MenuItem = MenuObject->rgItems;
 
-         if(fByPos)
-            res = x;
-         else
-            res = MenuItem->wID;
-
-         if((*gismc < MAX_GOINTOSUBMENU) && (gmdiFlags & GMDI_GOINTOPOPUPS) &&
-               MenuItem->hSubMenu)
-         {
-
-            SubMenuObject = UserGetMenuObject(MenuItem->hSubMenu);
-            if(!SubMenuObject || (SubMenuObject == MenuObject))
-               break;
+   /* empty menu */
+   if (!MenuItem) return -1;
 
-            (*gismc)++;
-            sres = IntGetMenuDefaultItem(SubMenuObject, 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
-co_IntInitTracking(PWND Window, PMENU_OBJECT Menu, BOOL Popup,
+co_IntInitTracking(PWND Window, PMENU Menu, BOOL Popup,
                    UINT Flags)
 {
    /* FIXME: Hide caret */
@@ -1177,11 +1105,11 @@ co_IntInitTracking(PWND Window, PMENU_OBJECT Menu, BOOL Popup,
    /* FIXME: Send WM_SETCURSOR message */
 
    if(!(Flags & TPM_NONOTIFY))
-      co_IntSendMessage(Window->head.h, WM_INITMENU, (WPARAM)Menu->MenuInfo.Self, 0);
+      co_IntSendMessage(Window->head.h, WM_INITMENU, (WPARAM)Menu->head.h, 0);
 }
 
 VOID FASTCALL
-co_IntExitTracking(PWND Window, PMENU_OBJECT Menu, BOOL Popup,
+co_IntExitTracking(PWND Window, PMENU Menu, BOOL Popup,
                    UINT Flags)
 {
    if(!(Flags & TPM_NONOTIFY))
@@ -1191,14 +1119,14 @@ co_IntExitTracking(PWND Window, PMENU_OBJECT Menu, BOOL Popup,
 }
 
 INT FASTCALL
-IntTrackMenu(PMENU_OBJECT Menu, PWND Window, INT x, INT y,
+IntTrackMenu(PMENU Menu, PWND Window, INT x, INT y,
              RECTL lprect)
 {
    return 0;
 }
 
 BOOL FASTCALL
-co_IntTrackPopupMenu(PMENU_OBJECT Menu, PWND Window,
+co_IntTrackPopupMenu(PMENU Menu, PWND Window,
                      UINT Flags, POINT *Pos, UINT MenuPos, RECTL *ExcludeRect)
 {
    co_IntInitTracking(Window, Menu, TRUE, Flags);
@@ -1207,39 +1135,6 @@ co_IntTrackPopupMenu(PMENU_OBJECT Menu, PWND Window,
    return FALSE;
 }
 
-
-/*!
- * Internal function. Called when the process is destroyed to free the remaining menu handles.
-*/
-BOOL FASTCALL
-IntCleanupMenus(struct _EPROCESS *Process, PPROCESSINFO Win32Process)
-{
-   PEPROCESS CurrentProcess;
-   PLIST_ENTRY LastHead = NULL;
-   PMENU_OBJECT MenuObject;
-
-   CurrentProcess = PsGetCurrentProcess();
-   if (CurrentProcess != Process)
-   {
-      KeAttachProcess(&Process->Pcb);
-   }
-
-   while (Win32Process->MenuListHead.Flink != &(Win32Process->MenuListHead) &&
-          Win32Process->MenuListHead.Flink != LastHead)
-   {
-      LastHead = Win32Process->MenuListHead.Flink;
-      MenuObject = CONTAINING_RECORD(Win32Process->MenuListHead.Flink, MENU_OBJECT, ListEntry);
-
-      IntDestroyMenuObject(MenuObject, FALSE, TRUE);
-   }
-
-   if (CurrentProcess != Process)
-   {
-      KeDetachProcess();
-   }
-   return TRUE;
-}
-
 BOOLEAN APIENTRY
 intGetTitleBarInfo(PWND pWindowObject, PTITLEBARINFO bti)
 {
@@ -1373,10 +1268,11 @@ intGetTitleBarInfo(PWND pWindowObject, PTITLEBARINFO bti)
 
 DWORD FASTCALL
 UserInsertMenuItem(
-   PMENU_OBJECT Menu,
+   PMENU Menu,
    UINT uItem,
    BOOL fByPosition,
-   LPCMENUITEMINFOW UnsafeItemInfo)
+   LPCMENUITEMINFOW UnsafeItemInfo,
+   PUNICODE_STRING lpstr)
 {
    NTSTATUS Status;
    ROSMENUITEMINFO ItemInfo;
@@ -1391,7 +1287,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) */
@@ -1404,7 +1300,7 @@ UserInsertMenuItem(
          return FALSE;
       }
       ItemInfo.hbmpItem = (HBITMAP)0;
-      return IntInsertMenuItem(Menu, uItem, fByPosition, &ItemInfo);
+      return IntInsertMenuItem(Menu, uItem, fByPosition, &ItemInfo, lpstr);
    }
 
    SetLastNtError(Status);
@@ -1413,117 +1309,87 @@ UserInsertMenuItem(
 
 UINT FASTCALL IntGetMenuState( HMENU hMenu, UINT uId, UINT uFlags)
 {
-   PMENU_OBJECT MenuObject, SubMenu;
-   PMENU_ITEM mi;
+   PMENU MenuObject;
+   PITEM pItem;
 
    if (!(MenuObject = UserGetMenuObject(hMenu)))
    {
       return (UINT)-1;
    }
 
-   if (IntGetMenuItemByFlag(MenuObject, uId, uFlags, &SubMenu, &mi, NULL))
+   if (!(pItem = MENU_FindItem( &MenuObject, &uId, uFlags ))) return -1;
+
+   if (pItem->spSubMenu)
    {
-      if (mi->hSubMenu)
-      {
-         if (SubMenu)
-         {
-            UINT nSubItems = SubMenu->MenuInfo.MenuItemCount;
-            return (nSubItems << 8) | ((mi->fState | mi->fType) & 0xff);
-         }
-         else
-            return (UINT)-1;
-      }
-      return (mi->fType | mi->fState);
+      return (pItem->spSubMenu->cItems << 8) | ((pItem->fState|pItem->fType) & 0xff);
    }
-   return (UINT)-1;
+   else
+      return (pItem->fType | pItem->fState);  
 }
 
 HMENU FASTCALL IntGetSubMenu( HMENU hMenu, int nPos)
 {
-   PMENU_OBJECT MenuObject, SubMenu;
+   PMENU MenuObject;
+   PITEM pItem;
 
    if (!(MenuObject = UserGetMenuObject(hMenu)))
    {
       return NULL;
    }
-   if (IntGetMenuItemByFlag(MenuObject, nPos, MF_BYPOSITION, &SubMenu, NULL, NULL))
+
+   if (!(pItem = MENU_FindItem( &MenuObject, (UINT*)&nPos, MF_BYPOSITION ))) return NULL;
+
+   if (pItem->spSubMenu)
    {
-      return SubMenu ? UserHMGetHandle(SubMenu) : NULL;
+      HMENU hsubmenu = UserHMGetHandle(pItem->spSubMenu);
+      return hsubmenu;
    }
    return NULL;
 }
 
 UINT FASTCALL IntFindSubMenu(HMENU *hMenu, HMENU hSubTarget )
 {
-   PMENU_OBJECT MenuObject;
-   PMENU_ITEM mi;
-   UINT i;
-
-   if ( (*hMenu) == (HMENU)0xffff || !(MenuObject = UserGetMenuObject(*hMenu)) )
-      return NO_SELECTED_ITEM;
+    PMENU menu;
+    HMENU hSubMenu;
+    UINT i;
+    PITEM item;
 
-   for (i = 0; i < MenuObject->MenuInfo.MenuItemCount; i++)
-   {
-       if (!IntGetMenuItemByFlag(MenuObject, i, MF_BYPOSITION, NULL, &mi, NULL))
-       {
-          return NO_SELECTED_ITEM;
-       }
-
-       if (!(mi->fType & MF_POPUP)) continue;
+    if (((*hMenu)==(HMENU)0xffff) ||(!(menu = UserGetMenuObject(*hMenu))))
+        return NO_SELECTED_ITEM;
 
-       if (mi->hSubMenu == hSubTarget)
-       {
-          return i;
-       }
-       else
-       {
-          HMENU hsubmenu = mi->hSubMenu;
-          UINT pos = IntFindSubMenu(&hsubmenu, hSubTarget );
-          if (pos != NO_SELECTED_ITEM)
-          {
-             *hMenu = hsubmenu;
-             return pos;
-          }
-       }
-   }
-   return NO_SELECTED_ITEM;
+    item = menu->rgItems;
+    for (i = 0; i < menu->cItems; i++, item++)
+    {
+        if (!item->spSubMenu)
+           continue;
+        else
+        {
+           hSubMenu = UserHMGetHandle(item->spSubMenu);
+           if (hSubMenu == hSubTarget)
+           {
+              return i;
+           }
+           else 
+           {
+              HMENU hsubmenu = hSubMenu;
+              UINT pos = IntFindSubMenu( &hsubmenu, hSubTarget );
+              if (pos != NO_SELECTED_ITEM)
+              {
+                  *hMenu = hsubmenu;
+                  return pos;
+              }
+           }
+        }
+    }
+    return NO_SELECTED_ITEM;
 }
 
-/* FUNCTIONS *****************************************************************/
-
-/*
- * @implemented
- */
-DWORD APIENTRY
-NtUserCheckMenuItem(
-   HMENU hMenu,
-   UINT uIDCheckItem,
-   UINT uCheck)
-{
-   PMENU_OBJECT Menu;
-   DECLARE_RETURN(DWORD);
-
-   TRACE("Enter NtUserCheckMenuItem\n");
-   UserEnterExclusive();
-
-   if(!(Menu = UserGetMenuObject(hMenu)))
-   {
-      RETURN( (DWORD)-1);
-   }
-
-   RETURN( IntCheckMenuItem(Menu, uIDCheckItem, uCheck));
-
-CLEANUP:
-   TRACE("Leave NtUserCheckMenuItem, ret=%i\n",_ret_);
-   UserLeave();
-   END_CLEANUP;
-}
 
-HMENU FASTCALL UserCreateMenu(BOOL PopupMenu)
+HMENU FASTCALL UserCreateMenu(PDESKTOP Desktop, BOOL PopupMenu)
 {
    PWINSTATION_OBJECT WinStaObject;
    HANDLE Handle;
-   PMENU_OBJECT Menu;
+   PMENU Menu;
    NTSTATUS Status;
    PEPROCESS CurrentProcess = PsGetCurrentProcess();
 
@@ -1540,57 +1406,582 @@ HMENU FASTCALL UserCreateMenu(BOOL PopupMenu)
 
        if (!NT_SUCCESS(Status))
        {
-          ERR("Validation of window station handle (0x%X) failed\n",
-             CurrentProcess->Win32WindowStation);
+          ERR("Validation of window station handle (%p) failed\n",
+              CurrentProcess->Win32WindowStation);
           SetLastNtError(Status);
           return (HMENU)0;
        }
-       Menu = IntCreateMenu(&Handle, !PopupMenu);
+       Menu = IntCreateMenu(&Handle, !PopupMenu, Desktop, GetW32ProcessInfo());
+       if (Menu && Menu->head.rpdesk->rpwinstaParent != WinStaObject)
+       {
+          ERR("Desktop Window Station does not match Process one!\n");
+       }
        ObDereferenceObject(WinStaObject);
    }
    else
    {
-       Menu = IntCreateMenu(&Handle, !PopupMenu);
+       Menu = IntCreateMenu(&Handle, !PopupMenu, GetW32ThreadInfo()->rpdesk, GetW32ProcessInfo());
    }
 
    if (Menu) UserDereferenceObject(Menu);
    return (HMENU)Handle;
 }
 
-/*
- * @implemented
- */
-BOOL APIENTRY
-NtUserDeleteMenu(
-   HMENU hMenu,
-   UINT uPosition,
-   UINT uFlags)
+BOOL FASTCALL
+IntMenuItemInfo(
+   PMENU Menu,
+   UINT Item,
+   BOOL ByPosition,
+   PROSMENUITEMINFO ItemInfo,
+   BOOL SetOrGet,
+   PUNICODE_STRING lpstr)
 {
-   PMENU_OBJECT Menu;
-   DECLARE_RETURN(BOOL);
-
-   TRACE("Enter NtUserDeleteMenu\n");
-   UserEnterExclusive();
+   PITEM MenuItem;
+   BOOL Ret;
 
-   if(!(Menu = UserGetMenuObject(hMenu)))
+   if (!(MenuItem = MENU_FindItem( &Menu, &Item, (ByPosition ? MF_BYPOSITION : MF_BYCOMMAND) )))
    {
-      RETURN( FALSE);
+      EngSetLastError(ERROR_MENU_ITEM_NOT_FOUND);
+      return( FALSE);
    }
-
-   RETURN( IntRemoveMenuItem(Menu, uPosition, uFlags, TRUE));
-
-CLEANUP:
-   TRACE("Leave NtUserDeleteMenu, ret=%i\n",_ret_);
-   UserLeave();
-   END_CLEANUP;
+   if (SetOrGet)
+   {
+      Ret = IntSetMenuItemInfo(Menu, MenuItem, ItemInfo, lpstr);
+   }
+   else
+   {
+      Ret = IntGetMenuItemInfo(Menu, MenuItem, ItemInfo);
+   }
+   return( Ret);
 }
 
-/*
- * @implemented
- */
-BOOLEAN APIENTRY
-NtUserGetTitleBarInfo(
-    HWND hwnd,
+BOOL FASTCALL
+UserMenuItemInfo(
+   PMENU Menu,
+   UINT Item,
+   BOOL ByPosition,
+   PROSMENUITEMINFO UnsafeItemInfo,
+   BOOL SetOrGet,
+   PUNICODE_STRING lpstr)
+{
+   PITEM MenuItem;
+   ROSMENUITEMINFO ItemInfo;
+   NTSTATUS Status;
+   UINT Size;
+   BOOL Ret;
+
+   Status = MmCopyFromCaller(&Size, &UnsafeItemInfo->cbSize, sizeof(UINT));
+   if (! NT_SUCCESS(Status))
+   {
+      SetLastNtError(Status);
+      return( FALSE);
+   }
+   if (sizeof(MENUITEMINFOW) != Size
+         && FIELD_OFFSET(MENUITEMINFOW, hbmpItem) != Size
+         && sizeof(ROSMENUITEMINFO) != Size)
+   {
+      EngSetLastError(ERROR_INVALID_PARAMETER);
+      return( FALSE);
+   }
+   Status = MmCopyFromCaller(&ItemInfo, UnsafeItemInfo, Size);
+   if (! NT_SUCCESS(Status))
+   {
+      SetLastNtError(Status);
+      return( FALSE);
+   }
+   /* If this is a pre-0x0500 _WIN32_WINNT MENUITEMINFOW, you can't
+      set/get hbmpItem */
+   if (FIELD_OFFSET(MENUITEMINFOW, hbmpItem) == Size
+         && 0 != (ItemInfo.fMask & MIIM_BITMAP))
+   {
+      EngSetLastError(ERROR_INVALID_PARAMETER);
+      return( FALSE);
+   }
+
+   if (!(MenuItem = MENU_FindItem( &Menu, &Item, (ByPosition ? MF_BYPOSITION : MF_BYCOMMAND) )))
+   {
+      EngSetLastError(ERROR_MENU_ITEM_NOT_FOUND);
+      return( FALSE);
+   }
+
+   if (SetOrGet)
+   {
+      Ret = IntSetMenuItemInfo(Menu, MenuItem, &ItemInfo, lpstr);
+   }
+   else
+   {
+      Ret = IntGetMenuItemInfo(Menu, MenuItem, &ItemInfo);
+      if (Ret)
+      {
+         Status = MmCopyToCaller(UnsafeItemInfo, &ItemInfo, Size);
+         if (! NT_SUCCESS(Status))
+         {
+            SetLastNtError(Status);
+            return( FALSE);
+         }
+      }
+   }
+
+   return( Ret);
+}
+
+BOOL FASTCALL
+UserMenuInfo(
+   PMENU Menu,
+   PROSMENUINFO UnsafeMenuInfo,
+   BOOL SetOrGet)
+{
+   BOOL Res;
+   DWORD Size;
+   NTSTATUS Status;
+   ROSMENUINFO MenuInfo;
+
+   Status = MmCopyFromCaller(&Size, &UnsafeMenuInfo->cbSize, sizeof(DWORD));
+   if (! NT_SUCCESS(Status))
+   {
+      SetLastNtError(Status);
+      return( FALSE);
+   }
+   if(Size < sizeof(MENUINFO) || sizeof(ROSMENUINFO) < Size)
+   {
+      EngSetLastError(ERROR_INVALID_PARAMETER);
+      return( FALSE);
+   }
+   Status = MmCopyFromCaller(&MenuInfo, UnsafeMenuInfo, Size);
+   if (! NT_SUCCESS(Status))
+   {
+      SetLastNtError(Status);
+      return( FALSE);
+   }
+
+   if(SetOrGet)
+   {
+      /* Set MenuInfo */
+      Res = IntSetMenuInfo(Menu, &MenuInfo);
+   }
+   else
+   {
+      /* Get MenuInfo */
+      Res = IntGetMenuInfo(Menu, &MenuInfo);
+      if (Res)
+      {
+         Status = MmCopyToCaller(UnsafeMenuInfo, &MenuInfo, Size);
+         if (! NT_SUCCESS(Status))
+         {
+            SetLastNtError(Status);
+            return( FALSE);
+         }
+      }
+   }
+
+   return( Res);
+}
+
+VOID FASTCALL
+MENU_AdjustMenuItemRect(PMENU menu, PRECTL rect)
+{
+    if (menu->dwArrowsOn)
+    {
+        UINT arrow_bitmap_height;
+        //BITMAP bmp;
+        //GetObjectW(get_up_arrow_bitmap(), sizeof(bmp), &bmp);
+        arrow_bitmap_height = gpsi->oembmi[65].cy; ///// Menu up arrow! OBM_UPARROW DFCS_MENUARROWUP
+        //arrow_bitmap_height = bmp.bmHeight;
+        rect->top += arrow_bitmap_height - menu->iTop;
+        rect->bottom += arrow_bitmap_height - menu->iTop;
+    }
+}
+
+BOOL FASTCALL
+IntGetMenuItemRect(
+   PWND pWnd,
+   PMENU Menu,
+   UINT uItem,
+   PRECTL Rect)
+{
+   LONG XMove, YMove;
+   PITEM MenuItem;
+
+   if (!pWnd)
+   {
+      HWND hWnd = Menu->hWnd;
+      if (!(pWnd = UserGetWindowObject(hWnd))) return FALSE;
+   }
+
+   if ((MenuItem = MENU_FindItem (&Menu, &uItem, MF_BYPOSITION)))
+   {
+      Rect->left   = MenuItem->xItem; 
+      Rect->top    = MenuItem->yItem; 
+      Rect->right  = MenuItem->cxItem; // Do this for now......
+      Rect->bottom = MenuItem->cyItem;
+   }
+   else
+   {
+      ERR("Failed Item Lookup! %d\n", uItem);
+      return FALSE;
+   }
+
+   if (Menu->fFlags & MNF_POPUP)
+   {
+     XMove = pWnd->rcClient.left;
+     YMove = pWnd->rcClient.top;
+   }
+   else
+   {
+     XMove = pWnd->rcWindow.left;
+     YMove = pWnd->rcWindow.top;
+   }
+
+   Rect->left   += XMove;
+   Rect->top    += YMove;
+   Rect->right  += XMove;
+   Rect->bottom += YMove;
+
+   return TRUE;
+}
+
+PMENU FASTCALL MENU_GetSystemMenu(PWND Window, PMENU Popup)
+{
+   PMENU Menu, NewMenu = NULL, SysMenu = NULL;
+   HMENU hSysMenu, hNewMenu = NULL;
+   ROSMENUITEMINFO ItemInfoSet = {0};
+   ROSMENUITEMINFO ItemInfo = {0};
+   UNICODE_STRING MenuName;
+
+   hSysMenu = UserCreateMenu(Window->head.rpdesk, FALSE);
+   if (NULL == hSysMenu)
+   {
+      return NULL;
+   }
+   SysMenu = UserGetMenuObject(hSysMenu);
+   if (NULL == SysMenu)
+   {
+       UserDestroyMenu(hSysMenu);
+       return NULL;
+   }
+   
+   SysMenu->fFlags |= MNF_SYSMENU;
+   SysMenu->hWnd = Window->head.h;
+
+   if (!Popup)
+   {
+      //hNewMenu = co_IntLoadSysMenuTemplate();
+      if ( Window->ExStyle & WS_EX_MDICHILD )
+      {
+         RtlInitUnicodeString( &MenuName, L"SYSMENUMDI");
+         hNewMenu = co_IntCallLoadMenu( hModClient, &MenuName);
+      }
+      else
+      {
+         RtlInitUnicodeString( &MenuName, L"SYSMENU");
+         hNewMenu = co_IntCallLoadMenu( hModClient, &MenuName);
+         //ERR("%wZ\n",&MenuName);
+      }
+      if (!hNewMenu)
+      {
+         ERR("No Menu!!\n");
+         IntReleaseMenuObject(SysMenu);
+         UserDestroyMenu(hSysMenu);
+         return NULL;
+      }
+      Menu = UserGetMenuObject(hNewMenu);
+      if (!Menu)
+      {
+         IntReleaseMenuObject(SysMenu);
+         UserDestroyMenu(hSysMenu);
+         return NULL;
+      }
+
+      // Do the rest in here.
+
+      Menu->fFlags |= MNS_CHECKORBMP | MNF_SYSMENU  | MNF_POPUP;
+
+      ItemInfoSet.cbSize = sizeof( MENUITEMINFOW);
+      ItemInfoSet.fMask = MIIM_BITMAP;
+      ItemInfoSet.hbmpItem = HBMMENU_POPUP_CLOSE;
+      IntMenuItemInfo(Menu, SC_CLOSE, FALSE, &ItemInfoSet, TRUE, NULL);
+      ItemInfoSet.hbmpItem = HBMMENU_POPUP_RESTORE;
+      IntMenuItemInfo(Menu, SC_RESTORE, FALSE, &ItemInfoSet, TRUE, NULL);
+      ItemInfoSet.hbmpItem = HBMMENU_POPUP_MAXIMIZE;
+      IntMenuItemInfo(Menu, SC_MAXIMIZE, FALSE, &ItemInfoSet, TRUE, NULL);
+      ItemInfoSet.hbmpItem = HBMMENU_POPUP_MINIMIZE;
+      IntMenuItemInfo(Menu, SC_MINIMIZE, FALSE, &ItemInfoSet, TRUE, NULL);
+
+      NewMenu = IntCloneMenu(Menu);
+
+      IntReleaseMenuObject(NewMenu);
+      UserSetMenuDefaultItem(NewMenu, SC_CLOSE, FALSE);
+
+      IntDestroyMenuObject(Menu, FALSE);
+   }
+   else
+   {
+      NewMenu = Popup;
+   }
+   if (NewMenu)
+   {
+      NewMenu->fFlags |= MNF_SYSMENU | MNF_POPUP;
+
+      if (Window->pcls->style & CS_NOCLOSE)
+         IntRemoveMenuItem(NewMenu, SC_CLOSE, MF_BYCOMMAND, TRUE);
+
+      ItemInfo.cbSize = sizeof(MENUITEMINFOW);
+      ItemInfo.fMask = MIIM_FTYPE | MIIM_STRING | MIIM_STATE | MIIM_SUBMENU;
+      ItemInfo.fType = 0;
+      ItemInfo.fState = MFS_ENABLED;
+      ItemInfo.dwTypeData = NULL;
+      ItemInfo.cch = 0;
+      ItemInfo.hSubMenu = UserHMGetHandle(NewMenu);
+      IntInsertMenuItem(SysMenu, (UINT) -1, TRUE, &ItemInfo, NULL);
+
+      return SysMenu;
+   }
+   ERR("failed to load system menu!\n");
+   return NULL;
+}
+
+PMENU FASTCALL
+IntGetSystemMenu(PWND Window, BOOL bRevert)
+{
+   PMENU Menu;
+
+   if (bRevert)
+   {
+      if (Window->SystemMenu)
+      {
+         Menu = UserGetMenuObject(Window->SystemMenu);
+         if (Menu && !(Menu->fFlags & MNF_SYSDESKMN))
+         {
+            IntDestroyMenuObject(Menu, TRUE);
+            Window->SystemMenu = NULL;
+         }
+      }
+   }
+   else
+   {
+      Menu = Window->SystemMenu ? UserGetMenuObject(Window->SystemMenu) : NULL;
+      if ((!Window->SystemMenu || Menu->fFlags & MNF_SYSDESKMN) && Window->style & WS_SYSMENU)
+      {
+         Menu = MENU_GetSystemMenu(Window, NULL);
+         Window->SystemMenu = Menu ? UserHMGetHandle(Menu) : NULL;
+      }
+   }
+
+   if (Window->SystemMenu)
+   {
+      HMENU hMenu = IntGetSubMenu( Window->SystemMenu, 0);
+      /* Store the dummy sysmenu handle to facilitate the refresh */
+      /* of the close button if the SC_CLOSE item change */
+      Menu = UserGetMenuObject(hMenu);
+      if (Menu)
+      {
+         Menu->spwndNotify = Window;
+         Menu->fFlags |= MNF_SYSSUBMENU;
+      }
+      return Menu;
+   }
+   return NULL;
+}
+
+BOOL FASTCALL
+IntSetSystemMenu(PWND Window, PMENU Menu)
+{
+   PMENU OldMenu;
+
+   if (!(Window->style & WS_SYSMENU)) return FALSE;
+
+   if (Window->SystemMenu)
+   {
+      OldMenu = UserGetMenuObject(Window->SystemMenu);
+      if (OldMenu)
+      {
+          OldMenu->fFlags &= ~MNF_SYSMENU;
+         IntDestroyMenuObject(OldMenu, TRUE);
+      }
+   }
+
+   OldMenu = MENU_GetSystemMenu(Window, Menu);
+   if (OldMenu)
+   {  // Use spmenuSys too!
+      Window->SystemMenu = UserHMGetHandle(OldMenu);
+   }
+   else
+      Window->SystemMenu = NULL;
+
+   if (Menu && Window != Menu->spwndNotify)
+   {
+      Menu->spwndNotify = Window;
+   } 
+
+   return TRUE;
+}
+
+
+/* FUNCTIONS *****************************************************************/
+
+/*
+ * @implemented
+ */
+DWORD APIENTRY
+NtUserCheckMenuItem(
+   HMENU hMenu,
+   UINT uIDCheckItem,
+   UINT uCheck)
+{
+   PMENU Menu;
+   DECLARE_RETURN(DWORD);
+
+   TRACE("Enter NtUserCheckMenuItem\n");
+   UserEnterExclusive();
+
+   if(!(Menu = UserGetMenuObject(hMenu)))
+   {
+      RETURN( (DWORD)-1);
+   }
+
+   RETURN( IntCheckMenuItem(Menu, uIDCheckItem, uCheck));
+
+CLEANUP:
+   TRACE("Leave NtUserCheckMenuItem, ret=%lu\n",_ret_);
+   UserLeave();
+   END_CLEANUP;
+}
+
+/*
+ * @implemented
+ */
+BOOL APIENTRY
+NtUserDeleteMenu(
+   HMENU hMenu,
+   UINT uPosition,
+   UINT uFlags)
+{
+   PMENU Menu;
+   DECLARE_RETURN(BOOL);
+
+   TRACE("Enter NtUserDeleteMenu\n");
+   UserEnterExclusive();
+
+   if(!(Menu = UserGetMenuObject(hMenu)))
+   {
+      RETURN( FALSE);
+   }
+
+   RETURN( IntRemoveMenuItem(Menu, uPosition, uFlags, TRUE));
+
+CLEANUP:
+   TRACE("Leave NtUserDeleteMenu, ret=%i\n",_ret_);
+   UserLeave();
+   END_CLEANUP;
+}
+
+/*
+ * NtUserGetSystemMenu
+ *
+ * The NtUserGetSystemMenu function allows the application to access the
+ * window menu (also known as the system menu or the control menu) for
+ * copying and modifying.
+ *
+ * Parameters
+ *    hWnd
+ *       Handle to the window that will own a copy of the window menu.
+ *    bRevert
+ *       Specifies the action to be taken. If this parameter is FALSE,
+ *       NtUserGetSystemMenu returns a handle to the copy of the window menu
+ *       currently in use. The copy is initially identical to the window menu
+ *       but it can be modified.
+ *       If this parameter is TRUE, GetSystemMenu resets the window menu back
+ *       to the default state. The previous window menu, if any, is destroyed.
+ *
+ * Return Value
+ *    If the bRevert parameter is FALSE, the return value is a handle to a
+ *    copy of the window menu. If the bRevert parameter is TRUE, the return
+ *    value is NULL.
+ *
+ * Status
+ *    @implemented
+ */
+
+HMENU APIENTRY
+NtUserGetSystemMenu(HWND hWnd, BOOL bRevert)
+{
+   PWND Window;
+   PMENU Menu;
+   DECLARE_RETURN(HMENU);
+
+   TRACE("Enter NtUserGetSystemMenu\n");
+   UserEnterShared();
+
+   if (!(Window = UserGetWindowObject(hWnd)))
+   {
+      RETURN(NULL);
+   }
+
+   if (!(Menu = IntGetSystemMenu(Window, bRevert)))
+   {
+      RETURN(NULL);
+   }
+
+   RETURN(Menu->head.h);
+
+CLEANUP:
+   TRACE("Leave NtUserGetSystemMenu, ret=%p\n", _ret_);
+   UserLeave();
+   END_CLEANUP;
+}
+
+/*
+ * NtUserSetSystemMenu
+ *
+ * Status
+ *    @implemented
+ */
+
+BOOL APIENTRY
+NtUserSetSystemMenu(HWND hWnd, HMENU hMenu)
+{
+   BOOL Result = FALSE;
+   PWND Window;
+   PMENU Menu;
+   DECLARE_RETURN(BOOL);
+
+   TRACE("Enter NtUserSetSystemMenu\n");
+   UserEnterExclusive();
+
+   if (!(Window = UserGetWindowObject(hWnd)))
+   {
+      RETURN( FALSE);
+   }
+
+   if (hMenu)
+   {
+      /*
+       * Assign new menu handle and Up the Lock Count.
+       */
+      if (!(Menu = IntGetMenuObject(hMenu)))
+      {
+         RETURN( FALSE);
+      }
+
+      Result = IntSetSystemMenu(Window, Menu);
+   }
+   else
+      EngSetLastError(ERROR_INVALID_MENU_HANDLE);
+
+   RETURN( Result);
+
+CLEANUP:
+   TRACE("Leave NtUserSetSystemMenu, ret=%i\n",_ret_);
+   UserLeave();
+   END_CLEANUP;
+}
+
+/*
+ * @implemented
+ */
+BOOLEAN APIENTRY
+NtUserGetTitleBarInfo(
+    HWND hwnd,
     PTITLEBARINFO bti)
 {
     PWND WindowObject;
@@ -1647,7 +2038,7 @@ NtUserGetTitleBarInfo(
     RETURN( retValue );
 
 CLEANUP:
-    TRACE("Leave NtUserGetTitleBarInfo, ret=%i\n",_ret_);
+    TRACE("Leave NtUserGetTitleBarInfo, ret=%u\n",_ret_);
     UserLeave();
     END_CLEANUP;
 }
@@ -1657,20 +2048,20 @@ CLEANUP:
  */
 BOOL FASTCALL UserDestroyMenu(HMENU hMenu)
 {
-   PMENU_OBJECT Menu;
+   PMENU Menu;
+   PTHREADINFO pti = PsGetCurrentThreadWin32Thread();
 
    if(!(Menu = UserGetMenuObject(hMenu)))
    {
       return FALSE;
    }
 
-   if(Menu->Process != PsGetCurrentProcess())
+   if (Menu->head.rpdesk != pti->rpdesk)
    {
       EngSetLastError(ERROR_ACCESS_DENIED);
       return FALSE;
    }
-
-   return IntDestroyMenuObject(Menu, FALSE, TRUE);
+   return IntDestroyMenuObject(Menu, FALSE);
 }
 
 /*
@@ -1680,7 +2071,7 @@ BOOL APIENTRY
 NtUserDestroyMenu(
    HMENU hMenu)
 {
-   PMENU_OBJECT Menu;
+   PMENU Menu;
    DECLARE_RETURN(BOOL);
 
    TRACE("Enter NtUserDestroyMenu\n");
@@ -1690,14 +2081,12 @@ NtUserDestroyMenu(
    {
       RETURN( FALSE);
    }
-
-   if(Menu->Process != PsGetCurrentProcess())
+   if (Menu->head.rpdesk != gptiCurrent->rpdesk)
    {
       EngSetLastError(ERROR_ACCESS_DENIED);
       RETURN( FALSE);
    }
-
-   RETURN( IntDestroyMenuObject(Menu, TRUE, TRUE));
+   RETURN( IntDestroyMenuObject(Menu, TRUE));
 
 CLEANUP:
    TRACE("Leave NtUserDestroyMenu, ret=%i\n",_ret_);
@@ -1714,7 +2103,7 @@ NtUserEnableMenuItem(
    UINT uIDEnableItem,
    UINT uEnable)
 {
-   PMENU_OBJECT Menu;
+   PMENU Menu;
    DECLARE_RETURN(UINT);
 
    TRACE("Enter NtUserEnableMenuItem\n");
@@ -1728,7 +2117,7 @@ NtUserEnableMenuItem(
    RETURN( IntEnableMenuItem(Menu, uIDEnableItem, uEnable));
 
 CLEANUP:
-   TRACE("Leave NtUserEnableMenuItem, ret=%i\n",_ret_);
+   TRACE("Leave NtUserEnableMenuItem, ret=%u\n",_ret_);
    UserLeave();
    END_CLEANUP;
 }
@@ -1743,219 +2132,125 @@ NtUserGetMenuBarInfo(
    LONG idItem,
    PMENUBARINFO pmbi)
 {
-   BOOL Res = TRUE;
-   PMENU_OBJECT MenuObject;
-   PMENU_ITEM mi;
-   PWND WindowObject;
+   PWND pWnd;
    HMENU hMenu;
-   POINT Offset;
-   RECTL Rect;
    MENUBARINFO kmbi;
+   BOOL Ret;
+   NTSTATUS Status = STATUS_SUCCESS;
+   PMENU Menu = NULL;
    DECLARE_RETURN(BOOL);
 
    TRACE("Enter NtUserGetMenuBarInfo\n");
    UserEnterShared();
 
-   if (!(WindowObject = UserGetWindowObject(hwnd)))
-     {
+   if (!(pWnd = UserGetWindowObject(hwnd)))
+   {
         EngSetLastError(ERROR_INVALID_WINDOW_HANDLE);
         RETURN(FALSE);
-     }
-
-   hMenu = (HMENU)(DWORD_PTR)WindowObject->IDMenu;
-
-   if (!(MenuObject = UserGetMenuObject(hMenu)))
-     {
-       EngSetLastError(ERROR_INVALID_MENU_HANDLE);
-       RETURN(FALSE);
-     }
-
-   if (pmbi->cbSize != sizeof(MENUBARINFO))
-     {
-       EngSetLastError(ERROR_INVALID_PARAMETER);
-       RETURN(FALSE);
-     }
-
-   kmbi.cbSize = sizeof(MENUBARINFO);
-   kmbi.fBarFocused = FALSE;
-   kmbi.fFocused = FALSE;
-   kmbi.hwndMenu = NULL;
+   }
 
    switch (idObject)
    {
-      case OBJID_MENU:
-      {
-         PMENU_OBJECT SubMenuObject;
-         kmbi.hMenu = hMenu;
-         if (idItem) /* Non-Zero-Based. */
-           {
-              if (IntGetMenuItemByFlag(MenuObject, idItem-1, MF_BYPOSITION, NULL, &mi, NULL) > -1)
-                   kmbi.rcBar = mi->Rect;
-              else
-                {
-                   Res = FALSE;
-                   break;
-                }
-           }
-         else
-           {
-              /* If items is zero we assume info for the menu itself. */
-              if (!(IntGetClientOrigin(WindowObject, &Offset)))
-                {
-                   Res = FALSE;
-                   break;
-                }
-              Rect.left = Offset.x;
-              Rect.right = Offset.x + MenuObject->MenuInfo.Width;
-              Rect.bottom = Offset.y;
-              Rect.top = Offset.y - MenuObject->MenuInfo.Height;
-              kmbi.rcBar = Rect;
-              TRACE("Rect top = %d bottom = %d left = %d right = %d \n",
-                       Rect.top, Rect.bottom, Rect.left, Rect.right);
-           }
-         if (idItem)
-           {
-              if (idItem-1 == MenuObject->MenuInfo.FocusedItem)
-                    kmbi.fFocused = TRUE;
-           }
-         if (MenuObject->MenuInfo.FocusedItem != NO_SELECTED_ITEM)
-               kmbi.fBarFocused = TRUE;
-
-         if (MenuObject->MenuItemList)
-         {
-         SubMenuObject = UserGetMenuObject(MenuObject->MenuItemList->hSubMenu);
-         if(SubMenuObject) kmbi.hwndMenu = SubMenuObject->MenuInfo.Wnd;
-         }
-         TRACE("OBJID_MENU, idItem = %d\n",idItem);
-         break;
-      }
-      case OBJID_CLIENT:
-      {
-         PMENU_OBJECT SubMenuObject, XSubMenuObject;
-         HMENU hMenuChk;
-         // Windows does this! Wine checks for Atom and uses GetWindowLongPtrW.
-         hMenuChk = (HMENU)co_IntSendMessage(hwnd, MN_GETHMENU, 0, 0);
-
-         if (!(MenuObject = UserGetMenuObject(hMenuChk)))
-         {
-            ERR("Window does not have a Popup Menu!\n");
+    case OBJID_CLIENT:
+        if (!pWnd->pcls->fnid)
+            RETURN(FALSE);
+        if (pWnd->pcls->fnid != FNID_MENU)
+        {
+            WARN("called on invalid window: %d\n", pWnd->pcls->fnid);
             EngSetLastError(ERROR_INVALID_MENU_HANDLE);
             RETURN(FALSE);
-         }
+        }
+        // Windows does this! Wine checks for Atom and uses GetWindowLongPtrW.
+        hMenu = (HMENU)co_IntSendMessage(hwnd, MN_GETHMENU, 0, 0);
+        break;
+    case OBJID_MENU:
+        hMenu = UlongToHandle(pWnd->IDMenu);
+        break;
+    case OBJID_SYSMENU:
+        if (!(pWnd->style & WS_SYSMENU)) RETURN(FALSE);
+        Menu = IntGetSystemMenu(pWnd, FALSE);
+        hMenu = Menu->head.h;
+        break;
+    default:
+        RETURN(FALSE);
+   }
 
-         SubMenuObject = UserGetMenuObject(MenuObject->MenuItemList->hSubMenu);
-         if(SubMenuObject) kmbi.hMenu = SubMenuObject->MenuInfo.Self;
-         else
-           {
-              Res = FALSE;
-              ERR("OBJID_CLIENT, No SubMenu!\n");
-              break;
-           }
-         if (idItem)
-           {
-              if (IntGetMenuItemByFlag(SubMenuObject, idItem-1, MF_BYPOSITION, NULL, &mi, NULL) > -1)
-                   kmbi.rcBar = mi->Rect;
-              else
-                {
-                   Res = FALSE;
-                   break;
-                }
-           }
-         else
-           {
-              PWND SubWinObj;
-              if (!(SubWinObj = UserGetWindowObject(SubMenuObject->MenuInfo.Wnd)))
-                {
-                   Res = FALSE;
-                   break;
-                }
-              if (!(IntGetClientOrigin(SubWinObj, &Offset)))
-                {
-                   Res = FALSE;
-                   break;
-                }
-              Rect.left = Offset.x;
-              Rect.right = Offset.x + SubMenuObject->MenuInfo.Width;
-              Rect.top = Offset.y;
-              Rect.bottom = Offset.y + SubMenuObject->MenuInfo.Height;
-              kmbi.rcBar = Rect;
-           }
-         if (idItem)
-           {
-              if (idItem-1 == SubMenuObject->MenuInfo.FocusedItem)
-                   kmbi.fFocused = TRUE;
-           }
-         if (SubMenuObject->MenuInfo.FocusedItem != NO_SELECTED_ITEM)
-               kmbi.fBarFocused = TRUE;
-         XSubMenuObject = UserGetMenuObject(SubMenuObject->MenuItemList->hSubMenu);
-         if (XSubMenuObject) kmbi.hwndMenu = XSubMenuObject->MenuInfo.Wnd;
-         TRACE("OBJID_CLIENT, idItem = %d\n",idItem);
-         break;
-      }
-      case OBJID_SYSMENU:
-      {
-         PMENU_OBJECT SysMenuObject, SubMenuObject;
-         if(!(SysMenuObject = IntGetSystemMenu(WindowObject, FALSE, FALSE)))
-         {
-           Res = FALSE;
-           break;
-         }
-         kmbi.hMenu = SysMenuObject->MenuInfo.Self;
-         if (idItem)
-           {
-              if (IntGetMenuItemByFlag(SysMenuObject, idItem-1, MF_BYPOSITION, NULL, &mi, NULL) > -1)
-                   kmbi.rcBar = mi->Rect;
-              else
-                {
-                   Res = FALSE;
-                   break;
-                }
-           }
-         else
-           {
-              PWND SysWinObj;
-              if (!(SysWinObj = UserGetWindowObject(SysMenuObject->MenuInfo.Wnd)))
-                {
-                   Res = FALSE;
-                   break;
-                }
-              if (!(IntGetClientOrigin(SysWinObj, &Offset)))
-                {
-                   Res = FALSE;
-                   break;
-                }
-              Rect.left = Offset.x;
-              Rect.right = Offset.x + SysMenuObject->MenuInfo.Width;
-              Rect.top = Offset.y;
-              Rect.bottom = Offset.y + SysMenuObject->MenuInfo.Height;
-              kmbi.rcBar = Rect;
-           }
-         if (idItem)
-           {
-              if (idItem-1 == SysMenuObject->MenuInfo.FocusedItem)
-                    kmbi.fFocused = TRUE;
-           }
-         if (SysMenuObject->MenuInfo.FocusedItem != NO_SELECTED_ITEM)
-               kmbi.fBarFocused = TRUE;
-         SubMenuObject = UserGetMenuObject(SysMenuObject->MenuItemList->hSubMenu);
-         if(SubMenuObject) kmbi.hwndMenu = SubMenuObject->MenuInfo.Wnd;
-         TRACE("OBJID_SYSMENU, idItem = %d\n",idItem);
-         break;
-      }
-      default:
-         Res = FALSE;
-         ERR("Unknown idObject = %d, idItem = %d\n",idObject,idItem);
-   }
-   if (Res)
-     {
-        NTSTATUS Status = MmCopyToCaller(pmbi, &kmbi, sizeof(MENUBARINFO));
-        if (! NT_SUCCESS(Status))
-          {
-            SetLastNtError(Status);
-            RETURN(FALSE);
-          }
-     }
-   RETURN(Res);
+   if (!hMenu)
+      RETURN(FALSE);
+
+   _SEH2_TRY
+   {
+       kmbi.cbSize = pmbi->cbSize;
+   }
+   _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+   {
+       kmbi.cbSize = 0;
+   }
+   _SEH2_END
+
+   if (kmbi.cbSize != sizeof(MENUBARINFO))
+   {
+       EngSetLastError(ERROR_INVALID_PARAMETER);
+       RETURN(FALSE);
+   }
+
+   if (!Menu) Menu = UserGetMenuObject(hMenu);
+   if (!Menu)
+       RETURN(FALSE);
+
+   if (idItem < 0 || idItem > Menu->cItems)
+       RETURN(FALSE);
+
+   RECTL_vSetEmptyRect(&kmbi.rcBar);
+
+   if (idItem == 0)
+   {
+      Ret = IntGetMenuItemRect(pWnd, Menu, 0, &kmbi.rcBar);
+      kmbi.rcBar.right = kmbi.rcBar.left + Menu->cxMenu;
+      kmbi.rcBar.bottom = kmbi.rcBar.top + Menu->cyMenu;
+      TRACE("idItem 0 %d\n",Ret);
+   }
+   else
+   {
+      Ret = IntGetMenuItemRect(pWnd, Menu, idItem-1, &kmbi.rcBar);
+      TRACE("idItem X %d\n", Ret);
+   }
+
+   kmbi.hMenu = hMenu;
+   kmbi.hwndMenu = NULL;
+   kmbi.fBarFocused = FALSE;
+   kmbi.fFocused = FALSE;
+   //kmbi.fBarFocused = top_popup_hmenu == hMenu;
+   if (idItem)
+   {
+       kmbi.fFocused = Menu->iItem == idItem-1;
+       if (kmbi.fFocused && (Menu->rgItems[idItem - 1].spSubMenu))
+       {
+          kmbi.hwndMenu = Menu->rgItems[idItem - 1].spSubMenu->hWnd;
+       }
+   }
+/*   else
+   {
+       kmbi.fFocused = kmbi.fBarFocused;
+   }
+*/
+   _SEH2_TRY
+   {
+      RtlCopyMemory(pmbi, &kmbi, sizeof(MENUBARINFO));
+   }
+   _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+   {
+      Status = _SEH2_GetExceptionCode();
+   }
+   _SEH2_END
+
+   if (!NT_SUCCESS(Status))
+   {
+      SetLastNtError(Status);
+      RETURN(FALSE);
+   }
+
+   RETURN(TRUE);
 
 CLEANUP:
    TRACE("Leave NtUserGetMenuBarInfo, ret=%i\n",_ret_);
@@ -1971,8 +2266,9 @@ NtUserGetMenuIndex(
    HMENU hMenu,
    HMENU hSubMenu)
 {
-   PMENU_OBJECT Menu, SubMenu;
-   PMENU_ITEM MenuItem;
+   PMENU Menu, SubMenu;
+   PITEM MenuItem;
+   UINT i;
    DECLARE_RETURN(UINT);
 
    TRACE("Enter NtUserGetMenuIndex\n");
@@ -1982,18 +2278,16 @@ NtUserGetMenuIndex(
         !(SubMenu = UserGetMenuObject(hSubMenu)) )
       RETURN(0xFFFFFFFF);
 
-   MenuItem = Menu->MenuItemList;
-   while(MenuItem)
+   MenuItem = Menu->rgItems;
+   for (i = 0; i < Menu->cItems; i++, MenuItem++)
    {
-      if (MenuItem->hSubMenu == hSubMenu)
-         RETURN(MenuItem->wID);
-      MenuItem = MenuItem->Next;
+       if (MenuItem->spSubMenu == SubMenu)
+          RETURN(MenuItem->wID);
    }
-
    RETURN(0xFFFFFFFF);
 
 CLEANUP:
-   TRACE("Leave NtUserGetMenuIndex, ret=%i\n",_ret_);
+   TRACE("Leave NtUserGetMenuIndex, ret=%u\n",_ret_);
    UserLeave();
    END_CLEANUP;
 }
@@ -2011,9 +2305,9 @@ NtUserGetMenuItemRect(
    PWND ReferenceWnd;
    LONG XMove, YMove;
    RECTL Rect;
-   NTSTATUS Status;
-   PMENU_OBJECT Menu;
-   PMENU_ITEM MenuItem;
+   PMENU Menu;
+   PITEM MenuItem;
+   NTSTATUS Status = STATUS_SUCCESS;
    DECLARE_RETURN(BOOL);
 
    TRACE("Enter NtUserGetMenuItemRect\n");
@@ -2024,21 +2318,26 @@ NtUserGetMenuItemRect(
       RETURN(FALSE);
    }
 
-   if (IntGetMenuItemByFlag(Menu, uItem, MF_BYPOSITION, NULL, &MenuItem, NULL) > -1)
-        Rect = MenuItem->Rect;
+   if ((MenuItem = MENU_FindItem (&Menu, &uItem, MF_BYPOSITION)))
+   {
+      Rect.left   = MenuItem->xItem; 
+      Rect.top    = MenuItem->yItem; 
+      Rect.right  = MenuItem->cxItem; // Do this for now......
+      Rect.bottom = MenuItem->cyItem;
+   }
    else
       RETURN(FALSE);
 
    if(!hWnd)
    {
-       hWnd = Menu->MenuInfo.Wnd;
+       hWnd = Menu->hWnd;
    }
 
    if (lprcItem == NULL) RETURN( FALSE);
 
    if (!(ReferenceWnd = UserGetWindowObject(hWnd))) RETURN( FALSE);
 
-   if(MenuItem->fType & MF_POPUP)
+   if (Menu->fFlags & MNF_POPUP)
    {
      XMove = ReferenceWnd->rcClient.left;
      YMove = ReferenceWnd->rcClient.top;
@@ -2054,13 +2353,22 @@ NtUserGetMenuItemRect(
    Rect.right  += XMove;
    Rect.bottom += YMove;
 
-   Status = MmCopyToCaller(lprcItem, &Rect, sizeof(RECT));
-   if (! NT_SUCCESS(Status))
+   _SEH2_TRY
+   {
+      RtlCopyMemory(lprcItem, &Rect, sizeof(RECTL));
+   }
+   _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+   {
+      Status = _SEH2_GetExceptionCode();
+   }
+   _SEH2_END
+
+   if (!NT_SUCCESS(Status))
    {
       SetLastNtError(Status);
-      RETURN( FALSE);
+      RETURN(FALSE);
    }
-   RETURN( TRUE);
+   RETURN(TRUE);
 
 CLEANUP:
    TRACE("Leave NtUserGetMenuItemRect, ret=%i\n",_ret_);
@@ -2078,7 +2386,7 @@ NtUserHiliteMenuItem(
    UINT uItemHilite,
    UINT uHilite)
 {
-   PMENU_OBJECT Menu;
+   PMENU Menu;
    PWND Window;
    DECLARE_RETURN(BOOLEAN);
 
@@ -2097,71 +2405,14 @@ NtUserHiliteMenuItem(
       RETURN(FALSE);
    }
 
-   if(Window->IDMenu == (UINT)(UINT_PTR)hMenu)
-   {
-      RETURN( IntHiliteMenuItem(Window, Menu, uItemHilite, uHilite));
-   }
-
-   RETURN(FALSE);
+   RETURN( IntHiliteMenuItem(Window, Menu, uItemHilite, uHilite));
 
 CLEANUP:
-   TRACE("Leave NtUserHiliteMenuItem, ret=%i\n",_ret_);
+   TRACE("Leave NtUserHiliteMenuItem, ret=%u\n",_ret_);
    UserLeave();
    END_CLEANUP;
 }
 
-static
-BOOL FASTCALL
-UserMenuInfo(
-   PMENU_OBJECT Menu,
-   PROSMENUINFO UnsafeMenuInfo,
-   BOOL SetOrGet)
-{
-   BOOL Res;
-   DWORD Size;
-   NTSTATUS Status;
-   ROSMENUINFO MenuInfo;
-
-   Status = MmCopyFromCaller(&Size, &UnsafeMenuInfo->cbSize, sizeof(DWORD));
-   if (! NT_SUCCESS(Status))
-   {
-      SetLastNtError(Status);
-      return( FALSE);
-   }
-   if(Size < sizeof(MENUINFO) || sizeof(ROSMENUINFO) < Size)
-   {
-      EngSetLastError(ERROR_INVALID_PARAMETER);
-      return( FALSE);
-   }
-   Status = MmCopyFromCaller(&MenuInfo, UnsafeMenuInfo, Size);
-   if (! NT_SUCCESS(Status))
-   {
-      SetLastNtError(Status);
-      return( FALSE);
-   }
-
-   if(SetOrGet)
-   {
-      /* Set MenuInfo */
-      Res = IntSetMenuInfo(Menu, &MenuInfo);
-   }
-   else
-   {
-      /* Get MenuInfo */
-      Res = IntGetMenuInfo(Menu, &MenuInfo);
-      if (Res)
-      {
-         Status = MmCopyToCaller(UnsafeMenuInfo, &MenuInfo, Size);
-         if (! NT_SUCCESS(Status))
-         {
-            SetLastNtError(Status);
-            return( FALSE);
-         }
-      }
-   }
-
-   return( Res);
-}
 
 /*
  * @implemented
@@ -2173,9 +2424,9 @@ NtUserMenuItemFromPoint(
    DWORD X,
    DWORD Y)
 {
-   PMENU_OBJECT Menu;
+   PMENU Menu;
    PWND Window = NULL;
-   PMENU_ITEM mi;
+   PITEM mi;
    int i;
    DECLARE_RETURN(int);
 
@@ -2187,7 +2438,7 @@ NtUserMenuItemFromPoint(
       RETURN( -1);
    }
 
-   if (!(Window = UserGetWindowObject(Menu->MenuInfo.Wnd)))
+   if (!(Window = UserGetWindowObject(Menu->hWnd)))
    {
       RETURN( -1);
    }
@@ -2195,14 +2446,19 @@ NtUserMenuItemFromPoint(
    X -= Window->rcWindow.left;
    Y -= Window->rcWindow.top;
 
-   mi = Menu->MenuItemList;
-   for (i = 0; NULL != mi; i++)
+   mi = Menu->rgItems;
+   for (i = 0; i < Menu->cItems; i++, mi++)
    {
-      if (RECTL_bPointInRect(&(mi->Rect), X, Y))
+      RECTL Rect;
+      Rect.left   = mi->xItem; 
+      Rect.top    = mi->yItem; 
+      Rect.right  = mi->cxItem; // Do this for now......
+      Rect.bottom = mi->cyItem;
+      //MENU_AdjustMenuItemRect(Menu, &Rect); Need gpsi OBMI via callback!
+      if (RECTL_bPointInRect(&Rect, X, Y))
       {
          break;
       }
-      mi = mi->Next;
    }
 
    RETURN( (mi ? i : NO_SELECTED_ITEM));
@@ -2213,80 +2469,6 @@ CLEANUP:
    END_CLEANUP;
 }
 
-static
-BOOL FASTCALL
-UserMenuItemInfo(
-   PMENU_OBJECT Menu,
-   UINT Item,
-   BOOL ByPosition,
-   PROSMENUITEMINFO UnsafeItemInfo,
-   BOOL SetOrGet)
-{
-   PMENU_ITEM MenuItem;
-   ROSMENUITEMINFO ItemInfo;
-   NTSTATUS Status;
-   UINT Size;
-   BOOL Ret;
-
-   Status = MmCopyFromCaller(&Size, &UnsafeItemInfo->cbSize, sizeof(UINT));
-   if (! NT_SUCCESS(Status))
-   {
-      SetLastNtError(Status);
-      return( FALSE);
-   }
-   if (sizeof(MENUITEMINFOW) != Size
-         && FIELD_OFFSET(MENUITEMINFOW, hbmpItem) != Size
-         && sizeof(ROSMENUITEMINFO) != Size)
-   {
-      EngSetLastError(ERROR_INVALID_PARAMETER);
-      return( FALSE);
-   }
-   Status = MmCopyFromCaller(&ItemInfo, UnsafeItemInfo, Size);
-   if (! NT_SUCCESS(Status))
-   {
-      SetLastNtError(Status);
-      return( FALSE);
-   }
-   /* If this is a pre-0x0500 _WIN32_WINNT MENUITEMINFOW, you can't
-      set/get hbmpItem */
-   if (FIELD_OFFSET(MENUITEMINFOW, hbmpItem) == Size
-         && 0 != (ItemInfo.fMask & MIIM_BITMAP))
-   {
-      EngSetLastError(ERROR_INVALID_PARAMETER);
-      return( FALSE);
-   }
-
-   if (IntGetMenuItemByFlag(Menu, Item,
-                            (ByPosition ? MF_BYPOSITION : MF_BYCOMMAND),
-                            NULL, &MenuItem, NULL) < 0)
-   {
-      EngSetLastError(ERROR_INVALID_PARAMETER);
-// This will crash menu (line 80) correct_behavior test!
-// "NT4 and below can't handle a bigger MENUITEMINFO struct"
-      //EngSetLastError(ERROR_MENU_ITEM_NOT_FOUND);
-      return( FALSE);
-   }
-
-   if (SetOrGet)
-   {
-      Ret = IntSetMenuItemInfo(Menu, MenuItem, &ItemInfo);
-   }
-   else
-   {
-      Ret = IntGetMenuItemInfo(Menu, MenuItem, &ItemInfo);
-      if (Ret)
-      {
-         Status = MmCopyToCaller(UnsafeItemInfo, &ItemInfo, Size);
-         if (! NT_SUCCESS(Status))
-         {
-            SetLastNtError(Status);
-            return( FALSE);
-         }
-      }
-   }
-
-   return( Ret);
-}
 
 /*
  * @implemented
@@ -2297,7 +2479,7 @@ NtUserRemoveMenu(
    UINT uPosition,
    UINT uFlags)
 {
-   PMENU_OBJECT Menu;
+   PMENU Menu;
    DECLARE_RETURN(BOOL);
 
    TRACE("Enter NtUserRemoveMenu\n");
@@ -2325,7 +2507,7 @@ NtUserSetMenuContextHelpId(
    HMENU hMenu,
    DWORD dwContextHelpId)
 {
-   PMENU_OBJECT Menu;
+   PMENU Menu;
    DECLARE_RETURN(BOOL);
 
    TRACE("Enter NtUserSetMenuContextHelpId\n");
@@ -2353,7 +2535,7 @@ NtUserSetMenuDefaultItem(
    UINT uItem,
    UINT fByPos)
 {
-   PMENU_OBJECT Menu;
+   PMENU Menu;
    DECLARE_RETURN(BOOL);
 
    TRACE("Enter NtUserSetMenuDefaultItem\n");
@@ -2379,7 +2561,7 @@ BOOL APIENTRY
 NtUserSetMenuFlagRtoL(
    HMENU hMenu)
 {
-   PMENU_OBJECT Menu;
+   PMENU Menu;
    DECLARE_RETURN(BOOL);
 
    TRACE("Enter NtUserSetMenuFlagRtoL\n");
@@ -2406,7 +2588,7 @@ NtUserThunkedMenuInfo(
    HMENU hMenu,
    LPCMENUINFO lpcmi)
 {
-   PMENU_OBJECT Menu;
+   PMENU Menu;
    DECLARE_RETURN(BOOL);
 
    TRACE("Enter NtUserThunkedMenuInfo\n");
@@ -2437,7 +2619,7 @@ NtUserThunkedMenuItemInfo(
    LPMENUITEMINFOW lpmii,
    PUNICODE_STRING lpszCaption)
 {
-   PMENU_OBJECT Menu;
+   PMENU Menu;
    NTSTATUS Status;
    UNICODE_STRING lstrCaption;
    DECLARE_RETURN(BOOL);
@@ -2453,10 +2635,10 @@ NtUserThunkedMenuItemInfo(
       RETURN(FALSE);
    }
 
-   lstrCaption.Buffer = NULL;
+   RtlInitUnicodeString(&lstrCaption, 0);
 
    /* Check if we got a Caption */
-   if (lpszCaption)
+   if (lpszCaption && lpszCaption->Buffer)
    {
       /* Copy the string to kernel mode */
       Status = ProbeAndCaptureUnicodeString( &lstrCaption,
@@ -2470,9 +2652,9 @@ NtUserThunkedMenuItemInfo(
       }
    }
 
-   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_);
@@ -2480,135 +2662,4 @@ CLEANUP:
    END_CLEANUP;
 }
 
-////// ReactOS NtUserBad
-/*
- * @implemented
- */
-DWORD
-APIENTRY
-NtUserBuildMenuItemList(
-   HMENU hMenu,
-   VOID* Buffer,
-   ULONG nBufSize,
-   DWORD Reserved)
-{
-   DWORD res = -1;
-   PMENU_OBJECT Menu;
-   DECLARE_RETURN(DWORD);
-
-   TRACE("Enter NtUserBuildMenuItemList\n");
-   UserEnterExclusive();
-
-   if(!(Menu = UserGetMenuObject(hMenu)))
-   {
-      RETURN( (DWORD)-1);
-   }
-
-   if(Buffer)
-   {
-      res = IntBuildMenuItemList(Menu, Buffer, nBufSize);
-   }
-   else
-   {
-      res = Menu->MenuInfo.MenuItemCount;
-   }
-
-   RETURN( res);
-
-CLEANUP:
-   TRACE("Leave NtUserBuildMenuItemList, ret=%i\n",_ret_);
-   UserLeave();
-   END_CLEANUP;
-}
-
-/*
- * @implemented
- */
-UINT APIENTRY
-NtUserGetMenuDefaultItem(
-   HMENU hMenu,
-   UINT fByPos,
-   UINT gmdiFlags)
-{
-   PMENU_OBJECT Menu;
-   DWORD gismc = 0;
-   DECLARE_RETURN(UINT);
-
-   TRACE("Enter NtUserGetMenuDefaultItem\n");
-   UserEnterExclusive();
-
-   if(!(Menu = UserGetMenuObject(hMenu)))
-   {
-      RETURN(-1);
-   }
-
-   RETURN( IntGetMenuDefaultItem(Menu, fByPos, gmdiFlags, &gismc));
-
-CLEANUP:
-   TRACE("Leave NtUserGetMenuDefaultItem, ret=%i\n",_ret_);
-   UserLeave();
-   END_CLEANUP;
-}
-
-/*
- * @implemented
- */
-BOOL
-APIENTRY
-NtUserMenuInfo(
-   HMENU hMenu,
-   PROSMENUINFO UnsafeMenuInfo,
-   BOOL SetOrGet)
-{
-   PMENU_OBJECT Menu;
-   DECLARE_RETURN(BOOL);
-
-   TRACE("Enter NtUserMenuInfo\n");
-   UserEnterShared();
-
-   if (!(Menu = UserGetMenuObject(hMenu)))
-   {
-      RETURN(FALSE);
-   }
-
-   RETURN(UserMenuInfo(Menu, UnsafeMenuInfo, SetOrGet));
-
-CLEANUP:
-   TRACE("Leave NtUserMenuInfo, ret=%i\n",_ret_);
-   UserLeave();
-   END_CLEANUP;
-}
-
-/*
- * @implemented
- */
-BOOL
-APIENTRY
-NtUserMenuItemInfo(
-   HMENU hMenu,
-   UINT Item,
-   BOOL ByPosition,
-   PROSMENUITEMINFO UnsafeItemInfo,
-   BOOL SetOrGet)
-{
-   PMENU_OBJECT Menu;
-   DECLARE_RETURN(BOOL);
-
-   TRACE("Enter NtUserMenuItemInfo\n");
-   UserEnterExclusive();
-
-   if (!(Menu = UserGetMenuObject(hMenu)))
-   {
-      RETURN(FALSE);
-   }
-
-   RETURN( UserMenuItemInfo(Menu, Item, ByPosition, UnsafeItemInfo, SetOrGet));
-
-CLEANUP:
-   TRACE("Leave NtUserMenuItemInfo, ret=%i\n",_ret_);
-   UserLeave();
-   END_CLEANUP;
-
-}
-
 /* EOF */