[USER32]
[reactos.git] / reactos / dll / win32 / user32 / windows / menu.c
index c48a031..badf2d9 100644 (file)
 /* INCLUDES ******************************************************************/
 
 #include <user32.h>
-
 #include <wine/debug.h>
-WINE_DEFAULT_DEBUG_CHANNEL(user32);
+
+LRESULT DefWndNCPaint(HWND hWnd, HRGN hRgn, BOOL Active);
+
+WINE_DEFAULT_DEBUG_CHANNEL(menu);
 
 /* internal popup menu window messages */
-#define MM_SETMENUHANDLE (WM_USER + 0)
-#define MM_GETMENUHANDLE (WM_USER + 1)
+
+#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
+
+#define ITEM_PREV              -1
+#define ITEM_NEXT               1
 
 /* Internal MenuTrackMenu() flags */
 #define TPM_INTERNAL           0xF0000000
@@ -26,13 +38,14 @@ WINE_DEFAULT_DEBUG_CHANNEL(user32);
 #define TPM_BUTTONDOWN         0x40000000              /* menu was clicked before tracking */
 #define TPM_POPUPMENU           0x20000000              /* menu is a popup menu */
 
-/* TYPES *********************************************************************/
 
 #define MENU_TYPE_MASK (MF_STRING | MF_BITMAP | MF_OWNERDRAW | MF_SEPARATOR)
 
 #define MENU_ITEM_TYPE(flags) ((flags) & MENU_TYPE_MASK)
+
+/* macro to test that flags do not indicate bitmap, ownerdraw or separator */
 #define IS_STRING_ITEM(flags) (MF_STRING == MENU_ITEM_TYPE(flags))
-#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_SYSTEM_MENU(MenuInfo)  \
        (0 == ((MenuInfo)->Flags & MF_POPUP) && 0 != ((MenuInfo)->Flags & MF_SYSMENU))
@@ -40,28 +53,25 @@ WINE_DEFAULT_DEBUG_CHANNEL(user32);
 #define IS_SYSTEM_POPUP(MenuInfo) \
        (0 != ((MenuInfo)->Flags & MF_POPUP) && 0 != ((MenuInfo)->Flags & MF_SYSMENU))
 
-#define IS_MAGIC_ITEM(Bmp)   ((int) Bmp <12)
-#define IS_MAGIC_BITMAP(id) ((id) && ((INT_PTR)(id) < 12) && ((INT_PTR)(id) >= -1))
+#define IS_BITMAP_ITEM(flags) (MF_BITMAP == MENU_ITEM_TYPE(flags))
+
+/* Use global popup window because there's no way 2 menus can
+ * be tracked at the same time.  */
+static HWND TopPopup;
+
+/* Flag set by EndMenu() to force an exit from menu tracking */
+static BOOL fEndMenu = FALSE;
 
 #define MENU_ITEM_HBMP_SPACE (5)
 #define MENU_BAR_ITEMS_SPACE (12)
 #define SEPARATOR_HEIGHT (5)
 #define MENU_TAB_SPACE (8)
 
-#define ITEM_PREV              -1
-#define ITEM_NEXT               1
-
 #define MAKEINTATOMA(atom)  ((LPCSTR)((ULONG_PTR)((WORD)(atom))))
 #define MAKEINTATOMW(atom)  ((LPCWSTR)((ULONG_PTR)((WORD)(atom))))
 #define POPUPMENU_CLASS_ATOMA   MAKEINTATOMA(32768)  /* PopupMenu */
 #define POPUPMENU_CLASS_ATOMW   MAKEINTATOMW(32768)  /* PopupMenu */
 
-/* internal flags for menu tracking */
-
-#define TF_ENDMENU              0x0001
-#define TF_SUSPENDPOPUP         0x0002
-#define TF_SKIPREMOVE          0x0004
-
 typedef struct
 {
   UINT  TrackFlags;
@@ -71,7 +81,6 @@ typedef struct
   POINT Pt;
 } MTRACKER;
 
-static LRESULT WINAPI PopupMenuWndProcW(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
 
 /*********************************************************************
  * PopupMenu class descriptor
@@ -80,21 +89,13 @@ const struct builtin_class_descr POPUPMENU_builtin_class =
 {
     POPUPMENU_CLASS_ATOMW,                     /* name */
     CS_SAVEBITS | CS_DBLCLKS,                  /* style  */
-    (WNDPROC) PopupMenuWndProcW,               /* FIXME - procW */
     (WNDPROC) NULL,                            /* FIXME - procA */
+    (WNDPROC) PopupMenuWndProcW,               /* FIXME - procW */
     sizeof(MENUINFO *),                        /* extra */
     (LPCWSTR) IDC_ARROW,                       /* cursor */
     (HBRUSH)(COLOR_MENU + 1)                   /* brush */
 };
 
-
-/* INTERNAL FUNCTIONS ********************************************************/
-
-/* Rip the fun and easy to use and fun WINE unicode string manipulation routines.
- * Of course I didnt copy the ASM code because we want this to be portable
- * and it needs to go away.
- */
-
 #ifndef GET_WORD
 #define GET_WORD(ptr)  (*(WORD *)(ptr))
 #endif
@@ -105,17 +106,7 @@ const struct builtin_class_descr POPUPMENU_builtin_class =
 HFONT hMenuFont = NULL;
 HFONT hMenuFontBold = NULL;
 
-/* Flag set by EndMenu() to force an exit from menu tracking */
-static BOOL fEndMenu = FALSE;
-
-/* Use global popup window because there's no way 2 menus can
- * be tracked at the same time.  */
-static HWND TopPopup;
-
 /* Dimension of the menu bitmaps */
-static WORD ArrowBitmapWidth = 0, ArrowBitmapHeight = 0;
-
-static HBITMAP StdMnArrow = NULL;
 static HBITMAP BmpSysMenu = NULL;
 
 static SIZE MenuCharSize;
@@ -137,7 +128,7 @@ MenuGetRosMenuInfo(PROSMENUINFO MenuInfo, HMENU Menu)
 /***********************************************************************
  *           MenuSetRosMenuInfo
  *
- * Set full information about menu      
+ * Set full information about menu
  */
 static BOOL FASTCALL
 MenuSetRosMenuInfo(PROSMENUINFO MenuInfo)
@@ -169,12 +160,12 @@ static BOOL FASTCALL
 MenuGetRosMenuItemInfo(HMENU Menu, UINT Index, PROSMENUITEMINFO ItemInfo)
 {
   UINT Save_Mask = ItemInfo->fMask; /* Save the org mask bits. */
-  
+
   if (ItemInfo->dwTypeData != NULL)
     {
       HeapFree(GetProcessHeap(), 0, ItemInfo->dwTypeData);
     }
-  
+
 
   ItemInfo->fMask = MIIM_BITMAP | MIIM_CHECKMARKS | MIIM_DATA | MIIM_FTYPE
              | MIIM_ID | MIIM_STATE | MIIM_STRING | MIIM_SUBMENU | MIIM_TYPE;
@@ -287,25 +278,146 @@ MenuCleanupAllRosMenuItemInfo(PROSMENUITEMINFO ItemInfo)
 static void FASTCALL
 MenuLoadBitmaps(VOID)
 {
-  /* Load menu bitmaps */
-  if (NULL == StdMnArrow)
+  /* Load system buttons bitmaps */
+  if (NULL == BmpSysMenu)
+    {
+      BmpSysMenu = LoadBitmapW(0, MAKEINTRESOURCEW(OBM_CLOSE));
+    }
+}
+
+/***********************************************************************
+ *           MenuDrawPopupGlyph
+ *
+ * Draws popup magic glyphs (can be found in system menu).
+ */
+static void FASTCALL
+MenuDrawPopupGlyph(HDC dc, LPRECT r, INT_PTR popupMagic, BOOL inactive, BOOL hilite)
+{
+  LOGFONTW lf;
+  HFONT hFont, hOldFont;
+  COLORREF clrsave;
+  INT bkmode;
+  TCHAR 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;
+  }
+  ZeroMemory(&lf, sizeof(LOGFONTW));
+  InflateRect(r, -2, -2);
+  lf.lfHeight = r->bottom - r->top;
+  lf.lfWidth = 0;
+  lf.lfWeight = FW_NORMAL;
+  lf.lfCharSet = DEFAULT_CHARSET;
+  lstrcpy(lf.lfFaceName, TEXT("Marlett"));
+  hFont = CreateFontIndirect(&lf);
+  /* save font and text color */
+  hOldFont = SelectObject(dc, hFont);
+  clrsave = GetTextColor(dc);
+  bkmode = GetBkMode(dc);
+  /* set color and drawing mode */
+  SetBkMode(dc, TRANSPARENT);
+  if (inactive)
+  {
+    /* draw shadow */
+    if (!hilite)
     {
-      StdMnArrow = LoadBitmapW(0, MAKEINTRESOURCEW(OBM_MNARROW));
+      SetTextColor(dc, GetSysColor(COLOR_HIGHLIGHTTEXT));
+      TextOut(dc, r->left + 1, r->top + 1, &symbol, 1);
+    }
+  }
+  SetTextColor(dc, GetSysColor(inactive ? COLOR_GRAYTEXT : (hilite ? COLOR_HIGHLIGHTTEXT : COLOR_MENUTEXT)));
+  /* draw selected symbol */
+  TextOut(dc, r->left, r->top, &symbol, 1);
+  /* restore previous settings */
+  SetTextColor(dc, clrsave);
+  SelectObject(dc, hOldFont);
+  SetBkMode(dc, bkmode);
+  DeleteObject(hFont);
+}
+
+/***********************************************************************
+ *           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 MenuFindItemByKey(HWND WndOwner, PROSMENUINFO MenuInfo,
+                  WCHAR Key, BOOL ForceMenuChar)
+{
+  ROSMENUINFO SysMenuInfo;
+  PROSMENUITEMINFO Items, ItemInfo;
+  LRESULT MenuChar;
+  UINT i;
+
+  TRACE("\tlooking for '%c' (0x%02x) in [%p]\n", (char) Key, Key, MenuInfo);
 
-      if (NULL != StdMnArrow)
+  if (NULL == MenuInfo || ! IsMenu(MenuInfo->Self))
+    {
+      if (MenuGetRosMenuInfo(&SysMenuInfo, GetSystemMenu(WndOwner, FALSE)))
+        {
+          MenuInfo = &SysMenuInfo;
+        }
+      else
         {
-          BITMAP bm;
-          GetObjectW(StdMnArrow, sizeof(BITMAP), &bm);
-          ArrowBitmapWidth = bm.bmWidth;
-          ArrowBitmapHeight = bm.bmHeight;
+          MenuInfo = NULL;
         }
     }
 
-  /* Load system buttons bitmaps */
-  if (NULL == BmpSysMenu)
+  if (NULL != MenuInfo)
     {
-      BmpSysMenu = LoadBitmapW(0, MAKEINTRESOURCEW(OBM_CLOSE));
+      if (MenuGetAllRosMenuItemInfo(MenuInfo->Self, &Items) <= 0)
+        {
+          return -1;
+        }
+      if (! ForceMenuChar)
+        {
+          Key = toupperW(Key);
+          ItemInfo = Items;
+          for (i = 0; i < MenuInfo->MenuItemCount; i++, ItemInfo++)
+            {
+              if ((ItemInfo->Text) && NULL != ItemInfo->dwTypeData)
+                {
+                  WCHAR *p = (WCHAR *) ItemInfo->dwTypeData - 2;
+                  do
+                    {
+                      p = strchrW(p + 2, '&');
+                   }
+                  while (NULL != p && L'&' == p[1]);
+                  if (NULL != p && (toupperW(p[1]) == Key))
+                    {
+                      return i;
+                    }
+                }
+            }
+        }
+
+      MenuChar = SendMessageW(WndOwner, WM_MENUCHAR,
+                              MAKEWPARAM(Key, MenuInfo->Flags), (LPARAM) MenuInfo->Self);
+      if (2 == HIWORD(MenuChar))
+        {
+          return LOWORD(MenuChar);
+        }
+      if (1 == HIWORD(MenuChar))
+        {
+          return (UINT) (-2);
+        }
     }
+
+  return (UINT)(-1);
 }
 
 /***********************************************************************
@@ -313,18 +425,18 @@ MenuLoadBitmaps(VOID)
  *
  * Get the size of a bitmap item.
  */
-static void FASTCALL
-MenuGetBitmapItemSize(PROSMENUITEMINFO lpitem, SIZE *Size, HWND WndOwner)
+static void FASTCALL MenuGetBitmapItemSize(PROSMENUITEMINFO lpitem, SIZE *size,
+                                                                                  HWND WndOwner)
 {
-  BITMAP Bm;
-  HBITMAP Bmp = lpitem->hbmpItem;
+    BITMAP bm;
+    HBITMAP bmp = lpitem->hbmpItem;
 
-  Size->cx = Size->cy = 0;
+    size->cx = size->cy = 0;
 
-  /* check if there is a magic menu item associated with this item */
-  if (0 != Bmp && IS_MAGIC_ITEM((INT)(Bmp)))
+    /* check if there is a magic menu item associated with this item */
+    if (IS_MAGIC_BITMAP(bmp))
     {
-      switch((INT_PTR) Bmp)
+      switch((INT_PTR) bmp)
         {
             case (INT_PTR)HBMMENU_CALLBACK:
             {
@@ -336,8 +448,8 @@ MenuGetBitmapItemSize(PROSMENUITEMINFO lpitem, SIZE *Size, HWND WndOwner)
                 measItem.itemHeight = lpitem->Rect.bottom - lpitem->Rect.top;
                 measItem.itemData = lpitem->dwItemData;
                 SendMessageW( WndOwner, WM_MEASUREITEM, lpitem->wID, (LPARAM)&measItem);
-                Size->cx = measItem.itemWidth;
-                Size->cy = measItem.itemHeight;
+                size->cx = measItem.itemWidth;
+                size->cy = measItem.itemHeight;
                 return;
             }
             break;
@@ -345,7 +457,7 @@ MenuGetBitmapItemSize(PROSMENUITEMINFO lpitem, SIZE *Size, HWND WndOwner)
           case (INT_PTR) HBMMENU_SYSTEM:
             if (0 != lpitem->dwItemData)
               {
-                Bmp = (HBITMAP) lpitem->dwItemData;
+                bmp = (HBITMAP) lpitem->dwItemData;
                 break;
               }
             /* fall through */
@@ -354,25 +466,22 @@ MenuGetBitmapItemSize(PROSMENUITEMINFO lpitem, SIZE *Size, HWND WndOwner)
           case (INT_PTR) HBMMENU_MBAR_CLOSE:
           case (INT_PTR) HBMMENU_MBAR_MINIMIZE_D:
           case (INT_PTR) HBMMENU_MBAR_CLOSE_D:
-            /* FIXME: Why we need to subtract these magic values? */
-            /* to make them smaller than the menu bar? */
-            Size->cx = GetSystemMetrics(SM_CXSIZE) - 2;
-            Size->cy = GetSystemMetrics(SM_CYSIZE) - 4;
-            return;
           case (INT_PTR) HBMMENU_POPUP_CLOSE:
           case (INT_PTR) HBMMENU_POPUP_RESTORE:
           case (INT_PTR) HBMMENU_POPUP_MAXIMIZE:
           case (INT_PTR) HBMMENU_POPUP_MINIMIZE:
-          default:
-            FIXME("Magic menu bitmap not implemented\n");
+            /* FIXME: Why we need to subtract these magic values? */
+            /* to make them smaller than the menu bar? */
+            size->cx = GetSystemMetrics(SM_CXSIZE) - 2;
+            size->cy = GetSystemMetrics(SM_CYSIZE) - 4;
             return;
         }
     }
 
-  if (GetObjectW(Bmp, sizeof(BITMAP), &Bm))
+    if (GetObjectW(bmp, sizeof(BITMAP), &bm))
     {
-      Size->cx = Bm.bmWidth;
-      Size->cy = Bm.bmHeight;
+        size->cx = bm.bmWidth;
+        size->cy = bm.bmHeight;
     }
 }
 
@@ -381,91 +490,84 @@ MenuGetBitmapItemSize(PROSMENUITEMINFO lpitem, SIZE *Size, HWND WndOwner)
  *
  * Draw a bitmap item.
  */
