diff --git a/reactos/win32ss/include/ntuser.h b/reactos/win32ss/include/ntuser.h index 79a8c287b2f..8e6b03e847d 100644 --- a/reactos/win32ss/include/ntuser.h +++ b/reactos/win32ss/include/ntuser.h @@ -5,6 +5,7 @@ typedef struct _PROCESSINFO *PPROCESSINFO; typedef struct _THREADINFO *PTHREADINFO; struct _DESKTOP; struct _WND; +struct tagPOPUPMENU; #define FIRST_USER_HANDLE 0x0020 /* first possible value for low word of user handle */ #define LAST_USER_HANDLE 0xffef /* last possible value for low word of user handle */ @@ -313,7 +314,7 @@ typedef struct tagITEM struct tagMENU* spSubMenu; /* Pop-up menu. */ HANDLE hbmpChecked; HANDLE hbmpUnchecked; - USHORT* lpstr; /* Item text pointer. */ + USHORT* Xlpstr; /* Item text pointer. */ ULONG cch; DWORD_PTR dwItemData; ULONG xItem; /* Item position. left */ @@ -326,6 +327,9 @@ typedef struct tagITEM HBITMAP hbmp; /* bitmap */ INT cxBmp; /* Width Maximum size of the bitmap items in MIIM_BITMAP state */ INT cyBmp; /* Height " */ + //// ReactOS + UNICODE_STRING lpstr; + struct tagITEM *Next; } ITEM, *PITEM; typedef struct tagMENULIST @@ -347,7 +351,7 @@ typedef struct tagMENU { PROCDESKHEAD head; ULONG fFlags; /* [Style flags | Menu flags] */ - INT iItem; /* nPos of selected item, if -1 not selected. */ + INT iItem; /* nPos of selected item, if -1 not selected. AKA focused item */ UINT cAlloced; /* Number of allocated items. Inc's of 8 */ UINT cItems; /* Number of items in the menu */ ULONG cxMenu; /* Width of the whole menu */ @@ -363,8 +367,54 @@ typedef struct tagMENU INT iTop; /* Current scroll position Top */ INT iMaxTop; /* Current scroll position Max Top */ DWORD dwArrowsOn:2; /* Arrows: 0 off, 1 on, 2 to the top, 3 to the bottom. */ + //// ReactOS + LIST_ENTRY ListEntry; + HWND hWnd; /* Window containing the menu */ + BOOL TimeToHide; } MENU, *PMENU; +typedef struct tagPOPUPMENU +{ + ULONG fIsMenuBar:1; + ULONG fHasMenuBar:1; + ULONG fIsSysMenu:1; + ULONG fIsTrackPopup:1; + ULONG fDroppedLeft:1; + ULONG fHierarchyDropped:1; + ULONG fRightButton:1; + ULONG fToggle:1; + ULONG fSynchronous:1; + ULONG fFirstClick:1; + ULONG fDropNextPopup:1; + ULONG fNoNotify:1; + ULONG fAboutToHide:1; + ULONG fShowTimer:1; + ULONG fHideTimer:1; + ULONG fDestroyed:1; + ULONG fDelayedFree:1; + ULONG fFlushDelayedFree:1; + ULONG fFreed:1; + ULONG fInCancel:1; + ULONG fTrackMouseEvent:1; + ULONG fSendUninit:1; + ULONG fRtoL:1; +// ULONG fDesktopMenu:1; + ULONG iDropDir:5; + ULONG fUseMonitorRect:1; + struct _WND *spwndNotify; + struct _WND *spwndPopupMenu; + struct _WND *spwndNextPopup; + struct _WND *spwndPrevPopup; + PMENU spmenu; + PMENU spmenuAlternate; + struct _WND *spwndActivePopup; + struct tagPOPUPMENU *ppopupmenuRoot; + struct tagPOPUPMENU *ppmDelayedFree; + UINT posSelectedItem; + UINT posDropped; +} POPUPMENU, *PPOPUPMENU; + + typedef struct _REGISTER_SYSCLASS { /* This is a reactos specific class used to initialize the @@ -657,6 +707,12 @@ typedef struct _SBWND SBCALC SBCalc; } SBWND, *PSBWND; +typedef struct _MENUWND +{ + WND wnd; + PPOPUPMENU ppopupmenu; +} MENUWND, *PMENUWND; + typedef struct _PFNCLIENT { WNDPROC pfnScrollBarWndProc; @@ -3371,16 +3427,20 @@ typedef struct tagROSMENUINFO DWORD dwContextHelpID; ULONG_PTR dwMenuData; /* ----------- Extra ----------- */ + ULONG fFlags; /* Menu flags (MF_POPUP, MF_SYSMENU) */ + UINT iItem; /* Currently focused item */ + UINT cItems; /* Number of items in the menu */ + WORD cxMenu; /* Width of the whole menu */ + WORD cyMenu; /* Height of the whole menu */ + ULONG cxTextAlign; + PWND spwndNotify; /* window receiving the messages for ownerdraw */ + INT iTop; + INT iMaxTop; + DWORD dwArrowsOn:2; + HMENU Self; /* Handle of this menu */ - WORD Flags; /* Menu flags (MF_POPUP, MF_SYSMENU) */ - UINT FocusedItem; /* Currently focused item */ - UINT MenuItemCount; /* Number of items in the menu */ HWND Wnd; /* Window containing the menu */ - WORD Width; /* Width of the whole menu */ - WORD Height; /* Height of the whole menu */ - HWND WndOwner; /* window receiving the messages for ownerdraw */ - BOOL TimeToHide; /* Request hiding when receiving a second click in the top-level menu item */ - SIZE maxBmpSize; /* Maximum size of the bitmap items in MIIM_BITMAP state */ + BOOL TimeToHide; /* Request hiding when receiving a second click in the top-level menu item */ } ROSMENUINFO, *PROSMENUINFO; BOOL @@ -3410,6 +3470,7 @@ typedef struct tagROSMENUITEMINFO RECT Rect; /* Item area (relative to menu window) */ UINT dxTab; /* X position of text after Tab */ LPWSTR lpstr; /* Copy of the text pointer in MenuItem->Text */ + SIZE maxBmpSize; /* Maximum size of the bitmap items in MIIM_BITMAP state */ } ROSMENUITEMINFO, *PROSMENUITEMINFO; BOOL diff --git a/reactos/win32ss/user/ntuser/accelerator.c b/reactos/win32ss/user/ntuser/accelerator.c index 4c88bfab859..f43ee5e152a 100644 --- a/reactos/win32ss/user/ntuser/accelerator.c +++ b/reactos/win32ss/user/ntuser/accelerator.c @@ -50,8 +50,7 @@ co_IntTranslateAccelerator( UINT Mask = 0, nPos; HWND hWnd; HMENU hMenu, hSubMenu; - PMENU_OBJECT MenuObject, SubMenu; - PMENU_ITEM MenuItem; + PMENU MenuObject; ASSERT_REFS_CO(Window); @@ -101,16 +100,11 @@ co_IntTranslateAccelerator( hMenu = (Window->style & WS_CHILD) ? 0 : (HMENU)Window->IDMenu; hSubMenu = NULL; MenuObject = IntGetMenuObject(hMenu); + nPos = pAccel->cmd; if (MenuObject) { - nPos = IntGetMenuItemByFlag(MenuObject, - pAccel->cmd, - MF_BYCOMMAND, - &SubMenu, - &MenuItem, - NULL); - if (nPos != (UINT) - 1) - hSubMenu = SubMenu->head.h; + if ((MENU_FindItem (&MenuObject, &nPos, MF_BYPOSITION))) + hSubMenu = MenuObject->head.h; else hMenu = NULL; } @@ -120,16 +114,11 @@ co_IntTranslateAccelerator( hMenu = Window->SystemMenu; hSubMenu = hMenu; /* system menu is a popup menu */ MenuObject = IntGetMenuObject(hMenu); + nPos = pAccel->cmd; if (MenuObject) { - nPos = IntGetMenuItemByFlag(MenuObject, - pAccel->cmd, - MF_BYCOMMAND, - &SubMenu, - &MenuItem, - NULL); - if (nPos != (UINT) - 1) - hSubMenu = SubMenu->head.h; + if ((MENU_FindItem (&MenuObject, &nPos, MF_BYPOSITION))) + hSubMenu = MenuObject->head.h; else hMenu = NULL; } diff --git a/reactos/win32ss/user/ntuser/menu.c b/reactos/win32ss/user/ntuser/menu.c index b22f62926ee..8c6c1a3bd94 100644 --- a/reactos/win32ss/user/ntuser/menu.c +++ b/reactos/win32ss/user/ntuser/menu.c @@ -11,6 +11,18 @@ DBG_DEFAULT_CHANNEL(UserMenu); /* INTERNAL ******************************************************************/ +/* maximum allowed depth of any branch in the menu tree. + * This value is slightly larger than in windows (25) to + * stay on the safe side. */ +#define MAXMENUDEPTH 30 + +#define MNS_STYLE_MASK (MNS_NOCHECK|MNS_MODELESS|MNS_DRAGDROP|MNS_AUTODISMISS|MNS_NOTIFYBYPOS|MNS_CHECKORBMP) + +#define MENUITEMINFO_TYPE_MASK \ + (MFT_STRING | MFT_BITMAP | MFT_OWNERDRAW | MFT_SEPARATOR | \ + MFT_MENUBARBREAK | MFT_MENUBREAK | MFT_RADIOCHECK | \ + MFT_RIGHTORDER | MFT_RIGHTJUSTIFY /* same as MF_HELP */ ) + /* Maximum number of menu items a menu can contain */ #define MAX_MENU_ITEMS (0x4000) #define MAX_GOINTOSUBMENU (0x10) @@ -44,18 +56,18 @@ DBG_DEFAULT_CHANNEL(UserMenu); } \ } -#define FreeMenuText(MenuItem) \ +#define FreeMenuText(Menu,MenuItem) \ { \ if((MENU_ITEM_TYPE((MenuItem)->fType) == MF_STRING) && \ - (MenuItem)->Text.Length) { \ - ExFreePoolWithTag((MenuItem)->Text.Buffer, TAG_STRING); \ + (MenuItem)->lpstr.Length) { \ + DesktopHeapFree(((PMENU)Menu)->head.rpdesk, (MenuItem)->lpstr.Buffer); \ } \ } -PMENU_OBJECT FASTCALL UserGetMenuObject(HMENU hMenu) +PMENU FASTCALL UserGetMenuObject(HMENU hMenu) { - PMENU_OBJECT Menu; + PMENU Menu; if (!hMenu) { @@ -63,7 +75,7 @@ PMENU_OBJECT FASTCALL UserGetMenuObject(HMENU hMenu) return NULL; } - Menu = (PMENU_OBJECT)UserGetObject(gHandleTable, hMenu, TYPE_MENU); + Menu = (PMENU)UserGetObject(gHandleTable, hMenu, TYPE_MENU); if (!Menu) { EngSetLastError(ERROR_INVALID_MENU_HANDLE); @@ -76,15 +88,15 @@ PMENU_OBJECT FASTCALL UserGetMenuObject(HMENU hMenu) #if 0 void FASTCALL -DumpMenuItemList(PMENU_ITEM MenuItem) +DumpMenuItemList(PITEM MenuItem) { UINT cnt = 0; while(MenuItem) { - if(MenuItem->Text.Length) - DbgPrint(" %d. %wZ\n", ++cnt, &MenuItem->Text); + if(MenuItem->lpstr.Length) + DbgPrint(" %d. %wZ\n", ++cnt, &MenuItem->lpstr); else - DbgPrint(" %d. NO TEXT dwTypeData==%d\n", ++cnt, (DWORD)MenuItem->Text.Buffer); + DbgPrint(" %d. NO TEXT dwTypeData==%d\n", ++cnt, (DWORD)MenuItem->lpstr.Buffer); DbgPrint(" fType="); if(MFT_BITMAP & MenuItem->fType) DbgPrint("MFT_BITMAP "); @@ -127,10 +139,10 @@ DumpMenuItemList(PMENU_ITEM MenuItem) } #endif -PMENU_OBJECT FASTCALL +PMENU FASTCALL IntGetMenuObject(HMENU hMenu) { - PMENU_OBJECT Menu = UserGetMenuObject(hMenu); + PMENU Menu = UserGetMenuObject(hMenu); if (Menu) Menu->head.cLockObj++; @@ -138,32 +150,25 @@ IntGetMenuObject(HMENU hMenu) } BOOL FASTCALL -IntFreeMenuItem(PMENU_OBJECT Menu, PMENU_ITEM MenuItem, BOOL bRecurse) +IntFreeMenuItem(PMENU Menu, PITEM MenuItem, BOOL bRecurse) { - FreeMenuText(MenuItem); - if(bRecurse && MenuItem->hSubMenu) + FreeMenuText(Menu,MenuItem); + if(bRecurse && MenuItem->spSubMenu) { - PMENU_OBJECT SubMenu; - SubMenu = UserGetMenuObject(MenuItem->hSubMenu ); - if(SubMenu) - { - IntDestroyMenuObject(SubMenu, bRecurse, TRUE); - } + IntDestroyMenuObject(MenuItem->spSubMenu, bRecurse, TRUE); } /* Free memory */ - ExFreePoolWithTag(MenuItem, TAG_MENUITEM); + DesktopHeapFree(Menu->head.rpdesk, MenuItem); return TRUE; } BOOL FASTCALL -IntRemoveMenuItem(PMENU_OBJECT Menu, UINT uPosition, UINT uFlags, - BOOL bRecurse) +IntRemoveMenuItem(PMENU Menu, UINT uPosition, UINT uFlags, BOOL bRecurse) { - PMENU_ITEM PrevMenuItem, MenuItem; - if(IntGetMenuItemByFlag(Menu, uPosition, uFlags, &Menu, &MenuItem, - &PrevMenuItem) > -1) + PITEM PrevMenuItem, MenuItem = NULL; + if(IntGetMenuItemByFlag(Menu, uPosition, uFlags, &Menu, &MenuItem, &PrevMenuItem) > -1) { if(MenuItem) { @@ -171,9 +176,9 @@ IntRemoveMenuItem(PMENU_OBJECT Menu, UINT uPosition, UINT uFlags, PrevMenuItem->Next = MenuItem->Next; else { - Menu->MenuItemList = MenuItem->Next; + Menu->rgItems = MenuItem->Next; } - Menu->MenuInfo.MenuItemCount--; + Menu->cItems--; return IntFreeMenuItem(Menu, MenuItem, bRecurse); } } @@ -181,32 +186,38 @@ IntRemoveMenuItem(PMENU_OBJECT Menu, UINT uPosition, UINT uFlags, } UINT FASTCALL -IntDeleteMenuItems(PMENU_OBJECT Menu, BOOL bRecurse) +IntDeleteMenuItems(PMENU Menu, BOOL bRecurse) { UINT res = 0; - PMENU_ITEM NextItem; - PMENU_ITEM CurItem = Menu->MenuItemList; - while(CurItem) + PITEM NextItem; + PITEM CurItem = Menu->rgItems; + while(CurItem && Menu->cItems) { + Menu->cItems--; //// This is the last of this mess~! Removal requires new start up sequence. Do it like windows and wine! + //// wine MENU_CopySysPopup and ReactOS User32LoadSysMenuTemplateForKernel. + //// SC_CLOSE First and SC_CLOSED Last + //// Use menu item blocks not chain. + /// So do it like windows~! NextItem = CurItem->Next; IntFreeMenuItem(Menu, CurItem, bRecurse); + CurItem->Next = 0; // mark the item as end of the list!!! CurItem = NextItem; res++; } - Menu->MenuInfo.MenuItemCount = 0; - Menu->MenuItemList = NULL; + Menu->cItems = 0; + Menu->rgItems = NULL; return res; } BOOL FASTCALL -IntDestroyMenuObject(PMENU_OBJECT Menu, +IntDestroyMenuObject(PMENU Menu, BOOL bRecurse, BOOL RemoveFromProcess) { if(Menu) { PWND Window; - PWINSTATION_OBJECT WindowStation; - NTSTATUS Status; + //PWINSTATION_OBJECT WindowStation; + //NTSTATUS Status; /* Remove all menu items */ IntDeleteMenuItems(Menu, bRecurse); /* Do not destroy submenus */ @@ -216,70 +227,227 @@ IntDestroyMenuObject(PMENU_OBJECT Menu, RemoveEntryList(&Menu->ListEntry); } - Status = ObReferenceObjectByHandle(Menu->Process->Win32WindowStation, + /*Status = ObReferenceObjectByHandle(Menu->Process->Win32WindowStation, 0, ExWindowStationObjectType, KernelMode, (PVOID*)&WindowStation, NULL); - if(NT_SUCCESS(Status)) + if(NT_SUCCESS(Status))*/ + if (PsGetCurrentProcessSessionId() == Menu->head.rpdesk->rpwinstaParent->dwSessionId) { BOOL ret; - if (Menu->MenuInfo.Wnd) + if (Menu->hWnd) { - Window = UserGetWindowObject(Menu->MenuInfo.Wnd); + Window = UserGetWindowObject(Menu->hWnd); if (Window) { Window->IDMenu = 0; } } -// UserDereferenceObject(Menu); - ret = UserDeleteObject(Menu->MenuInfo.Self, TYPE_MENU); - ObDereferenceObject(WindowStation); + //UserDereferenceObject(Menu); + ret = UserDeleteObject(Menu->head.h, TYPE_MENU); + if (!ret) + { // Make sure it is really dead or just marked for deletion. + ret = UserObjectInDestroy(Menu->head.h); + if (ret && EngGetLastError() == ERROR_INVALID_HANDLE) ret = FALSE; + } // See test_subpopup_locked_by_menu tests.... + //ObDereferenceObject(WindowStation); return ret; } } return FALSE; } -PMENU_OBJECT FASTCALL +BOOL IntDestroyMenu( PMENU pMenu, BOOL RemoveFromProcess) +{ + /* DestroyMenu should not destroy system menu popup owner */ + if ((pMenu->fFlags & (MNF_POPUP | MNF_SYSSUBMENU)) == MNF_POPUP )//&& pMenu->hWnd) + { + //DestroyWindow( pMenu->hWnd ); + //pMenu->hWnd = 0; + } + + if (pMenu->rgItems) /* recursively destroy submenus */ + { + int i; + ITEM *item = pMenu->rgItems; + for (i = pMenu->cItems; i > 0; i--, item++) + { + if (item->spSubMenu) IntDestroyMenu(item->spSubMenu, RemoveFromProcess); + //FreeMenuText(pMenu,item); + } + DesktopHeapFree(pMenu->head.rpdesk, pMenu->rgItems ); + } + //IntDestroyMenuObject(pMenu, bRecurse, RemoveFromProcess); + return TRUE; +} + +/********************************************************************** + * MENU_depth + * + * detect if there are loops in the menu tree (or the depth is too large) + */ +int MENU_depth( PMENU pmenu, int depth) +{ + UINT i; + ITEM *item; + int subdepth; + + depth++; + if( depth > MAXMENUDEPTH) return depth; + item = pmenu->rgItems; + subdepth = depth; + for( i = 0; i < pmenu->cItems && subdepth <= MAXMENUDEPTH; i++, item++) + { + if( item->spSubMenu) + { + int bdepth = MENU_depth( item->spSubMenu, depth); + if( bdepth > subdepth) subdepth = bdepth; + } + if( subdepth > MAXMENUDEPTH) + TRACE("<- hmenu %p\n", item->spSubMenu); + } + return subdepth; +} + +/*********************************************************************** + * MENU_FindItem + * + * Find a menu item. Return a pointer on the item, and modifies *hmenu + * in case the item was in a sub-menu. + */ +ITEM *MENU_FindItem( PMENU *pmenu, UINT *nPos, UINT wFlags ) +{ + MENU *menu = *pmenu; + ITEM *fallback = NULL; + UINT fallback_pos = 0; + UINT i; + PITEM pItem; + + if (wFlags & MF_BYPOSITION) + { + if (*nPos >= menu->cItems) return NULL; + pItem = menu->rgItems; + //pItem = &menu->rgItems[*nPos]; + i = 0; + while(pItem) // Do this for now. + { + if (i < (INT)menu->cItems) + { + if ( *nPos == i ) return pItem; + } + pItem = pItem->Next; + i++; + } + } + else + { + PITEM item = menu->rgItems; + for (i = 0; item ,i < menu->cItems; i++, item = item->Next)//, item++) + { + if (item->spSubMenu) + { + PMENU psubmenu = item->spSubMenu; + PITEM subitem = MENU_FindItem( &psubmenu, nPos, wFlags ); + if (subitem) + { + *pmenu = psubmenu; + return subitem; + } + else if (item->wID == *nPos) + { + /* fallback to this item if nothing else found */ + fallback_pos = i; + fallback = item; + } + } + else if (item->wID == *nPos) + { + *nPos = i; + return item; + } + } + } + + if (fallback) + *nPos = fallback_pos; + + return fallback; +} + +BOOL IntRemoveMenu( PMENU pMenu, UINT nPos, UINT wFlags, BOOL bRecurse ) +{ + PITEM item, NewItems; + + TRACE("(menu=%p pos=%04x flags=%04x)\n",pMenu, nPos, wFlags); + if (!(item = MENU_FindItem( &pMenu, &nPos, wFlags ))) return FALSE; + + /* Remove item */ + + //FreeMenuText(pMenu,item); + + if (bRecurse && item->spSubMenu) + { + IntDestroyMenu(item->spSubMenu, TRUE); + } + ////// Use cAlloced with inc's of 8's.... + if (--pMenu->cItems == 0) + { + DesktopHeapFree(pMenu->head.rpdesk, pMenu->rgItems ); + pMenu->rgItems = NULL; + } + else + { + while(nPos < pMenu->cItems) + { + *item = *(item+1); + item++; + nPos++; + } + NewItems = DesktopHeapAlloc(pMenu->head.rpdesk, pMenu->cItems * sizeof(ITEM)); + RtlCopyMemory(NewItems, pMenu->rgItems, pMenu->cItems * sizeof(ITEM)); + DesktopHeapFree(pMenu->head.rpdesk, pMenu->rgItems); + pMenu->rgItems = NewItems; + } + return TRUE; +} + +PMENU FASTCALL IntCreateMenu(PHANDLE Handle, BOOL IsMenuBar) { - PMENU_OBJECT Menu; + PMENU Menu; PPROCESSINFO CurrentWin32Process; - Menu = (PMENU_OBJECT)UserCreateObject( gHandleTable, + Menu = (PMENU)UserCreateObject( gHandleTable, NULL, NULL, Handle, TYPE_MENU, - sizeof(MENU_OBJECT)); + sizeof(MENU)); if(!Menu) { *Handle = 0; return NULL; } - Menu->Process = PsGetCurrentProcess(); - Menu->RtoL = FALSE; /* Default */ - Menu->MenuInfo.cbSize = sizeof(MENUINFO); /* Not used */ - Menu->MenuInfo.fMask = 0; /* Not used */ - Menu->MenuInfo.dwStyle = 0; /* FIXME */ - Menu->MenuInfo.cyMax = 0; /* Default */ - Menu->MenuInfo.hbrBack = NULL; /* No brush */ - Menu->MenuInfo.dwContextHelpID = 0; /* Default */ - Menu->MenuInfo.dwMenuData = 0; /* Default */ - Menu->MenuInfo.Self = *Handle; - Menu->MenuInfo.FocusedItem = NO_SELECTED_ITEM; - Menu->MenuInfo.Flags = (IsMenuBar ? 0 : MNF_POPUP); - Menu->MenuInfo.Wnd = NULL; - Menu->MenuInfo.WndOwner = NULL; - Menu->MenuInfo.Height = 0; - Menu->MenuInfo.Width = 0; - Menu->MenuInfo.TimeToHide = FALSE; + Menu->cyMax = 0; /* Default */ + Menu->hbrBack = NULL; /* No brush */ + Menu->dwContextHelpId = 0; /* Default */ + Menu->dwMenuData = 0; /* Default */ + Menu->iItem = NO_SELECTED_ITEM; // Focused item + Menu->fFlags = (IsMenuBar ? 0 : MNF_POPUP); + Menu->spwndNotify = NULL; + Menu->cyMenu = 0; // Height + Menu->cxMenu = 0; // Width + Menu->cItems = 0; // Item count + Menu->iTop = 0; + Menu->iMaxTop = 0; + Menu->cxTextAlign = 0; + Menu->rgItems = NULL; - Menu->MenuInfo.MenuItemCount = 0; - Menu->MenuItemList = NULL; + Menu->hWnd = NULL; + Menu->TimeToHide = FALSE; /* Insert menu item into process menu handle list */ CurrentWin32Process = PsGetCurrentProcessWin32Process(); @@ -289,105 +457,104 @@ IntCreateMenu(PHANDLE Handle, BOOL IsMenuBar) } BOOL FASTCALL -IntCloneMenuItems(PMENU_OBJECT Destination, PMENU_OBJECT Source) +IntCloneMenuItems(PMENU Destination, PMENU Source) { - PMENU_ITEM MenuItem, NewMenuItem = NULL; - PMENU_ITEM Old = NULL; + PITEM MenuItem, NewMenuItem = NULL; + PITEM Old = NULL; - if(!Source->MenuInfo.MenuItemCount) + if(!Source->cItems) return FALSE; - MenuItem = Source->MenuItemList; + MenuItem = Source->rgItems; while(MenuItem) { Old = NewMenuItem; if(NewMenuItem) NewMenuItem->Next = MenuItem; - NewMenuItem = ExAllocatePoolWithTag(PagedPool, sizeof(MENU_ITEM), TAG_MENUITEM); + NewMenuItem = DesktopHeapAlloc(Destination->head.rpdesk, sizeof(ITEM)); if(!NewMenuItem) break; + RtlZeroMemory(NewMenuItem, sizeof(NewMenuItem)); NewMenuItem->fType = MenuItem->fType; NewMenuItem->fState = MenuItem->fState; NewMenuItem->wID = MenuItem->wID; - NewMenuItem->hSubMenu = MenuItem->hSubMenu; + NewMenuItem->spSubMenu = MenuItem->spSubMenu; NewMenuItem->hbmpChecked = MenuItem->hbmpChecked; NewMenuItem->hbmpUnchecked = MenuItem->hbmpUnchecked; NewMenuItem->dwItemData = MenuItem->dwItemData; if((MENU_ITEM_TYPE(NewMenuItem->fType) == MF_STRING)) { - if(MenuItem->Text.Length) + if(MenuItem->lpstr.Length) { - NewMenuItem->Text.Length = 0; - NewMenuItem->Text.MaximumLength = MenuItem->Text.MaximumLength; - NewMenuItem->Text.Buffer = (PWSTR)ExAllocatePoolWithTag(PagedPool, MenuItem->Text.MaximumLength, TAG_STRING); - if(!NewMenuItem->Text.Buffer) + NewMenuItem->lpstr.Length = 0; + NewMenuItem->lpstr.MaximumLength = MenuItem->lpstr.MaximumLength; + NewMenuItem->lpstr.Buffer = DesktopHeapAlloc(Destination->head.rpdesk, MenuItem->lpstr.MaximumLength); + if(!NewMenuItem->lpstr.Buffer) { - ExFreePoolWithTag(NewMenuItem, TAG_MENUITEM); + DesktopHeapFree(Destination->head.rpdesk, NewMenuItem); break; } - RtlCopyUnicodeString(&NewMenuItem->Text, &MenuItem->Text); + RtlCopyUnicodeString(&NewMenuItem->lpstr, &MenuItem->lpstr); } else { - NewMenuItem->Text.Buffer = MenuItem->Text.Buffer; + NewMenuItem->lpstr.Buffer = MenuItem->lpstr.Buffer; } } else { - NewMenuItem->Text.Buffer = MenuItem->Text.Buffer; + NewMenuItem->lpstr.Buffer = MenuItem->lpstr.Buffer; } - NewMenuItem->hbmpItem = MenuItem->hbmpItem; + NewMenuItem->hbmp = MenuItem->hbmp; NewMenuItem->Next = NULL; if(Old) Old->Next = NewMenuItem; else - Destination->MenuItemList = NewMenuItem; - Destination->MenuInfo.MenuItemCount++; + Destination->rgItems = NewMenuItem; + Destination->cItems++; MenuItem = MenuItem->Next; } return TRUE; } -PMENU_OBJECT FASTCALL -IntCloneMenu(PMENU_OBJECT Source) +PMENU FASTCALL +IntCloneMenu(PMENU Source) { PPROCESSINFO CurrentWin32Process; HANDLE hMenu; - PMENU_OBJECT Menu; + PMENU Menu; if(!Source) return NULL; - Menu = (PMENU_OBJECT)UserCreateObject( gHandleTable, + Menu = (PMENU)UserCreateObject( gHandleTable, NULL, NULL, &hMenu, TYPE_MENU, - sizeof(MENU_OBJECT)); + sizeof(MENU)); if(!Menu) return NULL; - Menu->Process = PsGetCurrentProcess(); - Menu->RtoL = Source->RtoL; - Menu->MenuInfo.cbSize = sizeof(MENUINFO); /* Not used */ - Menu->MenuInfo.fMask = Source->MenuInfo.fMask; - Menu->MenuInfo.dwStyle = Source->MenuInfo.dwStyle; - Menu->MenuInfo.cyMax = Source->MenuInfo.cyMax; - Menu->MenuInfo.hbrBack = Source->MenuInfo.hbrBack; - Menu->MenuInfo.dwContextHelpID = Source->MenuInfo.dwContextHelpID; - Menu->MenuInfo.dwMenuData = Source->MenuInfo.dwMenuData; - Menu->MenuInfo.Self = hMenu; - Menu->MenuInfo.FocusedItem = NO_SELECTED_ITEM; - Menu->MenuInfo.Wnd = NULL; - Menu->MenuInfo.WndOwner = NULL; - Menu->MenuInfo.Height = 0; - Menu->MenuInfo.Width = 0; - Menu->MenuInfo.TimeToHide = FALSE; + Menu->fFlags = Source->fFlags; + Menu->cyMax = Source->cyMax; + Menu->hbrBack = Source->hbrBack; + Menu->dwContextHelpId = Source->dwContextHelpId; + Menu->dwMenuData = Source->dwMenuData; + Menu->iItem = NO_SELECTED_ITEM; + Menu->spwndNotify = NULL; + Menu->cyMenu = 0; + Menu->cxMenu = 0; + Menu->cItems = 0; + Menu->iTop = 0; + Menu->iMaxTop = 0; + Menu->cxTextAlign = 0; + Menu->rgItems = NULL; - Menu->MenuInfo.MenuItemCount = 0; - Menu->MenuItemList = NULL; + Menu->hWnd = NULL; + Menu->TimeToHide = FALSE; /* Insert menu item into process menu handle list */ CurrentWin32Process = PsGetCurrentProcessWin32Process(); @@ -399,101 +566,117 @@ IntCloneMenu(PMENU_OBJECT Source) } BOOL FASTCALL -IntSetMenuFlagRtoL(PMENU_OBJECT Menu) +IntSetMenuFlagRtoL(PMENU Menu) { - Menu->RtoL = TRUE; + Menu->fFlags |= MNF_RTOL; return TRUE; } BOOL FASTCALL -IntSetMenuContextHelpId(PMENU_OBJECT Menu, DWORD dwContextHelpId) +IntSetMenuContextHelpId(PMENU Menu, DWORD dwContextHelpId) { - Menu->MenuInfo.dwContextHelpID = dwContextHelpId; + Menu->dwContextHelpId = dwContextHelpId; return TRUE; } BOOL FASTCALL -IntGetMenuInfo(PMENU_OBJECT Menu, PROSMENUINFO lpmi) +IntGetMenuInfo(PMENU Menu, PROSMENUINFO lpmi) { if(lpmi->fMask & MIM_BACKGROUND) - lpmi->hbrBack = Menu->MenuInfo.hbrBack; + lpmi->hbrBack = Menu->hbrBack; if(lpmi->fMask & MIM_HELPID) - lpmi->dwContextHelpID = Menu->MenuInfo.dwContextHelpID; + lpmi->dwContextHelpID = Menu->dwContextHelpId; if(lpmi->fMask & MIM_MAXHEIGHT) - lpmi->cyMax = Menu->MenuInfo.cyMax; + lpmi->cyMax = Menu->cyMax; if(lpmi->fMask & MIM_MENUDATA) - lpmi->dwMenuData = Menu->MenuInfo.dwMenuData; + lpmi->dwMenuData = Menu->dwMenuData; if(lpmi->fMask & MIM_STYLE) - lpmi->dwStyle = Menu->MenuInfo.dwStyle; + lpmi->dwStyle = Menu->fFlags & MNS_STYLE_MASK; + if (sizeof(MENUINFO) < lpmi->cbSize) { - RtlCopyMemory((char *) lpmi + sizeof(MENUINFO), - (char *) &Menu->MenuInfo + sizeof(MENUINFO), - lpmi->cbSize - sizeof(MENUINFO)); - } - if (sizeof(ROSMENUINFO) == lpmi->cbSize) - { - lpmi->maxBmpSize.cx = Menu->MenuInfo.maxBmpSize.cx; - lpmi->maxBmpSize.cy = Menu->MenuInfo.maxBmpSize.cy; + lpmi->cItems = Menu->cItems; + + lpmi->iItem = Menu->iItem; + lpmi->cxMenu = Menu->cxMenu; + lpmi->cyMenu = Menu->cyMenu; + lpmi->spwndNotify = Menu->spwndNotify; + lpmi->cxTextAlign = Menu->cxTextAlign; + lpmi->iTop = Menu->iMaxTop; + lpmi->iMaxTop = Menu->iMaxTop; + lpmi->dwArrowsOn = Menu->dwArrowsOn; + + lpmi->fFlags = Menu->fFlags; + lpmi->Self = Menu->head.h; + lpmi->TimeToHide = Menu->TimeToHide; + lpmi->Wnd = Menu->hWnd; } return TRUE; } BOOL FASTCALL -IntSetMenuInfo(PMENU_OBJECT Menu, PROSMENUINFO lpmi) +IntSetMenuInfo(PMENU Menu, PROSMENUINFO lpmi) { if(lpmi->fMask & MIM_BACKGROUND) - Menu->MenuInfo.hbrBack = lpmi->hbrBack; + Menu->hbrBack = lpmi->hbrBack; if(lpmi->fMask & MIM_HELPID) - Menu->MenuInfo.dwContextHelpID = lpmi->dwContextHelpID; + Menu->dwContextHelpId = lpmi->dwContextHelpID; if(lpmi->fMask & MIM_MAXHEIGHT) - Menu->MenuInfo.cyMax = lpmi->cyMax; + Menu->cyMax = lpmi->cyMax; if(lpmi->fMask & MIM_MENUDATA) - Menu->MenuInfo.dwMenuData = lpmi->dwMenuData; + Menu->dwMenuData = lpmi->dwMenuData; if(lpmi->fMask & MIM_STYLE) - Menu->MenuInfo.dwStyle = lpmi->dwStyle; + Menu->fFlags ^= (Menu->fFlags ^ lpmi->dwStyle) & MNS_STYLE_MASK; if(lpmi->fMask & MIM_APPLYTOSUBMENUS) { int i; - PMENU_ITEM item = Menu->MenuItemList; - for ( i = Menu->MenuInfo.MenuItemCount; i; i--, item = item->Next) + PITEM item = Menu->rgItems; + for ( i = Menu->cItems; i; i--, item = item->Next) { - if ( item->hSubMenu ) + if ( item->spSubMenu ) { - PMENU_OBJECT SubMenu; - if (!(SubMenu = UserGetMenuObject(item->hSubMenu))) continue; - IntSetMenuInfo( SubMenu, lpmi); + IntSetMenuInfo( item->spSubMenu, lpmi); } } + /* PITEM item = Menu->rgItems; + for ( i = Menu->cItems; i; i--, item++) + { + if ( item->spSubMenu ) + { + IntSetMenuInfo( item->spSubMenu, lpmi); + } + }*/ } if (sizeof(MENUINFO) < lpmi->cbSize) { - Menu->MenuInfo.FocusedItem = lpmi->FocusedItem; - Menu->MenuInfo.Height = lpmi->Height; - Menu->MenuInfo.Width = lpmi->Width; - Menu->MenuInfo.Wnd = lpmi->Wnd; - Menu->MenuInfo.WndOwner = lpmi->WndOwner; - Menu->MenuInfo.TimeToHide = lpmi->TimeToHide; - } - if (sizeof(ROSMENUINFO) == lpmi->cbSize) - { - Menu->MenuInfo.maxBmpSize.cx = lpmi->maxBmpSize.cx; - Menu->MenuInfo.maxBmpSize.cy = lpmi->maxBmpSize.cy; + Menu->iItem = lpmi->iItem; + Menu->cyMenu = lpmi->cyMenu; + Menu->cxMenu = lpmi->cxMenu; + Menu->spwndNotify = lpmi->spwndNotify; + Menu->cxTextAlign = lpmi->cxTextAlign; + Menu->iTop = lpmi->iTop; + Menu->iMaxTop = lpmi->iMaxTop; + Menu->dwArrowsOn = lpmi->dwArrowsOn; + + Menu->TimeToHide = lpmi->TimeToHide; + Menu->hWnd = lpmi->Wnd; } return TRUE; } - +// +// Old and yeah~..... Why start with a -1 for position search? +// int FASTCALL -IntGetMenuItemByFlag(PMENU_OBJECT Menu, +IntGetMenuItemByFlag(PMENU Menu, UINT uSearchBy, UINT fFlag, - PMENU_OBJECT *SubMenu, - PMENU_ITEM *MenuItem, - PMENU_ITEM *PrevMenuItem) + PMENU *SubMenu, + PITEM *MenuItem, + PITEM *PrevMenuItem) { - PMENU_ITEM PrevItem = NULL; - PMENU_ITEM CurItem = Menu->MenuItemList; + PITEM PrevItem = NULL; + PITEM CurItem = Menu->rgItems; int p; int ret; @@ -542,17 +725,12 @@ IntGetMenuItemByFlag(PMENU_OBJECT Menu, } else { - if(CurItem->hSubMenu) + if(CurItem->spSubMenu) { - PMENU_OBJECT NewMenu = UserGetMenuObject(CurItem->hSubMenu); - if(NewMenu) + ret = IntGetMenuItemByFlag(CurItem->spSubMenu, uSearchBy, fFlag, SubMenu, MenuItem, PrevMenuItem); + if(ret != -1) { - ret = IntGetMenuItemByFlag(NewMenu, uSearchBy, fFlag, - SubMenu, MenuItem, PrevMenuItem); - if(ret != -1) - { - return ret; - } + return ret; } } } @@ -566,13 +744,13 @@ IntGetMenuItemByFlag(PMENU_OBJECT Menu, int FASTCALL -IntInsertMenuItemToList(PMENU_OBJECT Menu, PMENU_ITEM MenuItem, int pos) +IntInsertMenuItemToList(PMENU Menu, PITEM MenuItem, int pos) { - PMENU_ITEM CurItem; - PMENU_ITEM LastItem = NULL; + PITEM CurItem; + PITEM LastItem = NULL; UINT npos = 0; - CurItem = Menu->MenuItemList; + CurItem = Menu->rgItems; while(CurItem && (pos != 0)) { LastItem = CurItem; @@ -589,17 +767,17 @@ IntInsertMenuItemToList(PMENU_OBJECT Menu, PMENU_ITEM MenuItem, int pos) else { /* Insert at the beginning */ - Menu->MenuItemList = MenuItem; + Menu->rgItems = MenuItem; } MenuItem->Next = CurItem; - Menu->MenuInfo.MenuItemCount++; + Menu->cItems++; return npos; } BOOL FASTCALL -IntGetMenuItemInfo(PMENU_OBJECT Menu, /* UNUSED PARAM!! */ - PMENU_ITEM MenuItem, PROSMENUITEMINFO lpmii) +IntGetMenuItemInfo(PMENU Menu, /* UNUSED PARAM!! */ + PITEM MenuItem, PROSMENUITEMINFO lpmii) { NTSTATUS Status; @@ -609,7 +787,7 @@ IntGetMenuItemInfo(PMENU_OBJECT Menu, /* UNUSED PARAM!! */ } if(lpmii->fMask & MIIM_BITMAP) { - lpmii->hbmpItem = MenuItem->hbmpItem; + lpmii->hbmpItem = MenuItem->hbmp; } if(lpmii->fMask & MIIM_CHECKMARKS) { @@ -630,7 +808,7 @@ IntGetMenuItemInfo(PMENU_OBJECT Menu, /* UNUSED PARAM!! */ } if(lpmii->fMask & MIIM_SUBMENU) { - lpmii->hSubMenu = MenuItem->hSubMenu; + lpmii->hSubMenu = MenuItem->spSubMenu ? MenuItem->spSubMenu->head.h : NULL; } if ((lpmii->fMask & MIIM_STRING) || @@ -638,13 +816,13 @@ IntGetMenuItemInfo(PMENU_OBJECT Menu, /* UNUSED PARAM!! */ { if (lpmii->dwTypeData == NULL) { - lpmii->cch = MenuItem->Text.Length / sizeof(WCHAR); + lpmii->cch = MenuItem->lpstr.Length / sizeof(WCHAR); } else - { - Status = MmCopyToCaller(lpmii->dwTypeData, MenuItem->Text.Buffer, + { //// lpmii->lpstr can be read in user mode!!!! + Status = MmCopyToCaller(lpmii->dwTypeData, MenuItem->lpstr.Buffer, min(lpmii->cch * sizeof(WCHAR), - MenuItem->Text.MaximumLength)); + MenuItem->lpstr.MaximumLength)); if (! NT_SUCCESS(Status)) { SetLastNtError(Status); @@ -655,18 +833,23 @@ IntGetMenuItemInfo(PMENU_OBJECT Menu, /* UNUSED PARAM!! */ if (sizeof(ROSMENUITEMINFO) == lpmii->cbSize) { - lpmii->Rect = MenuItem->Rect; + lpmii->Rect.left = MenuItem->xItem; + lpmii->Rect.top = MenuItem->yItem; + lpmii->Rect.right = MenuItem->cxItem; // Do this for now...... + lpmii->Rect.bottom = MenuItem->cyItem; lpmii->dxTab = MenuItem->dxTab; - lpmii->lpstr = MenuItem->Text.Buffer; // Use DesktopHeap! + lpmii->lpstr = MenuItem->lpstr.Buffer; + lpmii->maxBmpSize.cx = MenuItem->cxBmp; + lpmii->maxBmpSize.cy = MenuItem->cyBmp; } return TRUE; } BOOL FASTCALL -IntSetMenuItemInfo(PMENU_OBJECT MenuObject, PMENU_ITEM MenuItem, PROSMENUITEMINFO lpmii) +IntSetMenuItemInfo(PMENU MenuObject, PITEM MenuItem, PROSMENUITEMINFO lpmii, PUNICODE_STRING lpstr) { - PMENU_OBJECT SubMenuObject; + PMENU SubMenuObject; UINT fTypeMask = (MFT_BITMAP | MFT_MENUBARBREAK | MFT_MENUBREAK | MFT_OWNERDRAW | MFT_RADIOCHECK | MFT_RIGHTJUSTIFY | MFT_SEPARATOR); if(!MenuItem || !MenuObject || !lpmii) @@ -680,13 +863,16 @@ IntSetMenuItemInfo(PMENU_OBJECT MenuObject, PMENU_ITEM MenuItem, PROSMENUITEMINF } if (lpmii->fMask & MIIM_TYPE) { + #if 0 //// Done in User32. if (lpmii->fMask & ( MIIM_STRING | MIIM_FTYPE | MIIM_BITMAP)) { ERR("IntSetMenuItemInfo: Invalid combination of fMask bits used\n"); + KeRosDumpStackFrames(NULL, 20); /* This does not happen on Win9x/ME */ SetLastNtError( ERROR_INVALID_PARAMETER); return FALSE; } + #endif /* * Delete the menu item type when changing type from * MF_STRING. @@ -694,33 +880,36 @@ IntSetMenuItemInfo(PMENU_OBJECT MenuObject, PMENU_ITEM MenuItem, PROSMENUITEMINF if (MenuItem->fType != lpmii->fType && MENU_ITEM_TYPE(MenuItem->fType) == MFT_STRING) { - FreeMenuText(MenuItem); - RtlInitUnicodeString(&MenuItem->Text, NULL); + FreeMenuText(MenuObject,MenuItem); + RtlInitUnicodeString(&MenuItem->lpstr, NULL); } if(lpmii->fType & MFT_BITMAP) { if(lpmii->hbmpItem) - MenuItem->hbmpItem = lpmii->hbmpItem; + MenuItem->hbmp = lpmii->hbmpItem; else { /* Win 9x/Me stuff */ - MenuItem->hbmpItem = (HBITMAP)((ULONG_PTR)(LOWORD(lpmii->dwTypeData))); + MenuItem->hbmp = (HBITMAP)((ULONG_PTR)(LOWORD(lpmii->dwTypeData))); } } MenuItem->fType |= lpmii->fType; } if (lpmii->fMask & MIIM_FTYPE ) { + #if 0 //// ? if(( lpmii->fType & MFT_BITMAP)) { ERR("IntSetMenuItemInfo: Can not use FTYPE and MFT_BITMAP.\n"); SetLastNtError( ERROR_INVALID_PARAMETER); return FALSE; } - MenuItem->fType |= lpmii->fType; /* Need to save all the flags, this fixed MFT_RIGHTJUSTIFY */ + #endif + MenuItem->fType &= ~MENUITEMINFO_TYPE_MASK; + MenuItem->fType |= lpmii->fType & MENUITEMINFO_TYPE_MASK; } if(lpmii->fMask & MIIM_BITMAP) { - MenuItem->hbmpItem = lpmii->hbmpItem; + MenuItem->hbmp = lpmii->hbmpItem; } if(lpmii->fMask & MIIM_CHECKMARKS) { @@ -747,79 +936,158 @@ IntSetMenuItemInfo(PMENU_OBJECT MenuObject, PMENU_ITEM MenuItem, PROSMENUITEMINF if(lpmii->fMask & MIIM_SUBMENU) { - MenuItem->hSubMenu = lpmii->hSubMenu; /* Make sure the submenu is marked as a popup menu */ - if (MenuItem->hSubMenu) + if (lpmii->hSubMenu) { - SubMenuObject = UserGetMenuObject(MenuItem->hSubMenu); + SubMenuObject = UserGetMenuObject(lpmii->hSubMenu); if (SubMenuObject != NULL) { - SubMenuObject->MenuInfo.Flags |= MNF_POPUP; + SubMenuObject->fFlags |= MNF_POPUP; + // Now fix the test_subpopup_locked_by_menu tests.... + if (MenuItem->spSubMenu) UserDereferenceObject(MenuItem->spSubMenu); + MenuItem->spSubMenu = SubMenuObject; + UserReferenceObject(SubMenuObject); } + else + { + EngSetLastError( ERROR_INVALID_PARAMETER); + return FALSE; + } + } + else + { // If submenu just dereference it. + if (MenuItem->spSubMenu) UserDereferenceObject(MenuItem->spSubMenu); + MenuItem->spSubMenu = NULL; } } if ((lpmii->fMask & MIIM_STRING) || ((lpmii->fMask & MIIM_TYPE) && (MENU_ITEM_TYPE(lpmii->fType) == MF_STRING))) { - FreeMenuText(MenuItem); + FreeMenuText(MenuObject,MenuItem); if(lpmii->dwTypeData && lpmii->cch) { UNICODE_STRING Source; - Source.Length = - Source.MaximumLength = lpmii->cch * sizeof(WCHAR); + Source.Length = Source.MaximumLength = lpmii->cch * sizeof(WCHAR); Source.Buffer = lpmii->dwTypeData; - MenuItem->Text.Buffer = (PWSTR)ExAllocatePoolWithTag( - PagedPool, Source.Length + sizeof(WCHAR), TAG_STRING); - if(MenuItem->Text.Buffer != NULL) + MenuItem->lpstr.Buffer = DesktopHeapAlloc( MenuObject->head.rpdesk, Source.Length + sizeof(WCHAR)); + if(MenuItem->lpstr.Buffer != NULL) { - MenuItem->Text.Length = 0; - MenuItem->Text.MaximumLength = Source.Length + sizeof(WCHAR); - RtlCopyUnicodeString(&MenuItem->Text, &Source); - MenuItem->Text.Buffer[MenuItem->Text.Length / sizeof(WCHAR)] = 0; + MenuItem->lpstr.Length = 0; + MenuItem->lpstr.MaximumLength = Source.Length + sizeof(WCHAR); + RtlCopyUnicodeString(&MenuItem->lpstr, &Source); + MenuItem->lpstr.Buffer[MenuItem->lpstr.Length / sizeof(WCHAR)] = 0; + + MenuItem->cch = MenuItem->lpstr.Length / sizeof(WCHAR); + MenuItem->Xlpstr = (USHORT*)MenuItem->lpstr.Buffer; } else { - RtlInitUnicodeString(&MenuItem->Text, NULL); + RtlInitUnicodeString(&MenuItem->lpstr, NULL); + MenuItem->Xlpstr = NULL; } } else { - if (0 == (MenuObject->MenuInfo.Flags & MNF_SYSDESKMN)) + if (0 == (MenuObject->fFlags & MNF_SYSDESKMN)) { MenuItem->fType |= MF_SEPARATOR; } - RtlInitUnicodeString(&MenuItem->Text, NULL); + RtlInitUnicodeString(&MenuItem->lpstr, NULL); } } + //if( !MenuItem->lpstr.Buffer && !(MenuItem->fType & MFT_OWNERDRAW) && !MenuItem->hbmp) + // MenuItem->fType |= MFT_SEPARATOR; break system menu..... + + /* Force size recalculation! */ + MenuObject->cyMenu = 0; + if (sizeof(ROSMENUITEMINFO) == lpmii->cbSize) { - MenuItem->Rect = lpmii->Rect; + MenuItem->xItem = lpmii->Rect.left; + MenuItem->yItem = lpmii->Rect.top; + MenuItem->cxItem = lpmii->Rect.right; // Do this for now...... + MenuItem->cyItem = lpmii->Rect.bottom; MenuItem->dxTab = lpmii->dxTab; - lpmii->lpstr = MenuItem->Text.Buffer; /* Use DesktopHeap! Send back new allocated string or zero */ + lpmii->lpstr = MenuItem->lpstr.Buffer; /* Send back new allocated string or zero */ + MenuItem->cxBmp = lpmii->maxBmpSize.cx; + MenuItem->cyBmp = lpmii->maxBmpSize.cy; } return TRUE; } + +/********************************************************************** + * MENU_InsertItem + * + * Insert (allocate) a new item into a menu. + */ +ITEM *MENU_InsertItem( PMENU menu, UINT pos, UINT flags ) +{ + ITEM *newItems; + + /* Find where to insert new item */ + + if (flags & MF_BYPOSITION) { + if (pos > menu->cItems) + pos = menu->cItems; + } else { + if (!MENU_FindItem( &menu, &pos, flags )) + pos = menu->cItems; + } + + /* Make sure that MDI system buttons stay on the right side. + * Note: XP treats only bitmap handles 1 - 6 as "magic" ones + * regardless of their id. + */ + while ( pos > 0 && + (INT_PTR)menu->rgItems[pos - 1].hbmp >= (INT_PTR)HBMMENU_SYSTEM && + (INT_PTR)menu->rgItems[pos - 1].hbmp <= (INT_PTR)HBMMENU_MBAR_CLOSE_D) + pos--; + + TRACE("inserting at %u flags %x\n", pos, flags); + + /* Create new items array */ + + newItems = DesktopHeapAlloc(menu->head.rpdesk, sizeof(ITEM) * (menu->cItems+1) ); + if (!newItems) + { + WARN("allocation failed\n" ); + return NULL; + } + if (menu->cItems > 0) + { + /* Copy the old array into the new one */ + if (pos > 0) RtlCopyMemory( newItems, menu->rgItems, pos * sizeof(ITEM) ); + if (pos < menu->cItems) RtlCopyMemory( &newItems[pos+1], &menu->rgItems[pos], (menu->cItems-pos)*sizeof(ITEM) ); + DesktopHeapFree(menu->head.rpdesk, menu->rgItems ); + } + menu->rgItems = newItems; + menu->cItems++; + RtlZeroMemory( &newItems[pos], sizeof(*newItems) ); + menu->cyMenu = 0; /* force size recalculate */ + return &newItems[pos]; +} + BOOL FASTCALL IntInsertMenuItem( - _In_ PMENU_OBJECT MenuObject, + _In_ PMENU MenuObject, UINT uItem, BOOL fByPosition, PROSMENUITEMINFO ItemInfo) { int pos; - PMENU_ITEM MenuItem; - PMENU_OBJECT SubMenu = NULL; + PITEM MenuItem; + PMENU SubMenu = NULL; NT_ASSERT(MenuObject != NULL); - - if (MAX_MENU_ITEMS <= MenuObject->MenuInfo.MenuItemCount) + //ERR("InsertMenuItem\n"); + if (MAX_MENU_ITEMS <= MenuObject->cItems) { EngSetLastError(ERROR_NOT_ENOUGH_MEMORY); return FALSE; @@ -830,9 +1098,9 @@ IntInsertMenuItem( SubMenu = MenuObject; /* calculate position */ pos = (int)uItem; - if(uItem > MenuObject->MenuInfo.MenuItemCount) + if(uItem > MenuObject->cItems) { - pos = MenuObject->MenuInfo.MenuItemCount; + pos = MenuObject->cItems; } } else @@ -843,7 +1111,7 @@ IntInsertMenuItem( { /* Default to last position of menu */ SubMenu = MenuObject; - pos = MenuObject->MenuInfo.MenuItemCount; + pos = MenuObject->cItems; } @@ -852,31 +1120,24 @@ IntInsertMenuItem( pos = -1; } - MenuItem = ExAllocatePoolWithTag(PagedPool, sizeof(MENU_ITEM), TAG_MENUITEM); + MenuItem = DesktopHeapAlloc(MenuObject->head.rpdesk, sizeof(ITEM)); if (NULL == MenuItem) { EngSetLastError(ERROR_NOT_ENOUGH_MEMORY); return FALSE; } - MenuItem->fType = MFT_STRING; - MenuItem->fState = MFS_ENABLED | MFS_UNCHECKED; - MenuItem->wID = 0; - MenuItem->hSubMenu = (HMENU)0; - MenuItem->hbmpChecked = (HBITMAP)0; - MenuItem->hbmpUnchecked = (HBITMAP)0; - MenuItem->dwItemData = 0; - RtlInitUnicodeString(&MenuItem->Text, NULL); - MenuItem->hbmpItem = (HBITMAP)0; + RtlZeroMemory(MenuItem, sizeof(MenuItem)); - if(!IntSetMenuItemInfo(SubMenu, MenuItem, ItemInfo)) + if(!IntSetMenuItemInfo(SubMenu, MenuItem, ItemInfo, NULL)) { - ExFreePoolWithTag(MenuItem, TAG_MENUITEM); + DesktopHeapFree(MenuObject->head.rpdesk, MenuItem); return FALSE; } /* Force size recalculation! */ - MenuObject->MenuInfo.Height = 0; + MenuObject->cyMenu = 0; + MenuItem->hbmpChecked = MenuItem->hbmpUnchecked = 0; pos = IntInsertMenuItemToList(SubMenu, MenuItem, pos); @@ -886,58 +1147,53 @@ IntInsertMenuItem( } UINT FASTCALL -IntEnableMenuItem(PMENU_OBJECT MenuObject, UINT uIDEnableItem, UINT uEnable) +IntEnableMenuItem(PMENU MenuObject, UINT uIDEnableItem, UINT uEnable) { - PMENU_ITEM MenuItem; - UINT res = IntGetMenuItemByFlag(MenuObject, uIDEnableItem, uEnable, NULL, &MenuItem, NULL); - if(!MenuItem || (res == (UINT)-1)) - { - return (UINT)-1; - } + PITEM MenuItem; + UINT res; + + if (!(MenuItem = MENU_FindItem( &MenuObject, &uIDEnableItem, uEnable ))) return (UINT)-1; res = MenuItem->fState & (MF_GRAYED | MF_DISABLED); - if(uEnable & MF_DISABLED) - { - MenuItem->fState |= MF_DISABLED; - MenuItem->fState |= uEnable & MF_GRAYED; - } - else - { - if(uEnable & MF_GRAYED) - { - MenuItem->fState |= (MF_GRAYED | MF_DISABLED); - } - else - { - MenuItem->fState &= ~(MF_DISABLED | MF_GRAYED); - } - } + MenuItem->fState ^= (res ^ uEnable) & (MF_GRAYED | MF_DISABLED); + /* If the close item in the system menu change update the close button */ + if((MenuItem->wID == SC_CLOSE) && (res != uEnable)) + { + if (MenuObject->fFlags & MNF_SYSSUBMENU && MenuObject->spwndNotify != 0) + { + RECTL rc = MenuObject->spwndNotify->rcWindow; + + /* Refresh the frame to reflect the change */ + IntMapWindowPoints(0, MenuObject->spwndNotify, (POINT *)&rc, 2); + rc.bottom = 0; + co_UserRedrawWindow(MenuObject->spwndNotify, &rc, 0, RDW_FRAME | RDW_INVALIDATE | RDW_NOCHILDREN); + } + } return res; } - - +#if 0 // Moved to User32. DWORD FASTCALL -IntBuildMenuItemList(PMENU_OBJECT MenuObject, PVOID Buffer, ULONG nMax) +IntBuildMenuItemList(PMENU MenuObject, PVOID Buffer, ULONG nMax) { DWORD res = 0; ROSMENUITEMINFO mii; PVOID Buf; - PMENU_ITEM CurItem = MenuObject->MenuItemList; + PITEM CurItem = MenuObject->rgItems; PWCHAR StrOut; NTSTATUS Status; WCHAR NulByte; if (0 != nMax) { - if (nMax < MenuObject->MenuInfo.MenuItemCount * sizeof(ROSMENUITEMINFO)) + if (nMax < MenuObject->cItems * sizeof(ROSMENUITEMINFO)) { return 0; } - StrOut = (PWCHAR)((char *) Buffer + MenuObject->MenuInfo.MenuItemCount + StrOut = (PWCHAR)((char *) Buffer + MenuObject->cItems * sizeof(ROSMENUITEMINFO)); - nMax -= MenuObject->MenuInfo.MenuItemCount * sizeof(ROSMENUITEMINFO); + nMax -= MenuObject->cItems * sizeof(ROSMENUITEMINFO); Buf = Buffer; mii.cbSize = sizeof(ROSMENUITEMINFO); mii.fMask = 0; @@ -945,9 +1201,9 @@ IntBuildMenuItemList(PMENU_OBJECT MenuObject, PVOID Buffer, ULONG nMax) while (NULL != CurItem) { - mii.cch = CurItem->Text.Length / sizeof(WCHAR); + mii.cch = CurItem->lpstr.Length / sizeof(WCHAR); mii.dwItemData = CurItem->dwItemData; - if (0 != CurItem->Text.Length) + if (0 != CurItem->lpstr.Length) { mii.dwTypeData = StrOut; } @@ -959,12 +1215,17 @@ IntBuildMenuItemList(PMENU_OBJECT MenuObject, PVOID Buffer, ULONG nMax) mii.fType = CurItem->fType; mii.wID = CurItem->wID; mii.hbmpChecked = CurItem->hbmpChecked; - mii.hbmpItem = CurItem->hbmpItem; + mii.hbmpItem = CurItem->hbmp; mii.hbmpUnchecked = CurItem->hbmpUnchecked; - mii.hSubMenu = CurItem->hSubMenu; - mii.Rect = CurItem->Rect; + mii.hSubMenu = CurItem->spSubMenu ? CurItem->spSubMenu->head.h : NULL; + mii.Rect.left = CurItem->xItem; + mii.Rect.top = CurItem->yItem; + mii.Rect.right = CurItem->cxItem; // Do this for now...... + mii.Rect.bottom = CurItem->cyItem; mii.dxTab = CurItem->dxTab; - mii.lpstr = CurItem->Text.Buffer; // Use DesktopHeap! + mii.lpstr = CurItem->lpstr.Buffer; // Can be read from user side! + //mii.maxBmpSize.cx = CurItem->cxBmp; + //mii.maxBmpSize.cy = CurItem->cyBmp; Status = MmCopyToCaller(Buf, &mii, sizeof(ROSMENUITEMINFO)); if (! NT_SUCCESS(Status)) @@ -974,18 +1235,18 @@ IntBuildMenuItemList(PMENU_OBJECT MenuObject, PVOID Buffer, ULONG nMax) } Buf = (PVOID)((ULONG_PTR)Buf + sizeof(ROSMENUITEMINFO)); - if (0 != CurItem->Text.Length - && (nMax >= CurItem->Text.Length + sizeof(WCHAR))) + if (0 != CurItem->lpstr.Length + && (nMax >= CurItem->lpstr.Length + sizeof(WCHAR))) { /* Copy string */ - Status = MmCopyToCaller(StrOut, CurItem->Text.Buffer, - CurItem->Text.Length); + Status = MmCopyToCaller(StrOut, CurItem->lpstr.Buffer, + CurItem->lpstr.Length); if (! NT_SUCCESS(Status)) { SetLastNtError(Status); return 0; } - StrOut += CurItem->Text.Length / sizeof(WCHAR); + StrOut += CurItem->lpstr.Length / sizeof(WCHAR); Status = MmCopyToCaller(StrOut, &NulByte, sizeof(WCHAR)); if (! NT_SUCCESS(Status)) { @@ -993,9 +1254,9 @@ IntBuildMenuItemList(PMENU_OBJECT MenuObject, PVOID Buffer, ULONG nMax) return 0; } StrOut++; - nMax -= CurItem->Text.Length + sizeof(WCHAR); + nMax -= CurItem->lpstr.Length + sizeof(WCHAR); } - else if (0 != CurItem->Text.Length) + else if (0 != CurItem->lpstr.Length) { break; } @@ -1008,82 +1269,69 @@ IntBuildMenuItemList(PMENU_OBJECT MenuObject, PVOID Buffer, ULONG nMax) { while (NULL != CurItem) { - res += sizeof(ROSMENUITEMINFO) + CurItem->Text.Length + sizeof(WCHAR); + res += sizeof(ROSMENUITEMINFO) + CurItem->lpstr.Length + sizeof(WCHAR); CurItem = CurItem->Next; } } + return res; +} +#endif +DWORD FASTCALL +IntCheckMenuItem(PMENU MenuObject, UINT uIDCheckItem, UINT uCheck) +{ + PITEM MenuItem; + DWORD res; + + if (!(MenuItem = MENU_FindItem( &MenuObject, &uIDCheckItem, uCheck ))) return -1; + + res = (DWORD)(MenuItem->fState & MF_CHECKED); + + MenuItem->fState ^= (res ^ uCheck) & MF_CHECKED; return res; } - -DWORD FASTCALL -IntCheckMenuItem(PMENU_OBJECT MenuObject, UINT uIDCheckItem, UINT uCheck) -{ - PMENU_ITEM MenuItem; - int res = -1; - - if((IntGetMenuItemByFlag(MenuObject, uIDCheckItem, uCheck, NULL, &MenuItem, NULL) < 0) || !MenuItem) - { - return -1; - } - - res = (DWORD)(MenuItem->fState & MF_CHECKED); - if(uCheck & MF_CHECKED) - { - MenuItem->fState |= MF_CHECKED; - } - else - { - MenuItem->fState &= ~MF_CHECKED; - } - - return (DWORD)res; -} - BOOL FASTCALL IntHiliteMenuItem(PWND WindowObject, - PMENU_OBJECT MenuObject, + PMENU MenuObject, UINT uItemHilite, UINT uHilite) { - PMENU_ITEM MenuItem; - int Pos; + PITEM MenuItem; - Pos = IntGetMenuItemByFlag(MenuObject, uItemHilite, uHilite, NULL, &MenuItem, NULL); + if (!(MenuItem = MENU_FindItem( &MenuObject, &uItemHilite, uHilite ))) return FALSE; - if (!MenuItem || (uHilite & MF_BYPOSITION && Pos == -1)) + if (MenuItem) { - return FALSE; + if (uHilite & MF_HILITE) + { + MenuItem->fState |= MF_HILITE; + } + else + { + MenuItem->fState &= ~MF_HILITE; + } } - - if (uHilite & MF_HILITE) - { - MenuItem->fState |= MF_HILITE; - } - else - { - MenuItem->fState &= ~MF_HILITE; - } - /* FIXME: Update the window's menu */ return TRUE; } BOOL FASTCALL -UserSetMenuDefaultItem(PMENU_OBJECT MenuObject, UINT uItem, UINT fByPos) +UserSetMenuDefaultItem(PMENU MenuObject, UINT uItem, UINT fByPos) { BOOL ret = FALSE; - PMENU_ITEM MenuItem = MenuObject->MenuItemList; + PITEM MenuItem = MenuObject->rgItems; + while(MenuItem) + { + MenuItem->fState &= ~MFS_DEFAULT; + MenuItem = MenuItem->Next; + } + + /* no default item */ if(uItem == (UINT)-1) { - while(MenuItem) - { - MenuItem->fState &= ~MFS_DEFAULT; - MenuItem = MenuItem->Next; - } return TRUE; } @@ -1126,14 +1374,13 @@ UserSetMenuDefaultItem(PMENU_OBJECT MenuObject, UINT uItem, UINT fByPos) UINT FASTCALL -IntGetMenuDefaultItem(PMENU_OBJECT MenuObject, UINT fByPos, UINT gmdiFlags, +IntGetMenuDefaultItem(PMENU MenuObject, UINT fByPos, UINT gmdiFlags, DWORD *gismc) { UINT x = 0; UINT res = -1; UINT sres; - PMENU_OBJECT SubMenuObject; - PMENU_ITEM MenuItem = MenuObject->MenuItemList; + PITEM MenuItem = MenuObject->rgItems; while(MenuItem) { @@ -1149,15 +1396,14 @@ IntGetMenuDefaultItem(PMENU_OBJECT MenuObject, UINT fByPos, UINT gmdiFlags, res = MenuItem->wID; if((*gismc < MAX_GOINTOSUBMENU) && (gmdiFlags & GMDI_GOINTOPOPUPS) && - MenuItem->hSubMenu) + MenuItem->spSubMenu) { - SubMenuObject = UserGetMenuObject(MenuItem->hSubMenu); - if(!SubMenuObject || (SubMenuObject == MenuObject)) + if(MenuItem->spSubMenu == MenuObject) break; (*gismc)++; - sres = IntGetMenuDefaultItem(SubMenuObject, fByPos, gmdiFlags, gismc); + sres = IntGetMenuDefaultItem(MenuItem->spSubMenu, fByPos, gmdiFlags, gismc); (*gismc)--; if(sres > (UINT)-1) @@ -1175,7 +1421,7 @@ IntGetMenuDefaultItem(PMENU_OBJECT MenuObject, UINT fByPos, UINT gmdiFlags, } VOID FASTCALL -co_IntInitTracking(PWND Window, PMENU_OBJECT Menu, BOOL Popup, +co_IntInitTracking(PWND Window, PMENU Menu, BOOL Popup, UINT Flags) { /* FIXME: Hide caret */ @@ -1186,11 +1432,11 @@ co_IntInitTracking(PWND Window, PMENU_OBJECT Menu, BOOL Popup, /* FIXME: Send WM_SETCURSOR message */ if(!(Flags & TPM_NONOTIFY)) - co_IntSendMessage(Window->head.h, WM_INITMENU, (WPARAM)Menu->MenuInfo.Self, 0); + co_IntSendMessage(Window->head.h, WM_INITMENU, (WPARAM)Menu->head.h, 0); } VOID FASTCALL -co_IntExitTracking(PWND Window, PMENU_OBJECT Menu, BOOL Popup, +co_IntExitTracking(PWND Window, PMENU Menu, BOOL Popup, UINT Flags) { if(!(Flags & TPM_NONOTIFY)) @@ -1200,14 +1446,14 @@ co_IntExitTracking(PWND Window, PMENU_OBJECT Menu, BOOL Popup, } INT FASTCALL -IntTrackMenu(PMENU_OBJECT Menu, PWND Window, INT x, INT y, +IntTrackMenu(PMENU Menu, PWND Window, INT x, INT y, RECTL lprect) { return 0; } BOOL FASTCALL -co_IntTrackPopupMenu(PMENU_OBJECT Menu, PWND Window, +co_IntTrackPopupMenu(PMENU Menu, PWND Window, UINT Flags, POINT *Pos, UINT MenuPos, RECTL *ExcludeRect) { co_IntInitTracking(Window, Menu, TRUE, Flags); @@ -1225,7 +1471,7 @@ IntCleanupMenus(struct _EPROCESS *Process, PPROCESSINFO Win32Process) { PEPROCESS CurrentProcess; PLIST_ENTRY LastHead = NULL; - PMENU_OBJECT MenuObject; + PMENU MenuObject; CurrentProcess = PsGetCurrentProcess(); if (CurrentProcess != Process) @@ -1237,8 +1483,8 @@ IntCleanupMenus(struct _EPROCESS *Process, PPROCESSINFO Win32Process) Win32Process->MenuListHead.Flink != LastHead) { LastHead = Win32Process->MenuListHead.Flink; - MenuObject = CONTAINING_RECORD(Win32Process->MenuListHead.Flink, MENU_OBJECT, ListEntry); - + MenuObject = CONTAINING_RECORD(Win32Process->MenuListHead.Flink, MENU, ListEntry); + ERR("Menus are stuck on the process list!\n"); IntDestroyMenuObject(MenuObject, FALSE, TRUE); } @@ -1382,7 +1628,7 @@ intGetTitleBarInfo(PWND pWindowObject, PTITLEBARINFO bti) DWORD FASTCALL UserInsertMenuItem( - PMENU_OBJECT Menu, + PMENU Menu, UINT uItem, BOOL fByPosition, LPCMENUITEMINFOW UnsafeItemInfo) @@ -1422,117 +1668,87 @@ UserInsertMenuItem( UINT FASTCALL IntGetMenuState( HMENU hMenu, UINT uId, UINT uFlags) { - PMENU_OBJECT MenuObject, SubMenu; - PMENU_ITEM mi; + PMENU MenuObject; + PITEM pItem; if (!(MenuObject = UserGetMenuObject(hMenu))) { return (UINT)-1; } - if (IntGetMenuItemByFlag(MenuObject, uId, uFlags, &SubMenu, &mi, NULL)) + if (!(pItem = MENU_FindItem( &MenuObject, &uId, uFlags ))) return -1; + + if (pItem->spSubMenu) { - if (mi->hSubMenu) - { - if (SubMenu) - { - UINT nSubItems = SubMenu->MenuInfo.MenuItemCount; - return (nSubItems << 8) | ((mi->fState | mi->fType) & 0xff); - } - else - return (UINT)-1; - } - return (mi->fType | mi->fState); + return (pItem->spSubMenu->cItems << 8) | ((pItem->fState|pItem->fType) & 0xff); } - return (UINT)-1; + else + return (pItem->fType | pItem->fState); } HMENU FASTCALL IntGetSubMenu( HMENU hMenu, int nPos) { - PMENU_OBJECT MenuObject, SubMenu; + PMENU MenuObject; + PITEM pItem; if (!(MenuObject = UserGetMenuObject(hMenu))) { return NULL; } - if (IntGetMenuItemByFlag(MenuObject, nPos, MF_BYPOSITION, &SubMenu, NULL, NULL)) + + if (!(pItem = MENU_FindItem( &MenuObject, (UINT*)&nPos, MF_BYPOSITION ))) return NULL; + + if (pItem->spSubMenu) { - return SubMenu ? UserHMGetHandle(SubMenu) : NULL; + HMENU hsubmenu = UserHMGetHandle(pItem->spSubMenu); + return hsubmenu; } return NULL; } UINT FASTCALL IntFindSubMenu(HMENU *hMenu, HMENU hSubTarget ) { - PMENU_OBJECT MenuObject; - PMENU_ITEM mi; - UINT i; + PMENU menu; + HMENU hSubMenu; + UINT i; + PITEM item; - if ( (*hMenu) == (HMENU)0xffff || !(MenuObject = UserGetMenuObject(*hMenu)) ) - return NO_SELECTED_ITEM; + if (((*hMenu)==(HMENU)0xffff) ||(!(menu = UserGetMenuObject(*hMenu)))) + return NO_SELECTED_ITEM; - for (i = 0; i < MenuObject->MenuInfo.MenuItemCount; i++) - { - if (!IntGetMenuItemByFlag(MenuObject, i, MF_BYPOSITION, NULL, &mi, NULL)) - { - return NO_SELECTED_ITEM; - } - - if (!(mi->hSubMenu)) continue; - - if (mi->hSubMenu == hSubTarget) - { - return i; - } - else - { - HMENU hsubmenu = mi->hSubMenu; - UINT pos = IntFindSubMenu(&hsubmenu, hSubTarget ); - if (pos != NO_SELECTED_ITEM) - { - *hMenu = hsubmenu; - return pos; - } - } - } - return NO_SELECTED_ITEM; + item = menu->rgItems; + for (i = 0; i < menu->cItems; i++, item = item->Next)//item++) + { + if (!item->spSubMenu) + continue; + else + { + hSubMenu = UserHMGetHandle(item->spSubMenu); + if (hSubMenu == hSubTarget) + { + return i; + } + else + { + HMENU hsubmenu = hSubMenu; + UINT pos = IntFindSubMenu( &hsubmenu, hSubTarget ); + if (pos != NO_SELECTED_ITEM) + { + *hMenu = hsubmenu; + return pos; + } + } + } + } + return NO_SELECTED_ITEM; } -/* FUNCTIONS *****************************************************************/ - -/* - * @implemented - */ -DWORD APIENTRY -NtUserCheckMenuItem( - HMENU hMenu, - UINT uIDCheckItem, - UINT uCheck) -{ - PMENU_OBJECT Menu; - DECLARE_RETURN(DWORD); - - TRACE("Enter NtUserCheckMenuItem\n"); - UserEnterExclusive(); - - if(!(Menu = UserGetMenuObject(hMenu))) - { - RETURN( (DWORD)-1); - } - - RETURN( IntCheckMenuItem(Menu, uIDCheckItem, uCheck)); - -CLEANUP: - TRACE("Leave NtUserCheckMenuItem, ret=%lu\n",_ret_); - UserLeave(); - END_CLEANUP; -} HMENU FASTCALL UserCreateMenu(BOOL PopupMenu) { PWINSTATION_OBJECT WinStaObject; HANDLE Handle; - PMENU_OBJECT Menu; + PMENU Menu; NTSTATUS Status; PEPROCESS CurrentProcess = PsGetCurrentProcess(); @@ -1555,6 +1771,10 @@ HMENU FASTCALL UserCreateMenu(BOOL PopupMenu) return (HMENU)0; } Menu = IntCreateMenu(&Handle, !PopupMenu); + if (Menu->head.rpdesk->rpwinstaParent != WinStaObject) + { + ERR("Desktop Window Station does not match Process one!\n"); + } ObDereferenceObject(WinStaObject); } else @@ -1566,6 +1786,221 @@ HMENU FASTCALL UserCreateMenu(BOOL PopupMenu) return (HMENU)Handle; } +BOOL FASTCALL +UserMenuItemInfo( + PMENU Menu, + UINT Item, + BOOL ByPosition, + PROSMENUITEMINFO UnsafeItemInfo, + BOOL SetOrGet) +{ + PITEM MenuItem; + ROSMENUITEMINFO ItemInfo; + NTSTATUS Status; + UINT Size; + BOOL Ret; + + Status = MmCopyFromCaller(&Size, &UnsafeItemInfo->cbSize, sizeof(UINT)); + if (! NT_SUCCESS(Status)) + { + SetLastNtError(Status); + return( FALSE); + } + if (sizeof(MENUITEMINFOW) != Size + && FIELD_OFFSET(MENUITEMINFOW, hbmpItem) != Size + && sizeof(ROSMENUITEMINFO) != Size) + { + EngSetLastError(ERROR_INVALID_PARAMETER); + return( FALSE); + } + Status = MmCopyFromCaller(&ItemInfo, UnsafeItemInfo, Size); + if (! NT_SUCCESS(Status)) + { + SetLastNtError(Status); + return( FALSE); + } + /* If this is a pre-0x0500 _WIN32_WINNT MENUITEMINFOW, you can't + set/get hbmpItem */ + if (FIELD_OFFSET(MENUITEMINFOW, hbmpItem) == Size + && 0 != (ItemInfo.fMask & MIIM_BITMAP)) + { + EngSetLastError(ERROR_INVALID_PARAMETER); + return( FALSE); + } + + if (!(MenuItem = MENU_FindItem( &Menu, &Item, (ByPosition ? MF_BYPOSITION : MF_BYCOMMAND) ))) + { + EngSetLastError(ERROR_MENU_ITEM_NOT_FOUND); + return( FALSE); + } + + if (SetOrGet) + { + Ret = IntSetMenuItemInfo(Menu, MenuItem, &ItemInfo, NULL); + } + else + { + Ret = IntGetMenuItemInfo(Menu, MenuItem, &ItemInfo); + if (Ret) + { + Status = MmCopyToCaller(UnsafeItemInfo, &ItemInfo, Size); + if (! NT_SUCCESS(Status)) + { + SetLastNtError(Status); + return( FALSE); + } + } + } + + return( Ret); +} + +BOOL FASTCALL +UserMenuInfo( + PMENU Menu, + PROSMENUINFO UnsafeMenuInfo, + BOOL SetOrGet) +{ + BOOL Res; + DWORD Size; + NTSTATUS Status; + ROSMENUINFO MenuInfo; + + Status = MmCopyFromCaller(&Size, &UnsafeMenuInfo->cbSize, sizeof(DWORD)); + if (! NT_SUCCESS(Status)) + { + SetLastNtError(Status); + return( FALSE); + } + if(Size < sizeof(MENUINFO) || sizeof(ROSMENUINFO) < Size) + { + EngSetLastError(ERROR_INVALID_PARAMETER); + return( FALSE); + } + Status = MmCopyFromCaller(&MenuInfo, UnsafeMenuInfo, Size); + if (! NT_SUCCESS(Status)) + { + SetLastNtError(Status); + return( FALSE); + } + + if(SetOrGet) + { + /* Set MenuInfo */ + Res = IntSetMenuInfo(Menu, &MenuInfo); + } + else + { + /* Get MenuInfo */ + Res = IntGetMenuInfo(Menu, &MenuInfo); + if (Res) + { + Status = MmCopyToCaller(UnsafeMenuInfo, &MenuInfo, Size); + if (! NT_SUCCESS(Status)) + { + SetLastNtError(Status); + return( FALSE); + } + } + } + + return( Res); +} + +VOID FASTCALL +MENU_AdjustMenuItemRect(PMENU menu, PRECTL rect) +{ + if (menu->dwArrowsOn) + { + UINT arrow_bitmap_height; + //BITMAP bmp; + //GetObjectW(get_up_arrow_bitmap(), sizeof(bmp), &bmp); + arrow_bitmap_height = gpsi->oembmi[65].cy; ///// Menu up arrow! OBM_UPARROW DFCS_MENUARROWUP + //arrow_bitmap_height = bmp.bmHeight; + rect->top += arrow_bitmap_height - menu->iTop; + rect->bottom += arrow_bitmap_height - menu->iTop; + } +} + +BOOL FASTCALL +IntGetMenuItemRect( + PWND pWnd, + PMENU Menu, + UINT uItem, + PRECTL Rect) +{ + LONG XMove, YMove; + PITEM MenuItem; + //int p = 0; + + if (!pWnd) + { + HWND hWnd = Menu->hWnd; + if (!(pWnd = UserGetWindowObject(hWnd))) return FALSE; + } + + if ((MenuItem = MENU_FindItem (&Menu, &uItem, MF_BYPOSITION))) + { + Rect->left = MenuItem->xItem; + Rect->top = MenuItem->yItem; + Rect->right = MenuItem->cxItem; // Do this for now...... + Rect->bottom = MenuItem->cyItem; + } + else + { + ERR("Failed Item Lookup! %d\n", uItem); + return FALSE; + } + + if (Menu->fFlags & MNF_POPUP) + { + XMove = pWnd->rcClient.left; + YMove = pWnd->rcClient.top; + } + else + { + XMove = pWnd->rcWindow.left; + YMove = pWnd->rcWindow.top; + } + + Rect->left += XMove; + Rect->top += YMove; + Rect->right += XMove; + Rect->bottom += YMove; + + return TRUE; +} + +/* FUNCTIONS *****************************************************************/ + +/* + * @implemented + */ +DWORD APIENTRY +NtUserCheckMenuItem( + HMENU hMenu, + UINT uIDCheckItem, + UINT uCheck) +{ + PMENU Menu; + DECLARE_RETURN(DWORD); + + TRACE("Enter NtUserCheckMenuItem\n"); + UserEnterExclusive(); + + if(!(Menu = UserGetMenuObject(hMenu))) + { + RETURN( (DWORD)-1); + } + + RETURN( IntCheckMenuItem(Menu, uIDCheckItem, uCheck)); + +CLEANUP: + TRACE("Leave NtUserCheckMenuItem, ret=%lu\n",_ret_); + UserLeave(); + END_CLEANUP; +} + /* * @implemented */ @@ -1575,7 +2010,7 @@ NtUserDeleteMenu( UINT uPosition, UINT uFlags) { - PMENU_OBJECT Menu; + PMENU Menu; DECLARE_RETURN(BOOL); TRACE("Enter NtUserDeleteMenu\n"); @@ -1666,19 +2101,20 @@ CLEANUP: */ BOOL FASTCALL UserDestroyMenu(HMENU hMenu) { - PMENU_OBJECT Menu; + PMENU Menu; + PTHREADINFO pti = PsGetCurrentThreadWin32Thread(); if(!(Menu = UserGetMenuObject(hMenu))) { return FALSE; } - if(Menu->Process != PsGetCurrentProcess()) + //if(Menu->Process != PsGetCurrentProcess()) + if (Menu->head.rpdesk != pti->rpdesk) { EngSetLastError(ERROR_ACCESS_DENIED); return FALSE; } - return IntDestroyMenuObject(Menu, FALSE, TRUE); } @@ -1689,7 +2125,7 @@ BOOL APIENTRY NtUserDestroyMenu( HMENU hMenu) { - PMENU_OBJECT Menu; + PMENU Menu; DECLARE_RETURN(BOOL); TRACE("Enter NtUserDestroyMenu\n"); @@ -1699,13 +2135,11 @@ NtUserDestroyMenu( { RETURN( FALSE); } - - if(Menu->Process != PsGetCurrentProcess()) + if (Menu->head.rpdesk != gptiCurrent->rpdesk) { EngSetLastError(ERROR_ACCESS_DENIED); RETURN( FALSE); } - RETURN( IntDestroyMenuObject(Menu, TRUE, TRUE)); CLEANUP: @@ -1723,7 +2157,7 @@ NtUserEnableMenuItem( UINT uIDEnableItem, UINT uEnable) { - PMENU_OBJECT Menu; + PMENU Menu; DECLARE_RETURN(UINT); TRACE("Enter NtUserEnableMenuItem\n"); @@ -1742,50 +2176,6 @@ CLEANUP: END_CLEANUP; } -BOOL FASTCALL -IntGetMenuItemRect( - PWND pWnd, - PMENU_OBJECT Menu, - UINT uItem, - PRECTL Rect) -{ - LONG XMove, YMove; - PMENU_ITEM MenuItem; - int p = 0; - - if (!pWnd) - { - HWND hWnd = Menu->MenuInfo.Wnd; - if (!(pWnd = UserGetWindowObject(hWnd))) return FALSE; - } - - if ((p = IntGetMenuItemByFlag(Menu, uItem, MF_BYPOSITION, NULL, &MenuItem, NULL)) > -1) - *Rect = MenuItem->Rect; - else - { - ERR("Failed Item Lookup! %d\n", p); - return FALSE; - } - - if (Menu->MenuInfo.Flags & MNF_POPUP) - { - XMove = pWnd->rcClient.left; - YMove = pWnd->rcClient.top; - } - else - { - XMove = pWnd->rcWindow.left; - YMove = pWnd->rcWindow.top; - } - - Rect->left += XMove; - Rect->top += YMove; - Rect->right += XMove; - Rect->bottom += YMove; - - return TRUE; -} - /* * @implemented */ @@ -1801,7 +2191,7 @@ NtUserGetMenuBarInfo( MENUBARINFO kmbi; BOOL Ret; NTSTATUS Status = STATUS_SUCCESS; - PMENU_OBJECT Menu = NULL; + PMENU Menu = NULL; DECLARE_RETURN(BOOL); TRACE("Enter NtUserGetMenuBarInfo\n"); @@ -1833,7 +2223,7 @@ NtUserGetMenuBarInfo( case OBJID_SYSMENU: if (!(pWnd->style & WS_SYSMENU)) RETURN(FALSE); Menu = IntGetSystemMenu(pWnd, FALSE, FALSE); - hMenu = Menu->MenuInfo.Self; + hMenu = Menu->head.h; break; default: RETURN(FALSE); @@ -1862,16 +2252,16 @@ NtUserGetMenuBarInfo( if (!Menu) RETURN(FALSE); - if (idItem < 0 || idItem > Menu->MenuInfo.MenuItemCount) + if (idItem < 0 || idItem > Menu->cItems) RETURN(FALSE); RECTL_vSetEmptyRect(&kmbi.rcBar); if (idItem == 0) { - Ret = IntGetMenuItemRect(pWnd, Menu, -1, &kmbi.rcBar); - kmbi.rcBar.right = kmbi.rcBar.left + Menu->MenuInfo.Width; - kmbi.rcBar.bottom = kmbi.rcBar.top + Menu->MenuInfo.Height; + Ret = IntGetMenuItemRect(pWnd, Menu, 0, &kmbi.rcBar); + kmbi.rcBar.right = kmbi.rcBar.left + Menu->cxMenu; + kmbi.rcBar.bottom = kmbi.rcBar.top + Menu->cyMenu; ERR("idItem 0 %d\n",Ret); } else @@ -1882,16 +2272,20 @@ NtUserGetMenuBarInfo( kmbi.hMenu = hMenu; kmbi.hwndMenu = NULL; + kmbi.fBarFocused = FALSE; + kmbi.fFocused = FALSE; //kmbi.fBarFocused = top_popup_hmenu == hMenu; if (idItem) { - PMENU_OBJECT SubMenuObject; - kmbi.fFocused = Menu->MenuInfo.FocusedItem == idItem-1; - - if ( kmbi.fFocused && Menu->MenuItemList->hSubMenu ) + PITEM MenuItem; + UINT nPos = idItem-1; + kmbi.fFocused = Menu->iItem == idItem-1; + //if (kmbi->fFocused && (Menu->rgItems[idItem - 1].spSubMenu)) + MenuItem = MENU_FindItem (&Menu, &nPos, MF_BYPOSITION); + if ( MenuItem && kmbi.fFocused && MenuItem->spSubMenu ) { - SubMenuObject = UserGetMenuObject(Menu->MenuItemList->hSubMenu); - if (SubMenuObject) kmbi.hwndMenu = SubMenuObject->MenuInfo.Wnd; + //kmbi.hwndMenu = Menu->rgItems[idItem - 1].spSubMenu->hWnd; + kmbi.hwndMenu = MenuItem->spSubMenu->hWnd; } } /* else @@ -1931,8 +2325,8 @@ NtUserGetMenuIndex( HMENU hMenu, HMENU hSubMenu) { - PMENU_OBJECT Menu, SubMenu; - PMENU_ITEM MenuItem; + PMENU Menu, SubMenu; + PITEM MenuItem; DECLARE_RETURN(UINT); TRACE("Enter NtUserGetMenuIndex\n"); @@ -1942,10 +2336,10 @@ NtUserGetMenuIndex( !(SubMenu = UserGetMenuObject(hSubMenu)) ) RETURN(0xFFFFFFFF); - MenuItem = Menu->MenuItemList; + MenuItem = Menu->rgItems; while(MenuItem) { - if (MenuItem->hSubMenu == hSubMenu) + if (MenuItem->spSubMenu == SubMenu) RETURN(MenuItem->wID); MenuItem = MenuItem->Next; } @@ -1971,8 +2365,8 @@ NtUserGetMenuItemRect( PWND ReferenceWnd; LONG XMove, YMove; RECTL Rect; - PMENU_OBJECT Menu; - PMENU_ITEM MenuItem; + PMENU Menu; + PITEM MenuItem; NTSTATUS Status = STATUS_SUCCESS; DECLARE_RETURN(BOOL); @@ -1984,21 +2378,26 @@ NtUserGetMenuItemRect( RETURN(FALSE); } - if (IntGetMenuItemByFlag(Menu, uItem, MF_BYPOSITION, NULL, &MenuItem, NULL) > -1) - Rect = MenuItem->Rect; + if ((MenuItem = MENU_FindItem (&Menu, &uItem, MF_BYPOSITION))) + { + Rect.left = MenuItem->xItem; + Rect.top = MenuItem->yItem; + Rect.right = MenuItem->cxItem; // Do this for now...... + Rect.bottom = MenuItem->cyItem; + } else RETURN(FALSE); if(!hWnd) { - hWnd = Menu->MenuInfo.Wnd; + hWnd = Menu->hWnd; } if (lprcItem == NULL) RETURN( FALSE); if (!(ReferenceWnd = UserGetWindowObject(hWnd))) RETURN( FALSE); - if (Menu->MenuInfo.Flags & MNF_POPUP) + if (Menu->fFlags & MNF_POPUP) { XMove = ReferenceWnd->rcClient.left; YMove = ReferenceWnd->rcClient.top; @@ -2047,7 +2446,7 @@ NtUserHiliteMenuItem( UINT uItemHilite, UINT uHilite) { - PMENU_OBJECT Menu; + PMENU Menu; PWND Window; DECLARE_RETURN(BOOLEAN); @@ -2074,58 +2473,6 @@ CLEANUP: END_CLEANUP; } -static -BOOL FASTCALL -UserMenuInfo( - PMENU_OBJECT Menu, - PROSMENUINFO UnsafeMenuInfo, - BOOL SetOrGet) -{ - BOOL Res; - DWORD Size; - NTSTATUS Status; - ROSMENUINFO MenuInfo; - - Status = MmCopyFromCaller(&Size, &UnsafeMenuInfo->cbSize, sizeof(DWORD)); - if (! NT_SUCCESS(Status)) - { - SetLastNtError(Status); - return( FALSE); - } - if(Size < sizeof(MENUINFO) || sizeof(ROSMENUINFO) < Size) - { - EngSetLastError(ERROR_INVALID_PARAMETER); - return( FALSE); - } - Status = MmCopyFromCaller(&MenuInfo, UnsafeMenuInfo, Size); - if (! NT_SUCCESS(Status)) - { - SetLastNtError(Status); - return( FALSE); - } - - if(SetOrGet) - { - /* Set MenuInfo */ - Res = IntSetMenuInfo(Menu, &MenuInfo); - } - else - { - /* Get MenuInfo */ - Res = IntGetMenuInfo(Menu, &MenuInfo); - if (Res) - { - Status = MmCopyToCaller(UnsafeMenuInfo, &MenuInfo, Size); - if (! NT_SUCCESS(Status)) - { - SetLastNtError(Status); - return( FALSE); - } - } - } - - return( Res); -} /* * @implemented @@ -2137,9 +2484,9 @@ NtUserMenuItemFromPoint( DWORD X, DWORD Y) { - PMENU_OBJECT Menu; + PMENU Menu; PWND Window = NULL; - PMENU_ITEM mi; + PITEM mi; int i; DECLARE_RETURN(int); @@ -2151,7 +2498,7 @@ NtUserMenuItemFromPoint( RETURN( -1); } - if (!(Window = UserGetWindowObject(Menu->MenuInfo.Wnd))) + if (!(Window = UserGetWindowObject(Menu->hWnd))) { RETURN( -1); } @@ -2159,10 +2506,16 @@ NtUserMenuItemFromPoint( X -= Window->rcWindow.left; Y -= Window->rcWindow.top; - mi = Menu->MenuItemList; - for (i = 0; NULL != mi; i++) + mi = Menu->rgItems; + for (i = 0; NULL != mi; i++)//, mi++) { - if (RECTL_bPointInRect(&(mi->Rect), X, Y)) + RECTL Rect; + Rect.left = mi->xItem; + Rect.top = mi->yItem; + Rect.right = mi->cxItem; // Do this for now...... + Rect.bottom = mi->cyItem; + //MENU_AdjustMenuItemRect(Menu, &Rect); Need gpsi OBMI via callback! + if (RECTL_bPointInRect(&Rect, X, Y)) { break; } @@ -2177,80 +2530,6 @@ CLEANUP: END_CLEANUP; } -static -BOOL FASTCALL -UserMenuItemInfo( - PMENU_OBJECT Menu, - UINT Item, - BOOL ByPosition, - PROSMENUITEMINFO UnsafeItemInfo, - BOOL SetOrGet) -{ - PMENU_ITEM MenuItem; - ROSMENUITEMINFO ItemInfo; - NTSTATUS Status; - UINT Size; - BOOL Ret; - - Status = MmCopyFromCaller(&Size, &UnsafeItemInfo->cbSize, sizeof(UINT)); - if (! NT_SUCCESS(Status)) - { - SetLastNtError(Status); - return( FALSE); - } - if (sizeof(MENUITEMINFOW) != Size - && FIELD_OFFSET(MENUITEMINFOW, hbmpItem) != Size - && sizeof(ROSMENUITEMINFO) != Size) - { - EngSetLastError(ERROR_INVALID_PARAMETER); - return( FALSE); - } - Status = MmCopyFromCaller(&ItemInfo, UnsafeItemInfo, Size); - if (! NT_SUCCESS(Status)) - { - SetLastNtError(Status); - return( FALSE); - } - /* If this is a pre-0x0500 _WIN32_WINNT MENUITEMINFOW, you can't - set/get hbmpItem */ - if (FIELD_OFFSET(MENUITEMINFOW, hbmpItem) == Size - && 0 != (ItemInfo.fMask & MIIM_BITMAP)) - { - EngSetLastError(ERROR_INVALID_PARAMETER); - return( FALSE); - } - - if (IntGetMenuItemByFlag(Menu, Item, - (ByPosition ? MF_BYPOSITION : MF_BYCOMMAND), - NULL, &MenuItem, NULL) < 0) - { - EngSetLastError(ERROR_INVALID_PARAMETER); -// This will crash menu (line 80) correct_behavior test! -// "NT4 and below can't handle a bigger MENUITEMINFO struct" -// EngSetLastError(ERROR_MENU_ITEM_NOT_FOUND); - return( FALSE); - } - - if (SetOrGet) - { - Ret = IntSetMenuItemInfo(Menu, MenuItem, &ItemInfo); - } - else - { - Ret = IntGetMenuItemInfo(Menu, MenuItem, &ItemInfo); - if (Ret) - { - Status = MmCopyToCaller(UnsafeItemInfo, &ItemInfo, Size); - if (! NT_SUCCESS(Status)) - { - SetLastNtError(Status); - return( FALSE); - } - } - } - - return( Ret); -} /* * @implemented @@ -2261,7 +2540,7 @@ NtUserRemoveMenu( UINT uPosition, UINT uFlags) { - PMENU_OBJECT Menu; + PMENU Menu; DECLARE_RETURN(BOOL); TRACE("Enter NtUserRemoveMenu\n"); @@ -2289,7 +2568,7 @@ NtUserSetMenuContextHelpId( HMENU hMenu, DWORD dwContextHelpId) { - PMENU_OBJECT Menu; + PMENU Menu; DECLARE_RETURN(BOOL); TRACE("Enter NtUserSetMenuContextHelpId\n"); @@ -2317,7 +2596,7 @@ NtUserSetMenuDefaultItem( UINT uItem, UINT fByPos) { - PMENU_OBJECT Menu; + PMENU Menu; DECLARE_RETURN(BOOL); TRACE("Enter NtUserSetMenuDefaultItem\n"); @@ -2343,7 +2622,7 @@ BOOL APIENTRY NtUserSetMenuFlagRtoL( HMENU hMenu) { - PMENU_OBJECT Menu; + PMENU Menu; DECLARE_RETURN(BOOL); TRACE("Enter NtUserSetMenuFlagRtoL\n"); @@ -2370,7 +2649,7 @@ NtUserThunkedMenuInfo( HMENU hMenu, LPCMENUINFO lpcmi) { - PMENU_OBJECT Menu; + PMENU Menu; DECLARE_RETURN(BOOL); TRACE("Enter NtUserThunkedMenuInfo\n"); @@ -2401,7 +2680,7 @@ NtUserThunkedMenuItemInfo( LPMENUITEMINFOW lpmii, PUNICODE_STRING lpszCaption) { - PMENU_OBJECT Menu; + PMENU Menu; NTSTATUS Status; UNICODE_STRING lstrCaption; DECLARE_RETURN(BOOL); @@ -2420,7 +2699,7 @@ NtUserThunkedMenuItemInfo( lstrCaption.Buffer = NULL; /* Check if we got a Caption */ - if (lpszCaption) + if (lpszCaption && lpszCaption->Buffer) { /* Copy the string to kernel mode */ Status = ProbeAndCaptureUnicodeString( &lstrCaption, @@ -2432,6 +2711,7 @@ NtUserThunkedMenuItemInfo( SetLastNtError(Status); RETURN(FALSE); } + ///// Now use it! } if (bInsert) RETURN( UserInsertMenuItem(Menu, uItem, fByPosition, lpmii)); @@ -2444,10 +2724,8 @@ CLEANUP: END_CLEANUP; } -////// ReactOS NtUserBad -/* - * @implemented - */ +////// ReactOS NtUserBad is unpluged! + DWORD APIENTRY NtUserBuildMenuItemList( @@ -2456,8 +2734,8 @@ NtUserBuildMenuItemList( ULONG nBufSize, DWORD Reserved) { - DWORD res = -1; - PMENU_OBJECT Menu; +/* DWORD res = -1; + PMENU Menu; DECLARE_RETURN(DWORD); TRACE("Enter NtUserBuildMenuItemList\n"); @@ -2474,7 +2752,7 @@ NtUserBuildMenuItemList( } else { - res = Menu->MenuInfo.MenuItemCount; + res = Menu->cItems; } RETURN( res); @@ -2483,18 +2761,19 @@ CLEANUP: TRACE("Leave NtUserBuildMenuItemList, ret=%lu\n",_ret_); UserLeave(); END_CLEANUP; +*/ + STUB + + return 0; } -/* - * @implemented - */ UINT APIENTRY NtUserGetMenuDefaultItem( HMENU hMenu, UINT fByPos, UINT gmdiFlags) { - PMENU_OBJECT Menu; +/* PMENU Menu; DWORD gismc = 0; DECLARE_RETURN(UINT); @@ -2512,11 +2791,12 @@ CLEANUP: TRACE("Leave NtUserGetMenuDefaultItem, ret=%u\n",_ret_); UserLeave(); END_CLEANUP; +*/ + STUB + + return 0; } -/* - * @implemented - */ BOOL APIENTRY NtUserMenuInfo( @@ -2524,7 +2804,7 @@ NtUserMenuInfo( PROSMENUINFO UnsafeMenuInfo, BOOL SetOrGet) { - PMENU_OBJECT Menu; +/* PMENU Menu; DECLARE_RETURN(BOOL); TRACE("Enter NtUserMenuInfo\n"); @@ -2541,11 +2821,12 @@ CLEANUP: TRACE("Leave NtUserMenuInfo, ret=%i\n",_ret_); UserLeave(); END_CLEANUP; +*/ + STUB + + return 0; } -/* - * @implemented - */ BOOL APIENTRY NtUserMenuItemInfo( @@ -2555,7 +2836,7 @@ NtUserMenuItemInfo( PROSMENUITEMINFO UnsafeItemInfo, BOOL SetOrGet) { - PMENU_OBJECT Menu; +/* PMENU Menu; DECLARE_RETURN(BOOL); TRACE("Enter NtUserMenuItemInfo\n"); @@ -2572,7 +2853,10 @@ CLEANUP: TRACE("Leave NtUserMenuItemInfo, ret=%i\n",_ret_); UserLeave(); END_CLEANUP; +*/ + STUB + return 0; } /* EOF */ diff --git a/reactos/win32ss/user/ntuser/menu.h b/reactos/win32ss/user/ntuser/menu.h index 1ca12747dbb..9ff6b0cbee0 100644 --- a/reactos/win32ss/user/ntuser/menu.h +++ b/reactos/win32ss/user/ntuser/menu.h @@ -10,32 +10,6 @@ #define MF_END (0x0080) #endif -typedef struct _MENU_ITEM -{ - struct _MENU_ITEM *Next; - UINT fType; - UINT fState; - UINT wID; - HMENU hSubMenu; - HBITMAP hbmpChecked; - HBITMAP hbmpUnchecked; - ULONG_PTR dwItemData; - UNICODE_STRING Text; - HBITMAP hbmpItem; - RECTL Rect; - UINT dxTab; -} MENU_ITEM, *PMENU_ITEM; - -typedef struct _MENU_OBJECT -{ - PROCDESKHEAD head; - PEPROCESS Process; - LIST_ENTRY ListEntry; - PMENU_ITEM MenuItemList; - ROSMENUINFO MenuInfo; - BOOL RtoL; -} MENU_OBJECT, *PMENU_OBJECT; - typedef struct _SETMENUITEMRECT { UINT uItem; @@ -43,33 +17,34 @@ typedef struct _SETMENUITEMRECT RECTL rcRect; } SETMENUITEMRECT, *PSETMENUITEMRECT; -PMENU_OBJECT FASTCALL +PMENU FASTCALL IntGetMenuObject(HMENU hMenu); #define IntReleaseMenuObject(MenuObj) \ UserDereferenceObject(MenuObj) BOOL FASTCALL -IntDestroyMenuObject(PMENU_OBJECT MenuObject, BOOL bRecurse, BOOL RemoveFromProcess); +IntDestroyMenuObject(PMENU MenuObject, BOOL bRecurse, BOOL RemoveFromProcess); -PMENU_OBJECT FASTCALL -IntCloneMenu(PMENU_OBJECT Source); +PMENU FASTCALL +IntCloneMenu(PMENU Source); int FASTCALL -IntGetMenuItemByFlag(PMENU_OBJECT MenuObject, UINT uSearchBy, UINT fFlag, - PMENU_OBJECT *SubMenu, PMENU_ITEM *MenuItem, - PMENU_ITEM *PrevMenuItem); +IntGetMenuItemByFlag(PMENU MenuObject, UINT uSearchBy, UINT fFlag, + PMENU *SubMenu, PITEM *MenuItem, + PITEM *PrevMenuItem); BOOL FASTCALL IntCleanupMenus(struct _EPROCESS *Process, PPROCESSINFO Win32Process); BOOL FASTCALL -IntInsertMenuItem(_In_ PMENU_OBJECT MenuObject, UINT uItem, BOOL fByPosition, +IntInsertMenuItem(_In_ PMENU MenuObject, UINT uItem, BOOL fByPosition, PROSMENUITEMINFO ItemInfo); -PMENU_OBJECT FASTCALL +PMENU FASTCALL IntGetSystemMenu(PWND Window, BOOL bRevert, BOOL RetMenu); UINT FASTCALL IntFindSubMenu(HMENU *hMenu, HMENU hSubTarget ); UINT FASTCALL IntGetMenuState( HMENU hMenu, UINT uId, UINT uFlags); - +BOOL FASTCALL IntRemoveMenuItem(PMENU Menu, UINT uPosition, UINT uFlags, BOOL bRecurse); +PITEM MENU_FindItem( PMENU *pmenu, UINT *nPos, UINT wFlags ); diff --git a/reactos/win32ss/user/ntuser/object.c b/reactos/win32ss/user/ntuser/object.c index a7de628ff87..c807be0852e 100644 --- a/reactos/win32ss/user/ntuser/object.c +++ b/reactos/win32ss/user/ntuser/object.c @@ -597,7 +597,7 @@ PVOID FASTCALL ValidateHandle(HANDLE handle, HANDLE_TYPE type) } /* - * NtUserValidateHandleSecure + * NtUserValidateHandleSecure W2k3 has one argument. * * Status * @implemented @@ -609,62 +609,46 @@ NtUserValidateHandleSecure( HANDLE handle, BOOL Restricted) { - if(!Restricted) + UINT uType; + PPROCESSINFO ppi; + PUSER_HANDLE_ENTRY entry; + + DECLARE_RETURN(BOOL); + UserEnterExclusive(); + + if (!(entry = handle_to_entry(gHandleTable, handle ))) + { + EngSetLastError(ERROR_INVALID_HANDLE); + RETURN( FALSE); + } + uType = entry->type; + switch (uType) { - UINT uType; - { - PUSER_HANDLE_ENTRY entry; - if (!(entry = handle_to_entry(gHandleTable, handle ))) - { - EngSetLastError(ERROR_INVALID_HANDLE); - return FALSE; - } - uType = entry->type; - } - switch (uType) - { case TYPE_WINDOW: - { - if (UserGetWindowObject((HWND) handle)) return TRUE; - return FALSE; - } + case TYPE_INPUTCONTEXT: + ppi = ((PTHREADINFO)entry->pi)->ppi; + break; case TYPE_MENU: - { - if (UserGetMenuObject((HMENU) handle)) return TRUE; - return FALSE; - } case TYPE_ACCELTABLE: - { - if (UserGetAccelObject((HACCEL) handle)) return TRUE; - return FALSE; - } case TYPE_CURSOR: - { - if (UserGetCurIconObject((HCURSOR) handle)) return TRUE; - return FALSE; - } case TYPE_HOOK: - { - if (IntGetHookObject((HHOOK) handle)) return TRUE; - return FALSE; - } - case TYPE_MONITOR: - { - if (UserGetMonitorObject((HMONITOR) handle)) return TRUE; - return FALSE; - } case TYPE_CALLPROC: - { - WNDPROC_INFO Proc; - return UserGetCallProcInfo( handle, &Proc ); - } + case TYPE_SETWINDOWPOS: + ppi = entry->pi; + break; default: - EngSetLastError(ERROR_INVALID_HANDLE); - } + ppi = NULL; + break; } - else - { /* Is handle entry restricted? */ - STUB - } - return FALSE; + + if (!ppi) RETURN( FALSE); + + // Same process job returns TRUE. + if (gptiCurrent->ppi->pW32Job == ppi->pW32Job) RETURN( TRUE); + + RETURN( FALSE); + +CLEANUP: + UserLeave(); + END_CLEANUP; } diff --git a/reactos/win32ss/user/ntuser/simplecall.c b/reactos/win32ss/user/ntuser/simplecall.c index 59a92a5e62a..5661052c3e6 100644 --- a/reactos/win32ss/user/ntuser/simplecall.c +++ b/reactos/win32ss/user/ntuser/simplecall.c @@ -401,17 +401,17 @@ NtUserCallTwoParam( case TWOPARAM_ROUTINE_SETMENUBARHEIGHT: { DWORD_PTR Ret; - PMENU_OBJECT MenuObject = IntGetMenuObject((HMENU)Param1); + PMENU MenuObject = IntGetMenuObject((HMENU)Param1); if(!MenuObject) RETURN( 0); if(Param2 > 0) { - Ret = (MenuObject->MenuInfo.Height == (int)Param2); - MenuObject->MenuInfo.Height = (int)Param2; + Ret = (MenuObject->cyMenu == (int)Param2); + MenuObject->cyMenu = (int)Param2; } else - Ret = (DWORD_PTR)MenuObject->MenuInfo.Height; + Ret = (DWORD_PTR)MenuObject->cyMenu; IntReleaseMenuObject(MenuObject); RETURN( Ret); } @@ -564,9 +564,9 @@ NtUserCallHwndLock( break; case HWNDLOCK_ROUTINE_SETFOREGROUNDWINDOWMOUSE: - TRACE("co_IntSetForegroundWindow 1 0x%p\n",hWnd); + TRACE("co_IntSetForegroundWindow M 1 0x%p\n",hWnd); Ret = co_IntSetForegroundWindowMouse(Window); - TRACE("co_IntSetForegroundWindow 2 0x%p\n",hWnd); + TRACE("co_IntSetForegroundWindow M 2 0x%p\n",hWnd); break; case HWNDLOCK_ROUTINE_UPDATEWINDOW: diff --git a/reactos/win32ss/user/ntuser/userfuncs.h b/reactos/win32ss/user/ntuser/userfuncs.h index 4cfff9f8678..96935084a42 100644 --- a/reactos/win32ss/user/ntuser/userfuncs.h +++ b/reactos/win32ss/user/ntuser/userfuncs.h @@ -1,6 +1,6 @@ #pragma once -PMENU_OBJECT FASTCALL UserGetMenuObject(HMENU hMenu); +PMENU FASTCALL UserGetMenuObject(HMENU hMenu); #define ASSERT_REFS_CO(_obj_) \ { \ @@ -109,7 +109,7 @@ PWND FASTCALL UserGetAncestor(PWND Wnd, UINT Type); /*************** MENU.C ***************/ HMENU FASTCALL UserCreateMenu(BOOL PopupMenu); -BOOL FASTCALL UserSetMenuDefaultItem(PMENU_OBJECT Menu, UINT uItem, UINT fByPos); +BOOL FASTCALL UserSetMenuDefaultItem(PMENU Menu, UINT uItem, UINT fByPos); BOOL FASTCALL UserDestroyMenu(HMENU hMenu); /*************** SCROLLBAR.C ***************/ diff --git a/reactos/win32ss/user/ntuser/window.c b/reactos/win32ss/user/ntuser/window.c index 102b4962aee..6e95a3e6b8d 100644 --- a/reactos/win32ss/user/ntuser/window.c +++ b/reactos/win32ss/user/ntuser/window.c @@ -459,7 +459,7 @@ UserFreeWindowInfo(PTHREADINFO ti, PWND Wnd) } // DesktopHeapFree(Wnd->head.rpdesk, Wnd); -// WindowObject->Wnd = NULL; +// WindowObject->hWnd = NULL; } /*********************************************************************** @@ -479,7 +479,7 @@ static LRESULT co_UserFreeWindow(PWND Window, HWND *Children; HWND *ChildHandle; PWND Child; - PMENU_OBJECT Menu; + PMENU Menu; BOOLEAN BelongsToThreadData; ASSERT(Window); @@ -792,7 +792,7 @@ IntSetMenu( HMENU Menu, BOOL *Changed) { - PMENU_OBJECT OldMenu, NewMenu = NULL; + PMENU OldMenu, NewMenu = NULL; if ((Wnd->style & (WS_CHILD | WS_POPUP)) == WS_CHILD) { @@ -810,7 +810,7 @@ IntSetMenu( if (Wnd->IDMenu) { OldMenu = IntGetMenuObject((HMENU) Wnd->IDMenu); - ASSERT(NULL == OldMenu || OldMenu->MenuInfo.Wnd == Wnd->head.h); + ASSERT(NULL == OldMenu || OldMenu->hWnd == Wnd->head.h); } else { @@ -829,7 +829,7 @@ IntSetMenu( EngSetLastError(ERROR_INVALID_MENU_HANDLE); return FALSE; } - if (NULL != NewMenu->MenuInfo.Wnd) + if (NULL != NewMenu->hWnd) { /* Can't use the same menu for two windows */ if (NULL != OldMenu) @@ -845,12 +845,12 @@ IntSetMenu( Wnd->IDMenu = (UINT) Menu; if (NULL != NewMenu) { - NewMenu->MenuInfo.Wnd = Wnd->head.h; + NewMenu->hWnd = Wnd->head.h; IntReleaseMenuObject(NewMenu); } if (NULL != OldMenu) { - OldMenu->MenuInfo.Wnd = NULL; + OldMenu->hWnd = NULL; IntReleaseMenuObject(OldMenu); } @@ -895,13 +895,13 @@ co_DestroyThreadWindows(struct _ETHREAD *Thread) } } -PMENU_OBJECT FASTCALL +PMENU FASTCALL IntGetSystemMenu(PWND Window, BOOL bRevert, BOOL RetMenu) { - PMENU_OBJECT Menu, NewMenu = NULL, SysMenu = NULL, ret = NULL; + PMENU Menu, NewMenu = NULL, SysMenu = NULL, ret = NULL; PTHREADINFO W32Thread; HMENU hNewMenu, hSysMenu; - ROSMENUITEMINFO ItemInfo; + ROSMENUITEMINFO ItemInfo = {0}; if(bRevert) { @@ -929,10 +929,10 @@ IntGetSystemMenu(PWND Window, BOOL bRevert, BOOL RetMenu) NewMenu = IntCloneMenu(Menu); if(NewMenu) - { - Window->SystemMenu = NewMenu->MenuInfo.Self; - NewMenu->MenuInfo.Flags |= MNF_SYSDESKMN; - NewMenu->MenuInfo.Wnd = Window->head.h; + { // Use spmenuSys + Window->SystemMenu = NewMenu->head.h; + NewMenu->fFlags |= MNF_SYSDESKMN; + NewMenu->hWnd = Window->head.h; ret = NewMenu; //IntReleaseMenuObject(NewMenu); } @@ -950,8 +950,8 @@ IntGetSystemMenu(PWND Window, BOOL bRevert, BOOL RetMenu) UserDestroyMenu(hSysMenu); return NULL; } - SysMenu->MenuInfo.Flags |= MNF_SYSDESKMN; - SysMenu->MenuInfo.Wnd = Window->head.h; + SysMenu->fFlags |= MNF_SYSDESKMN; + SysMenu->hWnd = Window->head.h; hNewMenu = co_IntLoadSysMenuTemplate(); if(!hNewMenu) { @@ -970,21 +970,24 @@ IntGetSystemMenu(PWND Window, BOOL bRevert, BOOL RetMenu) NewMenu = IntCloneMenu(Menu); if(NewMenu) { - NewMenu->MenuInfo.Flags |= MNF_SYSDESKMN | MNF_POPUP; - NewMenu->MenuInfo.dwStyle = MNS_CHECKORBMP; + NewMenu->fFlags |= MNF_SYSDESKMN | MNF_POPUP; + // Do not set MNS_CHECKORBMP it breaks menus, also original code destroyed the style anyway. IntReleaseMenuObject(NewMenu); UserSetMenuDefaultItem(NewMenu, SC_CLOSE, FALSE); + if (Window->pcls->style & CS_NOCLOSE) + IntRemoveMenuItem(NewMenu, SC_CLOSE, MF_BYCOMMAND, TRUE); + ItemInfo.cbSize = sizeof(MENUITEMINFOW); ItemInfo.fMask = MIIM_FTYPE | MIIM_STRING | MIIM_STATE | MIIM_SUBMENU; ItemInfo.fType = 0; ItemInfo.fState = MFS_ENABLED; ItemInfo.dwTypeData = NULL; ItemInfo.cch = 0; - ItemInfo.hSubMenu = NewMenu->MenuInfo.Self; + ItemInfo.hSubMenu = NewMenu->head.h; IntInsertMenuItem(SysMenu, (UINT) -1, TRUE, &ItemInfo); - Window->SystemMenu = SysMenu->MenuInfo.Self; + Window->SystemMenu = SysMenu->head.h; ret = SysMenu; } @@ -1419,15 +1422,15 @@ co_UserSetParent(HWND hWndChild, HWND hWndNewParent) } BOOL FASTCALL -IntSetSystemMenu(PWND Window, PMENU_OBJECT Menu) +IntSetSystemMenu(PWND Window, PMENU Menu) { - PMENU_OBJECT OldMenu; + PMENU OldMenu; if(Window->SystemMenu) { OldMenu = IntGetMenuObject(Window->SystemMenu); if(OldMenu) { - OldMenu->MenuInfo.Flags &= ~ MNF_SYSDESKMN; + OldMenu->fFlags &= ~ MNF_SYSDESKMN; IntReleaseMenuObject(OldMenu); } } @@ -1435,10 +1438,10 @@ IntSetSystemMenu(PWND Window, PMENU_OBJECT Menu) if(Menu) { /* FIXME: Check window style, propably return FALSE? */ - Window->SystemMenu = Menu->MenuInfo.Self; - Menu->MenuInfo.Flags |= MNF_SYSDESKMN; + Window->SystemMenu = Menu->head.h; + Menu->fFlags |= MNF_SYSDESKMN; } - else + else // Use spmenuSys too! Window->SystemMenu = (HMENU)0; return TRUE; @@ -1752,7 +1755,7 @@ PWND FASTCALL IntCreateWindow(CREATESTRUCTW* Cs, PWND pWnd = NULL; HWND hWnd; PTHREADINFO pti = NULL; - PMENU_OBJECT SystemMenu; + PMENU SystemMenu; BOOL MenuChanged; BOOL bUnicodeWindow; @@ -1985,8 +1988,8 @@ PWND FASTCALL IntCreateWindow(CREATESTRUCTW* Cs, { SystemMenu = IntGetSystemMenu(pWnd, TRUE, TRUE); if(SystemMenu) - { - pWnd->SystemMenu = SystemMenu->MenuInfo.Self; + { // spmenuSys + pWnd->SystemMenu = SystemMenu->head.h; IntReleaseMenuObject(SystemMenu); } } @@ -3678,7 +3681,7 @@ HMENU APIENTRY NtUserGetSystemMenu(HWND hWnd, BOOL bRevert) { PWND Window; - PMENU_OBJECT Menu; + PMENU Menu; DECLARE_RETURN(HMENU); TRACE("Enter NtUserGetSystemMenu\n"); @@ -3694,7 +3697,7 @@ NtUserGetSystemMenu(HWND hWnd, BOOL bRevert) RETURN(NULL); } - RETURN(Menu->MenuInfo.Self); + RETURN(Menu->head.h); CLEANUP: TRACE("Leave NtUserGetSystemMenu, ret=%p\n", _ret_); @@ -3714,7 +3717,7 @@ NtUserSetSystemMenu(HWND hWnd, HMENU hMenu) { BOOL Result = FALSE; PWND Window; - PMENU_OBJECT Menu; + PMENU Menu; DECLARE_RETURN(BOOL); TRACE("Enter NtUserSetSystemMenu\n"); diff --git a/reactos/win32ss/user/user32/windows/menu.c b/reactos/win32ss/user/user32/windows/menu.c index d3eeae860bc..bf335d60d4a 100644 --- a/reactos/win32ss/user/user32/windows/menu.c +++ b/reactos/win32ss/user/user32/windows/menu.c @@ -14,6 +14,7 @@ #include LRESULT DefWndNCPaint(HWND hWnd, HRGN hRgn, BOOL Active); +BOOL WINAPI GdiValidateHandle(HGDIOBJ hobj); WINE_DEFAULT_DEBUG_CHANNEL(menu); @@ -44,15 +45,30 @@ WINE_DEFAULT_DEBUG_CHANNEL(menu); #define MENU_ITEM_TYPE(flags) ((flags) & MENU_TYPE_MASK) +#define MNS_STYLE_MASK (MNS_NOCHECK|MNS_MODELESS|MNS_DRAGDROP|MNS_AUTODISMISS|MNS_NOTIFYBYPOS|MNS_CHECKORBMP) + +#define MENUITEMINFO_TYPE_MASK \ + (MFT_STRING | MFT_BITMAP | MFT_OWNERDRAW | MFT_SEPARATOR | \ + MFT_MENUBARBREAK | MFT_MENUBREAK | MFT_RADIOCHECK | \ + MFT_RIGHTORDER | MFT_RIGHTJUSTIFY /* same as MF_HELP */ ) + +#define TYPE_MASK (MENUITEMINFO_TYPE_MASK | MF_POPUP | MF_SYSMENU) + +#define STATE_MASK (~TYPE_MASK) + +#define MENUITEMINFO_STATE_MASK (STATE_MASK & ~(MF_BYPOSITION | MF_MOUSESELECT)) + +#define MII_STATE_MASK (MFS_GRAYED|MFS_CHECKED|MFS_HILITE|MFS_DEFAULT) + /* 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_MAGIC_BITMAP(id) ((id) && ((INT_PTR)(id) < 12) && ((INT_PTR)(id) >= -1)) #define IS_SYSTEM_MENU(MenuInfo) \ - (0 == ((MenuInfo)->Flags & MNF_POPUP) && 0 != ((MenuInfo)->Flags & MNF_SYSDESKMN)) + (0 == ((MenuInfo)->fFlags & MNF_POPUP) && 0 != ((MenuInfo)->fFlags & MNF_SYSDESKMN)) #define IS_SYSTEM_POPUP(MenuInfo) \ - (0 != ((MenuInfo)->Flags & MNF_POPUP) && 0 != ((MenuInfo)->Flags & MNF_SYSDESKMN)) + (0 != ((MenuInfo)->fFlags & MNF_POPUP) && 0 != ((MenuInfo)->fFlags & MNF_SYSDESKMN)) #define IS_BITMAP_ITEM(flags) (MF_BITMAP == MENU_ITEM_TYPE(flags)) @@ -108,6 +124,250 @@ static HBITMAP BmpSysMenu = NULL; static SIZE MenuCharSize; + +/*********************************************************************** + * MENU_GetMenu + * + * Validate the given menu handle and returns the menu structure pointer. + */ +PMENU FORCEINLINE MENU_GetMenu(HMENU hMenu) +{ + return ValidateHandle(hMenu, TYPE_MENU); +} + +/*********************************************************************** + * MENU_FindItem + * + * Find a menu item. Return a pointer on the item, and modifies *hmenu + * in case the item was in a sub-menu. + */ +ITEM *MENU_FindItem( HMENU *hmenu, UINT *nPos, UINT wFlags ) +{ + MENU *menu; + ITEM *fallback = NULL; + UINT fallback_pos = 0; + UINT i; + PITEM pItem; + + if ((*hmenu == (HMENU)0xffff) || (!(menu = MENU_GetMenu(*hmenu)))) return NULL; + if (wFlags & MF_BYPOSITION) + { + if (*nPos >= menu->cItems) return NULL; + pItem = menu->rgItems ? DesktopPtrToUser(menu->rgItems) : NULL; + //pItem = &menu->rgItems[*nPos]; + i = 0; + while(pItem) // Do this for now. + { + if (i < (INT)menu->cItems) + { + if ( *nPos == i ) return pItem; + } + pItem = pItem->Next ? DesktopPtrToUser(pItem->Next) : NULL; + i++; + } + } + else + { + PITEM item = menu->rgItems ? DesktopPtrToUser(menu->rgItems) : NULL; + for (i = 0; item ,i < menu->cItems; i++, item = item->Next ? DesktopPtrToUser(item->Next) : NULL)//, item++) + { + if (item->spSubMenu) + { + PMENU pSubMenu = DesktopPtrToUser(item->spSubMenu); + HMENU hsubmenu = UserHMGetHandle(pSubMenu); + ITEM *subitem = MENU_FindItem( &hsubmenu, nPos, wFlags ); + if (subitem) + { + *hmenu = hsubmenu; + return subitem; + } + else if (item->wID == *nPos) + { + /* fallback to this item if nothing else found */ + fallback_pos = i; + fallback = item; + } + } + else if (item->wID == *nPos) + { + *nPos = i; + return item; + } + } + } + + if (fallback) + *nPos = fallback_pos; + + return fallback; +} + +#define MAX_GOINTOSUBMENU (0x10) +UINT FASTCALL +IntGetMenuDefaultItem(PMENU Menu, BOOL fByPos, UINT gmdiFlags, DWORD *gismc) +{ + UINT x = 0; + UINT res = -1; + UINT sres; + PITEM Item = Menu->rgItems ? DesktopPtrToUser(Menu->rgItems) : NULL; + + while(Item) + { + if (Item->fState & MFS_DEFAULT) + { + if (!(gmdiFlags & GMDI_USEDISABLED) && + (Item->fState & MFS_DISABLED) ) + break; + + res = fByPos ? x : Item->wID; + + if ((*gismc < MAX_GOINTOSUBMENU) && + (gmdiFlags & GMDI_GOINTOPOPUPS) && + Item->spSubMenu) + { + if (DesktopPtrToUser(Item->spSubMenu) == Menu) + break; + + (*gismc)++; + sres = IntGetMenuDefaultItem( DesktopPtrToUser(Item->spSubMenu), fByPos, gmdiFlags, gismc); + (*gismc)--; + + if(sres > (UINT)-1) + res = sres; + } + break; + } + Item = Item->Next ? DesktopPtrToUser(Item->Next) : NULL; + x++; + } + return res; +} + +static BOOL GetMenuItemInfo_common ( HMENU hmenu, + UINT item, + BOOL bypos, + LPMENUITEMINFOW lpmii, + BOOL unicode) +{ + ITEM *pItem = MENU_FindItem (&hmenu, &item, bypos ? MF_BYPOSITION : 0); + + //debug_print_menuitem("GetMenuItemInfo_common: ", pItem, ""); + + if (!pItem) + { + SetLastError( ERROR_MENU_ITEM_NOT_FOUND); + //SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + if( lpmii->fMask & MIIM_TYPE) + { + if( lpmii->fMask & ( MIIM_STRING | MIIM_FTYPE | MIIM_BITMAP)) + { + ERR("invalid combination of fMask bits used\n"); + /* this does not happen on Win9x/ME */ + SetLastError( ERROR_INVALID_PARAMETER); + return FALSE; + } + lpmii->fType = pItem->fType & MENUITEMINFO_TYPE_MASK; + if( pItem->hbmp) lpmii->fType |= MFT_BITMAP; + lpmii->hbmpItem = pItem->hbmp; /* not on Win9x/ME */ + if( lpmii->fType & MFT_BITMAP) + { + lpmii->dwTypeData = (LPWSTR) pItem->hbmp; + lpmii->cch = 0; + } + else if( lpmii->fType & (MFT_OWNERDRAW | MFT_SEPARATOR)) + { + /* this does not happen on Win9x/ME */ + lpmii->dwTypeData = 0; + lpmii->cch = 0; + } + } + + /* copy the text string */ + if ((lpmii->fMask & (MIIM_TYPE|MIIM_STRING))) + { + if( !pItem->Xlpstr ) + { // Very strange this fixes a wine test with a crash. + if(lpmii->dwTypeData && lpmii->cch && !(GdiValidateHandle((HGDIOBJ)lpmii->dwTypeData)) ) + { + lpmii->cch = 0; + if( unicode) + *((WCHAR *)lpmii->dwTypeData) = 0; + else + *((CHAR *)lpmii->dwTypeData) = 0; + } + } + else + { + int len; + LPWSTR text = DesktopPtrToUser(pItem->Xlpstr); + if (unicode) + { + len = strlenW(text); + if(lpmii->dwTypeData && lpmii->cch) + lstrcpynW(lpmii->dwTypeData, text, lpmii->cch); + } + else + { + len = WideCharToMultiByte( CP_ACP, 0, text, -1, NULL, 0, NULL, NULL ) - 1; + if(lpmii->dwTypeData && lpmii->cch) + if (!WideCharToMultiByte( CP_ACP, 0, text, -1, + (LPSTR)lpmii->dwTypeData, lpmii->cch, NULL, NULL )) + ((LPSTR)lpmii->dwTypeData)[lpmii->cch - 1] = 0; + } + /* if we've copied a substring we return its length */ + if(lpmii->dwTypeData && lpmii->cch) + if (lpmii->cch <= len + 1) + lpmii->cch--; + else + lpmii->cch = len; + else + { + /* return length of string */ + /* not on Win9x/ME if fType & MFT_BITMAP */ + lpmii->cch = len; + } + } + } + + if (lpmii->fMask & MIIM_FTYPE) + lpmii->fType = pItem->fType & MENUITEMINFO_TYPE_MASK; + + if (lpmii->fMask & MIIM_BITMAP) + lpmii->hbmpItem = pItem->hbmp; + + if (lpmii->fMask & MIIM_STATE) + lpmii->fState = pItem->fState & MII_STATE_MASK; //MENUITEMINFO_STATE_MASK; + + if (lpmii->fMask & MIIM_ID) + lpmii->wID = pItem->wID; + + if (lpmii->fMask & MIIM_SUBMENU && pItem->spSubMenu ) + { + PMENU pSubMenu = DesktopPtrToUser(pItem->spSubMenu); + HMENU hSubMenu = UserHMGetHandle(pSubMenu); + lpmii->hSubMenu = hSubMenu; + } + else + { + /* hSubMenu is always cleared + * (not on Win9x/ME ) */ + lpmii->hSubMenu = 0; + } + + if (lpmii->fMask & MIIM_CHECKMARKS) + { + lpmii->hbmpChecked = pItem->hbmpChecked; + lpmii->hbmpUnchecked = pItem->hbmpUnchecked; + } + if (lpmii->fMask & MIIM_DATA) + lpmii->dwItemData = pItem->dwItemData; + + return TRUE; +} + /*********************************************************************** * MenuGetRosMenuInfo * @@ -116,10 +376,31 @@ static SIZE MenuCharSize; static BOOL FASTCALL MenuGetRosMenuInfo(PROSMENUINFO MenuInfo, HMENU Menu) { - MenuInfo->cbSize = sizeof(ROSMENUINFO); - MenuInfo->fMask = MIM_BACKGROUND | MIM_HELPID | MIM_MAXHEIGHT | MIM_MENUDATA | MIM_STYLE; + PMENU pMenu; + if (!(pMenu = ValidateHandle(Menu, TYPE_MENU))) return FALSE; - return NtUserMenuInfo(Menu, MenuInfo, FALSE); + MenuInfo->hbrBack = pMenu->hbrBack; + MenuInfo->dwContextHelpID = pMenu->dwContextHelpId; + MenuInfo->cyMax = pMenu->cyMax; + MenuInfo->dwMenuData = pMenu->dwMenuData; + MenuInfo->dwStyle = pMenu->fFlags & MNS_STYLE_MASK; + + MenuInfo->cItems = pMenu->cItems; + + MenuInfo->iItem = pMenu->iItem; + MenuInfo->cxMenu = pMenu->cxMenu; + MenuInfo->cyMenu = pMenu->cyMenu; + MenuInfo->spwndNotify = pMenu->spwndNotify; + MenuInfo->cxTextAlign = pMenu->cxTextAlign; + MenuInfo->iTop = pMenu->iMaxTop; + MenuInfo->iMaxTop = pMenu->iMaxTop; + MenuInfo->dwArrowsOn = pMenu->dwArrowsOn; + + MenuInfo->fFlags = pMenu->fFlags; + MenuInfo->Self = pMenu->head.h; + MenuInfo->TimeToHide = pMenu->TimeToHide; + MenuInfo->Wnd = pMenu->hWnd; + return TRUE; } /*********************************************************************** @@ -133,7 +414,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); + return NtUserThunkedMenuInfo(MenuInfo->Self, (LPCMENUINFO)MenuInfo); } /*********************************************************************** @@ -156,41 +437,68 @@ MenuInitRosMenuItemInfo(PROSMENUITEMINFO ItemInfo) static BOOL FASTCALL MenuGetRosMenuItemInfo(HMENU Menu, UINT Index, PROSMENUITEMINFO ItemInfo) { + PITEM pItem; 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; ItemInfo->dwTypeData = NULL; - if (! NtUserMenuItemInfo(Menu, Index, TRUE, ItemInfo, FALSE)) - { + if (!(pItem = MENU_FindItem(&Menu, &Index, MF_BYPOSITION))) + { ItemInfo->fType = 0; return FALSE; - } + } + + ItemInfo->fType = pItem->fType; + ItemInfo->hbmpItem = pItem->hbmp; + ItemInfo->hbmpChecked = pItem->hbmpChecked; + ItemInfo->hbmpUnchecked = pItem->hbmpUnchecked; + ItemInfo->dwItemData = pItem->dwItemData; + ItemInfo->wID = pItem->wID; + ItemInfo->fState = pItem->fState; + + if (pItem->spSubMenu) + { + PMENU pSubMenu = DesktopPtrToUser(pItem->spSubMenu); + HMENU hSubMenu = UserHMGetHandle(pSubMenu); + ItemInfo->hSubMenu = hSubMenu; + } + else + ItemInfo->hSubMenu = NULL; if (MENU_ITEM_TYPE(ItemInfo->fType) == MF_STRING) - { - ItemInfo->cch++; - ItemInfo->dwTypeData = HeapAlloc(GetProcessHeap(), 0, - ItemInfo->cch * sizeof(WCHAR)); - if (NULL == ItemInfo->dwTypeData) + { + LPWSTR lpstr = pItem->lpstr.Buffer ? DesktopPtrToUser(pItem->lpstr.Buffer) : NULL; + if (lpstr) + { + ItemInfo->cch = pItem->lpstr.Length / sizeof(WCHAR); + ItemInfo->cch++; + ItemInfo->dwTypeData = HeapAlloc(GetProcessHeap(), 0, ItemInfo->cch * sizeof(WCHAR)); + if (ItemInfo->dwTypeData == NULL) { - return FALSE; + return FALSE; } + RtlCopyMemory(ItemInfo->dwTypeData, lpstr, min(ItemInfo->cch * sizeof(WCHAR), pItem->lpstr.MaximumLength)); + } + else + { + ItemInfo->cch = 0; + } + } + + ItemInfo->Rect.left = pItem->xItem; + ItemInfo->Rect.top = pItem->yItem; + ItemInfo->Rect.right = pItem->cxItem; // Do this for now...... + ItemInfo->Rect.bottom = pItem->cyItem; + ItemInfo->dxTab = pItem->dxTab; + ItemInfo->lpstr = pItem->lpstr.Buffer; + ItemInfo->maxBmpSize.cx = pItem->cxBmp; + ItemInfo->maxBmpSize.cy = pItem->cyBmp; - if (! NtUserMenuItemInfo(Menu, Index, TRUE, ItemInfo, FALSE)) - { - ItemInfo->fType = 0; - return FALSE; - } - ItemInfo->dwTypeData[ItemInfo->cch - 1] = UNICODE_NULL; - } ItemInfo->fMask = Save_Mask; return TRUE; } @@ -210,8 +518,7 @@ MenuSetRosMenuItemInfo(HMENU Menu, UINT Index, PROSMENUITEMINFO ItemInfo) { ItemInfo->cch = strlenW(ItemInfo->dwTypeData); } - Ret = NtUserMenuItemInfo(Menu, Index, TRUE, ItemInfo, TRUE); - + Ret = NtUserThunkedMenuItemInfo(Menu, Index, TRUE, FALSE, (LPMENUITEMINFOW)ItemInfo, NULL); return Ret; } @@ -224,10 +531,105 @@ static VOID FASTCALL MenuCleanupRosMenuItemInfo(PROSMENUITEMINFO ItemInfo) { if (ItemInfo->dwTypeData != NULL) - { + { HeapFree(GetProcessHeap(), 0, ItemInfo->dwTypeData); ItemInfo->dwTypeData = NULL; - } + } +} + +DWORD FASTCALL +IntBuildMenuItemList(PMENU MenuObject, PVOID Buffer, ULONG nMax) +{ + DWORD res = 0; + ROSMENUITEMINFO mii; + PVOID Buf; + PITEM CurItem = MenuObject->rgItems ? DesktopPtrToUser(MenuObject->rgItems) : NULL; + PWCHAR StrOut; + WCHAR NulByte; + + if (0 != nMax) + { + if (nMax < MenuObject->cItems * sizeof(ROSMENUITEMINFO)) + { + return 0; + } + StrOut = (PWCHAR)((char *) Buffer + MenuObject->cItems * sizeof(ROSMENUITEMINFO)); + nMax -= MenuObject->cItems * sizeof(ROSMENUITEMINFO); + Buf = Buffer; + mii.cbSize = sizeof(ROSMENUITEMINFO); + mii.fMask = 0; + NulByte = L'\0'; + + while (NULL != CurItem) + { + mii.cch = CurItem->lpstr.Length / sizeof(WCHAR); + mii.dwItemData = CurItem->dwItemData; + if (0 != CurItem->lpstr.Length) + { + mii.dwTypeData = StrOut; + } + else + { + mii.dwTypeData = NULL; + } + mii.fState = CurItem->fState; + mii.fType = CurItem->fType; + mii.wID = CurItem->wID; + mii.hbmpChecked = CurItem->hbmpChecked; + mii.hbmpItem = CurItem->hbmp; + mii.hbmpUnchecked = CurItem->hbmpUnchecked; + if (CurItem->spSubMenu) + { + PMENU pSubMenu = DesktopPtrToUser(CurItem->spSubMenu); + HMENU hSubMenu = UserHMGetHandle(pSubMenu); + mii.hSubMenu = hSubMenu; + } + else + mii.hSubMenu = NULL; + mii.Rect.left = CurItem->xItem; + mii.Rect.top = CurItem->yItem; + mii.Rect.right = CurItem->cxItem; // Do this for now...... + mii.Rect.bottom = CurItem->cyItem; + mii.dxTab = CurItem->dxTab; + mii.lpstr = CurItem->lpstr.Buffer; // Can be read from user side! + //mii.maxBmpSize.cx = CurItem->cxBmp; + //mii.maxBmpSize.cy = CurItem->cyBmp; + + RtlCopyMemory(Buf, &mii, sizeof(ROSMENUITEMINFO)); + Buf = (PVOID)((ULONG_PTR)Buf + sizeof(ROSMENUITEMINFO)); + + if (0 != CurItem->lpstr.Length && (nMax >= CurItem->lpstr.Length + sizeof(WCHAR))) + { + LPWSTR lpstr = CurItem->lpstr.Buffer ? DesktopPtrToUser(CurItem->lpstr.Buffer) : NULL; + if (lpstr) + { + /* Copy string */ + RtlCopyMemory(StrOut, lpstr, CurItem->lpstr.Length); + + StrOut += CurItem->lpstr.Length / sizeof(WCHAR); + RtlCopyMemory(StrOut, &NulByte, sizeof(WCHAR)); + StrOut++; + nMax -= CurItem->lpstr.Length + sizeof(WCHAR); + } + } + else if (0 != CurItem->lpstr.Length) + { + break; + } + + CurItem = CurItem->Next ? DesktopPtrToUser(CurItem->Next) : NULL; + res++; + } + } + else + { + while (NULL != CurItem) + { + res += sizeof(ROSMENUITEMINFO) + CurItem->lpstr.Length + sizeof(WCHAR); + CurItem = CurItem->Next ? DesktopPtrToUser(CurItem->Next) : NULL; + } + } + return res; } /*********************************************************************** @@ -239,19 +641,22 @@ static INT FASTCALL MenuGetAllRosMenuItemInfo(HMENU Menu, PROSMENUITEMINFO *ItemInfo) { DWORD BufSize; + PMENU pMenu; - BufSize = NtUserBuildMenuItemList(Menu, (VOID *) 1, 0, 0); + if (!(pMenu = ValidateHandle(Menu, TYPE_MENU))) return -1; + + BufSize = IntBuildMenuItemList(pMenu, (PVOID)1, 0); if (BufSize == (DWORD) -1 || BufSize == 0) - { + { return -1; - } + } *ItemInfo = HeapAlloc(GetProcessHeap(), 0, BufSize); if (NULL == *ItemInfo) - { + { return -1; - } + } - return NtUserBuildMenuItemList(Menu, *ItemInfo, BufSize, 0); + return IntBuildMenuItemList(pMenu, (PVOID)*ItemInfo, BufSize); } /*********************************************************************** @@ -319,14 +724,14 @@ static UINT MenuGetStartOfNextColumn( PROSMENUITEMINFO MenuItems; UINT i; - i = MenuInfo->FocusedItem; + i = MenuInfo->iItem; if ( i == NO_SELECTED_ITEM ) return i; if (MenuGetAllRosMenuItemInfo(MenuInfo->Self, &MenuItems) <= 0) return NO_SELECTED_ITEM; - for (i++ ; i < MenuInfo->MenuItemCount; i++) + for (i++ ; i < MenuInfo->cItems; i++) if (0 != (MenuItems[i].fType & (MF_MENUBREAK | MF_MENUBARBREAK))) return i; @@ -346,14 +751,14 @@ static UINT FASTCALL MenuGetStartOfPrevColumn( PROSMENUITEMINFO MenuItems; UINT i; - if (!MenuInfo->FocusedItem || MenuInfo->FocusedItem == NO_SELECTED_ITEM) + if (!MenuInfo->iItem || MenuInfo->iItem == NO_SELECTED_ITEM) return NO_SELECTED_ITEM; if (MenuGetAllRosMenuItemInfo(MenuInfo->Self, &MenuItems) <= 0) return NO_SELECTED_ITEM; /* Find the start of the column */ - for (i = MenuInfo->FocusedItem; + for (i = MenuInfo->iItem; 0 != i && 0 == (MenuItems[i].fType & (MF_MENUBREAK | MF_MENUBARBREAK)); --i) { @@ -376,47 +781,6 @@ static UINT FASTCALL MenuGetStartOfPrevColumn( return i; } -/*********************************************************************** - * MenuFindSubMenu - * - * Find a Sub menu. Return the position of the submenu, and modifies - * *hmenu in case it is found in another sub-menu. - * If the submenu cannot be found, NO_SELECTED_ITEM is returned. - */ -static UINT FASTCALL MenuFindSubMenu(HMENU *hmenu, HMENU hSubTarget ) -{ - ROSMENUINFO menu; - UINT i; - ROSMENUITEMINFO item; - if (((*hmenu)==(HMENU)0xffff) || - (!MenuGetRosMenuInfo(&menu, *hmenu))) - return NO_SELECTED_ITEM; - - MenuInitRosMenuItemInfo(&item); - for (i = 0; i < menu.MenuItemCount; i++) { - if (! MenuGetRosMenuItemInfo(menu.Self, i, &item)) - { - MenuCleanupRosMenuItemInfo(&item); - return NO_SELECTED_ITEM; - } - if (!(item.hSubMenu)) continue; - if (item.hSubMenu == hSubTarget) { - MenuCleanupRosMenuItemInfo(&item); - return i; - } - else { - HMENU hsubmenu = item.hSubMenu; - UINT pos = MenuFindSubMenu(&hsubmenu, hSubTarget ); - if (pos != NO_SELECTED_ITEM) { - *hmenu = hsubmenu; - return pos; - } - } - } - MenuCleanupRosMenuItemInfo(&item); - return NO_SELECTED_ITEM; -} - /*********************************************************************** * MenuLoadBitmaps * @@ -432,6 +796,126 @@ MenuLoadBitmaps(VOID) BmpSysMenu = LoadBitmapW(0, MAKEINTRESOURCEW(OBM_CLOSE)); } } +/////////// Make gpsi OBMI via callback ////////////// +/*********************************************************************** + * get_arrow_bitmap + */ +HBITMAP get_arrow_bitmap(void) +{ + static HBITMAP arrow_bitmap; + + if (!arrow_bitmap) arrow_bitmap = LoadBitmapW(0, MAKEINTRESOURCEW(OBM_MNARROW)); + return arrow_bitmap; +} + +/*********************************************************************** + * get_down_arrow_bitmap DFCS_MENUARROWDOWN + */ +HBITMAP get_down_arrow_bitmap(void) +{ + static HBITMAP arrow_bitmap; + + if (!arrow_bitmap) arrow_bitmap = LoadBitmapW(0, MAKEINTRESOURCEW(OBM_DNARROW)); + return arrow_bitmap; +} + +/*********************************************************************** + * get_down_arrow_inactive_bitmap DFCS_MENUARROWDOWN | DFCS_INACTIVE + */ +HBITMAP get_down_arrow_inactive_bitmap(void) +{ + static HBITMAP arrow_bitmap; + + if (!arrow_bitmap) arrow_bitmap = LoadBitmapW(0, MAKEINTRESOURCEW(OBM_DNARROWI)); + return arrow_bitmap; +} + +/*********************************************************************** + * get_up_arrow_bitmap DFCS_MENUARROWUP + */ +HBITMAP get_up_arrow_bitmap(void) +{ + static HBITMAP arrow_bitmap; + + if (!arrow_bitmap) arrow_bitmap = LoadBitmapW(0, MAKEINTRESOURCEW(OBM_UPARROW)); + return arrow_bitmap; +} + +/*********************************************************************** + * get_up_arrow_inactive_bitmap DFCS_MENUARROWUP | DFCS_INACTIVE + */ +static HBITMAP get_up_arrow_inactive_bitmap(void) +{ + static HBITMAP arrow_bitmap; + + if (!arrow_bitmap) arrow_bitmap = LoadBitmapW(0, MAKEINTRESOURCEW(OBM_UPARROWI)); + return arrow_bitmap; +} +//////////////// +/*********************************************************************** + * MenuFindSubMenu + * + * Find a Sub menu. Return the position of the submenu, and modifies + * *hmenu in case it is found in another sub-menu. + * If the submenu cannot be found, NO_SELECTED_ITEM is returned. + */ +static UINT FASTCALL MenuFindSubMenu(HMENU *hmenu, HMENU hSubTarget ) +{ + PMENU menu, pSubMenu; + HMENU hSubMenu; + UINT i; + PITEM item; + + if (((*hmenu)==(HMENU)0xffff) ||(!(menu = MENU_GetMenu(*hmenu)))) + return NO_SELECTED_ITEM; + + item = menu->rgItems ? DesktopPtrToUser(menu->rgItems) : NULL; + for (i = 0; i < menu->cItems; i++, item = item->Next ? DesktopPtrToUser(item->Next) : NULL)//item++) + { + if (!item->spSubMenu) + continue; + else + { + pSubMenu = DesktopPtrToUser(item->spSubMenu); + hSubMenu = UserHMGetHandle(pSubMenu); + if (hSubMenu == hSubTarget) + { + return i; + } + else + { + HMENU hsubmenu = hSubMenu; + UINT pos = MenuFindSubMenu( &hsubmenu, hSubTarget ); + if (pos != NO_SELECTED_ITEM) + { + *hmenu = hsubmenu; + return pos; + } + } + } + } + return NO_SELECTED_ITEM; +} + +/*********************************************************************** + * MENU_AdjustMenuItemRect + * + * Adjust menu item rectangle according to scrolling state. + */ +static void +MENU_AdjustMenuItemRect(PROSMENUINFO menu, LPRECT rect) +{ + if (menu->dwArrowsOn) + { + UINT arrow_bitmap_height; + BITMAP bmp; + + GetObjectW(get_up_arrow_bitmap(), sizeof(bmp), &bmp); + arrow_bitmap_height = bmp.bmHeight; + rect->top += arrow_bitmap_height - menu->iTop; + rect->bottom += arrow_bitmap_height - menu->iTop; + } +} /*********************************************************************** * MenuDrawPopupGlyph @@ -535,7 +1019,7 @@ static UINT FASTCALL MenuFindItemByKey(HWND WndOwner, PROSMENUINFO MenuInfo, if ( !ForceMenuChar ) { ItemInfo = Items; - for (i = 0; i < MenuInfo->MenuItemCount; i++, ItemInfo++) + for (i = 0; i < MenuInfo->cItems; i++, ItemInfo++) { if ((ItemInfo->lpstr) && NULL != ItemInfo->dwTypeData) { @@ -550,8 +1034,8 @@ static UINT FASTCALL MenuFindItemByKey(HWND WndOwner, PROSMENUINFO MenuInfo, } } - Flags |= MenuInfo->Flags & MNF_POPUP ? MF_POPUP : 0; - Flags |= MenuInfo->Flags & MNF_SYSDESKMN ? MF_SYSMENU : 0; + Flags |= MenuInfo->fFlags & MNF_POPUP ? MF_POPUP : 0; + Flags |= MenuInfo->fFlags & MNF_SYSDESKMN ? MF_SYSMENU : 0; MenuChar = SendMessageW(WndOwner, WM_MENUCHAR, MAKEWPARAM(Key, Flags), (LPARAM) MenuInfo->Self); @@ -631,7 +1115,7 @@ static void FASTCALL MenuGetBitmapItemSize(PROSMENUITEMINFO lpitem, SIZE *size, * Draw a bitmap item. */ static void FASTCALL MenuDrawBitmapItem(HDC hdc, PROSMENUITEMINFO lpitem, const RECT *rect, - HMENU hmenu, HWND WndOwner, UINT odaction, BOOL MenuBar) + PROSMENUINFO MenuInfo, HWND WndOwner, UINT odaction, BOOL MenuBar) { BITMAP bm; DWORD rop; @@ -699,7 +1183,9 @@ static void FASTCALL MenuDrawBitmapItem(HDC hdc, PROSMENUITEMINFO lpitem, const 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.itemState |= (!(MenuInfo->fFlags & MNF_UNDERLINE))?ODS_NOACCEL:0; + //drawItem.itemState |= (MenuInfo->fFlags & MNF_INACTIVE)?ODS_INACTIVE:0; + drawItem.hwndItem = (HWND)MenuInfo->Self; drawItem.hDC = hdc; drawItem.rcItem = *rect; drawItem.itemData = lpitem->dwItemData; @@ -750,14 +1236,19 @@ static void FASTCALL MenuDrawBitmapItem(HDC hdc, PROSMENUITEMINFO lpitem, const * Calculate the size of the menu item and store it in lpitem->rect. */ static void FASTCALL MenuCalcItemSize( HDC hdc, PROSMENUITEMINFO lpitem, PROSMENUINFO MenuInfo, HWND hwndOwner, - INT orgX, INT orgY, BOOL menuBar) + INT orgX, INT orgY, BOOL menuBar, BOOL textandbmp) { WCHAR *p; UINT check_bitmap_width = GetSystemMetrics( SM_CXMENUCHECK ); + UINT arrow_bitmap_width; + BITMAP bm; INT itemheight = 0; TRACE("dc=%x owner=%x (%d,%d)\n", hdc, hwndOwner, orgX, orgY); + GetObjectW( get_arrow_bitmap(), sizeof(bm), &bm ); + arrow_bitmap_width = bm.bmWidth; + MenuCharSize.cx = GdiGetCharDimensions( hdc, NULL, &MenuCharSize.cy ); SetRect( &lpitem->Rect, orgX, orgY, orgX, orgY ); @@ -776,24 +1267,26 @@ static void FASTCALL MenuCalcItemSize( HDC hdc, PROSMENUITEMINFO lpitem, PROSMEN * 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; - + // Or this, + //Item->cxBmp = mis.itemWidth; + //Item->cyBmp = mis.itemHeight; TRACE("id=%04lx size=%dx%d\n", - lpitem->wID, mis.itemWidth, mis.itemHeight); + lpitem->wID, lpitem->Rect.right-lpitem->Rect.left, + lpitem->Rect.bottom-lpitem->Rect.top); return; } if (lpitem->fType & MF_SEPARATOR) { - lpitem->Rect.bottom += SEPARATOR_HEIGHT; + lpitem->Rect.bottom += GetSystemMetrics( SM_CYMENUSIZE)/2;//SEPARATOR_HEIGHT; if( !menuBar) - lpitem->Rect.right += check_bitmap_width + MenuCharSize.cx; + lpitem->Rect.right += arrow_bitmap_width/*check_bitmap_width*/ + MenuCharSize.cx; return; } @@ -807,21 +1300,17 @@ static void FASTCALL MenuCalcItemSize( HDC hdc, PROSMENUITEMINFO lpitem, PROSMEN 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)) - { - MenuInfo->maxBmpSize.cx = abs(size.cx) + MENU_ITEM_HBMP_SPACE; - MenuInfo->maxBmpSize.cy = abs(size.cy); - } + lpitem->maxBmpSize = size; + MenuInfo->cxTextAlign = max(MenuInfo->cxTextAlign, size.cx); MenuSetRosMenuInfo(MenuInfo); + lpitem->Rect.right += size.cx + 2; itemheight = size.cy + 2; if( !(MenuInfo->dwStyle & MNS_NOCHECK)) lpitem->Rect.right += 2 * check_bitmap_width; lpitem->Rect.right += 4 + MenuCharSize.cx; lpitem->dxTab = lpitem->Rect.right; - lpitem->Rect.right += check_bitmap_width; + lpitem->Rect.right += arrow_bitmap_width;//check_bitmap_width; } else /* hbmpItem & MenuBar */ { MenuGetBitmapItemSize(lpitem, &size, hwndOwner ); lpitem->Rect.right += size.cx; @@ -894,6 +1383,17 @@ static void FASTCALL MenuCalcItemSize( HDC hdc, PROSMENUITEMINFO lpitem, PROSMEN TRACE("(%ld,%ld)-(%ld,%ld)\n", lpitem->Rect.left, lpitem->Rect.top, lpitem->Rect.right, lpitem->Rect.bottom); } +/*********************************************************************** + * MENU_GetMaxPopupHeight + */ +static UINT +MENU_GetMaxPopupHeight(PROSMENUINFO lppop) +{ + if (lppop->cyMax) + return lppop->cyMax; + return GetSystemMetrics(SM_CYSCREEN) - GetSystemMetrics(SM_CYBORDER); +} + /*********************************************************************** * MenuPopupMenuCalcSize * @@ -904,10 +1404,11 @@ static void FASTCALL MenuPopupMenuCalcSize(PROSMENUINFO MenuInfo, HWND WndOwner) ROSMENUITEMINFO lpitem; HDC hdc; int start, i; - int orgX, orgY, maxX, maxTab, maxTabWidth; + int orgX, orgY, maxX, maxTab, maxTabWidth, maxHeight; + BOOL textandbmp = FALSE; - MenuInfo->Width = MenuInfo->Height = 0; - if (MenuInfo->MenuItemCount == 0) + MenuInfo->cxMenu = MenuInfo->cyMenu = 0; + if (MenuInfo->cItems == 0) { MenuSetRosMenuInfo(MenuInfo); return; @@ -919,11 +1420,10 @@ static void FASTCALL MenuPopupMenuCalcSize(PROSMENUINFO MenuInfo, HWND WndOwner) start = 0; maxX = 2 + 1; - MenuInfo->maxBmpSize.cx = 0; - MenuInfo->maxBmpSize.cy = 0; + MenuInfo->cxTextAlign = 0; MenuInitRosMenuItemInfo(&lpitem); - while (start < MenuInfo->MenuItemCount) + while (start < MenuInfo->cItems) { orgX = maxX; orgY = 2; @@ -931,7 +1431,7 @@ static void FASTCALL MenuPopupMenuCalcSize(PROSMENUINFO MenuInfo, HWND WndOwner) maxTab = maxTabWidth = 0; /* Parse items until column break or end of menu */ - for (i = start; i < MenuInfo->MenuItemCount; i++) + for (i = start; i < MenuInfo->cItems; i++) { if (! MenuGetRosMenuItemInfo(MenuInfo->Self, i, &lpitem)) { @@ -942,7 +1442,9 @@ static void FASTCALL MenuPopupMenuCalcSize(PROSMENUINFO MenuInfo, HWND WndOwner) if (i != start && (lpitem.fType & (MF_MENUBREAK | MF_MENUBARBREAK))) break; - MenuCalcItemSize(hdc, &lpitem, MenuInfo, WndOwner, orgX, orgY, FALSE); + if( lpitem.lpstr && lpitem.hbmpItem) textandbmp = TRUE; + + MenuCalcItemSize(hdc, &lpitem, MenuInfo, WndOwner, orgX, orgY, FALSE, textandbmp); if (! MenuSetRosMenuItemInfo(MenuInfo->Self, i, &lpitem)) { MenuCleanupRosMenuItemInfo(&lpitem); @@ -957,7 +1459,7 @@ static void FASTCALL MenuPopupMenuCalcSize(PROSMENUINFO MenuInfo, HWND WndOwner) maxX = max(maxX, lpitem.Rect.right); orgY = lpitem.Rect.bottom; if ((lpitem.lpstr) && lpitem.dxTab ) - { + { maxTab = max( maxTab, lpitem.dxTab ); maxTabWidth = max(maxTabWidth, lpitem.Rect.right - lpitem.dxTab); } @@ -978,14 +1480,33 @@ static void FASTCALL MenuPopupMenuCalcSize(PROSMENUINFO MenuInfo, HWND WndOwner) } start++; } - MenuInfo->Height = max(MenuInfo->Height, orgY); + MenuInfo->cyMenu = max(MenuInfo->cyMenu, orgY); } - MenuInfo->Width = maxX; + MenuInfo->cxMenu = maxX; + /* if none of the items have both text and bitmap then + * the text and bitmaps are all aligned on the left. If there is at + * least one item with both text and bitmap then bitmaps are + * on the left and texts left aligned with the right hand side + * of the bitmaps */ + if( !textandbmp) MenuInfo->cxTextAlign = 0; /* space for 3d border */ - MenuInfo->Height += 2; - MenuInfo->Width += 2; + MenuInfo->cyMenu += MENU_BOTTOM_MARGIN; + MenuInfo->cxMenu += 2; + + /* Adjust popup height if it exceeds maximum */ + maxHeight = MENU_GetMaxPopupHeight(MenuInfo); + MenuInfo->iMaxTop = MenuInfo->cyMenu - MENU_TOP_MARGIN; + if (MenuInfo->cyMenu >= maxHeight) + { + MenuInfo->cyMenu = maxHeight; + MenuInfo->dwArrowsOn = 1; + } + else + { + MenuInfo->dwArrowsOn = 0; + } MenuCleanupRosMenuItemInfo(&lpitem); MenuSetRosMenuInfo(MenuInfo); @@ -1008,19 +1529,18 @@ static void FASTCALL MenuMenuBarCalcSize( HDC hdc, LPRECT lprect, int start, i, orgX, orgY, maxY, helpPos; if ((lprect == NULL) || (MenuInfo == NULL)) return; - if (MenuInfo->MenuItemCount == 0) return; + if (MenuInfo->cItems == 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; + MenuInfo->cxMenu = lprect->right - lprect->left; + MenuInfo->cyMenu = 0; maxY = lprect->top + 1; start = 0; helpPos = -1; - MenuInfo->maxBmpSize.cx = 0; - MenuInfo->maxBmpSize.cy = 0; + MenuInfo->cxTextAlign = 0; MenuInitRosMenuItemInfo(&ItemInfo); - while (start < MenuInfo->MenuItemCount) + while (start < MenuInfo->cItems) { if (! MenuGetRosMenuItemInfo(MenuInfo->Self, start, &ItemInfo)) { @@ -1031,14 +1551,14 @@ static void FASTCALL MenuMenuBarCalcSize( HDC hdc, LPRECT lprect, orgY = maxY; /* Parse items until line break or end of menu */ - for (i = start; i < MenuInfo->MenuItemCount; i++) + for (i = start; i < MenuInfo->cItems; 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); + MenuCalcItemSize(hdc, &ItemInfo, MenuInfo, hwndOwner, orgX, orgY, TRUE, FALSE); if (! MenuSetRosMenuItemInfo(MenuInfo->Self, i, &ItemInfo)) { MenuCleanupRosMenuItemInfo(&ItemInfo); @@ -1052,7 +1572,7 @@ static void FASTCALL MenuMenuBarCalcSize( HDC hdc, LPRECT lprect, } maxY = max( maxY, ItemInfo.Rect.bottom ); orgX = ItemInfo.Rect.right; - if (i + 1 < MenuInfo->MenuItemCount) + if (i + 1 < MenuInfo->cItems) { if (! MenuGetRosMenuItemInfo(MenuInfo->Self, i + 1, &ItemInfo)) { @@ -1081,21 +1601,21 @@ HBMMENU_MBAR_CLOSE, MINIMIZE & RESTORE, look the same size as the menu bar! */ } lprect->bottom = maxY; - MenuInfo->Height = lprect->bottom - lprect->top; + MenuInfo->cyMenu = 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)) + if (! MenuGetRosMenuItemInfo(MenuInfo->Self, MenuInfo->cItems - 1, &ItemInfo)) { MenuCleanupRosMenuItemInfo(&ItemInfo); return; } orgY = ItemInfo.Rect.top; orgX = lprect->right; - for (i = MenuInfo->MenuItemCount - 1; helpPos <= i; i--) + for (i = MenuInfo->cItems - 1; helpPos <= i; i--) { if (i < helpPos) { @@ -1125,6 +1645,51 @@ HBMMENU_MBAR_CLOSE, MINIMIZE & RESTORE, look the same size as the menu bar! */ MenuCleanupRosMenuItemInfo(&ItemInfo); } +/*********************************************************************** + * MENU_DrawScrollArrows + * + * Draw scroll arrows. + */ +static void +MENU_DrawScrollArrows(PROSMENUINFO lppop, HDC hdc) +{ + HDC hdcMem = CreateCompatibleDC(hdc); + HBITMAP hOrigBitmap; + UINT arrow_bitmap_width, arrow_bitmap_height; + BITMAP bmp; + RECT rect; + + GetObjectW(get_down_arrow_bitmap(), sizeof(bmp), &bmp); + arrow_bitmap_width = bmp.bmWidth; + arrow_bitmap_height = bmp.bmHeight; + + + if (lppop->iTop) + hOrigBitmap = SelectObject(hdcMem, get_up_arrow_bitmap()); + else + hOrigBitmap = SelectObject(hdcMem, get_up_arrow_inactive_bitmap()); + rect.left = 0; + rect.top = 0; + rect.right = lppop->cxMenu; + rect.bottom = arrow_bitmap_height; + FillRect(hdc, &rect, GetSysColorBrush(COLOR_MENU)); + BitBlt(hdc, (lppop->cxMenu - arrow_bitmap_width) / 2, 0, + arrow_bitmap_width, arrow_bitmap_height, hdcMem, 0, 0, SRCCOPY); + rect.top = lppop->cyMenu - arrow_bitmap_height; + rect.bottom = lppop->cyMenu; + FillRect(hdc, &rect, GetSysColorBrush(COLOR_MENU)); + if (lppop->iTop < lppop->iMaxTop - (MENU_GetMaxPopupHeight(lppop) - 2 * arrow_bitmap_height)) + SelectObject(hdcMem, get_down_arrow_bitmap()); + else + SelectObject(hdcMem, get_down_arrow_inactive_bitmap()); + BitBlt(hdc, (lppop->cxMenu - arrow_bitmap_width) / 2, + lppop->cyMenu - arrow_bitmap_height, + arrow_bitmap_width, arrow_bitmap_height, hdcMem, 0, 0, SRCCOPY); + SelectObject(hdcMem, hOrigBitmap); + DeleteDC(hdcMem); +} + + /*********************************************************************** * MenuDrawMenuItem * @@ -1180,6 +1745,7 @@ static void FASTCALL MenuDrawMenuItem(HWND hWnd, PROSMENUINFO MenuInfo, HWND Wnd } rect = lpitem->Rect; + MENU_AdjustMenuItemRect(MenuInfo, &rect); if (lpitem->fType & MF_OWNERDRAW) { @@ -1199,9 +1765,13 @@ static void FASTCALL MenuDrawMenuItem(HWND hWnd, PROSMENUINFO MenuInfo, HWND Wnd 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; + if (lpitem->fState & MF_CHECKED) dis.itemState |= ODS_CHECKED; + if (lpitem->fState & MF_DEFAULT) dis.itemState |= ODS_DEFAULT; + if (lpitem->fState & MF_DISABLED) dis.itemState |= ODS_DISABLED; + if (lpitem->fState & MF_GRAYED) dis.itemState |= ODS_GRAYED | ODS_DISABLED; + if (lpitem->fState & MF_HILITE) dis.itemState |= ODS_SELECTED; + //if (!(MenuInfo->fFlags & MNF_UNDERLINE)) dis.itemState |= ODS_NOACCEL; + //if (MenuInfo->fFlags & MNF_INACTIVE) dis.itemState |= ODS_INACTIVE; dis.itemAction = odaction; /* ODA_DRAWENTIRE | ODA_SELECT | ODA_FOCUS; */ dis.hwndItem = (HWND) MenuInfo->Self; dis.hDC = hdc; @@ -1346,8 +1916,8 @@ static void FASTCALL MenuDrawMenuItem(HWND hWnd, PROSMENUINFO MenuInfo, HWND Wnd bmpRect.left += check_bitmap_width + 2; if (!(checked && (MenuInfo->dwStyle & MNS_CHECKORBMP))) { - bmpRect.right = bmpRect.left + MenuInfo->maxBmpSize.cx; - MenuDrawBitmapItem(hdc, lpitem, &bmpRect, MenuInfo->Self, WndOwner, odaction, menuBar); + bmpRect.right = bmpRect.left + lpitem->maxBmpSize.cx; + MenuDrawBitmapItem(hdc, lpitem, &bmpRect, MenuInfo, WndOwner, odaction, menuBar); } } /* Draw the popup-menu arrow */ @@ -1365,7 +1935,7 @@ static void FASTCALL MenuDrawMenuItem(HWND hWnd, PROSMENUINFO MenuInfo, HWND Wnd } else if( lpitem->hbmpItem) { /* Draw the bitmap */ - MenuDrawBitmapItem(hdc, lpitem, &rect, MenuInfo->Self, WndOwner, odaction, menuBar); + MenuDrawBitmapItem(hdc, lpitem, &rect, MenuInfo, WndOwner, odaction, menuBar); } /* process text if present */ @@ -1374,13 +1944,14 @@ static void FASTCALL MenuDrawMenuItem(HWND hWnd, PROSMENUINFO MenuInfo, HWND Wnd register int i = 0; HFONT hfontOld = 0; - UINT uFormat = menuBar ? DT_CENTER | DT_VCENTER | DT_SINGLELINE - : DT_LEFT | DT_VCENTER | DT_SINGLELINE; + UINT uFormat = menuBar ? + DT_CENTER | DT_VCENTER | DT_SINGLELINE : + DT_LEFT | DT_VCENTER | DT_SINGLELINE; - if(MenuInfo->dwStyle & MNS_CHECKORBMP) - rect.left += max(0, MenuInfo->maxBmpSize.cx - GetSystemMetrics(SM_CXMENUCHECK)); + if((MenuInfo->dwStyle & MNS_CHECKORBMP)) + rect.left += max(0, MenuInfo->cxTextAlign - GetSystemMetrics(SM_CXMENUCHECK)); else - rect.left += MenuInfo->maxBmpSize.cx; + rect.left += MenuInfo->cxTextAlign; if ( lpitem->fState & MFS_DEFAULT ) { @@ -1482,21 +2053,26 @@ static void FASTCALL MenuDrawPopupMenu(HWND hwnd, HDC hdc, HMENU hmenu ) DrawEdge (hdc, &rect, EDGE_RAISED, BF_RECT); /* draw menu items */ - if (MenuGetRosMenuInfo(&MenuInfo, hmenu) && MenuInfo.MenuItemCount) + if (MenuGetRosMenuInfo(&MenuInfo, hmenu) && MenuInfo.cItems) { UINT u; - - MenuInitRosMenuItemInfo(&ItemInfo); + MenuInitRosMenuItemInfo(&ItemInfo); - for (u = 0; u < MenuInfo.MenuItemCount; u++) + for (u = 0; u < MenuInfo.cItems; u++) { if (MenuGetRosMenuItemInfo(MenuInfo.Self, u, &ItemInfo)) { - MenuDrawMenuItem(hwnd, &MenuInfo, MenuInfo.WndOwner, hdc, &ItemInfo, - MenuInfo.Height, FALSE, ODA_DRAWENTIRE); + HWND WndOwner = MenuInfo.spwndNotify ? MenuInfo.spwndNotify->head.h : NULL; + MenuDrawMenuItem(hwnd, &MenuInfo, WndOwner, hdc, &ItemInfo, + MenuInfo.cyMenu, FALSE, ODA_DRAWENTIRE); } } + /* draw scroll arrows */ + if (MenuInfo.dwArrowsOn) + MENU_DrawScrollArrows(&MenuInfo, hdc); + + MenuSetRosMenuInfo(&MenuInfo); MenuCleanupRosMenuItemInfo(&ItemInfo); } } else @@ -1530,15 +2106,16 @@ UINT MenuDrawMenuBar( HDC hDC, LPRECT lprect, HWND hwnd, MenuMenuBarCalcSize(hDC, lprect, &lppop, hwnd); - lprect->bottom = lprect->top + lppop.Height; + lprect->bottom = lprect->top + lppop.cyMenu; if (hfontOld) SelectObject( hDC, hfontOld); - return lppop.Height; + return lppop.cyMenu; } else return DrawMenuBarTemp(hwnd, hDC, lprect, hMenu, NULL); } + /*********************************************************************** * MenuShowPopup * @@ -1559,17 +2136,17 @@ static BOOL FASTCALL MenuShowPopup(HWND hwndOwner, HMENU hmenu, UINT id, UINT fl hwndOwner, hmenu, id, x, y, xanchor, yanchor); if (! MenuGetRosMenuInfo(&MenuInfo, hmenu)) return FALSE; - if (MenuInfo.FocusedItem != NO_SELECTED_ITEM) + if (MenuInfo.iItem != NO_SELECTED_ITEM) { MenuInitRosMenuItemInfo(&ItemInfo); - if (MenuGetRosMenuItemInfo(MenuInfo.Self, MenuInfo.FocusedItem, &ItemInfo)) + if (MenuGetRosMenuItemInfo(MenuInfo.Self, MenuInfo.iItem, &ItemInfo)) { ItemInfo.fMask |= MIIM_STATE; ItemInfo.fState &= ~(MF_HILITE|MF_MOUSESELECT); - MenuSetRosMenuItemInfo(MenuInfo.Self, MenuInfo.FocusedItem, &ItemInfo); + MenuSetRosMenuItemInfo(MenuInfo.Self, MenuInfo.iItem, &ItemInfo); } MenuCleanupRosMenuItemInfo(&ItemInfo); - MenuInfo.FocusedItem = NO_SELECTED_ITEM; + MenuInfo.iItem = NO_SELECTED_ITEM; } /* store the owner for DrawItem */ @@ -1578,15 +2155,15 @@ static BOOL FASTCALL MenuShowPopup(HWND hwndOwner, HMENU hmenu, UINT id, UINT fl SetLastError( ERROR_INVALID_WINDOW_HANDLE ); return FALSE; } - MenuInfo.WndOwner = hwndOwner; + MenuInfo.spwndNotify = ValidateHwndNoErr(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); + width = MenuInfo.cxMenu + GetSystemMetrics(SM_CXBORDER); + height = MenuInfo.cyMenu + GetSystemMetrics(SM_CYBORDER); /* FIXME: should use item rect */ pt.x = x; @@ -1647,6 +2224,44 @@ static BOOL FASTCALL MenuShowPopup(HWND hwndOwner, HMENU hmenu, UINT id, UINT fl return TRUE; } +/*********************************************************************** + * MENU_EnsureMenuItemVisible + */ +void +MENU_EnsureMenuItemVisible(PROSMENUINFO lppop, PROSMENUITEMINFO item, HDC hdc) +{ + if (lppop->dwArrowsOn) + { + //ITEM *item = &lppop->items[wIndex]; + UINT nMaxHeight = MENU_GetMaxPopupHeight(lppop); + UINT nOldPos = lppop->iTop; + RECT rc; + UINT arrow_bitmap_height; + BITMAP bmp; + + GetClientRect(lppop->Wnd, &rc); + + GetObjectW(get_down_arrow_bitmap(), sizeof(bmp), &bmp); + arrow_bitmap_height = bmp.bmHeight; + + rc.top += arrow_bitmap_height; + rc.bottom -= arrow_bitmap_height + MENU_BOTTOM_MARGIN; + + nMaxHeight -= GetSystemMetrics(SM_CYBORDER) + 2 * arrow_bitmap_height; + if (item->Rect.bottom > lppop->iTop + nMaxHeight) + { + lppop->iTop = item->Rect.bottom - nMaxHeight; + ScrollWindow(lppop->Wnd, 0, nOldPos - lppop->iTop, &rc, &rc); + MENU_DrawScrollArrows(lppop, hdc); + } + else if (item->Rect.top - MENU_TOP_MARGIN < lppop->iTop) + { + lppop->iTop = item->Rect.top - MENU_TOP_MARGIN; + ScrollWindow(lppop->Wnd, 0, nOldPos - lppop->iTop, &rc, &rc); + MENU_DrawScrollArrows(lppop, hdc); + } + } +} /*********************************************************************** * MenuSelectItem @@ -1660,9 +2275,9 @@ static void FASTCALL MenuSelectItem(HWND hwndOwner, PROSMENUINFO hmenu, UINT wIn TRACE("owner=%p menu=%p index=0x%04x select=0x%04x\n", hwndOwner, hmenu, wIndex, sendMenuSelect); - if (!hmenu || !hmenu->MenuItemCount || !hmenu->Wnd) return; - if (hmenu->FocusedItem == wIndex) return; - if (hmenu->Flags & MNF_POPUP) hdc = GetDC(hmenu->Wnd); + if (!hmenu || !hmenu->cItems || !hmenu->Wnd) return; + if (hmenu->iItem == wIndex) return; + if (hmenu->fFlags & MNF_POPUP) hdc = GetDC(hmenu->Wnd); else hdc = GetDCEx(hmenu->Wnd, 0, DCX_CACHE | DCX_WINDOW); if (!top_popup) { top_popup = hmenu->Wnd; @@ -1674,33 +2289,34 @@ static void FASTCALL MenuSelectItem(HWND hwndOwner, PROSMENUINFO hmenu, UINT wIn MenuInitRosMenuItemInfo(&ItemInfo); /* Clear previous highlighted item */ - if (hmenu->FocusedItem != NO_SELECTED_ITEM) + if (hmenu->iItem != NO_SELECTED_ITEM) { - if (MenuGetRosMenuItemInfo(hmenu->Self, hmenu->FocusedItem, &ItemInfo)) + if (MenuGetRosMenuItemInfo(hmenu->Self, hmenu->iItem, &ItemInfo)) { ItemInfo.fMask |= MIIM_STATE; ItemInfo.fState &= ~(MF_HILITE|MF_MOUSESELECT); - MenuSetRosMenuItemInfo(hmenu->Self, hmenu->FocusedItem, &ItemInfo); + MenuSetRosMenuItemInfo(hmenu->Self, hmenu->iItem, &ItemInfo); } + //MENU_EnsureMenuItemVisible(hmenu, &ItemInfo, hdc); MenuDrawMenuItem(hmenu->Wnd, hmenu, hwndOwner, hdc, &ItemInfo, - hmenu->Height, !(hmenu->Flags & MNF_POPUP), + hmenu->cyMenu, !(hmenu->fFlags & MNF_POPUP), ODA_SELECT); } /* Highlight new item (if any) */ - hmenu->FocusedItem = wIndex; + hmenu->iItem = wIndex; MenuSetRosMenuInfo(hmenu); - if (hmenu->FocusedItem != NO_SELECTED_ITEM) + if (hmenu->iItem != NO_SELECTED_ITEM) { - if (MenuGetRosMenuItemInfo(hmenu->Self, hmenu->FocusedItem, &ItemInfo)) + if (MenuGetRosMenuItemInfo(hmenu->Self, hmenu->iItem, &ItemInfo)) { if (!(ItemInfo.fType & MF_SEPARATOR)) { ItemInfo.fMask |= MIIM_STATE; ItemInfo.fState |= MF_HILITE; - MenuSetRosMenuItemInfo(hmenu->Self, hmenu->FocusedItem, &ItemInfo); + MenuSetRosMenuItemInfo(hmenu->Self, hmenu->iItem, &ItemInfo); MenuDrawMenuItem(hmenu->Wnd, hmenu, hwndOwner, hdc, - &ItemInfo, hmenu->Height, !(hmenu->Flags & MNF_POPUP), + &ItemInfo, hmenu->cyMenu, !(hmenu->fFlags & MNF_POPUP), ODA_SELECT); } if (sendMenuSelect) @@ -1708,7 +2324,7 @@ static void FASTCALL MenuSelectItem(HWND hwndOwner, PROSMENUINFO hmenu, UINT wIn WPARAM wParam = MAKEWPARAM( ItemInfo.hSubMenu ? wIndex : ItemInfo.wID, ItemInfo.fType | ItemInfo.fState | (ItemInfo.hSubMenu ? MF_POPUP : 0) | - (hmenu->Flags & MNF_SYSDESKMN ? MF_SYSMENU : 0 ) ); + (hmenu->fFlags & MNF_SYSDESKMN ? MF_SYSMENU : 0 ) ); SendMessageW(hwndOwner, WM_MENUSELECT, wParam, (LPARAM) hmenu->Self); } @@ -1727,7 +2343,7 @@ static void FASTCALL MenuSelectItem(HWND hwndOwner, PROSMENUINFO hmenu, UINT wIn { WPARAM wParam = MAKEWPARAM( Pos, ItemInfo.fType | ItemInfo.fState | (ItemInfo.hSubMenu ? MF_POPUP : 0) | - (TopMenuInfo.Flags & MNF_SYSDESKMN ? MF_SYSMENU : 0 ) ); + (TopMenuInfo.fFlags & MNF_SYSDESKMN ? MF_SYSMENU : 0 ) ); SendMessageW(hwndOwner, WM_MENUSELECT, wParam, (LPARAM) topmenu); } @@ -1755,7 +2371,7 @@ MenuMoveSelection(HWND WndOwner, PROSMENUINFO MenuInfo, INT Offset) TRACE("hwnd=%x menu=%x off=0x%04x\n", WndOwner, MenuInfo, Offset); /* Prevent looping */ - if (0 == MenuInfo->MenuItemCount || 0 == Offset) + if (0 == MenuInfo->cItems || 0 == Offset) return; else if (Offset < -1) Offset = -1; @@ -1764,7 +2380,7 @@ MenuMoveSelection(HWND WndOwner, PROSMENUINFO MenuInfo, INT Offset) MenuInitRosMenuItemInfo(&ItemInfo); - OrigPos = MenuInfo->FocusedItem; + OrigPos = MenuInfo->iItem; if (OrigPos == NO_SELECTED_ITEM) /* NO_SELECTED_ITEM is not -1 ! */ { OrigPos = 0; @@ -1772,7 +2388,7 @@ MenuMoveSelection(HWND WndOwner, PROSMENUINFO MenuInfo, INT Offset) } else { - i = MenuInfo->FocusedItem; + i = MenuInfo->iItem; } do @@ -1782,9 +2398,9 @@ MenuMoveSelection(HWND WndOwner, PROSMENUINFO MenuInfo, INT Offset) /* Clip and wrap around */ if (i < 0) { - i = MenuInfo->MenuItemCount - 1; + i = MenuInfo->cItems - 1; } - else if (i >= MenuInfo->MenuItemCount) + else if (i >= MenuInfo->cItems) { i = 0; } @@ -1802,13 +2418,13 @@ MenuMoveSelection(HWND WndOwner, PROSMENUINFO MenuInfo, INT Offset) MenuCleanupRosMenuItemInfo(&ItemInfo); } -// -// This breaks some test results. Should handle A2U if called! -// -LRESULT WINAPI PopupMenuWndProcA(HWND Wnd, UINT Message, WPARAM wParam, LPARAM lParam) +#if 0 +LRESULT WINAPI +PopupMenuWndProcW(HWND Wnd, UINT Message, WPARAM wParam, LPARAM lParam) { -#ifdef __REACTOS__ +#ifdef __REACTOS__ // Do this now, remove after Server side is fixed. PWND pWnd; + PPOPUPMENU pPopupMenu; pWnd = ValidateHwnd(Wnd); if (pWnd) @@ -1817,9 +2433,12 @@ LRESULT WINAPI PopupMenuWndProcA(HWND Wnd, UINT Message, WPARAM wParam, LPARAM l { if (Message != WM_NCCREATE) { - return DefWindowProcA(Wnd, Message, wParam, lParam); + return DefWindowProcW(Wnd, Message, wParam, lParam); } NtUserSetWindowFNID(Wnd, FNID_MENU); + pPopupMenu = HeapAlloc( GetProcessHeap(), 0, sizeof(POPUPMENU) ); + pPopupMenu->spwndPopupMenu = pWnd; + SetWindowLongPtrW(Wnd, 0, (LONG_PTR)pPopupMenu); } else { @@ -1828,18 +2447,19 @@ LRESULT WINAPI PopupMenuWndProcA(HWND Wnd, UINT Message, WPARAM wParam, LPARAM l ERR("Wrong window class for Menu!\n"); return 0; } + pPopupMenu = ((PMENUWND)pWnd)->ppopupmenu; } } #endif - TRACE("YES! hwnd=%x msg=0x%04x wp=0x%04lx 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) { case WM_CREATE: { - CREATESTRUCTA *cs = (CREATESTRUCTA *) lParam; - SetWindowLongPtrA(Wnd, 0, (LONG_PTR)cs->lpCreateParams); + CREATESTRUCTW *cs = (CREATESTRUCTW *) lParam; + pPopupMenu->spmenu = ValidateHandle(cs->lpCreateParams, TYPE_MENU); return 0; } @@ -1850,16 +2470,15 @@ LRESULT WINAPI PopupMenuWndProcA(HWND Wnd, UINT Message, WPARAM wParam, LPARAM l { PAINTSTRUCT ps; BeginPaint(Wnd, &ps); - MenuDrawPopupMenu(Wnd, ps.hdc, (HMENU)GetWindowLongPtrA(Wnd, 0)); + MenuDrawPopupMenu(Wnd, ps.hdc, pPopupMenu->spmenu->head.h); EndPaint(Wnd, &ps); return 0; } case WM_PRINTCLIENT: { - MenuDrawPopupMenu( Wnd, (HDC)wParam, - (HMENU)GetWindowLongPtrW( Wnd, 0 ) ); - return 0; + MenuDrawPopupMenu( Wnd, (HDC)wParam, pPopupMenu->spmenu->head.h); + return 0; } case WM_ERASEBKGND: @@ -1874,39 +2493,51 @@ LRESULT WINAPI PopupMenuWndProcA(HWND Wnd, UINT Message, WPARAM wParam, LPARAM l } break; -#ifdef __REACTOS__ case WM_NCDESTROY: + { + HeapFree( GetProcessHeap(), 0, pPopupMenu ); + SetWindowLongPtrW(Wnd, 0, 0); NtUserSetWindowFNID(Wnd, FNID_DESTROY); break; -#endif + } case WM_SHOWWINDOW: if (0 != wParam) - { - if (0 == GetWindowLongPtrA(Wnd, 0)) - { + { + if (!pPopupMenu || !pPopupMenu->spmenu) + { OutputDebugStringA("no menu to display\n"); - } - } - else - { - SetWindowLongPtrA(Wnd, 0, 0); - } + } + } + /*else + { + pPopupMenu->spmenu = NULL; ///// WTF? + }*/ break; case MM_SETMENUHANDLE: - SetWindowLongPtrA(Wnd, 0, wParam); - break; + { + PMENU pmenu = ValidateHandle((HMENU)wParam, TYPE_MENU); + if (!pmenu) + { + ERR("Bad Menu Handle\n"); + break; + } + pPopupMenu->spmenu = pmenu; + break; + } case MM_GETMENUHANDLE: - case MN_GETHMENU: - return GetWindowLongPtrA(Wnd, 0); + case MN_GETHMENU: + return (LRESULT)(pPopupMenu ? (pPopupMenu->spmenu ? pPopupMenu->spmenu->head.h : NULL) : NULL); default: - return DefWindowProcA(Wnd, Message, wParam, lParam); + return DefWindowProcW(Wnd, Message, wParam, lParam); } + return 0; } +#endif LRESULT WINAPI PopupMenuWndProcW(HWND Wnd, UINT Message, WPARAM wParam, LPARAM lParam) @@ -2007,6 +2638,42 @@ PopupMenuWndProcW(HWND Wnd, UINT Message, WPARAM wParam, LPARAM lParam) return 0; } +// +// This breaks some test results. Should handle A2U if called! +// +LRESULT WINAPI PopupMenuWndProcA(HWND Wnd, UINT Message, WPARAM wParam, LPARAM lParam) +{ + PWND pWnd; + + pWnd = ValidateHwnd(Wnd); + if (pWnd && !pWnd->fnid && Message != WM_NCCREATE) + { + return DefWindowProcA(Wnd, Message, wParam, lParam); + } + TRACE("YES! hwnd=%x msg=0x%04x wp=0x%04lx lp=0x%08lx\n", Wnd, Message, wParam, lParam); + + switch(Message) + { + case WM_NCCREATE: + case WM_CREATE: + case WM_MOUSEACTIVATE: + case WM_PAINT: + case WM_PRINTCLIENT: + case WM_ERASEBKGND: + case WM_DESTROY: + case WM_NCDESTROY: + case WM_SHOWWINDOW: + case MM_SETMENUHANDLE: + case MM_GETMENUHANDLE: + case MN_GETHMENU: + return PopupMenuWndProcW(Wnd, Message, wParam, lParam); + + default: + return DefWindowProcA(Wnd, Message, wParam, lParam); + } + return 0; +} + /********************************************************************** * MENU_ParseResource * @@ -2129,7 +2796,7 @@ User32LoadSysMenuTemplateForKernel(PVOID Arguments, ULONG ArgumentLength) menuinfo.cbSize = sizeof(menuinfo); menuinfo.fMask = MIM_STYLE; GetMenuInfo(hmenu, &menuinfo); - menuinfo.dwStyle |= MNS_NOCHECK; + menuinfo.dwStyle |= MNS_CHECKORBMP; // test_menu_bmp_and_string MNS_CHECKORBMP SetMenuInfo(hmenu, &menuinfo); // adding bitmaps to menu items @@ -2241,12 +2908,12 @@ DrawMenuBarTemp(HWND Wnd, HDC DC, LPRECT Rect, HMENU Menu, HFONT Font) FontOld = SelectObject(DC, Font); - if (0 == MenuInfo.Height) + if (0 == MenuInfo.cyMenu) { MenuMenuBarCalcSize(DC, Rect, &MenuInfo, Wnd); } - Rect->bottom = Rect->top + MenuInfo.Height; + Rect->bottom = Rect->top + MenuInfo.cyMenu; FillRect(DC, Rect, GetSysColorBrush(flat_menu ? COLOR_MENUBAR : COLOR_MENU)); @@ -2255,28 +2922,57 @@ DrawMenuBarTemp(HWND Wnd, HDC DC, LPRECT Rect, HMENU Menu, HFONT Font) MoveToEx(DC, Rect->left, Rect->bottom - 1, NULL); LineTo(DC, Rect->right, Rect->bottom - 1); - if (0 == MenuInfo.MenuItemCount) + if (0 == MenuInfo.cItems) { SelectObject(DC, FontOld); return GetSystemMetrics(SM_CYMENU); } MenuInitRosMenuItemInfo(&ItemInfo); - for (i = 0; i < MenuInfo.MenuItemCount; i++) + for (i = 0; i < MenuInfo.cItems; i++) { if (MenuGetRosMenuItemInfo(MenuInfo.Self, i, &ItemInfo)) { MenuDrawMenuItem(Wnd, &MenuInfo, Wnd, DC, &ItemInfo, - MenuInfo.Height, TRUE, ODA_DRAWENTIRE); + MenuInfo.cyMenu, TRUE, ODA_DRAWENTIRE); } } MenuCleanupRosMenuItemInfo(&ItemInfo); SelectObject(DC, FontOld); - return MenuInfo.Height; + return MenuInfo.cyMenu; } +#if 0 +static BOOL MENU_InitPopup( HWND hwndOwner, HMENU hmenu, UINT flags ) +{ + POPUPMENU *menu; + DWORD ex_style = 0; + TRACE("owner=%p hmenu=%p\n", hwndOwner, hmenu); + + if (!(menu = MENU_GetMenu( hmenu ))) return FALSE; + + /* store the owner for DrawItem */ + if (!IsWindow( hwndOwner )) + { + SetLastError( ERROR_INVALID_WINDOW_HANDLE ); + return FALSE; + } + menu->hwndOwner = hwndOwner; + + if (flags & TPM_LAYOUTRTL) + ex_style = WS_EX_LAYOUTRTL; + + /* NOTE: In Windows, top menu popup is not owned. */ + menu->hWnd = CreateWindowExW( ex_style, (LPCWSTR)POPUPMENU_CLASS_ATOM, NULL, + WS_POPUP, 0, 0, 0, 0, + hwndOwner, 0, (HINSTANCE)GetWindowLongPtrW(hwndOwner, GWLP_HINSTANCE), + (LPVOID)hmenu ); + if( !menu->hWnd ) return FALSE; + return TRUE; +} +#endif /*********************************************************************** * MenuShowSubPopup * @@ -2295,13 +2991,13 @@ MenuShowSubPopup(HWND WndOwner, PROSMENUINFO MenuInfo, BOOL SelectFirst, UINT Fl TRACE("owner=%x menu=%p 0x%04x\n", WndOwner, MenuInfo, SelectFirst); - if (NO_SELECTED_ITEM == MenuInfo->FocusedItem) + if (NO_SELECTED_ITEM == MenuInfo->iItem) { return MenuInfo->Self; } MenuInitRosMenuItemInfo(&ItemInfo); - if (! MenuGetRosMenuItemInfo(MenuInfo->Self, MenuInfo->FocusedItem, &ItemInfo)) + if (! MenuGetRosMenuItemInfo(MenuInfo->Self, MenuInfo->iItem, &ItemInfo)) { MenuCleanupRosMenuItemInfo(&ItemInfo); return MenuInfo->Self; @@ -2319,10 +3015,10 @@ MenuShowSubPopup(HWND WndOwner, PROSMENUINFO MenuInfo, BOOL SelectFirst, UINT Fl if (0 == (Flags & TPM_NONOTIFY)) { SendMessageW(WndOwner, WM_INITMENUPOPUP, (WPARAM) ItemInfo.hSubMenu, - MAKELPARAM(MenuInfo->FocusedItem, IS_SYSTEM_MENU(MenuInfo))); + MAKELPARAM(MenuInfo->iItem, IS_SYSTEM_MENU(MenuInfo))); } - if (! MenuGetRosMenuItemInfo(MenuInfo->Self, MenuInfo->FocusedItem, &ItemInfo)) + if (! MenuGetRosMenuItemInfo(MenuInfo->Self, MenuInfo->iItem, &ItemInfo)) { MenuCleanupRosMenuItemInfo(&ItemInfo); return MenuInfo->Self; @@ -2332,7 +3028,7 @@ MenuShowSubPopup(HWND WndOwner, PROSMENUINFO MenuInfo, BOOL SelectFirst, UINT Fl /* correct item if modified as a reaction to WM_INITMENUPOPUP message */ if (0 == (ItemInfo.fState & MF_HILITE)) { - if (0 != (MenuInfo->Flags & MNF_POPUP)) + if (0 != (MenuInfo->fFlags & MNF_POPUP)) { Dc = GetDC(MenuInfo->Wnd); } @@ -2344,9 +3040,9 @@ MenuShowSubPopup(HWND WndOwner, PROSMENUINFO MenuInfo, BOOL SelectFirst, UINT Fl SelectObject(Dc, hMenuFont); ItemInfo.fMask |= MIIM_STATE; ItemInfo.fState |= MF_HILITE; - MenuSetRosMenuItemInfo(MenuInfo->Self, MenuInfo->FocusedItem, &ItemInfo); - MenuDrawMenuItem(MenuInfo->Wnd, MenuInfo, WndOwner, Dc, &ItemInfo, MenuInfo->Height, - ! (MenuInfo->Flags & MNF_POPUP), ODA_DRAWENTIRE); + MenuSetRosMenuItemInfo(MenuInfo->Self, MenuInfo->iItem, &ItemInfo); + MenuDrawMenuItem(MenuInfo->Wnd, MenuInfo, WndOwner, Dc, &ItemInfo, MenuInfo->cyMenu, + !(MenuInfo->fFlags & MNF_POPUP), ODA_DRAWENTIRE); ReleaseDC(MenuInfo->Wnd, Dc); } @@ -2358,10 +3054,11 @@ MenuShowSubPopup(HWND WndOwner, PROSMENUINFO MenuInfo, BOOL SelectFirst, UINT Fl ItemInfo.fMask |= MIIM_STATE; ItemInfo.fState |= MF_MOUSESELECT; - MenuSetRosMenuItemInfo(MenuInfo->Self, MenuInfo->FocusedItem, &ItemInfo); + MenuSetRosMenuItemInfo(MenuInfo->Self, MenuInfo->iItem, &ItemInfo); if (IS_SYSTEM_MENU(MenuInfo)) - { + { + ERR("Right click on window bar and Draw system menu!\n"); MenuInitSysMenuPopup(ItemInfo.hSubMenu, GetWindowLongPtrW(MenuInfo->Wnd, GWL_STYLE), GetClassLongPtrW(MenuInfo->Wnd, GCL_STYLE), HTSYSMENU); if (Flags & TPM_LAYOUTRTL) Rect.left; @@ -2369,19 +3066,23 @@ MenuShowSubPopup(HWND WndOwner, PROSMENUINFO MenuInfo, BOOL SelectFirst, UINT Fl Rect.top = Rect.bottom; Rect.right = GetSystemMetrics(SM_CXSIZE); Rect.bottom = GetSystemMetrics(SM_CYSIZE); - } + } else { GetWindowRect(MenuInfo->Wnd, &Rect); - if (0 != (MenuInfo->Flags & MNF_POPUP)) + if (0 != (MenuInfo->fFlags & MNF_POPUP)) { + RECT rc = ItemInfo.Rect; + + MENU_AdjustMenuItemRect(MenuInfo, &rc); + if(Flags & TPM_LAYOUTRTL) Rect.left += GetSystemMetrics(SM_CXBORDER); else Rect.left += ItemInfo.Rect.right- GetSystemMetrics(SM_CXBORDER); - Rect.top += ItemInfo.Rect.top - MENU_TOP_MARGIN;//3; - Rect.right = ItemInfo.Rect.left - ItemInfo.Rect.right + GetSystemMetrics(SM_CXBORDER); - Rect.bottom = ItemInfo.Rect.top - ItemInfo.Rect.bottom - MENU_TOP_MARGIN - MENU_BOTTOM_MARGIN/*2*/ + Rect.top += rc.top - MENU_TOP_MARGIN;//3; + Rect.right = rc.left - rc.right + GetSystemMetrics(SM_CXBORDER); + Rect.bottom = rc.top - rc.bottom - MENU_TOP_MARGIN - MENU_BOTTOM_MARGIN/*2*/ - GetSystemMetrics(SM_CYBORDER); } else @@ -2399,7 +3100,9 @@ MenuShowSubPopup(HWND WndOwner, PROSMENUINFO MenuInfo, BOOL SelectFirst, UINT Fl /* use default alignment for submenus */ Flags &= ~(TPM_CENTERALIGN | TPM_RIGHTALIGN | TPM_VCENTERALIGN | TPM_BOTTOMALIGN); - MenuShowPopup(WndOwner, ItemInfo.hSubMenu, MenuInfo->FocusedItem, Flags, + //MENU_InitPopup( WndOwner, ItemInfo.hSubMenu, Flags ); + + MenuShowPopup(WndOwner, ItemInfo.hSubMenu, MenuInfo->iItem, Flags, Rect.left, Rect.top, Rect.right, Rect.bottom ); if (SelectFirst && MenuGetRosMenuInfo(&SubMenuInfo, ItemInfo.hSubMenu)) { @@ -2425,7 +3128,7 @@ void MENU_EndMenu( HWND hwnd ) BOOL Ret = FALSE; if (top_popup_hmenu) Ret = MenuGetRosMenuInfo(&MenuInfo, top_popup_hmenu); - if (Ret && hwnd == MenuInfo.WndOwner) EndMenu(); + if (Ret && hwnd == (MenuInfo.spwndNotify ? MenuInfo.spwndNotify->head.h : NULL)) EndMenu(); } /*********************************************************************** @@ -2442,11 +3145,11 @@ MenuHideSubPopups(HWND WndOwner, PROSMENUINFO MenuInfo, TRACE("owner=%x menu=%x 0x%04x\n", WndOwner, MenuInfo, SendMenuSelect); - if (NULL != MenuInfo && NULL != top_popup && NO_SELECTED_ITEM != MenuInfo->FocusedItem) + if (NULL != MenuInfo && NULL != top_popup && NO_SELECTED_ITEM != MenuInfo->iItem) { MenuInitRosMenuItemInfo(&ItemInfo); ItemInfo.fMask |= MIIM_FTYPE | MIIM_STATE; - if (! MenuGetRosMenuItemInfo(MenuInfo->Self, MenuInfo->FocusedItem, &ItemInfo) + if (! MenuGetRosMenuItemInfo(MenuInfo->Self, MenuInfo->iItem, &ItemInfo) || 0 == (ItemInfo.hSubMenu) || 0 == (ItemInfo.fState & MF_MOUSESELECT)) { @@ -2455,7 +3158,7 @@ MenuHideSubPopups(HWND WndOwner, PROSMENUINFO MenuInfo, } ItemInfo.fState &= ~MF_MOUSESELECT; ItemInfo.fMask |= MIIM_STATE; - MenuSetRosMenuItemInfo(MenuInfo->Self, MenuInfo->FocusedItem, &ItemInfo); + MenuSetRosMenuItemInfo(MenuInfo->Self, MenuInfo->iItem, &ItemInfo); if (MenuGetRosMenuInfo(&SubMenuInfo, ItemInfo.hSubMenu)) { MenuHideSubPopups(WndOwner, &SubMenuInfo, FALSE, wFlags); @@ -2485,7 +3188,7 @@ MenuSwitchTracking(MTRACKER* Mt, PROSMENUINFO PtMenuInfo, UINT Index, UINT wFlag if (MenuGetRosMenuInfo(&TopMenuInfo, Mt->TopMenu) && Mt->TopMenu != PtMenuInfo->Self && - 0 == ((PtMenuInfo->Flags | TopMenuInfo.Flags) & MNF_POPUP)) + 0 == ((PtMenuInfo->fFlags | TopMenuInfo.fFlags) & MNF_POPUP)) { /* both are top level menus (system and menu-bar) */ MenuHideSubPopups(Mt->OwnerWnd, &TopMenuInfo, FALSE, wFlags); @@ -2518,13 +3221,13 @@ MenuExecFocusedItem(MTRACKER *Mt, PROSMENUINFO MenuInfo, UINT Flags) TRACE("%p menu=%p\n", Mt, MenuInfo); - if (0 == MenuInfo->MenuItemCount || NO_SELECTED_ITEM == MenuInfo->FocusedItem) + if (0 == MenuInfo->cItems || NO_SELECTED_ITEM == MenuInfo->iItem) { return -1; } MenuInitRosMenuItemInfo(&ItemInfo); - if (! MenuGetRosMenuItemInfo(MenuInfo->Self, MenuInfo->FocusedItem, &ItemInfo)) + if (! MenuGetRosMenuItemInfo(MenuInfo->Self, MenuInfo->iItem, &ItemInfo)) { MenuCleanupRosMenuItemInfo(&ItemInfo); return -1; @@ -2541,7 +3244,7 @@ MenuExecFocusedItem(MTRACKER *Mt, PROSMENUINFO MenuInfo, UINT Flags) do not send a message to the owner */ if (0 == (Flags & TPM_RETURNCMD)) { - if (0 != (MenuInfo->Flags & MNF_SYSDESKMN)) + if (0 != (MenuInfo->fFlags & MNF_SYSDESKMN)) { PostMessageW(Mt->OwnerWnd, WM_SYSCOMMAND, ItemInfo.wID, MAKELPARAM((SHORT) Mt->Pt.x, (SHORT) Mt->Pt.y)); @@ -2553,7 +3256,7 @@ MenuExecFocusedItem(MTRACKER *Mt, PROSMENUINFO MenuInfo, UINT Flags) DWORD dwStyle = MenuInfo->dwStyle | (ret ? topmenuI.dwStyle : 0); if (dwStyle & MNS_NOTIFYBYPOS) - PostMessageW(Mt->OwnerWnd, WM_MENUCOMMAND, MenuInfo->FocusedItem, (LPARAM)MenuInfo->Self); + PostMessageW(Mt->OwnerWnd, WM_MENUCOMMAND, MenuInfo->iItem, (LPARAM)MenuInfo->Self); else PostMessageW(Mt->OwnerWnd, WM_COMMAND, ItemInfo.wID, 0); } @@ -2610,7 +3313,7 @@ MenuButtonDown(MTRACKER* Mt, HMENU PtMenu, UINT Flags) if (!(Item.fType & MF_SEPARATOR) && !(Item.fState & (MFS_DISABLED | MFS_GRAYED)) ) { - if (MenuInfo.FocusedItem != Index) + if (MenuInfo.iItem != Index) { MenuSwitchTracking(Mt, &MenuInfo, Index, Flags); } @@ -2663,7 +3366,7 @@ MenuButtonUp(MTRACKER *Mt, HMENU PtMenu, UINT Flags) } MenuInitRosMenuItemInfo(&ItemInfo); if (0 <= Id && MenuGetRosMenuItemInfo(MenuInfo.Self, Id, &ItemInfo) && - MenuInfo.FocusedItem == Id) + MenuInfo.iItem == Id) { if (0 == (ItemInfo.hSubMenu)) { @@ -2710,10 +3413,10 @@ MenuPtMenu(HMENU Menu, POINT Pt) } /* try subpopup first (if any) */ - if (NO_SELECTED_ITEM != MenuInfo.FocusedItem) + if (NO_SELECTED_ITEM != MenuInfo.iItem) { MenuInitRosMenuItemInfo(&ItemInfo); - if (MenuGetRosMenuItemInfo(MenuInfo.Self, MenuInfo.FocusedItem, &ItemInfo) && + if (MenuGetRosMenuItemInfo(MenuInfo.Self, MenuInfo.iItem, &ItemInfo) && 0 != (ItemInfo.hSubMenu) && 0 != (ItemInfo.fState & MF_MOUSESELECT)) { @@ -2729,7 +3432,7 @@ MenuPtMenu(HMENU Menu, POINT Pt) /* check the current window (avoiding WM_HITTEST) */ Ht = DefWndNCHitTest(MenuInfo.Wnd, Pt); - if (0 != (MenuInfo.Flags & MNF_POPUP)) + if (0 != (MenuInfo.fFlags & MNF_POPUP)) { if (HTNOWHERE != Ht && HTERROR != Ht) { @@ -2789,7 +3492,7 @@ MenuMouseMove(MTRACKER *Mt, HMENU PtMenu, UINT Flags) TRUE, Mt->TopMenu); } } - else if (MenuInfo.FocusedItem != Index) + else if (MenuInfo.iItem != Index) { MenuInitRosMenuItemInfo(&ItemInfo); if (MenuGetRosMenuItemInfo(MenuInfo.Self, Index, &ItemInfo) && @@ -2817,13 +3520,13 @@ MenuGetSubPopup(HMENU Menu) ROSMENUITEMINFO ItemInfo; if (! MenuGetRosMenuInfo(&MenuInfo, Menu) - || NO_SELECTED_ITEM == MenuInfo.FocusedItem) + || NO_SELECTED_ITEM == MenuInfo.iItem) { return NULL; } MenuInitRosMenuItemInfo(&ItemInfo); - if (! MenuGetRosMenuItemInfo(MenuInfo.Self, MenuInfo.FocusedItem, &ItemInfo)) + if (! MenuGetRosMenuItemInfo(MenuInfo.Self, MenuInfo.iItem, &ItemInfo)) { MenuCleanupRosMenuItemInfo(&ItemInfo); return NULL; @@ -2854,8 +3557,8 @@ MenuDoNextMenu(MTRACKER* Mt, UINT Vk, UINT wFlags) return (LRESULT) FALSE; } - if ((VK_LEFT == Vk && 0 == TopMenuInfo.FocusedItem) - || (VK_RIGHT == Vk && TopMenuInfo.FocusedItem == TopMenuInfo.MenuItemCount - 1)) + if ((VK_LEFT == Vk && 0 == TopMenuInfo.iItem) + || (VK_RIGHT == Vk && TopMenuInfo.iItem == TopMenuInfo.cItems - 1)) { MDINEXTMENU NextMenu; HMENU NewMenu; @@ -2890,7 +3593,7 @@ MenuDoNextMenu(MTRACKER* Mt, UINT Vk, UINT wFlags) { return FALSE; } - Id = MenuInfo.MenuItemCount - 1; + Id = MenuInfo.cItems - 1; } } else if (0 != (Style & WS_SYSMENU)) @@ -3015,7 +3718,7 @@ MenuKeyEscape(MTRACKER *Mt, UINT Flags) if (Mt->CurrentMenu != Mt->TopMenu) { if (MenuGetRosMenuInfo(&MenuInfo, Mt->CurrentMenu) - && 0 != (MenuInfo.Flags & MNF_POPUP)) + && 0 != (MenuInfo.fFlags & MNF_POPUP)) { MenuPrev = MenuTmp = Mt->TopMenu; @@ -3087,7 +3790,7 @@ MenuKeyLeft(MTRACKER* Mt, UINT Flags) { return; } - if ((MenuPrev == Mt->TopMenu) && !(TopMenuInfo.Flags & MNF_POPUP)) + if ((MenuPrev == Mt->TopMenu) && !(TopMenuInfo.fFlags & MNF_POPUP)) { /* move menu bar selection if no more popups are left */ @@ -3127,7 +3830,7 @@ static void FASTCALL MenuKeyRight(MTRACKER *Mt, UINT Flags) Mt->CurrentMenu, Mt->TopMenu); if (! MenuGetRosMenuInfo(&MenuInfo, Mt->TopMenu)) return; - if ((MenuInfo.Flags & MNF_POPUP) || (Mt->CurrentMenu != Mt->TopMenu)) + if ((MenuInfo.fFlags & MNF_POPUP) || (Mt->CurrentMenu != Mt->TopMenu)) { /* If already displaying a popup, try to display sub-popup */ @@ -3157,7 +3860,7 @@ static void FASTCALL MenuKeyRight(MTRACKER *Mt, UINT Flags) return; } - if (!(MenuInfo.Flags & MNF_POPUP)) /* menu bar tracking */ + if (!(MenuInfo.fFlags & MNF_POPUP)) /* menu bar tracking */ { if (Mt->CurrentMenu != Mt->TopMenu) { @@ -3243,7 +3946,7 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y, while (! fEndMenu) { BOOL ErrorExit = FALSE; - PVOID menu = ValidateHandle(mt.CurrentMenu, TYPE_MENU); + PMENU menu = ValidateHandle(mt.CurrentMenu, TYPE_MENU); if (!menu) /* sometimes happens if I do a window manager close */ break; @@ -3268,7 +3971,7 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y, } if (!enterIdleSent) { - HWND win = MenuInfo.Flags & MNF_POPUP ? MenuInfo.Wnd : NULL; + HWND win = MenuInfo.fFlags & MNF_POPUP ? MenuInfo.Wnd : NULL; enterIdleSent = TRUE; SendMessageW( mt.OwnerWnd, WM_ENTERIDLE, MSGF_MENU, (LPARAM) win); } @@ -3316,6 +4019,7 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y, /* no WM_NC... messages in captured state */ case WM_RBUTTONDBLCLK: + ERR("WM_RBUTTONDBLCLK\n"); case WM_RBUTTONDOWN: if (!(wFlags & TPM_RIGHTBUTTON)) break; /* fall through */ @@ -3387,7 +4091,7 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y, case VK_DOWN: /* If on menu bar, pull-down the menu */ if (MenuGetRosMenuInfo(&MenuInfo, mt.CurrentMenu)) { - if (!(MenuInfo.Flags & MNF_POPUP)) + if (!(MenuInfo.fFlags & MNF_POPUP)) { if (MenuGetRosMenuInfo(&MenuInfo, mt.TopMenu)) mt.CurrentMenu = MenuShowSubPopup(mt.OwnerWnd, &MenuInfo, TRUE, wFlags); @@ -3417,13 +4121,13 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y, hi.iContextType = HELPINFO_MENUITEM; if (MenuGetRosMenuInfo(&MenuInfo, mt.CurrentMenu)) { - if (MenuInfo.FocusedItem == NO_SELECTED_ITEM) + if (MenuInfo.iItem == NO_SELECTED_ITEM) hi.iCtrlId = 0; else { MenuInitRosMenuItemInfo(&ItemInfo); if (MenuGetRosMenuItemInfo(MenuInfo.Self, - MenuInfo.FocusedItem, + MenuInfo.iItem, &ItemInfo)) { hi.iCtrlId = ItemInfo.wID; @@ -3510,7 +4214,7 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y, { MenuHideSubPopups(mt.OwnerWnd, &MenuInfo, FALSE, wFlags); - if (MenuInfo.Flags & MNF_POPUP) + if (MenuInfo.fFlags & MNF_POPUP) { IntNotifyWinEvent(EVENT_SYSTEM_MENUPOPUPEND, MenuInfo.Wnd, OBJID_CLIENT, CHILDID_SELF, 0); DestroyWindow(MenuInfo.Wnd); @@ -3574,7 +4278,7 @@ static BOOL FASTCALL MenuInitTracking(HWND hWnd, HMENU hMenu, BOOL bPopup, UINT * menu sizes will be recalculated once the menu created/shown. */ - if (!MenuInfo.Height) + if (!MenuInfo.cyMenu) { /* app changed/recreated menu bar entries in WM_INITMENU Recalculate menu sizes else clicks will not work */ @@ -3586,7 +4290,7 @@ static BOOL FASTCALL MenuInitTracking(HWND hWnd, HMENU hMenu, BOOL bPopup, UINT IntNotifyWinEvent( EVENT_SYSTEM_MENUSTART, hWnd, - MenuInfo.Flags & MNF_SYSDESKMN ? OBJID_SYSMENU : OBJID_MENU, + MenuInfo.fFlags & MNF_SYSDESKMN ? OBJID_SYSMENU : OBJID_MENU, CHILDID_SELF, 0); return TRUE; } @@ -3886,16 +4590,13 @@ MenuSetItemData( mii->fMask |= MIIM_STATE; } - if(Flags & MF_POPUP) + if(Flags & MF_POPUP && IsMenu((HMENU)IDNewItem)) { mii->fMask |= MIIM_SUBMENU; mii->hSubMenu = (HMENU)IDNewItem; } - else - { - mii->fMask |= MIIM_ID; - mii->wID = (UINT)IDNewItem; - } + mii->fMask |= MIIM_ID; + mii->wID = (UINT)IDNewItem; return TRUE; } @@ -3915,16 +4616,63 @@ User32CallLoadMenuFromKernel(PVOID Arguments, ULONG ArgumentLength) return ZwCallbackReturn(&Result, sizeof(LRESULT), STATUS_SUCCESS); } +/********************************************************************** + * MENU_NormalizeMenuItemInfoStruct + * + * Helper for SetMenuItemInfo and InsertMenuItemInfo: + * check, copy and extend the MENUITEMINFO struct from the version that the application + * supplied to the version used by wine source. */ +static BOOL MENU_NormalizeMenuItemInfoStruct( const MENUITEMINFOW *pmii_in, + MENUITEMINFOW *pmii_out ) +{ + /* do we recognize the size? */ + if( !pmii_in || (pmii_in->cbSize != sizeof( MENUITEMINFOW) && + pmii_in->cbSize != sizeof( MENUITEMINFOW) - sizeof( pmii_in->hbmpItem)) ) { + SetLastError( ERROR_INVALID_PARAMETER); + return FALSE; + } + /* copy the fields that we have */ + memcpy( pmii_out, pmii_in, pmii_in->cbSize); + /* if the hbmpItem member is missing then extend */ + if( pmii_in->cbSize != sizeof( MENUITEMINFOW)) { + pmii_out->cbSize = sizeof( MENUITEMINFOW); + pmii_out->hbmpItem = NULL; + } + /* test for invalid bit combinations */ + if( (pmii_out->fMask & MIIM_TYPE && + pmii_out->fMask & (MIIM_STRING | MIIM_FTYPE | MIIM_BITMAP)) || + (pmii_out->fMask & MIIM_FTYPE && pmii_out->fType & MFT_BITMAP)) { + ERR("invalid combination of fMask bits used\n"); + /* this does not happen on Win9x/ME */ + SetLastError( ERROR_INVALID_PARAMETER); + return FALSE; + } + /* convert old style (MIIM_TYPE) to the new and keep the old one too */ + if( pmii_out->fMask & MIIM_TYPE){ + pmii_out->fMask |= MIIM_FTYPE; + if( IS_STRING_ITEM(pmii_out->fType)){ + pmii_out->fMask |= MIIM_STRING; + } else if( (pmii_out->fType) & MFT_BITMAP){ + pmii_out->fMask |= MIIM_BITMAP; + pmii_out->hbmpItem = UlongToHandle(LOWORD(pmii_out->dwTypeData)); + } + } + if (pmii_out->fMask & MIIM_FTYPE ) + { + pmii_out->fType &= ~MENUITEMINFO_TYPE_MASK; + pmii_out->fType |= pmii_in->fType & MENUITEMINFO_TYPE_MASK; + } + if (pmii_out->fMask & MIIM_STATE) + /* Other menu items having MFS_DEFAULT are not converted + to normal items */ + pmii_out->fState = pmii_in->fState & MENUITEMINFO_STATE_MASK; + + return TRUE; +} + /* FUNCTIONS *****************************************************************/ -/*static BOOL -MenuIsStringItem(ULONG TypeData) -{ - return(MF_STRING == MENU_ITEM_TYPE(ItemInfo->fType)); -}*/ - - /* * @implemented */ @@ -3934,11 +4682,9 @@ AppendMenuA(HMENU hMenu, UINT_PTR uIDNewItem, LPCSTR lpNewItem) { - return(InsertMenuA(hMenu, -1, uFlags | MF_BYPOSITION, uIDNewItem, - lpNewItem)); + return(InsertMenuA(hMenu, -1, uFlags | MF_BYPOSITION, uIDNewItem, lpNewItem)); } - /* * @implemented */ @@ -3948,11 +4694,9 @@ AppendMenuW(HMENU hMenu, UINT_PTR uIDNewItem, LPCWSTR lpNewItem) { - return(InsertMenuW(hMenu, -1, uFlags | MF_BYPOSITION, uIDNewItem, - lpNewItem)); + return(InsertMenuW(hMenu, -1, uFlags | MF_BYPOSITION, uIDNewItem, lpNewItem)); } - /* * @implemented */ @@ -3961,141 +4705,86 @@ CheckMenuItem(HMENU hmenu, UINT uIDCheckItem, UINT uCheck) { + PMENU pMenu; + PITEM item; + DWORD Ret; + + if (!(pMenu = ValidateHandle(hmenu, TYPE_MENU))) + return -1; + + if (!(item = MENU_FindItem( &hmenu, &uIDCheckItem, uCheck ))) return -1; + + Ret = item->fState & MFS_CHECKED; + if ( Ret == (uCheck & MFS_CHECKED)) return Ret; // Already Checked... + 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].hSubMenu) && (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 WINAPI -CheckMenuRadioItem(HMENU hmenu, - UINT idFirst, - UINT idLast, - UINT idCheck, - UINT uFlags) +CheckMenuRadioItem(HMENU hMenu, + UINT first, + UINT last, + UINT check, + UINT bypos) { - UINT cChecked = 0; - UINT cUnchecked = 0; - UINT cMenuChanged = 0; + BOOL done = FALSE; + UINT i; + PITEM mi_first = NULL, mi_check; + HMENU m_first, m_check; + MENUITEMINFOW mii; + mii.cbSize = sizeof( mii); - if (!MenuCheckMenuRadioItem(hmenu, idFirst, idLast, idCheck, uFlags, FALSE, &cChecked, &cUnchecked, &cMenuChanged)) - return FALSE; + for (i = first; i <= last; i++) + { + UINT pos = i; - if (cMenuChanged > 1) - return FALSE; + if (!mi_first) + { + m_first = hMenu; + mi_first = MENU_FindItem(&m_first, &pos, bypos); + if (!mi_first) continue; + mi_check = mi_first; + m_check = m_first; + } + else + { + m_check = hMenu; + mi_check = MENU_FindItem(&m_check, &pos, bypos); + if (!mi_check) continue; + } - cMenuChanged = 0; - cChecked = 0; - cUnchecked = 0; + if (m_first != m_check) continue; + if (mi_check->fType == MFT_SEPARATOR) continue; - if (!MenuCheckMenuRadioItem(hmenu, idFirst, idLast, idCheck, uFlags, TRUE, &cChecked, &cUnchecked, &cMenuChanged)) - return FALSE; - - return (cChecked != 0); + if (i == check) + { + if (!(mi_check->fType & MFT_RADIOCHECK) || !(mi_check->fState & MFS_CHECKED)) + { + mii.fMask = MIIM_FTYPE | MIIM_STATE; + mii.fType = (mi_check->fType & MENUITEMINFO_TYPE_MASK) | MFT_RADIOCHECK; + mii.fState = (mi_check->fState & MII_STATE_MASK) | MFS_CHECKED; + NtUserThunkedMenuItemInfo(m_check, i, bypos, FALSE, &mii, NULL); + } + done = TRUE; + } + else + { + /* MSDN is wrong, Windows does not remove MFT_RADIOCHECK */ + if (mi_check->fState & MFS_CHECKED) + { + mii.fMask = MIIM_STATE; + mii.fState = (mi_check->fState & MII_STATE_MASK) & ~MFS_CHECKED; + NtUserThunkedMenuItemInfo(m_check, i, bypos, FALSE, &mii, NULL); + } + } + } + return done; } - /* * @implemented */ @@ -4106,7 +4795,6 @@ CreateMenu(VOID) return NtUserxCreateMenu(); } - /* * @implemented */ @@ -4117,26 +4805,13 @@ CreatePopupMenu(VOID) return NtUserxCreatePopupMenu(); } - /* * @implemented */ BOOL WINAPI DrawMenuBar(HWND hWnd) { -// return NtUserxDrawMenuBar(hWnd); - ROSMENUINFO MenuInfo; - HMENU hMenu; - hMenu = GetMenu(hWnd); - if (!hMenu) - return FALSE; - MenuGetRosMenuInfo(&MenuInfo, hMenu); - MenuInfo.Height = 0; // make sure to recalc size - MenuSetRosMenuInfo(&MenuInfo); - - SetWindowPos( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | - SWP_NOZORDER | SWP_FRAMECHANGED ); - return TRUE; + return NtUserxDrawMenuBar(hWnd); } /* @@ -4193,11 +4868,13 @@ BOOL WINAPI HiliteMenuItem( HWND hWnd, HMENU hMenu, UINT wItemID, if (!NtUserHiliteMenuItem(hWnd, hMenu, wItemID, wHilite)) return FALSE; // Without the above call we fail 3 out of the wine failed todo tests, see CORE-7967 // Now redraw menu. - if (!MenuGetRosMenuInfo(&MenuInfo, hMenu)) return FALSE; - if (MenuInfo.FocusedItem == wItemID) return TRUE; - MenuHideSubPopups( hWnd, &MenuInfo, FALSE, 0 ); - MenuSelectItem( hWnd, &MenuInfo, wItemID, TRUE, 0 ); - return TRUE; + if (MenuGetRosMenuInfo(&MenuInfo, hMenu)) + { + if (MenuInfo.iItem == wItemID) return TRUE; + MenuHideSubPopups( hWnd, &MenuInfo, FALSE, 0 ); + MenuSelectItem( hWnd, &MenuInfo, wItemID, TRUE, 0 ); + } + return TRUE; // Always returns TRUE! } /* @@ -4234,7 +4911,6 @@ BOOL WINAPI GetMenuBarInfo( HWND hwnd, LONG idObject, LONG idItem, PMENUBARINFO return TRUE; } - /* * @implemented */ @@ -4245,6 +4921,18 @@ GetMenuCheckMarkDimensions(VOID) GetSystemMetrics(SM_CYMENUCHECK))); } +/* + * @implemented + */ +DWORD +WINAPI +GetMenuContextHelpId(HMENU hmenu) +{ + PMENU pMenu; + if ((pMenu = ValidateHandle(hmenu, TYPE_MENU))) + return pMenu->dwContextHelpId; + return 0; +} /* * @implemented @@ -4254,9 +4942,13 @@ GetMenuDefaultItem(HMENU hMenu, UINT fByPos, UINT gmdiFlags) { - return NtUserGetMenuDefaultItem(hMenu, fByPos, gmdiFlags); -} + PMENU pMenu; + DWORD gismc = 0; + if (!(pMenu = ValidateHandle(hMenu, TYPE_MENU))) + return (UINT)-1; + return IntGetMenuDefaultItem( pMenu, (BOOL)fByPos, gmdiFlags, &gismc); +} /* * @implemented @@ -4265,9 +4957,7 @@ BOOL WINAPI GetMenuInfo(HMENU hmenu, LPMENUINFO lpcmi) { - ROSMENUINFO mi; - BOOL res = FALSE; - PVOID pMenu; + PMENU pMenu; if (!lpcmi || (lpcmi->cbSize != sizeof(MENUINFO))) { @@ -4278,29 +4968,36 @@ GetMenuInfo(HMENU hmenu, if (!(pMenu = ValidateHandle(hmenu, TYPE_MENU))) return FALSE; - RtlZeroMemory(&mi, sizeof(MENUINFO)); - mi.cbSize = sizeof(MENUINFO); - mi.fMask = lpcmi->fMask; + if (lpcmi->fMask & MIM_BACKGROUND) + lpcmi->hbrBack = pMenu->hbrBack; - res = NtUserMenuInfo(hmenu, &mi, FALSE); + if (lpcmi->fMask & MIM_HELPID) + lpcmi->dwContextHelpID = pMenu->dwContextHelpId; - memcpy(lpcmi, &mi, sizeof(MENUINFO)); - return res; + if (lpcmi->fMask & MIM_MAXHEIGHT) + lpcmi->cyMax = pMenu->cyMax; + + if (lpcmi->fMask & MIM_MENUDATA) + lpcmi->dwMenuData = pMenu->dwMenuData; + + if (lpcmi->fMask & MIM_STYLE) + lpcmi->dwStyle = pMenu->fFlags & MNS_STYLE_MASK; + + return TRUE; } - /* * @implemented */ int WINAPI -GetMenuItemCount(HMENU Menu) +GetMenuItemCount(HMENU hmenu) { - ROSMENUINFO MenuInfo; - - return MenuGetRosMenuInfo(&MenuInfo, Menu) ? MenuInfo.MenuItemCount : 0; + PMENU pMenu; + if ((pMenu = ValidateHandle(hmenu, TYPE_MENU))) + return pMenu->cItems; + return -1; } - /* * @implemented */ @@ -4308,180 +5005,86 @@ UINT WINAPI GetMenuItemID(HMENU hMenu, int nPos) { - ROSMENUITEMINFO mii; + PMENU pMenu; + PITEM pItem; + INT i = 0; - mii.cbSize = sizeof(MENUITEMINFOW); - mii.fMask = MIIM_ID | MIIM_SUBMENU; + if (!(pMenu = ValidateHandle(hMenu, TYPE_MENU))) + return -1; - if (! NtUserMenuItemInfo(hMenu, nPos, MF_BYPOSITION, &mii, FALSE)) - { - return -1; - } - - if (NULL != mii.hSubMenu) - { - return -1; - } - if (0 == mii.wID) - { - return -1; - } - - return mii.wID; + pItem = pMenu->rgItems ? DesktopPtrToUser(pMenu->rgItems) : NULL; + if ( nPos >= 0 ) + { + //pItem = &menu->rgItems[nPos]; or pItem[nPos]; after dptu. + while(pItem) // Do this for now. + { + if (i < (INT)pMenu->cItems) + { + if ( nPos == i && !pItem->spSubMenu) return pItem->wID; + } + pItem = pItem->Next ? DesktopPtrToUser(pItem->Next) : NULL; + i++; + } + } + return -1; } - /* * @implemented */ BOOL WINAPI GetMenuItemInfoA( - HMENU Menu, - UINT Item, - BOOL ByPosition, - LPMENUITEMINFOA mii) + HMENU hmenu, + UINT item, + BOOL bypos, + LPMENUITEMINFOA lpmii) { - MENUITEMINFOW miiW; - LPSTR AnsiBuffer; - INT Count; + BOOL ret; + MENUITEMINFOA mii; - if (mii->cbSize != sizeof(MENUITEMINFOA) && - mii->cbSize != sizeof(MENUITEMINFOA) - sizeof(HBITMAP)) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - if(!(mii->fMask & (MIIM_TYPE | MIIM_STRING))) - { - /* No text requested, just pass on */ - return NtUserMenuItemInfo(Menu, Item, ByPosition, (PROSMENUITEMINFO) mii, FALSE); - } - - AnsiBuffer = mii->dwTypeData; - Count = miiW.cch = mii->cch; - RtlCopyMemory(&miiW, mii, mii->cbSize); - miiW.dwTypeData = 0; - - if (AnsiBuffer) - { - miiW.dwTypeData = RtlAllocateHeap(GetProcessHeap(), 0, - miiW.cch * sizeof(WCHAR)); - if (miiW.dwTypeData == NULL) return FALSE; - miiW.dwTypeData[0] = 0; - } - - if (!NtUserMenuItemInfo(Menu, Item, ByPosition, (PROSMENUITEMINFO)&miiW, FALSE)) - { - if (miiW.dwTypeData) RtlFreeHeap(GetProcessHeap(), 0, miiW.dwTypeData); - return FALSE; - } - - RtlCopyMemory(mii, &miiW, miiW.cbSize); - - if (!AnsiBuffer || !Count) - { - if (miiW.dwTypeData) RtlFreeHeap(GetProcessHeap(), 0, miiW.dwTypeData); - mii->dwTypeData = AnsiBuffer; - mii->cch = miiW.cch; - return TRUE; - } - - if ((miiW.fMask & MIIM_STRING) || (IS_STRING_ITEM(miiW.fType))) - { - 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 = miiW.cch; - } - } - else - { - AnsiBuffer[0] = 0; - } - - RtlFreeHeap(GetProcessHeap(), 0, miiW.dwTypeData); - mii->dwTypeData = AnsiBuffer; - - return TRUE; + if( lpmii->cbSize != sizeof( mii) && + lpmii->cbSize != sizeof( mii) - sizeof ( mii.hbmpItem)) + { + SetLastError( ERROR_INVALID_PARAMETER); + return FALSE; + } + memcpy( &mii, lpmii, lpmii->cbSize); + mii.cbSize = sizeof( mii); + ret = GetMenuItemInfo_common (hmenu, + item, + bypos, + (LPMENUITEMINFOW)&mii, + FALSE); + mii.cbSize = lpmii->cbSize; + memcpy( lpmii, &mii, mii.cbSize); + return ret; } - /* * @implemented */ BOOL WINAPI GetMenuItemInfoW( - HMENU Menu, + HMENU hMenu, UINT Item, - BOOL ByPosition, - LPMENUITEMINFOW mii) + BOOL bypos, + LPMENUITEMINFOW lpmii) { - MENUITEMINFOW miiW; - LPWSTR String; - INT Count; - - if (mii->cbSize != sizeof(MENUITEMINFOW) && - mii->cbSize != sizeof(MENUITEMINFOW) - sizeof(HBITMAP)) + BOOL ret; + MENUITEMINFOW mii; + if( lpmii->cbSize != sizeof( mii) && lpmii->cbSize != sizeof( mii) - sizeof ( mii.hbmpItem)) { - SetLastError(ERROR_INVALID_PARAMETER); + SetLastError( ERROR_INVALID_PARAMETER); return FALSE; } - - if(!(mii->fMask & (MIIM_TYPE | MIIM_STRING))) - { - /* No text requested, just pass on */ - return NtUserMenuItemInfo(Menu, Item, ByPosition, (PROSMENUITEMINFO) mii, FALSE); - } - - String = mii->dwTypeData; - Count = mii->cch; - RtlCopyMemory(&miiW, mii, mii->cbSize); - miiW.dwTypeData = 0; - - if (String) - { - miiW.dwTypeData = RtlAllocateHeap(GetProcessHeap(), 0, - miiW.cch * sizeof(WCHAR)); - if (miiW.dwTypeData == NULL) return FALSE; - miiW.dwTypeData[0] = 0; - } - - if (!NtUserMenuItemInfo(Menu, Item, ByPosition, (PROSMENUITEMINFO) &miiW, FALSE)) - { - if (miiW.dwTypeData) RtlFreeHeap(GetProcessHeap(), 0, miiW.dwTypeData); - return FALSE; - } - - RtlCopyMemory(mii, &miiW, miiW.cbSize); // Okay to over write user data. - - if (!String || !Count) - { - if (miiW.dwTypeData) RtlFreeHeap(GetProcessHeap(), 0, miiW.dwTypeData); - mii->dwTypeData = String; // may not be zero. - mii->cch = miiW.cch; - return TRUE; - } - - if ((miiW.fMask & MIIM_STRING) || (IS_STRING_ITEM(miiW.fType))) - { - lstrcpynW( String, miiW.dwTypeData, Count ); - } - - RtlFreeHeap(GetProcessHeap(), 0, miiW.dwTypeData); - mii->dwTypeData = String; - mii->cch = strlenW(String); - return TRUE; + memcpy( &mii, lpmii, lpmii->cbSize); + mii.cbSize = sizeof( mii); + ret = GetMenuItemInfo_common (hMenu, Item, bypos, &mii, TRUE); + mii.cbSize = lpmii->cbSize; + memcpy( lpmii, &mii, mii.cbSize); + return ret; } - /* * @implemented */ @@ -4492,39 +5095,21 @@ GetMenuState( UINT uId, UINT uFlags) { - ROSMENUINFO MenuInfo; - ROSMENUITEMINFO mii; - memset( &mii, 0, sizeof(mii) ); - mii.cbSize = sizeof(MENUITEMINFOW); - mii.fMask = MIIM_STATE | MIIM_FTYPE | MIIM_SUBMENU; + PITEM pItem; + TRACE("(menu=%p, id=%04x, flags=%04x);\n", hMenu, uId, uFlags); + if (!(pItem = MENU_FindItem( &hMenu, &uId, uFlags ))) return -1; - SetLastError(0); - if(NtUserMenuItemInfo(hMenu, uId, uFlags, &mii, FALSE)) - { - UINT nSubItems = 0; - if(mii.hSubMenu) - { - if (! MenuGetRosMenuInfo(&MenuInfo, mii.hSubMenu)) - { - 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; + if (pItem->spSubMenu) + { + PMENU pSubMenu = DesktopPtrToUser(pItem->spSubMenu); + HMENU hsubmenu = UserHMGetHandle(pSubMenu); + if (!IsMenu(hsubmenu)) return (UINT)-1; + else return (pSubMenu->cItems << 8) | ((pItem->fState|pItem->fType) & 0xff); + } + else + return (pItem->fType | pItem->fState); } - /* * @implemented */ @@ -4537,11 +5122,10 @@ GetMenuStringA( int nMaxCount, UINT uFlag) { - MENUITEMINFOA mii; +/* MENUITEMINFOA mii; memset( &mii, 0, sizeof(mii) ); mii.dwTypeData = lpString; - mii.fMask = MIIM_STRING | MIIM_FTYPE; - mii.fType = MFT_STRING; + mii.fMask = MIIM_STRING; mii.cbSize = sizeof(MENUITEMINFOA); mii.cch = nMaxCount; @@ -4549,8 +5133,29 @@ GetMenuStringA( return 0; else return mii.cch; -} +*/ + ITEM *item; + LPWSTR text; + ////// wine Code, seems to be faster. + TRACE("menu=%p item=%04x ptr=%p len=%d flags=%04x\n", hMenu, uIDItem, lpString, nMaxCount, uFlag ); + if (lpString && nMaxCount) lpString[0] = '\0'; + + if (!(item = MENU_FindItem( &hMenu, &uIDItem, uFlag ))) + { + SetLastError( ERROR_MENU_ITEM_NOT_FOUND); + return 0; + } + + text = item->Xlpstr ? DesktopPtrToUser(item->Xlpstr) : NULL; + + if (!text) return 0; + if (!lpString || !nMaxCount) return WideCharToMultiByte( CP_ACP, 0, text, -1, NULL, 0, NULL, NULL ); + if (!WideCharToMultiByte( CP_ACP, 0, text, -1, lpString, nMaxCount, NULL, NULL )) + lpString[nMaxCount-1] = 0; + ERR("returning %s\n", lpString); + return strlen(lpString); +} /* * @implemented @@ -4564,7 +5169,7 @@ GetMenuStringW( int nMaxCount, UINT uFlag) { - MENUITEMINFOW miiW; +/* MENUITEMINFOW miiW; memset( &miiW, 0, sizeof(miiW) ); miiW.dwTypeData = lpString; miiW.fMask = MIIM_STRING | MIIM_FTYPE; @@ -4576,8 +5181,32 @@ GetMenuStringW( return 0; else return miiW.cch; -} +*/ + ITEM *item; + LPWSTR text; + TRACE("menu=%p item=%04x ptr=%p len=%d flags=%04x\n", hMenu, uIDItem, lpString, nMaxCount, uFlag ); + + if (lpString && nMaxCount) lpString[0] = '\0'; + + if (!(item = MENU_FindItem( &hMenu, &uIDItem, uFlag ))) + { + SetLastError( ERROR_MENU_ITEM_NOT_FOUND); + return 0; + } + + text = item->Xlpstr ? DesktopPtrToUser(item->Xlpstr) : NULL; + + if (!lpString || !nMaxCount) return text ? strlenW(text) : 0; + if( !(text)) + { + lpString[0] = 0; + return 0; + } + lstrcpynW( lpString, text, nMaxCount ); + ERR("returning %S\n", lpString); + return strlenW(lpString); +} /* * @implemented @@ -4588,16 +5217,15 @@ GetSubMenu( HMENU hMenu, int nPos) { - ROSMENUITEMINFO mi; - - mi.cbSize = sizeof(MENUITEMINFOW); - mi.fMask = MIIM_SUBMENU; - - if (NtUserMenuItemInfo(hMenu, (UINT)nPos, MF_BYPOSITION, &mi, FALSE)) - { - return IsMenu(mi.hSubMenu) ? mi.hSubMenu : NULL; - } + PITEM pItem; + if (!(pItem = MENU_FindItem( &hMenu, (UINT*)&nPos, MF_BYPOSITION ))) return NULL; + if (pItem->spSubMenu) + { + PMENU pSubMenu = DesktopPtrToUser(pItem->spSubMenu); + HMENU hsubmenu = UserHMGetHandle(pSubMenu); + if (IsMenu(hsubmenu)) return hsubmenu; + } return NULL; } @@ -4617,7 +5245,6 @@ GetSystemMenu( return NULL == TopMenu ? NULL : GetSubMenu(TopMenu, 0); } - /* * @implemented */ @@ -4644,8 +5271,6 @@ InsertMenuA( return InsertMenuItemA(hMenu, uPosition, (BOOL)((MF_BYPOSITION & uFlags) > 0), &mii); } - - /* * @implemented */ @@ -4657,43 +5282,38 @@ InsertMenuItemA( BOOL fByPosition, LPCMENUITEMINFOA lpmii) { - MENUITEMINFOW mi; - UNICODE_STRING MenuText; - BOOL res = FALSE; - BOOL CleanHeap = FALSE; + MENUITEMINFOW mii; + UNICODE_STRING UnicodeString; + BOOL res; - if((lpmii->cbSize == sizeof(MENUITEMINFOA)) || - (lpmii->cbSize == sizeof(MENUITEMINFOA) - sizeof(HBITMAP))) + TRACE("hmenu %p, item %04x, by pos %d, info %p\n", hMenu, uItem, fByPosition, lpmii); + + RtlInitUnicodeString(&UnicodeString, 0); + + if (!MENU_NormalizeMenuItemInfoStruct( (const MENUITEMINFOW *)lpmii, &mii )) return FALSE; + + /* copy the text string */ + if (((mii.fMask & MIIM_STRING) || + ((mii.fMask & MIIM_TYPE) && (MENU_ITEM_TYPE(mii.fType) == MF_STRING))) + && mii.dwTypeData && !(GdiValidateHandle((HGDIOBJ)mii.dwTypeData)) ) { - RtlCopyMemory ( &mi, lpmii, lpmii->cbSize ); - - if( lpmii->cbSize != sizeof( MENUITEMINFOW)) - { - mi.cbSize = sizeof( MENUITEMINFOW); - mi.hbmpItem = NULL; - } - /* copy the text string */ - if (((mi.fMask & MIIM_STRING) || - ((mi.fMask & MIIM_TYPE) && (MENU_ITEM_TYPE(mi.fType) == MF_STRING))) - && mi.dwTypeData != NULL) - { - if (!RtlCreateUnicodeStringFromAsciiz(&MenuText, (LPSTR)mi.dwTypeData)) + if (!RtlCreateUnicodeStringFromAsciiz(&UnicodeString, (LPSTR)mii.dwTypeData)) { SetLastError (ERROR_NOT_ENOUGH_MEMORY); return FALSE; } - mi.dwTypeData = MenuText.Buffer; - mi.cch = MenuText.Length / sizeof(WCHAR); - CleanHeap = TRUE; - } - res = NtUserThunkedMenuItemInfo(hMenu, uItem, fByPosition, TRUE, &mi, NULL); - - if ( CleanHeap ) RtlFreeUnicodeString ( &MenuText ); + mii.dwTypeData = UnicodeString.Buffer; + mii.cch = UnicodeString.Length / sizeof(WCHAR); } + else + { + UnicodeString.Buffer = NULL; + } + res = NtUserThunkedMenuItemInfo(hMenu, uItem, fByPosition, TRUE, &mii, &UnicodeString); + if ( UnicodeString.Buffer ) RtlFreeUnicodeString ( &UnicodeString ); return res; } - /* * @implemented */ @@ -4705,7 +5325,7 @@ InsertMenuItemW( BOOL fByPosition, LPCMENUITEMINFOW lpmii) { - MENUITEMINFOW mi; + MENUITEMINFOW mii; UNICODE_STRING MenuText; BOOL res = FALSE; @@ -4713,31 +5333,25 @@ InsertMenuItemW( if a bad user passes bad data, we crash his process instead of the entire kernel */ - if((lpmii->cbSize == sizeof(MENUITEMINFOW)) || - (lpmii->cbSize == sizeof(MENUITEMINFOW) - sizeof(HBITMAP))) - { - RtlCopyMemory(&mi, lpmii, lpmii->cbSize); + TRACE("hmenu %p, item %04x, by pos %d, info %p\n", hMenu, uItem, fByPosition, lpmii); - if( lpmii->cbSize != sizeof( MENUITEMINFOW)) - { - mi.cbSize = sizeof( MENUITEMINFOW); - mi.hbmpItem = NULL; - } - /* copy the text string */ - if (((mi.fMask & MIIM_STRING) || - ((mi.fMask & MIIM_TYPE) && (MENU_ITEM_TYPE(mi.fType) == MF_STRING))) - && mi.dwTypeData != NULL) - { - RtlInitUnicodeString(&MenuText, (PWSTR)lpmii->dwTypeData); - mi.dwTypeData = MenuText.Buffer; - mi.cch = MenuText.Length / sizeof(WCHAR); - } - res = NtUserThunkedMenuItemInfo(hMenu, uItem, fByPosition, TRUE, &mi, NULL); + RtlInitUnicodeString(&MenuText, 0); + + if (!MENU_NormalizeMenuItemInfoStruct( (const MENUITEMINFOW *)lpmii, &mii )) return FALSE; + + /* copy the text string */ + if (((mii.fMask & MIIM_STRING) || + ((mii.fMask & MIIM_TYPE) && (MENU_ITEM_TYPE(mii.fType) == MF_STRING))) + && mii.dwTypeData && !(GdiValidateHandle((HGDIOBJ)mii.dwTypeData)) ) + { + RtlInitUnicodeString(&MenuText, (PWSTR)lpmii->dwTypeData); + mii.dwTypeData = MenuText.Buffer; + mii.cch = MenuText.Length / sizeof(WCHAR); } + res = NtUserThunkedMenuItemInfo(hMenu, uItem, fByPosition, TRUE, &mii, &MenuText); return res; } - /* * @implemented */ @@ -4764,7 +5378,6 @@ InsertMenuW( return InsertMenuItemW(hMenu, uPosition, (BOOL)((MF_BYPOSITION & uFlags) > 0), &mii); } - /* * @implemented */ @@ -4777,7 +5390,6 @@ IsMenu( return FALSE; } - /* * @implemented */ @@ -4793,7 +5405,6 @@ LoadMenuA(HINSTANCE hInstance, return(LoadMenuIndirectA((PVOID)LoadResource(hInstance, Resource))); } - /* * @implemented */ @@ -4803,7 +5414,6 @@ LoadMenuIndirectA(CONST MENUTEMPLATE *lpMenuTemplate) return(LoadMenuIndirectW(lpMenuTemplate)); } - /* * @implemented */ @@ -4845,7 +5455,6 @@ LoadMenuIndirectW(CONST MENUTEMPLATE *lpMenuTemplate) } } - /* * @implemented */ @@ -4861,7 +5470,6 @@ LoadMenuW(HINSTANCE hInstance, return(LoadMenuIndirectW((PVOID)LoadResource(hInstance, Resource))); } - /* * @implemented */ @@ -4875,7 +5483,6 @@ MenuItemFromPoint( return NtUserMenuItemFromPoint(hWnd, hMenu, ptScreen.x, ptScreen.y); } - /* * @implemented */ @@ -4888,41 +5495,26 @@ ModifyMenuA( UINT_PTR uIDNewItem, LPCSTR lpNewItem) { - ROSMENUINFO mi; - ROSMENUITEMINFO rmii; MENUITEMINFOA mii; memset( &mii, 0, sizeof(mii) ); - mii.cbSize = sizeof(MENUITEMINFOA); + mii.cbSize = sizeof(MENUITEMINFOA); mii.fMask = MIIM_FTYPE; - if (!MenuGetRosMenuInfo( &mi, hMnu )) return FALSE; - - mi.Height = 0; - - if (!MenuSetRosMenuInfo( &mi )) return FALSE; - - MenuInitRosMenuItemInfo( &rmii ); - - if(!MenuGetRosMenuItemInfo( hMnu, uPosition, &rmii)) return FALSE; - - if (rmii.hSubMenu && (uFlags & MF_POPUP) && (rmii.hSubMenu != (HMENU)uIDNewItem)) - NtUserDestroyMenu( rmii.hSubMenu ); /* ModifyMenu() spec */ - - MenuCleanupRosMenuItemInfo( &rmii ); - MenuSetItemData((LPMENUITEMINFOW) &mii, uFlags, uIDNewItem, (LPCWSTR) lpNewItem, FALSE); + //if (mii.hSubMenu && (uFlags & MF_POPUP) && (mii.hSubMenu != (HMENU)uIDNewItem)) + // NtUserDestroyMenu( mii.hSubMenu ); /* ModifyMenu() spec */ + return SetMenuItemInfoA( hMnu, uPosition, (BOOL)(MF_BYPOSITION & uFlags), &mii); } - /* * @implemented */ @@ -4935,28 +5527,11 @@ ModifyMenuW( UINT_PTR uIDNewItem, LPCWSTR lpNewItem) { - ROSMENUINFO mi; - ROSMENUITEMINFO rmii; MENUITEMINFOW mii; memset ( &mii, 0, sizeof(mii) ); mii.cbSize = sizeof(MENUITEMINFOW); mii.fMask = MIIM_FTYPE; - if (!MenuGetRosMenuInfo( &mi, hMnu )) return FALSE; - - mi.Height = 0; // Force size recalculation. - - if (!MenuSetRosMenuInfo( &mi )) return FALSE; - - MenuInitRosMenuItemInfo( &rmii ); - - if(!MenuGetRosMenuItemInfo( hMnu, uPosition, &rmii)) return FALSE; - - if (rmii.hSubMenu && (uFlags & MF_POPUP) && (rmii.hSubMenu != (HMENU)uIDNewItem)) - NtUserDestroyMenu( rmii.hSubMenu ); /* ModifyMenu() spec */ - - MenuCleanupRosMenuItemInfo( &rmii ); - /* Init new data for this menu item */ MenuSetItemData( &mii, uFlags, @@ -4964,14 +5539,15 @@ ModifyMenuW( lpNewItem, TRUE); - /* Now, make Win32k IntSetMenuItemInfo handle the changes to this menu item. */ + //if (mii.hSubMenu && (uFlags & MF_POPUP) && (mii.hSubMenu != (HMENU)uIDNewItem)) + // NtUserDestroyMenu( mii.hSubMenu ); /* ModifyMenu() spec */ + return SetMenuItemInfoW( hMnu, uPosition, (BOOL)(MF_BYPOSITION & uFlags), &mii); } - /* * @implemented */ @@ -4982,7 +5558,6 @@ SetMenu(HWND hWnd, return NtUserSetMenu(hWnd, hMenu, TRUE); } - /* * @implemented */ @@ -5002,10 +5577,9 @@ SetMenuInfo( } memcpy(&mi, lpcmi, sizeof(MENUINFO)); - return NtUserMenuInfo(hmenu, &mi, TRUE); + return NtUserThunkedMenuInfo(hmenu, (LPCMENUINFO)&mi); } - /* * @implemented */ @@ -5018,88 +5592,63 @@ SetMenuItemBitmaps( HBITMAP hBitmapUnchecked, HBITMAP hBitmapChecked) { - ROSMENUITEMINFO uItem; + MENUITEMINFOW uItem; memset ( &uItem, 0, sizeof(uItem) ); - uItem.fMask = MIIM_STATE | MIIM_BITMAP; - - 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); + uItem.cbSize = sizeof(MENUITEMINFOW); + uItem.fMask = MIIM_CHECKMARKS; + uItem.hbmpUnchecked = hBitmapUnchecked; + uItem.hbmpChecked = hBitmapChecked; + return SetMenuItemInfoW(hMenu, uPosition, (BOOL)(uFlags & MF_BYPOSITION), &uItem); } - /* * @implemented */ BOOL WINAPI SetMenuItemInfoA( - HMENU hMenu, - UINT uItem, - BOOL fByPosition, + HMENU hmenu, + UINT item, + BOOL bypos, LPCMENUITEMINFOA lpmii) { - MENUITEMINFOW MenuItemInfoW; + MENUITEMINFOW mii; UNICODE_STRING UnicodeString; - ULONG Result = FALSE; + BOOL Ret; - RtlCopyMemory(&MenuItemInfoW, lpmii, min(lpmii->cbSize, sizeof(MENUITEMINFOW))); + TRACE("hmenu %p, item %u, by pos %d, info %p\n", hmenu, item, bypos, lpmii); - if( lpmii->cbSize != sizeof( MENUITEMINFOW)) - { - MenuItemInfoW.cbSize = sizeof( MENUITEMINFOW); - MenuItemInfoW.hbmpItem = NULL; - } + RtlInitUnicodeString(&UnicodeString, 0); + + if (!MENU_NormalizeMenuItemInfoStruct( (const MENUITEMINFOW *)lpmii, &mii )) return FALSE; /* * MIIM_STRING == good * MIIM_TYPE & MFT_STRING == good * MIIM_STRING & MFT_STRING == good - * MIIM_STRING & MFT_OWNERSRAW == good + * MIIM_STRING & MFT_OWNERDRAW == good */ - if (((MenuItemInfoW.fMask & MIIM_STRING) || - ((MenuItemInfoW.fMask & MIIM_TYPE) && - (MENU_ITEM_TYPE(MenuItemInfoW.fType) == MF_STRING))) - && MenuItemInfoW.dwTypeData != NULL) + if (((mii.fMask & MIIM_STRING) || + ((mii.fMask & MIIM_TYPE) && (MENU_ITEM_TYPE(mii.fType) == MF_STRING))) + && mii.dwTypeData && !(GdiValidateHandle((HGDIOBJ)mii.dwTypeData)) ) { -/* cch is ignored when the content of a menu item is set by calling SetMenuItemInfo. */ - if (!RtlCreateUnicodeStringFromAsciiz(&UnicodeString, - (LPSTR)MenuItemInfoW.dwTypeData)) - { + /* cch is ignored when the content of a menu item is set by calling SetMenuItemInfo. */ + if (!RtlCreateUnicodeStringFromAsciiz(&UnicodeString, (LPSTR)mii.dwTypeData)) + { SetLastError (ERROR_NOT_ENOUGH_MEMORY); return FALSE; - } - MenuItemInfoW.dwTypeData = UnicodeString.Buffer; - MenuItemInfoW.cch = UnicodeString.Length / sizeof(WCHAR); + } + mii.dwTypeData = UnicodeString.Buffer; + mii.cch = UnicodeString.Length / sizeof(WCHAR); } else { - UnicodeString.Buffer = NULL; + UnicodeString.Buffer = NULL; } - - Result = NtUserMenuItemInfo(hMenu, uItem, fByPosition, - (PROSMENUITEMINFO)&MenuItemInfoW, TRUE); - - if (UnicodeString.Buffer != NULL) - { - RtlFreeUnicodeString(&UnicodeString); - } - - return Result; + Ret = NtUserThunkedMenuItemInfo(hmenu, item, bypos, FALSE, &mii, &UnicodeString); + if (UnicodeString.Buffer != NULL) RtlFreeUnicodeString(&UnicodeString); + return Ret; } - /* * @implemented */ @@ -5112,27 +5661,26 @@ SetMenuItemInfoW( LPCMENUITEMINFOW lpmii) { MENUITEMINFOW MenuItemInfoW; - ULONG Result; + UNICODE_STRING UnicodeString; + BOOL Ret; - RtlCopyMemory(&MenuItemInfoW, lpmii, min(lpmii->cbSize, sizeof(MENUITEMINFOW))); + TRACE("hmenu %p, item %u, by pos %d, info %p\n", hMenu, uItem, fByPosition, lpmii); - if( lpmii->cbSize != sizeof( MENUITEMINFOW)) - { - MenuItemInfoW.cbSize = sizeof( MENUITEMINFOW); - MenuItemInfoW.hbmpItem = NULL; - } + RtlInitUnicodeString(&UnicodeString, 0); + + if (!MENU_NormalizeMenuItemInfoStruct( (const MENUITEMINFOW *)lpmii, &MenuItemInfoW )) return FALSE; if (((MenuItemInfoW.fMask & MIIM_STRING) || ((MenuItemInfoW.fMask & MIIM_TYPE) && (MENU_ITEM_TYPE(MenuItemInfoW.fType) == MF_STRING))) - && MenuItemInfoW.dwTypeData != NULL) + && MenuItemInfoW.dwTypeData && !(GdiValidateHandle((HGDIOBJ)MenuItemInfoW.dwTypeData)) ) { - MenuItemInfoW.cch = strlenW(MenuItemInfoW.dwTypeData); + RtlInitUnicodeString(&UnicodeString, (PCWSTR)MenuItemInfoW.dwTypeData); + MenuItemInfoW.cch = strlenW(MenuItemInfoW.dwTypeData); } - Result = NtUserMenuItemInfo(hMenu, uItem, fByPosition, - (PROSMENUITEMINFO)&MenuItemInfoW, TRUE); + Ret = NtUserThunkedMenuItemInfo(hMenu, uItem, fByPosition, FALSE, &MenuItemInfoW, &UnicodeString); - return Result; + return Ret; } /* @@ -5182,23 +5730,6 @@ NEWTrackPopupMenu( } -/* - * @implemented - */ -DWORD -WINAPI -GetMenuContextHelpId(HMENU hmenu) -{ - ROSMENUINFO mi; - mi.cbSize = sizeof(ROSMENUINFO); - mi.fMask = MIM_HELPID; - - if(NtUserMenuInfo(hmenu, &mi, FALSE)) - { - return mi.dwContextHelpID; - } - return 0; -} /* * @unimplemented @@ -5331,7 +5862,3 @@ ChangeMenuA( }; } - - - -