[WIN32K] avoid BSOD in Bochs 2.6.8 CORE-13629, patch by Mark Jansen
[reactos.git] / win32ss / user / ntuser / menu.c
index a155c9f..965a72b 100644 (file)
@@ -2,7 +2,7 @@
  * COPYRIGHT:        See COPYING in the top level directory
  * PROJECT:          ReactOS kernel
  * PURPOSE:          Menus
- * FILE:             subsys/win32k/ntuser/menu.c
+ * FILE:             win32ss/user/ntuser/menu.c
  * PROGRAMER:        Thomas Weidenmueller (w3seek@users.sourceforge.net)
  */
 
@@ -11,7 +11,29 @@ DBG_DEFAULT_CHANNEL(UserMenu);
 
 /* INTERNAL ******************************************************************/
 
-BOOL FASTCALL IntSetMenuItemInfo(PMENU, PITEM, PROSMENUITEMINFO, PUNICODE_STRING);
+HFONT ghMenuFont = NULL;
+HFONT ghMenuFontBold = NULL;
+static SIZE MenuCharSize;
+
+/* Use global popup window because there's no way 2 menus can
+ * be tracked at the same time.  */
+static HWND top_popup = NULL;
+static HMENU top_popup_hmenu = NULL;
+
+BOOL fInsideMenuLoop = FALSE;
+BOOL fInEndMenu = FALSE;
+
+/* internal popup menu window messages */
+
+#define MM_SETMENUHANDLE        (WM_USER + 0)
+#define MM_GETMENUHANDLE        (WM_USER + 1)
+
+/* internal flags for menu tracking */
+
+#define TF_ENDMENU              0x10000
+#define TF_SUSPENDPOPUP         0x20000
+#define TF_SKIPREMOVE           0x40000
+
 
 /* maximum allowed depth of any branch in the menu tree.
  * This value is slightly larger than in windows (25) to
@@ -33,10 +55,47 @@ BOOL FASTCALL IntSetMenuItemInfo(PMENU, PITEM, PROSMENUITEMINFO, PUNICODE_STRING
 
 #define MII_STATE_MASK (MFS_GRAYED|MFS_CHECKED|MFS_HILITE|MFS_DEFAULT)
 
+#define IS_SYSTEM_MENU(MenuInfo)  \
+       (!((MenuInfo)->fFlags & MNF_POPUP) && ((MenuInfo)->fFlags & MNF_SYSMENU))
+
+#define IS_BITMAP_ITEM(flags) (MF_BITMAP == MENU_ITEM_TYPE(flags))
+
+#define IS_MAGIC_BITMAP(id) ((id) && ((INT_PTR)(id) < 12) && ((INT_PTR)(id) >= -1))
+#define IS_STRING_ITEM(flags) (MF_STRING == MENU_ITEM_TYPE(flags))
+
 /* Maximum number of menu items a menu can contain */
 #define MAX_MENU_ITEMS (0x4000)
 #define MAX_GOINTOSUBMENU (0x10)
 