-static void FASTCALL
-MenuDrawBitmapItem(HDC Dc, PROSMENUITEMINFO Item, const RECT *Rect,
+static void FASTCALL MenuDrawBitmapItem(HDC hdc, PROSMENUITEMINFO lpitem, const RECT *rect,
                     HMENU hmenu, HWND WndOwner, UINT odaction, BOOL MenuBar)
 {
-  BITMAP Bm;
-  DWORD Rop;
-  HDC DcMem;
-  HBITMAP Bmp;
-  int w = Rect->right - Rect->left;
-  int h = Rect->bottom - Rect->top;
-  int BmpXoffset = 0;
-  int Left, Top;
-  HBITMAP hbmpToDraw = (HBITMAP) Item->hbmpItem;
-  Bmp = hbmpToDraw;
-
-  /* Check if there is a magic menu item associated with this item */
-  if (IS_MAGIC_ITEM(hbmpToDraw))
-    {
-      UINT Flags = 0;
-      RECT r;
-
-      r = *Rect;
-      switch ((INT_PTR)hbmpToDraw)
+    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->hbmpItem;
+    bmp = hbmToDraw;
+
+    /* Check if there is a magic menu item associated with this item */
+    if (IS_MAGIC_BITMAP(hbmToDraw))
+    {
+        UINT flags = 0;
+        RECT r;
+
+      r = *rect;
+      switch ((INT_PTR)hbmToDraw)
         {
-          case (INT_PTR) HBMMENU_SYSTEM:
-            if (NULL != Item->dwTypeData)
-              {
-                Bmp = (HBITMAP)Item->dwTypeData;
-                if (! GetObjectW(Bmp, sizeof(BITMAP), &Bm))
-                  {
-                    return;
-                  }
-              }
+        case (INT_PTR)HBMMENU_SYSTEM:
+            if (lpitem->dwTypeData)
+            {
+                bmp = (HBITMAP)lpitem->dwTypeData;
+                if (!GetObjectW( bmp, sizeof(bm), &bm )) return;
+            }
             else
-              {
+            {
                 if (!BmpSysMenu) BmpSysMenu = LoadBitmapW(0, MAKEINTRESOURCEW(OBM_CLOSE));
-                Bmp = BmpSysMenu;
-                if (! GetObjectW(Bmp, sizeof(BITMAP), &Bm))
-                  {
-                    return;
-                  }
+                bmp = BmpSysMenu;
+                if (! GetObjectW(bmp, sizeof(bm), &bm)) return;
                 /* only use right half of the bitmap */
-                BmpXoffset = Bm.bmWidth / 2;
-                Bm.bmWidth -= BmpXoffset;
-              }
+                bmp_xoffset = bm.bmWidth / 2;
+                bm.bmWidth -= bmp_xoffset;
+            }
             goto got_bitmap;
-          case (INT_PTR) HBMMENU_MBAR_RESTORE:
-            Flags = DFCS_CAPTIONRESTORE;
+        case (INT_PTR)HBMMENU_MBAR_RESTORE:
+            flags = DFCS_CAPTIONRESTORE;
             break;
-          case (INT_PTR) HBMMENU_MBAR_MINIMIZE:
+        case (INT_PTR)HBMMENU_MBAR_MINIMIZE:
             r.right += 1;
-            Flags = DFCS_CAPTIONMIN;
+            flags = DFCS_CAPTIONMIN;
             break;
-          case (INT_PTR) HBMMENU_MBAR_MINIMIZE_D:
+        case (INT_PTR)HBMMENU_MBAR_MINIMIZE_D:
             r.right += 1;
-            Flags = DFCS_CAPTIONMIN | DFCS_INACTIVE;
+            flags = DFCS_CAPTIONMIN | DFCS_INACTIVE;
             break;
-          case (INT_PTR) HBMMENU_MBAR_CLOSE:
-            Flags = DFCS_CAPTIONCLOSE;
+        case (INT_PTR)HBMMENU_MBAR_CLOSE:
+            flags = DFCS_CAPTIONCLOSE;
             break;
-          case (INT_PTR) HBMMENU_MBAR_CLOSE_D:
-            Flags = DFCS_CAPTIONCLOSE | DFCS_INACTIVE;
+        case (INT_PTR)HBMMENU_MBAR_CLOSE_D:
+            flags = DFCS_CAPTIONCLOSE | DFCS_INACTIVE;
             break;
-          case (INT_PTR) HBMMENU_CALLBACK:
+        case (INT_PTR)HBMMENU_CALLBACK:
             {
                 DRAWITEMSTRUCT drawItem;
                 POINT origorg;
                 drawItem.CtlType = ODT_MENU;
                 drawItem.CtlID = 0;
-                drawItem.itemID = Item->wID;
+                drawItem.itemID = lpitem->wID;
                 drawItem.itemAction = odaction;
-                drawItem.itemState = (Item->fState & MF_CHECKED)?ODS_CHECKED:0;
-                drawItem.itemState |= (Item->fState & MF_DEFAULT)?ODS_DEFAULT:0;
-                drawItem.itemState |= (Item->fState & MF_DISABLED)?ODS_DISABLED:0;
-                drawItem.itemState |= (Item->fState & MF_GRAYED)?ODS_GRAYED|ODS_DISABLED:0;
-                drawItem.itemState |= (Item->fState & MF_HILITE)?ODS_SELECTED:0;
+                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.hwndItem = (HWND)hmenu;
-                drawItem.hDC = Dc;
-                drawItem.rcItem = *Rect;
-                drawItem.itemData = Item->dwItemData;
+                drawItem.hDC = hdc;
+                drawItem.rcItem = *rect;
+                drawItem.itemData = lpitem->dwItemData;
                 /* some applications make this assumption on the DC's origin */
-                SetViewportOrgEx( Dc, Item->Rect.left, Item->Rect.top, &origorg);
-                OffsetRect( &drawItem.rcItem, - Item->Rect.left, - Item->Rect.top);
+                SetViewportOrgEx( hdc, lpitem->Rect.left, lpitem->Rect.top, &origorg);
+                OffsetRect( &drawItem.rcItem, - lpitem->Rect.left, - lpitem->Rect.top);
                 SendMessageW( WndOwner, WM_DRAWITEM, 0, (LPARAM)&drawItem);
-                SetViewportOrgEx( Dc, origorg.x, origorg.y, NULL);
+                SetViewportOrgEx( hdc, origorg.x, origorg.y, NULL);
                 return;
             }
             break;
@@ -474,403 +576,736 @@ MenuDrawBitmapItem(HDC Dc, PROSMENUITEMINFO Item, const RECT *Rect,
           case (INT_PTR) HBMMENU_POPUP_RESTORE:
           case (INT_PTR) HBMMENU_POPUP_MAXIMIZE:
           case (INT_PTR) HBMMENU_POPUP_MINIMIZE:
-          default:
-            FIXME("Magic menu bitmap not implemented\n");
+            MenuDrawPopupGlyph(hdc, &r, (INT_PTR)hbmToDraw, lpitem->fState & MF_GRAYED, lpitem->fState & MF_HILITE);
             return;
         }
       InflateRect(&r, -1, -1);
-      if (0 != (Item->fState & MF_HILITE))
-        {
-          Flags |= DFCS_PUSHED;
-        }
-      DrawFrameControl(Dc, &r, DFC_CAPTION, Flags);
+      if (0 != (lpitem->fState & MF_HILITE))
+      {
+          flags |= DFCS_PUSHED;
+      }
+      DrawFrameControl(hdc, &r, DFC_CAPTION, flags);
       return;
     }
 
-  if (NULL == Bmp || ! GetObjectW(Bmp, sizeof(BITMAP), &Bm))
-    {
-      return;
-    }
+    if (!bmp || !GetObjectW( bmp, sizeof(bm), &bm )) return;
 
-got_bitmap:
-  DcMem = CreateCompatibleDC(Dc);
-  SelectObject(DcMem, Bmp);
+ got_bitmap:
+    hdcMem = CreateCompatibleDC( hdc );
+    SelectObject( hdcMem, bmp );
 
-  /* handle fontsize > bitmap_height */
-  Top = (Bm.bmHeight < h) ? Rect->top + (h - Bm.bmHeight) / 2 : Rect->top;
-  Left = Rect->left;
-  Rop= ((Item->fState & MF_HILITE) && !IS_MAGIC_BITMAP(hbmpToDraw)) ? NOTSRCCOPY : SRCCOPY;
-  if ((Item->fState & MF_HILITE) && Item->hbmpItem)
-    {
-      SetBkColor(Dc, GetSysColor(COLOR_HIGHLIGHT));
-    }
-  BitBlt(Dc, Left, Top, w, h, DcMem, BmpXoffset, 0, Rop);
-  DeleteDC(DcMem);
+    /* 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->hbmpItem)
+        SetBkColor(hdc, GetSysColor(COLOR_HIGHLIGHT));
+    BitBlt( hdc, left, top, w, h, hdcMem, bmp_xoffset, 0, rop );
+    DeleteDC( hdcMem );
 }
 
 /***********************************************************************
- *           MenuDrawMenuItem
+ *           MenuCalcItemSize
  *
- * Draw a single menu item.
+ * Calculate the size of the menu item and store it in lpitem->rect.
  */
-static void FASTCALL
-MenuDrawMenuItem(HWND Wnd, PROSMENUINFO MenuInfo, HWND WndOwner, HDC Dc,
-                 PROSMENUITEMINFO Item, UINT Height, BOOL MenuBar, UINT Action)
+static void FASTCALL MenuCalcItemSize( HDC hdc, PROSMENUITEMINFO lpitem, PROSMENUINFO MenuInfo, HWND hwndOwner,
+                 INT orgX, INT orgY, BOOL menuBar)
 {
-  RECT Rect;
-  PWCHAR Text;
-  BOOL flat_menu = FALSE;
-  int bkgnd;
-  
-  if (0 != (Item->fType & MF_SYSMENU))
+    WCHAR *p;
+    UINT check_bitmap_width = GetSystemMetrics( SM_CXMENUCHECK );
+    INT itemheight = 0;
+
+    TRACE("dc=%x owner=%x (%d,%d)\n", hdc, hwndOwner, orgX, orgY);
+
+    MenuCharSize.cx = GdiGetCharDimensions( hdc, NULL, &MenuCharSize.cy );
+
+    SetRect( &lpitem->Rect, orgX, orgY, orgX, orgY );
+
+    if (lpitem->fType & MF_OWNERDRAW)
     {
-      if (! IsIconic(Wnd))
-        {
-          UserGetInsideRectNC(Wnd, &Rect);
-          UserDrawSysMenuButton(Wnd, Dc, &Rect,
-                                Item->fState & (MF_HILITE | MF_MOUSESELECT));
-       }
-      return;
+        MEASUREITEMSTRUCT mis;
+        mis.CtlType    = ODT_MENU;
+        mis.CtlID      = 0;
+        mis.itemID     = lpitem->wID;
+        mis.itemData   = lpitem->dwItemData;
+        mis.itemHeight = HIWORD( GetDialogBaseUnits());
+        mis.itemWidth  = 0;
+        SendMessageW( hwndOwner, 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. 
+         */
+        lpitem->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 */
+            lpitem->Rect.bottom += GetSystemMetrics(SM_CYMENUSIZE);
+        } else
+            lpitem->Rect.bottom += mis.itemHeight;
+
+        TRACE("id=%04lx size=%dx%d\n",
+                lpitem->wID, mis.itemWidth, mis.itemHeight);
+        return;
     }
 
-    SystemParametersInfoW (SPI_GETFLATMENU, 0, &flat_menu, 0);
-    bkgnd = (MenuBar && flat_menu) ? COLOR_MENUBAR : COLOR_MENU;
+    if (lpitem->fType & MF_SEPARATOR)
+    {
+        lpitem->Rect.bottom += SEPARATOR_HEIGHT;
+        if( !menuBar)
+            lpitem->Rect.right += check_bitmap_width +  MenuCharSize.cx;
+        return;
+    }
 
-  /* Setup colors */
+    lpitem->XTab = 0;
 
-  if (0 != (Item->fState & MF_HILITE))
+    if (lpitem->hbmpItem)
     {
-      if (MenuBar && !flat_menu)
-        {
-          SetTextColor(Dc, GetSysColor(COLOR_MENUTEXT));
-          SetBkColor(Dc, GetSysColor(COLOR_MENU));
-        }
-      else
-        {
-          if (0 != (Item->fState & MF_GRAYED))
-            {
-              SetTextColor(Dc, GetSysColor(COLOR_GRAYTEXT));
-            }
-          else
+        SIZE size;
+
+        if (!menuBar) {
+            MenuGetBitmapItemSize(lpitem, &size, hwndOwner );
+            /* Keep the size of the bitmap in callback mode to be able
+             * to draw it correctly */
+            lpitem->Rect.right = lpitem->Rect.left + size.cx;
+            if (MenuInfo->maxBmpSize.cx < abs(size.cx) +  MENU_ITEM_HBMP_SPACE ||
+                MenuInfo->maxBmpSize.cy < abs(size.cy))
             {
-              SetTextColor(Dc, GetSysColor(COLOR_HIGHLIGHTTEXT));
+                MenuInfo->maxBmpSize.cx = abs(size.cx) + MENU_ITEM_HBMP_SPACE;
+                MenuInfo->maxBmpSize.cy = abs(size.cy);
             }
-          SetBkColor(Dc, GetSysColor(COLOR_HIGHLIGHT));
+            MenuSetRosMenuInfo(MenuInfo);
+            itemheight = size.cy + 2;
+
+            if( !(MenuInfo->dwStyle & MNS_NOCHECK))
+                lpitem->Rect.right += 2 * check_bitmap_width;
+            lpitem->Rect.right += 4 + MenuCharSize.cx;
+            lpitem->XTab = lpitem->Rect.right;
+            lpitem->Rect.right += check_bitmap_width;
+        } else /* hbmpItem & MenuBar */ {
+            MenuGetBitmapItemSize(lpitem, &size, hwndOwner );
+            lpitem->Rect.right  += size.cx;
+            if( lpitem->Text) lpitem->Rect.right  += 2;
+            itemheight = size.cy;
+
+            /* Special case: Minimize button doesn't have a space behind it. */
+            if (lpitem->hbmpItem == (HBITMAP)HBMMENU_MBAR_MINIMIZE ||
+                lpitem->hbmpItem == (HBITMAP)HBMMENU_MBAR_MINIMIZE_D)
+            lpitem->Rect.right -= 1;
         }
     }
-  else
-    {
-      if (0 != (Item->fState & MF_GRAYED))
-        {
-          SetTextColor(Dc, GetSysColor(COLOR_GRAYTEXT));
-        }
-      else
-        {
-          SetTextColor(Dc, GetSysColor(COLOR_MENUTEXT));
-        }
-      SetBkColor(Dc, GetSysColor(bkgnd));
-    }
-
-  Rect = Item->Rect;
-
-  if (Item->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;
-
-      dis.CtlType   = ODT_MENU;
-      dis.CtlID     = 0;
-      dis.itemID    = Item->wID;
-      dis.itemData  = (DWORD)Item->dwItemData;
-      dis.itemState = 0;
-      if (0 != (Item->fState & MF_CHECKED))
-        {
-          dis.itemState |= ODS_CHECKED;
-        }
-      if (0 != (Item->fState & MF_GRAYED))
-        {
-          dis.itemState |= ODS_GRAYED | ODS_DISABLED;
-        }
-      if (0 != (Item->fState & MF_HILITE))
-        {
-          dis.itemState |= ODS_SELECTED;
+    else if (!menuBar) {
+        if( !(MenuInfo->dwStyle & MNS_NOCHECK))
+             lpitem->Rect.right += check_bitmap_width;
+        lpitem->Rect.right += 4 + MenuCharSize.cx;
+        lpitem->XTab = lpitem->Rect.right;
+        lpitem->Rect.right += check_bitmap_width;
+    }
+
+    /* it must be a text item - unless it's the system menu */
+    if (!(lpitem->fType & MF_SYSMENU) && lpitem->Text) {
+        HFONT hfontOld = NULL;
+        RECT rc = lpitem->Rect;
+        LONG txtheight, txtwidth;
+
+        if ( lpitem->fState & MFS_DEFAULT ) {
+            hfontOld = SelectObject( hdc, hMenuFontBold );
         }
-      dis.itemAction = Action; /* ODA_DRAWENTIRE | ODA_SELECT | ODA_FOCUS; */
-      dis.hwndItem   = (HWND) MenuInfo->Self;
-      dis.hDC        = Dc;
-      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);
-      SendMessageW(WndOwner, WM_DRAWITEM, 0, (LPARAM) &dis);
-      /* Draw the popup-menu arrow */
-      if (0 != (Item->fType & MF_POPUP))
-        {
-          HDC DcMem = CreateCompatibleDC(Dc);
-          HBITMAP OrigBitmap;
-
-          OrigBitmap = SelectObject(DcMem, StdMnArrow);
-          BitBlt(Dc, Rect.right - ArrowBitmapWidth - 1,
-                 ((Rect.top + Rect.bottom) - ArrowBitmapHeight) / 2,
-                 ArrowBitmapWidth, ArrowBitmapHeight,
-                 DcMem, 0, 0, SRCCOPY);
-          SelectObject(DcMem, OrigBitmap);
-          DeleteDC(DcMem);
+        if (menuBar) {
+            txtheight = DrawTextW( hdc, lpitem->dwTypeData, -1, &rc,
+                    DT_SINGLELINE|DT_CALCRECT); 
+            lpitem->Rect.right  += rc.right - rc.left;
+            itemheight = max( max( itemheight, txtheight),
+                    GetSystemMetrics( SM_CYMENU) - 1);
+            lpitem->Rect.right +=  2 * MenuCharSize.cx;
+        } else {
+            if ((p = strchrW( lpitem->dwTypeData, '\t' )) != NULL) {
+                RECT tmprc = rc;
+                LONG tmpheight;
+                int n = (int)( p - lpitem->dwTypeData);
+                /* Item contains a tab (only meaningful in popup menus) */
+                /* get text size before the tab */
+                txtheight = DrawTextW( hdc, lpitem->dwTypeData, 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->XTab += 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->dwTypeData, -1, &rc,
+                        DT_SINGLELINE|DT_CALCRECT);
+                txtwidth = rc.right - rc.left;
+                lpitem->XTab += txtwidth;
+            }
+            lpitem->Rect.right  += 2 + txtwidth;
+            itemheight = max( itemheight,
+                                   max( txtheight + 2, MenuCharSize.cy + 4));
         }
-      return;
+        if (hfontOld) SelectObject (hdc, hfontOld);
+    } else if( menuBar) {
+        itemheight = max( itemheight, GetSystemMetrics(SM_CYMENU)-1);
     }
+    lpitem->Rect.bottom += itemheight;
+    TRACE("(%ld,%ld)-(%ld,%ld)\n", lpitem->Rect.left, lpitem->Rect.top, lpitem->Rect.right, lpitem->Rect.bottom);
+}
 
-  TRACE("rect={%ld,%ld,%ld,%ld}\n", Item->Rect.left, Item->Rect.top,
-                                     Item->Rect.right, Item->Rect.bottom);
-
-  if (MenuBar && 0 != (Item->fType & MF_SEPARATOR))
-  {
-     return;
-  }
+/***********************************************************************
+ *           MenuPopupMenuCalcSize
+ *
+ * Calculate the size of a popup menu.
+ */
+static void FASTCALL MenuPopupMenuCalcSize(PROSMENUINFO MenuInfo, HWND WndOwner)
+{
+    ROSMENUITEMINFO lpitem;
+    HDC hdc;
+    int start, i;
+    int orgX, orgY, maxX, maxTab, maxTabWidth;
 
-  if (Item->fState & MF_HILITE)
-  {
-    if (flat_menu)
-    {
-       InflateRect (&Rect, -1, -1);
-       FillRect(Dc, &Rect, GetSysColorBrush(COLOR_MENUHILIGHT));
-       InflateRect (&Rect, 1, 1);
-       FrameRect(Dc, &Rect, GetSysColorBrush(COLOR_HIGHLIGHT));
-    }
-    else
+    MenuInfo->Width = MenuInfo->Height = 0;
+    if (MenuInfo->MenuItemCount == 0)
     {
-       if (MenuBar)
-       {
-          DrawEdge(Dc, &Rect, BDR_SUNKENOUTER, BF_RECT);
-       }
-       else
-       {
-          FillRect(Dc, &Rect, GetSysColorBrush(COLOR_HIGHLIGHT));
-       }
+        MenuSetRosMenuInfo(MenuInfo);
+        return;
     }
-  }
-  else
-  {
-     FillRect(Dc, &Rect, GetSysColorBrush(bkgnd));
-  }
 
-  SetBkMode(Dc, TRANSPARENT);
+    hdc = GetDC(NULL);
+    SelectObject( hdc, hMenuFont );
 
-  /* vertical separator */
-  if (! MenuBar && 0 != (Item->fType & MF_MENUBARBREAK))
-  {
-    HPEN oldPen;
-    RECT rc = Rect;
-    rc.left -= 3;
-    rc.top = 3;
-    rc.bottom = Height - 3;
-    if (flat_menu)
-    {
-       oldPen = SelectObject( Dc, GetSysColorPen(COLOR_BTNSHADOW) );
-       MoveToEx( Dc, rc.left, rc.top, NULL );
-       LineTo( Dc, rc.left, rc.bottom );
-       SelectObject( Dc, oldPen );
-    }
-    else
-       DrawEdge(Dc, &rc, EDGE_ETCHED, BF_LEFT);
-  }
+    start = 0;
+    maxX = 2 + 1;
 
-  /* horizontal separator */
-  if (0 != (Item->fType & MF_SEPARATOR))
-  {
-    HPEN oldPen;
-    RECT rc = Rect;
-    rc.left++;
-    rc.right--;
-    rc.top += SEPARATOR_HEIGHT / 2;
-    if (flat_menu)
-    {
-       oldPen = SelectObject( Dc, GetSysColorPen(COLOR_BTNSHADOW) );
-       MoveToEx( Dc, rc.left, rc.top, NULL );
-       LineTo( Dc, rc.right, rc.top );
-       SelectObject( Dc, oldPen );
-    }
-    else
-       DrawEdge(Dc, &rc, EDGE_ETCHED, BF_TOP);
-    return;
-  }
+    MenuInfo->maxBmpSize.cx = 0;
+    MenuInfo->maxBmpSize.cy = 0;
 
-#if 0
-  /* helper lines for debugging */
-  /* This is a very good test tool when hacking menus! (JT) 07/16/2006 */
-  FrameRect(Dc, &Rect, GetStockObject(BLACK_BRUSH));
-  SelectObject(Dc, GetSysColorPen(COLOR_WINDOWFRAME));
-  MoveToEx(Dc, Rect.left, (Rect.top + Rect.bottom) / 2, NULL);
-  LineTo(Dc, Rect.right, (Rect.top + Rect.bottom) / 2);
-#endif
+    MenuInitRosMenuItemInfo(&lpitem);
+    while (start < MenuInfo->MenuItemCount)
+    {
+      orgX = maxX;
+      orgY = 2;
 
-  if (! MenuBar)
-  {
-     INT y = Rect.top + Rect.bottom;
-     RECT Rc = Rect;
-     UINT CheckBitmapWidth = GetSystemMetrics(SM_CXMENUCHECK);
-     UINT CheckBitmapHeight = GetSystemMetrics(SM_CYMENUCHECK);
-     int checked = FALSE;
-     /* Draw the check mark
-      *
-      * FIXME:
-      * Custom checkmark bitmaps are monochrome but not always 1bpp.
-      */
-     if( !(MenuInfo->dwStyle & MNS_NOCHECK)) 
-     {
-        HBITMAP bm = 0 != (Item->fState & MF_CHECKED) ? Item->hbmpChecked : Item->hbmpUnchecked;
-        if (NULL != bm)  /* we have a custom bitmap */
-        {
-           HDC DcMem = CreateCompatibleDC(Dc);
-           SelectObject(DcMem, bm);
-           BitBlt(Dc, Rc.left, (y - CheckBitmapHeight) / 2,
-                  CheckBitmapWidth, CheckBitmapHeight,
-                  DcMem, 0, 0, SRCCOPY);
-           DeleteDC(DcMem);
-           checked = TRUE;
-        }
-        else if (0 != (Item->fState & MF_CHECKED))  /* standard bitmaps */
-        {
-           RECT r;
-           HBITMAP bm = CreateBitmap(CheckBitmapWidth, CheckBitmapHeight, 1, 1, NULL);
-           HDC DcMem = CreateCompatibleDC(Dc);
-           SelectObject(DcMem, bm);
-           SetRect( &r, 0, 0, CheckBitmapWidth, CheckBitmapHeight);
-           DrawFrameControl(DcMem, &r, DFC_MENU,
-                            0 != (Item->fType & MFT_RADIOCHECK) ?
-                                 DFCS_MENUBULLET : DFCS_MENUCHECK);
-           BitBlt(Dc, Rc.left, (y - r.bottom) / 2, r.right, r.bottom,
-                  DcMem, 0, 0, SRCCOPY );
-           DeleteDC(DcMem);
-           DeleteObject(bm);
-           checked = TRUE;
-        }
-     }
-     if ((Item->hbmpItem)&& !( checked && (MenuInfo->dwStyle & MNS_CHECKORBMP)))
-     {
-        MenuDrawBitmapItem(Dc, Item, &Rect, MenuInfo->Self, WndOwner, Action, MenuBar);
-     }
-     /* Draw the popup-menu arrow */
-     if (0 != (Item->fType & MF_POPUP))
-     {
-        HDC DcMem = CreateCompatibleDC(Dc);
-        HBITMAP OrigBitmap;
-
-        OrigBitmap = SelectObject(DcMem, StdMnArrow);
-        BitBlt(Dc, Rect.right - ArrowBitmapWidth - 1,
-              (y - ArrowBitmapHeight) / 2,
-               ArrowBitmapWidth, ArrowBitmapHeight,
-               DcMem, 0, 0, SRCCOPY);
-        SelectObject(DcMem, OrigBitmap);
-        DeleteDC(DcMem);
-     }
-     Rect.left += 4;
-     if( !(MenuInfo->dwStyle & MNS_NOCHECK))
-        Rect.left += CheckBitmapWidth;
-     Rect.right -= ArrowBitmapWidth;
-  }
-  else if (Item->hbmpItem) /* Draw the bitmap */
-  {
-     MenuDrawBitmapItem(Dc, Item, &Rect, MenuInfo->Self, WndOwner, Action, MenuBar);
-  }
-  /* No bitmap - process text if present */
-  if (Item->Text)
-  {
-      register int i = 0;
-      HFONT FontOld = NULL;
+      maxTab = maxTabWidth = 0;
 
-      UINT uFormat = MenuBar ? DT_CENTER | DT_VCENTER | DT_SINGLELINE
-                     : DT_LEFT | DT_VCENTER | DT_SINGLELINE;
+      /* Parse items until column break or end of menu */
+      for (i = start; i < MenuInfo->MenuItemCount; i++)
+      {
+          if (! MenuGetRosMenuItemInfo(MenuInfo->Self, i, &lpitem))
+          {
+              MenuCleanupRosMenuItemInfo(&lpitem);
+              MenuSetRosMenuInfo(MenuInfo);
+              return;
+          }
+          if (i != start &&
+               (lpitem.fType & (MF_MENUBREAK | MF_MENUBARBREAK))) break;
 
-      if( !(MenuInfo->dwStyle & MNS_CHECKORBMP))
-             Rect.left += MenuInfo->maxBmpSize.cx;
-             
-      if (0 != (Item->fState & MFS_DEFAULT))
-        {
-          FontOld = SelectObject(Dc, hMenuFontBold);
+          MenuCalcItemSize(hdc, &lpitem, MenuInfo, WndOwner, orgX, orgY, FALSE);
+          if (! MenuSetRosMenuItemInfo(MenuInfo->Self, i, &lpitem))
+          {
+              MenuCleanupRosMenuItemInfo(&lpitem);
+              MenuSetRosMenuInfo(MenuInfo);
+              return;
+          }
+// Not sure here,, The patch from wine removes this.
+//        if ((lpitem.fType & MF_MENUBARBREAK) != 0)
+//        {
+//              OrgX++;
+//        }
+          maxX = max(maxX, lpitem.Rect.right);
+          orgY = lpitem.Rect.bottom;
+          if ((lpitem.Text) && lpitem.XTab )
+             {
+              maxTab = max( maxTab, lpitem.XTab );
+              maxTabWidth = max(maxTabWidth, lpitem.Rect.right - lpitem.XTab);
+          }
         }
 
-      if (MenuBar)
+        /* Finish the column (set all items to the largest width found) */
+        maxX = max( maxX, maxTab + maxTabWidth );
+        while (start < i)
         {
-          Rect.left += MENU_BAR_ITEMS_SPACE / 2;
-          Rect.right -= MENU_BAR_ITEMS_SPACE / 2;
+            if (MenuGetRosMenuItemInfo(MenuInfo->Self, start, &lpitem))
+            {
+                lpitem.Rect.right = maxX;
+                if ((lpitem.Text) && 0 != lpitem.XTab)
+                {
+                    lpitem.XTab = maxTab;
+                }
+                MenuSetRosMenuItemInfo(MenuInfo->Self, start, &lpitem);
+            }
+            start++;
+           }
+        MenuInfo->Height = max(MenuInfo->Height, orgY);
+    }
+
+    MenuInfo->Width  = maxX;
+
+    /* space for 3d border */
+    MenuInfo->Height += 2;
+    MenuInfo->Width += 2;
+
+    MenuCleanupRosMenuItemInfo(&lpitem);
+    MenuSetRosMenuInfo(MenuInfo);
+    ReleaseDC( 0, hdc );
+}
+
+/***********************************************************************
+ *           MenuMenuBarCalcSize
+ *
+ * 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 FASTCALL MenuMenuBarCalcSize( HDC hdc, LPRECT lprect,
+                                          PROSMENUINFO MenuInfo, HWND hwndOwner )
+{
+    ROSMENUITEMINFO ItemInfo;
+    int start, i, orgX, orgY, maxY, helpPos;
+
+    if ((lprect == NULL) || (MenuInfo == NULL)) return;
+    if (MenuInfo->MenuItemCount == 0) return;
+    TRACE("left=%ld top=%ld right=%ld bottom=%ld\n", lprect->left, lprect->top, lprect->right, lprect->bottom);
+    MenuInfo->Width = lprect->right - lprect->left;
+    MenuInfo->Height = 0;
+    maxY = lprect->top + 1;
+    start = 0;
+    helpPos = -1;
+
+    MenuInfo->maxBmpSize.cx = 0;
+    MenuInfo->maxBmpSize.cy = 0;
+
+    MenuInitRosMenuItemInfo(&ItemInfo);
+    while (start < MenuInfo->MenuItemCount)
+    {
+        if (! MenuGetRosMenuItemInfo(MenuInfo->Self, start, &ItemInfo))
+        {
+            MenuCleanupRosMenuItemInfo(&ItemInfo);
+            return;
         }
-      if (Item->hbmpItem == HBMMENU_CALLBACK || MenuInfo->maxBmpSize.cx != 0 )
+        orgX = lprect->left;
+        orgY = maxY;
+
+        /* Parse items until line break or end of menu */
+        for (i = start; i < MenuInfo->MenuItemCount; i++)
+           {
+            if ((helpPos == -1) && (ItemInfo.fType & MF_RIGHTJUSTIFY)) helpPos = i;
+            if ((i != start) &&
+               (ItemInfo.fType & (MF_MENUBREAK | MF_MENUBARBREAK))) break;
+
+            TRACE("calling MENU_CalcItemSize org=(%d, %d)\n", orgX, orgY);
+            MenuCalcItemSize(hdc, &ItemInfo, MenuInfo, hwndOwner, orgX, orgY, TRUE);
+            if (! MenuSetRosMenuItemInfo(MenuInfo->Self, i, &ItemInfo))
+            {
+                MenuCleanupRosMenuItemInfo(&ItemInfo);
+                return;
+            }
+
+            if (ItemInfo.Rect.right > lprect->right)
+            {
+                if (i != start) break;
+                else ItemInfo.Rect.right = lprect->right;
+            }
+            maxY = max( maxY, ItemInfo.Rect.bottom );
+            orgX = ItemInfo.Rect.right;
+            if (i + 1 < MenuInfo->MenuItemCount)
+            {
+                if (! MenuGetRosMenuItemInfo(MenuInfo->Self, i + 1, &ItemInfo))
+                {
+                    MenuCleanupRosMenuItemInfo(&ItemInfo);
+                    return;
+                }
+            }
+       }
+
+/* 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
+        /* Finish the line (set all items to the largest height found) */
+        while (start < i)
         {
-          Rect.left += MenuInfo->maxBmpSize.cx;
-          Rect.right -= MenuInfo->maxBmpSize.cx;
+            if (MenuGetRosMenuItemInfo(MenuInfo->Self, start, &ItemInfo))
+            {
+                ItemInfo.Rect.bottom = maxY;
+                MenuSetRosMenuItemInfo(MenuInfo->Self, start, &ItemInfo);
+            }
+            start++;
         }
+#else
+        start = i; /* This works! */
+#endif
+    }
 
-      Text = (PWCHAR) Item->dwTypeData;
-      if(Text)
+    lprect->bottom = maxY;
+    MenuInfo->Height = lprect->bottom - lprect->top;
+    MenuSetRosMenuInfo(MenuInfo);
+
+    if (helpPos != -1)
+    {
+      /* Flush right all items between the MF_RIGHTJUSTIFY and */
+      /* the last item (if several lines, only move the last line) */
+      if (! MenuGetRosMenuItemInfo(MenuInfo->Self, MenuInfo->MenuItemCount - 1, &ItemInfo))
       {
-        for (i = 0; L'\0' != Text[i]; i++)
+          MenuCleanupRosMenuItemInfo(&ItemInfo);
+          return;
+      }
+      orgY = ItemInfo.Rect.top;
+      orgX = lprect->right;
+      for (i = MenuInfo->MenuItemCount - 1; helpPos <= i; i--)
         {
-          if (L'\t' == Text[i] || L'\b' == Text[i])
+          if (i < helpPos)
+          {
+              break;                           /* done */
+          }
+          if (ItemInfo.Rect.top != orgY)
+          {
+              break;                           /* Other line */
+          }
+          if (orgX <= ItemInfo.Rect.right)
+          {
+              break;                           /* Too far right already */
+          }
+          ItemInfo.Rect.left += orgX - ItemInfo.Rect.right;
+          ItemInfo.Rect.right = orgX;
+          orgX = ItemInfo.Rect.left;
+          MenuSetRosMenuItemInfo(MenuInfo->Self, i, &ItemInfo);
+          if (helpPos + 1 <= i &&
+              ! MenuGetRosMenuItemInfo(MenuInfo->Self, i - 1, &ItemInfo))
             {
-              break;
+                MenuCleanupRosMenuItemInfo(&ItemInfo);
+                return;
             }
         }
-      }
+    }
 
-      if (0 != (Item->fState & MF_GRAYED))
-       {
-          if (0 == (Item->fState & MF_HILITE))
-           {
-              ++Rect.left; ++Rect.top; ++Rect.right; ++Rect.bottom;
-              SetTextColor(Dc, RGB(0xff, 0xff, 0xff));
-              DrawTextW(Dc, Text, i, &Rect, uFormat);
-              --Rect.left; --Rect.top; --Rect.right; --Rect.bottom;
+    MenuCleanupRosMenuItemInfo(&ItemInfo);
+}
+
+/***********************************************************************
+ *           MenuDrawMenuItem
+ *
+ * Draw a single menu item.
+ */
+static void FASTCALL MenuDrawMenuItem(HWND hWnd, PROSMENUINFO MenuInfo, HWND WndOwner, HDC hdc,
+                 PROSMENUITEMINFO lpitem, UINT Height, BOOL menuBar, UINT odaction)
+{
+    RECT rect;
+    PWCHAR Text;
+    BOOL flat_menu = FALSE;
+    int bkgnd;
+    PWND Wnd = ValidateHwnd(hWnd);
+
+    if (!Wnd)
+      return;
+
+    if (lpitem->fType & MF_SYSMENU)
+    {
+        if ( (Wnd->style & WS_MINIMIZE))
+        {
+          UserGetInsideRectNC(Wnd, &rect);
+          UserDrawSysMenuButton(hWnd, hdc, &rect,
+                                lpitem->fState & (MF_HILITE | MF_MOUSESELECT));
            }
-          SetTextColor(Dc, RGB(0x80, 0x80, 0x80));
+        return;
+    }
+
+    SystemParametersInfoW (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) {
+            SetTextColor(hdc, GetSysColor(COLOR_MENUTEXT));
+            SetBkColor(hdc, GetSysColor(COLOR_MENU));
+        } else {
+            if (lpitem->fState & MF_GRAYED)
+                SetTextColor(hdc, GetSysColor(COLOR_GRAYTEXT));
+            else
+                SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT));
+            SetBkColor(hdc, GetSysColor(COLOR_HIGHLIGHT));
         }
+    }
+    else
+    {
+        if (lpitem->fState & MF_GRAYED)
+            SetTextColor( hdc, GetSysColor( COLOR_GRAYTEXT ) );
+        else
+            SetTextColor( hdc, GetSysColor( COLOR_MENUTEXT ) );
+        SetBkColor( hdc, GetSysColor( bkgnd ) );
+    }
+
+    rect = lpitem->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;
+
+        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_GRAYED)  dis.itemState |= ODS_GRAYED | ODS_DISABLED;
+        if (lpitem->fState & MF_HILITE)  dis.itemState |= ODS_SELECTED;
+        dis.itemAction = odaction; /* ODA_DRAWENTIRE | ODA_SELECT | ODA_FOCUS; */
+        dis.hwndItem   = (HWND) MenuInfo->Self;
+        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", hWnd,
+               dis.itemID, dis.itemState, dis.itemAction, dis.hwndItem,
+               dis.hDC, dis.rcItem.left, dis.rcItem.top, dis.rcItem.right,
+               dis.rcItem.bottom);
+        SendMessageW(WndOwner, WM_DRAWITEM, 0, (LPARAM) &dis);
+        /* Draw the popup-menu arrow */
+        if (lpitem->fType & MF_POPUP)
+        {
+            RECT rectTemp;
+            CopyRect(&rectTemp, &rect);
+            rectTemp.left = rectTemp.right - GetSystemMetrics(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)
+        {
+            InflateRect (&rect, -1, -1);
+            FillRect(hdc, &rect, GetSysColorBrush(COLOR_MENUHILIGHT));
+            InflateRect (&rect, 1, 1);
+            FrameRect(hdc, &rect, GetSysColorBrush(COLOR_HIGHLIGHT));
+        }
+        else
+        {
+            if(menuBar)
+                DrawEdge(hdc, &rect, BDR_SUNKENOUTER, BF_RECT);
+            else
+                FillRect(hdc, &rect, GetSysColorBrush(COLOR_HIGHLIGHT));
+        }
+    }
+    else
+        FillRect( hdc, &rect, GetSysColorBrush(bkgnd) );
+
+    SetBkMode( hdc, TRANSPARENT );
 
-      DrawTextW(Dc, Text, i, &Rect, uFormat);
+    /* vertical separator */
+    if (!menuBar && (lpitem->fType & MF_MENUBARBREAK))
+    {
+        HPEN oldPen;
+        RECT rc = rect;
+
+        rc.left -= 3;
+        rc.top = 3;
+        rc.bottom = Height - 3;
+        if (flat_menu)
+        {
+            oldPen = SelectObject( hdc, GetStockObject(DC_PEN) );
+            SetDCPenColor(hdc, GetSysColor(COLOR_BTNSHADOW));
+            MoveToEx( hdc, rc.left, rc.top, NULL );
+            LineTo( hdc, rc.left, rc.bottom );
+            SelectObject( hdc, oldPen );
+        }
+        else
+            DrawEdge (hdc, &rc, EDGE_ETCHED, BF_LEFT);
+    }
+
+    /* horizontal separator */
+    if (lpitem->fType & MF_SEPARATOR)
+    {
+        HPEN oldPen;
+        RECT rc = rect;
 
-      /* paint the shortcut text */
-      if (! MenuBar && L'\0' != Text[i])  /* There's a tab or flush-right char */
+        rc.left++;
+        rc.right--;
+        rc.top += SEPARATOR_HEIGHT / 2;
+        if (flat_menu)
         {
-          if (L'\t' == Text[i])
+            oldPen = SelectObject( hdc, GetStockObject(DC_PEN) );
+            SetDCPenColor( hdc, GetSysColor(COLOR_BTNSHADOW));
+            MoveToEx( hdc, rc.left, rc.top, NULL );
+            LineTo( hdc, rc.right, rc.top );
+            SelectObject( 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, GetStockObject(BLACK_BRUSH));
+    SelectObject(hdc, GetStockObject(DC_PEN));
+    SetDCPenColor(hdc, GetSysColor(COLOR_WINDOWFRAME));
+    MoveToEx(hdc, rect.left, (rect.top + rect.bottom) / 2, NULL);
+    LineTo(hdc, rect.right, (rect.top + rect.bottom) / 2);
+#endif
+
+    if (!menuBar)
+    {
+        HBITMAP bm;
+        INT y = rect.top + rect.bottom;
+        RECT rc = rect;
+        int checked = FALSE;
+        UINT check_bitmap_width = GetSystemMetrics( SM_CXMENUCHECK );
+        UINT check_bitmap_height = GetSystemMetrics( SM_CYMENUCHECK );
+        /* Draw the check mark
+         *
+         * FIXME:
+         * Custom checkmark bitmaps are monochrome but not always 1bpp.
+         */
+        if( !(MenuInfo->dwStyle & MNS_NOCHECK)) {
+            bm = (lpitem->fState & MF_CHECKED) ? lpitem->hbmpChecked : 
+                lpitem->hbmpUnchecked;
+            if (bm)  /* we have a custom bitmap */
             {
-              Rect.left = Item->XTab;
-              uFormat = DT_LEFT | DT_VCENTER | DT_SINGLELINE;
+                HDC hdcMem = CreateCompatibleDC( hdc );
+
+                SelectObject( hdcMem, bm );
+                BitBlt( hdc, rc.left, (y - check_bitmap_height) / 2,
+                        check_bitmap_width, check_bitmap_height,
+                        hdcMem, 0, 0, SRCCOPY );
+                DeleteDC( hdcMem );
+                checked = TRUE;
             }
-          else
+            else if (lpitem->fState & MF_CHECKED) /* standard bitmaps */
+            {
+                RECT r;
+                CopyRect(&r, &rect);
+                r.right = r.left + GetSystemMetrics(SM_CXMENUCHECK);
+                DrawFrameControl( hdc, &r, DFC_MENU,
+                                 (lpitem->fType & MFT_RADIOCHECK) ?
+                                 DFCS_MENUBULLET : DFCS_MENUCHECK);
+                checked = TRUE;
+            }
+        }
+        if ( lpitem->hbmpItem )
+        {
+            RECT bmpRect;
+            CopyRect(&bmpRect, &rect);
+            if (!(MenuInfo->dwStyle & MNS_CHECKORBMP) && !(MenuInfo->dwStyle & MNS_NOCHECK))
+                bmpRect.left += check_bitmap_width + 2;
+            if (!(checked && (MenuInfo->dwStyle & MNS_CHECKORBMP)))
             {
-              Rect.right = Item->XTab;
-              uFormat = DT_RIGHT | DT_VCENTER | DT_SINGLELINE;
+                bmpRect.right = bmpRect.left + MenuInfo->maxBmpSize.cx;
+                MenuDrawBitmapItem(hdc, lpitem, &bmpRect, MenuInfo->Self, WndOwner, odaction, menuBar);
             }
+        }
+        /* Draw the popup-menu arrow */
+        if (lpitem->fType & MF_POPUP)
+        {
+            RECT rectTemp;
+            CopyRect(&rectTemp, &rect);
+            rectTemp.left = rectTemp.right - GetSystemMetrics(SM_CXMENUCHECK);
+            DrawFrameControl(hdc, &rectTemp, DFC_MENU, DFCS_MENUARROW);
+        }
+        rect.left += 4;
+        if( !(MenuInfo->dwStyle & MNS_NOCHECK))
+            rect.left += check_bitmap_width;
+        rect.right -= check_bitmap_width;
+    }
+    else if( lpitem->hbmpItem)
+    { /* Draw the bitmap */
+        MenuDrawBitmapItem(hdc, lpitem, &rect, MenuInfo->Self, WndOwner, odaction, menuBar);
+    }
+
+    /* process text if present */
+    if (lpitem->Text)
+    {
+        register int i = 0;
+        HFONT hfontOld = 0;
+
+        UINT uFormat = menuBar ? DT_CENTER | DT_VCENTER | DT_SINGLELINE
+                       : DT_LEFT | DT_VCENTER | DT_SINGLELINE;
 
-          if (0 != (Item->fState & MF_GRAYED))
+        if(MenuInfo->dwStyle & MNS_CHECKORBMP)
+             rect.left += max(0, MenuInfo->maxBmpSize.cx - GetSystemMetrics(SM_CXMENUCHECK));
+        else
+             rect.left += MenuInfo->maxBmpSize.cx;
+
+        if ( lpitem->fState & MFS_DEFAULT )
+        {
+            hfontOld = SelectObject(hdc, hMenuFontBold);
+        }
+
+        if (menuBar) {
+            rect.left += MENU_BAR_ITEMS_SPACE / 2;
+            rect.right -= MENU_BAR_ITEMS_SPACE / 2;
+        }
+
+        Text = (PWCHAR) lpitem->dwTypeData;
+        if(Text)
+        {
+            for (i = 0; L'\0' != Text[i]; i++)
+                if (Text[i] == L'\t' || Text[i] == L'\b')
+                    break;
+        }
+
+        if(lpitem->fState & MF_GRAYED)
+        {
+            if (!(lpitem->fState & MF_HILITE) )
             {
-              if (0 == (Item->fState & MF_HILITE))
-                {
-                  ++Rect.left; ++Rect.top; ++Rect.right; ++Rect.bottom;
-                  SetTextColor(Dc, RGB(0xff, 0xff, 0xff));
-                  DrawTextW(Dc, Text + i + 1, -1, &Rect, uFormat);
-                  --Rect.left; --Rect.top; --Rect.right; --Rect.bottom;
-                }
-              SetTextColor(Dc, RGB(0x80, 0x80, 0x80));
-           }
-          DrawTextW(Dc, Text + i + 1, -1, &Rect, uFormat);
+                ++rect.left; ++rect.top; ++rect.right; ++rect.bottom;
+                SetTextColor(hdc, RGB(0xff, 0xff, 0xff));
+                DrawTextW( hdc, Text, i, &rect, uFormat );
+                --rect.left; --rect.top; --rect.right; --rect.bottom;
+               }
+            SetTextColor(hdc, RGB(0x80, 0x80, 0x80));
         }
 
-      if (NULL != FontOld)
+        DrawTextW( hdc, Text, i, &rect, uFormat);
+
+        /* paint the shortcut text */
+        if (!menuBar && L'\0' != Text[i])  /* There's a tab or flush-right char */
         {
-          SelectObject(Dc, FontOld);
+            if (L'\t' == Text[i])
+            {
+                rect.left = lpitem->XTab;
+                uFormat = DT_LEFT | DT_VCENTER | DT_SINGLELINE;
+            }
+            else
+            {
+                rect.right = lpitem->XTab;
+                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;
+                    SetTextColor(hdc, RGB(0xff, 0xff, 0xff));
+                    DrawTextW( hdc, Text + i + 1, -1, &rect, uFormat);
+                    --rect.left; --rect.top; --rect.right; --rect.bottom;
+                }
+                SetTextColor(hdc, RGB(0x80, 0x80, 0x80));
+               }
+          DrawTextW( hdc, Text + i + 1, -1, &rect, uFormat );
         }
-  }
+
+        if (hfontOld)
+          SelectObject (hdc, hfontOld);
+    }
 }
 
 /***********************************************************************
@@ -878,65 +1313,263 @@ MenuDrawMenuItem(HWND Wnd, PROSMENUINFO MenuInfo, HWND WndOwner, HDC Dc,
  *
  * Paint a popup menu.
  */
-static void FASTCALL
-MenuDrawPopupMenu(HWND Wnd, HDC Dc, HMENU Menu)
+static void FASTCALL MenuDrawPopupMenu(HWND hwnd, HDC hdc, HMENU hmenu )
 {
-  HBRUSH PrevBrush = NULL;
-  HPEN PrevPen;
-  RECT Rect;
-  ROSMENUINFO MenuInfo;
-  ROSMENUITEMINFO ItemInfo;
-  UINT u;
+    HBRUSH hPrevBrush = 0;
+    RECT rect;
 
-  TRACE("wnd=%x dc=%x menu=%x\n", Wnd, Dc, Menu);
+    TRACE("wnd=%p dc=%p menu=%p\n", hwnd, hdc, hmenu);
 
-  GetClientRect(Wnd, &Rect);
+    GetClientRect( hwnd, &rect );
 
-  if (NULL != (PrevBrush = SelectObject(Dc, GetSysColorBrush(COLOR_MENU)))
-      && NULL != SelectObject(Dc, hMenuFont))
+    if((hPrevBrush = SelectObject( hdc, GetSysColorBrush(COLOR_MENU) ))
+        && (SelectObject( hdc, hMenuFont)))
     {
-      Rectangle(Dc, Rect.left, Rect.top, Rect.right, Rect.bottom);
+        HPEN hPrevPen;
 
-      PrevPen = SelectObject(Dc, GetStockObject(NULL_PEN));
-      if (NULL != PrevPen)
+        Rectangle( hdc, rect.left, rect.top, rect.right, rect.bottom );
+
+        hPrevPen = SelectObject( hdc, GetStockObject( NULL_PEN ) );
+        if ( hPrevPen )
         {
-          BOOL flat_menu = FALSE;
+            BOOL flat_menu = FALSE;
+            ROSMENUINFO MenuInfo;
+            ROSMENUITEMINFO ItemInfo;
 
-          SystemParametersInfoW (SPI_GETFLATMENU, 0, &flat_menu, 0);
-          if (flat_menu)
-             FrameRect(Dc, &Rect, GetSysColorBrush(COLOR_BTNSHADOW));
-          else
-             DrawEdge(Dc, &Rect, EDGE_RAISED, BF_RECT);
+            SystemParametersInfoW (SPI_GETFLATMENU, 0, &flat_menu, 0);
+            if (flat_menu)
+               FrameRect(hdc, &rect, GetSysColorBrush(COLOR_BTNSHADOW));
+            else
+               DrawEdge (hdc, &rect, EDGE_RAISED, BF_RECT);
+
+            /* draw menu items */
+            if (MenuGetRosMenuInfo(&MenuInfo, hmenu) && MenuInfo.MenuItemCount)
+            {
+                UINT u;
+                
+                               MenuInitRosMenuItemInfo(&ItemInfo);
+
+                for (u = 0; u < MenuInfo.MenuItemCount; u++)
+                {
+                    if (MenuGetRosMenuItemInfo(MenuInfo.Self, u, &ItemInfo))
+                    {
+                        MenuDrawMenuItem(hwnd, &MenuInfo, MenuInfo.WndOwner, hdc, &ItemInfo,
+                        MenuInfo.Height, FALSE, ODA_DRAWENTIRE);
+                    }
+                }
+
+                MenuCleanupRosMenuItemInfo(&ItemInfo);
+            }
+         } else
+         {
+             SelectObject( hdc, hPrevBrush );
+         }
+    }
+}
+
+/***********************************************************************
+ *           MenuDrawMenuBar
+ *
+ * Paint a menu bar. Returns the height of the menu bar.
+ * called from [windows/nonclient.c]
+ */
+UINT MenuDrawMenuBar( HDC hDC, LPRECT lprect, HWND hwnd,
+                         BOOL suppress_draw)
+{
+    ROSMENUINFO lppop;
+    HFONT hfontOld = 0;
+    HMENU hMenu = GetMenu(hwnd);
+
+    if (! MenuGetRosMenuInfo(&lppop, hMenu) || lprect == NULL)
+    {
+        return GetSystemMetrics(SM_CYMENU);
+    }
+
+    if (suppress_draw)
+    {
+        hfontOld = SelectObject(hDC, hMenuFont);
+
+        MenuMenuBarCalcSize(hDC, lprect, &lppop, hwnd);
+
+        lprect->bottom = lprect->top + lppop.Height;
+
+        if (hfontOld) SelectObject( hDC, hfontOld);
+        return lppop.Height;
+    }
+       else
+        return DrawMenuBarTemp(hwnd, hDC, lprect, hMenu, NULL);
+}
+
+/***********************************************************************
+ *           MenuShowPopup
+ *
+ * Display a popup menu.
+ */
+static BOOL FASTCALL MenuShowPopup(HWND hwndOwner, HMENU hmenu, UINT id, UINT flags,
+                              INT x, INT y, INT xanchor, INT yanchor )
+{
+    ROSMENUINFO MenuInfo;
+    ROSMENUITEMINFO ItemInfo;
+    UINT width, height;
+    POINT pt;
+    HMONITOR monitor;
+    MONITORINFO info;
+
+    TRACE("owner=%p hmenu=%p id=0x%04x x=0x%04x y=0x%04x xa=0x%04x ya=0x%04x\n",
+          hwndOwner, hmenu, id, x, y, xanchor, yanchor);
+
+    if (! MenuGetRosMenuInfo(&MenuInfo, hmenu)) return FALSE;
+    if (MenuInfo.FocusedItem != NO_SELECTED_ITEM)
+    {
+        MenuInitRosMenuItemInfo(&ItemInfo);
+        if (MenuGetRosMenuItemInfo(MenuInfo.Self, MenuInfo.FocusedItem, &ItemInfo))
+        {
+            ItemInfo.fMask |= MIIM_STATE;
+            ItemInfo.fState &= ~(MF_HILITE|MF_MOUSESELECT);
+            MenuSetRosMenuItemInfo(MenuInfo.Self, MenuInfo.FocusedItem, &ItemInfo);
+        }
+        MenuCleanupRosMenuItemInfo(&ItemInfo);
+        MenuInfo.FocusedItem = NO_SELECTED_ITEM;
+    }
+
+    /* store the owner for DrawItem */
+    MenuInfo.WndOwner = hwndOwner;
+    MenuSetRosMenuInfo(&MenuInfo);
+
+    MenuPopupMenuCalcSize(&MenuInfo, hwndOwner);
+
+    /* adjust popup menu pos so that it fits within the desktop */
+
+    width = MenuInfo.Width + GetSystemMetrics(SM_CXBORDER);
+    height = MenuInfo.Height + GetSystemMetrics(SM_CYBORDER);
+
+    /* FIXME: should use item rect */
+    pt.x = x;
+    pt.y = y;
+    monitor = MonitorFromPoint( pt, MONITOR_DEFAULTTONEAREST );
+    info.cbSize = sizeof(info);
+    GetMonitorInfoW( monitor, &info );
+
+    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;
 
-          /* draw menu items */
+    if( x + width > info.rcWork.right)
+    {
+        if( xanchor && x >= width - xanchor )
+            x -= width - xanchor;
+
+        if( x + width > info.rcWork.right)
+            x = info.rcWork.right - width;
+    }
+    if( x < info.rcWork.left ) x = info.rcWork.left;
+
+    if( y + height > info.rcWork.bottom)
+    {
+        if( yanchor && y >= height + yanchor )
+            y -= height + yanchor;
+
+        if( y + height > info.rcWork.bottom)
+            y = info.rcWork.bottom - height;
+    }
+    if( y < info.rcWork.top ) y = info.rcWork.top;
+
+    /* NOTE: In Windows, top menu popup is not owned. */
+    MenuInfo.Wnd = CreateWindowExW( 0, POPUPMENU_CLASS_ATOMW, NULL,
+                                  WS_POPUP, x, y, width, height,
+                                  hwndOwner, 0, (HINSTANCE) GetWindowLongPtrW(hwndOwner, GWLP_HINSTANCE),
+                                 (LPVOID) MenuInfo.Self);
+    if ( !MenuInfo.Wnd || ! MenuSetRosMenuInfo(&MenuInfo)) return FALSE;
+    if (!TopPopup) {
+        TopPopup = MenuInfo.Wnd;
+    }
+
+    /* Display the window */
+
+    SetWindowPos( MenuInfo.Wnd, HWND_TOPMOST, 0, 0, 0, 0,
+                  SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
+    UpdateWindow( MenuInfo.Wnd );
+    return TRUE;
+}
+
+LRESULT WINAPI
+PopupMenuWndProcA(HWND Wnd, UINT Message, WPARAM wParam, LPARAM lParam)
+{
+  TRACE("YES! hwnd=%x msg=0x%04x wp=0x%04lx lp=0x%08lx\n", Wnd, Message, wParam, lParam);
+
+  switch(Message)
+    {
+    case WM_CREATE:
+      {
+        CREATESTRUCTA *cs = (CREATESTRUCTA *) lParam;
+        SetWindowLongPtrA(Wnd, 0, (LONG) cs->lpCreateParams);
+        return 0;
+      }
+
+    case WM_MOUSEACTIVATE:  /* We don't want to be activated */
+      return MA_NOACTIVATE;
+
+    case WM_PAINT:
+      {
+        PAINTSTRUCT ps;
+        BeginPaint(Wnd, &ps);
+        MenuDrawPopupMenu(Wnd, ps.hdc, (HMENU)GetWindowLongPtrA(Wnd, 0));
+        EndPaint(Wnd, &ps);
+        return 0;
+      }
+
+    case WM_PRINTCLIENT:
+      {
+        MenuDrawPopupMenu( Wnd, (HDC)wParam,
+                                (HMENU)GetWindowLongPtrW( Wnd, 0 ) );
+        return 0;
+      }
+
+    case WM_ERASEBKGND:
+      return 1;
+
+    case WM_DESTROY:
+      /* zero out global pointer in case resident popup window was destroyed. */
+      if (Wnd == TopPopup)
+        {
+          TopPopup = NULL;
+        }
+      break;
+
+    case WM_SHOWWINDOW:
+      if (0 != wParam)
+        {
+          if (0 == GetWindowLongPtrA(Wnd, 0))
+            {
+              OutputDebugStringA("no menu to display\n");
+            }
+        }
+      else
+        {
+          SetWindowLongPtrA(Wnd, 0, 0);
+        }
+      break;
 
-          if (MenuGetRosMenuInfo(&MenuInfo, Menu) && 0 != MenuInfo.MenuItemCount)
-            {
-              MenuInitRosMenuItemInfo(&ItemInfo);
+    case MM_SETMENUHANDLE:
+      SetWindowLongPtrA(Wnd, 0, wParam);
+      break;
 
-              for (u = 0; u < MenuInfo.MenuItemCount; u++)
-                {
-                  if (MenuGetRosMenuItemInfo(MenuInfo.Self, u, &ItemInfo))
-                    {
-                      MenuDrawMenuItem(Wnd, &MenuInfo, MenuInfo.WndOwner, Dc, &ItemInfo,
-                                      MenuInfo.Height, FALSE, ODA_DRAWENTIRE);
-                    }
-                }
+    case MM_GETMENUHANDLE:
+    case MN_GETHMENU: 
+      return GetWindowLongPtrA(Wnd, 0);
 
-             MenuCleanupRosMenuItemInfo(&ItemInfo);
-           }
-       }
-      else
-        {
-          SelectObject(Dc, PrevBrush);
-       }
+    default:
+      return DefWindowProcA(Wnd, Message, wParam, lParam);
     }
+  return 0;
 }
 
-static LRESULT WINAPI
+LRESULT WINAPI
 PopupMenuWndProcW(HWND Wnd, UINT Message, WPARAM wParam, LPARAM lParam)
 {
-  TRACE("hwnd=%x msg=0x%04x wp=0x%04x lp=0x%08lx\n", Wnd, Message, wParam, lParam);
+  TRACE("hwnd=%x msg=0x%04x wp=0x%04lx lp=0x%08lx\n", Wnd, Message, wParam, lParam);
 
   switch(Message)
     {
@@ -959,6 +1592,13 @@ PopupMenuWndProcW(HWND Wnd, UINT Message, WPARAM wParam, LPARAM lParam)
         return 0;
       }
 
+    case WM_PRINTCLIENT:
+      {
+         MenuDrawPopupMenu( Wnd, (HDC)wParam,
+                                (HMENU)GetWindowLongPtrW( Wnd, 0 ) );
+         return 0;
+      }
+
     case WM_ERASEBKGND:
       return 1;
 
@@ -989,6 +1629,7 @@ PopupMenuWndProcW(HWND Wnd, UINT Message, WPARAM wParam, LPARAM lParam)
       break;
 
     case MM_GETMENUHANDLE:
+    case MN_GETHMENU:
       return GetWindowLongPtrW(Wnd, 0);
 
     default:
@@ -1045,6 +1686,7 @@ static LPCSTR MENUEX_ParseResource( LPCSTR res, HMENU hMenu)
          }
          mii.fMask |= MIIM_SUBMENU;
          mii.fType |= MF_POPUP;
+         mii.wID = (UINT) mii.hSubMenu;
        }
       else if(!*mii.dwTypeData && !(mii.fType & MF_SEPARATOR))
        {
@@ -1104,6 +1746,23 @@ static LPCSTR MENU_ParseResource( LPCSTR res, HMENU hMenu, BOOL unicode )
     }
     else  /* Not a popup */
     {
+      if(!unicode)
+      {
+        if (*str == 0)
+          flags = MF_SEPARATOR;
+      }
+      else
+      {
+        if (*(LPCWSTR)str == 0)
+          flags = MF_SEPARATOR;
+      }
+
+      if (flags & MF_SEPARATOR)
+      {
+        if (!(flags & (MF_GRAYED | MF_DISABLED)))
+          flags |= MF_GRAYED | MF_DISABLED;
+      }
+
       if(!unicode)
         AppendMenuA(hMenu, flags, id, *str ? str : NULL);
       else
@@ -1116,496 +1775,87 @@ static LPCSTR MENU_ParseResource( LPCSTR res, HMENU hMenu, BOOL unicode )
 }
 
 
-NTSTATUS STDCALL
+NTSTATUS WINAPI
 User32LoadSysMenuTemplateForKernel(PVOID Arguments, ULONG ArgumentLength)
 {
-  LRESULT Result;
-  Result = (LRESULT)LoadMenuW(User32Instance, L"SYSMENU");
-  return(ZwCallbackReturn(&Result, sizeof(LRESULT), STATUS_SUCCESS));
-}
-
-
-BOOL
-MenuInit(VOID)
-{
-  NONCLIENTMETRICSW ncm;
-
-  /* get the menu font */
-  if(!hMenuFont || !hMenuFontBold)
-  {
-    ncm.cbSize = sizeof(ncm);
-    if(!SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0))
-    {
-      DbgPrint("MenuInit(): SystemParametersInfoW(SPI_GETNONCLIENTMETRICS) failed!\n");
-      return FALSE;
-    }
-
-    hMenuFont = CreateFontIndirectW(&ncm.lfMenuFont);
-    if(hMenuFont == NULL)
-    {
-      DbgPrint("MenuInit(): CreateFontIndirectW(hMenuFont) failed!\n");
-      return FALSE;
-    }
-
-    ncm.lfMenuFont.lfWeight = max(ncm.lfMenuFont.lfWeight + 300, 1000);
-    hMenuFontBold = CreateFontIndirectW(&ncm.lfMenuFont);
-    if(hMenuFontBold == NULL)
-    {
-      DbgPrint("MenuInit(): CreateFontIndirectW(hMenuFontBold) failed!\n");
-      DeleteObject(hMenuFont);
-      hMenuFont = NULL;
-      return FALSE;
-    }
-  }
-
-  return TRUE;
-}
-
-
-VOID
-MenuCleanup(VOID)
-{
-  if (hMenuFont)
-  {
-    DeleteObject(hMenuFont);
-    hMenuFont = NULL;
-  }
-
-  if (hMenuFontBold)
-  {
-    DeleteObject(hMenuFontBold);
-    hMenuFontBold = NULL;
-  }
-}
-
-
-
-/***********************************************************************
- *           MenuCalcItemSize
- *
- * Calculate the size of the menu item and store it in ItemInfo->rect.
- */
-static void FASTCALL
-MenuCalcItemSize(HDC Dc, PROSMENUITEMINFO ItemInfo, PROSMENUINFO MenuInfo, HWND WndOwner,
-                 INT OrgX, INT OrgY, BOOL MenuBar)
-{
-  PWCHAR p;
-  INT itemheight = 0;
-  UINT CheckBitmapWidth = GetSystemMetrics(SM_CXMENUCHECK);
-
-  TRACE("dc=%x owner=%x (%d,%d)\n", Dc, WndOwner, OrgX, OrgY);
-
-  MenuCharSize.cx = GdiGetCharDimensions( Dc, NULL, &MenuCharSize.cy );
-
-  SetRect(&ItemInfo->Rect, OrgX, OrgY, OrgX, OrgY);
-
-  if (0 != (ItemInfo->fType & MF_OWNERDRAW))
-    {
-      /*
-       ** Experimentation under Windows reveals that an owner-drawn
-       ** menu is expected to return the size of the content part of
-       ** the menu item, not including the checkmark nor the submenu
-       ** arrow.  Windows adds those values itself and returns the
-       ** enlarged rectangle on subsequent WM_DRAWITEM messages.
-       */
-      MEASUREITEMSTRUCT mis;
-      mis.CtlType    = ODT_MENU;
-      mis.CtlID      = 0;
-      mis.itemID     = ItemInfo->wID;
-      mis.itemData   = (DWORD)ItemInfo->dwItemData;
-      mis.itemHeight = HIWORD( GetDialogBaseUnits());
-      mis.itemWidth  = 0;
-      SendMessageW(WndOwner, 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.
-    */
-      ItemInfo->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 */
-            ItemInfo->Rect.bottom += GetSystemMetrics(SM_CYMENUSIZE);
-        }
-      else
-        {
-          ItemInfo->Rect.bottom += mis.itemHeight;
-        }
-
-      TRACE("id=%04x size=%dx%d\n", ItemInfo->wID, mis.itemWidth, mis.itemHeight);
-      return;
-    }
-
-  if (0 != (ItemInfo->fType & MF_SEPARATOR))
-    {
-      ItemInfo->Rect.bottom += SEPARATOR_HEIGHT;
-      if( !MenuBar)
-            ItemInfo->Rect.right += ArrowBitmapWidth +  MenuCharSize.cx;
-      return;
-    }
-  
-  ItemInfo->XTab = 0;
-  
-  if (ItemInfo->hbmpItem)
-  {
-      SIZE Size;
-
-      if (!MenuBar)  /* hbmpItem */
-      {
-         MenuGetBitmapItemSize(ItemInfo, &Size, WndOwner );
-      /* Keep the size of the bitmap in callback mode to be able
-       * to draw it correctly */
-         ItemInfo->Rect.right = ItemInfo->Rect.left + Size.cx;
-         if (MenuInfo->maxBmpSize.cx < abs(Size.cx) +  MENU_ITEM_HBMP_SPACE ||
-             MenuInfo->maxBmpSize.cy < abs(Size.cy))
-         {
-             MenuInfo->maxBmpSize.cx = abs(Size.cx) + MENU_ITEM_HBMP_SPACE;
-             MenuInfo->maxBmpSize.cy = abs(Size.cy);
-         }
-         MenuSetRosMenuInfo(MenuInfo);
-         ItemInfo->Rect.right += Size.cx + 2;
-         itemheight = Size.cy + 2;
-
-         if( !(MenuInfo->dwStyle & MNS_NOCHECK))
-           ItemInfo->Rect.right += 2 * CheckBitmapWidth;
-         ItemInfo->Rect.right += 4 + MenuCharSize.cx;
-         ItemInfo->XTab = ItemInfo->Rect.right;
-         ItemInfo->Rect.right += ArrowBitmapWidth;
-      }
-      else /* hbmpItem & MenuBar */
-      {
-        MenuGetBitmapItemSize(ItemInfo, &Size, WndOwner );
-        ItemInfo->Rect.right  += Size.cx;
-          if( ItemInfo->Text) ItemInfo->Rect.right  += 2;
-          itemheight = Size.cy;
-
-      /* Special case: Minimize button doesn't have a space behind it. */
-        if (ItemInfo->hbmpItem == (HBITMAP)HBMMENU_MBAR_MINIMIZE ||
-            ItemInfo->hbmpItem == (HBITMAP)HBMMENU_MBAR_MINIMIZE_D)
-        ItemInfo->Rect.right -= 1;
-      }
-  }
-  else if (!MenuBar)
-  {
-      if( !(MenuInfo->dwStyle & MNS_NOCHECK))
-           ItemInfo->Rect.right += CheckBitmapWidth;
-      ItemInfo->Rect.right += 4 + MenuCharSize.cx;
-      ItemInfo->XTab = ItemInfo->Rect.right;
-      ItemInfo->Rect.right += ArrowBitmapWidth;
-  }
-
-  /* it must be a text item - unless it's the system menu */
-  if (0 == (ItemInfo->fType & MF_SYSMENU) && ItemInfo->Text)
-  {
-     HFONT hfontOld = NULL;
-     RECT rc = ItemInfo->Rect;
-     LONG txtheight, txtwidth;
-
-     if ( ItemInfo->fState & MFS_DEFAULT )
-     {
-        hfontOld = SelectObject( Dc, hMenuFontBold );
-     }
-     if (MenuBar) 
-     {
-        txtheight = DrawTextW( Dc, ItemInfo->dwTypeData, -1, &rc,
-                                                  DT_SINGLELINE|DT_CALCRECT); 
-        ItemInfo->Rect.right  += rc.right - rc.left;
-        itemheight = max( max( itemheight, txtheight),
-                                           GetSystemMetrics( SM_CYMENU) - 1);
-        ItemInfo->Rect.right +=  2 * MenuCharSize.cx;
-     } 
-     else 
-     {
-        if ((p = strchrW( ItemInfo->dwTypeData, '\t' )) != NULL)
-        {
-          RECT tmprc = rc;
-          LONG tmpheight;
-          int n = (int)( p - ItemInfo->dwTypeData);
-         /* Item contains a tab (only meaningful in popup menus) */
-         /* get text size before the tab */
-          txtheight = DrawTextW( Dc, ItemInfo->dwTypeData, 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( Dc, p, -1, &tmprc, DT_SINGLELINE|DT_CALCRECT);
-          ItemInfo->XTab += txtwidth;
-          txtheight = max( txtheight, tmpheight);
-          txtwidth += MenuCharSize.cx + /* space for the tab */
-          tmprc.right - tmprc.left; /* space for the short cut */
-        } 
-        else 
-        {
-          txtheight = DrawTextW( Dc, ItemInfo->dwTypeData, -1, &rc,
-                                                   DT_SINGLELINE|DT_CALCRECT);
-          txtwidth = rc.right - rc.left;
-          ItemInfo->XTab += txtwidth;
-        }
-        ItemInfo->Rect.right  += 2 + txtwidth;
-        itemheight = max( itemheight, max( txtheight + 2, MenuCharSize.cy + 4));
-     }
-     if (hfontOld) SelectObject (Dc, hfontOld);
-  } 
-  else if( MenuBar)
-  {
-     itemheight = max( itemheight, GetSystemMetrics(SM_CYMENU)-1);
-  }
-  ItemInfo->Rect.bottom += itemheight;
-  TRACE("(%ld,%ld)-(%ld,%ld)\n", ItemInfo->Rect.left, ItemInfo->Rect.top, ItemInfo->Rect.right, ItemInfo->Rect.bottom);
-}
-
-/***********************************************************************
- *           MenuPopupMenuCalcSize
- *
- * Calculate the size of a popup menu.
- */
-static void FASTCALL
-MenuPopupMenuCalcSize(PROSMENUINFO MenuInfo, HWND WndOwner)
-{
-  ROSMENUITEMINFO ItemInfo;
-  HDC Dc;
-  int Start, i;
-  int OrgX, OrgY, MaxX, MaxTab, MaxTabWidth;
-
-  MenuInfo->Width = MenuInfo->Height = 0;
-  if (0 == MenuInfo->MenuItemCount)
-    {
-      MenuSetRosMenuInfo(MenuInfo);
-      return;
-    }
-
-  Dc = GetDC(NULL);
-  SelectObject(Dc, hMenuFont);
-
-  Start = 0;
-  MaxX = 2 + 1;
-
-  MenuInfo->maxBmpSize.cx = 0;
-  MenuInfo->maxBmpSize.cy = 0;
-
-  MenuInitRosMenuItemInfo(&ItemInfo);  
-  while (Start < MenuInfo->MenuItemCount)
-    {
-      OrgX = MaxX;
-      OrgY = 2;
-
-      MaxTab = MaxTabWidth = 0;
-
-      /* Parse items until column break or end of menu */
-      for (i = Start; i < MenuInfo->MenuItemCount; i++)
-       {
-          if (! MenuGetRosMenuItemInfo(MenuInfo->Self, i, &ItemInfo))
-            {
-              MenuCleanupRosMenuItemInfo(&ItemInfo);
-              MenuSetRosMenuInfo(MenuInfo);
-              return;
-            }
-          if (i != Start &&
-              0 != (ItemInfo.fType & (MF_MENUBREAK | MF_MENUBARBREAK)))
-            {
-              break;
-            }
-          MenuCalcItemSize(Dc, &ItemInfo, MenuInfo, WndOwner, OrgX, OrgY, FALSE);
-          if (! MenuSetRosMenuItemInfo(MenuInfo->Self, i, &ItemInfo))
-            {
-              MenuCleanupRosMenuItemInfo(&ItemInfo);
-              MenuSetRosMenuInfo(MenuInfo);
-              return;
-            }
-// Not sure here,, The patch from wine removes this.
-//          if (0 != (ItemInfo.fType & MF_MENUBARBREAK))
-//            {
-//              OrgX++;
-//            }
-          MaxX = max(MaxX, ItemInfo.Rect.right);
-          OrgY = ItemInfo.Rect.bottom;
-          if ((ItemInfo.Text) && 0 != ItemInfo.XTab)
-           {
-              MaxTab = max(MaxTab, ItemInfo.XTab);
-              MaxTabWidth = max(MaxTabWidth, ItemInfo.Rect.right - ItemInfo.XTab);
-            }
-        }
-
-      /* Finish the column (set all items to the largest width found) */
-      MaxX = max(MaxX, MaxTab + MaxTabWidth);
-      while (Start < i)
-        {
-          if (MenuGetRosMenuItemInfo(MenuInfo->Self, Start, &ItemInfo))
-            {
-              ItemInfo.Rect.right = MaxX;
-              if ((ItemInfo.Text) && 0 != ItemInfo.XTab)
-                {
-                  ItemInfo.XTab = MaxTab;
-                }
-              MenuSetRosMenuItemInfo(MenuInfo->Self, Start, &ItemInfo);
-            }
-          Start++;
-       }
-      MenuInfo->Height = max(MenuInfo->Height, OrgY);
-    }
-
-  MenuInfo->Width = MaxX;
+  HMENU hmenu = LoadMenuW(User32Instance, L"SYSMENU");
+  LRESULT Result = (LRESULT)hmenu;
+  MENUINFO menuinfo = {0};
+  MENUITEMINFOW info = {0};
+
+  // removing space for checkboxes from menu
+  menuinfo.cbSize = sizeof(menuinfo);
+  menuinfo.fMask = MIM_STYLE;
+  GetMenuInfo(hmenu, &menuinfo);
+  menuinfo.dwStyle |= MNS_NOCHECK;
+  SetMenuInfo(hmenu, &menuinfo);
+
+  // adding bitmaps to menu items
+  info.cbSize = sizeof(info);
+  info.fMask |= MIIM_BITMAP;
+  info.hbmpItem = HBMMENU_POPUP_MINIMIZE;
+  SetMenuItemInfoW(hmenu, SC_MINIMIZE, FALSE, &info);
+  info.hbmpItem = HBMMENU_POPUP_RESTORE;
+  SetMenuItemInfoW(hmenu, SC_RESTORE, FALSE, &info);
+  info.hbmpItem = HBMMENU_POPUP_MAXIMIZE;
+  SetMenuItemInfoW(hmenu, SC_MAXIMIZE, FALSE, &info);
+  info.hbmpItem = HBMMENU_POPUP_CLOSE;
+  SetMenuItemInfoW(hmenu, SC_CLOSE, FALSE, &info);
 
-  /* space for 3d border */
-  MenuInfo->Height += 2;
-  MenuInfo->Width += 2;
-
-  ReleaseDC(NULL, Dc);
-  MenuCleanupRosMenuItemInfo(&ItemInfo);
-  MenuSetRosMenuInfo(MenuInfo);
+  return(ZwCallbackReturn(&Result, sizeof(LRESULT), STATUS_SUCCESS));
 }
 
-/***********************************************************************
- *           MenuMenuBarCalcSize
- *
- * 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 FASTCALL
-MenuMenuBarCalcSize(HDC Dc, LPRECT Rect, PROSMENUINFO MenuInfo, HWND WndOwner)
-{
-  ROSMENUITEMINFO ItemInfo;
-  int Start, i, OrgX, OrgY, MaxY, HelpPos;
-
-  if (NULL == Rect || NULL == MenuInfo)
-    {
-      return;
-    }
-  if (0 == MenuInfo->MenuItemCount)
-    {
-      return;
-    }
-
-  TRACE("left=%ld top=%ld right=%ld bottom=%ld\n",
-         Rect->left, Rect->top, Rect->right, Rect->bottom);
-  MenuInfo->Width = Rect->right - Rect->left;
-  MenuInfo->Height = 0;
-  MaxY = Rect->top + 1;
-  Start = 0;
-  HelpPos = -1;
-
-  MenuInfo->maxBmpSize.cx = 0;
-  MenuInfo->maxBmpSize.cy = 0;
-
-  MenuInitRosMenuItemInfo(&ItemInfo);
-  while (Start < MenuInfo->MenuItemCount)
-    {
-      if (! MenuGetRosMenuItemInfo(MenuInfo->Self, Start, &ItemInfo))
-        {
-          MenuCleanupRosMenuItemInfo(&ItemInfo);
-          return;
-        }
-      OrgX = Rect->left;
-      OrgY = MaxY;
-
-      /* Parse items until line break or end of menu */
-      for (i = Start; i < MenuInfo->MenuItemCount; i++)
-       {
-          if (-1 == HelpPos && 0 != (ItemInfo.fType & MF_RIGHTJUSTIFY))
-            {
-              HelpPos = i;
-            }
-          if (i != Start &&
-              0 != (ItemInfo.fType & (MF_MENUBREAK | MF_MENUBARBREAK)))
-            {
-              break;
-            }
-
-          TRACE("calling MENU_CalcItemSize org=(%d, %d)\n", OrgX, OrgY);
-          MenuCalcItemSize(Dc, &ItemInfo, MenuInfo, WndOwner, OrgX, OrgY, TRUE);
-          if (! MenuSetRosMenuItemInfo(MenuInfo->Self, i, &ItemInfo))
-            {
-              MenuCleanupRosMenuItemInfo(&ItemInfo);
-              return;
-            }
-
-          if (ItemInfo.Rect.right > Rect->right)
-            {
-              if (i != Start)
-                {
-                  break;
-                }
-              else
-                {
-                  ItemInfo.Rect.right = Rect->right;
-                }
-            }
-          MaxY = max(MaxY, ItemInfo.Rect.bottom );
-          OrgX = ItemInfo.Rect.right;
-          if (i + 1 < MenuInfo->MenuItemCount)
-            {
-              if (! MenuGetRosMenuItemInfo(MenuInfo->Self, i + 1, &ItemInfo))
-                {
-                  MenuCleanupRosMenuItemInfo(&ItemInfo);
-                  return;
-                }
-            }
-       }
-
-/* 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
-      /* Finish the line (set all items to the largest height found) */
-      while (Start < i)
-        {
-          if (MenuGetRosMenuItemInfo(MenuInfo->Self, Start, &ItemInfo))
-            {
-              ItemInfo.Rect.bottom = MaxY;
-              MenuSetRosMenuItemInfo(MenuInfo->Self, Start, &ItemInfo);
-            }
-          Start++;
-        }
-#else
-     Start = i; /* This works! */
-#endif
+
+BOOL
+MenuInit(VOID)
+{
+  NONCLIENTMETRICSW ncm;
+
+  /* get the menu font */
+  if(!hMenuFont || !hMenuFontBold)
+  {
+    ncm.cbSize = sizeof(ncm);
+    if(!SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0))
+    {
+      DbgPrint("MenuInit(): SystemParametersInfoW(SPI_GETNONCLIENTMETRICS) failed!\n");
+      return FALSE;
     }
 
-  Rect->bottom = MaxY;
-  MenuInfo->Height = Rect->bottom - Rect->top;
-  MenuSetRosMenuInfo(MenuInfo);
+    hMenuFont = CreateFontIndirectW(&ncm.lfMenuFont);
+    if(hMenuFont == NULL)
+    {
+      DbgPrint("MenuInit(): CreateFontIndirectW(hMenuFont) failed!\n");
+      return FALSE;
+    }
 
-  if (-1 != HelpPos)
+    ncm.lfMenuFont.lfWeight = max(ncm.lfMenuFont.lfWeight + 300, 1000);
+    hMenuFontBold = CreateFontIndirectW(&ncm.lfMenuFont);
+    if(hMenuFontBold == NULL)
     {
-      /* Flush right all items between the MF_RIGHTJUSTIFY and */
-      /* the last item (if several lines, only move the last line) */
-      if (! MenuGetRosMenuItemInfo(MenuInfo->Self, MenuInfo->MenuItemCount - 1, &ItemInfo))
-        {
-          MenuCleanupRosMenuItemInfo(&ItemInfo);
-          return;
-        }
-      OrgY = ItemInfo.Rect.top;
-      OrgX = Rect->right;
-      for (i = MenuInfo->MenuItemCount - 1; HelpPos <= i; i--)
-        {
-          if (i < HelpPos)
-            {
-              break;                           /* done */
-            }
-          if (ItemInfo.Rect.top != OrgY)
-            {
-              break;                           /* Other line */
-            }
-          if (OrgX <= ItemInfo.Rect.right)
-            {
-              break;                           /* Too far right already */
-            }
-          ItemInfo.Rect.left += OrgX - ItemInfo.Rect.right;
-          ItemInfo.Rect.right = OrgX;
-          OrgX = ItemInfo.Rect.left;
-          MenuSetRosMenuItemInfo(MenuInfo->Self, i, &ItemInfo);
-          if (HelpPos + 1 <= i &&
-              ! MenuGetRosMenuItemInfo(MenuInfo->Self, i - 1, &ItemInfo))
-            {
-              MenuCleanupRosMenuItemInfo(&ItemInfo);
-              return;
-            }
-        }
+      DbgPrint("MenuInit(): CreateFontIndirectW(hMenuFontBold) failed!\n");
+      DeleteObject(hMenuFont);
+      hMenuFont = NULL;
+      return FALSE;
     }
+  }
 
-  MenuCleanupRosMenuItemInfo(&ItemInfo);
+  return TRUE;
+}
+
+VOID
+MenuCleanup(VOID)
+{
+  if (hMenuFont)
+  {
+    DeleteObject(hMenuFont);
+    hMenuFont = NULL;
+  }
+
+  if (hMenuFontBold)
+  {
+    DeleteObject(hMenuFontBold);
+    hMenuFontBold = NULL;
+  }
 }
 
 /***********************************************************************
@@ -1627,9 +1877,9 @@ DrawMenuBarTemp(HWND Wnd, HDC DC, LPRECT Rect, HMENU Menu, HFONT Font)
   UINT i;
   HFONT FontOld = NULL;
   BOOL flat_menu = FALSE;
-  
+
   SystemParametersInfoW (SPI_GETFLATMENU, 0, &flat_menu, 0);
-  
+
   if (NULL == Menu)
     {
       Menu = GetMenu(Wnd);
@@ -1658,7 +1908,8 @@ DrawMenuBarTemp(HWND Wnd, HDC DC, LPRECT Rect, HMENU Menu, HFONT Font)
 
   FillRect(DC, Rect, GetSysColorBrush(flat_menu ? COLOR_MENUBAR : COLOR_MENU));
 
-  SelectObject(DC, GetSysColorPen(COLOR_3DFACE));
+  SelectObject(DC, GetStockObject(DC_PEN));
+  SetDCPenColor(DC, GetSysColor(COLOR_3DFACE));
   MoveToEx(DC, Rect->left, Rect->bottom, NULL);
   LineTo(DC, Rect->right, Rect->bottom);
 
@@ -1684,44 +1935,6 @@ DrawMenuBarTemp(HWND Wnd, HDC DC, LPRECT Rect, HMENU Menu, HFONT Font)
   return MenuInfo.Height;
 }
 
-
-/***********************************************************************
- *           MenuDrawMenuBar
- *
- * Paint a menu bar. Returns the height of the menu bar.
- * called from [windows/nonclient.c]
- */
-UINT MenuDrawMenuBar(HDC DC, LPRECT Rect, HWND Wnd, BOOL SuppressDraw)
-{
-  ROSMENUINFO MenuInfo;
-  HFONT FontOld = NULL;
-  HMENU Menu = GetMenu(Wnd);
-
-  if (NULL == Rect || ! MenuGetRosMenuInfo(&MenuInfo, Menu))
-    {
-      return GetSystemMetrics(SM_CYMENU);
-    }
-
-  if (SuppressDraw)
-    {
-      FontOld = SelectObject(DC, hMenuFont);
-
-      MenuMenuBarCalcSize(DC, Rect, &MenuInfo, Wnd);
-
-      Rect->bottom = Rect->top + MenuInfo.Height;
-
-      if (NULL != FontOld)
-        {
-          SelectObject(DC, FontOld);
-        }
-      return MenuInfo.Height;
-    }
-  else
-    {
-      return DrawMenuBarTemp(Wnd, DC, Rect, Menu, NULL);
-    }
-}
-
 /***********************************************************************
  *           MenuInitTracking
  */
