2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
5 * FILE: subsys/win32k/ntuser/menu.c
6 * PROGRAMER: Thomas Weidenmueller (w3seek@users.sourceforge.net)
10 DBG_DEFAULT_CHANNEL(UserMenu
);
12 /* INTERNAL ******************************************************************/
14 BOOL FASTCALL
IntSetMenuItemInfo(PMENU
, PITEM
, PROSMENUITEMINFO
, PUNICODE_STRING
);
16 /* maximum allowed depth of any branch in the menu tree.
17 * This value is slightly larger than in windows (25) to
18 * stay on the safe side. */
19 #define MAXMENUDEPTH 30
21 #define MNS_STYLE_MASK (MNS_NOCHECK|MNS_MODELESS|MNS_DRAGDROP|MNS_AUTODISMISS|MNS_NOTIFYBYPOS|MNS_CHECKORBMP)
23 #define MENUITEMINFO_TYPE_MASK \
24 (MFT_STRING | MFT_BITMAP | MFT_OWNERDRAW | MFT_SEPARATOR | \
25 MFT_MENUBARBREAK | MFT_MENUBREAK | MFT_RADIOCHECK | \
26 MFT_RIGHTORDER | MFT_RIGHTJUSTIFY /* same as MF_HELP */ )
28 #define TYPE_MASK (MENUITEMINFO_TYPE_MASK | MF_POPUP | MF_SYSMENU)
30 #define STATE_MASK (~TYPE_MASK)
32 #define MENUITEMINFO_STATE_MASK (STATE_MASK & ~(MF_BYPOSITION | MF_MOUSESELECT))
34 #define MII_STATE_MASK (MFS_GRAYED|MFS_CHECKED|MFS_HILITE|MFS_DEFAULT)
36 /* Maximum number of menu items a menu can contain */
37 #define MAX_MENU_ITEMS (0x4000)
38 #define MAX_GOINTOSUBMENU (0x10)
40 #define UpdateMenuItemState(state, change) \
42 if((change) & MF_GRAYED) { \
43 (state) |= MF_GRAYED; \
45 (state) &= ~MF_GRAYED; \
46 } /* Separate the two for test_menu_resource_layout.*/ \
47 if((change) & MF_DISABLED) { \
48 (state) |= MF_DISABLED; \
50 (state) &= ~MF_DISABLED; \
52 if((change) & MFS_CHECKED) { \
53 (state) |= MFS_CHECKED; \
55 (state) &= ~MFS_CHECKED; \
57 if((change) & MFS_HILITE) { \
58 (state) |= MFS_HILITE; \
60 (state) &= ~MFS_HILITE; \
62 if((change) & MFS_DEFAULT) { \
63 (state) |= MFS_DEFAULT; \
65 (state) &= ~MFS_DEFAULT; \
67 if((change) & MF_MOUSESELECT) { \
68 (state) |= MF_MOUSESELECT; \
70 (state) &= ~MF_MOUSESELECT; \
76 DumpMenuItemList(PMENU Menu
, PITEM MenuItem
)
78 UINT cnt
= 0, i
= Menu
->cItems
;
81 if(MenuItem
->lpstr
.Length
)
82 DbgPrint(" %d. %wZ\n", ++cnt
, &MenuItem
->lpstr
);
84 DbgPrint(" %d. NO TEXT dwTypeData==%d\n", ++cnt
, (DWORD
)MenuItem
->lpstr
.Buffer
);
86 if(MFT_BITMAP
& MenuItem
->fType
)
87 DbgPrint("MFT_BITMAP ");
88 if(MFT_MENUBARBREAK
& MenuItem
->fType
)
89 DbgPrint("MFT_MENUBARBREAK ");
90 if(MFT_MENUBREAK
& MenuItem
->fType
)
91 DbgPrint("MFT_MENUBREAK ");
92 if(MFT_OWNERDRAW
& MenuItem
->fType
)
93 DbgPrint("MFT_OWNERDRAW ");
94 if(MFT_RADIOCHECK
& MenuItem
->fType
)
95 DbgPrint("MFT_RADIOCHECK ");
96 if(MFT_RIGHTJUSTIFY
& MenuItem
->fType
)
97 DbgPrint("MFT_RIGHTJUSTIFY ");
98 if(MFT_SEPARATOR
& MenuItem
->fType
)
99 DbgPrint("MFT_SEPARATOR ");
100 if(MFT_STRING
& MenuItem
->fType
)
101 DbgPrint("MFT_STRING ");
102 DbgPrint("\n fState=");
103 if(MFS_DISABLED
& MenuItem
->fState
)
104 DbgPrint("MFS_DISABLED ");
106 DbgPrint("MFS_ENABLED ");
107 if(MFS_CHECKED
& MenuItem
->fState
)
108 DbgPrint("MFS_CHECKED ");
110 DbgPrint("MFS_UNCHECKED ");
111 if(MFS_HILITE
& MenuItem
->fState
)
112 DbgPrint("MFS_HILITE ");
114 DbgPrint("MFS_UNHILITE ");
115 if(MFS_DEFAULT
& MenuItem
->fState
)
116 DbgPrint("MFS_DEFAULT ");
117 if(MFS_GRAYED
& MenuItem
->fState
)
118 DbgPrint("MFS_GRAYED ");
119 DbgPrint("\n wId=%d\n", MenuItem
->wID
);
123 DbgPrint("Entries: %d\n", cnt
);
128 #define FreeMenuText(Menu,MenuItem) \
130 if((MENU_ITEM_TYPE((MenuItem)->fType) == MF_STRING) && \
131 (MenuItem)->lpstr.Length) { \
132 DesktopHeapFree(((PMENU)Menu)->head.rpdesk, (MenuItem)->lpstr.Buffer); \
137 IntGetMenuObject(HMENU hMenu
)
139 PMENU Menu
= UserGetMenuObject(hMenu
);
141 Menu
->head
.cLockObj
++;
146 PMENU FASTCALL
VerifyMenu(PMENU pMenu
)
151 if (!pMenu
) return NULL
;
155 hMenu
= UserHMGetHandle(pMenu
);
156 pItem
= pMenu
->rgItems
;
163 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
165 ERR("Run away LOOP!\n");
166 _SEH2_YIELD(return NULL
);
170 if ( UserObjectInDestroy(hMenu
))
172 ERR("Menu is marked for destruction!\n");
179 BOOL
IntDestroyMenu( PMENU pMenu
, BOOL bRecurse
, BOOL RemoveFromProcess
)
183 if (pMenu
->rgItems
) /* recursively destroy submenus */
186 ITEM
*item
= pMenu
->rgItems
;
187 for (i
= pMenu
->cItems
; i
> 0; i
--, item
++)
189 SubMenu
= item
->spSubMenu
;
190 item
->spSubMenu
= NULL
;
192 /* Remove Item Text */
193 FreeMenuText(pMenu
,item
);
195 /* Remove Item Bitmap and set it for this process */
196 if (item
->hbmp
&& !(item
->fState
& MFS_HBMMENUBMP
))
198 GreSetObjectOwner(item
->hbmp
, GDI_OBJ_HMGR_POWNED
);
202 /* Remove Item submenu */
203 if (bRecurse
&& SubMenu
)//VerifyMenu(SubMenu))
205 /* Release submenu since it was referenced when inserted */
206 IntReleaseMenuObject(SubMenu
);
207 IntDestroyMenuObject(SubMenu
, bRecurse
, RemoveFromProcess
);
211 DesktopHeapFree(pMenu
->head
.rpdesk
, pMenu
->rgItems
);
212 pMenu
->rgItems
= NULL
;
219 IntDestroyMenuObject(PMENU Menu
, BOOL bRecurse
, BOOL RemoveFromProcess
)
225 /* Remove all menu items */
226 IntDestroyMenu( Menu
, bRecurse
, RemoveFromProcess
);
228 if (RemoveFromProcess
)
230 RemoveEntryList(&Menu
->ListEntry
);
233 if (PsGetCurrentProcessSessionId() == Menu
->head
.rpdesk
->rpwinstaParent
->dwSessionId
)
238 Window
= UserGetWindowObject(Menu
->hWnd
);
243 /* DestroyMenu should not destroy system menu popup owner */
244 if ((Menu
->fFlags
& (MNF_POPUP
| MNF_SYSSUBMENU
)) == MNF_POPUP
)
246 // Should we check it to see if it has Class?
247 ERR("FIXME Pop up menu window thing'ie\n");
248 //co_UserDestroyWindow( Window );
253 ret
= UserDeleteObject(Menu
->head
.h
, TYPE_MENU
);
255 { // Make sure it is really dead or just marked for deletion.
256 ret
= UserObjectInDestroy(Menu
->head
.h
);
257 if (ret
&& EngGetLastError() == ERROR_INVALID_HANDLE
) ret
= FALSE
;
258 } // See test_subpopup_locked_by_menu tests....
265 /**********************************************************************
268 * detect if there are loops in the menu tree (or the depth is too large)
270 int FASTCALL
MENU_depth( PMENU pmenu
, int depth
)
276 if (!pmenu
) return depth
;
279 if( depth
> MAXMENUDEPTH
) return depth
;
280 item
= pmenu
->rgItems
;
282 for( i
= 0; item
, i
< pmenu
->cItems
&& subdepth
<= MAXMENUDEPTH
; i
++, item
++)
284 if( item
->spSubMenu
)//VerifyMenu(item->spSubMenu))
286 int bdepth
= MENU_depth( item
->spSubMenu
, depth
);
287 if( bdepth
> subdepth
) subdepth
= bdepth
;
289 if( subdepth
> MAXMENUDEPTH
)
290 TRACE("<- hmenu %p\n", item
->spSubMenu
);
295 /***********************************************************************
298 * Find a menu item. Return a pointer on the item, and modifies *hmenu
299 * in case the item was in a sub-menu.
301 PITEM FASTCALL
MENU_FindItem( PMENU
*pmenu
, UINT
*nPos
, UINT wFlags
)
304 ITEM
*fallback
= NULL
;
305 UINT fallback_pos
= 0;
308 if (!menu
) return NULL
;
310 if (wFlags
& MF_BYPOSITION
)
312 if (!menu
->cItems
) return NULL
;
313 if (*nPos
>= menu
->cItems
) return NULL
;
314 return &menu
->rgItems
[*nPos
];
318 PITEM item
= menu
->rgItems
;
319 for (i
= 0; item
, i
< menu
->cItems
; i
++, item
++)
323 PMENU psubmenu
= item
->spSubMenu
;//VerifyMenu(item->spSubMenu);
324 PITEM subitem
= MENU_FindItem( &psubmenu
, nPos
, wFlags
);
330 else if (item
->wID
== *nPos
)
332 /* fallback to this item if nothing else found */
337 else if (item
->wID
== *nPos
)
346 *nPos
= fallback_pos
;
352 IntRemoveMenuItem( PMENU pMenu
, UINT nPos
, UINT wFlags
, BOOL bRecurse
)
356 TRACE("(menu=%p pos=%04x flags=%04x)\n",pMenu
, nPos
, wFlags
);
357 if (!(item
= MENU_FindItem( &pMenu
, &nPos
, wFlags
))) return FALSE
;
361 FreeMenuText(pMenu
,item
);
362 if (bRecurse
&& item
->spSubMenu
)
364 IntDestroyMenuObject(item
->spSubMenu
, bRecurse
, TRUE
);
366 ////// Use cAlloced with inc's of 8's....
367 if (--pMenu
->cItems
== 0)
369 DesktopHeapFree(pMenu
->head
.rpdesk
, pMenu
->rgItems
);
370 pMenu
->rgItems
= NULL
;
374 while(nPos
< pMenu
->cItems
)
380 pMenu
->rgItems
= DesktopHeapReAlloc(pMenu
->head
.rpdesk
, pMenu
->rgItems
, pMenu
->cItems
* sizeof(ITEM
));
385 /**********************************************************************
388 * Insert (allocate) a new item into a menu.
390 ITEM
*MENU_InsertItem( PMENU menu
, UINT pos
, UINT flags
, PMENU
*submenu
, UINT
*npos
)
394 /* Find where to insert new item */
396 if (flags
& MF_BYPOSITION
) {
397 if (pos
> menu
->cItems
)
400 if (!MENU_FindItem( &menu
, &pos
, flags
))
402 if (submenu
) *submenu
= menu
;
403 if (npos
) *npos
= pos
;
408 /* Make sure that MDI system buttons stay on the right side.
409 * Note: XP treats only bitmap handles 1 - 6 as "magic" ones
410 * regardless of their id.
413 (INT_PTR
)menu
->rgItems
[pos
- 1].hbmp
>= (INT_PTR
)HBMMENU_SYSTEM
&&
414 (INT_PTR
)menu
->rgItems
[pos
- 1].hbmp
<= (INT_PTR
)HBMMENU_MBAR_CLOSE_D
)
417 TRACE("inserting at %u flags %x\n", pos
, flags
);
419 /* Create new items array */
421 newItems
= DesktopHeapAlloc(menu
->head
.rpdesk
, sizeof(ITEM
) * (menu
->cItems
+1) );
424 WARN("allocation failed\n" );
427 if (menu
->cItems
> 0)
429 /* Copy the old array into the new one */
430 if (pos
> 0) RtlCopyMemory( newItems
, menu
->rgItems
, pos
* sizeof(ITEM
) );
431 if (pos
< menu
->cItems
) RtlCopyMemory( &newItems
[pos
+1], &menu
->rgItems
[pos
], (menu
->cItems
-pos
)*sizeof(ITEM
) );
432 DesktopHeapFree(menu
->head
.rpdesk
, menu
->rgItems
);
434 menu
->rgItems
= newItems
;
436 RtlZeroMemory( &newItems
[pos
], sizeof(*newItems
) );
437 menu
->cyMenu
= 0; /* force size recalculate */
438 return &newItems
[pos
];
443 _In_ PMENU MenuObject
,
446 PROSMENUITEMINFO ItemInfo
,
447 PUNICODE_STRING lpstr
)
450 PMENU SubMenu
= NULL
;
452 NT_ASSERT(MenuObject
!= NULL
);
454 if (MAX_MENU_ITEMS
<= MenuObject
->cItems
)
456 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY
);
460 SubMenu
= MenuObject
;
462 if(!(MenuItem
= MENU_InsertItem( SubMenu
, uItem
, fByPosition
? MF_BYPOSITION
: MF_BYCOMMAND
, &SubMenu
, &uItem
))) return FALSE
;
464 if(!IntSetMenuItemInfo(SubMenu
, MenuItem
, ItemInfo
, lpstr
))
466 IntRemoveMenuItem(SubMenu
, uItem
, fByPosition
? MF_BYPOSITION
: MF_BYCOMMAND
, FALSE
);
470 /* Force size recalculation! */
472 MenuItem
->hbmpChecked
= MenuItem
->hbmpUnchecked
= 0;
474 TRACE("IntInsertMenuItemToList = %i %d\n", uItem
, (BOOL
)((INT
)uItem
>= 0));
480 IntCreateMenu(PHANDLE Handle
, BOOL IsMenuBar
)
483 PPROCESSINFO CurrentWin32Process
;
485 Menu
= (PMENU
)UserCreateObject( gHandleTable
,
497 Menu
->cyMax
= 0; /* Default */
498 Menu
->hbrBack
= NULL
; /* No brush */
499 Menu
->dwContextHelpId
= 0; /* Default */
500 Menu
->dwMenuData
= 0; /* Default */
501 Menu
->iItem
= NO_SELECTED_ITEM
; // Focused item
502 Menu
->fFlags
= (IsMenuBar
? 0 : MNF_POPUP
);
503 Menu
->spwndNotify
= NULL
;
504 Menu
->cyMenu
= 0; // Height
505 Menu
->cxMenu
= 0; // Width
506 Menu
->cItems
= 0; // Item count
509 Menu
->cxTextAlign
= 0;
510 Menu
->rgItems
= NULL
;
513 Menu
->TimeToHide
= FALSE
;
515 /* Insert menu item into process menu handle list */
516 CurrentWin32Process
= PsGetCurrentProcessWin32Process();
517 InsertTailList(&CurrentWin32Process
->MenuListHead
, &Menu
->ListEntry
);
523 IntCloneMenuItems(PMENU Destination
, PMENU Source
)
525 PITEM MenuItem
, NewMenuItem
= NULL
;
531 NewMenuItem
= DesktopHeapAlloc(Destination
->head
.rpdesk
, (Source
->cItems
+1) * sizeof(ITEM
));
532 if(!NewMenuItem
) return FALSE
;
534 RtlZeroMemory(NewMenuItem
, (Source
->cItems
+1) * sizeof(ITEM
));
536 Destination
->rgItems
= NewMenuItem
;
538 MenuItem
= Source
->rgItems
;
539 for (i
= 0; i
< Source
->cItems
; i
++, MenuItem
++, NewMenuItem
++)
541 NewMenuItem
->fType
= MenuItem
->fType
;
542 NewMenuItem
->fState
= MenuItem
->fState
;
543 NewMenuItem
->wID
= MenuItem
->wID
;
544 NewMenuItem
->spSubMenu
= MenuItem
->spSubMenu
;
545 NewMenuItem
->hbmpChecked
= MenuItem
->hbmpChecked
;
546 NewMenuItem
->hbmpUnchecked
= MenuItem
->hbmpUnchecked
;
547 NewMenuItem
->dwItemData
= MenuItem
->dwItemData
;
548 if (MenuItem
->lpstr
.Length
)
550 NewMenuItem
->lpstr
.Length
= 0;
551 NewMenuItem
->lpstr
.MaximumLength
= MenuItem
->lpstr
.MaximumLength
;
552 NewMenuItem
->lpstr
.Buffer
= DesktopHeapAlloc(Destination
->head
.rpdesk
, MenuItem
->lpstr
.MaximumLength
);
553 if (!NewMenuItem
->lpstr
.Buffer
)
555 DesktopHeapFree(Destination
->head
.rpdesk
, NewMenuItem
);
558 RtlCopyUnicodeString(&NewMenuItem
->lpstr
, &MenuItem
->lpstr
);
559 NewMenuItem
->lpstr
.Buffer
[MenuItem
->lpstr
.Length
/ sizeof(WCHAR
)] = 0;
560 NewMenuItem
->Xlpstr
= NewMenuItem
->lpstr
.Buffer
;
564 NewMenuItem
->lpstr
.Buffer
= MenuItem
->lpstr
.Buffer
;
565 NewMenuItem
->Xlpstr
= NewMenuItem
->lpstr
.Buffer
;
567 NewMenuItem
->hbmp
= MenuItem
->hbmp
;
573 IntCloneMenu(PMENU Source
)
575 PPROCESSINFO CurrentWin32Process
;
582 Menu
= (PMENU
)UserCreateObject( gHandleTable
,
591 Menu
->fFlags
= Source
->fFlags
;
592 Menu
->cyMax
= Source
->cyMax
;
593 Menu
->hbrBack
= Source
->hbrBack
;
594 Menu
->dwContextHelpId
= Source
->dwContextHelpId
;
595 Menu
->dwMenuData
= Source
->dwMenuData
;
596 Menu
->iItem
= NO_SELECTED_ITEM
;
597 Menu
->spwndNotify
= NULL
;
600 Menu
->cItems
= Source
->cItems
;
603 Menu
->cxTextAlign
= 0;
604 Menu
->rgItems
= NULL
;
607 Menu
->TimeToHide
= FALSE
;
609 /* Insert menu item into process menu handle list */
610 CurrentWin32Process
= PsGetCurrentProcessWin32Process();
611 InsertTailList(&CurrentWin32Process
->MenuListHead
, &Menu
->ListEntry
);
613 IntCloneMenuItems(Menu
, Source
);
619 IntSetMenuFlagRtoL(PMENU Menu
)
621 Menu
->fFlags
|= MNF_RTOL
;
626 IntSetMenuContextHelpId(PMENU Menu
, DWORD dwContextHelpId
)
628 Menu
->dwContextHelpId
= dwContextHelpId
;
633 IntGetMenuInfo(PMENU Menu
, PROSMENUINFO lpmi
)
635 if(lpmi
->fMask
& MIM_BACKGROUND
)
636 lpmi
->hbrBack
= Menu
->hbrBack
;
637 if(lpmi
->fMask
& MIM_HELPID
)
638 lpmi
->dwContextHelpID
= Menu
->dwContextHelpId
;
639 if(lpmi
->fMask
& MIM_MAXHEIGHT
)
640 lpmi
->cyMax
= Menu
->cyMax
;
641 if(lpmi
->fMask
& MIM_MENUDATA
)
642 lpmi
->dwMenuData
= Menu
->dwMenuData
;
643 if(lpmi
->fMask
& MIM_STYLE
)
644 lpmi
->dwStyle
= Menu
->fFlags
& MNS_STYLE_MASK
;
646 if (sizeof(MENUINFO
) < lpmi
->cbSize
)
648 lpmi
->cItems
= Menu
->cItems
;
650 lpmi
->iItem
= Menu
->iItem
;
651 lpmi
->cxMenu
= Menu
->cxMenu
;
652 lpmi
->cyMenu
= Menu
->cyMenu
;
653 lpmi
->spwndNotify
= Menu
->spwndNotify
;
654 lpmi
->cxTextAlign
= Menu
->cxTextAlign
;
655 lpmi
->iTop
= Menu
->iMaxTop
;
656 lpmi
->iMaxTop
= Menu
->iMaxTop
;
657 lpmi
->dwArrowsOn
= Menu
->dwArrowsOn
;
659 lpmi
->fFlags
= Menu
->fFlags
;
660 lpmi
->Self
= Menu
->head
.h
;
661 lpmi
->TimeToHide
= Menu
->TimeToHide
;
662 lpmi
->Wnd
= Menu
->hWnd
;
668 IntSetMenuInfo(PMENU Menu
, PROSMENUINFO lpmi
)
670 if(lpmi
->fMask
& MIM_BACKGROUND
)
671 Menu
->hbrBack
= lpmi
->hbrBack
;
672 if(lpmi
->fMask
& MIM_HELPID
)
673 Menu
->dwContextHelpId
= lpmi
->dwContextHelpID
;
674 if(lpmi
->fMask
& MIM_MAXHEIGHT
)
675 Menu
->cyMax
= lpmi
->cyMax
;
676 if(lpmi
->fMask
& MIM_MENUDATA
)
677 Menu
->dwMenuData
= lpmi
->dwMenuData
;
678 if(lpmi
->fMask
& MIM_STYLE
)
679 Menu
->fFlags
^= (Menu
->fFlags
^ lpmi
->dwStyle
) & MNS_STYLE_MASK
;
680 if(lpmi
->fMask
& MIM_APPLYTOSUBMENUS
)
683 PITEM item
= Menu
->rgItems
;
684 for ( i
= Menu
->cItems
; i
; i
--, item
++)
686 if ( item
->spSubMenu
)
688 IntSetMenuInfo( item
->spSubMenu
, lpmi
);
692 if (sizeof(MENUINFO
) < lpmi
->cbSize
)
694 Menu
->iItem
= lpmi
->iItem
;
695 Menu
->cyMenu
= lpmi
->cyMenu
;
696 Menu
->cxMenu
= lpmi
->cxMenu
;
697 Menu
->spwndNotify
= lpmi
->spwndNotify
;
698 Menu
->cxTextAlign
= lpmi
->cxTextAlign
;
699 Menu
->iTop
= lpmi
->iTop
;
700 Menu
->iMaxTop
= lpmi
->iMaxTop
;
701 Menu
->dwArrowsOn
= lpmi
->dwArrowsOn
;
703 Menu
->TimeToHide
= lpmi
->TimeToHide
;
704 Menu
->hWnd
= lpmi
->Wnd
;
710 IntGetMenuItemInfo(PMENU Menu
, /* UNUSED PARAM!! */
711 PITEM MenuItem
, PROSMENUITEMINFO lpmii
)
715 if(lpmii
->fMask
& (MIIM_FTYPE
| MIIM_TYPE
))
717 lpmii
->fType
= MenuItem
->fType
;
719 if(lpmii
->fMask
& MIIM_BITMAP
)
721 lpmii
->hbmpItem
= MenuItem
->hbmp
;
723 if(lpmii
->fMask
& MIIM_CHECKMARKS
)
725 lpmii
->hbmpChecked
= MenuItem
->hbmpChecked
;
726 lpmii
->hbmpUnchecked
= MenuItem
->hbmpUnchecked
;
728 if(lpmii
->fMask
& MIIM_DATA
)
730 lpmii
->dwItemData
= MenuItem
->dwItemData
;
732 if(lpmii
->fMask
& MIIM_ID
)
734 lpmii
->wID
= MenuItem
->wID
;
736 if(lpmii
->fMask
& MIIM_STATE
)
738 lpmii
->fState
= MenuItem
->fState
;
740 if(lpmii
->fMask
& MIIM_SUBMENU
)
742 lpmii
->hSubMenu
= MenuItem
->spSubMenu
? MenuItem
->spSubMenu
->head
.h
: NULL
;
745 if ((lpmii
->fMask
& MIIM_STRING
) ||
746 ((lpmii
->fMask
& MIIM_TYPE
) && (MENU_ITEM_TYPE(lpmii
->fType
) == MF_STRING
)))
748 if (lpmii
->dwTypeData
== NULL
)
750 lpmii
->cch
= MenuItem
->lpstr
.Length
/ sizeof(WCHAR
);
753 { //// lpmii->lpstr can be read in user mode!!!!
754 Status
= MmCopyToCaller(lpmii
->dwTypeData
, MenuItem
->lpstr
.Buffer
,
755 min(lpmii
->cch
* sizeof(WCHAR
),
756 MenuItem
->lpstr
.MaximumLength
));
757 if (! NT_SUCCESS(Status
))
759 SetLastNtError(Status
);
765 if (sizeof(ROSMENUITEMINFO
) == lpmii
->cbSize
)
767 lpmii
->Rect
.left
= MenuItem
->xItem
;
768 lpmii
->Rect
.top
= MenuItem
->yItem
;
769 lpmii
->Rect
.right
= MenuItem
->cxItem
; // Do this for now......
770 lpmii
->Rect
.bottom
= MenuItem
->cyItem
;
771 lpmii
->dxTab
= MenuItem
->dxTab
;
772 lpmii
->lpstr
= MenuItem
->lpstr
.Buffer
;
773 lpmii
->maxBmpSize
.cx
= MenuItem
->cxBmp
;
774 lpmii
->maxBmpSize
.cy
= MenuItem
->cyBmp
;
781 IntSetMenuItemInfo(PMENU MenuObject
, PITEM MenuItem
, PROSMENUITEMINFO lpmii
, PUNICODE_STRING lpstr
)
784 BOOL circref
= FALSE
;
786 if(!MenuItem
|| !MenuObject
|| !lpmii
)
790 if ( lpmii
->fMask
& MIIM_FTYPE
)
792 MenuItem
->fType
&= ~MENUITEMINFO_TYPE_MASK
;
793 MenuItem
->fType
|= lpmii
->fType
& MENUITEMINFO_TYPE_MASK
;
795 if (lpmii
->fMask
& MIIM_TYPE
)
797 #if 0 //// Done in User32.
798 if (lpmii
->fMask
& ( MIIM_STRING
| MIIM_FTYPE
| MIIM_BITMAP
))
800 ERR("IntSetMenuItemInfo: Invalid combination of fMask bits used\n");
801 KeRosDumpStackFrames(NULL
, 20);
802 /* This does not happen on Win9x/ME */
803 SetLastNtError( ERROR_INVALID_PARAMETER
);
808 * Delete the menu item type when changing type from
811 if (MenuItem
->fType
!= lpmii
->fType
&&
812 MENU_ITEM_TYPE(MenuItem
->fType
) == MFT_STRING
)
814 FreeMenuText(MenuObject
,MenuItem
);
815 RtlInitUnicodeString(&MenuItem
->lpstr
, NULL
);
816 MenuItem
->Xlpstr
= NULL
;
818 if(lpmii
->fType
& MFT_BITMAP
)
821 MenuItem
->hbmp
= lpmii
->hbmpItem
;
823 { /* Win 9x/Me stuff */
824 MenuItem
->hbmp
= (HBITMAP
)((ULONG_PTR
)(LOWORD(lpmii
->dwTypeData
)));
826 lpmii
->dwTypeData
= 0;
829 if(lpmii
->fMask
& MIIM_BITMAP
)
831 MenuItem
->hbmp
= lpmii
->hbmpItem
;
832 if (MenuItem
->hbmp
<= HBMMENU_POPUP_MINIMIZE
&& MenuItem
->hbmp
>= HBMMENU_CALLBACK
)
833 MenuItem
->fState
|= MFS_HBMMENUBMP
;
835 MenuItem
->fState
&= ~MFS_HBMMENUBMP
;
837 if(lpmii
->fMask
& MIIM_CHECKMARKS
)
839 MenuItem
->hbmpChecked
= lpmii
->hbmpChecked
;
840 MenuItem
->hbmpUnchecked
= lpmii
->hbmpUnchecked
;
842 if(lpmii
->fMask
& MIIM_DATA
)
844 MenuItem
->dwItemData
= lpmii
->dwItemData
;
846 if(lpmii
->fMask
& MIIM_ID
)
848 MenuItem
->wID
= lpmii
->wID
;
850 if(lpmii
->fMask
& MIIM_STATE
)
852 /* Remove MFS_DEFAULT flag from all other menu items if this item
853 has the MFS_DEFAULT state */
854 if(lpmii
->fState
& MFS_DEFAULT
)
855 UserSetMenuDefaultItem(MenuObject
, -1, 0);
856 /* Update the menu item state flags */
857 UpdateMenuItemState(MenuItem
->fState
, lpmii
->fState
);
860 if(lpmii
->fMask
& MIIM_SUBMENU
)
864 SubMenuObject
= UserGetMenuObject(lpmii
->hSubMenu
);
865 if ( SubMenuObject
&& !(UserObjectInDestroy(lpmii
->hSubMenu
)) )
867 //// wine Bug 12171 : Adding Popup Menu to itself! Could create endless loops.
869 if (MenuObject
== SubMenuObject
)
872 ERR("Pop Up Menu Double Trouble!\n");
873 SubMenuObject
= IntCreateMenu(&hMenu
, FALSE
); // It will be marked.
874 if (!SubMenuObject
) return FALSE
;
875 IntReleaseMenuObject(SubMenuObject
); // This will be referenced again after insertion.
878 if ( MENU_depth( SubMenuObject
, 0) > MAXMENUDEPTH
)
880 ERR( "Loop detected in menu hierarchy or maximum menu depth exceeded!\n");
881 if (circref
) IntDestroyMenuObject(SubMenuObject
, FALSE
, TRUE
);
884 /* Make sure the submenu is marked as a popup menu */
885 SubMenuObject
->fFlags
|= MNF_POPUP
;
886 // Now fix the test_subpopup_locked_by_menu tests....
887 if (MenuItem
->spSubMenu
) IntReleaseMenuObject(MenuItem
->spSubMenu
);
888 MenuItem
->spSubMenu
= SubMenuObject
;
889 UserReferenceObject(SubMenuObject
);
893 EngSetLastError( ERROR_INVALID_PARAMETER
);
898 { // If submenu just dereference it.
899 if (MenuItem
->spSubMenu
) IntReleaseMenuObject(MenuItem
->spSubMenu
);
900 MenuItem
->spSubMenu
= NULL
;
904 if ((lpmii
->fMask
& MIIM_STRING
) ||
905 ((lpmii
->fMask
& MIIM_TYPE
) && (MENU_ITEM_TYPE(lpmii
->fType
) == MF_STRING
)))
907 /* free the string when used */
908 FreeMenuText(MenuObject
,MenuItem
);
909 RtlInitUnicodeString(&MenuItem
->lpstr
, NULL
);
910 MenuItem
->Xlpstr
= NULL
;
912 if(lpmii
->dwTypeData
&& lpmii
->cch
&& lpstr
&& lpstr
->Buffer
)
914 UNICODE_STRING Source
;
916 Source
.Length
= Source
.MaximumLength
= lpmii
->cch
* sizeof(WCHAR
);
917 Source
.Buffer
= lpmii
->dwTypeData
;
919 MenuItem
->lpstr
.Buffer
= DesktopHeapAlloc( MenuObject
->head
.rpdesk
, Source
.Length
+ sizeof(WCHAR
));
920 if(MenuItem
->lpstr
.Buffer
!= NULL
)
922 MenuItem
->lpstr
.Length
= 0;
923 MenuItem
->lpstr
.MaximumLength
= Source
.Length
+ sizeof(WCHAR
);
924 RtlCopyUnicodeString(&MenuItem
->lpstr
, &Source
);
925 MenuItem
->lpstr
.Buffer
[MenuItem
->lpstr
.Length
/ sizeof(WCHAR
)] = 0;
927 MenuItem
->cch
= MenuItem
->lpstr
.Length
/ sizeof(WCHAR
);
928 MenuItem
->Xlpstr
= (USHORT
*)MenuItem
->lpstr
.Buffer
;
933 if( !(MenuObject
->fFlags
& MNF_SYSMENU
) &&
935 !lpmii
->dwTypeData
&&
936 !(MenuItem
->fType
& MFT_OWNERDRAW
) &&
938 MenuItem
->fType
|= MFT_SEPARATOR
;
940 if (sizeof(ROSMENUITEMINFO
) == lpmii
->cbSize
)
942 MenuItem
->xItem
= lpmii
->Rect
.left
;
943 MenuItem
->yItem
= lpmii
->Rect
.top
;
944 MenuItem
->cxItem
= lpmii
->Rect
.right
; // Do this for now......
945 MenuItem
->cyItem
= lpmii
->Rect
.bottom
;
946 MenuItem
->dxTab
= lpmii
->dxTab
;
947 lpmii
->lpstr
= MenuItem
->lpstr
.Buffer
; /* Send back new allocated string or zero */
948 MenuItem
->cxBmp
= lpmii
->maxBmpSize
.cx
;
949 MenuItem
->cyBmp
= lpmii
->maxBmpSize
.cy
;
957 IntEnableMenuItem(PMENU MenuObject
, UINT uIDEnableItem
, UINT uEnable
)
962 if (!(MenuItem
= MENU_FindItem( &MenuObject
, &uIDEnableItem
, uEnable
))) return (UINT
)-1;
964 res
= MenuItem
->fState
& (MF_GRAYED
| MF_DISABLED
);
966 MenuItem
->fState
^= (res
^ uEnable
) & (MF_GRAYED
| MF_DISABLED
);
968 /* If the close item in the system menu change update the close button */
969 if((MenuItem
->wID
== SC_CLOSE
) && (res
!= uEnable
))
971 if (MenuObject
->fFlags
& MNF_SYSSUBMENU
&& MenuObject
->spwndNotify
!= 0)
973 RECTL rc
= MenuObject
->spwndNotify
->rcWindow
;
975 /* Refresh the frame to reflect the change */
976 IntMapWindowPoints(0, MenuObject
->spwndNotify
, (POINT
*)&rc
, 2);
978 co_UserRedrawWindow(MenuObject
->spwndNotify
, &rc
, 0, RDW_FRAME
| RDW_INVALIDATE
| RDW_NOCHILDREN
);
985 IntCheckMenuItem(PMENU MenuObject
, UINT uIDCheckItem
, UINT uCheck
)
990 if (!(MenuItem
= MENU_FindItem( &MenuObject
, &uIDCheckItem
, uCheck
))) return -1;
992 res
= (DWORD
)(MenuItem
->fState
& MF_CHECKED
);
994 MenuItem
->fState
^= (res
^ uCheck
) & MF_CHECKED
;
1000 IntHiliteMenuItem(PWND WindowObject
,
1007 if (!(MenuItem
= MENU_FindItem( &MenuObject
, &uItemHilite
, uHilite
))) return FALSE
;
1009 if (uHilite
& MF_HILITE
)
1011 MenuItem
->fState
|= MF_HILITE
;
1015 MenuItem
->fState
&= ~MF_HILITE
;
1017 /* FIXME: Update the window's menu */
1019 return TRUE
; // Always returns true!!!!
1023 UserSetMenuDefaultItem(PMENU MenuObject
, UINT uItem
, UINT fByPos
)
1026 PITEM MenuItem
= MenuObject
->rgItems
;
1028 if (!MenuItem
) return FALSE
;
1030 /* reset all default-item flags */
1031 for (i
= 0; MenuItem
, i
< MenuObject
->cItems
; i
++, MenuItem
++)
1033 MenuItem
->fState
&= ~MFS_DEFAULT
;
1036 /* no default item */
1037 if(uItem
== (UINT
)-1)
1041 MenuItem
= MenuObject
->rgItems
;
1044 if ( uItem
>= MenuObject
->cItems
) return FALSE
;
1045 MenuItem
[uItem
].fState
|= MFS_DEFAULT
;
1050 for (i
= 0; MenuItem
, i
< MenuObject
->cItems
; i
++, MenuItem
++)
1052 if (MenuItem
->wID
== uItem
)
1054 MenuItem
->fState
|= MFS_DEFAULT
;
1065 IntGetMenuDefaultItem(PMENU MenuObject
, UINT fByPos
, UINT gmdiFlags
, DWORD
*gismc
)
1068 PITEM MenuItem
= MenuObject
->rgItems
;
1071 if (!MenuItem
) return -1;
1073 while ( !( MenuItem
->fState
& MFS_DEFAULT
) )
1076 if (i
>= MenuObject
->cItems
) return -1;
1079 /* default: don't return disabled items */
1080 if ( (!(GMDI_USEDISABLED
& gmdiFlags
)) && (MenuItem
->fState
& MFS_DISABLED
)) return -1;
1082 /* search rekursiv when needed */
1083 if ( (MenuItem
->fType
& MF_POPUP
) && (gmdiFlags
& GMDI_GOINTOPOPUPS
) && MenuItem
->spSubMenu
)
1087 ret
= IntGetMenuDefaultItem( MenuItem
->spSubMenu
, fByPos
, gmdiFlags
, gismc
);
1089 if ( -1 != ret
) return ret
;
1091 /* when item not found in submenu, return the popup item */
1093 return ( fByPos
) ? i
: MenuItem
->wID
;
1097 co_IntInitTracking(PWND Window
, PMENU Menu
, BOOL Popup
,
1100 /* FIXME: Hide caret */
1102 if(!(Flags
& TPM_NONOTIFY
))
1103 co_IntSendMessage(Window
->head
.h
, WM_SETCURSOR
, (WPARAM
)Window
->head
.h
, HTCAPTION
);
1105 /* FIXME: Send WM_SETCURSOR message */
1107 if(!(Flags
& TPM_NONOTIFY
))
1108 co_IntSendMessage(Window
->head
.h
, WM_INITMENU
, (WPARAM
)Menu
->head
.h
, 0);
1112 co_IntExitTracking(PWND Window
, PMENU Menu
, BOOL Popup
,
1115 if(!(Flags
& TPM_NONOTIFY
))
1116 co_IntSendMessage(Window
->head
.h
, WM_EXITMENULOOP
, 0 /* FIXME */, 0);
1118 /* FIXME: Show caret again */
1122 IntTrackMenu(PMENU Menu
, PWND Window
, INT x
, INT y
,
1129 co_IntTrackPopupMenu(PMENU Menu
, PWND Window
,
1130 UINT Flags
, POINT
*Pos
, UINT MenuPos
, RECTL
*ExcludeRect
)
1132 co_IntInitTracking(Window
, Menu
, TRUE
, Flags
);
1134 co_IntExitTracking(Window
, Menu
, TRUE
, Flags
);
1140 * Internal function. Called when the process is destroyed to free the remaining menu handles.
1143 IntCleanupMenus(struct _EPROCESS
*Process
, PPROCESSINFO Win32Process
)
1145 PEPROCESS CurrentProcess
;
1148 CurrentProcess
= PsGetCurrentProcess();
1149 if (CurrentProcess
!= Process
)
1151 KeAttachProcess(&Process
->Pcb
);
1154 while (!IsEmptyList(&Win32Process
->MenuListHead
))
1156 MenuObject
= CONTAINING_RECORD(Win32Process
->MenuListHead
.Flink
, MENU
, ListEntry
);
1157 TRACE("Menus are stuck on the process list!\n");
1158 IntDestroyMenuObject(MenuObject
, FALSE
, TRUE
);
1161 if (CurrentProcess
!= Process
)
1169 intGetTitleBarInfo(PWND pWindowObject
, PTITLEBARINFO bti
)
1173 DWORD dwExStyle
= 0;
1174 BOOLEAN retValue
= TRUE
;
1176 if (bti
->cbSize
== sizeof(TITLEBARINFO
))
1178 RtlZeroMemory(&bti
->rgstate
[0],sizeof(DWORD
)*(CCHILDREN_TITLEBAR
+1));
1180 bti
->rgstate
[0] = STATE_SYSTEM_FOCUSABLE
;
1182 dwStyle
= pWindowObject
->style
;
1183 dwExStyle
= pWindowObject
->ExStyle
;
1185 bti
->rcTitleBar
.top
= 0;
1186 bti
->rcTitleBar
.left
= 0;
1187 bti
->rcTitleBar
.right
= pWindowObject
->rcWindow
.right
- pWindowObject
->rcWindow
.left
;
1188 bti
->rcTitleBar
.bottom
= pWindowObject
->rcWindow
.bottom
- pWindowObject
->rcWindow
.top
;
1190 /* Is it iconiced ? */
1191 if ((dwStyle
& WS_ICONIC
)!=WS_ICONIC
)
1193 /* Remove frame from rectangle */
1194 if (HAS_THICKFRAME( dwStyle
, dwExStyle
))
1196 /* FIXME: Note this value should exists in pWindowObject for UserGetSystemMetrics(SM_CXFRAME) and UserGetSystemMetrics(SM_CYFRAME) */
1197 RECTL_vInflateRect( &bti
->rcTitleBar
, -UserGetSystemMetrics(SM_CXFRAME
), -UserGetSystemMetrics(SM_CYFRAME
) );
1199 else if (HAS_DLGFRAME( dwStyle
, dwExStyle
))
1201 /* FIXME: Note this value should exists in pWindowObject for UserGetSystemMetrics(SM_CXDLGFRAME) and UserGetSystemMetrics(SM_CYDLGFRAME) */
1202 RECTL_vInflateRect( &bti
->rcTitleBar
, -UserGetSystemMetrics(SM_CXDLGFRAME
), -UserGetSystemMetrics(SM_CYDLGFRAME
));
1204 else if (HAS_THINFRAME( dwStyle
, dwExStyle
))
1206 /* FIXME: Note this value should exists in pWindowObject for UserGetSystemMetrics(SM_CXBORDER) and UserGetSystemMetrics(SM_CYBORDER) */
1207 RECTL_vInflateRect( &bti
->rcTitleBar
, -UserGetSystemMetrics(SM_CXBORDER
), -UserGetSystemMetrics(SM_CYBORDER
) );
1210 /* We have additional border information if the window
1211 * is a child (but not an MDI child) */
1212 if ( (dwStyle
& WS_CHILD
) &&
1213 ((dwExStyle
& WS_EX_MDICHILD
) == 0 ) )
1215 if (dwExStyle
& WS_EX_CLIENTEDGE
)
1217 /* FIXME: Note this value should exists in pWindowObject for UserGetSystemMetrics(SM_CXEDGE) and UserGetSystemMetrics(SM_CYEDGE) */
1218 RECTL_vInflateRect (&bti
->rcTitleBar
, -UserGetSystemMetrics(SM_CXEDGE
), -UserGetSystemMetrics(SM_CYEDGE
));
1221 if (dwExStyle
& WS_EX_STATICEDGE
)
1223 /* FIXME: Note this value should exists in pWindowObject for UserGetSystemMetrics(SM_CXBORDER) and UserGetSystemMetrics(SM_CYBORDER) */
1224 RECTL_vInflateRect (&bti
->rcTitleBar
, -UserGetSystemMetrics(SM_CXBORDER
), -UserGetSystemMetrics(SM_CYBORDER
));
1229 bti
->rcTitleBar
.top
+= pWindowObject
->rcWindow
.top
;
1230 bti
->rcTitleBar
.left
+= pWindowObject
->rcWindow
.left
;
1231 bti
->rcTitleBar
.right
+= pWindowObject
->rcWindow
.left
;
1233 bti
->rcTitleBar
.bottom
= bti
->rcTitleBar
.top
;
1234 if (dwExStyle
& WS_EX_TOOLWINDOW
)
1236 /* FIXME: Note this value should exists in pWindowObject for UserGetSystemMetrics(SM_CYSMCAPTION) */
1237 bti
->rcTitleBar
.bottom
+= UserGetSystemMetrics(SM_CYSMCAPTION
);
1241 /* FIXME: Note this value should exists in pWindowObject for UserGetSystemMetrics(SM_CYCAPTION) and UserGetSystemMetrics(SM_CXSIZE) */
1242 bti
->rcTitleBar
.bottom
+= UserGetSystemMetrics(SM_CYCAPTION
);
1243 bti
->rcTitleBar
.left
+= UserGetSystemMetrics(SM_CXSIZE
);
1246 if (dwStyle
& WS_CAPTION
)
1248 bti
->rgstate
[1] = STATE_SYSTEM_INVISIBLE
;
1249 if (dwStyle
& WS_SYSMENU
)
1251 if (!(dwStyle
& (WS_MINIMIZEBOX
|WS_MAXIMIZEBOX
)))
1253 bti
->rgstate
[2] = STATE_SYSTEM_INVISIBLE
;
1254 bti
->rgstate
[3] = STATE_SYSTEM_INVISIBLE
;
1258 if (!(dwStyle
& WS_MINIMIZEBOX
))
1260 bti
->rgstate
[2] = STATE_SYSTEM_UNAVAILABLE
;
1262 if (!(dwStyle
& WS_MAXIMIZEBOX
))
1264 bti
->rgstate
[3] = STATE_SYSTEM_UNAVAILABLE
;
1268 if (!(dwExStyle
& WS_EX_CONTEXTHELP
))
1270 bti
->rgstate
[4] = STATE_SYSTEM_INVISIBLE
;
1272 if (pWindowObject
->pcls
->style
& CS_NOCLOSE
)
1274 bti
->rgstate
[5] = STATE_SYSTEM_UNAVAILABLE
;
1279 bti
->rgstate
[2] = STATE_SYSTEM_INVISIBLE
;
1280 bti
->rgstate
[3] = STATE_SYSTEM_INVISIBLE
;
1281 bti
->rgstate
[4] = STATE_SYSTEM_INVISIBLE
;
1282 bti
->rgstate
[5] = STATE_SYSTEM_INVISIBLE
;
1287 bti
->rgstate
[0] |= STATE_SYSTEM_INVISIBLE
;
1292 EngSetLastError(ERROR_INVALID_PARAMETER
);
1304 LPCMENUITEMINFOW UnsafeItemInfo
,
1305 PUNICODE_STRING lpstr
)
1308 ROSMENUITEMINFO ItemInfo
;
1310 /* Try to copy the whole MENUITEMINFOW structure */
1311 Status
= MmCopyFromCaller(&ItemInfo
, UnsafeItemInfo
, sizeof(MENUITEMINFOW
));
1312 if (NT_SUCCESS(Status
))
1314 if (sizeof(MENUITEMINFOW
) != ItemInfo
.cbSize
1315 && FIELD_OFFSET(MENUITEMINFOW
, hbmpItem
) != ItemInfo
.cbSize
)
1317 EngSetLastError(ERROR_INVALID_PARAMETER
);
1320 return IntInsertMenuItem(Menu
, uItem
, fByPosition
, &ItemInfo
, lpstr
);
1323 /* Try to copy without last field (not present in older versions) */
1324 Status
= MmCopyFromCaller(&ItemInfo
, UnsafeItemInfo
, FIELD_OFFSET(MENUITEMINFOW
, hbmpItem
));
1325 if (NT_SUCCESS(Status
))
1327 if (FIELD_OFFSET(MENUITEMINFOW
, hbmpItem
) != ItemInfo
.cbSize
)
1329 EngSetLastError(ERROR_INVALID_PARAMETER
);
1332 ItemInfo
.hbmpItem
= (HBITMAP
)0;
1333 return IntInsertMenuItem(Menu
, uItem
, fByPosition
, &ItemInfo
, lpstr
);
1336 SetLastNtError(Status
);
1340 UINT FASTCALL
IntGetMenuState( HMENU hMenu
, UINT uId
, UINT uFlags
)
1345 if (!(MenuObject
= UserGetMenuObject(hMenu
)))
1350 if (!(pItem
= MENU_FindItem( &MenuObject
, &uId
, uFlags
))) return -1;
1352 if (pItem
->spSubMenu
)
1354 return (pItem
->spSubMenu
->cItems
<< 8) | ((pItem
->fState
|pItem
->fType
) & 0xff);
1357 return (pItem
->fType
| pItem
->fState
);
1360 HMENU FASTCALL
IntGetSubMenu( HMENU hMenu
, int nPos
)
1365 if (!(MenuObject
= UserGetMenuObject(hMenu
)))
1370 if (!(pItem
= MENU_FindItem( &MenuObject
, (UINT
*)&nPos
, MF_BYPOSITION
))) return NULL
;
1372 if (pItem
->spSubMenu
)
1374 HMENU hsubmenu
= UserHMGetHandle(pItem
->spSubMenu
);
1380 UINT FASTCALL
IntFindSubMenu(HMENU
*hMenu
, HMENU hSubTarget
)
1387 if (((*hMenu
)==(HMENU
)0xffff) ||(!(menu
= UserGetMenuObject(*hMenu
))))
1388 return NO_SELECTED_ITEM
;
1390 item
= menu
->rgItems
;
1391 for (i
= 0; i
< menu
->cItems
; i
++, item
++)
1393 if (!item
->spSubMenu
)
1397 hSubMenu
= UserHMGetHandle(item
->spSubMenu
);
1398 if (hSubMenu
== hSubTarget
)
1404 HMENU hsubmenu
= hSubMenu
;
1405 UINT pos
= IntFindSubMenu( &hsubmenu
, hSubTarget
);
1406 if (pos
!= NO_SELECTED_ITEM
)
1414 return NO_SELECTED_ITEM
;
1418 HMENU FASTCALL
UserCreateMenu(BOOL PopupMenu
)
1420 PWINSTATION_OBJECT WinStaObject
;
1424 PEPROCESS CurrentProcess
= PsGetCurrentProcess();
1426 if (gpepCSRSS
!= CurrentProcess
)
1429 * gpepCSRSS does not have a Win32WindowStation
1432 Status
= IntValidateWindowStationHandle(CurrentProcess
->Win32WindowStation
,
1437 if (!NT_SUCCESS(Status
))
1439 ERR("Validation of window station handle (%p) failed\n",
1440 CurrentProcess
->Win32WindowStation
);
1441 SetLastNtError(Status
);
1444 Menu
= IntCreateMenu(&Handle
, !PopupMenu
);
1445 if (Menu
&& Menu
->head
.rpdesk
->rpwinstaParent
!= WinStaObject
)
1447 ERR("Desktop Window Station does not match Process one!\n");
1449 ObDereferenceObject(WinStaObject
);
1453 Menu
= IntCreateMenu(&Handle
, !PopupMenu
);
1456 if (Menu
) UserDereferenceObject(Menu
);
1457 return (HMENU
)Handle
;
1465 PROSMENUITEMINFO ItemInfo
,
1467 PUNICODE_STRING lpstr
)
1472 if (!(MenuItem
= MENU_FindItem( &Menu
, &Item
, (ByPosition
? MF_BYPOSITION
: MF_BYCOMMAND
) )))
1474 EngSetLastError(ERROR_MENU_ITEM_NOT_FOUND
);
1479 Ret
= IntSetMenuItemInfo(Menu
, MenuItem
, ItemInfo
, lpstr
);
1483 Ret
= IntGetMenuItemInfo(Menu
, MenuItem
, ItemInfo
);
1493 PROSMENUITEMINFO UnsafeItemInfo
,
1495 PUNICODE_STRING lpstr
)
1498 ROSMENUITEMINFO ItemInfo
;
1503 Status
= MmCopyFromCaller(&Size
, &UnsafeItemInfo
->cbSize
, sizeof(UINT
));
1504 if (! NT_SUCCESS(Status
))
1506 SetLastNtError(Status
);
1509 if (sizeof(MENUITEMINFOW
) != Size
1510 && FIELD_OFFSET(MENUITEMINFOW
, hbmpItem
) != Size
1511 && sizeof(ROSMENUITEMINFO
) != Size
)
1513 EngSetLastError(ERROR_INVALID_PARAMETER
);
1516 Status
= MmCopyFromCaller(&ItemInfo
, UnsafeItemInfo
, Size
);
1517 if (! NT_SUCCESS(Status
))
1519 SetLastNtError(Status
);
1522 /* If this is a pre-0x0500 _WIN32_WINNT MENUITEMINFOW, you can't
1524 if (FIELD_OFFSET(MENUITEMINFOW
, hbmpItem
) == Size
1525 && 0 != (ItemInfo
.fMask
& MIIM_BITMAP
))
1527 EngSetLastError(ERROR_INVALID_PARAMETER
);
1531 if (!(MenuItem
= MENU_FindItem( &Menu
, &Item
, (ByPosition
? MF_BYPOSITION
: MF_BYCOMMAND
) )))
1533 EngSetLastError(ERROR_MENU_ITEM_NOT_FOUND
);
1539 Ret
= IntSetMenuItemInfo(Menu
, MenuItem
, &ItemInfo
, lpstr
);
1543 Ret
= IntGetMenuItemInfo(Menu
, MenuItem
, &ItemInfo
);
1546 Status
= MmCopyToCaller(UnsafeItemInfo
, &ItemInfo
, Size
);
1547 if (! NT_SUCCESS(Status
))
1549 SetLastNtError(Status
);
1561 PROSMENUINFO UnsafeMenuInfo
,
1567 ROSMENUINFO MenuInfo
;
1569 Status
= MmCopyFromCaller(&Size
, &UnsafeMenuInfo
->cbSize
, sizeof(DWORD
));
1570 if (! NT_SUCCESS(Status
))
1572 SetLastNtError(Status
);
1575 if(Size
< sizeof(MENUINFO
) || sizeof(ROSMENUINFO
) < Size
)
1577 EngSetLastError(ERROR_INVALID_PARAMETER
);
1580 Status
= MmCopyFromCaller(&MenuInfo
, UnsafeMenuInfo
, Size
);
1581 if (! NT_SUCCESS(Status
))
1583 SetLastNtError(Status
);
1590 Res
= IntSetMenuInfo(Menu
, &MenuInfo
);
1595 Res
= IntGetMenuInfo(Menu
, &MenuInfo
);
1598 Status
= MmCopyToCaller(UnsafeMenuInfo
, &MenuInfo
, Size
);
1599 if (! NT_SUCCESS(Status
))
1601 SetLastNtError(Status
);
1611 MENU_AdjustMenuItemRect(PMENU menu
, PRECTL rect
)
1613 if (menu
->dwArrowsOn
)
1615 UINT arrow_bitmap_height
;
1617 //GetObjectW(get_up_arrow_bitmap(), sizeof(bmp), &bmp);
1618 arrow_bitmap_height
= gpsi
->oembmi
[65].cy
; ///// Menu up arrow! OBM_UPARROW DFCS_MENUARROWUP
1619 //arrow_bitmap_height = bmp.bmHeight;
1620 rect
->top
+= arrow_bitmap_height
- menu
->iTop
;
1621 rect
->bottom
+= arrow_bitmap_height
- menu
->iTop
;
1637 HWND hWnd
= Menu
->hWnd
;
1638 if (!(pWnd
= UserGetWindowObject(hWnd
))) return FALSE
;
1641 if ((MenuItem
= MENU_FindItem (&Menu
, &uItem
, MF_BYPOSITION
)))
1643 Rect
->left
= MenuItem
->xItem
;
1644 Rect
->top
= MenuItem
->yItem
;
1645 Rect
->right
= MenuItem
->cxItem
; // Do this for now......
1646 Rect
->bottom
= MenuItem
->cyItem
;
1650 ERR("Failed Item Lookup! %d\n", uItem
);
1654 if (Menu
->fFlags
& MNF_POPUP
)
1656 XMove
= pWnd
->rcClient
.left
;
1657 YMove
= pWnd
->rcClient
.top
;
1661 XMove
= pWnd
->rcWindow
.left
;
1662 YMove
= pWnd
->rcWindow
.top
;
1665 Rect
->left
+= XMove
;
1667 Rect
->right
+= XMove
;
1668 Rect
->bottom
+= YMove
;
1673 PMENU FASTCALL
MENU_GetSystemMenu(PWND Window
, PMENU Popup
)
1675 PMENU Menu
, NewMenu
= NULL
, SysMenu
= NULL
;
1676 HMENU hSysMenu
, hNewMenu
= NULL
;
1677 ROSMENUITEMINFO ItemInfoSet
= {0};
1678 ROSMENUITEMINFO ItemInfo
= {0};
1679 UNICODE_STRING MenuName
;
1681 hSysMenu
= UserCreateMenu(FALSE
);
1682 if (NULL
== hSysMenu
)
1686 SysMenu
= IntGetMenuObject(hSysMenu
);
1687 if (NULL
== SysMenu
)
1689 UserDestroyMenu(hSysMenu
);
1693 SysMenu
->fFlags
|= MNF_SYSMENU
;
1694 SysMenu
->hWnd
= Window
->head
.h
;
1698 //hNewMenu = co_IntLoadSysMenuTemplate();
1699 if ( Window
->ExStyle
& WS_EX_MDICHILD
)
1701 RtlInitUnicodeString( &MenuName
, L
"SYSMENUMDI");
1702 hNewMenu
= co_IntCallLoadMenu( hModClient
, &MenuName
);
1706 RtlInitUnicodeString( &MenuName
, L
"SYSMENU");
1707 hNewMenu
= co_IntCallLoadMenu( hModClient
, &MenuName
);
1708 //ERR("%wZ\n",&MenuName);
1713 IntReleaseMenuObject(SysMenu
);
1714 UserDestroyMenu(hSysMenu
);
1717 Menu
= IntGetMenuObject(hNewMenu
);
1720 IntReleaseMenuObject(SysMenu
);
1721 UserDestroyMenu(hSysMenu
);
1725 // Do the rest in here.
1727 Menu
->fFlags
|= MNS_CHECKORBMP
| MNF_SYSMENU
| MNF_POPUP
;
1729 ItemInfoSet
.cbSize
= sizeof( MENUITEMINFOW
);
1730 ItemInfoSet
.fMask
= MIIM_BITMAP
;
1731 ItemInfoSet
.hbmpItem
= HBMMENU_POPUP_CLOSE
;
1732 IntMenuItemInfo(Menu
, SC_CLOSE
, FALSE
, &ItemInfoSet
, TRUE
, NULL
);
1733 ItemInfoSet
.hbmpItem
= HBMMENU_POPUP_RESTORE
;
1734 IntMenuItemInfo(Menu
, SC_RESTORE
, FALSE
, &ItemInfoSet
, TRUE
, NULL
);
1735 ItemInfoSet
.hbmpItem
= HBMMENU_POPUP_MAXIMIZE
;
1736 IntMenuItemInfo(Menu
, SC_MAXIMIZE
, FALSE
, &ItemInfoSet
, TRUE
, NULL
);
1737 ItemInfoSet
.hbmpItem
= HBMMENU_POPUP_MINIMIZE
;
1738 IntMenuItemInfo(Menu
, SC_MINIMIZE
, FALSE
, &ItemInfoSet
, TRUE
, NULL
);
1740 NewMenu
= IntCloneMenu(Menu
);
1742 IntReleaseMenuObject(NewMenu
);
1743 UserSetMenuDefaultItem(NewMenu
, SC_CLOSE
, FALSE
);
1745 IntDestroyMenuObject(Menu
, FALSE
, TRUE
);
1753 NewMenu
->fFlags
|= MNF_SYSMENU
| MNF_POPUP
;
1755 if (Window
->pcls
->style
& CS_NOCLOSE
)
1756 IntRemoveMenuItem(NewMenu
, SC_CLOSE
, MF_BYCOMMAND
, TRUE
);
1758 ItemInfo
.cbSize
= sizeof(MENUITEMINFOW
);
1759 ItemInfo
.fMask
= MIIM_FTYPE
| MIIM_STRING
| MIIM_STATE
| MIIM_SUBMENU
;
1761 ItemInfo
.fState
= MFS_ENABLED
;
1762 ItemInfo
.dwTypeData
= NULL
;
1764 ItemInfo
.hSubMenu
= UserHMGetHandle(NewMenu
);
1765 IntInsertMenuItem(SysMenu
, (UINT
) -1, TRUE
, &ItemInfo
, NULL
);
1769 ERR("failed to load system menu!\n");
1774 IntGetSystemMenu(PWND Window
, BOOL bRevert
)
1780 if (Window
->SystemMenu
)
1782 Menu
= UserGetMenuObject(Window
->SystemMenu
);
1783 if (Menu
&& !(Menu
->fFlags
& MNF_SYSDESKMN
))
1785 IntDestroyMenuObject(Menu
, TRUE
, TRUE
);
1786 Window
->SystemMenu
= NULL
;
1792 Menu
= Window
->SystemMenu
? UserGetMenuObject(Window
->SystemMenu
) : NULL
;
1793 if ((!Window
->SystemMenu
|| Menu
->fFlags
& MNF_SYSDESKMN
) && Window
->style
& WS_SYSMENU
)
1795 Menu
= MENU_GetSystemMenu(Window
, NULL
);
1796 Window
->SystemMenu
= Menu
? UserHMGetHandle(Menu
) : NULL
;
1800 if (Window
->SystemMenu
)
1802 HMENU hMenu
= IntGetSubMenu( Window
->SystemMenu
, 0);
1803 /* Store the dummy sysmenu handle to facilitate the refresh */
1804 /* of the close button if the SC_CLOSE item change */
1805 Menu
= UserGetMenuObject(hMenu
);
1808 Menu
->spwndNotify
= Window
;
1809 Menu
->fFlags
|= MNF_SYSSUBMENU
;
1817 IntSetSystemMenu(PWND Window
, PMENU Menu
)
1821 if (!(Window
->style
& WS_SYSMENU
)) return FALSE
;
1823 if (Window
->SystemMenu
)
1825 OldMenu
= UserGetMenuObject(Window
->SystemMenu
);
1828 OldMenu
->fFlags
&= ~MNF_SYSMENU
;
1829 IntDestroyMenuObject(OldMenu
, TRUE
, TRUE
);
1833 OldMenu
= MENU_GetSystemMenu(Window
, Menu
);
1835 { // Use spmenuSys too!
1836 Window
->SystemMenu
= UserHMGetHandle(OldMenu
);
1839 Window
->SystemMenu
= NULL
;
1841 if (Menu
&& Window
!= Menu
->spwndNotify
)
1843 Menu
->spwndNotify
= Window
;
1850 /* FUNCTIONS *****************************************************************/
1856 NtUserCheckMenuItem(
1862 DECLARE_RETURN(DWORD
);
1864 TRACE("Enter NtUserCheckMenuItem\n");
1865 UserEnterExclusive();
1867 if(!(Menu
= UserGetMenuObject(hMenu
)))
1872 RETURN( IntCheckMenuItem(Menu
, uIDCheckItem
, uCheck
));
1875 TRACE("Leave NtUserCheckMenuItem, ret=%lu\n",_ret_
);
1890 DECLARE_RETURN(BOOL
);
1892 TRACE("Enter NtUserDeleteMenu\n");
1893 UserEnterExclusive();
1895 if(!(Menu
= UserGetMenuObject(hMenu
)))
1900 RETURN( IntRemoveMenuItem(Menu
, uPosition
, uFlags
, TRUE
));
1903 TRACE("Leave NtUserDeleteMenu, ret=%i\n",_ret_
);
1909 * NtUserGetSystemMenu
1911 * The NtUserGetSystemMenu function allows the application to access the
1912 * window menu (also known as the system menu or the control menu) for
1913 * copying and modifying.
1917 * Handle to the window that will own a copy of the window menu.
1919 * Specifies the action to be taken. If this parameter is FALSE,
1920 * NtUserGetSystemMenu returns a handle to the copy of the window menu
1921 * currently in use. The copy is initially identical to the window menu
1922 * but it can be modified.
1923 * If this parameter is TRUE, GetSystemMenu resets the window menu back
1924 * to the default state. The previous window menu, if any, is destroyed.
1927 * If the bRevert parameter is FALSE, the return value is a handle to a
1928 * copy of the window menu. If the bRevert parameter is TRUE, the return
1936 NtUserGetSystemMenu(HWND hWnd
, BOOL bRevert
)
1940 DECLARE_RETURN(HMENU
);
1942 TRACE("Enter NtUserGetSystemMenu\n");
1945 if (!(Window
= UserGetWindowObject(hWnd
)))
1950 if (!(Menu
= IntGetSystemMenu(Window
, bRevert
)))
1955 RETURN(Menu
->head
.h
);
1958 TRACE("Leave NtUserGetSystemMenu, ret=%p\n", _ret_
);
1964 * NtUserSetSystemMenu
1971 NtUserSetSystemMenu(HWND hWnd
, HMENU hMenu
)
1973 BOOL Result
= FALSE
;
1976 DECLARE_RETURN(BOOL
);
1978 TRACE("Enter NtUserSetSystemMenu\n");
1979 UserEnterExclusive();
1981 if (!(Window
= UserGetWindowObject(hWnd
)))
1989 * Assign new menu handle and Up the Lock Count.
1991 if (!(Menu
= IntGetMenuObject(hMenu
)))
1996 Result
= IntSetSystemMenu(Window
, Menu
);
1999 EngSetLastError(ERROR_INVALID_MENU_HANDLE
);
2004 TRACE("Leave NtUserSetSystemMenu, ret=%i\n",_ret_
);
2013 NtUserGetTitleBarInfo(
2018 TITLEBARINFO bartitleinfo
;
2019 DECLARE_RETURN(BOOLEAN
);
2020 BOOLEAN retValue
= TRUE
;
2022 TRACE("Enter NtUserGetTitleBarInfo\n");
2023 UserEnterExclusive();
2025 /* Vaildate the windows handle */
2026 if (!(WindowObject
= UserGetWindowObject(hwnd
)))
2028 EngSetLastError(ERROR_INVALID_WINDOW_HANDLE
);
2034 /* Copy our usermode buffer bti to local buffer bartitleinfo */
2035 ProbeForRead(bti
, sizeof(TITLEBARINFO
), 1);
2036 RtlCopyMemory(&bartitleinfo
, bti
, sizeof(TITLEBARINFO
));
2038 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2040 /* Fail copy the data */
2041 EngSetLastError(ERROR_INVALID_PARAMETER
);
2046 /* Get the tile bar info */
2049 retValue
= intGetTitleBarInfo(WindowObject
, &bartitleinfo
);
2054 /* Copy our buffer to user mode buffer bti */
2055 ProbeForWrite(bti
, sizeof(TITLEBARINFO
), 1);
2056 RtlCopyMemory(bti
, &bartitleinfo
, sizeof(TITLEBARINFO
));
2058 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2060 /* Fail copy the data */
2061 EngSetLastError(ERROR_INVALID_PARAMETER
);
2071 TRACE("Leave NtUserGetTitleBarInfo, ret=%u\n",_ret_
);
2079 BOOL FASTCALL
UserDestroyMenu(HMENU hMenu
)
2082 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
2084 if(!(Menu
= UserGetMenuObject(hMenu
)))
2089 if (Menu
->head
.rpdesk
!= pti
->rpdesk
)
2091 EngSetLastError(ERROR_ACCESS_DENIED
);
2094 return IntDestroyMenuObject(Menu
, FALSE
, TRUE
);
2105 DECLARE_RETURN(BOOL
);
2107 TRACE("Enter NtUserDestroyMenu\n");
2108 UserEnterExclusive();
2110 if(!(Menu
= UserGetMenuObject(hMenu
)))
2114 if (Menu
->head
.rpdesk
!= gptiCurrent
->rpdesk
)
2116 EngSetLastError(ERROR_ACCESS_DENIED
);
2119 RETURN( IntDestroyMenuObject(Menu
, TRUE
, TRUE
));
2122 TRACE("Leave NtUserDestroyMenu, ret=%i\n",_ret_
);
2131 NtUserEnableMenuItem(
2137 DECLARE_RETURN(UINT
);
2139 TRACE("Enter NtUserEnableMenuItem\n");
2140 UserEnterExclusive();
2142 if(!(Menu
= UserGetMenuObject(hMenu
)))
2147 RETURN( IntEnableMenuItem(Menu
, uIDEnableItem
, uEnable
));
2150 TRACE("Leave NtUserEnableMenuItem, ret=%u\n",_ret_
);
2159 NtUserGetMenuBarInfo(
2169 NTSTATUS Status
= STATUS_SUCCESS
;
2171 DECLARE_RETURN(BOOL
);
2173 TRACE("Enter NtUserGetMenuBarInfo\n");
2176 if (!(pWnd
= UserGetWindowObject(hwnd
)))
2178 EngSetLastError(ERROR_INVALID_WINDOW_HANDLE
);
2185 if (!pWnd
->pcls
->fnid
)
2187 if (pWnd
->pcls
->fnid
!= FNID_MENU
)
2189 WARN("called on invalid window: %d\n", pWnd
->pcls
->fnid
);
2190 EngSetLastError(ERROR_INVALID_MENU_HANDLE
);
2193 // Windows does this! Wine checks for Atom and uses GetWindowLongPtrW.
2194 hMenu
= (HMENU
)co_IntSendMessage(hwnd
, MN_GETHMENU
, 0, 0);
2197 hMenu
= UlongToHandle(pWnd
->IDMenu
);
2200 if (!(pWnd
->style
& WS_SYSMENU
)) RETURN(FALSE
);
2201 Menu
= IntGetSystemMenu(pWnd
, FALSE
);
2202 hMenu
= Menu
->head
.h
;
2213 kmbi
.cbSize
= pmbi
->cbSize
;
2215 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2221 if (kmbi
.cbSize
!= sizeof(MENUBARINFO
))
2223 EngSetLastError(ERROR_INVALID_PARAMETER
);
2227 if (!Menu
) Menu
= UserGetMenuObject(hMenu
);
2231 if (idItem
< 0 || idItem
> Menu
->cItems
)
2234 RECTL_vSetEmptyRect(&kmbi
.rcBar
);
2238 Ret
= IntGetMenuItemRect(pWnd
, Menu
, 0, &kmbi
.rcBar
);
2239 kmbi
.rcBar
.right
= kmbi
.rcBar
.left
+ Menu
->cxMenu
;
2240 kmbi
.rcBar
.bottom
= kmbi
.rcBar
.top
+ Menu
->cyMenu
;
2241 TRACE("idItem 0 %d\n",Ret
);
2245 Ret
= IntGetMenuItemRect(pWnd
, Menu
, idItem
-1, &kmbi
.rcBar
);
2246 TRACE("idItem X %d\n", Ret
);
2250 kmbi
.hwndMenu
= NULL
;
2251 kmbi
.fBarFocused
= FALSE
;
2252 kmbi
.fFocused
= FALSE
;
2253 //kmbi.fBarFocused = top_popup_hmenu == hMenu;
2256 kmbi
.fFocused
= Menu
->iItem
== idItem
-1;
2257 if (kmbi
.fFocused
&& (Menu
->rgItems
[idItem
- 1].spSubMenu
))
2259 kmbi
.hwndMenu
= Menu
->rgItems
[idItem
- 1].spSubMenu
->hWnd
;
2264 kmbi.fFocused = kmbi.fBarFocused;
2269 RtlCopyMemory(pmbi
, &kmbi
, sizeof(MENUBARINFO
));
2271 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2273 Status
= _SEH2_GetExceptionCode();
2277 if (!NT_SUCCESS(Status
))
2279 SetLastNtError(Status
);
2286 TRACE("Leave NtUserGetMenuBarInfo, ret=%i\n",_ret_
);
2299 PMENU Menu
, SubMenu
;
2302 DECLARE_RETURN(UINT
);
2304 TRACE("Enter NtUserGetMenuIndex\n");
2307 if ( !(Menu
= UserGetMenuObject(hMenu
)) ||
2308 !(SubMenu
= UserGetMenuObject(hSubMenu
)) )
2311 MenuItem
= Menu
->rgItems
;
2312 for (i
= 0; i
< Menu
->cItems
; i
++, MenuItem
++)
2314 if (MenuItem
->spSubMenu
== SubMenu
)
2315 RETURN(MenuItem
->wID
);
2320 TRACE("Leave NtUserGetMenuIndex, ret=%u\n",_ret_
);
2329 NtUserGetMenuItemRect(
2340 NTSTATUS Status
= STATUS_SUCCESS
;
2341 DECLARE_RETURN(BOOL
);
2343 TRACE("Enter NtUserGetMenuItemRect\n");
2346 if (!(Menu
= UserGetMenuObject(hMenu
)))
2351 if ((MenuItem
= MENU_FindItem (&Menu
, &uItem
, MF_BYPOSITION
)))
2353 Rect
.left
= MenuItem
->xItem
;
2354 Rect
.top
= MenuItem
->yItem
;
2355 Rect
.right
= MenuItem
->cxItem
; // Do this for now......
2356 Rect
.bottom
= MenuItem
->cyItem
;
2366 if (lprcItem
== NULL
) RETURN( FALSE
);
2368 if (!(ReferenceWnd
= UserGetWindowObject(hWnd
))) RETURN( FALSE
);
2370 if (Menu
->fFlags
& MNF_POPUP
)
2372 XMove
= ReferenceWnd
->rcClient
.left
;
2373 YMove
= ReferenceWnd
->rcClient
.top
;
2377 XMove
= ReferenceWnd
->rcWindow
.left
;
2378 YMove
= ReferenceWnd
->rcWindow
.top
;
2383 Rect
.right
+= XMove
;
2384 Rect
.bottom
+= YMove
;
2388 RtlCopyMemory(lprcItem
, &Rect
, sizeof(RECTL
));
2390 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2392 Status
= _SEH2_GetExceptionCode();
2396 if (!NT_SUCCESS(Status
))
2398 SetLastNtError(Status
);
2404 TRACE("Leave NtUserGetMenuItemRect, ret=%i\n",_ret_
);
2413 NtUserHiliteMenuItem(
2421 DECLARE_RETURN(BOOLEAN
);
2423 TRACE("Enter NtUserHiliteMenuItem\n");
2424 UserEnterExclusive();
2426 if(!(Window
= UserGetWindowObject(hWnd
)))
2428 EngSetLastError(ERROR_INVALID_WINDOW_HANDLE
);
2432 if(!(Menu
= UserGetMenuObject(hMenu
)))
2434 EngSetLastError(ERROR_INVALID_MENU_HANDLE
);
2438 RETURN( IntHiliteMenuItem(Window
, Menu
, uItemHilite
, uHilite
));
2441 TRACE("Leave NtUserHiliteMenuItem, ret=%u\n",_ret_
);
2451 NtUserMenuItemFromPoint(
2461 DECLARE_RETURN(int);
2463 TRACE("Enter NtUserMenuItemFromPoint\n");
2464 UserEnterExclusive();
2466 if (!(Menu
= UserGetMenuObject(hMenu
)))
2471 if (!(Window
= UserGetWindowObject(Menu
->hWnd
)))
2476 X
-= Window
->rcWindow
.left
;
2477 Y
-= Window
->rcWindow
.top
;
2480 for (i
= 0; i
< Menu
->cItems
; i
++, mi
++)
2483 Rect
.left
= mi
->xItem
;
2484 Rect
.top
= mi
->yItem
;
2485 Rect
.right
= mi
->cxItem
; // Do this for now......
2486 Rect
.bottom
= mi
->cyItem
;
2487 //MENU_AdjustMenuItemRect(Menu, &Rect); Need gpsi OBMI via callback!
2488 if (RECTL_bPointInRect(&Rect
, X
, Y
))
2494 RETURN( (mi
? i
: NO_SELECTED_ITEM
));
2497 TRACE("Leave NtUserMenuItemFromPoint, ret=%i\n",_ret_
);
2513 DECLARE_RETURN(BOOL
);
2515 TRACE("Enter NtUserRemoveMenu\n");
2516 UserEnterExclusive();
2518 if(!(Menu
= UserGetMenuObject(hMenu
)))
2523 RETURN(IntRemoveMenuItem(Menu
, uPosition
, uFlags
, FALSE
));
2526 TRACE("Leave NtUserRemoveMenu, ret=%i\n",_ret_
);
2536 NtUserSetMenuContextHelpId(
2538 DWORD dwContextHelpId
)
2541 DECLARE_RETURN(BOOL
);
2543 TRACE("Enter NtUserSetMenuContextHelpId\n");
2544 UserEnterExclusive();
2546 if(!(Menu
= UserGetMenuObject(hMenu
)))
2551 RETURN(IntSetMenuContextHelpId(Menu
, dwContextHelpId
));
2554 TRACE("Leave NtUserSetMenuContextHelpId, ret=%i\n",_ret_
);
2563 NtUserSetMenuDefaultItem(
2569 DECLARE_RETURN(BOOL
);
2571 TRACE("Enter NtUserSetMenuDefaultItem\n");
2572 UserEnterExclusive();
2574 if(!(Menu
= UserGetMenuObject(hMenu
)))
2579 RETURN( UserSetMenuDefaultItem(Menu
, uItem
, fByPos
));
2582 TRACE("Leave NtUserSetMenuDefaultItem, ret=%i\n",_ret_
);
2591 NtUserSetMenuFlagRtoL(
2595 DECLARE_RETURN(BOOL
);
2597 TRACE("Enter NtUserSetMenuFlagRtoL\n");
2598 UserEnterExclusive();
2600 if(!(Menu
= UserGetMenuObject(hMenu
)))
2605 RETURN(IntSetMenuFlagRtoL(Menu
));
2608 TRACE("Leave NtUserSetMenuFlagRtoL, ret=%i\n",_ret_
);
2617 NtUserThunkedMenuInfo(
2622 DECLARE_RETURN(BOOL
);
2624 TRACE("Enter NtUserThunkedMenuInfo\n");
2625 UserEnterExclusive();
2627 if (!(Menu
= UserGetMenuObject(hMenu
)))
2632 RETURN(UserMenuInfo(Menu
, (PROSMENUINFO
)lpcmi
, TRUE
));
2635 TRACE("Leave NtUserThunkedMenuInfo, ret=%i\n",_ret_
);
2644 NtUserThunkedMenuItemInfo(
2649 LPMENUITEMINFOW lpmii
,
2650 PUNICODE_STRING lpszCaption
)
2654 UNICODE_STRING lstrCaption
;
2655 DECLARE_RETURN(BOOL
);
2657 TRACE("Enter NtUserThunkedMenuItemInfo\n");
2658 UserEnterExclusive();
2660 /* lpszCaption may be NULL, check for it and call RtlInitUnicodeString()
2661 if bInsert == TRUE call UserInsertMenuItem() else UserSetMenuItemInfo() */
2663 if (!(Menu
= UserGetMenuObject(hMenu
)))
2668 RtlInitUnicodeString(&lstrCaption
, 0);
2670 /* Check if we got a Caption */
2671 if (lpszCaption
&& lpszCaption
->Buffer
)
2673 /* Copy the string to kernel mode */
2674 Status
= ProbeAndCaptureUnicodeString( &lstrCaption
,
2677 if (!NT_SUCCESS(Status
))
2679 ERR("Failed to capture MenuItem Caption (status 0x%08x)\n",Status
);
2680 SetLastNtError(Status
);
2685 if (bInsert
) RETURN( UserInsertMenuItem(Menu
, uItem
, fByPosition
, lpmii
, &lstrCaption
));
2687 RETURN( UserMenuItemInfo(Menu
, uItem
, fByPosition
, (PROSMENUITEMINFO
)lpmii
, TRUE
, &lstrCaption
));
2690 TRACE("Leave NtUserThunkedMenuItemInfo, ret=%i\n",_ret_
);