From 5e23122314c33684d26c6e86fe6399be5b193e59 Mon Sep 17 00:00:00 2001 From: James Tabor Date: Tue, 6 May 2014 18:09:07 +0000 Subject: [PATCH] [Win32k] - Utilize the new menu structures and use item array instead of the list method. Make sure your applications Appends are in order (reference Mdi.c). Sync ported more wine code too. - See CORE-5605, CORE-7447, CORE-7967 (Main Bug), CORE-8098 and CORE-8107 svn path=/trunk/; revision=63179 --- reactos/win32ss/include/ntuser.h | 3 +- reactos/win32ss/user/ntuser/accelerator.c | 4 +- reactos/win32ss/user/ntuser/menu.c | 961 +++++--------- reactos/win32ss/user/ntuser/menu.h | 5 +- reactos/win32ss/user/ntuser/userfuncs.h | 5 +- reactos/win32ss/user/ntuser/window.c | 7 +- reactos/win32ss/user/user32/windows/mdi.c | 26 +- reactos/win32ss/user/user32/windows/menu.c | 1395 +++++++++----------- 8 files changed, 923 insertions(+), 1483 deletions(-) diff --git a/reactos/win32ss/include/ntuser.h b/reactos/win32ss/include/ntuser.h index e1ed1608429..fb39f5ab11d 100644 --- a/reactos/win32ss/include/ntuser.h +++ b/reactos/win32ss/include/ntuser.h @@ -329,7 +329,6 @@ typedef struct tagITEM INT cyBmp; /* Height " */ //// ReactOS UNICODE_STRING lpstr; - struct tagITEM *Next; } ITEM, *PITEM; typedef struct tagMENULIST @@ -369,7 +368,7 @@ typedef struct tagMENU 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 */ + HWND hWnd; /* Window containing the menu, use POPUPMENU */ BOOL TimeToHide; } MENU, *PMENU; diff --git a/reactos/win32ss/user/ntuser/accelerator.c b/reactos/win32ss/user/ntuser/accelerator.c index f43ee5e152a..7777c509a24 100644 --- a/reactos/win32ss/user/ntuser/accelerator.c +++ b/reactos/win32ss/user/ntuser/accelerator.c @@ -99,7 +99,7 @@ co_IntTranslateAccelerator( /* Check if accelerator is associated with menu command */ hMenu = (Window->style & WS_CHILD) ? 0 : (HMENU)Window->IDMenu; hSubMenu = NULL; - MenuObject = IntGetMenuObject(hMenu); + MenuObject = UserGetMenuObject(hMenu); nPos = pAccel->cmd; if (MenuObject) { @@ -113,7 +113,7 @@ co_IntTranslateAccelerator( /* Check system menu now */ hMenu = Window->SystemMenu; hSubMenu = hMenu; /* system menu is a popup menu */ - MenuObject = IntGetMenuObject(hMenu); + MenuObject = UserGetMenuObject(hMenu); nPos = pAccel->cmd; if (MenuObject) { diff --git a/reactos/win32ss/user/ntuser/menu.c b/reactos/win32ss/user/ntuser/menu.c index f4c4e4c71c1..b7d5209954e 100644 --- a/reactos/win32ss/user/ntuser/menu.c +++ b/reactos/win32ss/user/ntuser/menu.c @@ -11,6 +11,8 @@ DBG_DEFAULT_CHANNEL(UserMenu); /* INTERNAL ******************************************************************/ +BOOL FASTCALL IntSetMenuItemInfo(PMENU, PITEM, PROSMENUITEMINFO, PUNICODE_STRING); + /* 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. */ @@ -23,16 +25,29 @@ DBG_DEFAULT_CHANNEL(UserMenu); 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) + /* Maximum number of menu items a menu can contain */ #define MAX_MENU_ITEMS (0x4000) #define MAX_GOINTOSUBMENU (0x10) #define UpdateMenuItemState(state, change) \ {\ - if((change) & MFS_DISABLED) { \ - (state) |= MFS_DISABLED; \ + if((change) & MF_GRAYED) { \ + (state) |= MF_GRAYED; \ + } else { \ + (state) &= ~MF_GRAYED; \ + } /* Separate the two for test_menu_resource_layout.*/ \ + if((change) & MF_DISABLED) { \ + (state) |= MF_DISABLED; \ } else { \ - (state) &= ~MFS_DISABLED; \ + (state) &= ~MF_DISABLED; \ } \ if((change) & MFS_CHECKED) { \ (state) |= MFS_CHECKED; \ @@ -56,42 +71,12 @@ DBG_DEFAULT_CHANNEL(UserMenu); } \ } -#define FreeMenuText(Menu,MenuItem) \ -{ \ - if((MENU_ITEM_TYPE((MenuItem)->fType) == MF_STRING) && \ - (MenuItem)->lpstr.Length) { \ - DesktopHeapFree(((PMENU)Menu)->head.rpdesk, (MenuItem)->lpstr.Buffer); \ - } \ -} - - -PMENU FASTCALL UserGetMenuObject(HMENU hMenu) -{ - PMENU Menu; - - if (!hMenu) - { - EngSetLastError(ERROR_INVALID_MENU_HANDLE); - return NULL; - } - - Menu = (PMENU)UserGetObject(gHandleTable, hMenu, TYPE_MENU); - if (!Menu) - { - EngSetLastError(ERROR_INVALID_MENU_HANDLE); - return NULL; - } - - return Menu; -} - - #if 0 void FASTCALL -DumpMenuItemList(PITEM MenuItem) +DumpMenuItemList(PMENU Menu, PITEM MenuItem) { - UINT cnt = 0; - while(MenuItem) + UINT cnt = 0, i = Menu->cItems; + while(i) { if(MenuItem->lpstr.Length) DbgPrint(" %d. %wZ\n", ++cnt, &MenuItem->lpstr); @@ -132,13 +117,22 @@ DumpMenuItemList(PITEM MenuItem) if(MFS_GRAYED & MenuItem->fState) DbgPrint("MFS_GRAYED "); DbgPrint("\n wId=%d\n", MenuItem->wID); - MenuItem = MenuItem->Next; + MenuItem++; + i--; } DbgPrint("Entries: %d\n", cnt); return; } #endif +#define FreeMenuText(Menu,MenuItem) \ +{ \ + if((MENU_ITEM_TYPE((MenuItem)->fType) == MF_STRING) && \ + (MenuItem)->lpstr.Length) { \ + DesktopHeapFree(((PMENU)Menu)->head.rpdesk, (MenuItem)->lpstr.Buffer); \ + } \ +} + PMENU FASTCALL IntGetMenuObject(HMENU hMenu) { @@ -149,64 +143,68 @@ IntGetMenuObject(HMENU hMenu) return Menu; } -BOOL FASTCALL -IntFreeMenuItem(PMENU Menu, PITEM MenuItem, BOOL bRecurse) +PMENU FASTCALL VerifyMenu(PMENU pMenu) { - FreeMenuText(Menu,MenuItem); - if(bRecurse && MenuItem->spSubMenu) - { - IntDestroyMenuObject(MenuItem->spSubMenu, bRecurse, TRUE); - } - - /* Free memory */ - DesktopHeapFree(Menu->head.rpdesk, MenuItem); - - return TRUE; -} + HMENU hMenu; + PITEM pItem; + UINT i; + if (!pMenu) return NULL; -BOOL FASTCALL -IntRemoveMenuItem(PMENU Menu, UINT uPosition, UINT uFlags, BOOL bRecurse) -{ - PITEM PrevMenuItem, MenuItem = NULL; - if(IntGetMenuItemByFlag(Menu, uPosition, uFlags, &Menu, &MenuItem, &PrevMenuItem) > -1) + ERR("VerifyMenu 1!\n"); + _SEH2_TRY { - if(MenuItem) + hMenu = UserHMGetHandle(pMenu); + pItem = pMenu->rgItems; + if (pItem) { - if(PrevMenuItem) - PrevMenuItem->Next = MenuItem->Next; - else - { - Menu->rgItems = MenuItem->Next; - } - Menu->cItems--; - return IntFreeMenuItem(Menu, MenuItem, bRecurse); + i = pItem[0].wID; + pItem[0].wID = i; } } - return FALSE; + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + ERR("Run away LOOP!\n"); + _SEH2_YIELD(return NULL); + } + _SEH2_END + ERR("VerifyMenu 2!\n"); + if ( UserObjectInDestroy(hMenu)) + return NULL; + ERR("VerifyMenu 3!\n"); + return pMenu; } -UINT FASTCALL -IntDeleteMenuItems(PMENU Menu, BOOL bRecurse) +BOOL IntDestroyMenu( PMENU pMenu, BOOL bRecurse, BOOL RemoveFromProcess) { - UINT res = 0; - 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->cItems = 0; - Menu->rgItems = NULL; - return res; + /* DestroyMenu should not destroy system menu popup owner */ + if ((pMenu->fFlags & (MNF_POPUP | MNF_SYSSUBMENU)) == MNF_POPUP && pMenu->hWnd) + { + //PWND pWnd = ValidateHwndNoErr(pMenu->hWnd); + ERR("FIXME Pop up menu window thing'ie\n"); + + //co_UserDestroyWindow( pWnd ); + //pMenu->hWnd = 0; + } + + if (pMenu->rgItems) /* recursively destroy submenus */ + { + int i; + ITEM *item = pMenu->rgItems; + for (i = pMenu->cItems; i > 0; i--, item++) + { + pMenu->cItems--; //// I hate recursion logic! (jt) 4/2014. See r63028 comment for IntDeleteMenuItems. + FreeMenuText(pMenu,item); + if (bRecurse && item->spSubMenu)//VerifyMenu(item->spSubMenu)) + { + IntDestroyMenu(item->spSubMenu, bRecurse, RemoveFromProcess); + item->spSubMenu = NULL; + } + } + DesktopHeapFree(pMenu->head.rpdesk, pMenu->rgItems ); + pMenu->rgItems = NULL; + pMenu->cItems = 0; //// What ever~! + } + return TRUE; } BOOL FASTCALL @@ -216,24 +214,15 @@ IntDestroyMenuObject(PMENU Menu, if(Menu) { PWND Window; - //PWINSTATION_OBJECT WindowStation; - //NTSTATUS Status; - + /* Remove all menu items */ - IntDeleteMenuItems(Menu, bRecurse); /* Do not destroy submenus */ + IntDestroyMenu( Menu, bRecurse, RemoveFromProcess); if(RemoveFromProcess) { RemoveEntryList(&Menu->ListEntry); } - /*Status = ObReferenceObjectByHandle(Menu->Process->Win32WindowStation, - 0, - ExWindowStationObjectType, - KernelMode, - (PVOID*)&WindowStation, - NULL); - if(NT_SUCCESS(Status))*/ if (PsGetCurrentProcessSessionId() == Menu->head.rpdesk->rpwinstaParent->dwSessionId) { BOOL ret; @@ -252,55 +241,32 @@ IntDestroyMenuObject(PMENU Menu, 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; } -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) +int FASTCALL MENU_depth( PMENU pmenu, int depth) { UINT i; ITEM *item; int subdepth; + if (!pmenu) return depth; + depth++; if( depth > MAXMENUDEPTH) return depth; item = pmenu->rgItems; subdepth = depth; - for( i = 0; i < pmenu->cItems && subdepth <= MAXMENUDEPTH; i++, item++) + for( i = 0; item, i < pmenu->cItems && subdepth <= MAXMENUDEPTH; i++, item++) { - if( item->spSubMenu) + if( item->spSubMenu)//VerifyMenu(item->spSubMenu)) { int bdepth = MENU_depth( item->spSubMenu, depth); if( bdepth > subdepth) subdepth = bdepth; @@ -317,38 +283,29 @@ int MENU_depth( PMENU pmenu, int depth) * 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 ) +PITEM FASTCALL MENU_FindItem( PMENU *pmenu, UINT *nPos, UINT wFlags ) { MENU *menu = *pmenu; ITEM *fallback = NULL; UINT fallback_pos = 0; UINT i; - PITEM pItem; + + if (!menu) return NULL; if (wFlags & MF_BYPOSITION) { + if (!menu->cItems) return NULL; 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++; - } + return &menu->rgItems[*nPos]; } else { PITEM item = menu->rgItems; - for (i = 0; item ,i < menu->cItems; i++, item = item->Next)//, item++) + for (i = 0; item, i < menu->cItems; i++, item++) { if (item->spSubMenu) { - PMENU psubmenu = item->spSubMenu; + PMENU psubmenu = item->spSubMenu;//VerifyMenu(item->spSubMenu); PITEM subitem = MENU_FindItem( &psubmenu, nPos, wFlags ); if (subitem) { @@ -376,20 +333,20 @@ ITEM *MENU_FindItem( PMENU *pmenu, UINT *nPos, UINT wFlags ) return fallback; } -BOOL IntRemoveMenu( PMENU pMenu, UINT nPos, UINT wFlags, BOOL bRecurse ) +BOOL FASTCALL +IntRemoveMenuItem( 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); + /* Remove item */ + FreeMenuText(pMenu,item); if (bRecurse && item->spSubMenu) { - IntDestroyMenu(item->spSubMenu, TRUE); + IntDestroyMenuObject(item->spSubMenu, bRecurse, TRUE); } ////// Use cAlloced with inc's of 8's.... if (--pMenu->cItems == 0) @@ -413,6 +370,100 @@ BOOL IntRemoveMenu( PMENU pMenu, UINT nPos, UINT wFlags, BOOL bRecurse ) return TRUE; } +/********************************************************************** + * MENU_InsertItem + * + * Insert (allocate) a new item into a menu. + */ +ITEM *MENU_InsertItem( PMENU menu, UINT pos, UINT flags, PMENU *submenu, UINT *npos ) +{ + 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 )) + { + if (submenu) *submenu = menu; + if (npos) *npos = pos; + 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 MenuObject, + UINT uItem, + BOOL fByPosition, + PROSMENUITEMINFO ItemInfo, + PUNICODE_STRING lpstr) +{ + PITEM MenuItem; + PMENU SubMenu = NULL; + + NT_ASSERT(MenuObject != NULL); + + if (MAX_MENU_ITEMS <= MenuObject->cItems) + { + EngSetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + + SubMenu = MenuObject; + + if(!(MenuItem = MENU_InsertItem( SubMenu, uItem, fByPosition ? MF_BYPOSITION : MF_BYCOMMAND, &SubMenu, &uItem ))) return FALSE; + + if(!IntSetMenuItemInfo(SubMenu, MenuItem, ItemInfo, lpstr)) + { + IntRemoveMenuItem(SubMenu, uItem, fByPosition ? MF_BYPOSITION : MF_BYCOMMAND, FALSE); + return FALSE; + } + + /* Force size recalculation! */ + SubMenu->cyMenu = 0; + MenuItem->hbmpChecked = MenuItem->hbmpUnchecked = 0; + + TRACE("IntInsertMenuItemToList = %i %d\n", uItem, (BOOL)((INT)uItem >= 0)); + + return TRUE; +} + PMENU FASTCALL IntCreateMenu(PHANDLE Handle, BOOL IsMenuBar) { @@ -460,21 +511,21 @@ BOOL FASTCALL IntCloneMenuItems(PMENU Destination, PMENU Source) { PITEM MenuItem, NewMenuItem = NULL; - PITEM Old = NULL; + UINT i; if(!Source->cItems) return FALSE; + NewMenuItem = DesktopHeapAlloc(Destination->head.rpdesk, (Source->cItems+1) * sizeof(ITEM)); + if(!NewMenuItem) return FALSE; + + RtlZeroMemory(NewMenuItem, (Source->cItems+1) * sizeof(ITEM)); + + Destination->rgItems = NewMenuItem; + MenuItem = Source->rgItems; - while(MenuItem) + for (i = 0; i < Source->cItems; i++, MenuItem++, NewMenuItem++) { - Old = NewMenuItem; - if(NewMenuItem) - NewMenuItem->Next = 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; @@ -506,16 +557,7 @@ IntCloneMenuItems(PMENU Destination, PMENU Source) NewMenuItem->lpstr.Buffer = MenuItem->lpstr.Buffer; } NewMenuItem->hbmp = MenuItem->hbmp; - - NewMenuItem->Next = NULL; - if(Old) - Old->Next = NewMenuItem; - else - Destination->rgItems = NewMenuItem; - Destination->cItems++; - MenuItem = MenuItem->Next; } - return TRUE; } @@ -547,7 +589,7 @@ IntCloneMenu(PMENU Source) Menu->spwndNotify = NULL; Menu->cyMenu = 0; Menu->cxMenu = 0; - Menu->cItems = 0; + Menu->cItems = Source->cItems; Menu->iTop = 0; Menu->iMaxTop = 0; Menu->cxTextAlign = 0; @@ -631,21 +673,13 @@ IntSetMenuInfo(PMENU Menu, PROSMENUINFO lpmi) { int i; PITEM item = Menu->rgItems; - for ( i = Menu->cItems; i; i--, item = item->Next) - { - if ( item->spSubMenu ) - { - 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) { @@ -664,117 +698,6 @@ IntSetMenuInfo(PMENU Menu, PROSMENUINFO lpmi) return TRUE; } -// -// Old and yeah~..... Why start with a -1 for position search? -// -int FASTCALL -IntGetMenuItemByFlag(PMENU Menu, - UINT uSearchBy, - UINT fFlag, - PMENU *SubMenu, - PITEM *MenuItem, - PITEM *PrevMenuItem) -{ - PITEM PrevItem = NULL; - PITEM CurItem = Menu->rgItems; - int p; - int ret; - - if(MF_BYPOSITION & fFlag) - { - p = uSearchBy; - while(CurItem && (p > 0)) - { - PrevItem = CurItem; - CurItem = CurItem->Next; - p--; - } - if(CurItem) - { - if(MenuItem) - *MenuItem = CurItem; - if(PrevMenuItem) - *PrevMenuItem = PrevItem; - } - else - { - if(MenuItem) - *MenuItem = NULL; - if(PrevMenuItem) - *PrevMenuItem = NULL; /* ? */ - return -1; - } - - return uSearchBy - p; - } - else - { - p = 0; - while(CurItem) - { - if(CurItem->wID == uSearchBy) - { - if(MenuItem) - *MenuItem = CurItem; - if(PrevMenuItem) - *PrevMenuItem = PrevItem; - if(SubMenu) - *SubMenu = Menu; - - return p; - } - else - { - if(CurItem->spSubMenu) - { - ret = IntGetMenuItemByFlag(CurItem->spSubMenu, uSearchBy, fFlag, SubMenu, MenuItem, PrevMenuItem); - if(ret != -1) - { - return ret; - } - } - } - PrevItem = CurItem; - CurItem = CurItem->Next; - p++; - } - } - return -1; -} - - -int FASTCALL -IntInsertMenuItemToList(PMENU Menu, PITEM MenuItem, int pos) -{ - PITEM CurItem; - PITEM LastItem = NULL; - UINT npos = 0; - - CurItem = Menu->rgItems; - while(CurItem && (pos != 0)) - { - LastItem = CurItem; - CurItem = CurItem->Next; - pos--; - npos++; - } - - if(LastItem) - { - /* Insert the item after LastItem */ - LastItem->Next = MenuItem; - } - else - { - /* Insert at the beginning */ - Menu->rgItems = MenuItem; - } - MenuItem->Next = CurItem; - Menu->cItems++; - - return npos; -} - BOOL FASTCALL IntGetMenuItemInfo(PMENU Menu, /* UNUSED PARAM!! */ PITEM MenuItem, PROSMENUITEMINFO lpmii) @@ -850,18 +773,17 @@ BOOL FASTCALL IntSetMenuItemInfo(PMENU MenuObject, PITEM MenuItem, PROSMENUITEMINFO lpmii, PUNICODE_STRING lpstr) { PMENU SubMenuObject; - UINT fTypeMask = (MFT_BITMAP | MFT_MENUBARBREAK | MFT_MENUBREAK | MFT_OWNERDRAW | MFT_RADIOCHECK | MFT_RIGHTJUSTIFY | MFT_SEPARATOR); if(!MenuItem || !MenuObject || !lpmii) { return FALSE; } - if (lpmii->fType & ~fTypeMask) + if ( lpmii->fMask & MIIM_FTYPE ) { - ERR("IntSetMenuItemInfo invalid fType flags %x\n", lpmii->fType & ~fTypeMask); - lpmii->fMask &= ~(MIIM_TYPE | MIIM_FTYPE); + MenuItem->fType &= ~MENUITEMINFO_TYPE_MASK; + MenuItem->fType |= lpmii->fType & MENUITEMINFO_TYPE_MASK; } - if (lpmii->fMask & MIIM_TYPE) + if (lpmii->fMask & MIIM_TYPE) { #if 0 //// Done in User32. if (lpmii->fMask & ( MIIM_STRING | MIIM_FTYPE | MIIM_BITMAP)) @@ -882,6 +804,7 @@ IntSetMenuItemInfo(PMENU MenuObject, PITEM MenuItem, PROSMENUITEMINFO lpmii, PUN { FreeMenuText(MenuObject,MenuItem); RtlInitUnicodeString(&MenuItem->lpstr, NULL); + MenuItem->Xlpstr = NULL; } if(lpmii->fType & MFT_BITMAP) { @@ -891,25 +814,12 @@ IntSetMenuItemInfo(PMENU MenuObject, PITEM MenuItem, PROSMENUITEMINFO lpmii, PUN { /* Win 9x/Me stuff */ MenuItem->hbmp = (HBITMAP)((ULONG_PTR)(LOWORD(lpmii->dwTypeData))); } + lpmii->dwTypeData = 0; } - 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; - } - #endif - MenuItem->fType &= ~MENUITEMINFO_TYPE_MASK; - MenuItem->fType |= lpmii->fType & MENUITEMINFO_TYPE_MASK; } if(lpmii->fMask & MIIM_BITMAP) { - MenuItem->hbmp = lpmii->hbmpItem; + MenuItem->hbmp = lpmii->hbmpItem; } if(lpmii->fMask & MIIM_CHECKMARKS) { @@ -942,9 +852,14 @@ IntSetMenuItemInfo(PMENU MenuObject, PITEM MenuItem, PROSMENUITEMINFO lpmii, PUN SubMenuObject = UserGetMenuObject(lpmii->hSubMenu); if (SubMenuObject != NULL) { + if ( MENU_depth( SubMenuObject, 0) > MAXMENUDEPTH) + { + ERR( "Loop detected in menu hierarchy or maximum menu depth exceeded!\n"); + return FALSE; + } SubMenuObject->fFlags |= MNF_POPUP; // Now fix the test_subpopup_locked_by_menu tests.... - if (MenuItem->spSubMenu) UserDereferenceObject(MenuItem->spSubMenu); + if (MenuItem->spSubMenu) IntReleaseMenuObject(MenuItem->spSubMenu); MenuItem->spSubMenu = SubMenuObject; UserReferenceObject(SubMenuObject); } @@ -956,7 +871,7 @@ IntSetMenuItemInfo(PMENU MenuObject, PITEM MenuItem, PROSMENUITEMINFO lpmii, PUN } else { // If submenu just dereference it. - if (MenuItem->spSubMenu) UserDereferenceObject(MenuItem->spSubMenu); + if (MenuItem->spSubMenu) IntReleaseMenuObject(MenuItem->spSubMenu); MenuItem->spSubMenu = NULL; } } @@ -964,9 +879,12 @@ IntSetMenuItemInfo(PMENU MenuObject, PITEM MenuItem, PROSMENUITEMINFO lpmii, PUN if ((lpmii->fMask & MIIM_STRING) || ((lpmii->fMask & MIIM_TYPE) && (MENU_ITEM_TYPE(lpmii->fType) == MF_STRING))) { + /* free the string when used */ FreeMenuText(MenuObject,MenuItem); + RtlInitUnicodeString(&MenuItem->lpstr, NULL); + MenuItem->Xlpstr = NULL; - if(lpmii->dwTypeData && lpmii->cch) + if(lpmii->dwTypeData && lpmii->cch && lpstr && lpstr->Buffer) { UNICODE_STRING Source; @@ -984,27 +902,15 @@ IntSetMenuItemInfo(PMENU MenuObject, PITEM MenuItem, PROSMENUITEMINFO lpmii, PUN MenuItem->cch = MenuItem->lpstr.Length / sizeof(WCHAR); MenuItem->Xlpstr = (USHORT*)MenuItem->lpstr.Buffer; } - else - { - RtlInitUnicodeString(&MenuItem->lpstr, NULL); - MenuItem->Xlpstr = NULL; - } - } - else - { - if (0 == (MenuObject->fFlags & MNF_SYSDESKMN)) - { - MenuItem->fType |= MF_SEPARATOR; - } - 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( !(MenuObject->fFlags & MNF_SYSDESKMN) && + !MenuItem->Xlpstr && + !lpmii->dwTypeData && + !(MenuItem->fType & MFT_OWNERDRAW) && + !MenuItem->hbmp) + MenuItem->fType |= MFT_SEPARATOR; if (sizeof(ROSMENUITEMINFO) == lpmii->cbSize) { @@ -1022,130 +928,6 @@ IntSetMenuItemInfo(PMENU MenuObject, PITEM MenuItem, PROSMENUITEMINFO lpmii, PUN } -/********************************************************************** - * 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 MenuObject, - UINT uItem, - BOOL fByPosition, - PROSMENUITEMINFO ItemInfo) -{ - int pos; - PITEM MenuItem; - PMENU SubMenu = NULL; - - NT_ASSERT(MenuObject != NULL); - //ERR("InsertMenuItem\n"); - if (MAX_MENU_ITEMS <= MenuObject->cItems) - { - EngSetLastError(ERROR_NOT_ENOUGH_MEMORY); - return FALSE; - } - - if (fByPosition) - { - SubMenu = MenuObject; - /* calculate position */ - pos = (int)uItem; - if(uItem > MenuObject->cItems) - { - pos = MenuObject->cItems; - } - } - else - { - pos = IntGetMenuItemByFlag(MenuObject, uItem, MF_BYCOMMAND, &SubMenu, NULL, NULL); - } - if (SubMenu == NULL) - { - /* Default to last position of menu */ - SubMenu = MenuObject; - pos = MenuObject->cItems; - } - - - if (pos < -1) - { - pos = -1; - } - - MenuItem = DesktopHeapAlloc(MenuObject->head.rpdesk, sizeof(ITEM)); - if (NULL == MenuItem) - { - EngSetLastError(ERROR_NOT_ENOUGH_MEMORY); - return FALSE; - } - - RtlZeroMemory(MenuItem, sizeof(MenuItem)); - - if(!IntSetMenuItemInfo(SubMenu, MenuItem, ItemInfo, NULL)) - { - DesktopHeapFree(MenuObject->head.rpdesk, MenuItem); - return FALSE; - } - - /* Force size recalculation! */ - MenuObject->cyMenu = 0; - MenuItem->hbmpChecked = MenuItem->hbmpUnchecked = 0; - - pos = IntInsertMenuItemToList(SubMenu, MenuItem, pos); - - TRACE("IntInsertMenuItemToList = %i\n", pos); - - return (pos >= 0); -} - UINT FASTCALL IntEnableMenuItem(PMENU MenuObject, UINT uIDEnableItem, UINT uEnable) { @@ -1173,109 +955,7 @@ IntEnableMenuItem(PMENU MenuObject, UINT uIDEnableItem, UINT uEnable) } return res; } -#if 0 // Moved to User32. -DWORD FASTCALL -IntBuildMenuItemList(PMENU MenuObject, PVOID Buffer, ULONG nMax) -{ - DWORD res = 0; - ROSMENUITEMINFO mii; - PVOID Buf; - PITEM CurItem = MenuObject->rgItems; - PWCHAR StrOut; - NTSTATUS Status; - 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; - 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->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)) - { - SetLastNtError(Status); - return 0; - } - Buf = (PVOID)((ULONG_PTR)Buf + sizeof(ROSMENUITEMINFO)); - - if (0 != CurItem->lpstr.Length - && (nMax >= CurItem->lpstr.Length + sizeof(WCHAR))) - { - /* Copy string */ - Status = MmCopyToCaller(StrOut, CurItem->lpstr.Buffer, - CurItem->lpstr.Length); - if (! NT_SUCCESS(Status)) - { - SetLastNtError(Status); - return 0; - } - StrOut += CurItem->lpstr.Length / sizeof(WCHAR); - Status = MmCopyToCaller(StrOut, &NulByte, sizeof(WCHAR)); - if (! NT_SUCCESS(Status)) - { - SetLastNtError(Status); - return 0; - } - StrOut++; - nMax -= CurItem->lpstr.Length + sizeof(WCHAR); - } - else if (0 != CurItem->lpstr.Length) - { - break; - } - - CurItem = CurItem->Next; - res++; - } - } - else - { - while (NULL != CurItem) - { - res += sizeof(ROSMENUITEMINFO) + CurItem->lpstr.Length + sizeof(WCHAR); - CurItem = CurItem->Next; - } - } - return res; -} -#endif DWORD FASTCALL IntCheckMenuItem(PMENU MenuObject, UINT uIDCheckItem, UINT uCheck) { @@ -1301,32 +981,31 @@ IntHiliteMenuItem(PWND WindowObject, if (!(MenuItem = MENU_FindItem( &MenuObject, &uItemHilite, uHilite ))) return FALSE; - if (MenuItem) + if (uHilite & MF_HILITE) { - if (uHilite & MF_HILITE) - { - MenuItem->fState |= MF_HILITE; - } - else - { - MenuItem->fState &= ~MF_HILITE; - } + MenuItem->fState |= MF_HILITE; + } + else + { + MenuItem->fState &= ~MF_HILITE; } /* FIXME: Update the window's menu */ - return TRUE; + return TRUE; // Always returns true!!!! } BOOL FASTCALL UserSetMenuDefaultItem(PMENU MenuObject, UINT uItem, UINT fByPos) { - BOOL ret = FALSE; + UINT i; PITEM MenuItem = MenuObject->rgItems; - while(MenuItem) + if (!MenuItem) return FALSE; + + /* reset all default-item flags */ + for (i = 0; MenuItem, i < MenuObject->cItems; i++, MenuItem++) { - MenuItem->fState &= ~MFS_DEFAULT; - MenuItem = MenuItem->Next; + MenuItem->fState &= ~MFS_DEFAULT; } /* no default item */ @@ -1334,90 +1013,59 @@ UserSetMenuDefaultItem(PMENU MenuObject, UINT uItem, UINT fByPos) { return TRUE; } - - if(fByPos) + MenuItem = MenuObject->rgItems; + if ( fByPos ) { - UINT pos = 0; - while(MenuItem) - { - if(pos == uItem) - { - MenuItem->fState |= MFS_DEFAULT; - ret = TRUE; - } - else - { - MenuItem->fState &= ~MFS_DEFAULT; - } - pos++; - MenuItem = MenuItem->Next; - } + if ( uItem >= MenuObject->cItems ) return FALSE; + MenuItem[uItem].fState |= MFS_DEFAULT; + return TRUE; } else { - while(MenuItem) + for (i = 0; MenuItem, i < MenuObject->cItems; i++, MenuItem++) { - if(!ret && (MenuItem->wID == uItem)) - { - MenuItem->fState |= MFS_DEFAULT; - ret = TRUE; - } - else - { - MenuItem->fState &= ~MFS_DEFAULT; - } - MenuItem = MenuItem->Next; + if (MenuItem->wID == uItem) + { + MenuItem->fState |= MFS_DEFAULT; + return TRUE; + } } + } - return ret; + return FALSE; } UINT FASTCALL -IntGetMenuDefaultItem(PMENU MenuObject, UINT fByPos, UINT gmdiFlags, - DWORD *gismc) +IntGetMenuDefaultItem(PMENU MenuObject, UINT fByPos, UINT gmdiFlags, DWORD *gismc) { - UINT x = 0; - UINT res = -1; - UINT sres; + UINT i = 0; PITEM MenuItem = MenuObject->rgItems; - while(MenuItem) - { - if(MenuItem->fState & MFS_DEFAULT) - { - - if(!(gmdiFlags & GMDI_USEDISABLED) && (MenuItem->fState & MFS_DISABLED)) - break; + /* empty menu */ + if (!MenuItem) return -1; - if(fByPos) - res = x; - else - res = MenuItem->wID; - - if((*gismc < MAX_GOINTOSUBMENU) && (gmdiFlags & GMDI_GOINTOPOPUPS) && - MenuItem->spSubMenu) - { - - if(MenuItem->spSubMenu == MenuObject) - break; - - (*gismc)++; - sres = IntGetMenuDefaultItem(MenuItem->spSubMenu, fByPos, gmdiFlags, gismc); - (*gismc)--; + while ( !( MenuItem->fState & MFS_DEFAULT ) ) + { + i++; MenuItem++; + if (i >= MenuObject->cItems ) return -1; + } - if(sres > (UINT)-1) - res = sres; - } + /* default: don't return disabled items */ + if ( (!(GMDI_USEDISABLED & gmdiFlags)) && (MenuItem->fState & MFS_DISABLED )) return -1; - break; - } + /* search rekursiv when needed */ + if ( (MenuItem->fType & MF_POPUP) && (gmdiFlags & GMDI_GOINTOPOPUPS) && MenuItem->spSubMenu) + { + UINT ret; + (*gismc)++; + ret = IntGetMenuDefaultItem( MenuItem->spSubMenu, fByPos, gmdiFlags, gismc ); + (*gismc)--; + if ( -1 != ret ) return ret; - MenuItem = MenuItem->Next; - x++; + /* when item not found in submenu, return the popup item */ } - - return res; + return ( fByPos ) ? i : MenuItem->wID; } VOID FASTCALL @@ -1484,7 +1132,7 @@ IntCleanupMenus(struct _EPROCESS *Process, PPROCESSINFO Win32Process) { LastHead = Win32Process->MenuListHead.Flink; MenuObject = CONTAINING_RECORD(Win32Process->MenuListHead.Flink, MENU, ListEntry); - ERR("Menus are stuck on the process list!\n"); + TRACE("Menus are stuck on the process list!\n"); IntDestroyMenuObject(MenuObject, FALSE, TRUE); } @@ -1631,7 +1279,8 @@ UserInsertMenuItem( PMENU Menu, UINT uItem, BOOL fByPosition, - LPCMENUITEMINFOW UnsafeItemInfo) + LPCMENUITEMINFOW UnsafeItemInfo, + PUNICODE_STRING lpstr) { NTSTATUS Status; ROSMENUITEMINFO ItemInfo; @@ -1646,7 +1295,7 @@ UserInsertMenuItem( EngSetLastError(ERROR_INVALID_PARAMETER); return FALSE; } - return IntInsertMenuItem(Menu, uItem, fByPosition, &ItemInfo); + return IntInsertMenuItem(Menu, uItem, fByPosition, &ItemInfo, lpstr); } /* Try to copy without last field (not present in older versions) */ @@ -1659,7 +1308,7 @@ UserInsertMenuItem( return FALSE; } ItemInfo.hbmpItem = (HBITMAP)0; - return IntInsertMenuItem(Menu, uItem, fByPosition, &ItemInfo); + return IntInsertMenuItem(Menu, uItem, fByPosition, &ItemInfo, lpstr); } SetLastNtError(Status); @@ -1717,7 +1366,7 @@ UINT FASTCALL IntFindSubMenu(HMENU *hMenu, HMENU hSubTarget ) return NO_SELECTED_ITEM; item = menu->rgItems; - for (i = 0; i < menu->cItems; i++, item = item->Next)//item++) + for (i = 0; i < menu->cItems; i++, item++) { if (!item->spSubMenu) continue; @@ -1792,7 +1441,8 @@ UserMenuItemInfo( UINT Item, BOOL ByPosition, PROSMENUITEMINFO UnsafeItemInfo, - BOOL SetOrGet) + BOOL SetOrGet, + PUNICODE_STRING lpstr) { PITEM MenuItem; ROSMENUITEMINFO ItemInfo; @@ -1836,7 +1486,7 @@ UserMenuItemInfo( if (SetOrGet) { - Ret = IntSetMenuItemInfo(Menu, MenuItem, &ItemInfo, NULL); + Ret = IntSetMenuItemInfo(Menu, MenuItem, &ItemInfo, lpstr); } else { @@ -1931,7 +1581,6 @@ IntGetMenuItemRect( { LONG XMove, YMove; PITEM MenuItem; - //int p = 0; if (!pWnd) { @@ -2109,7 +1758,6 @@ BOOL FASTCALL UserDestroyMenu(HMENU hMenu) return FALSE; } - //if(Menu->Process != PsGetCurrentProcess()) if (Menu->head.rpdesk != pti->rpdesk) { EngSetLastError(ERROR_ACCESS_DENIED); @@ -2277,15 +1925,15 @@ NtUserGetMenuBarInfo( //kmbi.fBarFocused = top_popup_hmenu == hMenu; if (idItem) { - PITEM MenuItem; - UINT nPos = idItem-1; + //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 ) + if (kmbi.fFocused && (Menu->rgItems[idItem - 1].spSubMenu)) + //MenuItem = MENU_FindItem (&Menu, &nPos, MF_BYPOSITION); + //if ( MenuItem && kmbi.fFocused && MenuItem->spSubMenu ) { - //kmbi.hwndMenu = Menu->rgItems[idItem - 1].spSubMenu->hWnd; - kmbi.hwndMenu = MenuItem->spSubMenu->hWnd; + kmbi.hwndMenu = Menu->rgItems[idItem - 1].spSubMenu->hWnd; + //kmbi.hwndMenu = MenuItem->spSubMenu->hWnd; } } /* else @@ -2327,6 +1975,7 @@ NtUserGetMenuIndex( { PMENU Menu, SubMenu; PITEM MenuItem; + UINT i; DECLARE_RETURN(UINT); TRACE("Enter NtUserGetMenuIndex\n"); @@ -2337,13 +1986,11 @@ NtUserGetMenuIndex( RETURN(0xFFFFFFFF); MenuItem = Menu->rgItems; - while(MenuItem) + for (i = 0; i < Menu->cItems; i++, MenuItem++) { - if (MenuItem->spSubMenu == SubMenu) - RETURN(MenuItem->wID); - MenuItem = MenuItem->Next; + if (MenuItem->spSubMenu == SubMenu) + RETURN(MenuItem->wID); } - RETURN(0xFFFFFFFF); CLEANUP: @@ -2507,7 +2154,7 @@ NtUserMenuItemFromPoint( Y -= Window->rcWindow.top; mi = Menu->rgItems; - for (i = 0; NULL != mi; i++)//, mi++) + for (i = 0; i < Menu->cItems; i++, mi++) { RECTL Rect; Rect.left = mi->xItem; @@ -2519,7 +2166,6 @@ NtUserMenuItemFromPoint( { break; } - mi = mi->Next; } RETURN( (mi ? i : NO_SELECTED_ITEM)); @@ -2696,7 +2342,7 @@ NtUserThunkedMenuItemInfo( RETURN(FALSE); } - lstrCaption.Buffer = NULL; + RtlInitUnicodeString(&lstrCaption, 0); /* Check if we got a Caption */ if (lpszCaption && lpszCaption->Buffer) @@ -2711,12 +2357,11 @@ NtUserThunkedMenuItemInfo( SetLastNtError(Status); RETURN(FALSE); } - ///// Now use it! } - if (bInsert) RETURN( UserInsertMenuItem(Menu, uItem, fByPosition, lpmii)); + if (bInsert) RETURN( UserInsertMenuItem(Menu, uItem, fByPosition, lpmii, &lstrCaption)); - RETURN( UserMenuItemInfo(Menu, uItem, fByPosition, (PROSMENUITEMINFO)lpmii, TRUE)); + RETURN( UserMenuItemInfo(Menu, uItem, fByPosition, (PROSMENUITEMINFO)lpmii, TRUE, &lstrCaption)); CLEANUP: TRACE("Leave NtUserThunkedMenuItemInfo, ret=%i\n",_ret_); diff --git a/reactos/win32ss/user/ntuser/menu.h b/reactos/win32ss/user/ntuser/menu.h index 9ff6b0cbee0..e5830546cb5 100644 --- a/reactos/win32ss/user/ntuser/menu.h +++ b/reactos/win32ss/user/ntuser/menu.h @@ -38,8 +38,7 @@ BOOL FASTCALL IntCleanupMenus(struct _EPROCESS *Process, PPROCESSINFO Win32Process); BOOL FASTCALL -IntInsertMenuItem(_In_ PMENU MenuObject, UINT uItem, BOOL fByPosition, - PROSMENUITEMINFO ItemInfo); +IntInsertMenuItem(_In_ PMENU MenuObject, UINT uItem, BOOL fByPosition, PROSMENUITEMINFO ItemInfo, PUNICODE_STRING lpstr); PMENU FASTCALL IntGetSystemMenu(PWND Window, BOOL bRevert, BOOL RetMenu); @@ -47,4 +46,4 @@ 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 ); +PITEM FASTCALL MENU_FindItem( PMENU *pmenu, UINT *nPos, UINT wFlags ); diff --git a/reactos/win32ss/user/ntuser/userfuncs.h b/reactos/win32ss/user/ntuser/userfuncs.h index 96935084a42..2e45bc6e4f7 100644 --- a/reactos/win32ss/user/ntuser/userfuncs.h +++ b/reactos/win32ss/user/ntuser/userfuncs.h @@ -1,6 +1,9 @@ #pragma once -PMENU FASTCALL UserGetMenuObject(HMENU hMenu); +FORCEINLINE PMENU UserGetMenuObject(HMENU hMenu) +{ + return ValidateHandle(hMenu, TYPE_MENU); +} #define ASSERT_REFS_CO(_obj_) \ { \ diff --git a/reactos/win32ss/user/ntuser/window.c b/reactos/win32ss/user/ntuser/window.c index 6e95a3e6b8d..6259742e623 100644 --- a/reactos/win32ss/user/ntuser/window.c +++ b/reactos/win32ss/user/ntuser/window.c @@ -953,6 +953,11 @@ IntGetSystemMenu(PWND Window, BOOL bRevert, BOOL RetMenu) SysMenu->fFlags |= MNF_SYSDESKMN; SysMenu->hWnd = Window->head.h; hNewMenu = co_IntLoadSysMenuTemplate(); + //if ( Window->ExStyle & WS_EX_MDICHILD ) + //hNewMenu = co_IntCallLoadMenu( NULL, L"SYSMENUMDI"); + // else + //hNewMenu = co_IntCallLoadMenu( NULL, L"SYSMENU"); + // Do the rest in here. if(!hNewMenu) { IntReleaseMenuObject(SysMenu); @@ -985,7 +990,7 @@ IntGetSystemMenu(PWND Window, BOOL bRevert, BOOL RetMenu) ItemInfo.dwTypeData = NULL; ItemInfo.cch = 0; ItemInfo.hSubMenu = NewMenu->head.h; - IntInsertMenuItem(SysMenu, (UINT) -1, TRUE, &ItemInfo); + IntInsertMenuItem(SysMenu, (UINT) -1, TRUE, &ItemInfo, NULL); Window->SystemMenu = SysMenu->head.h; diff --git a/reactos/win32ss/user/user32/windows/mdi.c b/reactos/win32ss/user/user32/windows/mdi.c index ba844d0da22..ae867416199 100644 --- a/reactos/win32ss/user/user32/windows/mdi.c +++ b/reactos/win32ss/user/user32/windows/mdi.c @@ -897,8 +897,11 @@ static BOOL MDI_AugmentFrameMenu( HWND frame, HWND hChild ) nItems = GetMenuItemCount(menu) - 1; iId = GetMenuItemID(menu,nItems) ; if (iId == SC_RESTORE || iId == SC_CLOSE) + { + ERR("system buttons already exist\n"); return 0; - + } +//// End /* create a copy of sysmenu popup and insert it into frame menu bar */ if (!(hSysPopup = GetSystemMenu(hChild, FALSE))) { @@ -907,21 +910,14 @@ static BOOL MDI_AugmentFrameMenu( HWND frame, HWND hChild ) } AppendMenuW(menu, MF_HELP | MF_BITMAP, - SC_MINIMIZE, (LPCWSTR)HBMMENU_MBAR_MINIMIZE ) ; + SC_CLOSE, is_close_enabled(hChild, hSysPopup) ? + (LPCWSTR)HBMMENU_MBAR_CLOSE : (LPCWSTR)HBMMENU_MBAR_CLOSE_D ); AppendMenuW(menu, MF_HELP | MF_BITMAP, SC_RESTORE, (LPCWSTR)HBMMENU_MBAR_RESTORE ); AppendMenuW(menu, MF_HELP | MF_BITMAP, - SC_CLOSE, is_close_enabled(hChild, hSysPopup) ? - (LPCWSTR)HBMMENU_MBAR_CLOSE : (LPCWSTR)HBMMENU_MBAR_CLOSE_D ); + SC_MINIMIZE, (LPCWSTR)HBMMENU_MBAR_MINIMIZE ) ; /* The system menu is replaced by the child icon */ -/* hIcon = (HICON)GetClassLongPtrW(hChild, GCLP_HICONSM); - if (!hIcon) - hIcon = (HICON)GetClassLongPtrW(hChild, GCLP_HICON); - if (!hIcon) - hIcon = LoadIconW(NULL, IDI_APPLICATION); -*/ -//// End hIcon = (HICON)SendMessageW(hChild, WM_GETICON, ICON_SMALL, 0); if (!hIcon) hIcon = (HICON)SendMessageW(hChild, WM_GETICON, ICON_BIG, 0); @@ -990,7 +986,10 @@ static BOOL MDI_RestoreFrameMenu( HWND frame, HWND hChild, HBITMAP hBmpClose ) nItems = GetMenuItemCount(menu) - 1; iId = GetMenuItemID(menu,nItems) ; if( !(iId == SC_RESTORE || iId == SC_CLOSE) ) + { + ERR("no system buttons then nothing to do\n"); return 0; + } /* * Remove the system menu, If that menu is the icon of the window @@ -1534,9 +1533,7 @@ LRESULT WINAPI DefMDIChildProcA( HWND hwnd, UINT message, case WM_CHILDACTIVATE: case WM_SYSCOMMAND: case WM_SHOWWINDOW: -#ifndef __REACTOS__ case WM_SETVISIBLE: -#endif case WM_SIZE: case WM_NEXTMENU: case WM_SYSCHAR: @@ -1613,9 +1610,8 @@ LRESULT WINAPI DefMDIChildProcW( HWND hwnd, UINT message, break; case WM_SHOWWINDOW: -#ifndef __REACTOS__ case WM_SETVISIBLE: -#endif //// Commented out r57663 + //// Commented out r57663 /*if (ci->hwndChildMaximized) ci->mdiFlags &= ~MDIF_NEEDUPDATE; else*/ MDI_PostUpdate(client, ci, SB_BOTH+1); break; diff --git a/reactos/win32ss/user/user32/windows/menu.c b/reactos/win32ss/user/user32/windows/menu.c index 7470a3c8f9f..f1ef54089da 100644 --- a/reactos/win32ss/user/user32/windows/menu.c +++ b/reactos/win32ss/user/user32/windows/menu.c @@ -15,6 +15,8 @@ LRESULT DefWndNCPaint(HWND hWnd, HRGN hRgn, BOOL Active); BOOL WINAPI GdiValidateHandle(HGDIOBJ hobj); +LRESULT DefWndNCHitTest(HWND hWnd, POINT Point); +void FASTCALL NcGetSysPopupPos(HWND Wnd, RECT *Rect); WINE_DEFAULT_DEBUG_CHANNEL(menu); @@ -132,7 +134,23 @@ static SIZE MenuCharSize; */ FORCEINLINE PMENU MENU_GetMenu(HMENU hMenu) { - return ValidateHandle(hMenu, TYPE_MENU); + return ValidateHandleNoErr(hMenu, TYPE_MENU); +} + +/*********************************************************************** + * get_win_sys_menu + * + * Get the system menu of a window + */ +static HMENU get_win_sys_menu( HWND hwnd ) +{ + HMENU ret = 0; + WND *win = ValidateHwnd( hwnd ); + if (win) + { + ret = win->SystemMenu; + } + return ret; } /*********************************************************************** @@ -154,22 +172,13 @@ ITEM *MENU_FindItem( HMENU *hmenu, UINT *nPos, UINT wFlags ) { 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++; - } + if (pItem) pItem = &pItem[*nPos]; + return pItem; } 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++) + for (i = 0; item, i < menu->cItems; i++, item++) { if (item->spSubMenu) { @@ -206,41 +215,33 @@ ITEM *MENU_FindItem( HMENU *hmenu, UINT *nPos, UINT wFlags ) UINT FASTCALL IntGetMenuDefaultItem(PMENU Menu, BOOL fByPos, UINT gmdiFlags, DWORD *gismc) { - UINT x = 0; - UINT res = -1; - UINT sres; + UINT i = 0; PITEM Item = Menu->rgItems ? DesktopPtrToUser(Menu->rgItems) : NULL; - while(Item) - { - if (Item->fState & MFS_DEFAULT) - { - if (!(gmdiFlags & GMDI_USEDISABLED) && - (Item->fState & MFS_DISABLED) ) - break; + /* empty menu */ + if (!Item) return -1; - res = fByPos ? x : Item->wID; + while ( !( Item->fState & MFS_DEFAULT ) ) + { + i++; Item++; + if (i >= Menu->cItems ) return -1; + } - if ((*gismc < MAX_GOINTOSUBMENU) && - (gmdiFlags & GMDI_GOINTOPOPUPS) && - Item->spSubMenu) - { - if (DesktopPtrToUser(Item->spSubMenu) == Menu) - break; + /* default: don't return disabled items */ + if ( (!(GMDI_USEDISABLED & gmdiFlags)) && (Item->fState & MFS_DISABLED )) return -1; - (*gismc)++; - sres = IntGetMenuDefaultItem( DesktopPtrToUser(Item->spSubMenu), fByPos, gmdiFlags, gismc); - (*gismc)--; + /* search rekursiv when needed */ + if ( (Item->fType & MF_POPUP) && (gmdiFlags & GMDI_GOINTOPOPUPS) && Item->spSubMenu) + { + UINT ret; + (*gismc)++; + ret = IntGetMenuDefaultItem( DesktopPtrToUser(Item->spSubMenu), fByPos, gmdiFlags, gismc ); + (*gismc)--; + if ( -1 != ret ) return ret; - if(sres > (UINT)-1) - res = sres; - } - break; - } - Item = Item->Next ? DesktopPtrToUser(Item->Next) : NULL; - x++; + /* when item not found in submenu, return the popup item */ } - return res; + return ( fByPos ) ? i : Item->wID; } static BOOL GetMenuItemInfo_common ( HMENU hmenu, @@ -256,7 +257,6 @@ static BOOL GetMenuItemInfo_common ( HMENU hmenu, if (!pItem) { SetLastError( ERROR_MENU_ITEM_NOT_FOUND); - //SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } @@ -339,7 +339,7 @@ static BOOL GetMenuItemInfo_common ( HMENU hmenu, lpmii->hbmpItem = pItem->hbmp; if (lpmii->fMask & MIIM_STATE) - lpmii->fState = pItem->fState & MII_STATE_MASK; //MENUITEMINFO_STATE_MASK; + lpmii->fState = pItem->fState & MENUITEMINFO_STATE_MASK; if (lpmii->fMask & MIIM_ID) lpmii->wID = pItem->wID; @@ -377,7 +377,7 @@ static BOOL FASTCALL MenuGetRosMenuInfo(PROSMENUINFO MenuInfo, HMENU Menu) { PMENU pMenu; - if (!(pMenu = ValidateHandle(Menu, TYPE_MENU))) return FALSE; + if (!(pMenu = ValidateHandleNoErr(Menu, TYPE_MENU))) return FALSE; MenuInfo->hbrBack = pMenu->hbrBack; MenuInfo->dwContextHelpID = pMenu->dwContextHelpId; @@ -518,6 +518,10 @@ MenuSetRosMenuItemInfo(HMENU Menu, UINT Index, PROSMENUITEMINFO ItemInfo) { ItemInfo->cch = strlenW(ItemInfo->dwTypeData); } + if (ItemInfo->hSubMenu) + { + if (!IsMenu(ItemInfo->hSubMenu)) ItemInfo->hSubMenu = NULL; + } Ret = NtUserThunkedMenuItemInfo(Menu, Index, TRUE, FALSE, (LPMENUITEMINFOW)ItemInfo, NULL); return Ret; } @@ -537,139 +541,6 @@ MenuCleanupRosMenuItemInfo(PROSMENUITEMINFO ItemInfo) } } -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; -} - -/*********************************************************************** - * MenuGetAllRosMenuItemInfo - * - * Get full information about all menu items - */ -static INT FASTCALL -MenuGetAllRosMenuItemInfo(HMENU Menu, PROSMENUITEMINFO *ItemInfo) -{ - DWORD BufSize; - PMENU pMenu; - - 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 IntBuildMenuItemList(pMenu, (PVOID)*ItemInfo, BufSize); -} - -/*********************************************************************** - * MenuCleanupAllRosMenuItemInfo - * - * Cleanup after use of MenuGetAllRosMenuItemInfo - */ -static VOID FASTCALL -MenuCleanupAllRosMenuItemInfo(PROSMENUITEMINFO ItemInfo) -{ - HeapFree(GetProcessHeap(), 0, ItemInfo); -} - /*********************************************************************** * MenuInitSysMenuPopup * @@ -718,22 +589,27 @@ void FASTCALL MenuInitSysMenuPopup(HMENU hmenu, DWORD style, DWORD clsStyle, LON * PROSMENUINFO MenuInfo) * *****************************************************************************/ -static UINT MenuGetStartOfNextColumn( - PROSMENUINFO MenuInfo) + +static UINT MENU_GetStartOfNextColumn( + HMENU hMenu ) { - PROSMENUITEMINFO MenuItems; + MENU *menu = MENU_GetMenu(hMenu); + PITEM pItem; UINT i; - i = MenuInfo->iItem; - if ( i == NO_SELECTED_ITEM ) - return i; + if(!menu) + return NO_SELECTED_ITEM; - if (MenuGetAllRosMenuItemInfo(MenuInfo->Self, &MenuItems) <= 0) - return NO_SELECTED_ITEM; + i = menu->iItem + 1; + if( i == NO_SELECTED_ITEM ) + return i; - for (i++ ; i < MenuInfo->cItems; i++) - if (0 != (MenuItems[i].fType & (MF_MENUBREAK | MF_MENUBARBREAK))) - return i; + pItem = menu->rgItems ? DesktopPtrToUser(menu->rgItems) : NULL; + if (!pItem) return NO_SELECTED_ITEM; + for( ; i < menu->cItems; ++i ) { + if (pItem[i].fType & (MF_MENUBREAK | MF_MENUBARBREAK)) + return i; + } return NO_SELECTED_ITEM; } @@ -744,38 +620,36 @@ static UINT MenuGetStartOfNextColumn( * PROSMENUINFO MenuInfo) * *****************************************************************************/ - -static UINT FASTCALL MenuGetStartOfPrevColumn( - PROSMENUINFO MenuInfo) +static UINT MENU_GetStartOfPrevColumn( + HMENU hMenu ) { - PROSMENUITEMINFO MenuItems; - UINT i; + MENU *menu = MENU_GetMenu(hMenu); + UINT i; + PITEM pItem; - if (!MenuInfo->iItem || MenuInfo->iItem == NO_SELECTED_ITEM) - return NO_SELECTED_ITEM; + if( !menu ) + return NO_SELECTED_ITEM; - if (MenuGetAllRosMenuItemInfo(MenuInfo->Self, &MenuItems) <= 0) - return NO_SELECTED_ITEM; + if( menu->iItem == 0 || menu->iItem == NO_SELECTED_ITEM ) + return NO_SELECTED_ITEM; + + pItem = menu->rgItems ? DesktopPtrToUser(menu->rgItems) : NULL; + if (!pItem) return NO_SELECTED_ITEM; /* Find the start of the column */ - for (i = MenuInfo->iItem; - 0 != i && 0 == (MenuItems[i].fType & (MF_MENUBREAK | MF_MENUBARBREAK)); - --i) - { - ; /* empty */ - } - if (i == 0) - { - MenuCleanupAllRosMenuItemInfo(MenuItems); - return NO_SELECTED_ITEM; - } + for(i = menu->iItem; i != 0 && + !(pItem[i].fType & (MF_MENUBREAK | MF_MENUBARBREAK)); + --i); /* empty */ - for (--i; 0 != i; --i) - if (MenuItems[i].fType & (MF_MENUBREAK | MF_MENUBARBREAK)) - break; + if(i == 0) + return NO_SELECTED_ITEM; + + for(--i; i != 0; --i) { + if (pItem[i].fType & (MF_MENUBREAK | MF_MENUBARBREAK)) + break; + } - MenuCleanupAllRosMenuItemInfo(MenuItems); TRACE("ret %d.\n", i ); return i; @@ -870,7 +744,7 @@ static UINT FASTCALL MenuFindSubMenu(HMENU *hmenu, HMENU hSubTarget ) 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++) + for (i = 0; i < menu->cItems; i++, item++) { if (!item->spSubMenu) continue; @@ -987,58 +861,48 @@ MenuDrawPopupGlyph(HDC dc, LPRECT r, INT_PTR popupMagic, BOOL inactive, BOOL hil * Find the menu item selected by a key press. * Return item id, -1 if none, -2 if we should close the menu. */ -static UINT FASTCALL MenuFindItemByKey(HWND WndOwner, PROSMENUINFO MenuInfo, +static UINT FASTCALL MENU_FindItemByKey(HWND WndOwner, HMENU hmenu, WCHAR Key, BOOL ForceMenuChar) { - ROSMENUINFO SysMenuInfo; - PROSMENUITEMINFO Items, ItemInfo; LRESULT MenuChar; - UINT i; WORD Flags = 0; - TRACE("\tlooking for '%c' (0x%02x) in [%p]\n", (char) Key, Key, MenuInfo); + TRACE("\tlooking for '%c' (0x%02x) in [%p]\n", (char)Key, Key, hmenu ); - if (NULL == MenuInfo || ! IsMenu(MenuInfo->Self)) - { - if (MenuGetRosMenuInfo(&SysMenuInfo, GetSystemMenu(WndOwner, FALSE))) - { - MenuInfo = &SysMenuInfo; - } - else - { - MenuInfo = NULL; - } - } + if (!IsMenu( hmenu )) hmenu = GetSubMenu( get_win_sys_menu(WndOwner), 0); + if (hmenu) + { + MENU *menu = MENU_GetMenu( hmenu ); + ITEM *item = menu->rgItems ? DesktopPtrToUser(menu->rgItems) : NULL; - if (NULL != MenuInfo) - { - if (MenuGetAllRosMenuItemInfo(MenuInfo->Self, &Items) <= 0) - { - return -1; - } - if ( !ForceMenuChar ) - { - ItemInfo = Items; - for (i = 0; i < MenuInfo->cItems; i++, ItemInfo++) - { - if ((ItemInfo->lpstr) && NULL != ItemInfo->dwTypeData) - { - WCHAR *p = (WCHAR *) ItemInfo->dwTypeData - 2; - do - { - p = strchrW (p + 2, '&'); - } - while (p != NULL && p [1] == '&'); - if (p && (toupperW(p[1]) == toupperW(Key))) return i; - } - } - } + if( !ForceMenuChar ) + { + UINT i; + BOOL cjk = GetSystemMetrics( SM_DBCSENABLED ); + + for (i = 0; i < menu->cItems; i++, item++) + { + LPWSTR text = item->Xlpstr ? DesktopPtrToUser(item->Xlpstr) : NULL; + if( text) + { + const WCHAR *p = text - 2; + do + { + const WCHAR *q = p + 2; + p = strchrW (q, '&'); + if (!p && cjk) p = strchrW (q, '\036'); /* Japanese Win16 */ + } + while (p != NULL && p [1] == '&'); + if (p && (toupperW(p[1]) == toupperW(Key))) return i; + } + } + } - Flags |= MenuInfo->fFlags & MNF_POPUP ? MF_POPUP : 0; - Flags |= MenuInfo->fFlags & MNF_SYSDESKMN ? MF_SYSMENU : 0; + Flags |= menu->fFlags & MNF_POPUP ? MF_POPUP : 0; + Flags |= menu->fFlags & MNF_SYSDESKMN ? MF_SYSMENU : 0; MenuChar = SendMessageW(WndOwner, WM_MENUCHAR, - MAKEWPARAM(Key, Flags), (LPARAM) MenuInfo->Self); + MAKEWPARAM(Key, Flags), (LPARAM) hmenu); if (HIWORD(MenuChar) == MNC_EXECUTE) return LOWORD(MenuChar); if (HIWORD(MenuChar) == MNC_CLOSE) return (UINT)(-2); } @@ -1530,7 +1394,7 @@ static void FASTCALL MenuMenuBarCalcSize( HDC hdc, LPRECT lprect, if ((lprect == NULL) || (MenuInfo == NULL)) return; if (MenuInfo->cItems == 0) return; - TRACE("left=%ld top=%ld right=%ld bottom=%ld\n", lprect->left, lprect->top, lprect->right, lprect->bottom); + TRACE("lprect %p %s\n", lprect, wine_dbgstr_rect( lprect)); MenuInfo->cxMenu = lprect->right - lprect->left; MenuInfo->cyMenu = 0; maxY = lprect->top + 1; @@ -1689,7 +1553,6 @@ MENU_DrawScrollArrows(PROSMENUINFO lppop, HDC hdc) DeleteDC(hdcMem); } - /*********************************************************************** * MenuDrawMenuItem * @@ -1702,7 +1565,7 @@ static void FASTCALL MenuDrawMenuItem(HWND hWnd, PROSMENUINFO MenuInfo, HWND Wnd PWCHAR Text; BOOL flat_menu = FALSE; int bkgnd; - PWND Wnd = ValidateHwnd(hWnd); + PWND Wnd = ValidateHwndNoErr(hWnd); if (!Wnd) return; @@ -1744,6 +1607,7 @@ static void FASTCALL MenuDrawMenuItem(HWND hWnd, PROSMENUINFO MenuInfo, HWND Wnd SetBkColor( hdc, GetSysColor( bkgnd ) ); } + TRACE("rect=%s\n", wine_dbgstr_rect( &lpitem->Rect)); rect = lpitem->Rect; MENU_AdjustMenuItemRect(MenuInfo, &rect); @@ -1949,7 +1813,7 @@ static void FASTCALL MenuDrawMenuItem(HWND hWnd, PROSMENUINFO MenuInfo, HWND Wnd DT_LEFT | DT_VCENTER | DT_SINGLELINE; if((MenuInfo->dwStyle & MNS_CHECKORBMP)) - rect.left += max(0, MenuInfo->cxTextAlign - GetSystemMetrics(SM_CXMENUCHECK)); + rect.left += max(0, (int)(MenuInfo->cxTextAlign - GetSystemMetrics(SM_CXMENUCHECK))); else rect.left += MenuInfo->cxTextAlign; @@ -2053,6 +1917,7 @@ static void FASTCALL MenuDrawPopupMenu(HWND hwnd, HDC hdc, HMENU hmenu ) DrawEdge (hdc, &rect, EDGE_RAISED, BF_RECT); /* draw menu items */ + //TRACE("hmenu %p Style %08x\n", hmenu, menu->dwStyle); if (MenuGetRosMenuInfo(&MenuInfo, hmenu) && MenuInfo.cItems) { UINT u; @@ -2115,6 +1980,44 @@ UINT MenuDrawMenuBar( HDC hDC, LPRECT lprect, HWND hwnd, return DrawMenuBarTemp(hwnd, hDC, lprect, hMenu, NULL); } +/*********************************************************************** + * MENU_InitPopup + * + * Popup menu initialization before WM_ENTERMENULOOP. + */ +static BOOL MENU_InitPopup( HWND hwndOwner, HMENU hmenu, UINT flags ) +{ + MENU *menu; + DWORD ex_style = 0; + ROSMENUINFO MenuInfo; + + 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; + } + MenuGetRosMenuInfo(&MenuInfo, menu->head.h); + //menu->hwndOwner = hwndOwner; + MenuInfo.spwndNotify = ValidateHwndNoErr( hwndOwner ); + + if (flags & TPM_LAYOUTRTL) + ex_style = WS_EX_LAYOUTRTL; + + /* NOTE: In Windows, top menu popup is not owned. */ + //menu->hWnd = CreateWindowExW( ex_style, WC_MENU, NULL, + MenuInfo.Wnd = CreateWindowExW( ex_style, WC_MENU, NULL, + WS_POPUP, 0, 0, 0, 0, + hwndOwner, 0, (HINSTANCE)GetWindowLongPtrW(hwndOwner, GWLP_HINSTANCE), + (LPVOID)hmenu ); + MenuSetRosMenuInfo(&MenuInfo); + if( !menu->hWnd ) return FALSE; + return TRUE; +} /*********************************************************************** * MenuShowPopup @@ -2130,7 +2033,6 @@ static BOOL FASTCALL MenuShowPopup(HWND hwndOwner, HMENU hmenu, UINT id, UINT fl POINT pt; HMONITOR monitor; MONITORINFO info; - DWORD ex_style = 0; TRACE("owner=%p hmenu=%p id=0x%04x x=0x%04x y=0x%04x xa=0x%04x ya=0x%04x\n", hwndOwner, hmenu, id, x, y, xanchor, yanchor); @@ -2149,15 +2051,9 @@ static BOOL FASTCALL MenuShowPopup(HWND hwndOwner, HMENU hmenu, UINT id, UINT fl MenuInfo.iItem = NO_SELECTED_ITEM; } - /* store the owner for DrawItem */ - if (!IsWindow(hwndOwner)) - { - SetLastError( ERROR_INVALID_WINDOW_HANDLE ); - return FALSE; - } - MenuInfo.spwndNotify = ValidateHwndNoErr(hwndOwner); + //menu->dwArrowsOn = 0; + MenuInfo.dwArrowsOn = 0; MenuSetRosMenuInfo(&MenuInfo); - MenuPopupMenuCalcSize(&MenuInfo, hwndOwner); /* adjust popup menu pos so that it fits within the desktop */ @@ -2173,10 +2069,8 @@ static BOOL FASTCALL MenuShowPopup(HWND hwndOwner, HMENU hmenu, UINT id, UINT fl GetMonitorInfoW( monitor, &info ); if (flags & TPM_LAYOUTRTL) - { - ex_style = WS_EX_LAYOUTRTL; flags ^= TPM_RIGHTALIGN; - } + if( flags & TPM_RIGHTALIGN ) x -= width; if( flags & TPM_CENTERALIGN ) x -= width / 2; @@ -2203,24 +2097,18 @@ static BOOL FASTCALL MenuShowPopup(HWND hwndOwner, HMENU hmenu, UINT id, UINT fl } if( y < info.rcMonitor.top ) y = info.rcMonitor.top; - /* NOTE: In Windows, top menu popup is not owned. */ - MenuInfo.Wnd = CreateWindowExW( ex_style, WC_MENU, NULL, - WS_POPUP, x, y, width, height, - hwndOwner, 0, (HINSTANCE) GetWindowLongPtrW(hwndOwner, GWLP_HINSTANCE), - (LPVOID) MenuInfo.Self); - if ( !MenuInfo.Wnd || ! MenuSetRosMenuInfo(&MenuInfo)) return FALSE; if (!top_popup) { top_popup = MenuInfo.Wnd; top_popup_hmenu = hmenu; } - - IntNotifyWinEvent(EVENT_SYSTEM_MENUPOPUPSTART, MenuInfo.Wnd, OBJID_CLIENT, CHILDID_SELF, 0); - /* Display the window */ - SetWindowPos( MenuInfo.Wnd, HWND_TOPMOST, 0, 0, 0, 0, - SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE); + SetWindowPos( MenuInfo.Wnd, HWND_TOPMOST, x, y, width, height, + SWP_SHOWWINDOW | SWP_NOACTIVATE); UpdateWindow( MenuInfo.Wnd ); + + IntNotifyWinEvent(EVENT_SYSTEM_MENUPOPUPSTART, MenuInfo.Wnd, OBJID_CLIENT, CHILDID_SELF, 0); + return TRUE; } @@ -2426,7 +2314,7 @@ PopupMenuWndProcW(HWND Wnd, UINT Message, WPARAM wParam, LPARAM lParam) PWND pWnd; PPOPUPMENU pPopupMenu; - pWnd = ValidateHwnd(Wnd); + pWnd = ValidateHwndNoErr(Wnd); if (pWnd) { if (!pWnd->fnid) @@ -2609,6 +2497,12 @@ PopupMenuWndProcW(HWND Wnd, UINT Message, WPARAM wParam, LPARAM lParam) } break; +#ifdef __REACTOS__ + case WM_NCDESTROY: + NtUserSetWindowFNID(Wnd, FNID_DESTROY); + break; +#endif + case WM_SHOWWINDOW: if (0 != wParam) { @@ -2721,7 +2615,6 @@ static LPCSTR MENU_ParseResource( LPCSTR res, HMENU hMenu) return res; } - /********************************************************************** * MENUEX_ParseResource * @@ -2784,88 +2677,6 @@ static LPCSTR MENUEX_ParseResource(LPCSTR res, HMENU hMenu) return res; } -NTSTATUS WINAPI -User32LoadSysMenuTemplateForKernel(PVOID Arguments, ULONG ArgumentLength) -{ - HMENU hmenu = LoadMenuW(User32Instance, L"SYSMENU"); - LRESULT Result = (LRESULT)hmenu; - MENUINFO menuinfo = {0}; - MENUITEMINFOW info = {0}; - - // removing space for checkboxes from menu - menuinfo.cbSize = sizeof(menuinfo); - menuinfo.fMask = MIM_STYLE; - GetMenuInfo(hmenu, &menuinfo); - menuinfo.dwStyle |= MNS_CHECKORBMP; // test_menu_bmp_and_string MNS_CHECKORBMP - SetMenuInfo(hmenu, &menuinfo); - - // adding bitmaps to menu items - info.cbSize = sizeof(info); - info.fMask |= MIIM_BITMAP; - info.hbmpItem = HBMMENU_POPUP_MINIMIZE; - SetMenuItemInfoW(hmenu, SC_MINIMIZE, FALSE, &info); - info.hbmpItem = HBMMENU_POPUP_RESTORE; - SetMenuItemInfoW(hmenu, SC_RESTORE, FALSE, &info); - info.hbmpItem = HBMMENU_POPUP_MAXIMIZE; - SetMenuItemInfoW(hmenu, SC_MAXIMIZE, FALSE, &info); - info.hbmpItem = HBMMENU_POPUP_CLOSE; - SetMenuItemInfoW(hmenu, SC_CLOSE, FALSE, &info); - - return(ZwCallbackReturn(&Result, sizeof(LRESULT), STATUS_SUCCESS)); -} - - -BOOL -MenuInit(VOID) -{ - NONCLIENTMETRICSW ncm; - - /* get the menu font */ - if(!hMenuFont || !hMenuFontBold) - { - ncm.cbSize = sizeof(ncm); - if(!SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0)) - { - ERR("MenuInit(): SystemParametersInfoW(SPI_GETNONCLIENTMETRICS) failed!\n"); - return FALSE; - } - - hMenuFont = CreateFontIndirectW(&ncm.lfMenuFont); - if(hMenuFont == NULL) - { - ERR("MenuInit(): CreateFontIndirectW(hMenuFont) failed!\n"); - return FALSE; - } - - ncm.lfMenuFont.lfWeight = max(ncm.lfMenuFont.lfWeight + 300, 1000); - hMenuFontBold = CreateFontIndirectW(&ncm.lfMenuFont); - if(hMenuFontBold == NULL) - { - ERR("MenuInit(): CreateFontIndirectW(hMenuFontBold) failed!\n"); - DeleteObject(hMenuFont); - hMenuFont = NULL; - return FALSE; - } - } - - return TRUE; -} - -VOID -MenuCleanup(VOID) -{ - if (hMenuFont) - { - DeleteObject(hMenuFont); - hMenuFont = NULL; - } - - if (hMenuFontBold) - { - DeleteObject(hMenuFontBold); - hMenuFontBold = NULL; - } -} /*********************************************************************** * DrawMenuBarTemp (USER32.@) @@ -2943,36 +2754,8 @@ DrawMenuBarTemp(HWND Wnd, HDC DC, LPRECT Rect, HMENU Menu, HFONT Font) 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 * @@ -2982,7 +2765,6 @@ static BOOL MENU_InitPopup( HWND hwndOwner, HMENU hmenu, UINT flags ) static HMENU FASTCALL MenuShowSubPopup(HWND WndOwner, PROSMENUINFO MenuInfo, BOOL SelectFirst, UINT Flags) { - extern void FASTCALL NcGetSysPopupPos(HWND Wnd, RECT *Rect); RECT Rect; ROSMENUITEMINFO ItemInfo; ROSMENUINFO SubMenuInfo; @@ -3100,7 +2882,7 @@ MenuShowSubPopup(HWND WndOwner, PROSMENUINFO MenuInfo, BOOL SelectFirst, UINT Fl /* use default alignment for submenus */ Flags &= ~(TPM_CENTERALIGN | TPM_RIGHTALIGN | TPM_VCENTERALIGN | TPM_BOTTOMALIGN); - //MENU_InitPopup( WndOwner, ItemInfo.hSubMenu, Flags ); + MENU_InitPopup( WndOwner, ItemInfo.hSubMenu, Flags ); MenuShowPopup(WndOwner, ItemInfo.hSubMenu, MenuInfo->iItem, Flags, Rect.left, Rect.top, Rect.right, Rect.bottom ); @@ -3124,11 +2906,10 @@ MenuShowSubPopup(HWND WndOwner, PROSMENUINFO MenuInfo, BOOL SelectFirst, UINT Fl */ void MENU_EndMenu( HWND hwnd ) { - ROSMENUINFO MenuInfo; - BOOL Ret = FALSE; - if (top_popup_hmenu) - Ret = MenuGetRosMenuInfo(&MenuInfo, top_popup_hmenu); - if (Ret && hwnd == (MenuInfo.spwndNotify ? MenuInfo.spwndNotify->head.h : NULL)) EndMenu(); + MENU *menu; + menu = top_popup_hmenu ? MENU_GetMenu( top_popup_hmenu ) : NULL; + if (menu && ( hwnd == menu->hWnd || hwnd == (menu->spwndNotify ? menu->spwndNotify->head.h : NULL)) ) + EndMenu(); } /*********************************************************************** @@ -3281,7 +3062,7 @@ MenuExecFocusedItem(MTRACKER *Mt, PROSMENUINFO MenuInfo, UINT Flags) * Return TRUE if we can go on with menu tracking. */ static BOOL FASTCALL -MenuButtonDown(MTRACKER* Mt, HMENU PtMenu, UINT Flags) +MENU_ButtonDown(MTRACKER* Mt, HMENU PtMenu, UINT Flags) { int Index; ROSMENUINFO MenuInfo; @@ -3344,7 +3125,7 @@ MenuButtonDown(MTRACKER* Mt, HMENU PtMenu, UINT Flags) * */ static INT FASTCALL -MenuButtonUp(MTRACKER *Mt, HMENU PtMenu, UINT Flags) +MENU_ButtonUp(MTRACKER *Mt, HMENU PtMenu, UINT Flags) { INT Id; ROSMENUINFO MenuInfo; @@ -3399,56 +3180,41 @@ MenuButtonUp(MTRACKER *Mt, HMENU PtMenu, UINT Flags) * Walks menu chain trying to find a menu pt maps to. */ static HMENU FASTCALL -MenuPtMenu(HMENU Menu, POINT Pt) +MENU_PtMenu(HMENU hMenu, POINT pt) { - extern LRESULT DefWndNCHitTest(HWND hWnd, POINT Point); - ROSMENUINFO MenuInfo; - ROSMENUITEMINFO ItemInfo; - HMENU Ret = NULL; - INT Ht; + MENU *menu; + PITEM pItem; + HMENU ret = NULL; - if (! MenuGetRosMenuInfo(&MenuInfo, Menu)) - { - return NULL; - } + menu = MENU_GetMenu( hMenu ); + if (!menu) return NULL; /* try subpopup first (if any) */ - if (NO_SELECTED_ITEM != MenuInfo.iItem) - { - MenuInitRosMenuItemInfo(&ItemInfo); - if (MenuGetRosMenuItemInfo(MenuInfo.Self, MenuInfo.iItem, &ItemInfo) && - 0 != (ItemInfo.hSubMenu) && - 0 != (ItemInfo.fState & MF_MOUSESELECT)) - { - Ret = MenuPtMenu(ItemInfo.hSubMenu, Pt); - if (NULL != Ret) - { - MenuCleanupRosMenuItemInfo(&ItemInfo); - return Ret; - } - } - MenuCleanupRosMenuItemInfo(&ItemInfo); - } + if (menu->iItem != NO_SELECTED_ITEM) + { + pItem = menu->rgItems ? DesktopPtrToUser(menu->rgItems) : NULL; + if ( pItem ) pItem = &pItem[menu->iItem]; + if ( pItem && pItem->spSubMenu && pItem->fState & MF_MOUSESELECT) + { + PMENU pSubMenu = DesktopPtrToUser(pItem->spSubMenu); + ret = MENU_PtMenu( UserHMGetHandle(pSubMenu), pt); + } + } /* check the current window (avoiding WM_HITTEST) */ - Ht = DefWndNCHitTest(MenuInfo.Wnd, Pt); - if (0 != (MenuInfo.fFlags & MNF_POPUP)) - { - if (HTNOWHERE != Ht && HTERROR != Ht) - { - Ret = Menu; - } - } - else if (HTSYSMENU == Ht) - { - Ret = NtUserGetSystemMenu(MenuInfo.Wnd, FALSE); - } - else if (HTMENU == Ht) - { - Ret = GetMenu(MenuInfo.Wnd); - } - - return Ret; + if (!ret) + { + INT ht = DefWndNCHitTest(menu->hWnd, pt); + if ( menu->fFlags & MNF_POPUP ) + { + if (ht != HTNOWHERE && ht != HTERROR) ret = hMenu; + } + else if (ht == HTSYSMENU) + ret = NtUserGetSystemMenu(menu->hWnd, FALSE); + else if (ht == HTMENU) + ret = GetMenu( menu->hWnd ); + } + return ret; } /*********************************************************************** @@ -3513,32 +3279,25 @@ MenuMouseMove(MTRACKER *Mt, HMENU PtMenu, UINT Flags) * * Return the handle of the selected sub-popup menu (if any). */ -static HMENU FASTCALL -MenuGetSubPopup(HMENU Menu) +static +HMENU MENU_GetSubPopup( HMENU hmenu ) { - ROSMENUINFO MenuInfo; - ROSMENUITEMINFO ItemInfo; + MENU *menu; + ITEM *item; - if (! MenuGetRosMenuInfo(&MenuInfo, Menu) - || NO_SELECTED_ITEM == MenuInfo.iItem) - { - return NULL; - } + menu = MENU_GetMenu( hmenu ); - MenuInitRosMenuItemInfo(&ItemInfo); - if (! MenuGetRosMenuItemInfo(MenuInfo.Self, MenuInfo.iItem, &ItemInfo)) - { - MenuCleanupRosMenuItemInfo(&ItemInfo); - return NULL; - } - if (0 != (ItemInfo.hSubMenu) && 0 != (ItemInfo.fState & MF_MOUSESELECT)) + if ((!menu) || (menu->iItem == NO_SELECTED_ITEM)) return 0; + + //item = &menu->rgItems[menu->iItem]; + item = menu->rgItems ? DesktopPtrToUser(menu->rgItems) : NULL; + if (item) item = &item[menu->iItem]; + if (item && (item->spSubMenu) && (item->fState & MF_MOUSESELECT)) { - MenuCleanupRosMenuItemInfo(&ItemInfo); - return ItemInfo.hSubMenu; + PMENU pSubMenu = DesktopPtrToUser(item->spSubMenu); + return UserHMGetHandle(pSubMenu); } - - MenuCleanupRosMenuItemInfo(&ItemInfo); - return NULL; + return 0; } /*********************************************************************** @@ -3726,7 +3485,7 @@ MenuKeyEscape(MTRACKER *Mt, UINT Flags) while (MenuTmp != Mt->CurrentMenu) { MenuPrev = MenuTmp; - MenuTmp = MenuGetSubPopup(MenuPrev); + MenuTmp = MENU_GetSubPopup(MenuPrev); } if (MenuGetRosMenuInfo(&MenuInfo, MenuPrev)) @@ -3757,13 +3516,8 @@ MenuKeyLeft(MTRACKER* Mt, UINT Flags) MenuPrev = MenuTmp = Mt->TopMenu; - if (! MenuGetRosMenuInfo(&MenuInfo, Mt->CurrentMenu)) - { - return; - } - /* Try to move 1 column left (if possible) */ - if ( (PrevCol = MenuGetStartOfPrevColumn(&MenuInfo)) != NO_SELECTED_ITEM) + if ( (PrevCol = MENU_GetStartOfPrevColumn(Mt->CurrentMenu)) != NO_SELECTED_ITEM) { if (MenuGetRosMenuInfo(&MenuInfo, Mt->CurrentMenu)) { @@ -3776,7 +3530,7 @@ MenuKeyLeft(MTRACKER* Mt, UINT Flags) while (MenuTmp != Mt->CurrentMenu) { MenuPrev = MenuTmp; - MenuTmp = MenuGetSubPopup(MenuPrev); + MenuTmp = MENU_GetSubPopup(MenuPrev); } if (! MenuGetRosMenuInfo(&PrevMenuInfo, MenuPrev)) @@ -3844,13 +3598,8 @@ static void FASTCALL MenuKeyRight(MTRACKER *Mt, UINT Flags) if (hmenutmp != Mt->CurrentMenu) return; } - if (! MenuGetRosMenuInfo(&CurrentMenuInfo, Mt->CurrentMenu)) - { - return; - } - /* Check to see if there's another column */ - if ( (NextCol = MenuGetStartOfNextColumn(&CurrentMenuInfo)) != NO_SELECTED_ITEM) + if ( (NextCol = MENU_GetStartOfNextColumn(Mt->CurrentMenu)) != NO_SELECTED_ITEM) { TRACE("Going to %d.\n", NextCol); if (MenuGetRosMenuInfo(&MenuInfo, Mt->CurrentMenu)) @@ -3899,6 +3648,7 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y, MSG msg; ROSMENUINFO MenuInfo; ROSMENUITEMINFO ItemInfo; + PMENU menu; BOOL fRemove; INT executedMenuId = -1; MTRACKER mt; @@ -3918,12 +3668,10 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y, if (!IsMenu(hmenu)) { - WARN("Invalid menu handle %p\n", hmenu); - SetLastError( ERROR_INVALID_MENU_HANDLE ); + WARN("Invalid menu handle %p\n", hmenu); // Error already set in IsMenu. return FALSE; } - fEndMenu = FALSE; if (! MenuGetRosMenuInfo(&MenuInfo, hmenu)) { return FALSE; @@ -3932,7 +3680,7 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y, if (wFlags & TPM_BUTTONDOWN) { /* Get the result in order to start the tracking or not */ - fRemove = MenuButtonDown( &mt, hmenu, wFlags ); + fRemove = MENU_ButtonDown( &mt, hmenu, wFlags ); fEndMenu = !fRemove; } @@ -3943,10 +3691,10 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y, NtUserxSetGUIThreadHandle(MSQ_STATE_MENUOWNER, capture_win); // 1 SetCapture(capture_win); // 2 - while (! fEndMenu) + while (!fEndMenu) { BOOL ErrorExit = FALSE; - PMENU menu = ValidateHandle(mt.CurrentMenu, TYPE_MENU); + menu = MENU_GetMenu( mt.CurrentMenu ); if (!menu) /* sometimes happens if I do a window manager close */ break; @@ -3964,7 +3712,7 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y, else { /* ReactOS Check */ - if (!ValidateHwnd(mt.OwnerWnd) || !ValidateHwnd(MenuInfo.Wnd)) + if (!ValidateHwndNoErr(mt.OwnerWnd) || !ValidateHwndNoErr(MenuInfo.Wnd)) { ErrorExit = TRUE; // Do not wait on dead windows, now test_capture_4 works. break; @@ -4012,14 +3760,13 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y, mt.Pt.y = (short)HIWORD(msg.lParam); /* Find a menu for this mouse event */ - hmenu = MenuPtMenu(mt.TopMenu, mt.Pt); + hmenu = MENU_PtMenu(mt.TopMenu, mt.Pt); switch(msg.message) { /* no WM_NC... messages in captured state */ case WM_RBUTTONDBLCLK: - ERR("WM_RBUTTONDBLCLK\n"); case WM_RBUTTONDOWN: if (!(wFlags & TPM_RIGHTBUTTON)) break; /* fall through */ @@ -4027,7 +3774,7 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y, case WM_LBUTTONDOWN: /* If the message belongs to the menu, removes it from the queue */ /* Else, end menu tracking */ - fRemove = MenuButtonDown(&mt, hmenu, wFlags); + fRemove = MENU_ButtonDown(&mt, hmenu, wFlags); fEndMenu = !fRemove; break; @@ -4038,7 +3785,7 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y, /* Check if a menu was selected by the mouse */ if (hmenu) { - executedMenuId = MenuButtonUp( &mt, hmenu, wFlags); + executedMenuId = MENU_ButtonUp( &mt, hmenu, wFlags); TRACE("executedMenuId %d\n", executedMenuId); /* End the loop if executedMenuId is an item ID */ @@ -4080,10 +3827,8 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y, case VK_END: if (MenuGetRosMenuInfo(&MenuInfo, mt.CurrentMenu)) { - MenuSelectItem(mt.OwnerWnd, &MenuInfo, - NO_SELECTED_ITEM, FALSE, 0 ); - MenuMoveSelection(mt.OwnerWnd, &MenuInfo, - VK_HOME == msg.wParam ? ITEM_NEXT : ITEM_PREV); + MenuSelectItem(mt.OwnerWnd, &MenuInfo, NO_SELECTED_ITEM, FALSE, 0 ); + MenuMoveSelection(mt.OwnerWnd, &MenuInfo, VK_HOME == msg.wParam ? ITEM_NEXT : ITEM_PREV); } break; @@ -4097,8 +3842,7 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y, mt.CurrentMenu = MenuShowSubPopup(mt.OwnerWnd, &MenuInfo, TRUE, wFlags); } else /* otherwise try to move selection */ - MenuMoveSelection(mt.OwnerWnd, &MenuInfo, - (msg.wParam == VK_UP)? ITEM_PREV : ITEM_NEXT ); + MenuMoveSelection(mt.OwnerWnd, &MenuInfo, (msg.wParam == VK_UP)? ITEM_PREV : ITEM_NEXT ); } break; @@ -4168,14 +3912,12 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y, /* We will find a better way real soon... */ if (msg.wParam < 32) break; - pos = MenuFindItemByKey(mt.OwnerWnd, &MenuInfo, - LOWORD(msg.wParam), FALSE); + pos = MENU_FindItemByKey(mt.OwnerWnd, mt.CurrentMenu, LOWORD(msg.wParam), FALSE); if (pos == (UINT)-2) fEndMenu = TRUE; else if (pos == (UINT)-1) MessageBeep(0); else { - MenuSelectItem(mt.OwnerWnd, &MenuInfo, pos, - TRUE, 0); + MenuSelectItem(mt.OwnerWnd, &MenuInfo, pos, TRUE, 0); executedMenuId = MenuExecFocusedItem(&mt, &MenuInfo, wFlags); fEndMenu = (executedMenuId != -2); } @@ -4259,11 +4001,19 @@ static BOOL FASTCALL MenuInitTracking(HWND hWnd, HMENU hMenu, BOOL bPopup, UINT * It also enables menus to be displayed in more than one window, * but there are some bugs left that need to be fixed in this case. */ - if (MenuGetRosMenuInfo(&MenuInfo, hMenu)) + if (!bPopup && (MenuGetRosMenuInfo(&MenuInfo, hMenu))) { MenuInfo.Wnd = hWnd; MenuSetRosMenuInfo(&MenuInfo); } + //if (!bPopup) menu->hWnd = hWnd; + if (!top_popup) + { + top_popup = MenuInfo.Wnd;//menu->hWnd; + top_popup_hmenu = hMenu; + } + + fEndMenu = FALSE; /* Send WM_ENTERMENULOOP and WM_INITMENU message only if TPM_NONOTIFY flag is not specified */ if (!(wFlags & TPM_NONOTIFY)) @@ -4294,6 +4044,7 @@ static BOOL FASTCALL MenuInitTracking(HWND hWnd, HMENU hMenu, BOOL bPopup, UINT CHILDID_SELF, 0); return TRUE; } + /*********************************************************************** * MenuExitTracking */ @@ -4337,7 +4088,6 @@ VOID MenuTrackMouseMenuBar( HWND hWnd, ULONG ht, POINT pt) } } - /*********************************************************************** * MenuTrackKbdMenuBar * @@ -4373,6 +4123,9 @@ VOID MenuTrackKbdMenuBar(HWND hwnd, UINT wParam, WCHAR wChar) MenuInitTracking( hwnd, hTrackMenu, FALSE, wFlags ); + /* fetch the window menu again, it may have changed */ + hTrackMenu = (wParam & HTSYSMENU) ? get_win_sys_menu( hwnd ) : GetMenu( hwnd ); + if (! MenuGetRosMenuInfo(&MenuInfo, hTrackMenu)) { goto track_menu; @@ -4380,7 +4133,7 @@ VOID MenuTrackKbdMenuBar(HWND hwnd, UINT wParam, WCHAR wChar) if( wChar && wChar != ' ' ) { - uItem = MenuFindItemByKey( hwnd, &MenuInfo, wChar, (wParam & HTSYSMENU) ); + uItem = MENU_FindItemByKey( hwnd, hTrackMenu, wChar, (wParam & HTSYSMENU) ); if ( uItem >= (UINT)(-2) ) { if( uItem == (UINT)(-1) ) MessageBeep(0); @@ -4408,42 +4161,59 @@ track_menu: /********************************************************************** * TrackPopupMenuEx (USER32.@) */ -BOOL WINAPI TrackPopupMenuEx( HMENU Menu, UINT Flags, int x, int y, - HWND Wnd, LPTPMPARAMS Tpm) +BOOL WINAPI TrackPopupMenuEx( HMENU hMenu, UINT wFlags, int x, int y, + HWND hWnd, LPTPMPARAMS lpTpm) { BOOL ret = FALSE; - ROSMENUINFO MenuInfo; + MENU *menu; - if (!IsMenu(Menu)) + TRACE("hmenu %p flags %04x (%d,%d) hwnd %p lpTpm %p rect %s\n", + hMenu, wFlags, x, y, hWnd, lpTpm, + lpTpm ? wine_dbgstr_rect( &lpTpm->rcExclude) : "-" ); + + /* Parameter check */ + /* FIXME: this check is performed several times, here and in the called + functions. That could be optimized */ + if (!(menu = MENU_GetMenu( hMenu ))) { SetLastError( ERROR_INVALID_MENU_HANDLE ); return FALSE; } - /* ReactOS Check */ - if (!ValidateHwnd(Wnd)) - { - /* invalid window see wine menu.c test_menu_trackpopupmenu line 3146 */ - return FALSE; - } - - MenuGetRosMenuInfo(&MenuInfo, Menu); - if (IsWindow(MenuInfo.Wnd)) + if (IsWindow(menu->hWnd)) { SetLastError( ERROR_POPUP_ALREADY_ACTIVE ); return FALSE; } - MenuInitTracking(Wnd, Menu, TRUE, Flags); + if (MENU_InitPopup( hWnd, hMenu, wFlags )) + { + MenuInitTracking(hWnd, hMenu, TRUE, wFlags); + + /* Send WM_INITMENUPOPUP message only if TPM_NONOTIFY flag is not specified */ + if (!(wFlags & TPM_NONOTIFY)) + SendMessageW(hWnd, WM_INITMENUPOPUP, (WPARAM) hMenu, 0); - /* Send WM_INITMENUPOPUP message only if TPM_NONOTIFY flag is not specified */ - if (!(Flags & TPM_NONOTIFY)) - SendMessageW(Wnd, WM_INITMENUPOPUP, (WPARAM) Menu, 0); + if (MenuShowPopup(hWnd, hMenu, 0, wFlags, x, y, 0, 0 )) + ret = MenuTrackMenu(hMenu, wFlags | TPM_POPUPMENU, 0, 0, hWnd, + lpTpm ? &lpTpm->rcExclude : NULL); + MenuExitTracking(hWnd, TRUE); - if (MenuShowPopup(Wnd, Menu, 0, Flags, x, y, 0, 0 )) - ret = MenuTrackMenu(Menu, Flags | TPM_POPUPMENU, 0, 0, Wnd, - Tpm ? &Tpm->rcExclude : NULL); - MenuExitTracking(Wnd, TRUE); + if (menu->hWnd) + { + ROSMENUINFO MenuInfo; + if (IsWindow( menu->hWnd )) // wine hack around this with their destroy function. + DestroyWindow( menu->hWnd ); // Fix wrong error return. + //menu->hWnd = 0; + MenuGetRosMenuInfo(&MenuInfo, menu->head.h); + MenuInfo.Wnd = 0; + MenuSetRosMenuInfo(&MenuInfo); + + if (!(wFlags & TPM_NONOTIFY)) + SendMessageW( hWnd, WM_UNINITMENUPOPUP, (WPARAM)hMenu, + MAKELPARAM(0, IS_SYSTEM_MENU(menu)) ); + } + } return ret; } @@ -4456,164 +4226,63 @@ BOOL WINAPI TrackPopupMenu( HMENU Menu, UINT Flags, int x, int y, return TrackPopupMenuEx( Menu, Flags, x, y, Wnd, NULL); } -/* - * From MSDN: - * The MFT_BITMAP, MFT_SEPARATOR, and MFT_STRING values cannot be combined - * with one another. Also MFT_OWNERDRAW. Set fMask to MIIM_TYPE to use fType. - * - * Windows 2K/XP: fType is used only if fMask has a value of MIIM_FTYPE. - * - * MIIM_TYPE: Retrieves or sets the fType and dwTypeData members. Windows - * 2K/XP: MIIM_TYPE is replaced by MIIM_BITMAP, MIIM_FTYPE, and MIIM_STRING. - * MFT_STRING is replaced by MIIM_STRING. - * (So, I guess we should use MIIM_STRING only for strings?) - * - * MIIM_FTYPE: Windows 2K/Windows XP: Retrieves or sets the fType member. - * - * Based on wine, SetMenuItemInfo_common: - * 1) set MIIM_STRING | MIIM_FTYPE | MIIM_BITMAP any one with MIIM_TYPE, - * it will result in a error. - * 2) set menu mask to MIIM_FTYPE and MFT_BITMAP ftype it will result in a error. - * These conditions are addressed in Win32k IntSetMenuItemInfo. +/********************************************************************** + * MENU_mnu2mnuii * + * Uses flags, id and text ptr, passed by InsertMenu() and + * ModifyMenu() to setup a MenuItemInfo structure. */ -static -BOOL -FASTCALL -MenuSetItemData( - LPMENUITEMINFOW mii, - UINT Flags, - UINT_PTR IDNewItem, - LPCWSTR NewItem, - BOOL Unicode) +static void MENU_mnu2mnuii( UINT flags, UINT_PTR id, LPCWSTR str, LPMENUITEMINFOW pmii, BOOL Unicode) { -/* - * Let us assume MIIM_FTYPE is set and building a new menu item structure. - */ - if(Flags & MF_BITMAP) - { - mii->fMask |= MIIM_BITMAP; /* Use the new way of seting hbmpItem.*/ - mii->hbmpItem = (HBITMAP) NewItem; - - if (Flags & MF_HELP) - { - /* increase ident */ - mii->fType |= MF_HELP; - } - } - else if(Flags & MF_OWNERDRAW) - { - mii->fType |= MFT_OWNERDRAW; - mii->fMask |= MIIM_DATA; - mii->dwItemData = (DWORD_PTR) NewItem; - } - else if (Flags & MF_SEPARATOR) - { - mii->fType |= MFT_SEPARATOR; - if (!(Flags & (MF_GRAYED|MF_DISABLED))) - Flags |= MF_GRAYED|MF_DISABLED; - } - else /* Default action MF_STRING. */ - { - /* Item beginning with a backspace is a help item */ - if (NewItem != NULL) - { - if (Unicode) - { - if (*NewItem == '\b') - { - mii->fType |= MF_HELP; - NewItem++; - } - } - else - { - LPCSTR NewItemA = (LPCSTR) NewItem; - if (*NewItemA == '\b') - { - mii->fType |= MF_HELP; - NewItemA++; - NewItem = (LPCWSTR) NewItemA; - } - } - - if (Flags & MF_HELP) - mii->fType |= MF_HELP; - mii->fMask |= MIIM_STRING; - mii->fType |= MFT_STRING; /* Zero */ - mii->dwTypeData = (LPWSTR)NewItem; - if (Unicode) - mii->cch = (NULL == NewItem ? 0 : strlenW(NewItem)); - else - mii->cch = (NULL == NewItem ? 0 : strlen((LPCSTR)NewItem)); - } - else - { - mii->fType |= MFT_SEPARATOR; - if (!(Flags & (MF_GRAYED|MF_DISABLED))) - Flags |= MF_GRAYED|MF_DISABLED; - } - } - - if(Flags & MF_RIGHTJUSTIFY) /* Same as MF_HELP */ - { - mii->fType |= MFT_RIGHTJUSTIFY; - } - - if(Flags & MF_MENUBREAK) - { - mii->fType |= MFT_MENUBREAK; - } - else if(Flags & MF_MENUBARBREAK) - { - mii->fType |= MFT_MENUBARBREAK; - } - - if(Flags & MF_GRAYED || Flags & MF_DISABLED) - { - if (Flags & MF_GRAYED) - mii->fState |= MF_GRAYED; - - if (Flags & MF_DISABLED) - mii->fState |= MF_DISABLED; - - mii->fMask |= MIIM_STATE; - } - else if (Flags & MF_HILITE) - { - mii->fState |= MF_HILITE; - mii->fMask |= MIIM_STATE; - } - else /* default state */ - { - mii->fState |= MFS_ENABLED; - mii->fMask |= MIIM_STATE; - } - - if(Flags & MF_POPUP && IsMenu((HMENU)IDNewItem)) - { - mii->fMask |= MIIM_SUBMENU; - mii->hSubMenu = (HMENU)IDNewItem; - } - mii->fMask |= MIIM_ID; - mii->wID = (UINT)IDNewItem; - return TRUE; -} - -NTSTATUS WINAPI -User32CallLoadMenuFromKernel(PVOID Arguments, ULONG ArgumentLength) -{ - PLOADMENU_CALLBACK_ARGUMENTS Common; - LRESULT Result; - - Common = (PLOADMENU_CALLBACK_ARGUMENTS) Arguments; - - Result = (LRESULT)LoadMenuW( Common->hModule, - IS_INTRESOURCE(Common->MenuName[0]) ? - MAKEINTRESOURCE(Common->MenuName[0]) : - (LPCWSTR)&Common->MenuName); - - return ZwCallbackReturn(&Result, sizeof(LRESULT), STATUS_SUCCESS); + RtlZeroMemory( pmii, sizeof( MENUITEMINFOW)); + pmii->cbSize = sizeof( MENUITEMINFOW); + pmii->fMask = MIIM_STATE | MIIM_ID | MIIM_FTYPE; + /* setting bitmap clears text and vice versa */ + if( IS_STRING_ITEM(flags)) { + pmii->fMask |= MIIM_STRING | MIIM_BITMAP; + if( !str) + flags |= MF_SEPARATOR; + /* Item beginning with a backspace is a help item */ + /* FIXME: wrong place, this is only true in win16 */ + else + { + if (Unicode) + { + if (*str == '\b') + { + flags |= MF_HELP; + str++; + } + } + else + { + LPCSTR NewItemA = (LPCSTR) str; + if (*NewItemA == '\b') + { + flags |= MF_HELP; + NewItemA++; + str = (LPCWSTR) NewItemA; + } + TRACE("A cch %d\n",strlen(NewItemA)); + } + } + pmii->dwTypeData = (LPWSTR)str; + } else if( flags & MFT_BITMAP){ + pmii->fMask |= MIIM_BITMAP | MIIM_STRING; + pmii->hbmpItem = (HBITMAP)str; + } + if( flags & MF_OWNERDRAW){ + pmii->fMask |= MIIM_DATA; + pmii->dwItemData = (ULONG_PTR) str; + } + if( flags & MF_POPUP && MENU_GetMenu((HMENU)id)) { + pmii->fMask |= MIIM_SUBMENU; + pmii->hSubMenu = (HMENU)id; + } + if( flags & MF_SEPARATOR) flags |= MF_GRAYED | MF_DISABLED; + pmii->fState = flags & MENUITEMINFO_STATE_MASK & ~MFS_DEFAULT; + pmii->fType = flags & MENUITEMINFO_TYPE_MASK; + pmii->wID = (UINT)id; } /********************************************************************** @@ -4670,6 +4339,104 @@ static BOOL MENU_NormalizeMenuItemInfoStruct( const MENUITEMINFOW *pmii_in, return TRUE; } +BOOL +MenuInit(VOID) +{ + NONCLIENTMETRICSW ncm; + + /* get the menu font */ + if(!hMenuFont || !hMenuFontBold) + { + ncm.cbSize = sizeof(ncm); + if(!SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0)) + { + ERR("MenuInit(): SystemParametersInfoW(SPI_GETNONCLIENTMETRICS) failed!\n"); + return FALSE; + } + + hMenuFont = CreateFontIndirectW(&ncm.lfMenuFont); + if(hMenuFont == NULL) + { + ERR("MenuInit(): CreateFontIndirectW(hMenuFont) failed!\n"); + return FALSE; + } + + ncm.lfMenuFont.lfWeight = max(ncm.lfMenuFont.lfWeight + 300, 1000); + hMenuFontBold = CreateFontIndirectW(&ncm.lfMenuFont); + if(hMenuFontBold == NULL) + { + ERR("MenuInit(): CreateFontIndirectW(hMenuFontBold) failed!\n"); + DeleteObject(hMenuFont); + hMenuFont = NULL; + return FALSE; + } + } + + return TRUE; +} + +VOID +MenuCleanup(VOID) +{ + if (hMenuFont) + { + DeleteObject(hMenuFont); + hMenuFont = NULL; + } + + if (hMenuFontBold) + { + DeleteObject(hMenuFontBold); + hMenuFontBold = NULL; + } +} + +NTSTATUS WINAPI +User32LoadSysMenuTemplateForKernel(PVOID Arguments, ULONG ArgumentLength) +{ + HMENU hmenu = LoadMenuW(User32Instance, L"SYSMENU"); + LRESULT Result = (LRESULT)hmenu; + MENUINFO menuinfo = {0}; + MENUITEMINFOW info = {0}; + + // removing space for checkboxes from menu + menuinfo.cbSize = sizeof(menuinfo); + menuinfo.fMask = MIM_STYLE; + GetMenuInfo(hmenu, &menuinfo); + menuinfo.dwStyle |= MNS_CHECKORBMP; // test_menu_bmp_and_string MNS_CHECKORBMP + SetMenuInfo(hmenu, &menuinfo); + + // adding bitmaps to menu items + info.cbSize = sizeof(info); + info.fMask |= MIIM_BITMAP; + info.hbmpItem = HBMMENU_POPUP_MINIMIZE; + SetMenuItemInfoW(hmenu, SC_MINIMIZE, FALSE, &info); + info.hbmpItem = HBMMENU_POPUP_RESTORE; + SetMenuItemInfoW(hmenu, SC_RESTORE, FALSE, &info); + info.hbmpItem = HBMMENU_POPUP_MAXIMIZE; + SetMenuItemInfoW(hmenu, SC_MAXIMIZE, FALSE, &info); + info.hbmpItem = HBMMENU_POPUP_CLOSE; + SetMenuItemInfoW(hmenu, SC_CLOSE, FALSE, &info); + + return(ZwCallbackReturn(&Result, sizeof(LRESULT), STATUS_SUCCESS)); +} + +NTSTATUS WINAPI +User32CallLoadMenuFromKernel(PVOID Arguments, ULONG ArgumentLength) +{ + PLOADMENU_CALLBACK_ARGUMENTS Common; + LRESULT Result; + + Common = (PLOADMENU_CALLBACK_ARGUMENTS) Arguments; + + Result = (LRESULT)LoadMenuW( Common->hModule, + IS_INTRESOURCE(Common->MenuName[0]) ? + MAKEINTRESOURCE(Common->MenuName[0]) : + (LPCWSTR)&Common->MenuName); + + return ZwCallbackReturn(&Result, sizeof(LRESULT), STATUS_SUCCESS); +} + /* FUNCTIONS *****************************************************************/ @@ -4682,7 +4449,33 @@ AppendMenuA(HMENU hMenu, UINT_PTR uIDNewItem, LPCSTR lpNewItem) { - return(InsertMenuA(hMenu, -1, uFlags | MF_BYPOSITION, uIDNewItem, lpNewItem)); + MENUITEMINFOW mii; + UNICODE_STRING UnicodeString; + BOOL res; + + RtlInitUnicodeString(&UnicodeString, 0); + + MENU_mnu2mnuii( uFlags, uIDNewItem, (LPCWSTR)lpNewItem, &mii, FALSE); + + /* copy the text string, it wll be one or the other */ + if (lpNewItem && mii.fMask & MIIM_STRING && !mii.hbmpItem && mii.dwTypeData) + { + if (!RtlCreateUnicodeStringFromAsciiz(&UnicodeString, (LPSTR)mii.dwTypeData)) + { + SetLastError (ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + mii.dwTypeData = UnicodeString.Buffer; + mii.cch = UnicodeString.Length / sizeof(WCHAR); + } + else + { + TRACE("AMA Handle bitmaps\n"); + } + ////// Answer a question, why a -1? To hunt for the end of the item list. Get it, to Append? + res = NtUserThunkedMenuItemInfo(hMenu, -1, TRUE, TRUE, &mii, &UnicodeString); + if ( UnicodeString.Buffer ) RtlFreeUnicodeString ( &UnicodeString ); + return res; } /* @@ -4694,7 +4487,23 @@ AppendMenuW(HMENU hMenu, UINT_PTR uIDNewItem, LPCWSTR lpNewItem) { - return(InsertMenuW(hMenu, -1, uFlags | MF_BYPOSITION, uIDNewItem, lpNewItem)); + MENUITEMINFOW mii; + UNICODE_STRING MenuText; + BOOL res; + + RtlInitUnicodeString(&MenuText, 0); + + MENU_mnu2mnuii( uFlags, uIDNewItem, lpNewItem, &mii, TRUE); + + /* copy the text string, it wll be one or the other */ + if (lpNewItem && mii.fMask & MIIM_STRING && !mii.hbmpItem && mii.dwTypeData) + { + RtlInitUnicodeString(&MenuText, (PWSTR)mii.dwTypeData); + mii.dwTypeData = MenuText.Buffer; + mii.cch = MenuText.Length / sizeof(WCHAR); + } + res = NtUserThunkedMenuItemInfo(hMenu, -1, TRUE, TRUE, &mii, &MenuText); + return res; } /* @@ -4720,7 +4529,6 @@ CheckMenuItem(HMENU hmenu, return NtUserCheckMenuItem(hmenu, uIDCheckItem, uCheck); } - /* * @implemented */ @@ -4855,7 +4663,7 @@ EndMenu(VOID) /* don't end up with an orphaned menu */ PostMessageW( top_popup, WM_CANCELMODE, 0, 0); } - return TRUE; + return fEndMenu; } BOOL WINAPI HiliteMenuItem( HWND hWnd, HMENU hMenu, UINT wItemID, @@ -4891,7 +4699,6 @@ GetMenu(HWND hWnd) return UlongToHandle(Wnd->IDMenu); } - /* * @implemented */ @@ -5005,28 +4812,10 @@ UINT WINAPI GetMenuItemID(HMENU hMenu, int nPos) { - PMENU pMenu; - PITEM pItem; - INT i = 0; - - if (!(pMenu = ValidateHandle(hMenu, TYPE_MENU))) - return -1; - - 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; + ITEM * lpmi; + if (!(lpmi = MENU_FindItem(&hMenu,(UINT*)&nPos,MF_BYPOSITION))) return -1; + if (lpmi->spSubMenu) return -1; + return lpmi->wID; } /* @@ -5096,18 +4885,21 @@ GetMenuState( UINT uFlags) { PITEM pItem; + UINT Type = 0; TRACE("(menu=%p, id=%04x, flags=%04x);\n", hMenu, uId, uFlags); if (!(pItem = MENU_FindItem( &hMenu, &uId, uFlags ))) return -1; + if (!pItem->Xlpstr && pItem->hbmp) Type = MFT_BITMAP; + 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 (pSubMenu->cItems << 8) | ((pItem->fState|pItem->fType|Type) & 0xff); } else - return (pItem->fType | pItem->fState); + return (pItem->fType | pItem->fState | Type); } /* @@ -5122,18 +4914,6 @@ GetMenuStringA( int nMaxCount, UINT uFlag) { -/* MENUITEMINFOA mii; - memset( &mii, 0, sizeof(mii) ); - mii.dwTypeData = lpString; - mii.fMask = MIIM_STRING; - mii.cbSize = sizeof(MENUITEMINFOA); - mii.cch = nMaxCount; - - if(!(GetMenuItemInfoA( hMenu, uIDItem, (BOOL)(MF_BYPOSITION & uFlag),&mii))) - return 0; - else - return mii.cch; -*/ ITEM *item; LPWSTR text; ////// wine Code, seems to be faster. @@ -5153,7 +4933,7 @@ GetMenuStringA( 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); + TRACE("A returning %s\n", lpString); return strlen(lpString); } @@ -5169,19 +4949,6 @@ GetMenuStringW( int nMaxCount, UINT uFlag) { -/* MENUITEMINFOW miiW; - memset( &miiW, 0, sizeof(miiW) ); - miiW.dwTypeData = lpString; - miiW.fMask = MIIM_STRING | MIIM_FTYPE; - miiW.fType = MFT_STRING; - miiW.cbSize = sizeof(MENUITEMINFOW); - miiW.cch = nMaxCount; - - if(!(GetMenuItemInfoW( hMenu, uIDItem, (BOOL)(MF_BYPOSITION & uFlag),&miiW))) - return 0; - else - return miiW.cch; -*/ ITEM *item; LPWSTR text; @@ -5204,7 +4971,7 @@ GetMenuStringW( return 0; } lstrcpynW( lpString, text, nMaxCount ); - ERR("returning %S\n", lpString); + TRACE("W returning %S\n", lpString); return strlenW(lpString); } @@ -5257,18 +5024,32 @@ InsertMenuA( UINT_PTR uIDNewItem, LPCSTR lpNewItem) { - MENUITEMINFOA mii; - memset( &mii, 0, sizeof(mii) ); - mii.cbSize = sizeof(MENUITEMINFOA); - mii.fMask = MIIM_FTYPE; - - MenuSetItemData((LPMENUITEMINFOW) &mii, - uFlags, - uIDNewItem, - (LPCWSTR) lpNewItem, - FALSE); - - return InsertMenuItemA(hMenu, uPosition, (BOOL)((MF_BYPOSITION & uFlags) > 0), &mii); + MENUITEMINFOW mii; + UNICODE_STRING UnicodeString; + BOOL res; + + RtlInitUnicodeString(&UnicodeString, 0); + + MENU_mnu2mnuii( uFlags, uIDNewItem, (LPCWSTR)lpNewItem, &mii, FALSE); + + /* copy the text string, it wll be one or the other */ + if (lpNewItem && mii.fMask & MIIM_STRING && !mii.hbmpItem && mii.dwTypeData) + { + if (!RtlCreateUnicodeStringFromAsciiz(&UnicodeString, (LPSTR)mii.dwTypeData)) + { + SetLastError (ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + mii.dwTypeData = UnicodeString.Buffer; + mii.cch = UnicodeString.Length / sizeof(WCHAR); + } + else + { + TRACE("Handle bitmaps\n"); + } + res = NtUserThunkedMenuItemInfo(hMenu, uPosition, (BOOL)(uFlags & MF_BYPOSITION), TRUE, &mii, &UnicodeString); + if ( UnicodeString.Buffer ) RtlFreeUnicodeString ( &UnicodeString ); + return res; } /* @@ -5307,7 +5088,7 @@ InsertMenuItemA( } else { - UnicodeString.Buffer = NULL; + TRACE("Handle bitmaps\n"); } res = NtUserThunkedMenuItemInfo(hMenu, uItem, fByPosition, TRUE, &mii, &UnicodeString); if ( UnicodeString.Buffer ) RtlFreeUnicodeString ( &UnicodeString ); @@ -5365,17 +5146,22 @@ InsertMenuW( LPCWSTR lpNewItem) { MENUITEMINFOW mii; - memset( &mii, 0, sizeof(mii) ); - mii.cbSize = sizeof(MENUITEMINFOW); - mii.fMask = MIIM_FTYPE; + UNICODE_STRING MenuText; + BOOL res; - MenuSetItemData( &mii, - uFlags, - uIDNewItem, - lpNewItem, - TRUE); + RtlInitUnicodeString(&MenuText, 0); - return InsertMenuItemW(hMenu, uPosition, (BOOL)((MF_BYPOSITION & uFlags) > 0), &mii); + MENU_mnu2mnuii( uFlags, uIDNewItem, lpNewItem, &mii, TRUE); + + /* copy the text string, it wll be one or the other */ + if (lpNewItem && mii.fMask & MIIM_STRING && !mii.hbmpItem && mii.dwTypeData) + { + RtlInitUnicodeString(&MenuText, (PWSTR)mii.dwTypeData); + mii.dwTypeData = MenuText.Buffer; + mii.cch = MenuText.Length / sizeof(WCHAR); + } + res = NtUserThunkedMenuItemInfo(hMenu, uPosition, (BOOL)(uFlags & MF_BYPOSITION), TRUE, &mii, &MenuText); + return res; } /* @@ -5489,30 +5275,38 @@ MenuItemFromPoint( BOOL WINAPI ModifyMenuA( - HMENU hMnu, + HMENU hMenu, UINT uPosition, UINT uFlags, UINT_PTR uIDNewItem, LPCSTR lpNewItem) { - MENUITEMINFOA mii; - memset( &mii, 0, sizeof(mii) ); - mii.cbSize = sizeof(MENUITEMINFOA); - mii.fMask = MIIM_FTYPE; - - 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); + MENUITEMINFOW mii; + UNICODE_STRING UnicodeString; + BOOL res; + + RtlInitUnicodeString(&UnicodeString, 0); + + MENU_mnu2mnuii( uFlags, uIDNewItem, (LPCWSTR)lpNewItem, &mii, FALSE); + + /* copy the text string, it wll be one or the other */ + if (lpNewItem && mii.fMask & MIIM_STRING && !mii.hbmpItem && mii.dwTypeData) + { + if (!RtlCreateUnicodeStringFromAsciiz(&UnicodeString, (LPSTR)mii.dwTypeData)) + { + SetLastError (ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + mii.dwTypeData = UnicodeString.Buffer; + mii.cch = UnicodeString.Length / sizeof(WCHAR); + } + else + { + TRACE("Handle bitmaps\n"); + } + res = NtUserThunkedMenuItemInfo(hMenu, uPosition, (BOOL)(uFlags & MF_BYPOSITION), FALSE, &mii, &UnicodeString); + if ( UnicodeString.Buffer ) RtlFreeUnicodeString ( &UnicodeString ); + return res; } /* @@ -5521,31 +5315,33 @@ ModifyMenuA( BOOL WINAPI ModifyMenuW( - HMENU hMnu, + HMENU hMenu, UINT uPosition, UINT uFlags, UINT_PTR uIDNewItem, LPCWSTR lpNewItem) { MENUITEMINFOW mii; - memset ( &mii, 0, sizeof(mii) ); - mii.cbSize = sizeof(MENUITEMINFOW); - mii.fMask = MIIM_FTYPE; - - /* Init new data for this menu item */ - MenuSetItemData( &mii, - uFlags, - uIDNewItem, - lpNewItem, - TRUE); - - //if (mii.hSubMenu && (uFlags & MF_POPUP) && (mii.hSubMenu != (HMENU)uIDNewItem)) - // NtUserDestroyMenu( mii.hSubMenu ); /* ModifyMenu() spec */ - - return SetMenuItemInfoW( hMnu, - uPosition, - (BOOL)(MF_BYPOSITION & uFlags), - &mii); + UNICODE_STRING MenuText; + BOOL res; + + RtlInitUnicodeString(&MenuText, 0); + + MENU_mnu2mnuii( uFlags, uIDNewItem, lpNewItem, &mii, TRUE); + + /* copy the text string, it wll be one or the other */ + if (lpNewItem && mii.fMask & MIIM_STRING && !mii.hbmpItem && mii.dwTypeData) + { + RtlInitUnicodeString(&MenuText, (PWSTR)mii.dwTypeData); + mii.dwTypeData = MenuText.Buffer; + mii.cch = MenuText.Length / sizeof(WCHAR); + } + else + { + TRACE("Handle bitmaps\n"); + } + res = NtUserThunkedMenuItemInfo(hMenu, uPosition, (BOOL)(uFlags & MF_BYPOSITION), FALSE, &mii, &MenuText); + return res; } /* @@ -5729,8 +5525,6 @@ NEWTrackPopupMenu( NULL); // LPTPMPARAMS is null } - - /* * @unimplemented */ @@ -5756,7 +5550,6 @@ MenuWindowProcA( return FALSE; } return NtUserMessageCall(hWnd, Msg, wParam, lParam, Result, FNID_MENU, TRUE); - } /* -- 2.17.1