@@ -1747,7 +1960,7 @@ MenuInitTracking(HWND Wnd, HMENU Menu, BOOL Popup, UINT Flags)
       SendMessageW(Wnd, WM_INITMENU, (WPARAM)Menu, 0);
 
       MenuGetRosMenuInfo(&MenuInfo, Menu);
-      
+
       if (0 == MenuInfo.Height)
         {
           /* app changed/recreated menu bar entries in WM_INITMENU
@@ -1770,107 +1983,6 @@ MenuInitTracking(HWND Wnd, HMENU Menu, BOOL Popup, UINT Flags)
   return TRUE;
 }
 
-
-/***********************************************************************
- *           MenuShowPopup
- *
- * Display a popup menu.
- */
-static BOOL FASTCALL
-MenuShowPopup(HWND WndOwner, HMENU Menu, UINT Id,
-              INT X, INT Y, INT XAnchor, INT YAnchor )
-{
-  ROSMENUINFO MenuInfo;
-  ROSMENUITEMINFO ItemInfo;
-  UINT Width, Height;
-
-  TRACE("owner=%x hmenu=%x id=0x%04x x=0x%04x y=0x%04x xa=0x%04x ya=0x%04x\n",
-         WndOwner, Menu, Id, X, Y, XAnchor, YAnchor);
-
-  if (! MenuGetRosMenuInfo(&MenuInfo, Menu))
-    {
-      return FALSE;
-    }
-
-  if (NO_SELECTED_ITEM != MenuInfo.FocusedItem)
-    {
-      MenuInitRosMenuItemInfo(&ItemInfo);
-      if (MenuGetRosMenuItemInfo(MenuInfo.Self, MenuInfo.FocusedItem, &ItemInfo))
-        {
-          ItemInfo.fMask |= MIIM_STATE;
-          ItemInfo.fState &= ~(MF_HILITE|MF_MOUSESELECT);
-          MenuSetRosMenuItemInfo(MenuInfo.Self, MenuInfo.FocusedItem, &ItemInfo);
-        }
-      MenuCleanupRosMenuItemInfo(&ItemInfo);
-      MenuInfo.FocusedItem = NO_SELECTED_ITEM;
-    }
-
-  /* store the owner for DrawItem */
-  MenuInfo.WndOwner = WndOwner;
-  MenuSetRosMenuInfo(&MenuInfo);
-
-  MenuPopupMenuCalcSize(&MenuInfo, WndOwner);
-
-  /* adjust popup menu pos so that it fits within the desktop */
-
-  Width = MenuInfo.Width + GetSystemMetrics(SM_CXBORDER);
-  Height = MenuInfo.Height + GetSystemMetrics(SM_CYBORDER);
-
-  if (GetSystemMetrics(SM_CXSCREEN ) < X + Width)
-    {
-      if (0 != XAnchor && X >= Width - XAnchor)
-        {
-          X -= Width - XAnchor;
-        }
-      if (GetSystemMetrics(SM_CXSCREEN) < X + Width)
-        {
-          X = GetSystemMetrics(SM_CXSCREEN) - Width;
-        }
-    }
-  if (X < 0 )
-    {
-      X = 0;
-    }
-
-  if (GetSystemMetrics(SM_CYSCREEN) < Y + Height)
-    {
-      if (0 != YAnchor && Y >= Height + YAnchor)
-        {
-          Y -= Height + YAnchor;
-        }
-      if (GetSystemMetrics(SM_CYSCREEN) < Y + Height)
-        {
-          Y = GetSystemMetrics(SM_CYSCREEN) - Height;
-        }
-    }
-  if (Y < 0 )
-    {
-      Y = 0;
-    }
-
-
-  /* NOTE: In Windows, top menu popup is not owned. */
-  MenuInfo.Wnd = CreateWindowExW(0, POPUPMENU_CLASS_ATOMW, NULL,
-                                 WS_POPUP, X, Y, Width, Height,
-                                 WndOwner, 0, (HINSTANCE) GetWindowLongPtrW(WndOwner, GWLP_HINSTANCE),
-                                 (LPVOID) MenuInfo.Self);
-  if (NULL == MenuInfo.Wnd || ! MenuSetRosMenuInfo(&MenuInfo))
-    {
-      return FALSE;
-    }
-  if (NULL == TopPopup)
-    {
-      TopPopup = MenuInfo.Wnd;
-    }
-
-  /* Display the window */
-  SetWindowPos(MenuInfo.Wnd, HWND_TOPMOST, 0, 0, 0, 0,
-               SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
-  UpdateWindow(MenuInfo.Wnd);
-
-  return TRUE;
-}
-
 /***********************************************************************
  *           MenuFindSubMenu
  *
@@ -2077,8 +2189,7 @@ MenuMoveSelection(HWND WndOwner, PROSMENUINFO MenuInfo, INT Offset)
         }
       /* If this is a good candidate; */
       if (MenuGetRosMenuItemInfo(MenuInfo->Self, i, &ItemInfo) &&
-          0 == (ItemInfo.fType & MF_SEPARATOR) &&
-          0 == (ItemInfo.fState & (MFS_DISABLED | MFS_GRAYED)) )
+          0 == (ItemInfo.fType & MF_SEPARATOR))
         {
           MenuSelectItem(WndOwner, MenuInfo, i, TRUE, NULL);
           MenuCleanupRosMenuItemInfo(&ItemInfo);
@@ -2235,8 +2346,8 @@ MenuShowSubPopup(HWND WndOwner, PROSMENUINFO MenuInfo, BOOL SelectFirst, UINT Fl
 
   if (IS_SYSTEM_MENU(MenuInfo))
     {
-      MenuInitSysMenuPopup(ItemInfo.hSubMenu, GetWindowLongW(MenuInfo->Wnd, GWL_STYLE),
-                           GetClassLongW(MenuInfo->Wnd, GCL_STYLE), HTSYSMENU);
+      MenuInitSysMenuPopup(ItemInfo.hSubMenu, GetWindowLongPtrW(MenuInfo->Wnd, GWL_STYLE),
+                           GetClassLongPtrW(MenuInfo->Wnd, GCL_STYLE), HTSYSMENU);
 
       NcGetSysPopupPos(MenuInfo->Wnd, &Rect);
       Rect.top = Rect.bottom;
@@ -2263,7 +2374,7 @@ MenuShowSubPopup(HWND WndOwner, PROSMENUINFO MenuInfo, BOOL SelectFirst, UINT Fl
         }
     }
 
-  MenuShowPopup(WndOwner, ItemInfo.hSubMenu, MenuInfo->FocusedItem,
+  MenuShowPopup(WndOwner, ItemInfo.hSubMenu, MenuInfo->FocusedItem, Flags,
                 Rect.left, Rect.top, Rect.right, Rect.bottom );
   if (SelectFirst && MenuGetRosMenuInfo(&SubMenuInfo, ItemInfo.hSubMenu))
     {
@@ -2634,11 +2745,11 @@ MenuMouseMove(MTRACKER *Mt, HMENU PtMenu, UINT Flags)
     {
        MenuInitRosMenuItemInfo(&ItemInfo);
        if (MenuGetRosMenuItemInfo(MenuInfo.Self, Index, &ItemInfo) &&
-           !(ItemInfo.fType & MF_SEPARATOR) &&
-           !(ItemInfo.fState & (MFS_DISABLED | MFS_GRAYED)) )
+           !(ItemInfo.fType & MF_SEPARATOR))
        {
            MenuSwitchTracking(Mt, &MenuInfo, Index);
-           Mt->CurrentMenu = MenuShowSubPopup(Mt->OwnerWnd, &MenuInfo, FALSE, Flags);
+        if (!(ItemInfo.fState & (MFS_DISABLED | MFS_GRAYED)))
+               Mt->CurrentMenu = MenuShowSubPopup(Mt->OwnerWnd, &MenuInfo, FALSE, Flags);
        }
        MenuCleanupRosMenuItemInfo(&ItemInfo);
     }
@@ -2793,7 +2904,7 @@ MenuDoNextMenu(MTRACKER* Mt, UINT Vk)
 
       if (NULL == NextMenu.hmenuNext || NULL == NextMenu.hwndNext)
         {
-          DWORD Style = GetWindowLongW(Mt->OwnerWnd, GWL_STYLE);
+          DWORD Style = GetWindowLongPtrW(Mt->OwnerWnd, GWL_STYLE);
           NewWnd = Mt->OwnerWnd;
           if (IS_SYSTEM_MENU(&TopMenuInfo))
             {
@@ -2831,7 +2942,7 @@ MenuDoNextMenu(MTRACKER* Mt, UINT Vk)
 
           if (IsMenu(NewMenu) && IsWindow(NewWnd))
             {
-              DWORD Style = GetWindowLongW(NewWnd, GWL_STYLE);
+              DWORD Style = GetWindowLongPtrW(NewWnd, GWL_STYLE);
 
               if (0 != (Style & WS_SYSMENU)
                   && GetSystemMenu(NewWnd, FALSE) == NewMenu)
@@ -3084,109 +3195,37 @@ MenuKeyRight(MTRACKER *Mt, UINT Flags)
         {
           MenuSelectItem(Mt->OwnerWnd, &MenuInfo, NextCol, TRUE, 0);
         }
-      return;
-    }
-
-  if (0 == (MenuInfo.Flags & MF_POPUP))        /* menu bar tracking */
-    {
-      if (Mt->CurrentMenu != Mt->TopMenu)
-        {
-          MenuHideSubPopups(Mt->OwnerWnd, &MenuInfo, FALSE );
-          MenuTmp = Mt->CurrentMenu = Mt->TopMenu;
-        }
-      else
-        {
-          MenuTmp = NULL;
-        }
-
-      /* try to move to the next item */
-      if (! MenuDoNextMenu(Mt, VK_RIGHT))
-        {
-          MenuMoveSelection(Mt->OwnerWnd, &MenuInfo, ITEM_NEXT);
-        }
-
-      if (NULL != MenuTmp || 0 != (Mt->TrackFlags & TF_SUSPENDPOPUP))
-        {
-          if (! MenuSuspendPopup(Mt, WM_KEYDOWN)
-              && MenuGetRosMenuInfo(&MenuInfo, Mt->TopMenu))
-            {
-              Mt->CurrentMenu = MenuShowSubPopup(Mt->OwnerWnd, &MenuInfo,
-                                                 TRUE, Flags);
-            }
-        }
-    }
-}
-
-/***********************************************************************
- *           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
-MenuFindItemByKey(HWND WndOwner, PROSMENUINFO MenuInfo,
-                  WCHAR Key, BOOL ForceMenuChar)
-{
-  ROSMENUINFO SysMenuInfo;
-  PROSMENUITEMINFO Items, ItemInfo;
-  LRESULT MenuChar;
-  UINT i;
-
-  TRACE("\tlooking for '%c' (0x%02x) in [%p]\n", (char) Key, Key, MenuInfo);
-
-  if (NULL == MenuInfo || ! IsMenu(MenuInfo->Self))
-    {
-      if (MenuGetRosMenuInfo(&SysMenuInfo, GetSystemMenu(WndOwner, FALSE)))
-        {
-          MenuInfo = &SysMenuInfo;
-        }
-      else
-        {
-          MenuInfo = NULL;
-        }
-    }
-
-  if (NULL != MenuInfo)
-    {
-      if (MenuGetAllRosMenuItemInfo(MenuInfo->Self, &Items) <= 0)
-        {
-          return -1;
-        }
-      if (! ForceMenuChar)
-        {
-          Key = toupperW(Key);
-          ItemInfo = Items;
-          for (i = 0; i < MenuInfo->MenuItemCount; i++, ItemInfo++)
-            {
-              if ((ItemInfo->Text) && NULL != ItemInfo->dwTypeData)
-                {
-                  WCHAR *p = (WCHAR *) ItemInfo->dwTypeData - 2;
-                  do
-                    {
-                      p = strchrW(p + 2, '&');
-                   }
-                  while (NULL != p && L'&' == p[1]);
-                  if (NULL != p && (toupperW(p[1]) == Key))
-                    {
-                      return i;
-                    }
-                }
-            }
-        }
+      return;
+    }
 
-      MenuChar = SendMessageW(WndOwner, WM_MENUCHAR,
-                              MAKEWPARAM(Key, MenuInfo->Flags), (LPARAM) MenuInfo->Self);
-      if (2 == HIWORD(MenuChar))
+  if (0 == (MenuInfo.Flags & MF_POPUP))        /* menu bar tracking */
+    {
+      if (Mt->CurrentMenu != Mt->TopMenu)
         {
-          return LOWORD(MenuChar);
+          MenuHideSubPopups(Mt->OwnerWnd, &MenuInfo, FALSE );
+          MenuTmp = Mt->CurrentMenu = Mt->TopMenu;
         }
-      if (1 == HIWORD(MenuChar))
+      else
         {
-          return (UINT) (-2);
+          MenuTmp = NULL;
         }
-    }
 
-  return (UINT)(-1);
+      /* try to move to the next item */
+      if (! MenuDoNextMenu(Mt, VK_RIGHT))
+        {
+          MenuMoveSelection(Mt->OwnerWnd, &MenuInfo, ITEM_NEXT);
+        }
+
+      if (NULL != MenuTmp || 0 != (Mt->TrackFlags & TF_SUSPENDPOPUP))
+        {
+          if (! MenuSuspendPopup(Mt, WM_KEYDOWN)
+              && MenuGetRosMenuInfo(&MenuInfo, Mt->TopMenu))
+            {
+              Mt->CurrentMenu = MenuShowSubPopup(Mt->OwnerWnd, &MenuInfo,
+                                                 TRUE, Flags);
+            }
+        }
+    }
 }
 
 /***********************************************************************
@@ -3217,6 +3256,12 @@ MenuTrackMenu(HMENU Menu, UINT Flags, INT x, INT y,
          Menu, Flags, x, y, Wnd, Rect ? Rect->left : 0, Rect ? Rect->top : 0,
          Rect ? Rect->right : 0, Rect ? Rect->bottom : 0);
 
+  if (!IsMenu(Menu))
+  {
+    SetLastError( ERROR_INVALID_MENU_HANDLE );
+    return FALSE;
+  }
+
   fEndMenu = FALSE;
   if (! MenuGetRosMenuInfo(&MenuInfo, Menu))
     {
@@ -3233,8 +3278,13 @@ MenuTrackMenu(HMENU Menu, UINT Flags, INT x, INT y,
   SetCapture(Mt.OwnerWnd);
   (void)NtUserSetGUIThreadHandle(MSQ_STATE_MENUOWNER, Mt.OwnerWnd);
 
+  ERR("MenuTrackMenu 1\n");
   while (! fEndMenu)
     {
+      PVOID menu = ValidateHandle(Mt.CurrentMenu, VALIDATE_TYPE_MENU);
+      if (!menu) /* sometimes happens if I do a window manager close */
+         break;
+
       /* we have to keep the message in the queue until it's
        * clear that menu loop is not over yet. */
 
@@ -3263,7 +3313,7 @@ MenuTrackMenu(HMENU Menu, UINT Flags, INT x, INT y,
         }
 
       /* check if EndMenu() tried to cancel us, by posting this message */
-      if (WM_CANCELMODE == Msg.message)
+      if (Msg.message == WM_CANCELMODE)
         {
           /* we are now out of the loop */
           fEndMenu = TRUE;
@@ -3278,13 +3328,13 @@ MenuTrackMenu(HMENU Menu, UINT Flags, INT x, INT y,
       TranslateMessage(&Msg);
       Mt.Pt = Msg.pt;
 
-      if (Msg.hwnd == MenuInfo.Wnd || WM_TIMER != Msg.message)
+      if (Msg.hwnd == MenuInfo.Wnd || Msg.message != WM_TIMER)
         {
           EnterIdleSent = FALSE;
         }
 
       fRemove = FALSE;
-      if (WM_MOUSEFIRST <= Msg.message && Msg.message <= WM_MOUSELAST)
+      if ((Msg.message >= WM_MOUSEFIRST) && (Msg.message <= WM_MOUSELAST))
         {
           /*
            * Use the mouse coordinates in lParam instead of those in the MSG
@@ -3303,10 +3353,7 @@ MenuTrackMenu(HMENU Menu, UINT Flags, INT x, INT y,
 
               case WM_RBUTTONDBLCLK:
               case WM_RBUTTONDOWN:
-                if (0 == (Flags & TPM_RIGHTBUTTON))
-                  {
-                    break;
-                  }
+                if (!(Flags & TPM_RIGHTBUTTON)) break;
                 /* fall through */
               case WM_LBUTTONDBLCLK:
               case WM_LBUTTONDOWN:
@@ -3317,14 +3364,11 @@ MenuTrackMenu(HMENU Menu, UINT Flags, INT x, INT y,
                 break;
 
               case WM_RBUTTONUP:
-                if (0 == (Flags & TPM_RIGHTBUTTON))
-                  {
-                    break;
-                  }
+                if (0 == (Flags & TPM_RIGHTBUTTON)) break;
                 /* fall through */
               case WM_LBUTTONUP:
                 /* Check if a menu was selected by the mouse */
-                if (NULL != Menu)
+                if (Menu)
                   {
                     ExecutedMenuId = MenuButtonUp(&Mt, Menu, Flags);
 
@@ -3344,13 +3388,13 @@ MenuTrackMenu(HMENU Menu, UINT Flags, INT x, INT y,
               case WM_MOUSEMOVE:
                 if (Menu)
                   {
-                    fEndMenu |= ! MenuMouseMove(&Mt, Menu, Flags);
+                    fEndMenu |= !MenuMouseMove(&Mt, Menu, Flags);
                   }
                 break;
 
            } /* switch(Msg.message) - mouse */
        }
-      else if (WM_KEYFIRST <= Msg.message && Msg.message <= WM_KEYLAST)
+      else if ((Msg.message >= WM_KEYFIRST) && (Msg.message <= WM_KEYLAST))
        {
           fRemove = TRUE;  /* Keyboard messages are always removed */
           switch(Msg.message)
@@ -3368,17 +3412,12 @@ MenuTrackMenu(HMENU Menu, UINT Flags, INT x, INT y,
                         {
                           MenuSelectItem(Mt.OwnerWnd, &MenuInfo, NO_SELECTED_ITEM,
                                          FALSE, 0 );
-                        }
-                      /* fall through */
-
-                    case VK_UP:
-                      if (MenuGetRosMenuInfo(&MenuInfo, Mt.CurrentMenu))
-                        {
                           MenuMoveSelection(Mt.OwnerWnd, &MenuInfo,
                                             VK_HOME == Msg.wParam ? ITEM_NEXT : ITEM_PREV);
                         }
                       break;
 
+                    case VK_UP:
                     case VK_DOWN: /* If on menu bar, pull-down the menu */
                       if (MenuGetRosMenuInfo(&MenuInfo, Mt.CurrentMenu))
                         {
@@ -3392,7 +3431,8 @@ MenuTrackMenu(HMENU Menu, UINT Flags, INT x, INT y,
                             }
                           else      /* otherwise try to move selection */
                             {
-                              MenuMoveSelection(Mt.OwnerWnd, &MenuInfo, ITEM_NEXT);
+                              MenuMoveSelection(Mt.OwnerWnd, &MenuInfo,
+                                            VK_DOWN == Msg.wParam ? ITEM_NEXT : ITEM_PREV);
                             }
                         }
                       break;
@@ -3514,6 +3554,7 @@ MenuTrackMenu(HMENU Menu, UINT Flags, INT x, INT y,
           Mt.TrackFlags &= ~TF_SKIPREMOVE;
         }
     }
+  ERR("MenuTrackMenu 2\n");
 
   (void)NtUserSetGUIThreadHandle(MSQ_STATE_MENUOWNER, NULL);
   SetCapture(NULL);  /* release the capture */
@@ -3534,6 +3575,11 @@ MenuTrackMenu(HMENU Menu, UINT Flags, INT x, INT y,
                 {
                   DestroyWindow(MenuInfo.Wnd);
                   MenuInfo.Wnd = NULL;
+
+                  if (!(MenuInfo.Flags & TPM_NONOTIFY))
+                    SendMessageW( Mt.OwnerWnd, WM_UNINITMENUPOPUP, (WPARAM)Mt.TopMenu,
+                                 MAKELPARAM(0, IS_SYSTEM_MENU(&MenuInfo)) );
+
                 }
               MenuSelectItem(Mt.OwnerWnd, &MenuInfo, NO_SELECTED_ITEM, FALSE, NULL);
             }
@@ -3605,7 +3651,7 @@ MenuTrackKbdMenuBar(HWND hWnd, UINT wParam, WCHAR wChar)
 
     /* find window that has a menu */
 
-    while (!((GetWindowLongW( hWnd, GWL_STYLE ) &
+    while (!((GetWindowLongPtrW( hWnd, GWL_STYLE ) &
                                          (WS_CHILD | WS_POPUP)) != WS_CHILD))
         if (!(hWnd = GetAncestor( hWnd, GA_PARENT ))) return;
 
@@ -3614,7 +3660,7 @@ MenuTrackKbdMenuBar(HWND hWnd, UINT wParam, WCHAR wChar)
     hTrackMenu = GetMenu( hWnd );
     if (!hTrackMenu || IsIconic(hWnd) || wChar == ' ' )
     {
-        if (!(GetWindowLongW( hWnd, GWL_STYLE ) & WS_SYSMENU)) return;
+        if (!(GetWindowLongPtrW( hWnd, GWL_STYLE ) & WS_SYSMENU)) return;
         hTrackMenu = NtUserGetSystemMenu(hWnd, FALSE);
         uItem = 0;
         wParam |= HTSYSMENU; /* prevent item lookup */
@@ -3665,20 +3711,20 @@ track_menu:
 
 /*
  *  From MSDN:
- *  The MFT_BITMAP, MFT_SEPARATOR, and MFT_STRING values cannot be combined 
+ *  The MFT_BITMAP, MFT_SEPARATOR, and MFT_STRING values cannot be combined
  *  with one another. Also MFT_OWNERDRAW. Set fMask to MIIM_TYPE to use fType.
  *
  *  Windows 2K/XP: fType is used only if fMask has a value of MIIM_FTYPE.
  *
- *  MIIM_TYPE: Retrieves or sets the fType and dwTypeData members. Windows 
+ *  MIIM_TYPE: Retrieves or sets the fType and dwTypeData members. Windows
  *  2K/XP: MIIM_TYPE is replaced by  MIIM_BITMAP, MIIM_FTYPE, and MIIM_STRING.
- *  MFT_STRING is replaced by MIIM_STRING. 
+ *  MFT_STRING is replaced by MIIM_STRING.
  *  (So, I guess we should use MIIM_STRING only for strings?)
  *
  *  MIIM_FTYPE: Windows 2K/Windows XP: Retrieves or sets the fType member.
  *
  *  Based on wine, SetMenuItemInfo_common:
- *  1) set MIIM_STRING | MIIM_FTYPE | MIIM_BITMAP any one with MIIM_TYPE, 
+ *  1) set MIIM_STRING | MIIM_FTYPE | MIIM_BITMAP any one with MIIM_TYPE,
  *     it will result in a error.
  *  2) set menu mask to MIIM_FTYPE and MFT_BITMAP ftype it will result in a error.
  *     These conditions are addressed in Win32k IntSetMenuItemInfo.
@@ -3687,11 +3733,11 @@ track_menu:
 static
 BOOL
 FASTCALL
-MenuSetItemData( 
+MenuSetItemData(
   LPMENUITEMINFOW mii,
-  UINT Flags, 
-  UINT_PTR IDNewItem, 
-  LPCWSTR NewItem, 
+  UINT Flags,
+  UINT_PTR IDNewItem,
+  LPCWSTR NewItem,
   BOOL Unicode)
 {
 /*
@@ -3699,9 +3745,14 @@ MenuSetItemData(
  */
   if(Flags & MF_BITMAP)
   {
-    mii->fMask |= MIIM_BITMAP;   /* Use the new way of seting hbmpItem.*/
-    mii->hbmpItem = (HBITMAP) NewItem;
-    mii->fType &= ~MFT_BITMAP;  /* just incase, Kill the old way */
+     mii->fMask |= MIIM_BITMAP;   /* Use the new way of seting hbmpItem.*/
+     mii->hbmpItem = (HBITMAP) NewItem;
+
+     if (Flags & MF_HELP)
+     {
+         /* increase ident */
+         mii->fType |= MF_HELP;
+     }
   }
   else if(Flags & MF_OWNERDRAW)
   {
@@ -3712,6 +3763,8 @@ MenuSetItemData(
   else if (Flags & MF_SEPARATOR)
   {
     mii->fType |= MFT_SEPARATOR;
+    if (!(Flags & (MF_GRAYED|MF_DISABLED)))
+      Flags |= MF_GRAYED|MF_DISABLED;
   }
   else /* Default action MF_STRING. */
   {
@@ -3727,7 +3780,7 @@ MenuSetItemData(
           }
        }
        else
-       { 
+       {
           LPCSTR NewItemA = (LPCSTR) NewItem;
           if (*NewItemA == '\b')
           {
@@ -3736,15 +3789,23 @@ MenuSetItemData(
              NewItem = (LPCWSTR) NewItemA;
           }
        }
+
+       if (Flags & MF_HELP)
+         mii->fType |= MF_HELP;
+       mii->fMask |= MIIM_STRING;
+       mii->fType |= MFT_STRING; /* Zero */
+       mii->dwTypeData = (LPWSTR)NewItem;
+       if (Unicode)
+         mii->cch = (NULL == NewItem ? 0 : strlenW(NewItem));
+       else
+         mii->cch = (NULL == NewItem ? 0 : strlen((LPCSTR)NewItem));
     }
-    mii->fMask |= MIIM_STRING;
-    mii->fType |= MFT_STRING; /* Zero */
-    mii->dwTypeData = (LPWSTR)NewItem;
-    if (Unicode)
-       mii->cch = (NULL == NewItem ? 0 : strlenW(NewItem));
     else
-       mii->cch = (NULL == NewItem ? 0 : strlen((LPCSTR)NewItem));
-    mii->hbmpItem = NULL;
+    {
+      mii->fType |= MFT_SEPARATOR;
+      if (!(Flags & (MF_GRAYED|MF_DISABLED)))
+        Flags |= MF_GRAYED|MF_DISABLED;
+    }
   }
 
   if(Flags & MF_RIGHTJUSTIFY) /* Same as MF_HELP */
@@ -3761,14 +3822,19 @@ MenuSetItemData(
     mii->fType |= MFT_MENUBARBREAK;
   }
 
-  if(Flags & MF_GRAYED)
+  if(Flags & MF_GRAYED || Flags & MF_DISABLED)
   {
-    mii->fState |= MFS_GRAYED;
+    if (Flags & MF_GRAYED)
+      mii->fState |= MF_GRAYED;
+
+    if (Flags & MF_DISABLED)
+      mii->fState |= MF_DISABLED;
+
     mii->fMask |= MIIM_STATE;
   }
-  else if(Flags & MF_DISABLED)
+  else if (Flags & MF_HILITE)
   {
-    mii->fState |= MFS_DISABLED;
+    mii->fState |= MF_HILITE;
     mii->fMask |= MIIM_STATE;
   }
   else /* default state */
@@ -3791,6 +3857,22 @@ MenuSetItemData(
   return TRUE;
 }
 
+NTSTATUS WINAPI
+User32CallLoadMenuFromKernel(PVOID Arguments, ULONG ArgumentLength)
+{
+  PLOADMENU_CALLBACK_ARGUMENTS Common;
+  LRESULT Result;  
+
+  Common = (PLOADMENU_CALLBACK_ARGUMENTS) Arguments;
+  
+  Result = (LRESULT)LoadMenuW( Common->hModule,
+                               IS_INTRESOURCE(Common->MenuName[0]) ?
+                                  MAKEINTRESOURCE(Common->MenuName[0]) :
+                                        (LPCWSTR)&Common->MenuName);
+
+  return ZwCallbackReturn(&Result, sizeof(LRESULT), STATUS_SUCCESS);
+}
+
 
 /* FUNCTIONS *****************************************************************/
 
@@ -3804,7 +3886,7 @@ MenuIsStringItem(ULONG TypeData)
 /*
  * @implemented
  */
-BOOL STDCALL
+BOOL WINAPI
 AppendMenuA(HMENU hMenu,
            UINT uFlags,
            UINT_PTR uIDNewItem,
@@ -3818,7 +3900,7 @@ AppendMenuA(HMENU hMenu,
 /*
  * @implemented
  */
-BOOL STDCALL
+BOOL WINAPI
 AppendMenuW(HMENU hMenu,
            UINT uFlags,
            UINT_PTR uIDNewItem,
@@ -3832,7 +3914,7 @@ AppendMenuW(HMENU hMenu,
 /*
  * @implemented
  */
-DWORD STDCALL
+DWORD WINAPI
 CheckMenuItem(HMENU hmenu,
              UINT uIDCheckItem,
              UINT uCheck)
@@ -3840,62 +3922,142 @@ CheckMenuItem(HMENU hmenu,
   return NtUserCheckMenuItem(hmenu, uIDCheckItem, uCheck);
 }
 
+static
+BOOL
+MenuCheckMenuRadioItem(HMENU hMenu, UINT idFirst, UINT idLast, UINT idCheck, UINT uFlags, BOOL bCheck, PUINT pChecked, PUINT pUnchecked, PUINT pMenuChanged)
+{
+  UINT ItemCount, i;
+  PROSMENUITEMINFO Items = NULL;
+  UINT cChecked, cUnchecked;
+  BOOL bRet = TRUE;
+  //ROSMENUINFO mi;
+
+  if(idFirst > idLast)
+      return FALSE;
+
+  ItemCount = GetMenuItemCount(hMenu);
+
+  //mi.cbSize = sizeof(ROSMENUINFO);
+  //if(!NtUserMenuInfo(hmenu, &mi, FALSE)) return ret;
+
+
+  if(MenuGetAllRosMenuItemInfo(hMenu, &Items) <= 0)
+  {
+    ERR("MenuGetAllRosMenuItemInfo failed\n");
+    return FALSE;
+  }
+
+  cChecked = cUnchecked = 0;
+
+  for (i = 0 ; i < ItemCount; i++)
+  {
+    BOOL check = FALSE;
+    if (0 != (Items[i].fType & MF_MENUBARBREAK)) continue;
+    if (0 != (Items[i].fType & MF_SEPARATOR)) continue;
+
+    if ((Items[i].fType & MF_POPUP) && (uFlags == MF_BYCOMMAND))
+    {
+      MenuCheckMenuRadioItem(Items[i].hSubMenu, idFirst, idLast, idCheck, uFlags, bCheck, pChecked, pUnchecked, pMenuChanged);
+      continue;
+    }
+    if (uFlags & MF_BYPOSITION)
+    {
+      if (i < idFirst || i > idLast)
+        continue;
+
+      if (i == idCheck)
+      {
+        cChecked++;
+        check = TRUE;
+      }
+      else
+      {
+        cUnchecked++;
+      }
+    }
+      else
+      {
+        if (Items[i].wID < idFirst || Items[i].wID > idLast)
+          continue;
+
+        if (Items[i].wID == idCheck)
+        {
+          cChecked++;
+          check = TRUE;
+        }
+        else
+        {
+          cUnchecked++;
+        }
+      }
+
+      if (!bCheck)
+        continue;
+
+      Items[i].fMask = MIIM_STATE | MIIM_FTYPE;
+      if (check)
+      {
+        Items[i].fType |= MFT_RADIOCHECK;
+        Items[i].fState |= MFS_CHECKED;
+      }
+      else
+      {
+        Items[i].fState &= ~MFS_CHECKED;
+      }
+
+      if(!MenuSetRosMenuItemInfo(hMenu, i ,&Items[i]))
+      {
+        ERR("MenuSetRosMenuItemInfo failed\n");
+        bRet = FALSE;
+        break;
+      }
+  }
+  HeapFree(GetProcessHeap(), 0, Items);
+
+  *pChecked += cChecked;
+  *pUnchecked += cUnchecked;
+
+  if (cChecked || cUnchecked)
+    (*pMenuChanged)++;
+
+  return bRet;
+}
 
 /*
  * @implemented
  */
-BOOL STDCALL
+BOOL WINAPI
 CheckMenuRadioItem(HMENU hmenu,
                   UINT idFirst,
                   UINT idLast,
                   UINT idCheck,
                   UINT uFlags)
 {
-  ROSMENUINFO mi;
-  PROSMENUITEMINFO Items;
-  int i;
-  BOOL ret = FALSE;
-
-  mi.cbSize = sizeof(MENUINFO);
+  UINT cChecked = 0;
+  UINT cUnchecked = 0;
+  UINT cMenuChanged = 0;
 
-  TRACE("CheckMenuRadioItem\n");
+  if (!MenuCheckMenuRadioItem(hmenu, idFirst, idLast, idCheck, uFlags, FALSE, &cChecked, &cUnchecked, &cMenuChanged))
+    return FALSE;
 
-  if(idFirst > idLast) return ret;
+  if (cMenuChanged > 1)
+    return FALSE;
 
-  if(!NtUserMenuInfo(hmenu, &mi, FALSE)) return ret;
+  cMenuChanged = 0;
+  cChecked = 0;
+  cUnchecked = 0;
 
-  if(MenuGetAllRosMenuItemInfo(mi.Self, &Items) <= 0) return ret;
+  if (!MenuCheckMenuRadioItem(hmenu, idFirst, idLast, idCheck, uFlags, TRUE, &cChecked, &cUnchecked, &cMenuChanged))
+    return FALSE;
 
-  for (i = 0 ; i < mi.MenuItemCount; i++)
-    {
-      if (0 != (Items[i].fType & MF_MENUBARBREAK)) break;
-      if ( i >= idFirst && i <= idLast )
-      {
-         Items[i].fMask = MIIM_STATE | MIIM_FTYPE;
-         if ( i == idCheck)
-         {
-             Items[i].fType |= MFT_RADIOCHECK;
-             Items[i].fState |= MFS_CHECKED;
-         }
-         else
-         {
-             Items[i].fType &= ~MFT_RADIOCHECK;
-             Items[i].fState &= ~MFS_CHECKED;
-         }
-         if(!MenuSetRosMenuItemInfo(mi.Self, i ,&Items[i]))
-             break;
-      }
-   if ( i == mi.MenuItemCount) ret = TRUE;
-    }
-  MenuCleanupRosMenuItemInfo(Items);
-  return ret;
+  return (cChecked != 0);
 }
 
 
 /*
  * @implemented
  */
-HMENU STDCALL
+HMENU WINAPI
 CreateMenu(VOID)
 {
   MenuLoadBitmaps();
@@ -3906,7 +4068,7 @@ CreateMenu(VOID)
 /*
  * @implemented
  */
-HMENU STDCALL
+HMENU WINAPI
 CreatePopupMenu(VOID)
 {
   MenuLoadBitmaps();
@@ -3917,39 +4079,33 @@ CreatePopupMenu(VOID)
 /*
  * @implemented
  */
-BOOL STDCALL
-DeleteMenu(HMENU hMenu,
-          UINT uPosition,
-          UINT uFlags)
-{
-  return NtUserDeleteMenu(hMenu, uPosition, uFlags);
-}
-
-
-/*
- * @implemented
- */
-BOOL STDCALL
-DestroyMenu(HMENU hMenu)
-{
-    return NtUserDestroyMenu(hMenu);
-}
-
-
-/*
- * @implemented
- */
-BOOL STDCALL
+BOOL WINAPI
 DrawMenuBar(HWND hWnd)
 {
-  return (BOOL)NtUserCallHwndLock(hWnd, HWNDLOCK_ROUTINE_DRAWMENUBAR);
+//  return (BOOL)NtUserCallHwndLock(hWnd, HWNDLOCK_ROUTINE_DRAWMENUBAR);
+  ROSMENUINFO MenuInfo;
+  HMENU hMenu;
+  hMenu = GetMenu(hWnd);
+  if (!hMenu)
+     return FALSE;
+  MenuGetRosMenuInfo(&MenuInfo, hMenu);
+  MenuInfo.Height = 0; // make sure to recalc size
+  MenuSetRosMenuInfo(&MenuInfo);
+  /* The wine method doesn't work and I suspect it's more effort
+     then hackfix solution
+  SetWindowPos( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
+                  SWP_NOZORDER | SWP_FRAMECHANGED );
+  return TRUE;*/
+  // FIXME: hackfix
+  DefWndNCPaint(hWnd,(HRGN)-1,-1);
+  return TRUE;
 }
 
 
 /*
  * @implemented
  */
-BOOL STDCALL
+BOOL WINAPI
 EnableMenuItem(HMENU hMenu,
               UINT uIDEnableItem,
               UINT uEnable)
@@ -3960,7 +4116,7 @@ EnableMenuItem(HMENU hMenu,
 /*
  * @implemented
  */
-BOOL STDCALL
+BOOL WINAPI
 EndMenu(VOID)
 {
   GUITHREADINFO guii;
@@ -3976,30 +4132,22 @@ EndMenu(VOID)
 /*
  * @implemented
  */
-HMENU STDCALL
+HMENU WINAPI
 GetMenu(HWND hWnd)
 {
-  return NtUserGetMenu(hWnd);
-}
+       PWND Wnd = ValidateHwnd(hWnd);
 
+       if (!Wnd)
+               return NULL;
 
-/*
- * @implemented
- */
-BOOL STDCALL
-GetMenuBarInfo(HWND hwnd,
-              LONG idObject,
-              LONG idItem,
-              PMENUBARINFO pmbi)
-{
-  return (BOOL)NtUserGetMenuBarInfo(hwnd, idObject, idItem, pmbi);
+       return (HMENU)Wnd->IDMenu;
 }
 
 
 /*
  * @implemented
  */
-LONG STDCALL
+LONG WINAPI
 GetMenuCheckMarkDimensions(VOID)
 {
   return(MAKELONG(GetSystemMetrics(SM_CXMENUCHECK),
@@ -4010,7 +4158,7 @@ GetMenuCheckMarkDimensions(VOID)
 /*
  * @implemented
  */
-UINT STDCALL
+UINT WINAPI
 GetMenuDefaultItem(HMENU hMenu,
                   UINT fByPos,
                   UINT gmdiFlags)
@@ -4022,7 +4170,7 @@ GetMenuDefaultItem(HMENU hMenu,
 /*
  * @implemented
  */
-BOOL STDCALL
+BOOL WINAPI
 GetMenuInfo(HMENU hmenu,
            LPMENUINFO lpcmi)
 {
@@ -4046,7 +4194,7 @@ GetMenuInfo(HMENU hmenu,
 /*
  * @implemented
  */
-int STDCALL
+int WINAPI
 GetMenuItemCount(HMENU Menu)
 {
   ROSMENUINFO MenuInfo;
@@ -4058,7 +4206,7 @@ GetMenuItemCount(HMENU Menu)
 /*
  * @implemented
  */
-UINT STDCALL
+UINT WINAPI
 GetMenuItemID(HMENU hMenu,
              int nPos)
 {
@@ -4088,7 +4236,7 @@ GetMenuItemID(HMENU hMenu,
 /*
  * @implemented
  */
-BOOL STDCALL
+BOOL WINAPI
 GetMenuItemInfoA(
    HMENU Menu,
    UINT Item,
@@ -4121,7 +4269,8 @@ GetMenuItemInfoA(
    {
       miiW.dwTypeData = RtlAllocateHeap(GetProcessHeap(), 0,
                                         miiW.cch * sizeof(WCHAR));
-      if (miiW.dwTypeData == NULL) return FALSE;  
+      if (miiW.dwTypeData == NULL) return FALSE;
+      miiW.dwTypeData[0] = 0;
    }
 
    if (!NtUserMenuItemInfo(Menu, Item, ByPosition, (PROSMENUITEMINFO)&miiW, FALSE))
@@ -4142,13 +4291,27 @@ GetMenuItemInfoA(
 
    if ((miiW.fMask & MIIM_STRING) || (IS_STRING_ITEM(miiW.fType)))
    {
-      WideCharToMultiByte(CP_ACP, 0, miiW.dwTypeData, miiW.cch, AnsiBuffer,
-                             mii->cch, NULL, NULL);
+      if (miiW.cch)
+      {
+         if (!WideCharToMultiByte(CP_ACP, 0, miiW.dwTypeData, miiW.cch, AnsiBuffer, mii->cch, NULL, NULL))
+         {
+            AnsiBuffer[0] = 0;
+         }
+         if (Count > miiW.cch)
+         {
+            AnsiBuffer[miiW.cch] = 0;
+         }
+         mii->cch = mii->cch;
+      }
+   }
+   else
+   {
+      AnsiBuffer[0] = 0;
    }
 
    RtlFreeHeap(GetProcessHeap(), 0, miiW.dwTypeData);
    mii->dwTypeData = AnsiBuffer;
-   mii->cch = strlen(AnsiBuffer);
+
    return TRUE;
 }
 
@@ -4156,7 +4319,7 @@ GetMenuItemInfoA(
 /*
  * @implemented
  */
-BOOL STDCALL
+BOOL WINAPI
 GetMenuItemInfoW(
    HMENU Menu,
    UINT Item,
@@ -4166,7 +4329,7 @@ GetMenuItemInfoW(
    MENUITEMINFOW miiW;
    LPWSTR String;
    INT Count;
-   
+
    if (mii->cbSize != sizeof(MENUITEMINFOW) &&
        mii->cbSize != sizeof(MENUITEMINFOW) - sizeof(HBITMAP))
    {
@@ -4189,7 +4352,8 @@ GetMenuItemInfoW(
    {
       miiW.dwTypeData = RtlAllocateHeap(GetProcessHeap(), 0,
                                         miiW.cch * sizeof(WCHAR));
-      if (miiW.dwTypeData == NULL) return FALSE;  
+      if (miiW.dwTypeData == NULL) return FALSE;
+      miiW.dwTypeData[0] = 0;
    }
 
    if (!NtUserMenuItemInfo(Menu, Item, ByPosition, (PROSMENUITEMINFO) &miiW, FALSE))
@@ -4197,7 +4361,7 @@ GetMenuItemInfoW(
       if (miiW.dwTypeData) RtlFreeHeap(GetProcessHeap(), 0, miiW.dwTypeData);
       return FALSE;
    }
-   
+
    RtlCopyMemory(mii, &miiW, miiW.cbSize); // Okay to over write user data.
 
    if (!String || !Count)
@@ -4220,24 +4384,11 @@ GetMenuItemInfoW(
 }
 
 
-/*
- * @implemented
- */
-BOOL STDCALL
-GetMenuItemRect(HWND hWnd,
-               HMENU hMenu,
-               UINT uItem,
-               LPRECT lprcItem)
-{
-  return NtUserGetMenuItemRect( hWnd, hMenu, uItem, lprcItem);
-}
-
-
 /*
  * @implemented
  */
 UINT
-STDCALL
+WINAPI
 GetMenuState(
   HMENU hMenu,
   UINT uId,
@@ -4280,7 +4431,7 @@ GetMenuState(
  * @implemented
  */
 int
-STDCALL
+WINAPI
 GetMenuStringA(
   HMENU hMenu,
   UINT uIDItem,
@@ -4307,7 +4458,7 @@ GetMenuStringA(
  * @implemented
  */
 int
-STDCALL
+WINAPI
 GetMenuStringW(
   HMENU hMenu,
   UINT uIDItem,
@@ -4334,7 +4485,7 @@ GetMenuStringW(
  * @implemented
  */
 HMENU
-STDCALL
+WINAPI
 GetSubMenu(
   HMENU hMenu,
   int nPos)
@@ -4356,7 +4507,7 @@ GetSubMenu(
  * @implemented
  */
 HMENU
-STDCALL
+WINAPI
 GetSystemMenu(
   HWND hWnd,
   BOOL bRevert)
@@ -4373,23 +4524,7 @@ GetSystemMenu(
  * @implemented
  */
 BOOL
-STDCALL
-HiliteMenuItem(
-  HWND hwnd,
-  HMENU hmenu,
-  UINT uItemHilite,
-  UINT uHilite)
-{
-  return NtUserHiliteMenuItem(hwnd, hmenu, uItemHilite, uHilite);
-}
-
-
-
-/*
- * @implemented
- */
-BOOL
-STDCALL
+WINAPI
 InsertMenuA(
   HMENU hMenu,
   UINT uPosition,
@@ -4417,7 +4552,7 @@ InsertMenuA(
  * @implemented
  */
 BOOL
-STDCALL
+WINAPI
 InsertMenuItemA(
   HMENU hMenu,
   UINT uItem,
@@ -4435,7 +4570,7 @@ InsertMenuItemA(
   {
     RtlCopyMemory ( &mi, lpmii, lpmii->cbSize );
 
-    if( lpmii->cbSize != sizeof( MENUITEMINFOW)) 
+    if( lpmii->cbSize != sizeof( MENUITEMINFOW))
     {
        mi.cbSize = sizeof( MENUITEMINFOW);
        mi.hbmpItem = NULL;
@@ -4455,7 +4590,7 @@ InsertMenuItemA(
       mi.cch = MenuText.Length / sizeof(WCHAR);
       CleanHeap = TRUE;
     }
-    res = NtUserInsertMenuItem(hMenu, uItem, fByPosition, &mi);
+    res = NtUserThunkedMenuItemInfo(hMenu, uItem, fByPosition, TRUE, &mi, NULL);
 
     if ( CleanHeap ) RtlFreeUnicodeString ( &MenuText );
   }
@@ -4467,7 +4602,7 @@ InsertMenuItemA(
  * @implemented
  */
 BOOL
-STDCALL
+WINAPI
 InsertMenuItemW(
   HMENU hMenu,
   UINT uItem,
@@ -4487,7 +4622,7 @@ InsertMenuItemW(
   {
     RtlCopyMemory(&mi, lpmii, lpmii->cbSize);
 
-    if( lpmii->cbSize != sizeof( MENUITEMINFOW)) 
+    if( lpmii->cbSize != sizeof( MENUITEMINFOW))
     {
        mi.cbSize = sizeof( MENUITEMINFOW);
        mi.hbmpItem = NULL;
@@ -4501,7 +4636,7 @@ InsertMenuItemW(
       mi.dwTypeData = MenuText.Buffer;
       mi.cch = MenuText.Length / sizeof(WCHAR);
     }
-    res = NtUserInsertMenuItem(hMenu, uItem, fByPosition, &mi);
+    res = NtUserThunkedMenuItemInfo(hMenu, uItem, fByPosition, TRUE, &mi, NULL);
   }
   return res;
 }
@@ -4511,7 +4646,7 @@ InsertMenuItemW(
  * @implemented
  */
 BOOL
-STDCALL
+WINAPI
 InsertMenuW(
   HMENU hMenu,
   UINT uPosition,
@@ -4538,20 +4673,19 @@ InsertMenuW(
  * @implemented
  */
 BOOL
-STDCALL
+WINAPI
 IsMenu(
   HMENU Menu)
 {
-  ROSMENUINFO MenuInfo;
-
-  return MenuGetRosMenuInfo(&MenuInfo, Menu);
+  if (ValidateHandle(Menu, VALIDATE_TYPE_MENU)) return TRUE;
+  return FALSE;
 }
 
 
 /*
  * @implemented
  */
-HMENU STDCALL
+HMENU WINAPI
 LoadMenuA(HINSTANCE hInstance,
          LPCSTR lpMenuName)
 {
@@ -4567,7 +4701,7 @@ LoadMenuA(HINSTANCE hInstance,
 /*
  * @implemented
  */
-HMENU STDCALL
+HMENU WINAPI
 LoadMenuIndirectA(CONST MENUTEMPLATE *lpMenuTemplate)
 {
   return(LoadMenuIndirectW(lpMenuTemplate));
@@ -4577,7 +4711,7 @@ LoadMenuIndirectA(CONST MENUTEMPLATE *lpMenuTemplate)
 /*
  * @implemented
  */
-HMENU STDCALL
+HMENU WINAPI
 LoadMenuIndirectW(CONST MENUTEMPLATE *lpMenuTemplate)
 {
   HMENU hMenu;
@@ -4619,7 +4753,7 @@ LoadMenuIndirectW(CONST MENUTEMPLATE *lpMenuTemplate)
 /*
  * @implemented
  */
-HMENU STDCALL
+HMENU WINAPI
 LoadMenuW(HINSTANCE hInstance,
          LPCWSTR lpMenuName)
 {
@@ -4636,7 +4770,7 @@ LoadMenuW(HINSTANCE hInstance,
  * @implemented
  */
 int
-STDCALL
+WINAPI
 MenuItemFromPoint(
   HWND hWnd,
   HMENU hMenu,
@@ -4650,7 +4784,7 @@ MenuItemFromPoint(
  * @implemented
  */
 BOOL
-STDCALL
+WINAPI
 ModifyMenuA(
   HMENU hMnu,
   UINT uPosition,
@@ -4670,7 +4804,7 @@ ModifyMenuA(
   mi.Height = 0;
 
   if (!MenuSetRosMenuInfo( &mi )) return FALSE;
-  
+
   MenuInitRosMenuItemInfo( &rmii );
 
   if(!MenuGetRosMenuItemInfo( hMnu, uPosition, &rmii)) return FALSE;
@@ -4679,7 +4813,7 @@ ModifyMenuA(
     NtUserDestroyMenu( rmii.hSubMenu );   /* ModifyMenu() spec */
 
   MenuCleanupRosMenuItemInfo( &rmii );
-  
+
   MenuSetItemData((LPMENUITEMINFOW) &mii,
                   uFlags,
                   uIDNewItem,
@@ -4697,7 +4831,7 @@ ModifyMenuA(
  * @implemented
  */
 BOOL
-STDCALL
+WINAPI
 ModifyMenuW(
   HMENU hMnu,
   UINT uPosition,
@@ -4706,7 +4840,7 @@ ModifyMenuW(
   LPCWSTR lpNewItem)
 {
   ROSMENUINFO mi;
-  ROSMENUITEMINFO rmii;  
+  ROSMENUITEMINFO rmii;
   MENUITEMINFOW mii;
   memset ( &mii, 0, sizeof(mii) );
   mii.cbSize = sizeof(MENUITEMINFOW);
@@ -4745,21 +4879,7 @@ ModifyMenuW(
 /*
  * @implemented
  */
-BOOL
-STDCALL
-RemoveMenu(
-  HMENU hMenu,
-  UINT uPosition,
-  UINT uFlags)
-{
-  return NtUserRemoveMenu(hMenu, uPosition, uFlags);
-}
-
-
-/*
- * @implemented
- */
-BOOL STDCALL
+BOOL WINAPI
 SetMenu(HWND hWnd,
        HMENU hMenu)
 {
@@ -4771,29 +4891,19 @@ SetMenu(HWND hWnd,
  * @implemented
  */
 BOOL
-STDCALL
-SetMenuDefaultItem(
-  HMENU hMenu,
-  UINT uItem,
-  UINT fByPos)
-{
-  return NtUserSetMenuDefaultItem(hMenu, uItem, fByPos);
-}
-
-
-/*
- * @implemented
- */
-BOOL
-STDCALL
+WINAPI
 SetMenuInfo(
   HMENU hmenu,
   LPCMENUINFO lpcmi)
 {
   ROSMENUINFO mi;
   BOOL res = FALSE;
-  if(lpcmi->cbSize != sizeof(MENUINFO))
+
+  if (!lpcmi || (lpcmi->cbSize != sizeof(MENUINFO)))
+  {
+    SetLastError(ERROR_INVALID_PARAMETER);
     return res;
+  }
 
   memcpy(&mi, lpcmi, sizeof(MENUINFO));
   return NtUserMenuInfo(hmenu, &mi, TRUE);
@@ -4804,7 +4914,7 @@ SetMenuInfo(
  * @implemented
  */
 BOOL
-STDCALL
+WINAPI
 SetMenuItemBitmaps(
   HMENU hMenu,
   UINT uPosition,
@@ -4815,8 +4925,8 @@ SetMenuItemBitmaps(
   ROSMENUITEMINFO uItem;
   memset ( &uItem, 0, sizeof(uItem) );
   uItem.fMask = MIIM_STATE | MIIM_BITMAP;
-  
-  if(!(NtUserMenuItemInfo(hMenu, uPosition, 
+
+  if(!(NtUserMenuItemInfo(hMenu, uPosition,
                  (BOOL)(MF_BYPOSITION & uFlags), &uItem, FALSE))) return FALSE;
 
   if (!hBitmapChecked && !hBitmapUnchecked)
@@ -4838,7 +4948,7 @@ SetMenuItemBitmaps(
  * @implemented
  */
 BOOL
-STDCALL
+WINAPI
 SetMenuItemInfoA(
   HMENU hMenu,
   UINT uItem,
@@ -4852,7 +4962,7 @@ SetMenuItemInfoA(
 
   RtlCopyMemory(&MenuItemInfoW, lpmii, min(lpmii->cbSize, sizeof(MENUITEMINFOW)));
 
-  if( lpmii->cbSize != sizeof( MENUITEMINFOW)) 
+  if( lpmii->cbSize != sizeof( MENUITEMINFOW))
   {
      MenuItemInfoW.cbSize = sizeof( MENUITEMINFOW);
      MenuItemInfoW.hbmpItem = NULL;
@@ -4900,7 +5010,7 @@ SetMenuItemInfoA(
  * @implemented
  */
 BOOL
-STDCALL
+WINAPI
 SetMenuItemInfoW(
   HMENU hMenu,
   UINT uItem,
@@ -4912,14 +5022,14 @@ SetMenuItemInfoW(
 
   RtlCopyMemory(&MenuItemInfoW, lpmii, min(lpmii->cbSize, sizeof(MENUITEMINFOW)));
 
-  if( lpmii->cbSize != sizeof( MENUITEMINFOW)) 
+  if( lpmii->cbSize != sizeof( MENUITEMINFOW))
   {
      MenuItemInfoW.cbSize = sizeof( MENUITEMINFOW);
      MenuItemInfoW.hbmpItem = NULL;
   }
 
   if (((MenuItemInfoW.fMask & MIIM_STRING) ||
-      ((MenuItemInfoW.fMask & MIIM_TYPE) && 
+      ((MenuItemInfoW.fMask & MIIM_TYPE) &&
                            (MENU_ITEM_TYPE(MenuItemInfoW.fType) == MF_STRING)))
         && MenuItemInfoW.dwTypeData != NULL)
   {
@@ -4935,7 +5045,7 @@ SetMenuItemInfoW(
  * @implemented
  */
 BOOL
-STDCALL
+WINAPI
 SetSystemMenu (
   HWND hwnd,
   HMENU hMenu)
@@ -4958,7 +5068,7 @@ SetSystemMenu (
  * @implemented
  */
 BOOL
-STDCALL
+WINAPI
 TrackPopupMenu(
   HMENU Menu,
   UINT Flags,
@@ -4970,6 +5080,12 @@ TrackPopupMenu(
 {
   BOOL ret = FALSE;
 
+  if (!IsMenu(Menu))
+  {
+    SetLastError( ERROR_INVALID_MENU_HANDLE );
+    return FALSE;
+  }
+
   MenuInitTracking(Wnd, Menu, TRUE, Flags);
 
   /* Send WM_INITMENUPOPUP message only if TPM_NONOTIFY flag is not specified */
@@ -4978,12 +5094,11 @@ TrackPopupMenu(
       SendMessageW(Wnd, WM_INITMENUPOPUP, (WPARAM) Menu, 0);
     }
 
-  if (MenuShowPopup(Wnd, Menu, 0, x, y, 0, 0 ))
+  if (MenuShowPopup(Wnd, Menu, 0, Flags, x, y, 0, 0 ))
     {
       ret = MenuTrackMenu(Menu, Flags | TPM_POPUPMENU, 0, 0, Wnd, Rect);
     }
   MenuExitTracking(Wnd);
-
   return ret;
 }
 
@@ -4992,7 +5107,7 @@ TrackPopupMenu(
  * @unimplemented
  */
 BOOL
-STDCALL
+WINAPI
 TrackPopupMenuEx(
   HMENU Menu,
   UINT Flags,
@@ -5012,7 +5127,7 @@ TrackPopupMenuEx(
 //
 //
 BOOL
-STDCALL
+WINAPI
 NEWTrackPopupMenu(
   HMENU Menu,
   UINT Flags,
@@ -5031,23 +5146,11 @@ NEWTrackPopupMenu(
 }
 
 
-/*
- * @implemented
- */
-BOOL
-STDCALL
-SetMenuContextHelpId(HMENU hmenu,
-          DWORD dwContextHelpId)
-{
-  return NtUserSetMenuContextHelpId(hmenu, dwContextHelpId);
-}
-
-
 /*
  * @implemented
  */
 DWORD
-STDCALL
+WINAPI
 GetMenuContextHelpId(HMENU hmenu)
 {
   ROSMENUINFO mi;
@@ -5064,40 +5167,63 @@ GetMenuContextHelpId(HMENU hmenu)
 /*
  * @unimplemented
  */
-LRESULT
-STDCALL
+BOOL
+WINAPI
 MenuWindowProcA(
                HWND   hWnd,
+               ULONG_PTR Result,
                UINT   Msg,
                WPARAM wParam,
                LPARAM lParam
                )
 {
-  UNIMPLEMENTED;
-  return FALSE;
+  if ( Msg < WM_USER)
+  {
+     LRESULT lResult;
+     lResult = PopupMenuWndProcA(hWnd, Msg, wParam, lParam );
+     if (Result)
+     {
+        Result = (ULONG_PTR)lResult;
+        return TRUE;
+     }
+     return FALSE;
+  }
+  return NtUserMessageCall(hWnd, Msg, wParam, lParam, Result, FNID_MENU, TRUE);
+
 }
 
 /*
  * @unimplemented
  */
-LRESULT
-STDCALL
+BOOL
+WINAPI
 MenuWindowProcW(
                HWND   hWnd,
+               ULONG_PTR Result,
                UINT   Msg,
                WPARAM wParam,
                LPARAM lParam
                )
 {
-  UNIMPLEMENTED;
-  return FALSE;
+  if ( Msg < WM_USER)
+  {
+     LRESULT lResult;
+     lResult = PopupMenuWndProcW(hWnd, Msg, wParam, lParam );
+     if (Result)
+     {
+        Result = (ULONG_PTR)lResult;
+        return TRUE;
+     }
+     return FALSE;
+  }
+  return NtUserMessageCall(hWnd, Msg, wParam, lParam, Result, FNID_MENU, FALSE);
 }
 
 /*
  * @implemented
  */
 BOOL
-STDCALL
+WINAPI
 ChangeMenuW(
     HMENU hMenu,
     UINT cmd,
@@ -5135,7 +5261,7 @@ ChangeMenuW(
  * @implemented
  */
 BOOL
-STDCALL
+WINAPI
 ChangeMenuA(
     HMENU hMenu,
     UINT cmd,
@@ -5170,3 +5296,6 @@ ChangeMenuA(
 }
 
 
+
+
+