Fix the USER32 DLL initialization and cleanup routines to prevent memory/resource...
[reactos.git] / reactos / lib / user32 / windows / menu.c
index bb15617..65d1749 100644 (file)
 
 /* 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>
 
@@ -1086,6 +1077,8 @@ MenuInit(VOID)
     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
  *
@@ -3284,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 */
 
@@ -3485,7 +3500,7 @@ CheckMenuItem(HMENU hmenu,
 
 
 /*
- * @unimplemented
+ * @implemented
  */
 BOOL STDCALL
 CheckMenuRadioItem(HMENU hmenu,
@@ -3494,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;
 }
 
 
@@ -3544,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);
 }
 
 
@@ -3748,8 +3796,11 @@ GetMenuItemInfoA(
    }
 
    RtlCopyMemory(mii, &miiW, miiW.cbSize);
-   mii->dwTypeData = AnsiBuffer;
-
+   if (AnsiBuffer)
+   {
+        mii->dwTypeData = AnsiBuffer;
+        mii->cch = strlen(AnsiBuffer);
+   }
    return TRUE;
 }
 
@@ -3769,7 +3820,7 @@ GetMenuItemInfoW(
 
 
 /*
- * @unimplemented
+ * @implemented
  */
 BOOL STDCALL
 GetMenuItemRect(HWND hWnd,
@@ -3777,8 +3828,7 @@ GetMenuItemRect(HWND hWnd,
                UINT uItem,
                LPRECT lprcItem)
 {
-  UNIMPLEMENTED;
-  return(FALSE);
+  return NtUserGetMenuItemRect( hWnd, hMenu, uItem, lprcItem);
 }
 
 
@@ -3827,7 +3877,7 @@ GetMenuState(
 
 
 /*
- * @unimplemented
+ * @implemented
  */
 int
 STDCALL
@@ -3838,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
@@ -3855,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;
 }
 
 
@@ -3983,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);
 }
 
 
@@ -4142,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);
 }
 
 
@@ -4259,7 +4326,7 @@ MenuItemFromPoint(
 
 
 /*
- * @unimplemented
+ * @implemented
  */
 BOOL
 STDCALL
@@ -4270,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
@@ -4287,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);
 }
 
 
@@ -4351,7 +4579,7 @@ SetMenuInfo(
 
 
 /*
- * @unimplemented
+ * @implemented
  */
 BOOL
 STDCALL
@@ -4362,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
@@ -4411,7 +4654,7 @@ SetMenuItemInfoA(
 
 
 /*
- * @unimplemented
+ * @implemented
  */
 BOOL
 STDCALL
@@ -4424,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);