+/* Space between 2 columns */
+#define MENU_COL_SPACE 4
+
+/*  top and bottom margins for popup menus */
+#define MENU_TOP_MARGIN 2 //3
+#define MENU_BOTTOM_MARGIN 2
+
+#define MENU_ITEM_HBMP_SPACE (5)
+#define MENU_BAR_ITEMS_SPACE (12)
+#define SEPARATOR_HEIGHT (5)
+#define MENU_TAB_SPACE (8)
+
+typedef struct
+{
+  UINT  TrackFlags;
+  PMENU CurrentMenu; /* current submenu (can be equal to hTopMenu)*/
+  PMENU TopMenu;     /* initial menu */
+  PWND  OwnerWnd;    /* where notifications are sent */
+  POINT Pt;
+} MTRACKER;
+
+/* Internal MenuTrackMenu() flags */
+#define TPM_INTERNAL            0xF0000000
+#define TPM_BUTTONDOWN          0x40000000              /* menu was clicked before tracking */
+#define TPM_POPUPMENU           0x20000000              /* menu is a popup menu */
+
+#define ITEM_PREV               -1
+#define ITEM_NEXT                1
+
 #define UpdateMenuItemState(state, change) \
 {\
   if((change) & MF_GRAYED) { \
@@ -147,9 +206,12 @@ PMENU FASTCALL VerifyMenu(PMENU pMenu)
 {
    HMENU hMenu;
    PITEM pItem;
+   ULONG Error;
    UINT i;
    if (!pMenu) return NULL;
 
+   Error = EngGetLastError();
+
    _SEH2_TRY
    {
       hMenu = UserHMGetHandle(pMenu);
@@ -163,6 +225,7 @@ PMENU FASTCALL VerifyMenu(PMENU pMenu)
    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
    {
       ERR("Run away LOOP!\n");
+      EngSetLastError(Error);
       _SEH2_YIELD(return NULL);
    }
    _SEH2_END
@@ -170,23 +233,46 @@ PMENU FASTCALL VerifyMenu(PMENU pMenu)
    if ( UserObjectInDestroy(hMenu))
    {
       ERR("Menu is marked for destruction!\n");
-      return NULL;
+      pMenu = NULL;
    }
-
+   EngSetLastError(Error);
    return pMenu;
 }
 
-BOOL IntDestroyMenu( PMENU pMenu, BOOL bRecurse, BOOL RemoveFromProcess)
+BOOL
+FASTCALL
+IntIsMenu(HMENU Menu)
 {
-    /* DestroyMenu should not destroy system menu popup owner */
-    if ((pMenu->fFlags & (MNF_POPUP | MNF_SYSSUBMENU)) == MNF_POPUP && pMenu->hWnd)
-    {
-       //PWND pWnd = ValidateHwndNoErr(pMenu->hWnd);
-       ERR("FIXME Pop up menu window thing'ie\n");
-       
-       //co_UserDestroyWindow( pWnd );
-       //pMenu->hWnd = 0;
-    }
+  if (UserGetMenuObject(Menu)) return TRUE;
+  return FALSE;
+}
+
+
+PMENU WINAPI
+IntGetMenu(HWND hWnd)
+{
+       PWND Wnd = ValidateHwndNoErr(hWnd);
+
+       if (!Wnd)
+               return NULL;
+
+       return UserGetMenuObject(UlongToHandle(Wnd->IDMenu));
+}
+
+PMENU get_win_sys_menu( HWND hwnd )   
+{
+   PMENU ret = 0;
+   WND *win = ValidateHwndNoErr( hwnd );        
+   if (win)
+   {
+      ret = UserGetMenuObject(win->SystemMenu);
+   }
+   return ret;
+}
+
+BOOL IntDestroyMenu( PMENU pMenu, BOOL bRecurse)
+{
+    PMENU SubMenu;
 
     if (pMenu->rgItems) /* recursively destroy submenus */
     {
@@ -194,61 +280,124 @@ BOOL IntDestroyMenu( PMENU pMenu, BOOL bRecurse, BOOL RemoveFromProcess)
        ITEM *item = pMenu->rgItems;
        for (i = pMenu->cItems; i > 0; i--, item++)
        {
-           pMenu->cItems--; //// I hate recursion logic! (jt) 4/2014. See r63028 comment for IntDeleteMenuItems.
+           SubMenu = item->spSubMenu;
+           item->spSubMenu = NULL;
+
+           /* Remove Item Text */
            FreeMenuText(pMenu,item);
-           if (bRecurse && item->spSubMenu)//VerifyMenu(item->spSubMenu))
+
+           /* 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))
            {
-              IntDestroyMenu(item->spSubMenu, bRecurse, RemoveFromProcess);
-              item->spSubMenu = NULL;
+              /* 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; //// What ever~!
+       pMenu->rgItems = NULL;
+       pMenu->cItems = 0;
     }
     return TRUE;
 }
 
+/* Callback for the object manager */
+BOOLEAN
+UserDestroyMenuObject(PVOID Object)
+{
+    return IntDestroyMenuObject(Object, TRUE);
+}
+
 BOOL FASTCALL
-IntDestroyMenuObject(PMENU Menu,
-                     BOOL bRecurse, BOOL RemoveFromProcess)
+IntDestroyMenuObject(PMENU Menu, BOOL bRecurse)
 {
-   if(Menu)
+   if (Menu)
    {
       PWND Window;
-      
-      /* Remove all menu items */
-      IntDestroyMenu( Menu, bRecurse, RemoveFromProcess);
-
-      if(RemoveFromProcess)
-      {
-         RemoveEntryList(&Menu->ListEntry);
-      }
 
       if (PsGetCurrentProcessSessionId() == Menu->head.rpdesk->rpwinstaParent->dwSessionId)
       {
          BOOL ret;
          if (Menu->hWnd)
          {
-            Window = UserGetWindowObject(Menu->hWnd);
+            Window = ValidateHwndNoErr(Menu->hWnd);
             if (Window)
             {
-               Window->IDMenu = 0;
+               //Window->IDMenu = 0; Only in Win9x!! wine win test_SetMenu test...
+
+               /* 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);
+
+         if (!UserMarkObjectDestroy(Menu)) return TRUE;
+
+         /* Remove all menu items */
+         IntDestroyMenu( Menu, bRecurse);
+
          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....
+         TRACE("IntDestroyMenuObject %d\n",ret);
          return ret;
       }
    }
    return FALSE;
 }
 
+BOOL
+MenuInit(VOID)
+{
+  NONCLIENTMETRICSW ncm;
+
+  /* get the menu font */
+  if (!ghMenuFont || !ghMenuFontBold)
+  {
+    ncm.cbSize = sizeof(ncm);
+    if(!UserSystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0))
+    {
+      ERR("MenuInit(): SystemParametersInfo(SPI_GETNONCLIENTMETRICS) failed!\n");
+      return FALSE;
+    }
+
+    ghMenuFont = GreCreateFontIndirectW(&ncm.lfMenuFont);
+    if (ghMenuFont == NULL)
+    {
+      ERR("MenuInit(): CreateFontIndirectW(hMenuFont) failed!\n");
+      return FALSE;
+    }
+    ncm.lfMenuFont.lfWeight = max(ncm.lfMenuFont.lfWeight + 300, 1000);
+    ghMenuFontBold = GreCreateFontIndirectW(&ncm.lfMenuFont);
+    if (ghMenuFontBold == NULL)
+    {
+      ERR("MenuInit(): CreateFontIndirectW(hMenuFontBold) failed!\n");
+      GreDeleteObject(ghMenuFont);
+      ghMenuFont = NULL;
+      return FALSE;
+    }
+    
+    GreSetObjectOwner(ghMenuFont, GDI_OBJ_HMGR_PUBLIC);
+    GreSetObjectOwner(ghMenuFontBold, GDI_OBJ_HMGR_PUBLIC);
+
+    co_IntSetupOBM();
+  }
+
+  return TRUE;
+}
+
+
 /**********************************************************************
  *             MENU_depth
  *
@@ -266,7 +415,7 @@ int FASTCALL MENU_depth( PMENU pmenu, int depth)
     if( depth > MAXMENUDEPTH) return depth;
     item = pmenu->rgItems;
     subdepth = depth;
-    for( i = 0; item, i < pmenu->cItems && subdepth <= MAXMENUDEPTH; i++, item++)
+    for( i = 0; i < pmenu->cItems && subdepth <= MAXMENUDEPTH; i++, item++)
     {
         if( item->spSubMenu)//VerifyMenu(item->spSubMenu))
         {
@@ -279,6 +428,78 @@ int FASTCALL MENU_depth( PMENU pmenu, int depth)
     return subdepth;
 }
 
+
+/******************************************************************************
+ *
+ *   UINT MenuGetStartOfNextColumn(
+ *     PMENU Menu)
+ *
+ *****************************************************************************/
+
+static UINT  MENU_GetStartOfNextColumn(
+    PMENU  menu )
+{
+    PITEM pItem;
+    UINT i;
+
+    if(!menu)
+       return NO_SELECTED_ITEM;
+
+    i = menu->iItem + 1;
+    if( i == NO_SELECTED_ITEM )
+       return i;
+
+    pItem = menu->rgItems;
+    if (!pItem) return NO_SELECTED_ITEM;
+    for( ; i < menu->cItems; ++i ) {
+       if (pItem[i].fType & (MF_MENUBREAK | MF_MENUBARBREAK))
+           return i;
+    }
+
+    return NO_SELECTED_ITEM;
+}
+
+/******************************************************************************
+ *
+ *   UINT MenuGetStartOfPrevColumn(
+ *     PMENU Menu)
+ *
+ *****************************************************************************/
+static UINT  MENU_GetStartOfPrevColumn(
+    PMENU  menu )
+{
+    UINT  i;
+    PITEM pItem;
+
+    if( !menu )
+       return NO_SELECTED_ITEM;
+
+    if( menu->iItem == 0 || menu->iItem == NO_SELECTED_ITEM )
+       return NO_SELECTED_ITEM;
+
+    pItem = menu->rgItems;
+    if (!pItem) return NO_SELECTED_ITEM;
+
+    /* Find the start of the column */
+
+    for(i = menu->iItem; i != 0 &&
+        !(pItem[i].fType & (MF_MENUBREAK | MF_MENUBARBREAK));
+       --i); /* empty */
+
+    if(i == 0)
+       return NO_SELECTED_ITEM;
+
+    for(--i; i != 0; --i) {
+       if (pItem[i].fType & (MF_MENUBREAK | MF_MENUBARBREAK))
+           break;
+    }
+
+    TRACE("ret %d.\n", i );
+
+    return i;
+}
+
 /***********************************************************************
  *           MENU_FindItem
  *
@@ -303,7 +524,7 @@ PITEM FASTCALL MENU_FindItem( PMENU *pmenu, UINT *nPos, UINT wFlags )
     else
     {
         PITEM item = menu->rgItems;
-       for (i = 0; item, i < menu->cItems; i++, item++)
+       for (i = 0; i < menu->cItems; i++, item++)
        {
            if (item->spSubMenu)
            {
@@ -335,10 +556,48 @@ PITEM FASTCALL MENU_FindItem( PMENU *pmenu, UINT *nPos, UINT wFlags )
     return fallback;
 }
 
+/***********************************************************************
+ *           MenuFindSubMenu
+ *
+ * Find a Sub menu. Return the position of the submenu, and modifies
+ * *hmenu in case it is found in another sub-menu.
+ * If the submenu cannot be found, NO_SELECTED_ITEM is returned.
+ */
+static UINT FASTCALL MENU_FindSubMenu(PMENU *menu, PMENU SubTarget )
+{
+    UINT i;
+    PITEM item;
+
+    item = ((PMENU)*menu)->rgItems;
+    for (i = 0; i < ((PMENU)*menu)->cItems; i++, item++)
+    {
+        if (!item->spSubMenu)
+           continue;
+        else
+        {
+           if (item->spSubMenu == SubTarget)
+           {
+              return i;
+           }
+           else 
+           {
+              PMENU pSubMenu = item->spSubMenu;
+              UINT pos = MENU_FindSubMenu( &pSubMenu, SubTarget );
+              if (pos != NO_SELECTED_ITEM)
+              {
+                  *menu = pSubMenu;
+                  return pos;
+              }
+           }
+        }
+    }
+    return NO_SELECTED_ITEM;
+}
+
 BOOL FASTCALL
 IntRemoveMenuItem( PMENU pMenu, UINT nPos, UINT wFlags, BOOL bRecurse )
 {
-    PITEM item, NewItems;
+    PITEM item;
 
     TRACE("(menu=%p pos=%04x flags=%04x)\n",pMenu, nPos, wFlags);
     if (!(item = MENU_FindItem( &pMenu, &nPos, wFlags ))) return FALSE;
@@ -348,7 +607,7 @@ IntRemoveMenuItem( PMENU pMenu, UINT nPos, UINT wFlags, BOOL bRecurse )
     FreeMenuText(pMenu,item);
     if (bRecurse && item->spSubMenu)
     {
-       IntDestroyMenuObject(item->spSubMenu, bRecurse, TRUE);
+       IntDestroyMenuObject(item->spSubMenu, bRecurse);
     }
     ////// Use cAlloced with inc's of 8's....
     if (--pMenu->cItems == 0)
@@ -364,10 +623,7 @@ IntRemoveMenuItem( PMENU pMenu, UINT nPos, UINT wFlags, BOOL bRecurse )
            item++;
            nPos++;
        }
-        NewItems = DesktopHeapAlloc(pMenu->head.rpdesk, pMenu->cItems * sizeof(ITEM));
-        RtlCopyMemory(NewItems, pMenu->rgItems, pMenu->cItems * sizeof(ITEM));
-        DesktopHeapFree(pMenu->head.rpdesk, pMenu->rgItems);
-        pMenu->rgItems = NewItems;
+       pMenu->rgItems = DesktopHeapReAlloc(pMenu->head.rpdesk, pMenu->rgItems, pMenu->cItems * sizeof(ITEM));
     }
     return TRUE;
 }
@@ -450,7 +706,7 @@ IntInsertMenuItem(
    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);
@@ -461,20 +717,23 @@ IntInsertMenuItem(
    SubMenu->cyMenu = 0;
    MenuItem->hbmpChecked = MenuItem->hbmpUnchecked = 0;
 
-   TRACE("IntInsertMenuItemToList = %i %d\n", uItem, (BOOL)((INT)uItem >= 0));
+   TRACE("IntInsertMenuItemToList = %u %i\n", uItem, (BOOL)((INT)uItem >= 0));
 
    return TRUE;
 }
 
 PMENU FASTCALL
-IntCreateMenu(PHANDLE Handle, BOOL IsMenuBar)
+IntCreateMenu(
+    _Out_ PHANDLE Handle,
+    _In_ BOOL IsMenuBar,
+    _In_ PDESKTOP Desktop,
+    _In_ PPROCESSINFO ppi)
 {
    PMENU Menu;
-   PPROCESSINFO CurrentWin32Process;
 
    Menu = (PMENU)UserCreateObject( gHandleTable,
-                                          NULL,
-                                          NULL,
+                                          Desktop,
+                                          ppi->ptiList,
                                           Handle,
                                           TYPE_MENU,
                                           sizeof(MENU));
@@ -502,10 +761,6 @@ IntCreateMenu(PHANDLE Handle, BOOL IsMenuBar)
    Menu->hWnd = NULL;
    Menu->TimeToHide = FALSE;
 
-   /* Insert menu item into process menu handle list */
-   CurrentWin32Process = PsGetCurrentProcessWin32Process();
-   InsertTailList(&CurrentWin32Process->MenuListHead, &Menu->ListEntry);
-
    return Menu;
 }
 
@@ -562,19 +817,19 @@ IntCloneMenuItems(PMENU Destination, PMENU Source)
 PMENU FASTCALL
 IntCloneMenu(PMENU Source)
 {
-   PPROCESSINFO CurrentWin32Process;
    HANDLE hMenu;
    PMENU Menu;
 
    if(!Source)
       return NULL;
 
+   /* A menu is valid process wide. We can pass to the object manager any thread ptr */
    Menu = (PMENU)UserCreateObject( gHandleTable,
-                                          NULL,
-                                          NULL,
-                                          &hMenu,
-                                          TYPE_MENU,
-                                          sizeof(MENU));
+                                   Source->head.rpdesk,
+                                   ((PPROCESSINFO)Source->head.hTaskWow)->ptiList,
+                                   &hMenu,
+                                   TYPE_MENU,
+                                   sizeof(MENU));
    if(!Menu)
       return NULL;
 
@@ -596,10 +851,6 @@ IntCloneMenu(PMENU Source)
    Menu->hWnd = NULL;
    Menu->TimeToHide = FALSE;
 
-   /* Insert menu item into process menu handle list */
-   CurrentWin32Process = PsGetCurrentProcessWin32Process();
-   InsertTailList(&CurrentWin32Process->MenuListHead, &Menu->ListEntry);
-
    IntCloneMenuItems(Menu, Source);
 
    return Menu;
@@ -608,6 +859,7 @@ IntCloneMenu(PMENU Source)
 BOOL FASTCALL
 IntSetMenuFlagRtoL(PMENU Menu)
 {
+   ERR("SetMenuFlagRtoL\n");
    Menu->fFlags |= MNF_RTOL;
    return TRUE;
 }
@@ -642,7 +894,7 @@ IntGetMenuInfo(PMENU Menu, PROSMENUINFO lpmi)
      lpmi->cyMenu = Menu->cyMenu;
      lpmi->spwndNotify = Menu->spwndNotify;
      lpmi->cxTextAlign = Menu->cxTextAlign;
-     lpmi->iTop = Menu->iMaxTop;
+     lpmi->iTop = Menu->iTop;
      lpmi->iMaxTop = Menu->iMaxTop;
      lpmi->dwArrowsOn = Menu->dwArrowsOn;
 
@@ -677,7 +929,7 @@ IntSetMenuInfo(PMENU Menu, PROSMENUINFO lpmi)
          {
             IntSetMenuInfo( item->spSubMenu, lpmi);
          }
-      }      
+      }
    }
    if (sizeof(MENUINFO) < lpmi->cbSize)
    {
@@ -693,6 +945,12 @@ IntSetMenuInfo(PMENU Menu, PROSMENUINFO lpmi)
       Menu->TimeToHide = lpmi->TimeToHide;
       Menu->hWnd = lpmi->Wnd;
    }
+   if ( lpmi->fMask & MIM_STYLE)
+   {
+      if (lpmi->dwStyle & MNS_AUTODISMISS) FIXME("MNS_AUTODISMISS unimplemented wine\n");
+      if (lpmi->dwStyle & MNS_DRAGDROP)    FIXME("MNS_DRAGDROP unimplemented wine\n");
+      if (lpmi->dwStyle & MNS_MODELESS)    FIXME("MNS_MODELESS unimplemented wine\n");
+   }
    return TRUE;
 }
 
@@ -754,8 +1012,8 @@ IntGetMenuItemInfo(PMENU Menu, /* UNUSED PARAM!! */
 
    if (sizeof(ROSMENUITEMINFO) == lpmii->cbSize)
    {
-      lpmii->Rect.left   = MenuItem->xItem; 
-      lpmii->Rect.top    = MenuItem->yItem; 
+      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;
@@ -819,6 +1077,10 @@ IntSetMenuItemInfo(PMENU MenuObject, PITEM MenuItem, PROSMENUITEMINFO lpmii, PUN
    if(lpmii->fMask & MIIM_BITMAP)
    {
       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)
    {
@@ -856,14 +1118,18 @@ IntSetMenuItemInfo(PMENU MenuObject, PITEM MenuItem, PROSMENUITEMINFO lpmii, PUN
             {
                HANDLE hMenu;
                ERR("Pop Up Menu Double Trouble!\n");
-               SubMenuObject = IntCreateMenu(&hMenu, FALSE); // It will be marked.
+               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, TRUE);
+               if (circref) IntDestroyMenuObject(SubMenuObject, FALSE);
                return FALSE;
             }
             /* Make sure the submenu is marked as a popup menu */
@@ -915,7 +1181,7 @@ IntSetMenuItemInfo(PMENU MenuObject, PITEM MenuItem, PROSMENUITEMINFO lpmii, PUN
       }
    }
 
-   if( !(MenuObject->fFlags & MNF_SYSDESKMN) &&
+   if( !(MenuObject->fFlags & MNF_SYSMENU) &&
        !MenuItem->Xlpstr &&
        !lpmii->dwTypeData &&
        !(MenuItem->fType & MFT_OWNERDRAW) &&
@@ -924,8 +1190,8 @@ IntSetMenuItemInfo(PMENU MenuObject, PITEM MenuItem, PROSMENUITEMINFO lpmii, PUN
 
    if (sizeof(ROSMENUITEMINFO) == lpmii->cbSize)
    {
-      MenuItem->xItem  = lpmii->Rect.left; 
-      MenuItem->yItem  = lpmii->Rect.top; 
+      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;
@@ -951,17 +1217,31 @@ IntEnableMenuItem(PMENU MenuObject, UINT uIDEnableItem, UINT uEnable)
    MenuItem->fState ^= (res ^ uEnable) & (MF_GRAYED | MF_DISABLED);
 
    /* If the close item in the system menu change update the close button */
-   if((MenuItem->wID == SC_CLOSE) && (res != uEnable))
+   if (res != uEnable)
    {
+      switch (MenuItem->wID) // More than just close.
+      {
+        case SC_CLOSE:
+        case SC_MAXIMIZE:
+        case SC_MINIMIZE:
+        case SC_MOVE:
+        case SC_RESTORE:
+        case SC_SIZE:
        if (MenuObject->fFlags & MNF_SYSSUBMENU && MenuObject->spwndNotify != 0)
        {
-            RECTL rc = MenuObject->spwndNotify->rcWindow;
+            //RECTL rc = MenuObject->spwndNotify->rcWindow;
 
             /* 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);
+            //IntMapWindowPoints(0, MenuObject->spwndNotify, (POINT *)&rc, 2);
+            //rc.bottom = 0;
+            //co_UserRedrawWindow(MenuObject->spwndNotify, &rc, 0, RDW_FRAME | RDW_INVALIDATE | RDW_NOCHILDREN);
+
+            // Allow UxTheme!
+            UserPaintCaption(MenuObject->spwndNotify, DC_BUTTONS);
        }
+       default:
+           break;
+      }
    }
    return res;
 }
@@ -981,39 +1261,16 @@ IntCheckMenuItem(PMENU MenuObject, UINT uIDCheckItem, UINT uCheck)
    return res;
 }
 
-BOOL FASTCALL
-IntHiliteMenuItem(PWND WindowObject,
-                  PMENU MenuObject,
-                  UINT uItemHilite,
-                  UINT uHilite)
-{
-   PITEM MenuItem;
-
-   if (!(MenuItem = MENU_FindItem( &MenuObject, &uItemHilite, uHilite ))) return FALSE;
-
-   if (uHilite & MF_HILITE)
-   {
-      MenuItem->fState |= MF_HILITE;
-   }
-   else
-   {
-      MenuItem->fState &= ~MF_HILITE;
-   }
-   /* FIXME: Update the window's menu */
-
-   return TRUE; // Always returns true!!!!
-}
-
 BOOL FASTCALL
 UserSetMenuDefaultItem(PMENU MenuObject, UINT uItem, UINT fByPos)
 {
    UINT i;
    PITEM MenuItem = MenuObject->rgItems;
 
-   if (!MenuItem) return FALSE;   
+   if (!MenuItem) return FALSE;
 
    /* reset all default-item flags */
-   for (i = 0; MenuItem, i < MenuObject->cItems; i++, MenuItem++)
+   for (i = 0; i < MenuObject->cItems; i++, MenuItem++)
    {
        MenuItem->fState &= ~MFS_DEFAULT;
    }
@@ -1032,7 +1289,7 @@ UserSetMenuDefaultItem(PMENU MenuObject, UINT uItem, UINT fByPos)
    }
    else
    {
-      for (i = 0; MenuItem, i < MenuObject->cItems; i++, MenuItem++)
+      for (i = 0; i < MenuObject->cItems; i++, MenuItem++)
       {
           if (MenuItem->wID == uItem)
           {
@@ -1045,7 +1302,6 @@ UserSetMenuDefaultItem(PMENU MenuObject, UINT uItem, UINT fByPos)
    return FALSE;
 }
 
-
 UINT FASTCALL
 IntGetMenuDefaultItem(PMENU MenuObject, UINT fByPos, UINT gmdiFlags, DWORD *gismc)
 {
@@ -1065,7 +1321,7 @@ IntGetMenuDefaultItem(PMENU MenuObject, UINT fByPos, UINT gmdiFlags, DWORD *gism
    if ( (!(GMDI_USEDISABLED & gmdiFlags)) && (MenuItem->fState & MFS_DISABLED )) return -1;
 
    /* search rekursiv when needed */
-   if ( (MenuItem->fType & MF_POPUP) && (gmdiFlags & GMDI_GOINTOPOPUPS) && MenuItem->spSubMenu)
+   if ( (gmdiFlags & GMDI_GOINTOPOPUPS) && MenuItem->spSubMenu )
    {
       UINT ret;
       (*gismc)++;
@@ -1078,105 +1334,3263 @@ IntGetMenuDefaultItem(PMENU MenuObject, UINT fByPos, UINT gmdiFlags, DWORD *gism
    return ( fByPos ) ? i : MenuItem->wID;
 }
 
-VOID FASTCALL
-co_IntInitTracking(PWND Window, PMENU Menu, BOOL Popup,
-                   UINT Flags)
+PMENU
+FASTCALL
+co_IntGetSubMenu(
+  PMENU pMenu,
+  int nPos)
 {
-   /* FIXME: Hide caret */
+  PITEM pItem;
+  if (!(pItem = MENU_FindItem( &pMenu, (UINT*)&nPos, MF_BYPOSITION ))) return NULL;
+  return pItem->spSubMenu;
+}
 
-   if(!(Flags & TPM_NONOTIFY))
-      co_IntSendMessage(Window->head.h, WM_SETCURSOR, (WPARAM)Window->head.h, HTCAPTION);
+/***********************************************************************
+ *           MenuInitSysMenuPopup
+ *
+ * Grey the appropriate items in System menu.
+ */
+void FASTCALL MENU_InitSysMenuPopup(PMENU menu, DWORD style, DWORD clsStyle, LONG HitTest )
+{
+    BOOL gray;
+    UINT DefItem;
+
+    gray = !(style & WS_THICKFRAME) || (style & (WS_MAXIMIZE | WS_MINIMIZE));
+    IntEnableMenuItem( menu, SC_SIZE, (gray ? MF_GRAYED : MF_ENABLED) );
+    gray = ((style & WS_MAXIMIZE) != 0);
+    IntEnableMenuItem( menu, SC_MOVE, (gray ? MF_GRAYED : MF_ENABLED) );
+    gray = !(style & WS_MINIMIZEBOX) || (style & WS_MINIMIZE);
+    IntEnableMenuItem( menu, SC_MINIMIZE, (gray ? MF_GRAYED : MF_ENABLED) );
+    gray = !(style & WS_MAXIMIZEBOX) || (style & WS_MAXIMIZE);
+    IntEnableMenuItem( menu, SC_MAXIMIZE, (gray ? MF_GRAYED : MF_ENABLED) );
+    gray = !(style & (WS_MAXIMIZE | WS_MINIMIZE));
+    IntEnableMenuItem( menu, SC_RESTORE, (gray ? MF_GRAYED : MF_ENABLED) );
+    gray = (clsStyle & CS_NOCLOSE) != 0;
+
+    /* The menu item must keep its state if it's disabled */
+    if(gray)
+        IntEnableMenuItem( menu, SC_CLOSE, MF_GRAYED);
+
+    /* Set default menu item */
+    if(style & WS_MINIMIZE) DefItem = SC_RESTORE;
+    else if(HitTest == HTCAPTION) DefItem = ((style & (WS_MAXIMIZE | WS_MINIMIZE)) ? SC_RESTORE : SC_MAXIMIZE);
+    else DefItem = SC_CLOSE;
+
+    UserSetMenuDefaultItem(menu, DefItem, MF_BYCOMMAND);
+}
 
-   /* FIXME: Send WM_SETCURSOR message */
 
-   if(!(Flags & TPM_NONOTIFY))
-      co_IntSendMessage(Window->head.h, WM_INITMENU, (WPARAM)Menu->head.h, 0);
+/***********************************************************************
+ *           MenuDrawPopupGlyph
+ *
+ * Draws popup magic glyphs (can be found in system menu).
+ */
+static void FASTCALL
+MENU_DrawPopupGlyph(HDC dc, LPRECT r, INT_PTR popupMagic, BOOL inactive, BOOL hilite)
+{
+  LOGFONTW lf;
+  HFONT hFont, hOldFont;
+  COLORREF clrsave;
+  INT bkmode;
+  WCHAR symbol;
+  switch (popupMagic)
+  {
+  case (INT_PTR) HBMMENU_POPUP_RESTORE:
+    symbol = '2';
+    break;
+  case (INT_PTR) HBMMENU_POPUP_MINIMIZE:
+    symbol = '0';
+    break;
+  case (INT_PTR) HBMMENU_POPUP_MAXIMIZE:
+    symbol = '1';
+    break;
+  case (INT_PTR) HBMMENU_POPUP_CLOSE:
+    symbol = 'r';
+    break;
+  default:
+    ERR("Invalid popup magic bitmap %d\n", (int)popupMagic);
+    return;
+  }
+  RtlZeroMemory(&lf, sizeof(LOGFONTW));
+  RECTL_vInflateRect(r, -2, -2);
+  lf.lfHeight = r->bottom - r->top;
+  lf.lfWidth = 0;
+  lf.lfWeight = FW_NORMAL;
+  lf.lfCharSet = DEFAULT_CHARSET;
+  RtlCopyMemory(lf.lfFaceName, L"Marlett", sizeof(L"Marlett"));
+  hFont = GreCreateFontIndirectW(&lf);
+  /* save font and text color */
+  hOldFont = NtGdiSelectFont(dc, hFont);
+  clrsave = GreGetTextColor(dc);
+  bkmode = GreGetBkMode(dc);
+  /* set color and drawing mode */
+  IntGdiSetBkMode(dc, TRANSPARENT);
+  if (inactive)
+  {
+    /* draw shadow */
+    if (!hilite)
+    {
+      IntGdiSetTextColor(dc, IntGetSysColor(COLOR_HIGHLIGHTTEXT));
+      GreTextOutW(dc, r->left + 1, r->top + 1, &symbol, 1);
+    }
+  }
+  IntGdiSetTextColor(dc, IntGetSysColor(inactive ? COLOR_GRAYTEXT : (hilite ? COLOR_HIGHLIGHTTEXT : COLOR_MENUTEXT)));
+  /* draw selected symbol */
+  GreTextOutW(dc, r->left, r->top, &symbol, 1);
+  /* restore previous settings */
+  IntGdiSetTextColor(dc, clrsave);
+  NtGdiSelectFont(dc, hOldFont);
+  IntGdiSetBkMode(dc, bkmode);
+  GreDeleteObject(hFont);
 }
 
+/***********************************************************************
+ *           MENU_AdjustMenuItemRect
+ *
+ * Adjust menu item rectangle according to scrolling state.
+ */
 VOID FASTCALL
-co_IntExitTracking(PWND Window, PMENU Menu, BOOL Popup,
-                   UINT Flags)
+MENU_AdjustMenuItemRect(PMENU menu, PRECTL rect)
 {
-   if(!(Flags & TPM_NONOTIFY))
-      co_IntSendMessage(Window->head.h, WM_EXITMENULOOP, 0 /* FIXME */, 0);
-
-   /* FIXME: Show caret again */
+    if (menu->dwArrowsOn)
+    {
+        UINT arrow_bitmap_height;
+        arrow_bitmap_height = gpsi->oembmi[OBI_UPARROW].cy; ///// Menu up arrow! OBM_UPARROW
+        rect->top += arrow_bitmap_height - menu->iTop;
+        rect->bottom += arrow_bitmap_height - menu->iTop;
+    }
 }
 
-INT FASTCALL
-IntTrackMenu(PMENU Menu, PWND Window, INT x, INT y,
-             RECTL lprect)
+/***********************************************************************
+ *           MENU_FindItemByCoords
+ *
+ * Find the item at the specified coordinates (screen coords). Does
+ * not work for child windows and therefore should not be called for
+ * an arbitrary system menu.
+ */
+static ITEM *MENU_FindItemByCoords( MENU *menu, POINT pt, UINT *pos )
 {
-   return 0;
+    ITEM *item;
+    UINT i;
+    RECT rect;
+    PWND pWnd = ValidateHwndNoErr(menu->hWnd);
+
+    if (!IntGetWindowRect(pWnd, &rect)) return NULL;
+    if (pWnd->ExStyle & WS_EX_LAYOUTRTL)
+       pt.x = rect.right - 1 - pt.x;
+    else
+       pt.x -= rect.left;
+    pt.y -= rect.top;
+    item = menu->rgItems;
+    for (i = 0; i < menu->cItems; i++, item++)
+    {
+        //rect = item->rect;
+        rect.left   = item->xItem;
+        rect.top    = item->yItem; 
+        rect.right  = item->cxItem; // Do this for now......
+        rect.bottom = item->cyItem;
+
+        MENU_AdjustMenuItemRect(menu, &rect);
+       if (RECTL_bPointInRect(&rect, pt.x, pt.y))
+       {
+           if (pos) *pos = i;
+           return item;
+       }
+    }
+    return NULL;
 }
 
-BOOL FASTCALL
-co_IntTrackPopupMenu(PMENU Menu, PWND Window,
-                     UINT Flags, POINT *Pos, UINT MenuPos, RECTL *ExcludeRect)
+INT FASTCALL IntMenuItemFromPoint(PWND pWnd, HMENU hMenu, POINT ptScreen)
 {
-   co_IntInitTracking(Window, Menu, TRUE, Flags);
+    MENU *menu = UserGetMenuObject(hMenu);
+    UINT pos;
 
-   co_IntExitTracking(Window, Menu, TRUE, Flags);
-   return FALSE;
+    /*FIXME: Do we have to handle hWnd here? */
+    if (!menu) return -1;
+    if (!MENU_FindItemByCoords(menu, ptScreen, &pos)) return -1;
+    return pos;
 }
 
-
-/*!
- * Internal function. Called when the process is destroyed to free the remaining menu handles.
-*/
-BOOL FASTCALL
-IntCleanupMenus(struct _EPROCESS *Process, PPROCESSINFO Win32Process)
+/***********************************************************************
+ *           MenuFindItemByKey
+ *
+ * Find the menu item selected by a key press.
+ * Return item id, -1 if none, -2 if we should close the menu.
+ */
+static UINT FASTCALL MENU_FindItemByKey(PWND WndOwner, PMENU menu,
+                  WCHAR Key, BOOL ForceMenuChar)
 {
-   PEPROCESS CurrentProcess;
-   PLIST_ENTRY LastHead = NULL;
-   PMENU MenuObject;
+  LRESULT MenuChar;
+  WORD Flags = 0;
 
-   CurrentProcess = PsGetCurrentProcess();
-   if (CurrentProcess != Process)
-   {
-      KeAttachProcess(&Process->Pcb);
-   }
+  TRACE("\tlooking for '%c' (0x%02x) in [%p]\n", (char)Key, Key, menu );
 
-   while (Win32Process->MenuListHead.Flink != &(Win32Process->MenuListHead) &&
-          Win32Process->MenuListHead.Flink != LastHead)
-   {
-      LastHead = Win32Process->MenuListHead.Flink;
-      MenuObject = CONTAINING_RECORD(Win32Process->MenuListHead.Flink, MENU, ListEntry);
-      TRACE("Menus are stuck on the process list!\n");
-      IntDestroyMenuObject(MenuObject, FALSE, TRUE);
-   }
+  if (!menu || !VerifyMenu(menu))
+     menu = co_IntGetSubMenu( UserGetMenuObject(WndOwner->SystemMenu), 0 );
+  if (menu)
+  {
+     ITEM *item = menu->rgItems;
 
-   if (CurrentProcess != Process)
-   {
-      KeDetachProcess();
-   }
-   return TRUE;
+     if ( !ForceMenuChar )
+     {
+        UINT i;
+        BOOL cjk = UserGetSystemMetrics( SM_DBCSENABLED );
+
+        for (i = 0; i < menu->cItems; i++, item++)
+        {
+           LPWSTR text = item->Xlpstr;
+           if( text)
+           {
+              const WCHAR *p = text - 2;
+              do
+              {
+                 const WCHAR *q = p + 2;
+                 p = wcschr (q, '&');
+                 if (!p && cjk) p = wcschr (q, '\036'); /* Japanese Win16 */
+              }
+              while (p != NULL && p [1] == '&');
+              if (p && (towupper(p[1]) == towupper(Key))) return i;
+           }
+        }
+     }
+
+     Flags |= menu->fFlags & MNF_POPUP ? MF_POPUP : 0;
+     Flags |= menu->fFlags & MNF_SYSMENU ? MF_SYSMENU : 0;
+
+     MenuChar = co_IntSendMessage( UserHMGetHandle(WndOwner), WM_MENUCHAR,
+                              MAKEWPARAM(Key, Flags), (LPARAM) UserHMGetHandle(menu));
+     if (HIWORD(MenuChar) == MNC_EXECUTE) return LOWORD(MenuChar);
+     if (HIWORD(MenuChar) == MNC_CLOSE) return (UINT)(-2);
+  }
+  return (UINT)(-1);
 }
 
-BOOLEAN APIENTRY
-intGetTitleBarInfo(PWND pWindowObject, PTITLEBARINFO bti)
+/***********************************************************************
+ *           MenuGetBitmapItemSize
+ *
+ * Get the size of a bitmap item.
+ */
+static void FASTCALL MENU_GetBitmapItemSize(PITEM lpitem, SIZE *size, PWND WndOwner)
 {
+    BITMAP bm;
+    HBITMAP bmp = lpitem->hbmp;
 
-    DWORD dwStyle = 0;
-    DWORD dwExStyle = 0;
-    BOOLEAN retValue = TRUE;
+    size->cx = size->cy = 0;
 
-    if (bti->cbSize == sizeof(TITLEBARINFO))
+    /* check if there is a magic menu item associated with this item */
+    if (IS_MAGIC_BITMAP(bmp))
     {
-        RtlZeroMemory(&bti->rgstate[0],sizeof(DWORD)*(CCHILDREN_TITLEBAR+1));
+      switch((INT_PTR) bmp)
+        {
+            case (INT_PTR)HBMMENU_CALLBACK:
+            {
+                MEASUREITEMSTRUCT measItem;
+                measItem.CtlType = ODT_MENU;
+                measItem.CtlID = 0;
+                measItem.itemID = lpitem->wID;
+                measItem.itemWidth  = lpitem->cxItem - lpitem->xItem; //lpitem->Rect.right  - lpitem->Rect.left;
+                measItem.itemHeight = lpitem->cyItem - lpitem->yItem; //lpitem->Rect.bottom - lpitem->Rect.top;
+                measItem.itemData = lpitem->dwItemData;
+                co_IntSendMessage( UserHMGetHandle(WndOwner), WM_MEASUREITEM, 0, (LPARAM)&measItem);
+                size->cx = measItem.itemWidth;
+                size->cy = measItem.itemHeight;
+                TRACE("HBMMENU_CALLBACK Height %d Width %d\n",measItem.itemHeight,measItem.itemWidth);
+                return;
+            }
+            break;
 
-        bti->rgstate[0] = STATE_SYSTEM_FOCUSABLE;
+          case (INT_PTR) HBMMENU_SYSTEM:
+            if (lpitem->dwItemData)
+              {
+                bmp = (HBITMAP) lpitem->dwItemData;
+                break;
+              }
+            /* fall through */
+          case (INT_PTR) HBMMENU_MBAR_RESTORE:
+          case (INT_PTR) HBMMENU_MBAR_MINIMIZE:
+          case (INT_PTR) HBMMENU_MBAR_CLOSE:
+          case (INT_PTR) HBMMENU_MBAR_MINIMIZE_D:
+          case (INT_PTR) HBMMENU_MBAR_CLOSE_D:
+          case (INT_PTR) HBMMENU_POPUP_CLOSE:
+          case (INT_PTR) HBMMENU_POPUP_RESTORE:
+          case (INT_PTR) HBMMENU_POPUP_MAXIMIZE:
+          case (INT_PTR) HBMMENU_POPUP_MINIMIZE:
+            /* FIXME: Why we need to subtract these magic values? */
+            /* to make them smaller than the menu bar? */
+            size->cx = UserGetSystemMetrics(SM_CXSIZE) - 2;
+            size->cy = UserGetSystemMetrics(SM_CYSIZE) - 4;
+            return;
+        }
+    }
 
-        dwStyle = pWindowObject->style;
-        dwExStyle = pWindowObject->ExStyle;
+    if (GreGetObject(bmp, sizeof(BITMAP), &bm))
+    {
+        size->cx = bm.bmWidth;
+        size->cy = bm.bmHeight;
+    }
+}
 
-        bti->rcTitleBar.top  = 0;
-        bti->rcTitleBar.left = 0;
-        bti->rcTitleBar.right  = pWindowObject->rcWindow.right - pWindowObject->rcWindow.left;
-        bti->rcTitleBar.bottom = pWindowObject->rcWindow.bottom - pWindowObject->rcWindow.top;
+/***********************************************************************
+ *           MenuDrawBitmapItem
+ *
+ * Draw a bitmap item.
+ */
+static void FASTCALL MENU_DrawBitmapItem(HDC hdc, PITEM lpitem, const RECT *rect,
+                    PMENU Menu, PWND WndOwner, UINT odaction, BOOL MenuBar)
+{
+    BITMAP bm;
+    DWORD rop;
+    HDC hdcMem;
+    HBITMAP bmp;
+    int w = rect->right - rect->left;
+    int h = rect->bottom - rect->top;
+    int bmp_xoffset = 0;
+    int left, top;
+    HBITMAP hbmToDraw = lpitem->hbmp;
+    bmp = hbmToDraw;
+
+    /* Check if there is a magic menu item associated with this item */
+    if (IS_MAGIC_BITMAP(hbmToDraw))
+    {
+        UINT flags = 0;
+        RECT r;
 
-        /* Is it iconiced ? */
-        if ((dwStyle & WS_ICONIC)!=WS_ICONIC)
+      r = *rect;
+      switch ((INT_PTR)hbmToDraw)
+      {
+        case (INT_PTR)HBMMENU_SYSTEM:
+            if (lpitem->dwItemData)
+            {
+                if (ValidateHwndNoErr((HWND)lpitem->dwItemData))
+                {
+                   ERR("Get Item Data from this Window!!!\n");
+                }
+
+                ERR("Draw Bitmap\n");
+                bmp = (HBITMAP)lpitem->dwItemData;
+                if (!GreGetObject( bmp, sizeof(bm), &bm )) return;
+            }
+            else
+            {
+                PCURICON_OBJECT pIcon = NULL;
+                //if (!BmpSysMenu) BmpSysMenu = LoadBitmapW(0, MAKEINTRESOURCEW(OBM_CLOSE));
+                //bmp = BmpSysMenu;
+                //if (! GreGetObject(bmp, sizeof(bm), &bm)) return;
+                /* only use right half of the bitmap */
+                //bmp_xoffset = bm.bmWidth / 2;
+                //bm.bmWidth -= bmp_xoffset;
+                if (WndOwner)
+                {
+                    pIcon = NC_IconForWindow(WndOwner);
+                    // FIXME: NC_IconForWindow should reference it for us */
+                    if (pIcon) UserReferenceObject(pIcon);
+                }
+                ERR("Draw ICON\n");
+                if (pIcon)
+                {
+                   LONG cx = UserGetSystemMetrics(SM_CXSMICON);
+                   LONG cy = UserGetSystemMetrics(SM_CYSMICON);
+                   LONG x = rect->left - cx/2 + 1 + (rect->bottom - rect->top)/2; // this is really what Window does
+                   LONG y = (rect->top + rect->bottom)/2 - cy/2; // center
+                   UserDrawIconEx(hdc, x, y, pIcon, cx, cy, 0, NULL, DI_NORMAL);
+                   UserDereferenceObject(pIcon);
+                 }
+                 return;
+            }
+            goto got_bitmap;
+        case (INT_PTR)HBMMENU_MBAR_RESTORE:
+            flags = DFCS_CAPTIONRESTORE;
+            break;
+        case (INT_PTR)HBMMENU_MBAR_MINIMIZE:
+            r.right += 1;
+            flags = DFCS_CAPTIONMIN;
+            break;
+        case (INT_PTR)HBMMENU_MBAR_MINIMIZE_D:
+            r.right += 1;
+            flags = DFCS_CAPTIONMIN | DFCS_INACTIVE;
+            break;
+        case (INT_PTR)HBMMENU_MBAR_CLOSE:
+            flags = DFCS_CAPTIONCLOSE;
+            break;
+        case (INT_PTR)HBMMENU_MBAR_CLOSE_D:
+            flags = DFCS_CAPTIONCLOSE | DFCS_INACTIVE;
+            break;
+        case (INT_PTR)HBMMENU_CALLBACK:
+            {
+                DRAWITEMSTRUCT drawItem;
+                POINT origorg;
+                drawItem.CtlType = ODT_MENU;
+                drawItem.CtlID = 0;
+                drawItem.itemID = lpitem->wID;
+                drawItem.itemAction = odaction;
+                drawItem.itemState = (lpitem->fState & MF_CHECKED)?ODS_CHECKED:0;
+                drawItem.itemState |= (lpitem->fState & MF_DEFAULT)?ODS_DEFAULT:0;
+                drawItem.itemState |= (lpitem->fState & MF_DISABLED)?ODS_DISABLED:0;
+                drawItem.itemState |= (lpitem->fState & MF_GRAYED)?ODS_GRAYED|ODS_DISABLED:0;
+                drawItem.itemState |= (lpitem->fState & MF_HILITE)?ODS_SELECTED:0;
+                drawItem.itemState |= (!(Menu->fFlags & MNF_UNDERLINE))?ODS_NOACCEL:0;
+                drawItem.itemState |= (Menu->fFlags & MNF_INACTIVE)?ODS_INACTIVE:0;
+                drawItem.hwndItem = (HWND)UserHMGetHandle(Menu);
+                drawItem.hDC = hdc;
+                drawItem.rcItem = *rect;
+                drawItem.itemData = lpitem->dwItemData;
+                /* some applications make this assumption on the DC's origin */
+                GreSetViewportOrgEx( hdc, lpitem->xItem, lpitem->yItem, &origorg);
+                RECTL_vOffsetRect( &drawItem.rcItem, - lpitem->xItem, - lpitem->yItem);
+                co_IntSendMessage( UserHMGetHandle(WndOwner), WM_DRAWITEM, 0, (LPARAM)&drawItem);
+                GreSetViewportOrgEx( hdc, origorg.x, origorg.y, NULL);
+                return;
+            }
+            break;
+
+          case (INT_PTR) HBMMENU_POPUP_CLOSE:
+          case (INT_PTR) HBMMENU_POPUP_RESTORE:
+          case (INT_PTR) HBMMENU_POPUP_MAXIMIZE:
+          case (INT_PTR) HBMMENU_POPUP_MINIMIZE:
+            MENU_DrawPopupGlyph(hdc, &r, (INT_PTR)hbmToDraw, lpitem->fState & MF_GRAYED, lpitem->fState & MF_HILITE);
+            return;
+      }
+      RECTL_vInflateRect(&r, -1, -1);
+      if (lpitem->fState & MF_HILITE) flags |= DFCS_PUSHED;
+      DrawFrameControl(hdc, &r, DFC_CAPTION, flags);
+      return;
+    }
+
+    if (!bmp || !GreGetObject( bmp, sizeof(bm), &bm )) return;
+
+ got_bitmap:
+    hdcMem = NtGdiCreateCompatibleDC( hdc );
+    NtGdiSelectBitmap( hdcMem, bmp );
+    /* handle fontsize > bitmap_height */
+    top = (h>bm.bmHeight) ? rect->top+(h-bm.bmHeight)/2 : rect->top;
+    left=rect->left;
+    rop=((lpitem->fState & MF_HILITE) && !IS_MAGIC_BITMAP(hbmToDraw)) ? NOTSRCCOPY : SRCCOPY;
+    if ((lpitem->fState & MF_HILITE) && lpitem->hbmp)
+        IntGdiSetBkColor(hdc, IntGetSysColor(COLOR_HIGHLIGHT));
+    NtGdiBitBlt( hdc, left, top, w, h, hdcMem, bmp_xoffset, 0, rop , 0, 0);
+    IntGdiDeleteDC( hdcMem, FALSE );
+}
+
+LONG
+IntGetDialogBaseUnits(VOID)
+{
+    static DWORD units;
+
+    if (!units)
+    {
+        HDC hdc;
+        SIZE size;
+
+        if ((hdc = UserGetDCEx(NULL, NULL, DCX_CACHE)))
+        {
+            size.cx = IntGetCharDimensions( hdc, NULL, (PDWORD)&size.cy );
+            if (size.cx) units = MAKELONG( size.cx, size.cy );
+            UserReleaseDC( 0, hdc, FALSE);
+        }
+    }
+    return units;
+}
+
+
+/***********************************************************************
+ *           MenuCalcItemSize
+ *
+ * Calculate the size of the menu item and store it in lpitem->rect.
+ */
+static void FASTCALL MENU_CalcItemSize( HDC hdc, PITEM lpitem, PMENU Menu, PWND pwndOwner,
+                 INT orgX, INT orgY, BOOL menuBar, BOOL textandbmp)
+{
+    WCHAR *p;
+    UINT check_bitmap_width = UserGetSystemMetrics( SM_CXMENUCHECK );
+    UINT arrow_bitmap_width;
+    RECT Rect;
+    INT itemheight = 0;
+
+    TRACE("dc=%x owner=%x (%d,%d)\n", hdc, pwndOwner, orgX, orgY);
+
+    arrow_bitmap_width = gpsi->oembmi[OBI_MNARROW].cx;
+
+    MenuCharSize.cx = IntGetCharDimensions( hdc, NULL, (PDWORD)&MenuCharSize.cy );
+
+    RECTL_vSetRect( &Rect, orgX, orgY, orgX, orgY );
+
+    if (lpitem->fType & MF_OWNERDRAW)
+    {
+        MEASUREITEMSTRUCT mis;
+        mis.CtlType    = ODT_MENU;
+        mis.CtlID      = 0;
+        mis.itemID     = lpitem->wID;
+        mis.itemData   = lpitem->dwItemData;
+        mis.itemHeight = HIWORD( IntGetDialogBaseUnits());
+        mis.itemWidth  = 0;
+        co_IntSendMessage( UserHMGetHandle(pwndOwner), WM_MEASUREITEM, 0, (LPARAM)&mis );
+        /* Tests reveal that Windows ( Win95 thru WinXP) adds twice the average
+         * width of a menufont character to the width of an owner-drawn menu. 
+         */
+        Rect.right += mis.itemWidth + 2 * MenuCharSize.cx;
+        if (menuBar) {
+            /* under at least win95 you seem to be given a standard
+               height for the menu and the height value is ignored */
+            Rect.bottom += UserGetSystemMetrics(SM_CYMENUSIZE);
+        } else
+            Rect.bottom += mis.itemHeight;
+        // Or this,
+        //lpitem->cxBmp = mis.itemWidth;
+        //lpitem->cyBmp = mis.itemHeight;
+        TRACE("MF_OWNERDRAW Height %d Width %d\n",mis.itemHeight,mis.itemWidth);
+        TRACE("MF_OWNERDRAW id=%04lx size=%dx%d cx %d cy %d\n",
+                lpitem->wID, Rect.right-Rect.left,
+                 Rect.bottom-Rect.top, MenuCharSize.cx, MenuCharSize.cy);
+
+        lpitem->xItem = Rect.left;
+        lpitem->yItem = Rect.top;
+        lpitem->cxItem = Rect.right;
+        lpitem->cyItem = Rect.bottom;
+
+        return;
+    }
+
+    lpitem->xItem  = orgX;
+    lpitem->yItem  = orgY; 
+    lpitem->cxItem = orgX;
+    lpitem->cyItem = orgY;
+
+    if (lpitem->fType & MF_SEPARATOR)
+    {
+        lpitem->cyItem += UserGetSystemMetrics( SM_CYMENUSIZE)/2;//SEPARATOR_HEIGHT;
+        if( !menuBar)
+            lpitem->cxItem += arrow_bitmap_width + MenuCharSize.cx;
+        return;
+    }
+
+    lpitem->dxTab = 0;
+
+    if (lpitem->hbmp)
+    {
+        SIZE size;
+
+        if (!menuBar) {
+            MENU_GetBitmapItemSize(lpitem, &size, pwndOwner );
+            /* Keep the size of the bitmap in callback mode to be able
+             * to draw it correctly */
+            lpitem->cxBmp = size.cx;
+            lpitem->cyBmp = size.cy;
+            Menu->cxTextAlign = max(Menu->cxTextAlign, size.cx);
+            lpitem->cxItem += size.cx + 2;
+            itemheight = size.cy + 2;
+
+            if( !((Menu->fFlags & MNS_STYLE_MASK) & MNS_NOCHECK))
+                lpitem->cxItem += 2 * check_bitmap_width;
+            lpitem->cxItem += 4 + MenuCharSize.cx;
+            lpitem->dxTab = lpitem->cxItem;
+            lpitem->cxItem += arrow_bitmap_width;
+        } else /* hbmpItem & MenuBar */ {
+            MENU_GetBitmapItemSize(lpitem, &size, pwndOwner );
+            lpitem->cxItem  += size.cx;
+            if( lpitem->Xlpstr) lpitem->cxItem  += 2;
+            itemheight = size.cy;
+
+            /* Special case: Minimize button doesn't have a space behind it. */
+            if (lpitem->hbmp == (HBITMAP)HBMMENU_MBAR_MINIMIZE ||
+                lpitem->hbmp == (HBITMAP)HBMMENU_MBAR_MINIMIZE_D)
+            lpitem->cxItem -= 1;
+        }
+    }
+    else if (!menuBar) {
+        if( !((Menu->fFlags & MNS_STYLE_MASK) & MNS_NOCHECK))
+             lpitem->cxItem += check_bitmap_width;
+        lpitem->cxItem += 4 + MenuCharSize.cx;
+        lpitem->dxTab = lpitem->cxItem;
+        lpitem->cxItem += arrow_bitmap_width;
+    }
+
+    /* it must be a text item - unless it's the system menu */
+    if (!(lpitem->fType & MF_SYSMENU) && lpitem->Xlpstr) {
+        HFONT hfontOld = NULL;
+        RECT rc;// = lpitem->Rect;
+        LONG txtheight, txtwidth;
+
+        rc.left   = lpitem->xItem;
+        rc.top    = lpitem->yItem; 
+        rc.right  = lpitem->cxItem; // Do this for now......
+        rc.bottom = lpitem->cyItem;
+
+        if ( lpitem->fState & MFS_DEFAULT ) {
+            hfontOld = NtGdiSelectFont( hdc, ghMenuFontBold );
+        }
+        if (menuBar) {
+            txtheight = DrawTextW( hdc, lpitem->Xlpstr, -1, &rc, DT_SINGLELINE|DT_CALCRECT); 
+
+            lpitem->cxItem  += rc.right - rc.left;
+            itemheight = max( max( itemheight, txtheight), UserGetSystemMetrics( SM_CYMENU) - 1);
+
+            lpitem->cxItem +=  2 * MenuCharSize.cx;
+        } else {
+            if ((p = wcschr( lpitem->Xlpstr, '\t' )) != NULL) {
+                RECT tmprc = rc;
+                LONG tmpheight;
+                int n = (int)( p - lpitem->Xlpstr);
+                /* Item contains a tab (only meaningful in popup menus) */
+                /* get text size before the tab */
+                txtheight = DrawTextW( hdc, lpitem->Xlpstr, n, &rc,
+                        DT_SINGLELINE|DT_CALCRECT);
+                txtwidth = rc.right - rc.left;
+                p += 1; /* advance past the Tab */
+                /* get text size after the tab */
+                tmpheight = DrawTextW( hdc, p, -1, &tmprc,
+                        DT_SINGLELINE|DT_CALCRECT);
+                lpitem->dxTab += txtwidth;
+                txtheight = max( txtheight, tmpheight);
+                txtwidth += MenuCharSize.cx + /* space for the tab */
+                    tmprc.right - tmprc.left; /* space for the short cut */
+            } else {
+                txtheight = DrawTextW( hdc, lpitem->Xlpstr, -1, &rc,
+                        DT_SINGLELINE|DT_CALCRECT);
+                txtwidth = rc.right - rc.left;
+                lpitem->dxTab += txtwidth;
+            }
+            lpitem->cxItem  += 2 + txtwidth;
+            itemheight = max( itemheight,
+                                   max( txtheight + 2, MenuCharSize.cy + 4));
+        }
+        if (hfontOld)
+        {
+           NtGdiSelectFont (hdc, hfontOld);
+        }
+    } else if( menuBar) {
+        itemheight = max( itemheight, UserGetSystemMetrics(SM_CYMENU)-1);
+    }
+    lpitem->cyItem += itemheight;
+    TRACE("(%ld,%ld)-(%ld,%ld)\n", lpitem->xItem, lpitem->yItem, lpitem->cxItem, lpitem->cyItem);
+}
+
+/***********************************************************************
+ *           MENU_GetMaxPopupHeight
+ */
+static UINT
+MENU_GetMaxPopupHeight(PMENU lppop)
+{
+    if (lppop->cyMax)
+    {
+       //ERR("MGMaxPH cyMax %d\n",lppop->cyMax);
+       return lppop->cyMax;
+    }
+    //ERR("MGMaxPH SyMax %d\n",UserGetSystemMetrics(SM_CYSCREEN) - UserGetSystemMetrics(SM_CYBORDER));
+    return UserGetSystemMetrics(SM_CYSCREEN) - UserGetSystemMetrics(SM_CYBORDER);
+}
+
+/***********************************************************************
+ *           MenuPopupMenuCalcSize
+ *
+ * Calculate the size of a popup menu.
+ */
+static void FASTCALL MENU_PopupMenuCalcSize(PMENU Menu, PWND WndOwner)
+{
+    PITEM lpitem;
+    HDC hdc;
+    int start, i;
+    int orgX, orgY, maxX, maxTab, maxTabWidth, maxHeight;
+    BOOL textandbmp = FALSE;
+
+    Menu->cxMenu = Menu->cyMenu = 0;
+    if (Menu->cItems == 0) return;
+
+    hdc = UserGetDCEx(NULL, NULL, DCX_CACHE);
+
+    NtGdiSelectFont( hdc, ghMenuFont );
+
+    start = 0;
+    maxX = 2 + 1;
+
+    Menu->cxTextAlign = 0;
+
+    while (start < Menu->cItems)
+    {
+      lpitem = &Menu->rgItems[start];
+      orgX = maxX;
+      if( lpitem->fType & (MF_MENUBREAK | MF_MENUBARBREAK))
+          orgX += MENU_COL_SPACE;
+      orgY = MENU_TOP_MARGIN;
+
+      maxTab = maxTabWidth = 0;
+      /* Parse items until column break or end of menu */
+      for (i = start; i < Menu->cItems; i++, lpitem++)
+      {
+          if (i != start &&
+               (lpitem->fType & (MF_MENUBREAK | MF_MENUBARBREAK))) break;
+
+          MENU_CalcItemSize(hdc, lpitem, Menu, WndOwner, orgX, orgY, FALSE, textandbmp);
+          maxX = max(maxX, lpitem->cxItem);
+          orgY = lpitem->cyItem;
+          if (IS_STRING_ITEM(lpitem->fType) && lpitem->dxTab )
+          {
+              maxTab = max( maxTab, lpitem->dxTab );
+              maxTabWidth = max(maxTabWidth, lpitem->cxItem - lpitem->dxTab);
+          }
+          if( lpitem->Xlpstr && lpitem->hbmp) textandbmp = TRUE;
+      }
+
+        /* Finish the column (set all items to the largest width found) */
+      maxX = max( maxX, maxTab + maxTabWidth );
+      for (lpitem = &Menu->rgItems[start]; start < i; start++, lpitem++)
+      {
+          lpitem->cxItem = maxX;
+           if (IS_STRING_ITEM(lpitem->fType) && lpitem->dxTab)
+               lpitem->dxTab = maxTab;
+      }
+      Menu->cyMenu = max(Menu->cyMenu, orgY);
+    }
+
+    Menu->cxMenu  = maxX;
+    /* if none of the items have both text and bitmap then
+     * the text and bitmaps are all aligned on the left. If there is at
+     * least one item with both text and bitmap then bitmaps are
+     * on the left and texts left aligned with the right hand side
+     * of the bitmaps */
+    if( !textandbmp) Menu->cxTextAlign = 0;
+
+    /* space for 3d border */
+    Menu->cyMenu += MENU_BOTTOM_MARGIN;
+    Menu->cxMenu += 2;
+
+    /* Adjust popup height if it exceeds maximum */
+    maxHeight = MENU_GetMaxPopupHeight(Menu);
+    Menu->iMaxTop = Menu->cyMenu - MENU_TOP_MARGIN;
+    if (Menu->cyMenu >= maxHeight)
+    {
+       Menu->cyMenu = maxHeight;
+       Menu->dwArrowsOn = 1;
+    }
+    else
+    {   
+       Menu->dwArrowsOn = 0;
+    }
+    UserReleaseDC( 0, hdc, FALSE );
+}
+
+/***********************************************************************
+ *           MENU_MenuBarCalcSize
+ *
+ * FIXME: Word 6 implements its own MDI and its own 'close window' bitmap
+ * height is off by 1 pixel which causes lengthy window relocations when
+ * active document window is maximized/restored.
+ *
+ * Calculate the size of the menu bar.
+ */
+static void MENU_MenuBarCalcSize( HDC hdc, LPRECT lprect, PMENU lppop, PWND pwndOwner )
+{
+    ITEM *lpitem;
+    UINT start, i, helpPos;
+    int orgX, orgY, maxY;
+
+    if ((lprect == NULL) || (lppop == NULL)) return;
+    if (lppop->cItems == 0) return;
+    //TRACE("lprect %p %s\n", lprect, wine_dbgstr_rect( lprect));
+    lppop->cxMenu  = lprect->right - lprect->left;
+    lppop->cyMenu = 0;
+    maxY = lprect->top+1;
+    start = 0;
+    helpPos = ~0U;
+    lppop->cxTextAlign = 0;
+    while (start < lppop->cItems)
+    {
+       lpitem = &lppop->rgItems[start];
+       orgX = lprect->left;
+       orgY = maxY;
+
+         /* Parse items until line break or end of menu */
+       for (i = start; i < lppop->cItems; i++, lpitem++)
+       {
+           if ((helpPos == ~0U) && (lpitem->fType & MF_RIGHTJUSTIFY)) helpPos = i;
+           if ((i != start) &&
+               (lpitem->fType & (MF_MENUBREAK | MF_MENUBARBREAK))) break;
+
+           TRACE("calling MENU_CalcItemSize org=(%d, %d)\n", orgX, orgY );
+           //debug_print_menuitem ("  item: ", lpitem, "");
+           //MENU_CalcItemSize( hdc, lpitem, pwndOwner, orgX, orgY, TRUE, lppop );
+            MENU_CalcItemSize(hdc, lpitem, lppop, pwndOwner, orgX, orgY, TRUE, FALSE);
+
+           if (lpitem->cxItem > lprect->right)
+           {
+               if (i != start) break;
+               else lpitem->cxItem = lprect->right;
+           }
+           maxY = max( maxY, lpitem->cyItem );
+           orgX = lpitem->cxItem;
+       }
+
+         /* Finish the line (set all items to the largest height found) */
+
+/* FIXME: Is this really needed? */ /*NO! it is not needed, why make the
+   HBMMENU_MBAR_CLOSE, MINIMIZE & RESTORE, look the same size as the menu bar! */
+#if 0
+       while (start < i) lppop->rgItems[start++].cyItem = maxY;
+#endif
+       start = i; /* This works! */
+    }
+
+    lprect->bottom = maxY;
+    lppop->cyMenu = lprect->bottom - lprect->top;
+
+    /* Flush right all items between the MF_RIGHTJUSTIFY and */
+    /* the last item (if several lines, only move the last line) */
+    if (helpPos == ~0U) return;
+    lpitem = &lppop->rgItems[lppop->cItems-1];
+    orgY = lpitem->yItem;
+    orgX = lprect->right;
+    for (i = lppop->cItems - 1; i >= helpPos; i--, lpitem--) {
+        if (lpitem->yItem != orgY) break;      /* Other line */
+        if (lpitem->cxItem >= orgX) break;     /* Too far right already */
+        lpitem->xItem += orgX - lpitem->cxItem;
+        lpitem->cxItem = orgX;
+        orgX = lpitem->xItem;
+    }
+}
+
+/***********************************************************************
+ *           MENU_DrawScrollArrows
+ *
+ * Draw scroll arrows.
+ */
+static void MENU_DrawScrollArrows(PMENU lppop, HDC hdc)
+{
+    UINT arrow_bitmap_width, arrow_bitmap_height;
+    RECT rect, dfcrc;
+    UINT Flags = 0;
+
+    arrow_bitmap_width  = gpsi->oembmi[OBI_DNARROW].cx;
+    arrow_bitmap_height = gpsi->oembmi[OBI_DNARROW].cy;
+
+    rect.left = 0;
+    rect.top = 0;
+    rect.right = lppop->cxMenu;
+    rect.bottom = arrow_bitmap_height;
+    FillRect(hdc, &rect, IntGetSysColorBrush(COLOR_MENU));
+    dfcrc.left = (lppop->cxMenu - arrow_bitmap_width) / 2;
+    dfcrc.top = 0;
+    dfcrc.right = arrow_bitmap_width;
+    dfcrc.bottom = arrow_bitmap_height;
+    DrawFrameControl(hdc, &dfcrc, DFC_MENU, (lppop->iTop ? 0 : DFCS_INACTIVE)|DFCS_MENUARROWUP);
+
+    rect.top = lppop->cyMenu - arrow_bitmap_height;
+    rect.bottom = lppop->cyMenu;
+    FillRect(hdc, &rect, IntGetSysColorBrush(COLOR_MENU));
+    if (!(lppop->iTop < lppop->iMaxTop - (MENU_GetMaxPopupHeight(lppop) - 2 * arrow_bitmap_height)))
+       Flags = DFCS_INACTIVE;
+    dfcrc.left = (lppop->cxMenu - arrow_bitmap_width) / 2;
+    dfcrc.top = lppop->cyMenu - arrow_bitmap_height;
+    dfcrc.right = arrow_bitmap_width;
+    dfcrc.bottom = lppop->cyMenu;
+    DrawFrameControl(hdc, &dfcrc, DFC_MENU, Flags|DFCS_MENUARROWDOWN);
+}
+
+/***********************************************************************
+ *           MenuDrawMenuItem
+ *
+ * Draw a single menu item.
+ */
+static void FASTCALL MENU_DrawMenuItem(PWND Wnd, PMENU Menu, PWND WndOwner, HDC hdc,
+                 PITEM lpitem, UINT Height, BOOL menuBar, UINT odaction)
+{
+    RECT rect;
+    PWCHAR Text;
+    BOOL flat_menu = FALSE;
+    int bkgnd;
+    UINT arrow_bitmap_width = 0;
+    //RECT bmprc;
+
+    if (!menuBar) {
+        arrow_bitmap_width  = gpsi->oembmi[OBI_MNARROW].cx; 
+    }
+
+    if (lpitem->fType & MF_SYSMENU)
+    {
+        if (!(Wnd->style & WS_MINIMIZE))
+        {
+          NC_GetInsideRect(Wnd, &rect);
+          UserDrawSysMenuButton(Wnd, hdc, &rect, lpitem->fState & (MF_HILITE | MF_MOUSESELECT));
+       }
+        return;
+    }
+
+    UserSystemParametersInfo (SPI_GETFLATMENU, 0, &flat_menu, 0);
+    bkgnd = (menuBar && flat_menu) ? COLOR_MENUBAR : COLOR_MENU;
+  
+    /* Setup colors */
+
+    if (lpitem->fState & MF_HILITE)
+    {
+        if(menuBar && !flat_menu) {
+            IntGdiSetTextColor(hdc, IntGetSysColor(COLOR_MENUTEXT));
+            IntGdiSetBkColor(hdc, IntGetSysColor(COLOR_MENU));
+        } else {
+            if (lpitem->fState & MF_GRAYED)
+                IntGdiSetTextColor(hdc, IntGetSysColor(COLOR_GRAYTEXT));
+            else
+                IntGdiSetTextColor(hdc, IntGetSysColor(COLOR_HIGHLIGHTTEXT));
+            IntGdiSetBkColor(hdc, IntGetSysColor(COLOR_HIGHLIGHT));
+        }
+    }
+    else
+    {
+        if (lpitem->fState & MF_GRAYED)
+            IntGdiSetTextColor( hdc, IntGetSysColor( COLOR_GRAYTEXT ) );
+        else
+            IntGdiSetTextColor( hdc, IntGetSysColor( COLOR_MENUTEXT ) );
+        IntGdiSetBkColor( hdc, IntGetSysColor( bkgnd ) );
+    }
+
+    //TRACE("rect=%s\n", wine_dbgstr_rect( &lpitem->Rect));
+    //rect = lpitem->Rect;
+    rect.left   = lpitem->xItem;
+    rect.top    = lpitem->yItem; 
+    rect.right  = lpitem->cxItem; // Do this for now......
+    rect.bottom = lpitem->cyItem;
+
+    MENU_AdjustMenuItemRect(Menu, &rect);
+
+    if (lpitem->fType & MF_OWNERDRAW)
+    {
+        /*
+        ** Experimentation under Windows reveals that an owner-drawn
+        ** menu is given the rectangle which includes the space it requested
+        ** in its response to WM_MEASUREITEM _plus_ width for a checkmark
+        ** and a popup-menu arrow.  This is the value of lpitem->rect.
+        ** Windows will leave all drawing to the application except for
+        ** the popup-menu arrow.  Windows always draws that itself, after
+        ** the menu owner has finished drawing.
+        */
+        DRAWITEMSTRUCT dis;
+        COLORREF old_bk, old_text;
+
+        dis.CtlType   = ODT_MENU;
+        dis.CtlID     = 0;
+        dis.itemID    = lpitem->wID;
+        dis.itemData  = (DWORD)lpitem->dwItemData;
+        dis.itemState = 0;
+        if (lpitem->fState & MF_CHECKED)  dis.itemState |= ODS_CHECKED;
+        if (lpitem->fState & MF_DEFAULT)  dis.itemState |= ODS_DEFAULT;
+        if (lpitem->fState & MF_DISABLED) dis.itemState |= ODS_DISABLED;
+        if (lpitem->fState & MF_GRAYED)   dis.itemState |= ODS_GRAYED | ODS_DISABLED;
+        if (lpitem->fState & MF_HILITE)   dis.itemState |= ODS_SELECTED;
+        if (!(Menu->fFlags & MNF_UNDERLINE)) dis.itemState |= ODS_NOACCEL;
+        if (Menu->fFlags & MNF_INACTIVE) dis.itemState |= ODS_INACTIVE;
+        dis.itemAction = odaction; /* ODA_DRAWENTIRE | ODA_SELECT | ODA_FOCUS; */
+        dis.hwndItem   = (HWND) UserHMGetHandle(Menu);
+        dis.hDC        = hdc;
+        dis.rcItem     = rect;
+        TRACE("Ownerdraw: owner=%p itemID=%d, itemState=%d, itemAction=%d, "
+               "hwndItem=%p, hdc=%p, rcItem={%ld,%ld,%ld,%ld}\n", Wnd,
+               dis.itemID, dis.itemState, dis.itemAction, dis.hwndItem,
+               dis.hDC, dis.rcItem.left, dis.rcItem.top, dis.rcItem.right,
+               dis.rcItem.bottom);
+        TRACE("Ownerdraw: Width %d Height %d\n", dis.rcItem.right-dis.rcItem.left, dis.rcItem.bottom-dis.rcItem.top);
+        old_bk = GreGetBkColor(hdc);
+        old_text = GreGetTextColor(hdc);
+        co_IntSendMessage(UserHMGetHandle(WndOwner), WM_DRAWITEM, 0, (LPARAM) &dis);
+        IntGdiSetBkColor(hdc, old_bk);
+        IntGdiSetTextColor(hdc, old_text);
+        /* Draw the popup-menu arrow */
+        if (!menuBar && lpitem->spSubMenu)
+        {
+            RECT rectTemp;
+            RtlCopyMemory(&rectTemp, &rect, sizeof(RECT));
+            rectTemp.left = rectTemp.right - UserGetSystemMetrics(SM_CXMENUCHECK);
+            DrawFrameControl(hdc, &rectTemp, DFC_MENU, DFCS_MENUARROW);
+        }
+        return;
+    }
+
+    if (menuBar && (lpitem->fType & MF_SEPARATOR)) return;
+
+    if (lpitem->fState & MF_HILITE)
+    {
+        if (flat_menu)
+        {
+            RECTL_vInflateRect (&rect, -1, -1);
+            FillRect(hdc, &rect, IntGetSysColorBrush(COLOR_MENUHILIGHT));
+            RECTL_vInflateRect (&rect, 1, 1);
+            FrameRect(hdc, &rect, IntGetSysColorBrush(COLOR_HIGHLIGHT));
+        }
+        else
+        {
+            if(menuBar)
+                DrawEdge(hdc, &rect, BDR_SUNKENOUTER, BF_RECT);
+            else
+                FillRect(hdc, &rect, IntGetSysColorBrush(COLOR_HIGHLIGHT));
+        }
+    }
+    else
+        FillRect( hdc, &rect, IntGetSysColorBrush(bkgnd) );
+
+    IntGdiSetBkMode( hdc, TRANSPARENT );
+
+    /* vertical separator */
+    if (!menuBar && (lpitem->fType & MF_MENUBARBREAK))
+    {
+        HPEN oldPen;
+        RECT rc = rect;
+
+        rc.left -= 3;//MENU_COL_SPACE / 2 + 1; == 3!!
+        rc.top = 3;
+        rc.bottom = Height - 3;
+        if (flat_menu)
+        {
+            oldPen = NtGdiSelectPen( hdc, NtGdiGetStockObject(DC_PEN) );
+            IntSetDCPenColor(hdc, IntGetSysColor(COLOR_BTNSHADOW));
+            GreMoveTo( hdc, rc.left, rc.top, NULL );
+            NtGdiLineTo( hdc, rc.left, rc.bottom );
+            NtGdiSelectPen( hdc, oldPen );
+        }
+        else
+            DrawEdge (hdc, &rc, EDGE_ETCHED, BF_LEFT);
+    }
+
+    /* horizontal separator */
+    if (lpitem->fType & MF_SEPARATOR)
+    {
+        HPEN oldPen;
+        RECT rc = rect;
+
+        rc.left++;
+        rc.right--;
+        rc.top = ( rc.top + rc.bottom) / 2;
+        if (flat_menu)
+        {
+            oldPen = NtGdiSelectPen( hdc, NtGdiGetStockObject(DC_PEN) );
+            IntSetDCPenColor( hdc, IntGetSysColor(COLOR_BTNSHADOW));
+            GreMoveTo( hdc, rc.left, rc.top, NULL );
+            NtGdiLineTo( hdc, rc.right, rc.top );
+            NtGdiSelectPen( hdc, oldPen );
+        }
+        else
+            DrawEdge (hdc, &rc, EDGE_ETCHED, BF_TOP);
+        return;
+    }
+#if 0
+    /* helper lines for debugging */
+    /* This is a very good test tool when hacking menus! (JT) 07/16/2006 */
+    FrameRect(hdc, &rect, NtGdiGetStockObject(BLACK_BRUSH));
+    NtGdiSelectPen(hdc, NtGdiGetStockObject(DC_PEN));
+    IntSetDCPenColor(hdc, IntGetSysColor(COLOR_WINDOWFRAME));
+    GreMoveTo(hdc, rect.left, (rect.top + rect.bottom) / 2, NULL);
+    NtGdiLineTo(hdc, rect.right, (rect.top + rect.bottom) / 2);
+#endif
+#if 0 // breaks mdi menu bar icons.
+    if (lpitem->hbmp) {
+        /* calculate the bitmap rectangle in coordinates relative
+         * to the item rectangle */
+        if( menuBar) {
+            if( lpitem->hbmp == HBMMENU_CALLBACK)
+                bmprc.left = 3;
+            else 
+                bmprc.left = lpitem->Xlpstr ? MenuCharSize.cx : 0;          
+        }
+        else if ((Menu->fFlags & MNS_STYLE_MASK) & MNS_NOCHECK)
+            bmprc.left = 4;
+        else if ((Menu->fFlags & MNS_STYLE_MASK) & MNS_CHECKORBMP)
+            bmprc.left = 2;
+        else
+            bmprc.left = 4 + UserGetSystemMetrics(SM_CXMENUCHECK);
+
+        bmprc.right =  bmprc.left + lpitem->cxBmp;
+
+        if( menuBar && !(lpitem->hbmp == HBMMENU_CALLBACK))
+            bmprc.top = 0;
+        else
+            bmprc.top = (rect.bottom - rect.top - lpitem->cyBmp) / 2; 
+
+        bmprc.bottom =  bmprc.top + lpitem->cyBmp;
+    }
+#endif
+    if (!menuBar)
+    {
+        HBITMAP bm;
+        INT y = rect.top + rect.bottom;
+        RECT rc = rect;
+        BOOL checked = FALSE;
+        UINT check_bitmap_width = UserGetSystemMetrics( SM_CXMENUCHECK );
+        UINT check_bitmap_height = UserGetSystemMetrics( SM_CYMENUCHECK );
+        /* Draw the check mark
+         *
+         * FIXME:
+         * Custom checkmark bitmaps are monochrome but not always 1bpp.
+         */
+        if( !((Menu->fFlags & MNS_STYLE_MASK) & MNS_NOCHECK)) {
+            bm = (lpitem->fState & MF_CHECKED) ? lpitem->hbmpChecked : 
+                lpitem->hbmpUnchecked;
+            if (bm)  /* we have a custom bitmap */
+            {
+                HDC hdcMem = NtGdiCreateCompatibleDC( hdc );
+
+                NtGdiSelectBitmap( hdcMem, bm );
+                NtGdiBitBlt( hdc, rc.left, (y - check_bitmap_height) / 2,
+                        check_bitmap_width, check_bitmap_height,
+                        hdcMem, 0, 0, SRCCOPY, 0,0);
+                IntGdiDeleteDC( hdcMem, FALSE );
+                checked = TRUE;
+            }
+            else if (lpitem->fState & MF_CHECKED) /* standard bitmaps */
+            {
+                RECT r;
+                r = rect;
+                r.right = r.left + check_bitmap_width;
+                DrawFrameControl( hdc, &r, DFC_MENU,
+                                 (lpitem->fType & MFT_RADIOCHECK) ?
+                                 DFCS_MENUBULLET : DFCS_MENUCHECK);
+                checked = TRUE;
+            }
+        }
+        if ( lpitem->hbmp )//&& !( checked && ((Menu->fFlags & MNS_STYLE_MASK) & MNS_CHECKORBMP)))
+        {
+            RECT bmpRect = rect;
+            if (!((Menu->fFlags & MNS_STYLE_MASK) & MNS_CHECKORBMP) && !((Menu->fFlags & MNS_STYLE_MASK) & MNS_NOCHECK))
+                bmpRect.left += check_bitmap_width + 2;
+            if (!(checked && ((Menu->fFlags & MNS_STYLE_MASK) & MNS_CHECKORBMP)))
+            {
+                bmpRect.right = bmpRect.left + lpitem->cxBmp;
+                MENU_DrawBitmapItem(hdc, lpitem, &bmpRect, Menu, WndOwner, odaction, menuBar);
+            }
+        }
+        /* Draw the popup-menu arrow */
+        if (lpitem->spSubMenu)
+        {
+            RECT rectTemp;
+            RtlCopyMemory(&rectTemp, &rect, sizeof(RECT));
+            rectTemp.left = rectTemp.right - check_bitmap_width;
+            DrawFrameControl(hdc, &rectTemp, DFC_MENU, DFCS_MENUARROW);
+        }
+        rect.left += 4;
+        if( !((Menu->fFlags & MNS_STYLE_MASK) & MNS_NOCHECK))
+            rect.left += check_bitmap_width;
+        rect.right -= arrow_bitmap_width;
+    }
+    else if( lpitem->hbmp)
+    { /* Draw the bitmap */
+        MENU_DrawBitmapItem(hdc, lpitem, &rect/*bmprc*/, Menu, WndOwner, odaction, menuBar);
+    }
+
+    /* process text if present */
+    if (lpitem->Xlpstr)
+    {
+        int i = 0;
+        HFONT hfontOld = 0;
+
+        UINT uFormat = menuBar ?
+                       DT_CENTER | DT_VCENTER | DT_SINGLELINE :
+                       DT_LEFT | DT_VCENTER | DT_SINGLELINE;
+
+        if (((Menu->fFlags & MNS_STYLE_MASK) & MNS_CHECKORBMP))
+             rect.left += max(0, (int)(Menu->cxTextAlign - UserGetSystemMetrics(SM_CXMENUCHECK)));
+        else
+             rect.left += Menu->cxTextAlign;
+
+        if ( lpitem->fState & MFS_DEFAULT )
+        {
+            hfontOld = NtGdiSelectFont(hdc, ghMenuFontBold);            
+        }
+
+        if (menuBar) {
+            if( lpitem->hbmp)
+              rect.left += lpitem->cxBmp;
+            if( !(lpitem->hbmp == HBMMENU_CALLBACK)) 
+              rect.left += MenuCharSize.cx;
+            rect.right -= MenuCharSize.cx;
+        }
+
+        Text = lpitem->Xlpstr;
+        if(Text)
+        {
+            for (i = 0; Text[i]; i++)
+                if (Text[i] == L'\t' || Text[i] == L'\b')
+                    break;
+        }
+
+        if(lpitem->fState & MF_GRAYED)
+        {
+            if (!(lpitem->fState & MF_HILITE) )
+            {
+                ++rect.left; ++rect.top; ++rect.right; ++rect.bottom;
+                IntGdiSetTextColor(hdc, RGB(0xff, 0xff, 0xff));
+                DrawTextW( hdc, Text, i, &rect, uFormat );
+                --rect.left; --rect.top; --rect.right; --rect.bottom;
+            }
+            IntGdiSetTextColor(hdc, RGB(0x80, 0x80, 0x80));
+        }
+        DrawTextW( hdc, Text, i, &rect, uFormat);
+
+        /* paint the shortcut text */
+        if (!menuBar && L'\0' != Text[i])  /* There's a tab or flush-right char */
+        {
+            if (L'\t' == Text[i])
+            {
+                rect.left = lpitem->dxTab;
+                uFormat = DT_LEFT | DT_VCENTER | DT_SINGLELINE;
+            }
+            else
+            {
+                rect.right = lpitem->dxTab;
+                uFormat = DT_RIGHT | DT_VCENTER | DT_SINGLELINE;
+            }
+
+            if (lpitem->fState & MF_GRAYED)
+            {
+                if (!(lpitem->fState & MF_HILITE) )
+                {
+                    ++rect.left; ++rect.top; ++rect.right; ++rect.bottom;
+                    IntGdiSetTextColor(hdc, RGB(0xff, 0xff, 0xff));
+                    DrawTextW( hdc, Text + i + 1, -1, &rect, uFormat);
+                    --rect.left; --rect.top; --rect.right; --rect.bottom;
+                }
+                IntGdiSetTextColor(hdc, RGB(0x80, 0x80, 0x80));
+            }
+            DrawTextW( hdc, Text + i + 1, -1, &rect, uFormat );
+        }
+
+        if (hfontOld)
+        {
+           NtGdiSelectFont (hdc, hfontOld);
+        }
+    }
+}
+
+/***********************************************************************
+ *           MenuDrawPopupMenu
+ *
+ * Paint a popup menu.
+ */
+static void FASTCALL MENU_DrawPopupMenu(PWND wnd, HDC hdc, PMENU menu )
+{
+    HBRUSH hPrevBrush = 0, brush = IntGetSysColorBrush(COLOR_MENU);
+    RECT rect;
+
+    TRACE("DPM wnd=%p dc=%p menu=%p\n", wnd, hdc, menu);
+
+    IntGetClientRect( wnd, &rect );
+
+    if (menu && menu->hbrBack) brush = menu->hbrBack;
+    if((hPrevBrush = NtGdiSelectBrush( hdc, brush ))
+        && (NtGdiSelectFont( hdc, ghMenuFont)))
+    {
+        HPEN hPrevPen;
+
+        NtGdiRectangle( hdc, rect.left, rect.top, rect.right, rect.bottom );
+
+        hPrevPen = NtGdiSelectPen( hdc, NtGdiGetStockObject( NULL_PEN ) );
+        if ( hPrevPen )
+        {
+            BOOL flat_menu = FALSE;
+
+            UserSystemParametersInfo (SPI_GETFLATMENU, 0, &flat_menu, 0);
+            if (flat_menu)
+               FrameRect(hdc, &rect, IntGetSysColorBrush(COLOR_BTNSHADOW));
+            else
+               DrawEdge (hdc, &rect, EDGE_RAISED, BF_RECT);
+
+            TRACE("hmenu %p Style %08x\n", UserHMGetHandle(menu), (menu->fFlags & MNS_STYLE_MASK));
+            /* draw menu items */
+            if (menu && menu->cItems)
+            {
+                ITEM *item;
+                UINT u;
+
+                item = menu->rgItems;
+                for( u = menu->cItems; u > 0; u--, item++)
+                {
+                    MENU_DrawMenuItem(wnd, menu, menu->spwndNotify, hdc, item,
+                                         menu->cyMenu, FALSE, ODA_DRAWENTIRE);
+                }
+                /* draw scroll arrows */
+                if (menu->dwArrowsOn)
+                {
+                   MENU_DrawScrollArrows(menu, hdc);
+                }
+            }
+        }
+        else
+        {
+            NtGdiSelectBrush( hdc, hPrevBrush );
+        }
+    }
+}
+
+/**********************************************************************
+ *         MENU_IsMenuActive
+ */
+PWND MENU_IsMenuActive(VOID)
+{
+   return ValidateHwndNoErr(top_popup);
+}
+
+/**********************************************************************
+ *         MENU_EndMenu
+ *
+ * Calls EndMenu() if the hwnd parameter belongs to the menu owner
+ *
+ * Does the (menu stuff) of the default window handling of WM_CANCELMODE
+ */
+void MENU_EndMenu( PWND pwnd )
+{
+    PMENU menu = NULL;
+    menu = UserGetMenuObject(top_popup_hmenu);
+    if ( menu && ( UserHMGetHandle(pwnd) == menu->hWnd || pwnd == menu->spwndNotify ) )
+    {
+       if (fInsideMenuLoop && top_popup)
+       {
+          fInsideMenuLoop = FALSE;
+
+          if (fInEndMenu)
+          {
+             ERR("Already in End loop\n");
+             return;
+          }
+
+          fInEndMenu = TRUE;
+          UserPostMessage( top_popup, WM_CANCELMODE, 0, 0);
+       }
+    }
+}
+
+DWORD WINAPI
+IntDrawMenuBarTemp(PWND pWnd, HDC hDC, LPRECT Rect, PMENU pMenu, HFONT Font)
+{
+  UINT i;
+  HFONT FontOld = NULL;
+  BOOL flat_menu = FALSE;
+
+  UserSystemParametersInfo(SPI_GETFLATMENU, 0, &flat_menu, 0);
+
+  if (!pMenu)
+  {
+      pMenu = UserGetMenuObject(UlongToHandle(pWnd->IDMenu));
+  }
+
+  if (!Font)
+  {
+      Font = ghMenuFont;
+  }
+
+  if (Rect == NULL || !pMenu)
+  {
+      return UserGetSystemMetrics(SM_CYMENU);
+  }
+
+  TRACE("(%x, %x, %p, %x, %x)\n", pWnd, hDC, Rect, pMenu, Font);
+
+  FontOld = NtGdiSelectFont(hDC, Font);
+
+  if (pMenu->cyMenu == 0)
+  {
+      MENU_MenuBarCalcSize(hDC, Rect, pMenu, pWnd);
+  }
+
+  Rect->bottom = Rect->top + pMenu->cyMenu;
+
+  FillRect(hDC, Rect, IntGetSysColorBrush(flat_menu ? COLOR_MENUBAR : COLOR_MENU));
+
+  NtGdiSelectPen(hDC, NtGdiGetStockObject(DC_PEN));
+  IntSetDCPenColor(hDC, IntGetSysColor(COLOR_3DFACE));
+  GreMoveTo(hDC, Rect->left, Rect->bottom - 1, NULL);
+  NtGdiLineTo(hDC, Rect->right, Rect->bottom - 1);
+
+  if (pMenu->cItems == 0)
+  {
+      NtGdiSelectFont(hDC, FontOld);
+      return UserGetSystemMetrics(SM_CYMENU);
+  }
+
+  for (i = 0; i < pMenu->cItems; i++)
+  {
+      MENU_DrawMenuItem(pWnd, pMenu, pWnd, hDC, &pMenu->rgItems[i], pMenu->cyMenu, TRUE, ODA_DRAWENTIRE);
+  }
+
+  NtGdiSelectFont(hDC, FontOld);
+
+  return pMenu->cyMenu;
+}
+
+UINT MENU_DrawMenuBar( HDC hDC, LPRECT lprect, PWND pWnd, BOOL suppress_draw )
+{
+    HFONT hfontOld = 0;
+    PMENU lppop = UserGetMenuObject(UlongToHandle(pWnd->IDMenu));
+
+    if (lppop == NULL)
+    {
+        // No menu. Do not reserve any space
+        return 0;
+    }
+
+    if (lprect == NULL)
+    {
+        return UserGetSystemMetrics(SM_CYMENU);
+    }
+
+    if (suppress_draw)
+    {
+       hfontOld = NtGdiSelectFont(hDC, ghMenuFont);
+
+       MENU_MenuBarCalcSize(hDC, lprect, lppop, pWnd);
+
+       lprect->bottom = lprect->top + lppop->cyMenu;
+
+       if (hfontOld) NtGdiSelectFont( hDC, hfontOld);
+
+       return lppop->cyMenu;
+    }   
+    else
+    {
+       return IntDrawMenuBarTemp(pWnd, hDC, lprect, lppop, NULL);
+    }
+}
+
+/***********************************************************************
+ *           MENU_InitPopup
+ *   
+ * Popup menu initialization before WM_ENTERMENULOOP.
+ */
+static BOOL MENU_InitPopup( PWND pWndOwner, PMENU menu, UINT flags )
+{
+    PWND pWndCreated;
+    PPOPUPMENU pPopupMenu;
+    CREATESTRUCTW Cs;
+    LARGE_STRING WindowName;
+    UNICODE_STRING ClassName;
+    DWORD ex_style = WS_EX_TOOLWINDOW;
+
+    TRACE("owner=%p hmenu=%p\n", pWndOwner, menu);
+
+    menu->spwndNotify = pWndOwner;
+
+    if (flags & TPM_LAYOUTRTL || pWndOwner->ExStyle & WS_EX_LAYOUTRTL)
+       ex_style = WS_EX_LAYOUTRTL;
+
+    ClassName.Buffer = WC_MENU;
+    ClassName.Length = 0;
+
+    RtlZeroMemory(&WindowName, sizeof(WindowName));
+    RtlZeroMemory(&Cs, sizeof(Cs));
+    Cs.style = WS_POPUP;
+    Cs.dwExStyle = ex_style;
+    Cs.hInstance = hModClient; // hModuleWin; // Server side winproc!
+    Cs.lpszName = (LPCWSTR) &WindowName;
+    Cs.lpszClass = (LPCWSTR) &ClassName;
+    Cs.lpCreateParams = UserHMGetHandle(menu);
+    Cs.hwndParent = UserHMGetHandle(pWndOwner);
+
+    /* NOTE: In Windows, top menu popup is not owned. */
+    pWndCreated = co_UserCreateWindowEx( &Cs, &ClassName, &WindowName, NULL);
+
+    if( !pWndCreated ) return FALSE;
+
+    //
+    //  Setup pop up menu structure.
+    //
+    menu->hWnd = UserHMGetHandle(pWndCreated);
+
+    pPopupMenu = ((PMENUWND)pWndCreated)->ppopupmenu;
+
+    pPopupMenu->spwndActivePopup = pWndCreated; // top_popup = MenuInfo.Wnd or menu->hWnd
+    pPopupMenu->spwndNotify = pWndOwner;        // Same as MenuInfo.spwndNotify(which could be wrong) or menu->hwndOwner
+    //pPopupMenu->spmenu = menu; Should be set up already from WM_CREATE!
+
+    pPopupMenu->fIsTrackPopup = !!(flags & TPM_POPUPMENU);
+    pPopupMenu->fIsSysMenu    = !!(flags & TPM_SYSTEM_MENU);
+    pPopupMenu->fNoNotify     = !!(flags & TPM_NONOTIFY);
+    pPopupMenu->fRightButton  = !!(flags & TPM_RIGHTBUTTON);
+    pPopupMenu->fSynchronous  = !!(flags & TPM_RETURNCMD);
+
+    if (pPopupMenu->fRightButton)
+       pPopupMenu->fFirstClick = !!(UserGetKeyState(VK_RBUTTON) & 0x8000);
+    else
+       pPopupMenu->fFirstClick = !!(UserGetKeyState(VK_LBUTTON) & 0x8000);
+
+    if (gpsi->aiSysMet[SM_MENUDROPALIGNMENT] ||
+        menu->fFlags & MNF_RTOL)
+    {
+       pPopupMenu->fDroppedLeft = TRUE;
+    }
+    return TRUE;
+}
+
+/***********************************************************************
+ *           MenuShowPopup
+ *
+ * Display a popup menu.
+ */
+static BOOL FASTCALL MENU_ShowPopup(PWND pwndOwner, PMENU menu, UINT id, UINT flags,
+                              INT x, INT y, INT xanchor, INT yanchor )
+{
+    UINT width, height;
+    POINT pt;
+    PMONITOR monitor;
+    PWND pWnd;
+    USER_REFERENCE_ENTRY Ref;
+
+    TRACE("owner=%p menu=%p id=0x%04x x=0x%04x y=0x%04x xa=0x%04x ya=0x%04x\n",
+          pwndOwner, menu, id, x, y, xanchor, yanchor);
+
+    if (menu->iItem != NO_SELECTED_ITEM)
+    {
+        menu->rgItems[menu->iItem].fState &= ~(MF_HILITE|MF_MOUSESELECT);
+        menu->iItem = NO_SELECTED_ITEM;
+    }
+
+    menu->dwArrowsOn = 0;
+    MENU_PopupMenuCalcSize(menu, pwndOwner);
+
+    /* adjust popup menu pos so that it fits within the desktop */
+
+    width = menu->cxMenu + UserGetSystemMetrics(SM_CXBORDER);
+    height = menu->cyMenu + UserGetSystemMetrics(SM_CYBORDER);
+
+    /* FIXME: should use item rect */
+    pt.x = x;
+    pt.y = y;
+    monitor = UserMonitorFromPoint( pt, MONITOR_DEFAULTTONEAREST );
+
+    if (flags & TPM_LAYOUTRTL) 
+        flags ^= TPM_RIGHTALIGN;
+
+    if( flags & TPM_RIGHTALIGN ) x -= width;
+    if( flags & TPM_CENTERALIGN ) x -= width / 2;
+
+    if( flags & TPM_BOTTOMALIGN ) y -= height;
+    if( flags & TPM_VCENTERALIGN ) y -= height / 2;
+
+    if( x + width > monitor->rcMonitor.right)
+    {
+        if( xanchor && x >= width - xanchor )
+            x -= width - xanchor;
+
+        if( x + width > monitor->rcMonitor.right)
+            x = monitor->rcMonitor.right - width;
+    }
+    if( x < monitor->rcMonitor.left ) x = monitor->rcMonitor.left;
+
+    if( y + height > monitor->rcMonitor.bottom)
+    {
+        if( yanchor && y >= height + yanchor )
+            y -= height + yanchor;
+
+        if( y + height > monitor->rcMonitor.bottom)
+            y = monitor->rcMonitor.bottom - height;
+    }
+    if( y < monitor->rcMonitor.top ) y = monitor->rcMonitor.top;
+
+    pWnd = ValidateHwndNoErr( menu->hWnd );
+
+    if (!pWnd)
+    {
+       ERR("menu->hWnd bad hwnd %p\n",menu->hWnd);
+       return FALSE;
+    }
+
+    if (!top_popup) {
+        top_popup = menu->hWnd;
+        top_popup_hmenu = UserHMGetHandle(menu);
+    }
+
+    /* Display the window */
+    UserRefObjectCo(pWnd, &Ref);
+    co_WinPosSetWindowPos( pWnd, HWND_TOPMOST, x, y, width, height, SWP_SHOWWINDOW | SWP_NOACTIVATE);
+
+    co_IntUpdateWindows(pWnd, RDW_ALLCHILDREN, FALSE);
+
+    IntNotifyWinEvent(EVENT_SYSTEM_MENUPOPUPSTART, pWnd, OBJID_CLIENT, CHILDID_SELF, 0);
+    UserDerefObjectCo(pWnd);
+
+    return TRUE;
+}
+
+/***********************************************************************
+ *           MENU_EnsureMenuItemVisible
+ */
+void MENU_EnsureMenuItemVisible(PMENU lppop, UINT wIndex, HDC hdc)
+{
+    USER_REFERENCE_ENTRY Ref;
+    if (lppop->dwArrowsOn)
+    {
+        ITEM *item = &lppop->rgItems[wIndex];
+        UINT nMaxHeight = MENU_GetMaxPopupHeight(lppop);
+        UINT nOldPos = lppop->iTop;
+        RECT rc;
+        UINT arrow_bitmap_height;
+        PWND pWnd = ValidateHwndNoErr(lppop->hWnd);
+
+        IntGetClientRect(pWnd, &rc);
+
+        arrow_bitmap_height = gpsi->oembmi[OBI_DNARROW].cy;
+
+        rc.top += arrow_bitmap_height;
+        rc.bottom -= arrow_bitmap_height + MENU_BOTTOM_MARGIN;
+
+        nMaxHeight -= UserGetSystemMetrics(SM_CYBORDER) + 2 * arrow_bitmap_height;
+        UserRefObjectCo(pWnd, &Ref);
+        if (item->cyItem > lppop->iTop + nMaxHeight)
+        {
+            lppop->iTop = item->cyItem - nMaxHeight;
+            IntScrollWindow(pWnd, 0, nOldPos - lppop->iTop, &rc, &rc);
+            MENU_DrawScrollArrows(lppop, hdc);
+            //ERR("Scroll Down iTop %d iMaxTop %d nMaxHeight %d\n",lppop->iTop,lppop->iMaxTop,nMaxHeight);
+        }
+        else if (item->yItem - MENU_TOP_MARGIN < lppop->iTop)
+        {
+            lppop->iTop = item->yItem - MENU_TOP_MARGIN;
+            IntScrollWindow(pWnd, 0, nOldPos - lppop->iTop, &rc, &rc);
+            MENU_DrawScrollArrows(lppop, hdc);
+            //ERR("Scroll Up   iTop %d iMaxTop %d nMaxHeight %d\n",lppop->iTop,lppop->iMaxTop,nMaxHeight);
+        }
+        UserDerefObjectCo(pWnd);
+    }
+}
+
+/***********************************************************************
+ *           MenuSelectItem
+ */
+static void FASTCALL MENU_SelectItem(PWND pwndOwner, PMENU menu, UINT wIndex,
+                                    BOOL sendMenuSelect, PMENU topmenu)
+{
+    HDC hdc;
+    PWND pWnd;
+
+    TRACE("M_SI: owner=%p menu=%p index=0x%04x select=0x%04x\n", pwndOwner, menu, wIndex, sendMenuSelect);
+
+    if (!menu || !menu->cItems) return;
+
+    pWnd = ValidateHwndNoErr(menu->hWnd);
+
+    if (!pWnd) return;
+
+    if (menu->iItem == wIndex) return;
+
+    if (menu->fFlags & MNF_POPUP)
+       hdc = UserGetDCEx(pWnd, 0, DCX_USESTYLE);
+    else
+       hdc = UserGetDCEx(pWnd, 0, DCX_CACHE | DCX_WINDOW);
+
+    if (!top_popup) {
+        top_popup = menu->hWnd;                  //pPopupMenu->spwndActivePopup or
+                                                 //pPopupMenu->fIsTrackPopup set pPopupMenu->spwndPopupMenu;
+        top_popup_hmenu = UserHMGetHandle(menu); //pPopupMenu->spmenu
+    }
+
+    NtGdiSelectFont( hdc, ghMenuFont );
+
+     /* Clear previous highlighted item */
+    if (menu->iItem != NO_SELECTED_ITEM)
+    {
+        menu->rgItems[menu->iItem].fState &= ~(MF_HILITE|MF_MOUSESELECT);
+        MENU_DrawMenuItem(pWnd, menu, pwndOwner, hdc, &menu->rgItems[menu->iItem],
+                       menu->cyMenu, !(menu->fFlags & MNF_POPUP),
+                       ODA_SELECT);
+    }
+
+    /* Highlight new item (if any) */
+    menu->iItem = wIndex;
+    if (menu->iItem != NO_SELECTED_ITEM)
+    {
+        if (!(menu->rgItems[wIndex].fType & MF_SEPARATOR))
+        {
+             menu->rgItems[wIndex].fState |= MF_HILITE;
+             MENU_EnsureMenuItemVisible(menu, wIndex, hdc);
+             MENU_DrawMenuItem(pWnd, menu, pwndOwner, hdc,
+                               &menu->rgItems[wIndex], menu->cyMenu, !(menu->fFlags & MNF_POPUP), ODA_SELECT);
+        }
+        if (sendMenuSelect)
+        {
+           ITEM *ip = &menu->rgItems[menu->iItem];
+           WPARAM wParam = MAKEWPARAM( ip->spSubMenu ? wIndex : ip->wID, 
+                                       ip->fType | ip->fState |
+                                      (ip->spSubMenu ? MF_POPUP : 0) |
+                                      (menu->fFlags & MNF_SYSMENU ? MF_SYSMENU : 0 ) );
+
+           co_IntSendMessage(UserHMGetHandle(pwndOwner), WM_MENUSELECT, wParam, (LPARAM) UserHMGetHandle(menu));
+        }
+    }
+    else if (sendMenuSelect) 
+    {
+        if (topmenu) 
+        {
+            int pos;
+            pos = MENU_FindSubMenu(&topmenu, menu);
+            if (pos != NO_SELECTED_ITEM)
+            {
+               ITEM *ip = &topmenu->rgItems[pos];
+               WPARAM wParam = MAKEWPARAM( Pos, ip->fType | ip->fState |
+                                           (ip->spSubMenu ? MF_POPUP : 0) |
+                                           (topmenu->fFlags & MNF_SYSMENU ? MF_SYSMENU : 0 ) );
+
+               co_IntSendMessage(UserHMGetHandle(pwndOwner), WM_MENUSELECT, wParam, (LPARAM) UserHMGetHandle(topmenu));
+            }
+        }
+    }
+    UserReleaseDC(pWnd, hdc, FALSE);
+}
+
+/***********************************************************************
+ *           MenuMoveSelection
+ *
+ * Moves currently selected item according to the Offset parameter.
+ * If there is no selection then it should select the last item if
+ * Offset is ITEM_PREV or the first item if Offset is ITEM_NEXT.
+ */
+static void FASTCALL MENU_MoveSelection(PWND pwndOwner, PMENU menu, INT offset)
+{
+    INT i;
+
+    TRACE("pwnd=%x menu=%x off=0x%04x\n", pwndOwner, menu, offset);
+
+    if ((!menu) || (!menu->rgItems)) return;
+
+    if ( menu->iItem != NO_SELECTED_ITEM )
+    {
+       if ( menu->cItems == 1 )
+          return;
+       else
+       for (i = menu->iItem + offset ; i >= 0 && i < menu->cItems
+                                           ; i += offset)
+           if (!(menu->rgItems[i].fType & MF_SEPARATOR))
+           {
+               MENU_SelectItem( pwndOwner, menu, i, TRUE, 0 );
+               return;
+           }
+    }
+
+    for ( i = (offset > 0) ? 0 : menu->cItems - 1;
+                 i >= 0 && i < menu->cItems ; i += offset)
+       if (!(menu->rgItems[i].fType & MF_SEPARATOR))
+       {
+           MENU_SelectItem( pwndOwner, menu, i, TRUE, 0 );
+           return;
+       }
+}
+
+/***********************************************************************
+ *           MenuHideSubPopups
+ *
+ * Hide the sub-popup menus of this menu.
+ */
+static void FASTCALL MENU_HideSubPopups(PWND pWndOwner, PMENU Menu,
+                               BOOL SendMenuSelect, UINT wFlags)
+{
+  TRACE("owner=%x menu=%x 0x%04x\n", pWndOwner, Menu, SendMenuSelect);
+
+  if ( Menu && top_popup )
+  {
+      PITEM Item;
+
+      if (Menu->iItem != NO_SELECTED_ITEM)
+      {
+         Item = &Menu->rgItems[Menu->iItem];
+         if (!(Item->spSubMenu) ||
+             !(Item->fState & MF_MOUSESELECT)) return;
+         Item->fState &= ~MF_MOUSESELECT;
+      }
+      else
+         return;
+
+      if (Item->spSubMenu)
+      {
+          PWND pWnd;
+          if (!VerifyMenu(Item->spSubMenu)) return;
+          pWnd = ValidateHwndNoErr(Item->spSubMenu->hWnd);
+          MENU_HideSubPopups(pWndOwner, Item->spSubMenu, FALSE, wFlags);
+          MENU_SelectItem(pWndOwner, Item->spSubMenu, NO_SELECTED_ITEM, SendMenuSelect, NULL);
+          TRACE("M_HSP top p hm %p  pWndOwner IDMenu %p\n",top_popup_hmenu,pWndOwner->IDMenu);
+          co_UserDestroyWindow(pWnd);
+
+          /* Native returns handle to destroyed window */
+          if (!(wFlags & TPM_NONOTIFY))
+          {
+             co_IntSendMessage( UserHMGetHandle(pWndOwner), WM_UNINITMENUPOPUP, (WPARAM)UserHMGetHandle(Item->spSubMenu),
+                                 MAKELPARAM(0, IS_SYSTEM_MENU(Item->spSubMenu)) );
+          }
+          ////
+          // Call WM_UNINITMENUPOPUP FIRST before destroy!!
+          // Fixes todo_wine User32 test menu.c line 2239 GetMenuBarInfo callback....
+          //
+          Item->spSubMenu->hWnd = NULL;
+          ////
+      }
+  }
+}
+
+/***********************************************************************
+ *           MenuShowSubPopup
+ *
+ * Display the sub-menu of the selected item of this menu.
+ * Return the handle of the submenu, or menu if no submenu to display.
+ */
+static PMENU FASTCALL MENU_ShowSubPopup(PWND WndOwner, PMENU Menu, BOOL SelectFirst, UINT Flags)
+{
+  RECT Rect;
+  ITEM *Item;
+  HDC Dc;
+  PWND pWnd;
+
+  TRACE("owner=%x menu=%p 0x%04x\n", WndOwner, Menu, SelectFirst);
+
+  if (!Menu) return Menu;
+
+  if (Menu->iItem == NO_SELECTED_ITEM) return Menu;
+  
+  Item = &Menu->rgItems[Menu->iItem];
+  if (!(Item->spSubMenu) || (Item->fState & (MF_GRAYED | MF_DISABLED)))
+      return Menu;
+
+  /* message must be sent before using item,
+     because nearly everything may be changed by the application ! */
+
+  /* Send WM_INITMENUPOPUP message only if TPM_NONOTIFY flag is not specified */
+  if (!(Flags & TPM_NONOTIFY))
+  {
+      co_IntSendMessage(UserHMGetHandle(WndOwner), WM_INITMENUPOPUP,
+                        (WPARAM) UserHMGetHandle(Item->spSubMenu),
+                         MAKELPARAM(Menu->iItem, IS_SYSTEM_MENU(Menu)));
+  }
+
+  Item = &Menu->rgItems[Menu->iItem];
+  //Rect = ItemInfo.Rect;
+  Rect.left   = Item->xItem;
+  Rect.top    = Item->yItem;
+  Rect.right  = Item->cxItem; // Do this for now......
+  Rect.bottom = Item->cyItem;
+
+  pWnd = ValidateHwndNoErr(Menu->hWnd);
+
+  /* correct item if modified as a reaction to WM_INITMENUPOPUP message */
+  if (!(Item->fState & MF_HILITE))
+  {
+      if (Menu->fFlags & MNF_POPUP) Dc = UserGetDCEx(pWnd, NULL, DCX_USESTYLE);
+      else Dc = UserGetDCEx(pWnd, 0, DCX_CACHE | DCX_WINDOW);
+
+      NtGdiSelectFont(Dc, ghMenuFont);
+
+      Item->fState |= MF_HILITE;
+      MENU_DrawMenuItem(pWnd, Menu, WndOwner, Dc, Item, Menu->cyMenu,
+                       !(Menu->fFlags & MNF_POPUP), ODA_DRAWENTIRE);
+
+      UserReleaseDC(pWnd, Dc, FALSE);
+  }
+
+  if (!Item->yItem && !Item->xItem && !Item->cyItem && !Item->cxItem)
+  {
+      Item->xItem  = Rect.left; 
+      Item->yItem  = Rect.top;  
+      Item->cxItem = Rect.right; // Do this for now...... 
+      Item->cyItem = Rect.bottom;
+  }
+  Item->fState |= MF_MOUSESELECT;
+
+  if (IS_SYSTEM_MENU(Menu))
+  {
+      MENU_InitSysMenuPopup(Item->spSubMenu, pWnd->style, pWnd->pcls->style, HTSYSMENU);
+
+      NC_GetSysPopupPos(pWnd, &Rect);
+      if (Flags & TPM_LAYOUTRTL) Rect.left = Rect.right;
+      Rect.top = Rect.bottom;
+      Rect.right = UserGetSystemMetrics(SM_CXSIZE);
+      Rect.bottom = UserGetSystemMetrics(SM_CYSIZE);
+  }
+  else
+  {
+      IntGetWindowRect(pWnd, &Rect);
+      if (Menu->fFlags & MNF_POPUP)
+      {
+          RECT rc;
+          rc.left   = Item->xItem;
+          rc.top    = Item->yItem;
+          rc.right  = Item->cxItem; // Do this for now......
+          rc.bottom = Item->cyItem;
+
+          MENU_AdjustMenuItemRect(Menu, &rc);
+
+          /* The first item in the popup menu has to be at the
+             same y position as the focused menu item */
+          if(Flags & TPM_LAYOUTRTL)
+             Rect.left += UserGetSystemMetrics(SM_CXBORDER);
+          else
+             Rect.left += rc.right /*ItemInfo.Rect.right*/ - UserGetSystemMetrics(SM_CXBORDER);
+          Rect.top += rc.top - MENU_TOP_MARGIN;//3;
+          Rect.right = rc.left - rc.right + UserGetSystemMetrics(SM_CXBORDER);
+          Rect.bottom = rc.top - rc.bottom - MENU_TOP_MARGIN - MENU_BOTTOM_MARGIN/*2*/
+                                                     - UserGetSystemMetrics(SM_CYBORDER);
+      }
+      else
+      {
+          if(Flags & TPM_LAYOUTRTL)
+              Rect.left += Rect.right - Item->xItem; //ItemInfo.Rect.left;
+          else
+              Rect.left += Item->xItem; //ItemInfo.Rect.left;
+          Rect.top += Item->cyItem; //ItemInfo.Rect.bottom;
+          Rect.right  = Item->cxItem - Item->xItem; //ItemInfo.Rect.right - ItemInfo.Rect.left;
+          Rect.bottom = Item->cyItem - Item->yItem; //ItemInfo.Rect.bottom - ItemInfo.Rect.top;
+      }
+  }
+
+  /* use default alignment for submenus */
+  Flags &= ~(TPM_CENTERALIGN | TPM_RIGHTALIGN | TPM_VCENTERALIGN | TPM_BOTTOMALIGN);
+
+  MENU_InitPopup( WndOwner, Item->spSubMenu, Flags );
+
+  MENU_ShowPopup( WndOwner, Item->spSubMenu, Menu->iItem, Flags,
+                Rect.left, Rect.top, Rect.right, Rect.bottom );
+  if (SelectFirst)
+  {
+      MENU_MoveSelection(WndOwner, Item->spSubMenu, ITEM_NEXT);
+  }
+  return Item->spSubMenu;
+}
+
+/***********************************************************************
+ *           MenuExecFocusedItem
+ *
+ * Execute a menu item (for instance when user pressed Enter).
+ * Return the wID of the executed item. Otherwise, -1 indicating
+ * that no menu item was executed, -2 if a popup is shown;
+ * Have to receive the flags for the TrackPopupMenu options to avoid
+ * sending unwanted message.
+ *
+ */
+static INT FASTCALL MENU_ExecFocusedItem(MTRACKER *pmt, PMENU Menu, UINT Flags)
+{
+  PITEM Item;
+
+  TRACE("%p menu=%p\n", pmt, Menu);
+
+  if (!Menu || !Menu->cItems || Menu->iItem == NO_SELECTED_ITEM)
+  {
+      return -1;
+  }
+
+  Item = &Menu->rgItems[Menu->iItem];
+
+  TRACE("%p %08x %p\n", Menu, Item->wID, Item->spSubMenu);
+
+  if (!(Item->spSubMenu))
+  {
+      if (!(Item->fState & (MF_GRAYED | MF_DISABLED)) && !(Item->fType & MF_SEPARATOR))
+      {
+          /* If TPM_RETURNCMD is set you return the id, but
+            do not send a message to the owner */
+          if (!(Flags & TPM_RETURNCMD))
+          {
+              if (Menu->fFlags & MNF_SYSMENU)
+              {
+                  UserPostMessage(UserHMGetHandle(pmt->OwnerWnd), WM_SYSCOMMAND, Item->wID,
+                               MAKELPARAM((SHORT) pmt->Pt.x, (SHORT) pmt->Pt.y));
+              }
+              else
+              {
+                  DWORD dwStyle = ((Menu->fFlags & MNS_STYLE_MASK) | ( pmt->TopMenu ? (pmt->TopMenu->fFlags & MNS_STYLE_MASK) : 0) );
+
+                  if (dwStyle & MNS_NOTIFYBYPOS)
+                      UserPostMessage(UserHMGetHandle(pmt->OwnerWnd), WM_MENUCOMMAND, Menu->iItem, (LPARAM)UserHMGetHandle(Menu));
+                  else
+                      UserPostMessage(UserHMGetHandle(pmt->OwnerWnd), WM_COMMAND, Item->wID, 0);
+              }
+          }
+          return Item->wID;
+      }
+  }
+  else
+  {
+      pmt->CurrentMenu = MENU_ShowSubPopup(pmt->OwnerWnd, Menu, TRUE, Flags);
+      return -2;
+  }
+
+  return -1;
+}
+
+/***********************************************************************
+ *           MenuSwitchTracking
+ *
+ * Helper function for menu navigation routines.
+ */
+static void FASTCALL MENU_SwitchTracking(MTRACKER* pmt, PMENU PtMenu, UINT Index, UINT wFlags)
+{
+  TRACE("%x menu=%x 0x%04x\n", pmt, PtMenu, Index);
+
+  if ( pmt->TopMenu != PtMenu &&
+      !((PtMenu->fFlags | pmt->TopMenu->fFlags) & MNF_POPUP) )
+  {
+      /* both are top level menus (system and menu-bar) */
+      MENU_HideSubPopups(pmt->OwnerWnd, pmt->TopMenu, FALSE, wFlags);
+      MENU_SelectItem(pmt->OwnerWnd, pmt->TopMenu, NO_SELECTED_ITEM, FALSE, NULL);
+      pmt->TopMenu = PtMenu;
+  }
+  else
+  {
+      MENU_HideSubPopups(pmt->OwnerWnd, PtMenu, FALSE, wFlags);
+  }
+
+  MENU_SelectItem(pmt->OwnerWnd, PtMenu, Index, TRUE, NULL);
+}
+
+/***********************************************************************
+ *           MenuButtonDown
+ *
+ * Return TRUE if we can go on with menu tracking.
+ */
+static BOOL FASTCALL MENU_ButtonDown(MTRACKER* pmt, PMENU PtMenu, UINT Flags)
+{
+  TRACE("%x PtMenu=%p\n", pmt, PtMenu);
+
+  if (PtMenu)
+  {
+      UINT id = 0;
+      PITEM item;
+      if (IS_SYSTEM_MENU(PtMenu))
+      {
+         item = PtMenu->rgItems;
+      }
+      else
+      {
+         item = MENU_FindItemByCoords( PtMenu, pmt->Pt, &id );
+      }
+
+      if (item)
+      {
+          if (PtMenu->iItem != id)
+              MENU_SwitchTracking(pmt, PtMenu, id, Flags);
+
+          /* If the popup menu is not already "popped" */
+          if (!(item->fState & MF_MOUSESELECT))
+          {
+              pmt->CurrentMenu = MENU_ShowSubPopup(pmt->OwnerWnd, PtMenu, FALSE, Flags);
+          }
+
+          return TRUE;
+      }
+      /* Else the click was on the menu bar, finish the tracking */
+  }
+  return FALSE;
+}
+
+/***********************************************************************
+ *           MenuButtonUp
+ *
+ * Return the value of MenuExecFocusedItem if
+ * the selected item was not a popup. Else open the popup.
+ * A -1 return value indicates that we go on with menu tracking.
+ *
+ */
+static INT FASTCALL MENU_ButtonUp(MTRACKER *pmt, PMENU PtMenu, UINT Flags)
+{
+  TRACE("%p pmenu=%x\n", pmt, PtMenu);
+
+  if (PtMenu)
+  {
+      UINT Id = 0;
+      ITEM *item;
+      
+      if ( IS_SYSTEM_MENU(PtMenu) )
+      {
+          item = PtMenu->rgItems;
+      }
+      else
+      {
+          item = MENU_FindItemByCoords( PtMenu, pmt->Pt, &Id );
+      }
+
+      if (item && ( PtMenu->iItem == Id))
+      {
+          if (!(item->spSubMenu))
+          {
+              INT ExecutedMenuId = MENU_ExecFocusedItem( pmt, PtMenu, Flags);
+              if (ExecutedMenuId == -1 || ExecutedMenuId == -2) return -1;
+              return ExecutedMenuId;
+          }
+
+          /* If we are dealing with the menu bar                  */
+          /* and this is a click on an already "popped" item:     */
+          /* Stop the menu tracking and close the opened submenus */
+          if (pmt->TopMenu == PtMenu && PtMenu->TimeToHide)
+          {
+              return 0;
+          }
+      }
+      if ( IntGetMenu(PtMenu->hWnd) == PtMenu )
+      {
+          PtMenu->TimeToHide = TRUE;
+      }
+  }
+  return -1;
+}
+
+/***********************************************************************
+ *           MenuPtMenu
+ *
+ * Walks menu chain trying to find a menu pt maps to.
+ */
+static PMENU FASTCALL MENU_PtMenu(PMENU menu, POINT pt)
+{
+  PITEM pItem;
+  PMENU ret = NULL;
+
+  if (!menu) return NULL;
+
+  /* try subpopup first (if any) */
+  if (menu->iItem != NO_SELECTED_ITEM)
+  {
+     pItem = menu->rgItems;
+     if ( pItem ) pItem = &pItem[menu->iItem];
+     if ( pItem && pItem->spSubMenu && pItem->fState & MF_MOUSESELECT)
+     {
+        ret = MENU_PtMenu( pItem->spSubMenu, pt);
+     }
+  }
+
+  /* check the current window (avoiding WM_HITTEST) */
+  if (!ret)
+  {
+     PWND pWnd = ValidateHwndNoErr(menu->hWnd);
+     INT ht = GetNCHitEx(pWnd, pt);
+     if ( menu->fFlags & MNF_POPUP )
+     {
+        if (ht != HTNOWHERE && ht != HTERROR) ret = menu;
+     }
+     else if (ht == HTSYSMENU)
+        ret = get_win_sys_menu(menu->hWnd);
+     else if (ht == HTMENU)
+        ret = IntGetMenu( menu->hWnd );
+  }
+  return ret;
+}
+
+/***********************************************************************
+ *           MenuMouseMove
+ *
+ * Return TRUE if we can go on with menu tracking.
+ */
+static BOOL FASTCALL MENU_MouseMove(MTRACKER *pmt, PMENU PtMenu, UINT Flags)
+{
+  UINT Index = NO_SELECTED_ITEM;
+
+  if ( PtMenu )
+  {
+      if (IS_SYSTEM_MENU(PtMenu))
+      {
+          Index = 0;
+          //// ReactOS only HACK: CORE-2338
+          // Windows tracks mouse moves to the system menu but does not open it.
+          // Only keyboard tracking can do that.
+          //
+          TRACE("SystemMenu\n");
+          return TRUE; // Stay inside the Loop!
+      }
+      else
+          MENU_FindItemByCoords( PtMenu, pmt->Pt, &Index );
+  }
+
+  if (Index == NO_SELECTED_ITEM)
+  {
+      MENU_SelectItem(pmt->OwnerWnd, pmt->CurrentMenu, NO_SELECTED_ITEM, TRUE, pmt->TopMenu);
+  }
+  else if (PtMenu->iItem != Index)
+  {
+      MENU_SwitchTracking(pmt, PtMenu, Index, Flags);
+      pmt->CurrentMenu = MENU_ShowSubPopup(pmt->OwnerWnd, PtMenu, FALSE, Flags);
+  }
+  return TRUE;
+}
+
+/***********************************************************************
+ *           MenuGetSubPopup
+ *
+ * Return the handle of the selected sub-popup menu (if any).
+ */
+static PMENU MENU_GetSubPopup( PMENU menu )
+{
+    ITEM *item;
+
+    if ((!menu) || (menu->iItem == NO_SELECTED_ITEM)) return 0;
+
+    item = &menu->rgItems[menu->iItem];
+    if (item && (item->spSubMenu) && (item->fState & MF_MOUSESELECT))
+    {
+       return item->spSubMenu;
+    }
+    return 0;
+}
+
+/***********************************************************************
+ *           MenuDoNextMenu
+ *
+ * NOTE: WM_NEXTMENU documented in Win32 is a bit different.
+ */
+static LRESULT FASTCALL MENU_DoNextMenu(MTRACKER* pmt, UINT Vk, UINT wFlags)
+{
+    BOOL atEnd = FALSE;
+
+    /* When skipping left, we need to do something special after the
+       first menu.                                                  */
+    if (Vk == VK_LEFT && pmt->TopMenu->iItem == 0)
+    {
+        atEnd = TRUE;
+    }
+    /* When skipping right, for the non-system menu, we need to
+       handle the last non-special menu item (ie skip any window
+       icons such as MDI maximize, restore or close)             */
+    else if ((Vk == VK_RIGHT) && !IS_SYSTEM_MENU(pmt->TopMenu))
+    {
+        UINT i = pmt->TopMenu->iItem + 1;
+        while (i < pmt->TopMenu->cItems) {
+            if ((pmt->TopMenu->rgItems[i].wID >= SC_SIZE &&
+                 pmt->TopMenu->rgItems[i].wID <= SC_RESTORE)) {
+                i++;
+            } else break;
+        }
+        if (i == pmt->TopMenu->cItems) {
+            atEnd = TRUE;
+        }
+    }
+    /* When skipping right, we need to cater for the system menu */
+    else if ((Vk == VK_RIGHT) && IS_SYSTEM_MENU(pmt->TopMenu))
+    {
+        if (pmt->TopMenu->iItem == (pmt->TopMenu->cItems - 1)) {
+            atEnd = TRUE;
+        }
+    }
+
+   if ( atEnd )
+   {
+      MDINEXTMENU NextMenu;
+      PMENU MenuTmp;
+      PWND pwndTemp;
+      HMENU hNewMenu;
+      HWND hNewWnd;
+      UINT Id = 0;
+
+      MenuTmp = (IS_SYSTEM_MENU(pmt->TopMenu)) ? co_IntGetSubMenu(pmt->TopMenu, 0) : pmt->TopMenu;
+      NextMenu.hmenuIn = UserHMGetHandle(MenuTmp);
+      NextMenu.hmenuNext = NULL;
+      NextMenu.hwndNext = NULL;
+      co_IntSendMessage(UserHMGetHandle(pmt->OwnerWnd), WM_NEXTMENU, Vk, (LPARAM) &NextMenu);
+
+      TRACE("%p [%p] -> %p [%p]\n",
+             pmt->CurrentMenu, pmt->OwnerWnd, NextMenu.hmenuNext, NextMenu.hwndNext );
+
+      if (NULL == NextMenu.hmenuNext || NULL == NextMenu.hwndNext)
+      {
+          hNewWnd = UserHMGetHandle(pmt->OwnerWnd);
+          if (IS_SYSTEM_MENU(pmt->TopMenu))
+          {
+              /* switch to the menu bar */
+
+              if (pmt->OwnerWnd->style & WS_CHILD || !(MenuTmp = IntGetMenu(hNewWnd))) return FALSE;
+
+              if (Vk == VK_LEFT)
+              {
+                  Id = MenuTmp->cItems - 1;
+   
+                  /* Skip backwards over any system predefined icons,
+                     eg. MDI close, restore etc icons                 */
+                   while ((Id > 0) &&
+                          (MenuTmp->rgItems[Id].wID >= SC_SIZE &&
+                           MenuTmp->rgItems[Id].wID <= SC_RESTORE)) Id--;
+              }
+              hNewMenu = UserHMGetHandle(MenuTmp);
+          }
+          else if (pmt->OwnerWnd->style & WS_SYSMENU)
+          {
+              /* switch to the system menu */
+              MenuTmp = get_win_sys_menu(hNewWnd);
+              if (MenuTmp) hNewMenu = UserHMGetHandle(MenuTmp);
+          }
+          else
+              return FALSE;
+      }
+      else    /* application returned a new menu to switch to */
+      {
+          hNewMenu = NextMenu.hmenuNext;
+          hNewWnd = NextMenu.hwndNext;
+
+          if ((MenuTmp = UserGetMenuObject(hNewMenu)) && (pwndTemp = ValidateHwndNoErr(hNewWnd)))
+          {
+              if ( pwndTemp->style & WS_SYSMENU && (get_win_sys_menu(hNewWnd) == MenuTmp) )
+              {
+                  /* get the real system menu */
+                  MenuTmp = get_win_sys_menu(hNewWnd);
+                  hNewMenu = UserHMGetHandle(MenuTmp);
+              }
+              else if (pwndTemp->style & WS_CHILD || IntGetMenu(hNewWnd) != MenuTmp)
+              {
+                  /* FIXME: Not sure what to do here;
+                   * perhaps try to track NewMenu as a popup? */
+
+                  WARN(" -- got confused.\n");
+                  return FALSE;
+              }
+          }
+          else return FALSE;
+      }
+
+      if (hNewMenu != UserHMGetHandle(pmt->TopMenu))
+      {
+          MENU_SelectItem(pmt->OwnerWnd, pmt->TopMenu, NO_SELECTED_ITEM, FALSE, 0 );
+
+          if (pmt->CurrentMenu != pmt->TopMenu)
+              MENU_HideSubPopups(pmt->OwnerWnd, pmt->TopMenu, FALSE, wFlags);
+      }
+
+      if (hNewWnd != UserHMGetHandle(pmt->OwnerWnd))
+      {
+          PTHREADINFO pti = PsGetCurrentThreadWin32Thread();
+          pmt->OwnerWnd = ValidateHwndNoErr(hNewWnd);
+          ///// Use thread pms!!!!
+          MsqSetStateWindow(pti, MSQ_STATE_MENUOWNER, hNewWnd);
+          pti->MessageQueue->QF_flags &= ~QF_CAPTURELOCKED;
+          co_UserSetCapture(UserHMGetHandle(pmt->OwnerWnd));
+          pti->MessageQueue->QF_flags |= QF_CAPTURELOCKED;
+      }
+
+      pmt->TopMenu = pmt->CurrentMenu = UserGetMenuObject(hNewMenu); /* all subpopups are hidden */
+      MENU_SelectItem(pmt->OwnerWnd, pmt->TopMenu, Id, TRUE, 0);
+
+      return TRUE;
+   }
+   return FALSE;
+}
+
+/***********************************************************************
+ *           MenuSuspendPopup
+ *
+ * The idea is not to show the popup if the next input message is
+ * going to hide it anyway.
+ */
+static BOOL FASTCALL MENU_SuspendPopup(MTRACKER* pmt, UINT uMsg)
+{
+    MSG msg;
+
+    msg.hwnd = UserHMGetHandle(pmt->OwnerWnd); ////// ? silly wine'isms?
+
+    co_IntGetPeekMessage( &msg, 0, uMsg, uMsg, PM_NOYIELD | PM_REMOVE, FALSE);
+    pmt->TrackFlags |= TF_SKIPREMOVE;
+
+    switch( uMsg )
+    {
+    case WM_KEYDOWN:
+        co_IntGetPeekMessage( &msg, 0, 0, 0, PM_NOYIELD | PM_NOREMOVE, FALSE);
+        if( msg.message == WM_KEYUP || msg.message == WM_PAINT )
+        {
+            co_IntGetPeekMessage( &msg, 0, 0, 0, PM_NOYIELD | PM_REMOVE, FALSE);
+            co_IntGetPeekMessage( &msg, 0, 0, 0, PM_NOYIELD | PM_NOREMOVE, FALSE);
+            if( msg.message == WM_KEYDOWN &&
+                (msg.wParam == VK_LEFT || msg.wParam == VK_RIGHT))
+            {
+                 pmt->TrackFlags |= TF_SUSPENDPOPUP;
+                 return TRUE;
+            }
+        }
+        break;
+    }
+    /* failures go through this */
+    pmt->TrackFlags &= ~TF_SUSPENDPOPUP;
+    return FALSE;
+}
+
+/***********************************************************************
+ *           MenuKeyEscape
+ *
+ * Handle a VK_ESCAPE key event in a menu.
+ */
+static BOOL FASTCALL MENU_KeyEscape(MTRACKER *pmt, UINT Flags)
+{
+  BOOL EndMenu = TRUE;
+
+  if (pmt->CurrentMenu != pmt->TopMenu)
+  {
+      if (pmt->CurrentMenu && (pmt->CurrentMenu->fFlags & MNF_POPUP))
+      {
+          PMENU MenuPrev, MenuTmp;
+
+          MenuPrev = MenuTmp = pmt->TopMenu;
+
+          /* close topmost popup */
+          while (MenuTmp != pmt->CurrentMenu)
+          {
+              MenuPrev = MenuTmp;
+              MenuTmp = MENU_GetSubPopup(MenuPrev);
+          }
+
+          MENU_HideSubPopups(pmt->OwnerWnd, MenuPrev, TRUE, Flags);
+          pmt->CurrentMenu = MenuPrev;
+          EndMenu = FALSE;
+      }
+  }
+
+  return EndMenu;
+}
+
+/***********************************************************************
+ *           MenuKeyLeft
+ *
+ * Handle a VK_LEFT key event in a menu.
+ */
+static void FASTCALL MENU_KeyLeft(MTRACKER* pmt, UINT Flags, UINT msg)
+{
+  PMENU MenuTmp, MenuPrev;
+  UINT PrevCol;
+
+  MenuPrev = MenuTmp = pmt->TopMenu;
+
+  /* Try to move 1 column left (if possible) */
+  if ( (PrevCol = MENU_GetStartOfPrevColumn(pmt->CurrentMenu)) != NO_SELECTED_ITEM)
+  {
+     MENU_SelectItem(pmt->OwnerWnd, pmt->CurrentMenu, PrevCol, TRUE, 0);
+     return;
+  }
+
+  /* close topmost popup */
+  while (MenuTmp != pmt->CurrentMenu)
+  {
+      MenuPrev = MenuTmp;
+      MenuTmp = MENU_GetSubPopup(MenuPrev);
+  }
+
+  MENU_HideSubPopups(pmt->OwnerWnd, MenuPrev, TRUE, Flags);
+  pmt->CurrentMenu = MenuPrev;
+
+  if ((MenuPrev == pmt->TopMenu) && !(pmt->TopMenu->fFlags & MNF_POPUP))
+  {
+      /* move menu bar selection if no more popups are left */
+
+      if (!MENU_DoNextMenu(pmt, VK_LEFT, Flags))
+          MENU_MoveSelection(pmt->OwnerWnd, pmt->TopMenu, ITEM_PREV);
+
+      if (MenuPrev != MenuTmp || pmt->TrackFlags & TF_SUSPENDPOPUP)
+      {
+          /* A sublevel menu was displayed - display the next one
+           * unless there is another displacement coming up */
+
+          if (!MENU_SuspendPopup(pmt, msg))
+              pmt->CurrentMenu = MENU_ShowSubPopup(pmt->OwnerWnd, pmt->TopMenu,
+                                                 TRUE, Flags);
+      }
+  }
+}
+
+/***********************************************************************
+ *           MenuKeyRight
+ *
+ * Handle a VK_RIGHT key event in a menu.
+ */
+static void FASTCALL MENU_KeyRight(MTRACKER *pmt, UINT Flags, UINT msg)
+{
+    PMENU menutmp;
+    UINT NextCol;
+
+    TRACE("MenuKeyRight called, cur %p, top %p.\n",
+         pmt->CurrentMenu, pmt->TopMenu);
+
+    if ((pmt->TopMenu->fFlags & MNF_POPUP) || (pmt->CurrentMenu != pmt->TopMenu))
+    {
+      /* If already displaying a popup, try to display sub-popup */
+
+      menutmp = pmt->CurrentMenu;
+      pmt->CurrentMenu = MENU_ShowSubPopup(pmt->OwnerWnd, menutmp, TRUE, Flags);
+
+      /* if subpopup was displayed then we are done */
+      if (menutmp != pmt->CurrentMenu) return;
+    }
+
+    /* Check to see if there's another column */
+    if ( (NextCol = MENU_GetStartOfNextColumn(pmt->CurrentMenu)) != NO_SELECTED_ITEM)
+    {
+       TRACE("Going to %d.\n", NextCol);
+       MENU_SelectItem(pmt->OwnerWnd, pmt->CurrentMenu, NextCol, TRUE, 0);
+       return;
+    }
+
+    if (!(pmt->TopMenu->fFlags & MNF_POPUP)) /* menu bar tracking */
+    {
+       if (pmt->CurrentMenu != pmt->TopMenu)
+       {
+          MENU_HideSubPopups(pmt->OwnerWnd, pmt->TopMenu, FALSE, Flags);
+          menutmp = pmt->CurrentMenu = pmt->TopMenu;
+       }
+       else
+       {
+          menutmp = NULL;
+       }
+
+       /* try to move to the next item */
+       if ( !MENU_DoNextMenu(pmt, VK_RIGHT, Flags))
+           MENU_MoveSelection(pmt->OwnerWnd, pmt->TopMenu, ITEM_NEXT);
+
+       if ( menutmp || pmt->TrackFlags & TF_SUSPENDPOPUP )
+       {
+           if ( !MENU_SuspendPopup(pmt, msg) )
+               pmt->CurrentMenu = MENU_ShowSubPopup(pmt->OwnerWnd, pmt->TopMenu, TRUE, Flags);
+       }
+    }
+}
+
+/***********************************************************************
+ *           MenuTrackMenu
+ *
+ * Menu tracking code.
+ */
+static INT FASTCALL MENU_TrackMenu(PMENU pmenu, UINT wFlags, INT x, INT y,
+                            PWND pwnd, const RECT *lprect )
+{
+    MSG msg;
+    BOOL fRemove;
+    INT executedMenuId = -1;
+    MTRACKER mt;
+    HWND capture_win;
+    PMENU pmMouse;
+    BOOL enterIdleSent = FALSE;
+    PTHREADINFO pti = PsGetCurrentThreadWin32Thread();
+
+    if (pti != pwnd->head.pti)
+    {
+       ERR("Not the same PTI!!!!\n");
+    }
+
+    mt.TrackFlags = 0;
+    mt.CurrentMenu = pmenu;
+    mt.TopMenu = pmenu;
+    mt.OwnerWnd = pwnd;
+    mt.Pt.x = x;
+    mt.Pt.y = y;
+
+    TRACE("MTM : hmenu=%p flags=0x%08x (%d,%d) hwnd=%x (%ld,%ld)-(%ld,%ld)\n",
+         UserHMGetHandle(pmenu), wFlags, x, y, UserHMGetHandle(pwnd), lprect ? lprect->left : 0, lprect ? lprect->top : 0,
+         lprect ? lprect->right : 0, lprect ? lprect->bottom : 0);
+
+    pti->MessageQueue->QF_flags &= ~QF_ACTIVATIONCHANGE;
+
+    if (wFlags & TPM_BUTTONDOWN)
+    {
+        /* Get the result in order to start the tracking or not */
+        fRemove = MENU_ButtonDown( &mt, pmenu, wFlags );
+        fInsideMenuLoop = fRemove;
+    }
+
+    if (wFlags & TF_ENDMENU) fInsideMenuLoop = FALSE;
+
+    if (wFlags & TPM_POPUPMENU && pmenu->cItems == 0) // Tracking empty popup menu...
+    {
+       MsqSetStateWindow(pti, MSQ_STATE_MENUOWNER, NULL);
+       pti->MessageQueue->QF_flags &= ~QF_CAPTURELOCKED;
+       co_UserSetCapture(NULL); /* release the capture */
+       return 0;
+    }
+
+    capture_win = IntGetCapture();
+
+    while (fInsideMenuLoop)
+    {
+        BOOL ErrorExit = FALSE;
+        if (!VerifyMenu( mt.CurrentMenu )) /* sometimes happens if I do a window manager close */
+           break;
+
+        /* we have to keep the message in the queue until it's
+         * clear that menu loop is not over yet. */
+
+        for (;;)
+        {
+            if (co_IntGetPeekMessage( &msg, 0, 0, 0, PM_NOREMOVE, FALSE ))
+            {
+                if (!IntCallMsgFilter( &msg, MSGF_MENU )) break;
+                /* remove the message from the queue */
+                co_IntGetPeekMessage( &msg, 0, msg.message, msg.message, PM_REMOVE, FALSE );
+            }
+            else
+            {
+                /* ReactOS Checks */
+                if (!VerifyWnd(mt.OwnerWnd)                            ||
+                    !ValidateHwndNoErr(mt.CurrentMenu->hWnd)           ||
+                     pti->MessageQueue->QF_flags & QF_ACTIVATIONCHANGE ||
+                     capture_win != IntGetCapture() ) // Should not happen, but this is ReactOS...
+                {
+                   ErrorExit = TRUE; // Do not wait on dead windows, now win test_capture_4 works.
+                   break;
+                }
+
+                if (!enterIdleSent)
+                {
+                  HWND win = mt.CurrentMenu->fFlags & MNF_POPUP ? mt.CurrentMenu->hWnd : NULL;
+                  enterIdleSent = TRUE;
+                  co_IntSendMessage( UserHMGetHandle(mt.OwnerWnd), WM_ENTERIDLE, MSGF_MENU, (LPARAM) win);
+                }
+                co_IntWaitMessage(NULL, 0, 0);
+            }
+        }
+
+        if (ErrorExit) break; // Gracefully dropout.
+
+        /* check if EndMenu() tried to cancel us, by posting this message */
+        if (msg.message == WM_CANCELMODE)
+        {
+            /* we are now out of the loop */
+            fInsideMenuLoop = FALSE;
+
+            /* remove the message from the queue */
+            co_IntGetPeekMessage( &msg, 0, msg.message, msg.message, PM_REMOVE, FALSE );
+
+            /* break out of internal loop, ala ESCAPE */
+            break;
+        }
+
+        mt.Pt = msg.pt;
+
+        if ( (msg.hwnd == mt.CurrentMenu->hWnd) || ((msg.message!=WM_TIMER) && (msg.message!=WM_SYSTIMER)) )
+            enterIdleSent=FALSE;
+
+        fRemove = FALSE;
+        if ((msg.message >= WM_MOUSEFIRST) && (msg.message <= WM_MOUSELAST))
+        {
+            /*
+             * Use the mouse coordinates in lParam instead of those in the MSG
+             * struct to properly handle synthetic messages. They are already
+             * in screen coordinates.
+             */
+            mt.Pt.x = (short)LOWORD(msg.lParam);
+            mt.Pt.y = (short)HIWORD(msg.lParam);
+
+            /* Find a menu for this mouse event */
+            pmMouse = MENU_PtMenu( mt.TopMenu, mt.Pt );
+
+            switch(msg.message)
+            {
+                /* no WM_NC... messages in captured state */
+
+                case WM_RBUTTONDBLCLK:
+                case WM_RBUTTONDOWN:
+                     if (!(wFlags & TPM_RIGHTBUTTON))
+                     {
+                        if ( msg.message == WM_RBUTTONDBLCLK ) fInsideMenuLoop = FALSE; // Must exit or loop forever!
+                        break;
+                     }
+                    /* fall through */
+                case WM_LBUTTONDBLCLK:
+                case WM_LBUTTONDOWN:
+                    /* If the message belongs to the menu, removes it from the queue */
+                    /* Else, end menu tracking */
+                    fRemove = MENU_ButtonDown(&mt, pmMouse, wFlags);
+                    fInsideMenuLoop = fRemove;
+                    if ( msg.message == WM_LBUTTONDBLCLK ||
+                         msg.message == WM_RBUTTONDBLCLK ) fInsideMenuLoop = FALSE; // Must exit or loop forever!
+                    break;
+
+                case WM_RBUTTONUP:
+                    if (!(wFlags & TPM_RIGHTBUTTON)) break;
+                    /* fall through */
+                case WM_LBUTTONUP:
+                    /* Check if a menu was selected by the mouse */
+                    if (pmMouse)
+                    {
+                        executedMenuId = MENU_ButtonUp( &mt, pmMouse, wFlags);
+
+                    /* End the loop if executedMenuId is an item ID */
+                    /* or if the job was done (executedMenuId = 0). */
+                        fRemove = (executedMenuId != -1);
+                        fInsideMenuLoop = !fRemove;
+                    }
+                    /* No menu was selected by the mouse */
+                    /* if the function was called by TrackPopupMenu, continue
+                       with the menu tracking. If not, stop it */
+                    else
+                        fInsideMenuLoop = ((wFlags & TPM_POPUPMENU) ? TRUE : FALSE);
+
+                    break;
+
+                case WM_MOUSEMOVE:
+                    /* the selected menu item must be changed every time */
+                    /* the mouse moves. */
+
+                    if (pmMouse)
+                        fInsideMenuLoop |= MENU_MouseMove( &mt, pmMouse, wFlags );
+
+           } /* switch(msg.message) - mouse */
+        }
+        else if ((msg.message >= WM_KEYFIRST) && (msg.message <= WM_KEYLAST))
+        {
+            fRemove = TRUE;  /* Keyboard messages are always removed */
+            switch(msg.message)
+            {
+                case WM_KEYDOWN:
+                case WM_SYSKEYDOWN:
+                switch(msg.wParam)
+                {
+                    case VK_MENU:
+                    case VK_F10:
+                        fInsideMenuLoop = FALSE;
+                        break;
+
+                    case VK_HOME:
+                    case VK_END:
+                        MENU_SelectItem(mt.OwnerWnd, mt.CurrentMenu, NO_SELECTED_ITEM, FALSE, 0 );
+                        MENU_MoveSelection(mt.OwnerWnd, mt.CurrentMenu, VK_HOME == msg.wParam ? ITEM_NEXT : ITEM_PREV);
+                        break;
+
+                    case VK_UP:
+                    case VK_DOWN: /* If on menu bar, pull-down the menu */
+                        if (!(mt.CurrentMenu->fFlags & MNF_POPUP))
+                            mt.CurrentMenu = MENU_ShowSubPopup(mt.OwnerWnd, mt.TopMenu, TRUE, wFlags);
+                        else      /* otherwise try to move selection */
+                            MENU_MoveSelection(mt.OwnerWnd, mt.CurrentMenu, (msg.wParam == VK_UP)? ITEM_PREV : ITEM_NEXT );
+                        break;
+
+                    case VK_LEFT:
+                        MENU_KeyLeft( &mt, wFlags, msg.message );
+                        break;
+
+                    case VK_RIGHT:
+                        MENU_KeyRight( &mt, wFlags, msg.message );
+                        break;
+
+                    case VK_ESCAPE:
+                        fInsideMenuLoop = !MENU_KeyEscape(&mt, wFlags);
+                        break;
+
+                    case VK_F1:
+                    {
+                        HELPINFO hi;
+                        hi.cbSize = sizeof(HELPINFO);
+                        hi.iContextType = HELPINFO_MENUITEM;
+                        if (mt.CurrentMenu->iItem == NO_SELECTED_ITEM)
+                            hi.iCtrlId = 0;
+                        else
+                            hi.iCtrlId = pmenu->rgItems[mt.CurrentMenu->iItem].wID;
+                        hi.hItemHandle = UserHMGetHandle(mt.CurrentMenu);
+                        hi.dwContextId = pmenu->dwContextHelpId;
+                        hi.MousePos = msg.pt;
+                        co_IntSendMessage( UserHMGetHandle(pwnd), WM_HELP, 0, (LPARAM)&hi);
+                        break;
+                    }
+
+                    default:
+                        IntTranslateKbdMessage(&msg, 0);
+                        break;
+                }
+                break;  /* WM_KEYDOWN */
+
+                case WM_CHAR:
+                case WM_SYSCHAR:
+                {
+                    UINT pos;
+                    BOOL fEndMenu;
+
+                    if (msg.wParam == L'\r' || msg.wParam == L' ')
+                    {
+                        executedMenuId = MENU_ExecFocusedItem(&mt, mt.CurrentMenu, wFlags);
+                        fEndMenu = (executedMenuId != -2);
+                        fInsideMenuLoop = !fEndMenu;
+                        break;
+                    }
+
+                    /* Hack to avoid control chars. */
+                    /* We will find a better way real soon... */
+                    if (msg.wParam < 32) break;
+
+                    pos = MENU_FindItemByKey(mt.OwnerWnd, mt.CurrentMenu, LOWORD(msg.wParam), FALSE);
+
+                    if (pos == (UINT)-2) fInsideMenuLoop = FALSE;
+                    else if (pos == (UINT)-1) UserPostMessage(hwndSAS, WM_LOGONNOTIFY, LN_MESSAGE_BEEP, 0); //MessageBeep(0);
+                    else
+                    {
+                        MENU_SelectItem(mt.OwnerWnd, mt.CurrentMenu, pos, TRUE, 0);
+                        executedMenuId = MENU_ExecFocusedItem(&mt, mt.CurrentMenu, wFlags);
+                        fEndMenu = (executedMenuId != -2);
+                        fInsideMenuLoop = !fEndMenu;
+                    }
+                }
+                break;
+            }  /* switch(msg.message) - kbd */
+        }
+        else
+        {
+            co_IntGetPeekMessage( &msg, 0, msg.message, msg.message, PM_REMOVE, FALSE );
+            IntDispatchMessage( &msg );
+            continue;
+        }
+
+        if (fInsideMenuLoop) fRemove = TRUE;
+
+        /* finally remove message from the queue */
+
+        if (fRemove && !(mt.TrackFlags & TF_SKIPREMOVE) )
+            co_IntGetPeekMessage( &msg, 0, msg.message, msg.message, PM_REMOVE, FALSE );
+        else mt.TrackFlags &= ~TF_SKIPREMOVE;
+    }
+
+    MsqSetStateWindow(pti, MSQ_STATE_MENUOWNER, NULL);
+    pti->MessageQueue->QF_flags &= ~QF_CAPTURELOCKED;
+    co_UserSetCapture(NULL); /* release the capture */
+
+    /* If dropdown is still painted and the close box is clicked on
+       then the menu will be destroyed as part of the DispatchMessage above.
+       This will then invalidate the menu handle in mt.hTopMenu. We should
+       check for this first.  */
+    if ( VerifyMenu( mt.TopMenu ) )
+    {
+       if (VerifyWnd(mt.OwnerWnd))
+       {
+           MENU_HideSubPopups(mt.OwnerWnd, mt.TopMenu, FALSE, wFlags);
+
+           if (mt.TopMenu->fFlags & MNF_POPUP)
+           {
+              PWND pwndTM = ValidateHwndNoErr(mt.TopMenu->hWnd);
+              if (pwndTM)
+              {
+                 IntNotifyWinEvent(EVENT_SYSTEM_MENUPOPUPEND, pwndTM, OBJID_CLIENT, CHILDID_SELF, 0);
+
+                 co_UserDestroyWindow(pwndTM);
+              }
+              mt.TopMenu->hWnd = NULL;
+
+              if (!(wFlags & TPM_NONOTIFY))
+              {
+                 co_IntSendMessage( UserHMGetHandle(mt.OwnerWnd), WM_UNINITMENUPOPUP, (WPARAM)UserHMGetHandle(mt.TopMenu),
+                                 MAKELPARAM(0, IS_SYSTEM_MENU(mt.TopMenu)) );
+              }
+            }
+            MENU_SelectItem( mt.OwnerWnd, mt.TopMenu, NO_SELECTED_ITEM, FALSE, 0 );
+            co_IntSendMessage( UserHMGetHandle(mt.OwnerWnd), WM_MENUSELECT, MAKEWPARAM(0, 0xffff), 0 );
+       }
+
+       /* Reset the variable for hiding menu */
+       mt.TopMenu->TimeToHide = FALSE;
+    }
+
+    EngSetLastError( ERROR_SUCCESS );
+    /* The return value is only used by TrackPopupMenu */
+    if (!(wFlags & TPM_RETURNCMD)) return TRUE;
+    if (executedMenuId == -1) executedMenuId = 0;
+    return executedMenuId;
+}
+
+/***********************************************************************
+ *           MenuInitTracking
+ */
+static BOOL FASTCALL MENU_InitTracking(PWND pWnd, PMENU Menu, BOOL bPopup, UINT wFlags)
+{
+    HWND capture_win;
+    PTHREADINFO pti = PsGetCurrentThreadWin32Thread();
+
+    TRACE("hwnd=%p hmenu=%p\n", UserHMGetHandle(pWnd), UserHMGetHandle(Menu));
+
+    co_UserHideCaret(0);
+
+    /* This makes the menus of applications built with Delphi work.
+     * It also enables menus to be displayed in more than one window,
+     * but there are some bugs left that need to be fixed in this case.
+     */
+    if (!bPopup)
+    {
+        Menu->hWnd = UserHMGetHandle(pWnd);
+    }
+
+    if (!top_popup) {
+       top_popup = Menu->hWnd;
+       top_popup_hmenu = UserHMGetHandle(Menu);
+    }
+
+    fInsideMenuLoop = TRUE;
+    fInEndMenu = FALSE;
+
+    /* Send WM_ENTERMENULOOP and WM_INITMENU message only if TPM_NONOTIFY flag is not specified */
+    if (!(wFlags & TPM_NONOTIFY))
+    {
+       co_IntSendMessage( UserHMGetHandle(pWnd), WM_ENTERMENULOOP, bPopup, 0 );
+    }
+
+    //
+    // Capture is set before calling WM_INITMENU and after WM_ENTERMENULOOP, see msg_menu.
+    //
+    capture_win = (wFlags & TPM_POPUPMENU) ? Menu->hWnd : UserHMGetHandle(pWnd);
+    MsqSetStateWindow(pti, MSQ_STATE_MENUOWNER, capture_win); // 1
+    co_UserSetCapture(capture_win);                           // 2
+    pti->MessageQueue->QF_flags |= QF_CAPTURELOCKED; // Set the Q bits so noone can change this!
+
+    co_IntSendMessage( UserHMGetHandle(pWnd), WM_SETCURSOR, (WPARAM)UserHMGetHandle(pWnd), HTCAPTION );
+
+    if (!(wFlags & TPM_NONOTIFY))
+    {
+       co_IntSendMessage( UserHMGetHandle(pWnd), WM_INITMENU, (WPARAM)UserHMGetHandle(Menu), 0 );
+       /* If an app changed/recreated menu bar entries in WM_INITMENU
+        * menu sizes will be recalculated once the menu created/shown.
+        */
+    }
+
+    IntNotifyWinEvent( EVENT_SYSTEM_MENUSTART,
+                       pWnd,
+                       Menu->fFlags & MNF_SYSMENU ? OBJID_SYSMENU : OBJID_MENU,
+                       CHILDID_SELF, 0);
+    return TRUE;
+}
+
+/***********************************************************************
+ *           MenuExitTracking
+ */
+static BOOL FASTCALL MENU_ExitTracking(PWND pWnd, BOOL bPopup, UINT wFlags)
+{
+    TRACE("Exit Track hwnd=%p bPopup %d\n", UserHMGetHandle(pWnd), bPopup);
+
+    IntNotifyWinEvent( EVENT_SYSTEM_MENUEND, pWnd, OBJID_WINDOW, CHILDID_SELF, 0);
+
+    if (!(wFlags & TPM_NONOTIFY))
+       co_IntSendMessage( UserHMGetHandle(pWnd), WM_EXITMENULOOP, bPopup, 0 );
+
+    co_UserShowCaret(0);
+
+    top_popup = 0;
+    top_popup_hmenu = NULL;
+
+    return TRUE;
+}
+
+/***********************************************************************
+ *           MenuTrackMouseMenuBar
+ *
+ * Menu-bar tracking upon a mouse event. Called from NC_HandleSysCommand().
+ */
+VOID MENU_TrackMouseMenuBar( PWND pWnd, ULONG ht, POINT pt)
+{
+    PMENU pMenu = (ht == HTSYSMENU) ? IntGetSystemMenu(pWnd, FALSE) : IntGetMenu( UserHMGetHandle(pWnd) ); // See 74276 and CORE-12801
+    UINT wFlags = TPM_BUTTONDOWN | TPM_LEFTALIGN | TPM_LEFTBUTTON;
+
+    TRACE("wnd=%p ht=0x%04x (%ld,%ld)\n", pWnd, ht, pt.x, pt.y);
+
+    if (pWnd->ExStyle & WS_EX_LAYOUTRTL) wFlags |= TPM_LAYOUTRTL;
+    if (VerifyMenu(pMenu))
+    {
+        /* map point to parent client coordinates */
+        PWND Parent = UserGetAncestor(pWnd, GA_PARENT );
+        if (Parent != UserGetDesktopWindow())
+        {
+            IntScreenToClient(Parent, &pt);
+        }
+
+        MENU_InitTracking(pWnd, pMenu, FALSE, wFlags);
+        /* fetch the window menu again, it may have changed */
+        pMenu = (ht == HTSYSMENU) ? get_win_sys_menu( UserHMGetHandle(pWnd) ) : IntGetMenu( UserHMGetHandle(pWnd) );
+        MENU_TrackMenu(pMenu, wFlags, pt.x, pt.y, pWnd, NULL);
+        MENU_ExitTracking(pWnd, FALSE, wFlags);
+    }
+}
+
+/***********************************************************************
+ *           MenuTrackKbdMenuBar
+ *
+ * Menu-bar tracking upon a keyboard event. Called from NC_HandleSysCommand().
+ */
+VOID MENU_TrackKbdMenuBar(PWND pwnd, UINT wParam, WCHAR wChar)
+{
+    UINT uItem = NO_SELECTED_ITEM;
+    PMENU TrackMenu;
+    UINT wFlags = TPM_LEFTALIGN | TPM_LEFTBUTTON;
+
+    TRACE("hwnd %p wParam 0x%04x wChar 0x%04x\n", UserHMGetHandle(pwnd), wParam, wChar);
+
+    /* find window that has a menu */
+
+    while (!( (pwnd->style & (WS_CHILD | WS_POPUP)) != WS_CHILD ) )
+        if (!(pwnd = UserGetAncestor( pwnd, GA_PARENT ))) return;
+
+    /* check if we have to track a system menu */
+
+    TrackMenu = IntGetMenu( UserHMGetHandle(pwnd) );
+    if (!TrackMenu || (pwnd->style & WS_MINIMIZE) != 0 || wChar == ' ' )
+    {
+        if (!(pwnd->style & WS_SYSMENU)) return;
+        TrackMenu = get_win_sys_menu( UserHMGetHandle(pwnd) );
+        uItem = 0;
+        wParam |= HTSYSMENU; /* prevent item lookup */
+    }
+
+    if (!VerifyMenu( TrackMenu )) return;
+
+    MENU_InitTracking( pwnd, TrackMenu, FALSE, wFlags );
+
+    /* fetch the window menu again, it may have changed */
+    TrackMenu = (wParam & HTSYSMENU) ? get_win_sys_menu( UserHMGetHandle(pwnd) ) : IntGetMenu( UserHMGetHandle(pwnd) );
+
+    if( wChar && wChar != ' ' )
+    {
+        uItem = MENU_FindItemByKey( pwnd, TrackMenu, wChar, (wParam & HTSYSMENU) );
+        if ( uItem >= (UINT)(-2) )
+        {
+            if( uItem == (UINT)(-1) ) UserPostMessage(hwndSAS, WM_LOGONNOTIFY, LN_MESSAGE_BEEP, 0); //MessageBeep(0);
+            /* schedule end of menu tracking */
+            wFlags |= TF_ENDMENU;
+            goto track_menu;
+        }
+    }
+
+    MENU_SelectItem( pwnd, TrackMenu, uItem, TRUE, 0 );
+
+    if (!(wParam & HTSYSMENU) || wChar == ' ')
+    {
+        if( uItem == NO_SELECTED_ITEM )
+            MENU_MoveSelection( pwnd, TrackMenu, ITEM_NEXT );
+        else
+            UserPostMessage( UserHMGetHandle(pwnd), WM_KEYDOWN, VK_RETURN, 0 );
+    }
+
+track_menu:
+    MENU_TrackMenu( TrackMenu, wFlags, 0, 0, pwnd, NULL );
+    MENU_ExitTracking( pwnd, FALSE, wFlags);
+}
+
+/**********************************************************************
+ *           TrackPopupMenuEx   (USER32.@)
+ */
+BOOL WINAPI IntTrackPopupMenuEx( PMENU menu, UINT wFlags, int x, int y,
+                              PWND pWnd, LPTPMPARAMS lpTpm)
+{
+    BOOL ret = FALSE;
+    PTHREADINFO pti = PsGetCurrentThreadWin32Thread();
+
+    if (pti != pWnd->head.pti)
+    {
+       ERR("Must be the same pti!\n");
+       return ret;
+    }
+
+    TRACE("hmenu %p flags %04x (%d,%d) hwnd %p lpTpm %p \n", //rect %s\n",
+            UserHMGetHandle(menu), wFlags, x, y, UserHMGetHandle(pWnd), lpTpm); //,
+            //lpTpm ? wine_dbgstr_rect( &lpTpm->rcExclude) : "-" );
+
+    if (menu->hWnd && IntIsWindow(menu->hWnd))
+    {
+        EngSetLastError( ERROR_POPUP_ALREADY_ACTIVE );
+        return FALSE;
+    }
+
+    if (MENU_InitPopup( pWnd, menu, wFlags ))
+    {
+       MENU_InitTracking(pWnd, menu, TRUE, wFlags);
+
+       /* Send WM_INITMENUPOPUP message only if TPM_NONOTIFY flag is not specified */
+       if (!(wFlags & TPM_NONOTIFY))
+       {
+          co_IntSendMessage( UserHMGetHandle(pWnd), WM_INITMENUPOPUP, (WPARAM) UserHMGetHandle(menu), 0);
+       }
+
+       if (menu->fFlags & MNF_SYSMENU)
+          MENU_InitSysMenuPopup( menu, pWnd->style, pWnd->pcls->style, HTSYSMENU);
+
+       if (MENU_ShowPopup(pWnd, menu, 0, wFlags, x, y, 0, 0 ))
+          ret = MENU_TrackMenu( menu, wFlags | TPM_POPUPMENU, 0, 0, pWnd,
+                                lpTpm ? &lpTpm->rcExclude : NULL);
+       else
+       {
+          MsqSetStateWindow(pti, MSQ_STATE_MENUOWNER, NULL);
+          pti->MessageQueue->QF_flags &= ~QF_CAPTURELOCKED;
+          co_UserSetCapture(NULL); /* release the capture */
+       }
+
+       MENU_ExitTracking(pWnd, TRUE, wFlags);
+
+       if (menu->hWnd)
+       {
+          PWND pwndM = ValidateHwndNoErr( menu->hWnd );
+          if (pwndM) // wine hack around this with their destroy function.
+          {
+             if (!(pWnd->state & WNDS_DESTROYED))
+                co_UserDestroyWindow( pwndM ); // Fix wrong error return.
+          }
+          menu->hWnd = 0;
+
+          if (!(wFlags & TPM_NONOTIFY))
+          {
+             co_IntSendMessage( UserHMGetHandle(pWnd), WM_UNINITMENUPOPUP, (WPARAM)UserHMGetHandle(menu),
+                                            MAKELPARAM(0, IS_SYSTEM_MENU(menu)) );
+          }
+       }
+    }
+    return ret;
+}
+
+//
+// Menu Class Proc.
+//
+BOOL WINAPI
+PopupMenuWndProc(
+   PWND Wnd,
+   UINT Message,
+   WPARAM wParam,
+   LPARAM lParam,
+   LRESULT *lResult)
+{
+  PPOPUPMENU pPopupMenu;
+
+  *lResult = 0;
+
+  TRACE("PMWP : pwnd=%x msg=%d wp=0x%04lx lp=0x%08lx\n", Wnd, Message, wParam, lParam);
+
+  if (Wnd)
+  {
+     if (!Wnd->fnid)
+     {
+        if (Message != WM_NCCREATE)
+        {
+           *lResult = IntDefWindowProc(Wnd, Message, wParam, lParam, FALSE);
+           return TRUE;
+        }
+        Wnd->fnid = FNID_MENU;
+        pPopupMenu = DesktopHeapAlloc( Wnd->head.rpdesk, sizeof(POPUPMENU) );
+        pPopupMenu->posSelectedItem = NO_SELECTED_ITEM;
+        pPopupMenu->spwndPopupMenu = Wnd;
+        ((PMENUWND)Wnd)->ppopupmenu = pPopupMenu;
+        TRACE("Pop Up Menu is Setup! Msg %d\n",Message);
+        *lResult = 1;
+        return TRUE;
+     }
+     else
+     {
+        if (Wnd->fnid != FNID_MENU)
+        {
+           ERR("Wrong window class for Menu! fnid %x\n",Wnd->fnid);
+           return TRUE;
+        }
+        pPopupMenu = ((PMENUWND)Wnd)->ppopupmenu;
+     }
+  }
+
+  switch(Message)
+    {
+    case WM_CREATE:
+      {
+        CREATESTRUCTW *cs = (CREATESTRUCTW *) lParam;
+        pPopupMenu->spmenu = UserGetMenuObject(cs->lpCreateParams);
+        break;
+      }
+
+    case WM_MOUSEACTIVATE:  /* We don't want to be activated */
+      *lResult = MA_NOACTIVATE;
+      break;
+
+    case WM_PAINT:
+      {
+        PAINTSTRUCT ps;
+        IntBeginPaint(Wnd, &ps);
+        MENU_DrawPopupMenu(Wnd, ps.hdc, pPopupMenu->spmenu);
+        IntEndPaint(Wnd, &ps);
+        break;
+      }
+
+    case WM_PRINTCLIENT:
+      {
+         MENU_DrawPopupMenu( Wnd, (HDC)wParam, pPopupMenu->spmenu);
+         break;
+      }
+
+    case WM_ERASEBKGND:
+      *lResult = 1;
+      break;
+
+    case WM_DESTROY:
+      /* zero out global pointer in case resident popup window was destroyed. */
+      if (pPopupMenu)
+      {
+         if (UserHMGetHandle(Wnd) == top_popup)
+         {
+             top_popup = NULL;
+             top_popup_hmenu = NULL;
+         }
+      }
+      else
+      {
+         ERR("No Window Pop Up!\n");
+      }
+      break;
+
+    case WM_NCDESTROY:
+      {
+         DesktopHeapFree(Wnd->head.rpdesk, pPopupMenu );
+         ((PMENUWND)Wnd)->ppopupmenu = 0;
+         Wnd->fnid = FNID_DESTROY;
+         break;
+      }
+
+    case MM_SETMENUHANDLE: // wine'isms
+    case MN_SETHMENU:
+      {
+        PMENU pmenu = UserGetMenuObject((HMENU)wParam);
+        if (!pmenu)
+        {
+           ERR("Bad Menu Handle\n");
+           break;
+        }
+        pPopupMenu->spmenu = pmenu;
+        break;
+      }
+
+    case MM_GETMENUHANDLE: // wine'isms
+    case MN_GETHMENU:
+         *lResult = (LRESULT)(pPopupMenu ? (pPopupMenu->spmenu ? UserHMGetHandle(pPopupMenu->spmenu) : NULL) : NULL);
+         break;
+
+    default:
+      if (Message > MN_GETHMENU && Message < MN_GETHMENU+19)
+      {
+         ERR("Someone is passing unknown menu messages %d\n",Message);
+      }
+      TRACE("PMWP to IDWP %d\n",Message);
+      *lResult = IntDefWindowProc(Wnd, Message, wParam, lParam, FALSE);
+      break;
+    }
+
+  return TRUE;
+}
+
+BOOL FASTCALL
+IntHiliteMenuItem(PWND WindowObject,
+                  PMENU MenuObject,
+                  UINT uItemHilite,
+                  UINT uHilite)
+{
+   PITEM MenuItem;
+   UINT uItem = uItemHilite;
+
+   if (!(MenuItem = MENU_FindItem( &MenuObject, &uItem, uHilite ))) return TRUE;
+
+   if (uHilite & MF_HILITE)
+   {
+      MenuItem->fState |= MF_HILITE;
+   }
+   else
+   {
+      MenuItem->fState &= ~MF_HILITE;
+   }
+   if (MenuObject->iItem == uItemHilite) return TRUE;
+   MENU_HideSubPopups( WindowObject, MenuObject, FALSE, 0 );
+   MENU_SelectItem( WindowObject, MenuObject, uItemHilite, TRUE, 0 );
+
+   return TRUE; // Always returns true!!!!
+}
+
+BOOLEAN APIENTRY
+intGetTitleBarInfo(PWND pWindowObject, PTITLEBARINFO bti)
+{
+
+    DWORD dwStyle = 0;
+    DWORD dwExStyle = 0;
+    BOOLEAN retValue = TRUE;
+
+    if (bti->cbSize == sizeof(TITLEBARINFO))
+    {
+        RtlZeroMemory(&bti->rgstate[0],sizeof(DWORD)*(CCHILDREN_TITLEBAR+1));
+
+        bti->rgstate[0] = STATE_SYSTEM_FOCUSABLE;
+
+        dwStyle = pWindowObject->style;
+        dwExStyle = pWindowObject->ExStyle;
+
+        bti->rcTitleBar.top  = 0;
+        bti->rcTitleBar.left = 0;
+        bti->rcTitleBar.right  = pWindowObject->rcWindow.right - pWindowObject->rcWindow.left;
+        bti->rcTitleBar.bottom = pWindowObject->rcWindow.bottom - pWindowObject->rcWindow.top;
+
+        /* Is it iconiced ? */
+        if ((dwStyle & WS_ICONIC)!=WS_ICONIC)
         {
             /* Remove frame from rectangle */
             if (HAS_THICKFRAME( dwStyle, dwExStyle ))
@@ -1339,10 +4753,10 @@ UINT FASTCALL IntGetMenuState( HMENU hMenu, UINT uId, UINT uFlags)
 
    if (pItem->spSubMenu)
    {
-      return (pItem->spSubMenu->cItems << 8) | ((pItem->fState|pItem->fType) & 0xff);
+      return (pItem->spSubMenu->cItems << 8) | ((pItem->fState|pItem->fType|MF_POPUP) & 0xff);
    }
    else
-      return (pItem->fType | pItem->fState);  
+      return (pItem->fType | pItem->fState);
 }
 
 HMENU FASTCALL IntGetSubMenu( HMENU hMenu, int nPos)
@@ -1367,43 +4781,22 @@ HMENU FASTCALL IntGetSubMenu( HMENU hMenu, int nPos)
 
 UINT FASTCALL IntFindSubMenu(HMENU *hMenu, HMENU hSubTarget )
 {
-    PMENU menu;
-    HMENU hSubMenu;
-    UINT i;
-    PITEM item;
-
+    PMENU menu, pSubTarget;
+    UINT Pos;
     if (((*hMenu)==(HMENU)0xffff) ||(!(menu = UserGetMenuObject(*hMenu))))
         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;
+    pSubTarget = UserGetMenuObject(hSubTarget);
+
+    Pos = MENU_FindSubMenu(&menu, pSubTarget );
+
+    *hMenu = (menu ? UserHMGetHandle(menu) : NULL);
+
+    return Pos;
 }
 
 
-HMENU FASTCALL UserCreateMenu(BOOL PopupMenu)
+HMENU FASTCALL UserCreateMenu(PDESKTOP Desktop, BOOL PopupMenu)
 {
    PWINSTATION_OBJECT WinStaObject;
    HANDLE Handle;
@@ -1418,9 +4811,10 @@ HMENU FASTCALL UserCreateMenu(BOOL PopupMenu)
        */
 
       Status = IntValidateWindowStationHandle(CurrentProcess->Win32WindowStation,
-                     KernelMode,
+                     UserMode,
                      0,
-                     &WinStaObject);
+                     &WinStaObject,
+                     0);
 
        if (!NT_SUCCESS(Status))
        {
@@ -1429,8 +4823,8 @@ HMENU FASTCALL UserCreateMenu(BOOL PopupMenu)
           SetLastNtError(Status);
           return (HMENU)0;
        }
-       Menu = IntCreateMenu(&Handle, !PopupMenu);
-       if (Menu->head.rpdesk->rpwinstaParent != WinStaObject)
+       Menu = IntCreateMenu(&Handle, !PopupMenu, Desktop, GetW32ProcessInfo());
+       if (Menu && Menu->head.rpdesk->rpwinstaParent != WinStaObject)
        {
           ERR("Desktop Window Station does not match Process one!\n");
        }
@@ -1438,7 +4832,7 @@ HMENU FASTCALL UserCreateMenu(BOOL PopupMenu)
    }
    else
    {
-       Menu = IntCreateMenu(&Handle, !PopupMenu);
+       Menu = IntCreateMenu(&Handle, !PopupMenu, GetW32ThreadInfo()->rpdesk, GetW32ProcessInfo());
    }
 
    if (Menu) UserDereferenceObject(Menu);
@@ -1494,9 +4888,9 @@ UserMenuItemInfo(
       SetLastNtError(Status);
       return( FALSE);
    }
-   if (sizeof(MENUITEMINFOW) != Size
-         && FIELD_OFFSET(MENUITEMINFOW, hbmpItem) != Size
-         && sizeof(ROSMENUITEMINFO) != Size)
+   if ( Size != sizeof(MENUITEMINFOW) && 
+        Size != FIELD_OFFSET(MENUITEMINFOW, hbmpItem) &&
+        Size != sizeof(ROSMENUITEMINFO) )
    {
       EngSetLastError(ERROR_INVALID_PARAMETER);
       return( FALSE);
@@ -1518,6 +4912,10 @@ UserMenuItemInfo(
 
    if (!(MenuItem = MENU_FindItem( &Menu, &Item, (ByPosition ? MF_BYPOSITION : MF_BYCOMMAND) )))
    {
+      /* workaround for Word 95: pretend that SC_TASKLIST item exists. */
+      if ( SetOrGet && Item == SC_TASKLIST && !ByPosition )
+         return TRUE;
+
       EngSetLastError(ERROR_MENU_ITEM_NOT_FOUND);
       return( FALSE);
    }
@@ -1560,7 +4958,7 @@ UserMenuInfo(
       SetLastNtError(Status);
       return( FALSE);
    }
-   if(Size < sizeof(MENUINFO) || sizeof(ROSMENUINFO) < Size)
+   if ( Size < sizeof(MENUINFO) || Size > sizeof(ROSMENUINFO) )
    {
       EngSetLastError(ERROR_INVALID_PARAMETER);
       return( FALSE);
@@ -1595,21 +4993,6 @@ UserMenuInfo(
    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,
@@ -1619,6 +5002,20 @@ IntGetMenuItemRect(
 {
    LONG XMove, YMove;
    PITEM MenuItem;
+   UINT I = uItem;
+
+   if ((MenuItem = MENU_FindItem (&Menu, &I, 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! %u\n", uItem);
+      return FALSE;
+   }
 
    if (!pWnd)
    {
@@ -1626,40 +5023,323 @@ IntGetMenuItemRect(
       if (!(pWnd = UserGetWindowObject(hWnd))) return FALSE;
    }
 
-   if ((MenuItem = MENU_FindItem (&Menu, &uItem, MF_BYPOSITION)))
+   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 = UserHMGetHandle(Window);
+
+   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 = MF_POPUP;
+      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;
+}
+
+BOOL FASTCALL
+IntSetMenu(
+   PWND Wnd,
+   HMENU Menu,
+   BOOL *Changed)
+{
+   PMENU OldMenu, NewMenu = NULL;
+
+   if ((Wnd->style & (WS_CHILD | WS_POPUP)) == WS_CHILD)
+   {
+      ERR("SetMenu: Window is a Child 0x%p!\n",UserHMGetHandle(Wnd));
+      EngSetLastError(ERROR_INVALID_WINDOW_HANDLE);
+      return FALSE;
+   }
+
+   *Changed = (UlongToHandle(Wnd->IDMenu) != Menu);
+   if (! *Changed)
+   {
+      return TRUE;
+   }
+
+   if (Wnd->IDMenu)
    {
-      Rect->left   = MenuItem->xItem; 
-      Rect->top    = MenuItem->yItem; 
-      Rect->right  = MenuItem->cxItem; // Do this for now......
-      Rect->bottom = MenuItem->cyItem;
+      OldMenu = IntGetMenuObject(UlongToHandle(Wnd->IDMenu));
+      ASSERT(NULL == OldMenu || OldMenu->hWnd == UserHMGetHandle(Wnd));
    }
    else
    {
-      ERR("Failed Item Lookup! %d\n", uItem);
-      return FALSE;
+      OldMenu = NULL;
    }
 
-   if (Menu->fFlags & MNF_POPUP)
+   if (NULL != Menu)
    {
-     XMove = pWnd->rcClient.left;
-     YMove = pWnd->rcClient.top;
+      NewMenu = IntGetMenuObject(Menu);
+      if (NULL == NewMenu)
+      {
+         if (NULL != OldMenu)
+         {
+            IntReleaseMenuObject(OldMenu);
+         }
+         EngSetLastError(ERROR_INVALID_MENU_HANDLE);
+         return FALSE;
+      }
+      if (NULL != NewMenu->hWnd)
+      {
+         /* Can't use the same menu for two windows */
+         if (NULL != OldMenu)
+         {
+            IntReleaseMenuObject(OldMenu);
+         }
+         EngSetLastError(ERROR_INVALID_MENU_HANDLE);
+         return FALSE;
+      }
+
    }
-   else
+
+   Wnd->IDMenu = (UINT) Menu;
+   if (NULL != NewMenu)
    {
-     XMove = pWnd->rcWindow.left;
-     YMove = pWnd->rcWindow.top;
+      NewMenu->hWnd = UserHMGetHandle(Wnd);
+      IntReleaseMenuObject(NewMenu);
+   }
+   if (NULL != OldMenu)
+   {
+      OldMenu->hWnd = NULL;
+      IntReleaseMenuObject(OldMenu);
    }
-
-   Rect->left   += XMove;
-   Rect->top    += YMove;
-   Rect->right  += XMove;
-   Rect->bottom += YMove;
 
    return TRUE;
 }
 
+
 /* FUNCTIONS *****************************************************************/
 
+/*
+ * @implemented
+ */
+/* http://www.cyber-ta.org/releases/malware-analysis/public/SOURCES/b47155634ccb2c30630da7e3666d3d07/b47155634ccb2c30630da7e3666d3d07.trace.html#NtUserGetIconSize */
+DWORD
+APIENTRY
+NtUserCalcMenuBar(
+    HWND   hwnd,
+    DWORD  leftBorder,
+    DWORD  rightBorder,
+    DWORD  top,
+    LPRECT prc )
+{
+    HDC hdc;
+    PWND Window;
+    RECT Rect;
+    DWORD ret;
+
+    UserEnterExclusive();
+
+    if(!(Window = UserGetWindowObject(hwnd)))
+    {
+        EngSetLastError(ERROR_INVALID_WINDOW_HANDLE);
+        UserLeave();
+        return 0;
+    }
+
+    hdc = UserGetDCEx(NULL, NULL, DCX_CACHE);
+    if (!hdc)
+    {
+        UserLeave();
+        return 0;
+    }
+
+    Rect.left = leftBorder;
+    Rect.right = Window->rcWindow.right - Window->rcWindow.left - rightBorder;
+    Rect.top = top;
+    Rect.bottom = 0;
+
+    ret = MENU_DrawMenuBar(hdc, &Rect, Window, TRUE);
+
+    UserReleaseDC( 0, hdc, FALSE );
+
+    UserLeave();
+
+    return ret;
+}
+
 /*
  * @implemented
  */
@@ -1716,6 +5396,107 @@ CLEANUP:
    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
  */
@@ -1801,7 +5582,7 @@ BOOL FASTCALL UserDestroyMenu(HMENU hMenu)
       EngSetLastError(ERROR_ACCESS_DENIED);
       return FALSE;
    }
-   return IntDestroyMenuObject(Menu, FALSE, TRUE);
+   return IntDestroyMenuObject(Menu, FALSE);
 }
 
 /*
@@ -1826,7 +5607,7 @@ NtUserDestroyMenu(
       EngSetLastError(ERROR_ACCESS_DENIED);
       RETURN( FALSE);
    }
-   RETURN( IntDestroyMenuObject(Menu, TRUE, TRUE));
+   RETURN( IntDestroyMenuObject(Menu, TRUE));
 
 CLEANUP:
    TRACE("Leave NtUserDestroyMenu, ret=%i\n",_ret_);
@@ -1862,6 +5643,36 @@ CLEANUP:
    END_CLEANUP;
 }
 
+/*
+ * @implemented
+ */
+BOOL APIENTRY
+NtUserEndMenu(VOID)
+{
+   //PWND pWnd;
+   TRACE("Enter NtUserEndMenu\n");
+   UserEnterExclusive();
+ /*  if ( gptiCurrent->pMenuState &&
+        gptiCurrent->pMenuState->pGlobalPopupMenu )
+   {
+       pWnd = IntGetMSWND(gptiCurrent->pMenuState);
+       if (pWnd)
+       {
+          UserPostMessage( UserHMGetHandle(pWnd), WM_CANCELMODE, 0, 0);
+       }
+       else
+          gptiCurrent->pMenuState->fInsideMenuLoop = FALSE;
+   }*/
+   if (fInsideMenuLoop && top_popup)
+   {
+      fInsideMenuLoop = FALSE;
+      UserPostMessage( top_popup, WM_CANCELMODE, 0, 0);
+   }
+   UserLeave();
+   TRACE("Leave NtUserEndMenu\n");
+   return TRUE;
+}
+
 /*
  * @implemented
  */
@@ -1876,6 +5687,8 @@ NtUserGetMenuBarInfo(
    HMENU hMenu;
    MENUBARINFO kmbi;
    BOOL Ret;
+   PPOPUPMENU pPopupMenu;
+   USER_REFERENCE_ENTRY Ref;
    NTSTATUS Status = STATUS_SUCCESS;
    PMENU Menu = NULL;
    DECLARE_RETURN(BOOL);
@@ -1889,6 +5702,14 @@ NtUserGetMenuBarInfo(
         RETURN(FALSE);
    }
 
+   UserRefObjectCo(pWnd, &Ref);
+
+   RECTL_vSetEmptyRect(&kmbi.rcBar);
+   kmbi.hMenu = NULL;
+   kmbi.hwndMenu = NULL;
+   kmbi.fBarFocused = FALSE;
+   kmbi.fFocused = FALSE;
+
    switch (idObject)
    {
     case OBJID_CLIENT:
@@ -1896,20 +5717,30 @@ NtUserGetMenuBarInfo(
             RETURN(FALSE);
         if (pWnd->pcls->fnid != FNID_MENU)
         {
-            WARN("called on invalid window: %d\n", pWnd->pcls->fnid);
+            WARN("called on invalid window: %u\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);
+        pPopupMenu = ((PMENUWND)pWnd)->ppopupmenu;
+        if (pPopupMenu && pPopupMenu->spmenu)
+        {
+           if (UserHMGetHandle(pPopupMenu->spmenu) != hMenu)
+           {
+              ERR("Window Pop Up hMenu %p not the same as Get hMenu %p!\n",pPopupMenu->spmenu->head.h,hMenu);
+           }
+        }
         break;
     case OBJID_MENU:
+        if (pWnd->style & WS_CHILD) RETURN(FALSE);
         hMenu = UlongToHandle(pWnd->IDMenu);
+        TRACE("GMBI: OBJID_MENU hMenu %p\n",hMenu);
         break;
     case OBJID_SYSMENU:
         if (!(pWnd->style & WS_SYSMENU)) RETURN(FALSE);
-        Menu = IntGetSystemMenu(pWnd, FALSE, FALSE);
-        hMenu = Menu->head.h;
+        Menu = IntGetSystemMenu(pWnd, FALSE);
+        hMenu = UserHMGetHandle(Menu);
         break;
     default:
         RETURN(FALSE);
@@ -1920,6 +5751,7 @@ NtUserGetMenuBarInfo(
 
    _SEH2_TRY
    {
+       ProbeForRead(pmbi, sizeof(MENUBARINFO), 1);
        kmbi.cbSize = pmbi->cbSize;
    }
    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
@@ -1938,29 +5770,25 @@ NtUserGetMenuBarInfo(
    if (!Menu)
        RETURN(FALSE);
 
-   if (idItem < 0 || idItem > Menu->cItems)
+   if ((idItem < 0) || ((ULONG)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);
+      TRACE("idItem 0 %d\n",Ret);
    }
    else
    {
       Ret = IntGetMenuItemRect(pWnd, Menu, idItem-1, &kmbi.rcBar);
-      TRACE("idItem X %d\n", Ret);
+      TRACE("idItem b %d %d\n", idItem-1, Ret);
    }
 
    kmbi.hMenu = hMenu;
-   kmbi.hwndMenu = NULL;
-   kmbi.fBarFocused = FALSE;
-   kmbi.fFocused = FALSE;
-   //kmbi.fBarFocused = top_popup_hmenu == hMenu;
+   kmbi.fBarFocused = top_popup_hmenu == hMenu;
+   TRACE("GMBI: top p hm %p hMenu %p\n",top_popup_hmenu, hMenu);
    if (idItem)
    {
        kmbi.fFocused = Menu->iItem == idItem-1;
@@ -1969,13 +5797,14 @@ NtUserGetMenuBarInfo(
           kmbi.hwndMenu = Menu->rgItems[idItem - 1].spSubMenu->hWnd;
        }
    }
-/*   else
+   else
    {
        kmbi.fFocused = kmbi.fBarFocused;
    }
-*/
+
    _SEH2_TRY
    {
+      ProbeForWrite(pmbi, sizeof(MENUBARINFO), 1);
       RtlCopyMemory(pmbi, &kmbi, sizeof(MENUBARINFO));
    }
    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
@@ -1993,6 +5822,7 @@ NtUserGetMenuBarInfo(
    RETURN(TRUE);
 
 CLEANUP:
+   if (pWnd) UserDerefObjectCo(pWnd);
    TRACE("Leave NtUserGetMenuBarInfo, ret=%i\n",_ret_);
    UserLeave();
    END_CLEANUP;
@@ -2060,8 +5890,8 @@ NtUserGetMenuItemRect(
 
    if ((MenuItem = MENU_FindItem (&Menu, &uItem, MF_BYPOSITION)))
    {
-      Rect.left   = MenuItem->xItem; 
-      Rect.top    = MenuItem->yItem; 
+      Rect.left   = MenuItem->xItem;
+      Rect.top    = MenuItem->yItem;
       Rect.right  = MenuItem->cxItem; // Do this for now......
       Rect.bottom = MenuItem->cyItem;
    }
@@ -2153,6 +5983,63 @@ CLEANUP:
    END_CLEANUP;
 }
 
+/*
+ * @implemented
+ */
+DWORD
+APIENTRY
+NtUserDrawMenuBarTemp(
+   HWND hWnd,
+   HDC hDC,
+   PRECT pRect,
+   HMENU hMenu,
+   HFONT hFont)
+{
+   PMENU Menu;
+   PWND Window;
+   RECT Rect;
+   NTSTATUS Status = STATUS_SUCCESS;
+   DECLARE_RETURN(DWORD);
+
+   ERR("Enter NtUserDrawMenuBarTemp\n");
+   UserEnterExclusive();
+
+   if(!(Window = UserGetWindowObject(hWnd)))
+   {
+      EngSetLastError(ERROR_INVALID_WINDOW_HANDLE);
+      RETURN(0);
+   }
+
+   if(!(Menu = UserGetMenuObject(hMenu)))
+   {
+      EngSetLastError(ERROR_INVALID_MENU_HANDLE);
+      RETURN(0);
+   }
+
+   _SEH2_TRY
+   {
+      ProbeForRead(pRect, sizeof(RECT), sizeof(ULONG));
+      RtlCopyMemory(&Rect, pRect, sizeof(RECT));
+   }
+   _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+   {
+      Status = _SEH2_GetExceptionCode();
+   }
+   _SEH2_END;
+
+   if (Status != STATUS_SUCCESS)
+   {
+      SetLastNtError(Status);
+      RETURN(0);
+   }
+
+   RETURN( IntDrawMenuBarTemp(Window, hDC, &Rect, Menu, hFont));
+
+CLEANUP:
+   ERR("Leave NtUserDrawMenuBarTemp, ret=%u\n",_ret_);
+   UserLeave();
+   END_CLEANUP;
+}
 
 /*
  * @implemented
@@ -2167,7 +6054,7 @@ NtUserMenuItemFromPoint(
    PMENU Menu;
    PWND Window = NULL;
    PITEM mi;
-   int i;
+   ULONG i;
    DECLARE_RETURN(int);
 
    TRACE("Enter NtUserMenuItemFromPoint\n");
@@ -2190,11 +6077,14 @@ NtUserMenuItemFromPoint(
    for (i = 0; i < Menu->cItems; i++, mi++)
    {
       RECTL Rect;
-      Rect.left   = mi->xItem; 
-      Rect.top    = mi->yItem; 
-      Rect.right  = mi->cxItem; // Do this for now......
+
+      Rect.left   = mi->xItem;
+      Rect.top    = mi->yItem;
+      Rect.right  = mi->cxItem;
       Rect.bottom = mi->cyItem;
-      //MENU_AdjustMenuItemRect(Menu, &Rect); Need gpsi OBMI via callback!
+
+      MENU_AdjustMenuItemRect(Menu, &Rect);
+
       if (RECTL_bPointInRect(&Rect, X, Y))
       {
          break;
@@ -2210,6 +6100,41 @@ CLEANUP:
 }
 
 
+DWORD
+APIENTRY
+NtUserPaintMenuBar(
+    HWND hWnd,
+    HDC hDC,
+    ULONG leftBorder,
+    ULONG rightBorder,
+    ULONG top,
+    BOOL bActive)
+{
+   PWND Window;
+   RECT Rect;
+   DWORD ret;
+
+   UserEnterExclusive();
+
+   if(!(Window = UserGetWindowObject(hWnd)))
+   {
+      EngSetLastError(ERROR_INVALID_WINDOW_HANDLE);
+      UserLeave();
+      return 0;
+   }
+
+   Rect.left = leftBorder;
+   Rect.right = Window->rcWindow.right - Window->rcWindow.left - rightBorder;
+   Rect.top = top;
+   Rect.bottom = 0;
+
+   ret = MENU_DrawMenuBar(hDC, &Rect, Window, FALSE);
+
+   UserLeave();
+
+   return ret;
+}
+
 /*
  * @implemented
  */
@@ -2239,6 +6164,49 @@ CLEANUP:
 
 }
 
+/*
+ * @implemented
+ */
+BOOL APIENTRY
+NtUserSetMenu(
+   HWND hWnd,
+   HMENU Menu,
+   BOOL Repaint)
+{
+   PWND Window;
+   BOOL Changed;
+   DECLARE_RETURN(BOOL);
+
+   TRACE("Enter NtUserSetMenu\n");
+   UserEnterExclusive();
+
+   if (!(Window = UserGetWindowObject(hWnd)))
+   {
+      RETURN( FALSE);
+   }
+
+   if (!IntSetMenu(Window, Menu, &Changed))
+   {
+      RETURN( FALSE);
+   }
+
+   // Not minimized and please repaint!!!
+   if (!(Window->style & WS_MINIMIZE) && (Repaint || Changed))
+   {
+      USER_REFERENCE_ENTRY Ref;
+      UserRefObjectCo(Window, &Ref);
+      co_WinPosSetWindowPos(Window, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED);
+      UserDerefObjectCo(Window);
+   }
+
+   RETURN( TRUE);
+
+CLEANUP:
+   TRACE("Leave NtUserSetMenu, ret=%i\n",_ret_);
+   UserLeave();
+   END_CLEANUP;
+}
+
 /*
  * @implemented
  */
@@ -2370,13 +6338,13 @@ NtUserThunkedMenuItemInfo(
    /* lpszCaption may be NULL, check for it and call RtlInitUnicodeString()
       if bInsert == TRUE call UserInsertMenuItem() else UserSetMenuItemInfo()   */
 
+   RtlInitEmptyUnicodeString(&lstrCaption, NULL, 0);
+
    if (!(Menu = UserGetMenuObject(hMenu)))
    {
       RETURN(FALSE);
    }
 
-   RtlInitUnicodeString(&lstrCaption, 0);
-
    /* Check if we got a Caption */
    if (lpszCaption && lpszCaption->Buffer)
    {
@@ -2397,9 +6365,71 @@ NtUserThunkedMenuItemInfo(
    RETURN( UserMenuItemInfo(Menu, uItem, fByPosition, (PROSMENUITEMINFO)lpmii, TRUE, &lstrCaption));
 
 CLEANUP:
+   if (lstrCaption.Buffer)
+   {
+      ReleaseCapturedUnicodeString(&lstrCaption, UserMode);
+   }
+
    TRACE("Leave NtUserThunkedMenuItemInfo, ret=%i\n",_ret_);
    UserLeave();
    END_CLEANUP;
 }
 
+/*
+ * @implemented
+ */
+BOOL APIENTRY
+NtUserTrackPopupMenuEx(
+   HMENU hMenu,
+   UINT fuFlags,
+   int x,
+   int y,
+   HWND hWnd,
+   LPTPMPARAMS lptpm)
+{
+   PMENU menu;
+   PWND pWnd;
+   TPMPARAMS tpm;
+   BOOL Ret = FALSE;
+   USER_REFERENCE_ENTRY Ref;
+
+   TRACE("Enter NtUserTrackPopupMenuEx\n");
+   UserEnterExclusive();
+   /* Parameter check */
+   if (!(menu = UserGetMenuObject( hMenu )))
+   {
+      ERR("TPME : Invalid Menu handle.\n");
+      EngSetLastError( ERROR_INVALID_MENU_HANDLE );
+      goto Exit;
+   }
+
+   if (!(pWnd = UserGetWindowObject(hWnd)))
+   {
+      ERR("TPME : Invalid Window handle.\n");
+      goto Exit;
+   }
+
+   if (lptpm)
+   {
+      _SEH2_TRY
+      {
+         ProbeForRead(lptpm, sizeof(TPMPARAMS), sizeof(ULONG));
+         tpm = *lptpm;
+      }
+      _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+      { 
+         _SEH2_YIELD(goto Exit);
+      }
+      _SEH2_END
+   }
+   UserRefObjectCo(pWnd, &Ref);
+   Ret = IntTrackPopupMenuEx(menu, fuFlags, x, y, pWnd, lptpm ? &tpm : NULL);
+   UserDerefObjectCo(pWnd);
+
+Exit:
+   TRACE("Leave NtUserTrackPopupMenuEx, ret=%i\n",Ret);
+   UserLeave();
+   return Ret;
+}
+
 /* EOF */