Fix the USER32 DLL initialization and cleanup routines to prevent memory/resource...
[reactos.git] / reactos / lib / user32 / windows / menu.c
index 593f131..65d1749 100644 (file)
@@ -21,7 +21,7 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-/* $Id: menu.c,v 1.76 2004/12/13 15:38:18 navaraf Exp $
+/* $Id$
  *
  * PROJECT:         ReactOS user32.dll
  * FILE:            lib/user32/windows/menu.c
 
 /* INCLUDES ******************************************************************/
 
-#include "user32.h"
-#include <ctype.h>
-#include <string.h>
-#include <draw.h>
-#include <window.h>
-#include <strpool.h>
-#include <user32/callback.h>
-#include "user32/regcontrol.h"
-#include "../controls/controls.h"
-
+#include <user32.h>
 #define NDEBUG
 #include <debug.h>
 
@@ -71,7 +62,7 @@
        (0 != ((MenuInfo)->Flags & MF_POPUP) && 0 != ((MenuInfo)->Flags & MF_SYSMENU))
 
 #define IS_MAGIC_ITEM(Bmp)   ((int) Bmp <12)
-  
+
 #define MENU_BAR_ITEMS_SPACE (12)
 #define SEPARATOR_HEIGHT (5)
 #define MENU_TAB_SPACE (8)
@@ -126,8 +117,8 @@ const struct builtin_class_descr POPUPMENU_builtin_class =
 
 /* 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 
+/* 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.
  */
 
@@ -164,7 +155,7 @@ MenuGetRosMenuInfo(PROSMENUINFO MenuInfo, HMENU Menu)
 {
   MenuInfo->cbSize = sizeof(ROSMENUINFO);
   MenuInfo->fMask = MIM_BACKGROUND | MIM_HELPID | MIM_MAXHEIGHT | MIM_MENUDATA | MIM_STYLE;
-  
+
   return NtUserMenuInfo(Menu, MenuInfo, FALSE);
 }
 
@@ -178,7 +169,7 @@ MenuSetRosMenuInfo(PROSMENUINFO MenuInfo)
 {
   MenuInfo->cbSize = sizeof(ROSMENUINFO);
   MenuInfo->fMask = MIM_BACKGROUND | MIM_HELPID | MIM_MAXHEIGHT | MIM_MENUDATA | MIM_STYLE;
-  
+
   return NtUserMenuInfo(MenuInfo->Self, MenuInfo, TRUE);
 }
 
@@ -255,7 +246,7 @@ MenuSetRosMenuItemInfo(HMENU Menu, UINT Index, PROSMENUITEMINFO ItemInfo)
   ItemInfo->fMask = MIIM_BITMAP | MIIM_CHECKMARKS | MIIM_DATA | MIIM_FTYPE
                     | MIIM_ID | MIIM_STATE | MIIM_STRING | MIIM_SUBMENU | MIIM_TYPE;
 
-  
+
   Ret = NtUserMenuItemInfo(Menu, Index, TRUE, ItemInfo, TRUE);
 
   return Ret;
@@ -1063,7 +1054,7 @@ BOOL
 MenuInit(VOID)
 {
   NONCLIENTMETRICSW ncm;
-  
+
   /* get the menu font */
   if(!hMenuFont || !hMenuFontBold)
   {
@@ -1073,19 +1064,21 @@ MenuInit(VOID)
       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;
     }
   }
@@ -1094,6 +1087,24 @@ MenuInit(VOID)
 }
 
 
+VOID
+MenuCleanup(VOID)
+{
+  if (hMenuFont)
+  {
+    DeleteObject(hMenuFont);
+    hMenuFont = NULL;
+  }
+
+  if (hMenuFontBold)
+  {
+    DeleteObject(hMenuFontBold);
+    hMenuFontBold = NULL;
+  }
+}
+
+
+
 /***********************************************************************
  *           MenuCalcItemSize
  *
@@ -1884,46 +1895,56 @@ MenuMoveSelection(HWND WndOwner, PROSMENUINFO MenuInfo, INT Offset)
 {
   INT i;
   ROSMENUITEMINFO ItemInfo;
+  INT OrigPos;
 
   DPRINT("hwnd=%x menu=%x off=0x%04x\n", WndOwner, MenuInfo, Offset);
 
+  /* Prevent looping */
+  if (0 == MenuInfo->MenuItemCount || 0 == Offset)
+    return;
+  else if (Offset < -1)
+    Offset = -1;
+  else if (Offset > 1)
+    Offset = 1;
+
   MenuInitRosMenuItemInfo(&ItemInfo);
-  if (NO_SELECTED_ITEM != MenuInfo->FocusedItem)
+
+  OrigPos = MenuInfo->FocusedItem;
+  if (OrigPos == NO_SELECTED_ITEM) /* NO_SELECTED_ITEM is not -1 ! */
     {
-      if (1 == MenuInfo->MenuItemCount)
+       OrigPos = 0;
+       i = -1;
+    }
+  else
+    {
+      i = MenuInfo->FocusedItem;
+    }
+
+  do
+    {
+      /* Step */
+      i += Offset;
+      /* Clip and wrap around */
+      if (i < 0)
         {
-          MenuCleanupRosMenuItemInfo(&ItemInfo);
-          return;
+          i = MenuInfo->MenuItemCount - 1;
         }
-      else
+      else if (i >= MenuInfo->MenuItemCount)
         {
-          for (i = MenuInfo->FocusedItem + Offset;
-               0 <= i && i < MenuInfo->MenuItemCount;
-               i += Offset)
-            {
-              if (MenuGetRosMenuItemInfo(MenuInfo->Self, i, &ItemInfo) &&
-                  0 == (ItemInfo.fType & MF_SEPARATOR))
-                {
-                  MenuSelectItem(WndOwner, MenuInfo, i, TRUE, NULL);
-                  MenuCleanupRosMenuItemInfo(&ItemInfo);
-                  return;
-                }
-            }
+          i = 0;
         }
-    }
-
-  for (i = (0 < Offset) ? 0 : MenuInfo->MenuItemCount - 1;
-       0 <= i && i < MenuInfo->MenuItemCount; i += Offset)
-    {
+      /* If this is a good candidate; */
       if (MenuGetRosMenuItemInfo(MenuInfo->Self, i, &ItemInfo) &&
-          0 == (ItemInfo.fType & MF_SEPARATOR))
+          0 == (ItemInfo.fType & MF_SEPARATOR) &&
+          0 == (ItemInfo.fState & (MFS_DISABLED | MFS_GRAYED)) )
         {
           MenuSelectItem(WndOwner, MenuInfo, i, TRUE, NULL);
           MenuCleanupRosMenuItemInfo(&ItemInfo);
           return;
         }
-    }
+    } while (i != OrigPos);
 
+  /* Not found */
   MenuCleanupRosMenuItemInfo(&ItemInfo);
 }
 
@@ -1958,7 +1979,7 @@ MenuInitSysMenuPopup(HMENU Menu, DWORD Style, DWORD ClsStyle, LONG HitTest )
     {
       EnableMenuItem(Menu, SC_CLOSE, MF_GRAYED);
     }
-  
+
   /* Set default menu item */
   if(Style & WS_MINIMIZE)
   {
@@ -1978,7 +1999,7 @@ MenuInitSysMenuPopup(HMENU Menu, DWORD Style, DWORD ClsStyle, LONG HitTest )
   #if 0
   mii.cbSize = sizeof(MENUITEMINFOW);
   mii.fMask = MIIM_STATE;
-  if((DefItem != SC_CLOSE) && GetMenuItemInfoW(Menu, DefItem, FALSE, &mii) && 
+  if((DefItem != SC_CLOSE) && GetMenuItemInfoW(Menu, DefItem, FALSE, &mii) &&
      (mii.fState & (MFS_GRAYED | MFS_DISABLED)))
   {
     DefItem = SC_CLOSE;
@@ -2276,15 +2297,19 @@ MenuButtonDown(MTRACKER* Mt, HMENU PtMenu, UINT Flags)
           return FALSE;
         }
 
-      if (MenuInfo.FocusedItem != Index)
-        {
-          MenuSwitchTracking(Mt, &MenuInfo, Index);
-        }
+      if (!(Item.fType & MF_SEPARATOR) &&
+          !(Item.fState & (MFS_DISABLED | MFS_GRAYED)) )
+       {
+          if (MenuInfo.FocusedItem != Index)
+            {
+              MenuSwitchTracking(Mt, &MenuInfo, Index);
+            }
 
-      /* If the popup menu is not already "popped" */
-      if (0 == (Item.fState & MF_MOUSESELECT))
-        {
-          Mt->CurrentMenu = MenuShowSubPopup(Mt->OwnerWnd, &MenuInfo, FALSE, Flags);
+          /* If the popup menu is not already "popped" */
+          if (0 == (Item.fState & MF_MOUSESELECT))
+            {
+              Mt->CurrentMenu = MenuShowSubPopup(Mt->OwnerWnd, &MenuInfo, FALSE, Flags);
+            }
         }
 
       MenuCleanupRosMenuItemInfo(&Item);
@@ -2422,6 +2447,7 @@ MenuMouseMove(MTRACKER *Mt, HMENU PtMenu, UINT Flags)
 {
   UINT Index;
   ROSMENUINFO MenuInfo;
+  ROSMENUITEMINFO ItemInfo;
 
   if (NULL != PtMenu)
     {
@@ -2454,8 +2480,15 @@ MenuMouseMove(MTRACKER *Mt, HMENU PtMenu, UINT Flags)
     }
   else if (MenuInfo.FocusedItem != Index)
     {
-      MenuSwitchTracking(Mt, &MenuInfo, Index);
-      Mt->CurrentMenu = MenuShowSubPopup(Mt->OwnerWnd, &MenuInfo, FALSE, Flags);
+       MenuInitRosMenuItemInfo(&ItemInfo);
+       if (MenuGetRosMenuItemInfo(MenuInfo.Self, Index, &ItemInfo) &&
+           !(ItemInfo.fType & MF_SEPARATOR) &&
+           !(ItemInfo.fState & (MFS_DISABLED | MFS_GRAYED)) )
+       {
+           MenuSwitchTracking(Mt, &MenuInfo, Index);
+           Mt->CurrentMenu = MenuShowSubPopup(Mt->OwnerWnd, &MenuInfo, FALSE, Flags);
+       }
+       MenuCleanupRosMenuItemInfo(&ItemInfo);
     }
 
   return TRUE;
@@ -3262,9 +3295,13 @@ MenuTrackMenu(HMENU Menu, UINT Flags, INT x, INT y,
               case WM_SYSKEYDOWN:
                 switch (Msg.wParam)
                   {
+                    DbgPrint("Menu.c WM_SYSKEYDOWN wPram %d\n",Msg.wParam);
                     case VK_MENU:
                       fEndMenu = TRUE;
                       break;
+                    case VK_LMENU:
+                      fEndMenu = TRUE;
+                      break;
                   }
                 break;  /* WM_SYSKEYDOWN */
 
@@ -3331,7 +3368,7 @@ MenuTrackMenu(HMENU Menu, UINT Flags, INT x, INT y,
           Mt.TrackFlags &= ~TF_SKIPREMOVE;
         }
     }
-  
+
   NtUserSetGUIThreadHandle(MSQ_STATE_MENUOWNER, NULL);
   SetCapture(NULL);  /* release the capture */
 
@@ -3431,7 +3468,7 @@ AppendMenuA(HMENU hMenu,
            UINT_PTR uIDNewItem,
            LPCSTR lpNewItem)
 {
-  return(InsertMenuA(hMenu, -1, uFlags | MF_BYPOSITION, uIDNewItem, 
+  return(InsertMenuA(hMenu, -1, uFlags | MF_BYPOSITION, uIDNewItem,
                     lpNewItem));
 }
 
@@ -3445,7 +3482,7 @@ AppendMenuW(HMENU hMenu,
            UINT_PTR uIDNewItem,
            LPCWSTR lpNewItem)
 {
-  return(InsertMenuW(hMenu, -1, uFlags | MF_BYPOSITION, uIDNewItem, 
+  return(InsertMenuW(hMenu, -1, uFlags | MF_BYPOSITION, uIDNewItem,
                     lpNewItem));
 }
 
@@ -3463,7 +3500,7 @@ CheckMenuItem(HMENU hmenu,
 
 
 /*
- * @unimplemented
+ * @implemented
  */
 BOOL STDCALL
 CheckMenuRadioItem(HMENU hmenu,
@@ -3472,8 +3509,43 @@ CheckMenuRadioItem(HMENU hmenu,
                   UINT idCheck,
                   UINT uFlags)
 {
+  ROSMENUINFO mi;
+  PROSMENUITEMINFO Items;
+  int i;
+  BOOL ret = FALSE;
+
+  mi.cbSize = sizeof(MENUINFO);
+
   UNIMPLEMENTED;
-  return FALSE;
+
+  if(idFirst > idLast) return ret;
+
+  if(!NtUserMenuInfo(hmenu, &mi, FALSE)) return ret;
+
+  if(MenuGetAllRosMenuItemInfo(mi.Self, &Items) <= 0) return ret;
+
+  for (i = 0 ; i < mi.MenuItemCount; i++)
+    {
+      if (0 != (Items[i].fType & MF_MENUBARBREAK)) break;
+      if ( i >= idFirst && i <= idLast )
+      {
+         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;
 }
 
 
@@ -3522,14 +3594,12 @@ DestroyMenu(HMENU hMenu)
 
 
 /*
- * @unimplemented
+ * @implemented
  */
 BOOL STDCALL
 DrawMenuBar(HWND hWnd)
 {
-  UNIMPLEMENTED
-  /* FIXME - return NtUserCallHwndLock(hWnd, 0x55); */
-  return FALSE;
+  return (BOOL)NtUserCallHwndLock(hWnd, HWNDLOCK_ROUTINE_DRAWMENUBAR);
 }
 
 
@@ -3589,7 +3659,7 @@ GetMenuBarInfo(HWND hwnd,
 LONG STDCALL
 GetMenuCheckMarkDimensions(VOID)
 {
-  return(MAKELONG(GetSystemMetrics(SM_CXMENUCHECK), 
+  return(MAKELONG(GetSystemMetrics(SM_CXMENUCHECK),
                  GetSystemMetrics(SM_CYMENUCHECK)));
 }
 
@@ -3615,16 +3685,16 @@ GetMenuInfo(HMENU hmenu,
 {
   ROSMENUINFO mi;
   BOOL res = FALSE;
-  
+
   if(!lpcmi || (lpcmi->cbSize != sizeof(MENUINFO)))
     return FALSE;
-  
+
   RtlZeroMemory(&mi, sizeof(MENUINFO));
   mi.cbSize = sizeof(MENUINFO);
   mi.fMask = lpcmi->fMask;
-  
+
   res = NtUserMenuInfo(hmenu, &mi, FALSE);
-  
+
   memcpy(lpcmi, &mi, sizeof(MENUINFO));
   return res;
 }
@@ -3650,15 +3720,15 @@ GetMenuItemID(HMENU hMenu,
              int nPos)
 {
   ROSMENUITEMINFO mii;
-  
+
   mii.cbSize = sizeof(MENUITEMINFOW);
   mii.fMask = MIIM_ID | MIIM_SUBMENU;
-  
+
   if (! NtUserMenuItemInfo(hMenu, nPos, MF_BYPOSITION, &mii, FALSE))
     {
       return -1;
     }
-  
+
   if (NULL != mii.hSubMenu)
     {
       return -1;
@@ -3667,7 +3737,7 @@ GetMenuItemID(HMENU hMenu,
     {
       return -1;
     }
-  
+
   return mii.wID;
 }
 
@@ -3708,7 +3778,7 @@ GetMenuItemInfoA(
       if (miiW.dwTypeData == NULL)
          return FALSE;
    }
-   
+
    if (!NtUserMenuItemInfo(Menu, Item, ByPosition, (PROSMENUITEMINFO)&miiW, FALSE))
    {
       HeapFree(GetProcessHeap(), 0, miiW.dwTypeData);
@@ -3726,8 +3796,11 @@ GetMenuItemInfoA(
    }
 
    RtlCopyMemory(mii, &miiW, miiW.cbSize);
-   mii->dwTypeData = AnsiBuffer;
-
+   if (AnsiBuffer)
+   {
+        mii->dwTypeData = AnsiBuffer;
+        mii->cch = strlen(AnsiBuffer);
+   }
    return TRUE;
 }
 
@@ -3747,7 +3820,7 @@ GetMenuItemInfoW(
 
 
 /*
- * @unimplemented
+ * @implemented
  */
 BOOL STDCALL
 GetMenuItemRect(HWND hWnd,
@@ -3755,8 +3828,7 @@ GetMenuItemRect(HWND hWnd,
                UINT uItem,
                LPRECT lprcItem)
 {
-  UNIMPLEMENTED;
-  return(FALSE);
+  return NtUserGetMenuItemRect( hWnd, hMenu, uItem, lprcItem);
 }
 
 
@@ -3776,7 +3848,7 @@ GetMenuState(
   mii.cbSize = sizeof(MENUITEMINFOW);
   mii.fMask = MIIM_STATE | MIIM_TYPE | MIIM_SUBMENU;
   mii.dwTypeData = NULL;
-  
+
   SetLastError(0);
   if(NtUserMenuItemInfo(hMenu, uId, uFlags, &mii, FALSE))
     {
@@ -3788,24 +3860,24 @@ GetMenuState(
               return (UINT) -1;
             }
           nSubItems = MenuInfo.MenuItemCount;
-      
+
           /* FIXME - ported from wine, does that work (0xff)? */
           if(GetLastError() != ERROR_INVALID_MENU_HANDLE)
             return (nSubItems << 8) | ((mii.fState | mii.fType) & 0xff);
 
           return (UINT)-1; /* Invalid submenu */
         }
-    
+
       /* FIXME - ported from wine, does that work? */
       return (mii.fType | mii.fState);
     }
-  
+
   return (UINT)-1;
 }
 
 
 /*
- * @unimplemented
+ * @implemented
  */
 int
 STDCALL
@@ -3816,13 +3888,22 @@ GetMenuStringA(
   int nMaxCount,
   UINT uFlag)
 {
-  UNIMPLEMENTED;
-  return 0;
+  MENUITEMINFOA mii;
+  mii.dwTypeData = lpString;
+  mii.fMask = MIIM_STRING;
+  mii.fType = MF_STRING;
+  mii.cbSize = sizeof(MENUITEMINFOA);
+  mii.cch = nMaxCount;
+
+  if(!(GetMenuItemInfoA( hMenu, uIDItem, (BOOL)(MF_BYPOSITION & uFlag),&mii)))
+     return 0;
+  else
+     return mii.cch;
 }
 
 
 /*
- * @unimplemented
+ * @implemented
  */
 int
 STDCALL
@@ -3833,8 +3914,16 @@ GetMenuStringW(
   int nMaxCount,
   UINT uFlag)
 {
-  UNIMPLEMENTED;
-  return 0;
+  MENUITEMINFOW miiW;
+  miiW.dwTypeData = lpString;
+  miiW.fMask = MIIM_STRING;
+  miiW.cbSize = sizeof(MENUITEMINFOW);
+  miiW.cch = nMaxCount;
+
+  if(!(GetMenuItemInfoW( hMenu, uIDItem, (BOOL)(MF_BYPOSITION & uFlag),&miiW)))
+     return 0;
+  else
+     return miiW.cch;
 }
 
 
@@ -3909,7 +3998,7 @@ InsertMenuA(
   mii.fMask = MIIM_FTYPE | MIIM_STRING | MIIM_STATE;
   mii.fType = 0;
   mii.fState = MFS_ENABLED;
-  
+
   if(uFlags & MF_BITMAP)
   {
     mii.fType |= MFT_BITMAP;
@@ -3928,7 +4017,7 @@ InsertMenuA(
     mii.dwTypeData = (LPSTR)lpNewItem;
     mii.cch = (NULL == lpNewItem ? 0 : strlen(lpNewItem));
   }
-  
+
   if(uFlags & MF_RIGHTJUSTIFY)
   {
     mii.fType |= MFT_RIGHTJUSTIFY;
@@ -3949,7 +4038,7 @@ InsertMenuA(
   {
     mii.fState |= MFS_GRAYED;
   }
-  
+
   if(uFlags & MF_POPUP)
   {
     mii.fType |= MF_POPUP;
@@ -3961,7 +4050,7 @@ InsertMenuA(
     mii.fMask |= MIIM_ID;
     mii.wID = (UINT)uIDNewItem;
   }
-  return InsertMenuItemA(hMenu, uPosition, (BOOL)!(MF_BYPOSITION & uFlags), &mii);
+  return InsertMenuItemA(hMenu, uPosition, (BOOL)((MF_BYPOSITION & uFlags) > 0), &mii);
 }
 
 
@@ -3982,13 +4071,13 @@ InsertMenuItemA(
   BOOL CleanHeap = FALSE;
   NTSTATUS Status;
 
-  if((lpmii->cbSize == sizeof(MENUITEMINFOA)) || 
+  if((lpmii->cbSize == sizeof(MENUITEMINFOA)) ||
      (lpmii->cbSize == sizeof(MENUITEMINFOA) - sizeof(HBITMAP)))
   {
     RtlMoveMemory ( &mi, lpmii, lpmii->cbSize );
 
     /* copy the text string */
-    if((mi.fMask & (MIIM_TYPE | MIIM_STRING)) && 
+    if((mi.fMask & (MIIM_TYPE | MIIM_STRING)) &&
       (MENU_ITEM_TYPE(mi.fType) == MF_STRING) && mi.dwTypeData)
     {
       Status = RtlCreateUnicodeStringFromAsciiz(&MenuText, (LPSTR)mi.dwTypeData);
@@ -4026,17 +4115,17 @@ InsertMenuItemW(
   BOOL res = FALSE;
   mi.hbmpItem = (HBITMAP)0;
 
-  // while we could just pass 'lpmii' to win32k, we make a copy so that
-  // if a bad user passes bad data, we crash his process instead of the
-  // entire kernel
+  /* while we could just pass 'lpmii' to win32k, we make a copy so that
+     if a bad user passes bad data, we crash his process instead of the
+     entire kernel */
 
-  if((lpmii->cbSize == sizeof(MENUITEMINFOW)) || 
+  if((lpmii->cbSize == sizeof(MENUITEMINFOW)) ||
      (lpmii->cbSize == sizeof(MENUITEMINFOW) - sizeof(HBITMAP)))
   {
     memcpy(&mi, lpmii, lpmii->cbSize);
-    
+
     /* copy the text string */
-    if((mi.fMask & (MIIM_TYPE | MIIM_STRING)) && 
+    if((mi.fMask & (MIIM_TYPE | MIIM_STRING)) &&
       (MENU_ITEM_TYPE(mi.fType) == MF_STRING) &&
       mi.dwTypeData != NULL)
     {
@@ -4044,7 +4133,7 @@ InsertMenuItemW(
       mi.dwTypeData = MenuText.Buffer;
       mi.cch = MenuText.Length / sizeof(WCHAR);
     };
-    
+
     res = NtUserInsertMenuItem(hMenu, uItem, fByPosition, &mi);
   }
   return res;
@@ -4087,7 +4176,7 @@ InsertMenuW(
     mii.dwTypeData = (LPWSTR)lpNewItem;
     mii.cch = (NULL == lpNewItem ? 0 : wcslen(lpNewItem));
   }
-  
+
   if(uFlags & MF_RIGHTJUSTIFY)
   {
     mii.fType |= MFT_RIGHTJUSTIFY;
@@ -4108,7 +4197,7 @@ InsertMenuW(
   {
     mii.fState |= MFS_GRAYED;
   }
-  
+
   if(uFlags & MF_POPUP)
   {
     mii.fType |= MF_POPUP;
@@ -4120,7 +4209,7 @@ InsertMenuW(
     mii.fMask |= MIIM_ID;
     mii.wID = (UINT)uIDNewItem;
   }
-  return InsertMenuItemW(hMenu, uPosition, (BOOL)!(MF_BYPOSITION & uFlags), &mii);
+  return InsertMenuItemW(hMenu, uPosition, (BOOL)((MF_BYPOSITION & uFlags) > 0), &mii);
 }
 
 
@@ -4237,7 +4326,7 @@ MenuItemFromPoint(
 
 
 /*
- * @unimplemented
+ * @implemented
  */
 BOOL
 STDCALL
@@ -4248,13 +4337,94 @@ ModifyMenuA(
   UINT_PTR uIDNewItem,
   LPCSTR lpNewItem)
 {
+  MENUITEMINFOA mii;
+  memset( &mii, 0, sizeof(mii) );
+  mii.cbSize = sizeof(MENUITEMINFOA);
+  mii.fMask = MIIM_FTYPE | MIIM_STRING | MIIM_STATE;
+  mii.fType = 0;
+  mii.fState = MFS_ENABLED;
+
   UNIMPLEMENTED;
-  return FALSE;
+
+  if(!GetMenuItemInfoA( hMnu,
+                        uPosition,
+                       (BOOL)(MF_BYPOSITION & uFlags),
+                        &mii)) return FALSE;
+
+  if(uFlags & MF_BITMAP)
+  {
+    mii.fType |= MFT_BITMAP;
+    mii.fMask |= MIIM_BITMAP;
+    mii.hbmpItem = (HBITMAP) lpNewItem;
+  }
+  else if(uFlags & MF_OWNERDRAW)
+  {
+    mii.fType |= MFT_OWNERDRAW;
+    mii.fMask |= MIIM_DATA;
+    mii.dwItemData = (DWORD) lpNewItem;
+  }
+  else /* Default action MF_STRING. */
+  {
+    if(mii.dwTypeData != NULL)
+    {
+      HeapFree(GetProcessHeap(),0, mii.dwTypeData);
+    }
+    /* Item beginning with a backspace is a help item */
+    if (*lpNewItem == '\b')
+    {
+       mii.fType |= MF_HELP;
+       lpNewItem++;
+    }
+    mii.fMask |= MIIM_TYPE;
+    mii.dwTypeData = (LPSTR)lpNewItem;
+    mii.cch = (NULL == lpNewItem ? 0 : strlen(lpNewItem));
+  }
+
+  if(uFlags & MF_RIGHTJUSTIFY)
+  {
+    mii.fType |= MFT_RIGHTJUSTIFY;
+  }
+  if(uFlags & MF_MENUBREAK)
+  {
+    mii.fType |= MFT_MENUBREAK;
+  }
+  if(uFlags & MF_MENUBARBREAK)
+  {
+    mii.fType |= MFT_MENUBARBREAK;
+  }
+  if(uFlags & MF_DISABLED)
+  {
+    mii.fState |= MFS_DISABLED;
+  }
+  if(uFlags & MF_GRAYED)
+  {
+    mii.fState |= MFS_GRAYED;
+  }
+
+  if ((mii.fType & MF_POPUP) && (uFlags & MF_POPUP) && (mii.hSubMenu != (HMENU)uIDNewItem))
+    NtUserDestroyMenu( mii.hSubMenu );   /* ModifyMenu() spec */
+
+  if(uFlags & MF_POPUP)
+  {
+    mii.fType |= MF_POPUP;
+    mii.fMask |= MIIM_SUBMENU;
+    mii.hSubMenu = (HMENU)uIDNewItem;
+  }
+  else
+  {
+    mii.fMask |= MIIM_ID;
+    mii.wID = (UINT)uIDNewItem;
+  }
+
+  return SetMenuItemInfoA( hMnu,
+                           uPosition,
+                          (BOOL)(MF_BYPOSITION & uFlags),
+                           &mii);
 }
 
 
 /*
- * @unimplemented
+ * @implemented
  */
 BOOL
 STDCALL
@@ -4265,8 +4435,88 @@ ModifyMenuW(
   UINT_PTR uIDNewItem,
   LPCWSTR lpNewItem)
 {
+  MENUITEMINFOW mii;
+  memset ( &mii, 0, sizeof(mii) );
+  mii.cbSize = sizeof(MENUITEMINFOW);
+  mii.fMask = MIIM_FTYPE | MIIM_STRING | MIIM_STATE;
+  mii.fState = MFS_ENABLED;
+
   UNIMPLEMENTED;
-  return FALSE;
+
+  if(!NtUserMenuItemInfo( hMnu,
+                          uPosition,
+                         (BOOL)(MF_BYPOSITION & uFlags),
+                         (PROSMENUITEMINFO) &mii,
+                          FALSE)) return FALSE;
+
+  if(uFlags & MF_BITMAP)
+  {
+    mii.fType |= MFT_BITMAP;
+    mii.fMask |= MIIM_BITMAP;
+    mii.hbmpItem = (HBITMAP) lpNewItem;
+  }
+  else if(uFlags & MF_OWNERDRAW)
+  {
+    mii.fType |= MFT_OWNERDRAW;
+    mii.fMask |= MIIM_DATA;
+    mii.dwItemData = (DWORD) lpNewItem;
+  }
+  else
+  {
+    /*if(mii.dwTypeData != NULL)
+    {
+      HeapFree(GetProcessHeap(),0, mii.dwTypeData);
+    }*/
+    if (*lpNewItem == '\b')
+    {
+       mii.fType |= MF_HELP;
+       lpNewItem++;
+    }
+    mii.fMask |= MIIM_TYPE;
+    mii.dwTypeData = (LPWSTR)lpNewItem;
+    mii.cch = (NULL == lpNewItem ? 0 : wcslen(lpNewItem));
+  }
+
+  if(uFlags & MF_RIGHTJUSTIFY)
+  {
+    mii.fType |= MFT_RIGHTJUSTIFY;
+  }
+  if(uFlags & MF_MENUBREAK)
+  {
+    mii.fType |= MFT_MENUBREAK;
+  }
+  if(uFlags & MF_MENUBARBREAK)
+  {
+    mii.fType |= MFT_MENUBARBREAK;
+  }
+  if(uFlags & MF_DISABLED)
+  {
+    mii.fState |= MFS_DISABLED;
+  }
+  if(uFlags & MF_GRAYED)
+  {
+    mii.fState |= MFS_GRAYED;
+  }
+
+  if ((mii.fType & MF_POPUP) && (uFlags & MF_POPUP) && (mii.hSubMenu != (HMENU)uIDNewItem))
+    NtUserDestroyMenu( mii.hSubMenu );
+
+  if(uFlags & MF_POPUP)
+  {
+    mii.fType |= MF_POPUP;
+    mii.fMask |= MIIM_SUBMENU;
+    mii.hSubMenu = (HMENU)uIDNewItem;
+  }
+  else
+  {
+    mii.fMask |= MIIM_ID;
+    mii.wID = (UINT)uIDNewItem;
+  }
+
+  return SetMenuItemInfoW( hMnu,
+                           uPosition,
+                           (BOOL)(MF_BYPOSITION & uFlags),
+                           &mii);
 }
 
 
@@ -4322,14 +4572,14 @@ SetMenuInfo(
   BOOL res = FALSE;
   if(lpcmi->cbSize != sizeof(MENUINFO))
     return res;
-    
+
   memcpy(&mi, lpcmi, sizeof(MENUINFO));
   return NtUserMenuInfo(hmenu, &mi, TRUE);
 }
 
 
 /*
- * @unimplemented
+ * @implemented
  */
 BOOL
 STDCALL
@@ -4340,13 +4590,28 @@ SetMenuItemBitmaps(
   HBITMAP hBitmapUnchecked,
   HBITMAP hBitmapChecked)
 {
-  UNIMPLEMENTED;
-  return FALSE;
+  ROSMENUITEMINFO uItem;
+
+  if(!(NtUserMenuItemInfo(hMenu, uPosition, 
+                 (BOOL)(MF_BYPOSITION & uFlags), &uItem, FALSE))) return FALSE;
+
+  if (!hBitmapChecked && !hBitmapUnchecked)
+  {
+    uItem.fState &= ~MF_USECHECKBITMAPS;
+  }
+  else  /* Install new bitmaps */
+  {
+    uItem.hbmpChecked = hBitmapChecked;
+    uItem.hbmpUnchecked = hBitmapUnchecked;
+    uItem.fState |= MF_USECHECKBITMAPS;
+  }
+ return NtUserMenuItemInfo(hMenu, uPosition,
+                                 (BOOL)(MF_BYPOSITION & uFlags), &uItem, TRUE);
 }
 
 
 /*
- * @unimplemented
+ * @implemented
  */
 BOOL
 STDCALL
@@ -4389,7 +4654,7 @@ SetMenuItemInfoA(
 
 
 /*
- * @unimplemented
+ * @implemented
  */
 BOOL
 STDCALL
@@ -4402,7 +4667,10 @@ SetMenuItemInfoW(
   MENUITEMINFOW MenuItemInfoW;
 
   RtlCopyMemory(&MenuItemInfoW, lpmii, min(lpmii->cbSize, sizeof(MENUITEMINFOW)));
-  MenuItemInfoW.cch = wcslen(MenuItemInfoW.dwTypeData);
+  if (0 != (MenuItemInfoW.fMask & MIIM_STRING))
+  {
+    MenuItemInfoW.cch = wcslen(MenuItemInfoW.dwTypeData);
+  }
 
   return NtUserMenuItemInfo(hMenu, uItem, fByPosition,
                             (PROSMENUITEMINFO)&MenuItemInfoW, TRUE);
@@ -4414,7 +4682,7 @@ SetMenuItemInfoW(
 BOOL
 STDCALL
 SetSystemMenu (
-  HWND hwnd, 
+  HWND hwnd,
   HMENU hMenu)
 {
   if(!hwnd)
@@ -4506,7 +4774,7 @@ GetMenuContextHelpId(HMENU hmenu)
   ROSMENUINFO mi;
   mi.cbSize = sizeof(ROSMENUINFO);
   mi.fMask = MIM_HELPID;
-  
+
   if(NtUserMenuInfo(hmenu, &mi, FALSE))
   {
     return mi.dwContextHelpID;
@@ -4568,7 +4836,7 @@ ChangeMenuW(
     {
         case MF_APPEND :
             return AppendMenuW(hMenu, flags &~ MF_APPEND, cmdInsert, lpszNewItem);
-        
+
         case MF_DELETE :
             return DeleteMenu(hMenu, cmd, flags &~ MF_DELETE);
 
@@ -4606,7 +4874,7 @@ ChangeMenuA(
     {
         case MF_APPEND :
             return AppendMenuA(hMenu, flags &~ MF_APPEND, cmdInsert, lpszNewItem);
-        
+
         case MF_DELETE :
             return DeleteMenu(hMenu, cmd, flags &~ MF_DELETE);