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
)
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
);
211 DesktopHeapFree(pMenu
->head
.rpdesk
, pMenu
->rgItems
);
212 pMenu
->rgItems
= NULL
;
218 /* Callback for the object manager */
220 UserDestroyMenuObject(PVOID Object
)
222 return IntDestroyMenuObject(Object
, TRUE
);
226 IntDestroyMenuObject(PMENU Menu
, BOOL bRecurse
)
232 /* Remove all menu items */
233 IntDestroyMenu( Menu
, bRecurse
);
235 if (PsGetCurrentProcessSessionId() == Menu
->head
.rpdesk
->rpwinstaParent
->dwSessionId
)
240 Window
= UserGetWindowObject(Menu
->hWnd
);
245 /* DestroyMenu should not destroy system menu popup owner */
246 if ((Menu
->fFlags
& (MNF_POPUP
| MNF_SYSSUBMENU
)) == MNF_POPUP
)
248 // Should we check it to see if it has Class?
249 ERR("FIXME Pop up menu window thing'ie\n");
250 //co_UserDestroyWindow( Window );
255 ret
= UserDeleteObject(Menu
->head
.h
, TYPE_MENU
);
257 { // Make sure it is really dead or just marked for deletion.
258 ret
= UserObjectInDestroy(Menu
->head
.h
);
259 if (ret
&& EngGetLastError() == ERROR_INVALID_HANDLE
) ret
= FALSE
;
260 } // See test_subpopup_locked_by_menu tests....
267 /**********************************************************************
270 * detect if there are loops in the menu tree (or the depth is too large)
272 int FASTCALL
MENU_depth( PMENU pmenu
, int depth
)
278 if (!pmenu
) return depth
;
281 if( depth
> MAXMENUDEPTH
) return depth
;
282 item
= pmenu
->rgItems
;
284 for( i
= 0; item
, i
< pmenu
->cItems
&& subdepth
<= MAXMENUDEPTH
; i
++, item
++)
286 if( item
->spSubMenu
)//VerifyMenu(item->spSubMenu))
288 int bdepth
= MENU_depth( item
->spSubMenu
, depth
);
289 if( bdepth
> subdepth
) subdepth
= bdepth
;
291 if( subdepth
> MAXMENUDEPTH
)
292 TRACE("<- hmenu %p\n", item
->spSubMenu
);
297 /***********************************************************************
300 * Find a menu item. Return a pointer on the item, and modifies *hmenu
301 * in case the item was in a sub-menu.
303 PITEM FASTCALL
MENU_FindItem( PMENU
*pmenu
, UINT
*nPos
, UINT wFlags
)
306 ITEM
*fallback
= NULL
;
307 UINT fallback_pos
= 0;
310 if (!menu
) return NULL
;
312 if (wFlags
& MF_BYPOSITION
)
314 if (!menu
->cItems
) return NULL
;
315 if (*nPos
>= menu
->cItems
) return NULL
;
316 return &menu
->rgItems
[*nPos
];
320 PITEM item
= menu
->rgItems
;
321 for (i
= 0; item
, i
< menu
->cItems
; i
++, item
++)
325 PMENU psubmenu
= item
->spSubMenu
;//VerifyMenu(item->spSubMenu);
326 PITEM subitem
= MENU_FindItem( &psubmenu
, nPos
, wFlags
);
332 else if (item
->wID
== *nPos
)
334 /* fallback to this item if nothing else found */
339 else if (item
->wID
== *nPos
)
348 *nPos
= fallback_pos
;
354 IntRemoveMenuItem( PMENU pMenu
, UINT nPos
, UINT wFlags
, BOOL bRecurse
)
358 TRACE("(menu=%p pos=%04x flags=%04x)\n",pMenu
, nPos
, wFlags
);
359 if (!(item
= MENU_FindItem( &pMenu
, &nPos
, wFlags
))) return FALSE
;
363 FreeMenuText(pMenu
,item
);
364 if (bRecurse
&& item
->spSubMenu
)
366 IntDestroyMenuObject(item
->spSubMenu
, bRecurse
);
368 ////// Use cAlloced with inc's of 8's....
369 if (--pMenu
->cItems
== 0)
371 DesktopHeapFree(pMenu
->head
.rpdesk
, pMenu
->rgItems
);
372 pMenu
->rgItems
= NULL
;
376 while(nPos
< pMenu
->cItems
)
382 pMenu
->rgItems
= DesktopHeapReAlloc(pMenu
->head
.rpdesk
, pMenu
->rgItems
, pMenu
->cItems
* sizeof(ITEM
));
387 /**********************************************************************
390 * Insert (allocate) a new item into a menu.
392 ITEM
*MENU_InsertItem( PMENU menu
, UINT pos
, UINT flags
, PMENU
*submenu
, UINT
*npos
)
396 /* Find where to insert new item */
398 if (flags
& MF_BYPOSITION
) {
399 if (pos
> menu
->cItems
)
402 if (!MENU_FindItem( &menu
, &pos
, flags
))
404 if (submenu
) *submenu
= menu
;
405 if (npos
) *npos
= pos
;
410 /* Make sure that MDI system buttons stay on the right side.
411 * Note: XP treats only bitmap handles 1 - 6 as "magic" ones
412 * regardless of their id.
415 (INT_PTR
)menu
->rgItems
[pos
- 1].hbmp
>= (INT_PTR
)HBMMENU_SYSTEM
&&
416 (INT_PTR
)menu
->rgItems
[pos
- 1].hbmp
<= (INT_PTR
)HBMMENU_MBAR_CLOSE_D
)
419 TRACE("inserting at %u flags %x\n", pos
, flags
);
421 /* Create new items array */
423 newItems
= DesktopHeapAlloc(menu
->head
.rpdesk
, sizeof(ITEM
) * (menu
->cItems
+1) );
426 WARN("allocation failed\n" );
429 if (menu
->cItems
> 0)
431 /* Copy the old array into the new one */
432 if (pos
> 0) RtlCopyMemory( newItems
, menu
->rgItems
, pos
* sizeof(ITEM
) );
433 if (pos
< menu
->cItems
) RtlCopyMemory( &newItems
[pos
+1], &menu
->rgItems
[pos
], (menu
->cItems
-pos
)*sizeof(ITEM
) );
434 DesktopHeapFree(menu
->head
.rpdesk
, menu
->rgItems
);
436 menu
->rgItems
= newItems
;
438 RtlZeroMemory( &newItems
[pos
], sizeof(*newItems
) );
439 menu
->cyMenu
= 0; /* force size recalculate */
440 return &newItems
[pos
];
445 _In_ PMENU MenuObject
,
448 PROSMENUITEMINFO ItemInfo
,
449 PUNICODE_STRING lpstr
)
452 PMENU SubMenu
= NULL
;
454 NT_ASSERT(MenuObject
!= NULL
);
456 if (MAX_MENU_ITEMS
<= MenuObject
->cItems
)
458 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY
);
462 SubMenu
= MenuObject
;
464 if(!(MenuItem
= MENU_InsertItem( SubMenu
, uItem
, fByPosition
? MF_BYPOSITION
: MF_BYCOMMAND
, &SubMenu
, &uItem
))) return FALSE
;
466 if(!IntSetMenuItemInfo(SubMenu
, MenuItem
, ItemInfo
, lpstr
))
468 IntRemoveMenuItem(SubMenu
, uItem
, fByPosition
? MF_BYPOSITION
: MF_BYCOMMAND
, FALSE
);
472 /* Force size recalculation! */
474 MenuItem
->hbmpChecked
= MenuItem
->hbmpUnchecked
= 0;
476 TRACE("IntInsertMenuItemToList = %i %d\n", uItem
, (BOOL
)((INT
)uItem
>= 0));
483 _Out_ PHANDLE Handle
,
485 _In_ PDESKTOP Desktop
,
486 _In_ PPROCESSINFO ppi
)
490 Menu
= (PMENU
)UserCreateObject( gHandleTable
,
502 Menu
->cyMax
= 0; /* Default */
503 Menu
->hbrBack
= NULL
; /* No brush */
504 Menu
->dwContextHelpId
= 0; /* Default */
505 Menu
->dwMenuData
= 0; /* Default */
506 Menu
->iItem
= NO_SELECTED_ITEM
; // Focused item
507 Menu
->fFlags
= (IsMenuBar
? 0 : MNF_POPUP
);
508 Menu
->spwndNotify
= NULL
;
509 Menu
->cyMenu
= 0; // Height
510 Menu
->cxMenu
= 0; // Width
511 Menu
->cItems
= 0; // Item count
514 Menu
->cxTextAlign
= 0;
515 Menu
->rgItems
= NULL
;
518 Menu
->TimeToHide
= FALSE
;
524 IntCloneMenuItems(PMENU Destination
, PMENU Source
)
526 PITEM MenuItem
, NewMenuItem
= NULL
;
532 NewMenuItem
= DesktopHeapAlloc(Destination
->head
.rpdesk
, (Source
->cItems
+1) * sizeof(ITEM
));
533 if(!NewMenuItem
) return FALSE
;
535 RtlZeroMemory(NewMenuItem
, (Source
->cItems
+1) * sizeof(ITEM
));
537 Destination
->rgItems
= NewMenuItem
;
539 MenuItem
= Source
->rgItems
;
540 for (i
= 0; i
< Source
->cItems
; i
++, MenuItem
++, NewMenuItem
++)
542 NewMenuItem
->fType
= MenuItem
->fType
;
543 NewMenuItem
->fState
= MenuItem
->fState
;
544 NewMenuItem
->wID
= MenuItem
->wID
;
545 NewMenuItem
->spSubMenu
= MenuItem
->spSubMenu
;
546 NewMenuItem
->hbmpChecked
= MenuItem
->hbmpChecked
;
547 NewMenuItem
->hbmpUnchecked
= MenuItem
->hbmpUnchecked
;
548 NewMenuItem
->dwItemData
= MenuItem
->dwItemData
;
549 if (MenuItem
->lpstr
.Length
)
551 NewMenuItem
->lpstr
.Length
= 0;
552 NewMenuItem
->lpstr
.MaximumLength
= MenuItem
->lpstr
.MaximumLength
;
553 NewMenuItem
->lpstr
.Buffer
= DesktopHeapAlloc(Destination
->head
.rpdesk
, MenuItem
->lpstr
.MaximumLength
);
554 if (!NewMenuItem
->lpstr
.Buffer
)
556 DesktopHeapFree(Destination
->head
.rpdesk
, NewMenuItem
);
559 RtlCopyUnicodeString(&NewMenuItem
->lpstr
, &MenuItem
->lpstr
);
560 NewMenuItem
->lpstr
.Buffer
[MenuItem
->lpstr
.Length
/ sizeof(WCHAR
)] = 0;
561 NewMenuItem
->Xlpstr
= NewMenuItem
->lpstr
.Buffer
;
565 NewMenuItem
->lpstr
.Buffer
= MenuItem
->lpstr
.Buffer
;
566 NewMenuItem
->Xlpstr
= NewMenuItem
->lpstr
.Buffer
;
568 NewMenuItem
->hbmp
= MenuItem
->hbmp
;
574 IntCloneMenu(PMENU Source
)
582 /* A menu is valid process wide. We can pass to the object manager any thread ptr */
583 Menu
= (PMENU
)UserCreateObject( gHandleTable
,
585 ((PPROCESSINFO
)Source
->head
.hTaskWow
)->ptiList
,
592 Menu
->fFlags
= Source
->fFlags
;
593 Menu
->cyMax
= Source
->cyMax
;
594 Menu
->hbrBack
= Source
->hbrBack
;
595 Menu
->dwContextHelpId
= Source
->dwContextHelpId
;
596 Menu
->dwMenuData
= Source
->dwMenuData
;
597 Menu
->iItem
= NO_SELECTED_ITEM
;
598 Menu
->spwndNotify
= NULL
;
601 Menu
->cItems
= Source
->cItems
;
604 Menu
->cxTextAlign
= 0;
605 Menu
->rgItems
= NULL
;
608 Menu
->TimeToHide
= FALSE
;
610 IntCloneMenuItems(Menu
, Source
);
616 IntSetMenuFlagRtoL(PMENU Menu
)
618 Menu
->fFlags
|= MNF_RTOL
;
623 IntSetMenuContextHelpId(PMENU Menu
, DWORD dwContextHelpId
)
625 Menu
->dwContextHelpId
= dwContextHelpId
;
630 IntGetMenuInfo(PMENU Menu
, PROSMENUINFO lpmi
)
632 if(lpmi
->fMask
& MIM_BACKGROUND
)
633 lpmi
->hbrBack
= Menu
->hbrBack
;
634 if(lpmi
->fMask
& MIM_HELPID
)
635 lpmi
->dwContextHelpID
= Menu
->dwContextHelpId
;
636 if(lpmi
->fMask
& MIM_MAXHEIGHT
)
637 lpmi
->cyMax
= Menu
->cyMax
;
638 if(lpmi
->fMask
& MIM_MENUDATA
)
639 lpmi
->dwMenuData
= Menu
->dwMenuData
;
640 if(lpmi
->fMask
& MIM_STYLE
)
641 lpmi
->dwStyle
= Menu
->fFlags
& MNS_STYLE_MASK
;
643 if (sizeof(MENUINFO
) < lpmi
->cbSize
)
645 lpmi
->cItems
= Menu
->cItems
;
647 lpmi
->iItem
= Menu
->iItem
;
648 lpmi
->cxMenu
= Menu
->cxMenu
;
649 lpmi
->cyMenu
= Menu
->cyMenu
;
650 lpmi
->spwndNotify
= Menu
->spwndNotify
;
651 lpmi
->cxTextAlign
= Menu
->cxTextAlign
;
652 lpmi
->iTop
= Menu
->iMaxTop
;
653 lpmi
->iMaxTop
= Menu
->iMaxTop
;
654 lpmi
->dwArrowsOn
= Menu
->dwArrowsOn
;
656 lpmi
->fFlags
= Menu
->fFlags
;
657 lpmi
->Self
= Menu
->head
.h
;
658 lpmi
->TimeToHide
= Menu
->TimeToHide
;
659 lpmi
->Wnd
= Menu
->hWnd
;
665 IntSetMenuInfo(PMENU Menu
, PROSMENUINFO lpmi
)
667 if(lpmi
->fMask
& MIM_BACKGROUND
)
668 Menu
->hbrBack
= lpmi
->hbrBack
;
669 if(lpmi
->fMask
& MIM_HELPID
)
670 Menu
->dwContextHelpId
= lpmi
->dwContextHelpID
;
671 if(lpmi
->fMask
& MIM_MAXHEIGHT
)
672 Menu
->cyMax
= lpmi
->cyMax
;
673 if(lpmi
->fMask
& MIM_MENUDATA
)
674 Menu
->dwMenuData
= lpmi
->dwMenuData
;
675 if(lpmi
->fMask
& MIM_STYLE
)
676 Menu
->fFlags
^= (Menu
->fFlags
^ lpmi
->dwStyle
) & MNS_STYLE_MASK
;
677 if(lpmi
->fMask
& MIM_APPLYTOSUBMENUS
)
680 PITEM item
= Menu
->rgItems
;
681 for ( i
= Menu
->cItems
; i
; i
--, item
++)
683 if ( item
->spSubMenu
)
685 IntSetMenuInfo( item
->spSubMenu
, lpmi
);
689 if (sizeof(MENUINFO
) < lpmi
->cbSize
)
691 Menu
->iItem
= lpmi
->iItem
;
692 Menu
->cyMenu
= lpmi
->cyMenu
;
693 Menu
->cxMenu
= lpmi
->cxMenu
;
694 Menu
->spwndNotify
= lpmi
->spwndNotify
;
695 Menu
->cxTextAlign
= lpmi
->cxTextAlign
;
696 Menu
->iTop
= lpmi
->iTop
;
697 Menu
->iMaxTop
= lpmi
->iMaxTop
;
698 Menu
->dwArrowsOn
= lpmi
->dwArrowsOn
;
700 Menu
->TimeToHide
= lpmi
->TimeToHide
;
701 Menu
->hWnd
= lpmi
->Wnd
;
707 IntGetMenuItemInfo(PMENU Menu
, /* UNUSED PARAM!! */
708 PITEM MenuItem
, PROSMENUITEMINFO lpmii
)
712 if(lpmii
->fMask
& (MIIM_FTYPE
| MIIM_TYPE
))
714 lpmii
->fType
= MenuItem
->fType
;
716 if(lpmii
->fMask
& MIIM_BITMAP
)
718 lpmii
->hbmpItem
= MenuItem
->hbmp
;
720 if(lpmii
->fMask
& MIIM_CHECKMARKS
)
722 lpmii
->hbmpChecked
= MenuItem
->hbmpChecked
;
723 lpmii
->hbmpUnchecked
= MenuItem
->hbmpUnchecked
;
725 if(lpmii
->fMask
& MIIM_DATA
)
727 lpmii
->dwItemData
= MenuItem
->dwItemData
;
729 if(lpmii
->fMask
& MIIM_ID
)
731 lpmii
->wID
= MenuItem
->wID
;
733 if(lpmii
->fMask
& MIIM_STATE
)
735 lpmii
->fState
= MenuItem
->fState
;
737 if(lpmii
->fMask
& MIIM_SUBMENU
)
739 lpmii
->hSubMenu
= MenuItem
->spSubMenu
? MenuItem
->spSubMenu
->head
.h
: NULL
;
742 if ((lpmii
->fMask
& MIIM_STRING
) ||
743 ((lpmii
->fMask
& MIIM_TYPE
) && (MENU_ITEM_TYPE(lpmii
->fType
) == MF_STRING
)))
745 if (lpmii
->dwTypeData
== NULL
)
747 lpmii
->cch
= MenuItem
->lpstr
.Length
/ sizeof(WCHAR
);
750 { //// lpmii->lpstr can be read in user mode!!!!
751 Status
= MmCopyToCaller(lpmii
->dwTypeData
, MenuItem
->lpstr
.Buffer
,
752 min(lpmii
->cch
* sizeof(WCHAR
),
753 MenuItem
->lpstr
.MaximumLength
));
754 if (! NT_SUCCESS(Status
))
756 SetLastNtError(Status
);
762 if (sizeof(ROSMENUITEMINFO
) == lpmii
->cbSize
)
764 lpmii
->Rect
.left
= MenuItem
->xItem
;
765 lpmii
->Rect
.top
= MenuItem
->yItem
;
766 lpmii
->Rect
.right
= MenuItem
->cxItem
; // Do this for now......
767 lpmii
->Rect
.bottom
= MenuItem
->cyItem
;
768 lpmii
->dxTab
= MenuItem
->dxTab
;
769 lpmii
->lpstr
= MenuItem
->lpstr
.Buffer
;
770 lpmii
->maxBmpSize
.cx
= MenuItem
->cxBmp
;
771 lpmii
->maxBmpSize
.cy
= MenuItem
->cyBmp
;
778 IntSetMenuItemInfo(PMENU MenuObject
, PITEM MenuItem
, PROSMENUITEMINFO lpmii
, PUNICODE_STRING lpstr
)
781 BOOL circref
= FALSE
;
783 if(!MenuItem
|| !MenuObject
|| !lpmii
)
787 if ( lpmii
->fMask
& MIIM_FTYPE
)
789 MenuItem
->fType
&= ~MENUITEMINFO_TYPE_MASK
;
790 MenuItem
->fType
|= lpmii
->fType
& MENUITEMINFO_TYPE_MASK
;
792 if (lpmii
->fMask
& MIIM_TYPE
)
794 #if 0 //// Done in User32.
795 if (lpmii
->fMask
& ( MIIM_STRING
| MIIM_FTYPE
| MIIM_BITMAP
))
797 ERR("IntSetMenuItemInfo: Invalid combination of fMask bits used\n");
798 KeRosDumpStackFrames(NULL
, 20);
799 /* This does not happen on Win9x/ME */
800 SetLastNtError( ERROR_INVALID_PARAMETER
);
805 * Delete the menu item type when changing type from
808 if (MenuItem
->fType
!= lpmii
->fType
&&
809 MENU_ITEM_TYPE(MenuItem
->fType
) == MFT_STRING
)
811 FreeMenuText(MenuObject
,MenuItem
);
812 RtlInitUnicodeString(&MenuItem
->lpstr
, NULL
);
813 MenuItem
->Xlpstr
= NULL
;
815 if(lpmii
->fType
& MFT_BITMAP
)
818 MenuItem
->hbmp
= lpmii
->hbmpItem
;
820 { /* Win 9x/Me stuff */
821 MenuItem
->hbmp
= (HBITMAP
)((ULONG_PTR
)(LOWORD(lpmii
->dwTypeData
)));
823 lpmii
->dwTypeData
= 0;
826 if(lpmii
->fMask
& MIIM_BITMAP
)
828 MenuItem
->hbmp
= lpmii
->hbmpItem
;
829 if (MenuItem
->hbmp
<= HBMMENU_POPUP_MINIMIZE
&& MenuItem
->hbmp
>= HBMMENU_CALLBACK
)
830 MenuItem
->fState
|= MFS_HBMMENUBMP
;
832 MenuItem
->fState
&= ~MFS_HBMMENUBMP
;
834 if(lpmii
->fMask
& MIIM_CHECKMARKS
)
836 MenuItem
->hbmpChecked
= lpmii
->hbmpChecked
;
837 MenuItem
->hbmpUnchecked
= lpmii
->hbmpUnchecked
;
839 if(lpmii
->fMask
& MIIM_DATA
)
841 MenuItem
->dwItemData
= lpmii
->dwItemData
;
843 if(lpmii
->fMask
& MIIM_ID
)
845 MenuItem
->wID
= lpmii
->wID
;
847 if(lpmii
->fMask
& MIIM_STATE
)
849 /* Remove MFS_DEFAULT flag from all other menu items if this item
850 has the MFS_DEFAULT state */
851 if(lpmii
->fState
& MFS_DEFAULT
)
852 UserSetMenuDefaultItem(MenuObject
, -1, 0);
853 /* Update the menu item state flags */
854 UpdateMenuItemState(MenuItem
->fState
, lpmii
->fState
);
857 if(lpmii
->fMask
& MIIM_SUBMENU
)
861 SubMenuObject
= UserGetMenuObject(lpmii
->hSubMenu
);
862 if ( SubMenuObject
&& !(UserObjectInDestroy(lpmii
->hSubMenu
)) )
864 //// wine Bug 12171 : Adding Popup Menu to itself! Could create endless loops.
866 if (MenuObject
== SubMenuObject
)
869 ERR("Pop Up Menu Double Trouble!\n");
870 SubMenuObject
= IntCreateMenu(&hMenu
,
872 MenuObject
->head
.rpdesk
,
873 (PPROCESSINFO
)MenuObject
->head
.hTaskWow
); // 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
);
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
);
1139 intGetTitleBarInfo(PWND pWindowObject
, PTITLEBARINFO bti
)
1143 DWORD dwExStyle
= 0;
1144 BOOLEAN retValue
= TRUE
;
1146 if (bti
->cbSize
== sizeof(TITLEBARINFO
))
1148 RtlZeroMemory(&bti
->rgstate
[0],sizeof(DWORD
)*(CCHILDREN_TITLEBAR
+1));
1150 bti
->rgstate
[0] = STATE_SYSTEM_FOCUSABLE
;
1152 dwStyle
= pWindowObject
->style
;
1153 dwExStyle
= pWindowObject
->ExStyle
;
1155 bti
->rcTitleBar
.top
= 0;
1156 bti
->rcTitleBar
.left
= 0;
1157 bti
->rcTitleBar
.right
= pWindowObject
->rcWindow
.right
- pWindowObject
->rcWindow
.left
;
1158 bti
->rcTitleBar
.bottom
= pWindowObject
->rcWindow
.bottom
- pWindowObject
->rcWindow
.top
;
1160 /* Is it iconiced ? */
1161 if ((dwStyle
& WS_ICONIC
)!=WS_ICONIC
)
1163 /* Remove frame from rectangle */
1164 if (HAS_THICKFRAME( dwStyle
, dwExStyle
))
1166 /* FIXME: Note this value should exists in pWindowObject for UserGetSystemMetrics(SM_CXFRAME) and UserGetSystemMetrics(SM_CYFRAME) */
1167 RECTL_vInflateRect( &bti
->rcTitleBar
, -UserGetSystemMetrics(SM_CXFRAME
), -UserGetSystemMetrics(SM_CYFRAME
) );
1169 else if (HAS_DLGFRAME( dwStyle
, dwExStyle
))
1171 /* FIXME: Note this value should exists in pWindowObject for UserGetSystemMetrics(SM_CXDLGFRAME) and UserGetSystemMetrics(SM_CYDLGFRAME) */
1172 RECTL_vInflateRect( &bti
->rcTitleBar
, -UserGetSystemMetrics(SM_CXDLGFRAME
), -UserGetSystemMetrics(SM_CYDLGFRAME
));
1174 else if (HAS_THINFRAME( dwStyle
, dwExStyle
))
1176 /* FIXME: Note this value should exists in pWindowObject for UserGetSystemMetrics(SM_CXBORDER) and UserGetSystemMetrics(SM_CYBORDER) */
1177 RECTL_vInflateRect( &bti
->rcTitleBar
, -UserGetSystemMetrics(SM_CXBORDER
), -UserGetSystemMetrics(SM_CYBORDER
) );
1180 /* We have additional border information if the window
1181 * is a child (but not an MDI child) */
1182 if ( (dwStyle
& WS_CHILD
) &&
1183 ((dwExStyle
& WS_EX_MDICHILD
) == 0 ) )
1185 if (dwExStyle
& WS_EX_CLIENTEDGE
)
1187 /* FIXME: Note this value should exists in pWindowObject for UserGetSystemMetrics(SM_CXEDGE) and UserGetSystemMetrics(SM_CYEDGE) */
1188 RECTL_vInflateRect (&bti
->rcTitleBar
, -UserGetSystemMetrics(SM_CXEDGE
), -UserGetSystemMetrics(SM_CYEDGE
));
1191 if (dwExStyle
& WS_EX_STATICEDGE
)
1193 /* FIXME: Note this value should exists in pWindowObject for UserGetSystemMetrics(SM_CXBORDER) and UserGetSystemMetrics(SM_CYBORDER) */
1194 RECTL_vInflateRect (&bti
->rcTitleBar
, -UserGetSystemMetrics(SM_CXBORDER
), -UserGetSystemMetrics(SM_CYBORDER
));
1199 bti
->rcTitleBar
.top
+= pWindowObject
->rcWindow
.top
;
1200 bti
->rcTitleBar
.left
+= pWindowObject
->rcWindow
.left
;
1201 bti
->rcTitleBar
.right
+= pWindowObject
->rcWindow
.left
;
1203 bti
->rcTitleBar
.bottom
= bti
->rcTitleBar
.top
;
1204 if (dwExStyle
& WS_EX_TOOLWINDOW
)
1206 /* FIXME: Note this value should exists in pWindowObject for UserGetSystemMetrics(SM_CYSMCAPTION) */
1207 bti
->rcTitleBar
.bottom
+= UserGetSystemMetrics(SM_CYSMCAPTION
);
1211 /* FIXME: Note this value should exists in pWindowObject for UserGetSystemMetrics(SM_CYCAPTION) and UserGetSystemMetrics(SM_CXSIZE) */
1212 bti
->rcTitleBar
.bottom
+= UserGetSystemMetrics(SM_CYCAPTION
);
1213 bti
->rcTitleBar
.left
+= UserGetSystemMetrics(SM_CXSIZE
);
1216 if (dwStyle
& WS_CAPTION
)
1218 bti
->rgstate
[1] = STATE_SYSTEM_INVISIBLE
;
1219 if (dwStyle
& WS_SYSMENU
)
1221 if (!(dwStyle
& (WS_MINIMIZEBOX
|WS_MAXIMIZEBOX
)))
1223 bti
->rgstate
[2] = STATE_SYSTEM_INVISIBLE
;
1224 bti
->rgstate
[3] = STATE_SYSTEM_INVISIBLE
;
1228 if (!(dwStyle
& WS_MINIMIZEBOX
))
1230 bti
->rgstate
[2] = STATE_SYSTEM_UNAVAILABLE
;
1232 if (!(dwStyle
& WS_MAXIMIZEBOX
))
1234 bti
->rgstate
[3] = STATE_SYSTEM_UNAVAILABLE
;
1238 if (!(dwExStyle
& WS_EX_CONTEXTHELP
))
1240 bti
->rgstate
[4] = STATE_SYSTEM_INVISIBLE
;
1242 if (pWindowObject
->pcls
->style
& CS_NOCLOSE
)
1244 bti
->rgstate
[5] = STATE_SYSTEM_UNAVAILABLE
;
1249 bti
->rgstate
[2] = STATE_SYSTEM_INVISIBLE
;
1250 bti
->rgstate
[3] = STATE_SYSTEM_INVISIBLE
;
1251 bti
->rgstate
[4] = STATE_SYSTEM_INVISIBLE
;
1252 bti
->rgstate
[5] = STATE_SYSTEM_INVISIBLE
;
1257 bti
->rgstate
[0] |= STATE_SYSTEM_INVISIBLE
;
1262 EngSetLastError(ERROR_INVALID_PARAMETER
);
1274 LPCMENUITEMINFOW UnsafeItemInfo
,
1275 PUNICODE_STRING lpstr
)
1278 ROSMENUITEMINFO ItemInfo
;
1280 /* Try to copy the whole MENUITEMINFOW structure */
1281 Status
= MmCopyFromCaller(&ItemInfo
, UnsafeItemInfo
, sizeof(MENUITEMINFOW
));
1282 if (NT_SUCCESS(Status
))
1284 if (sizeof(MENUITEMINFOW
) != ItemInfo
.cbSize
1285 && FIELD_OFFSET(MENUITEMINFOW
, hbmpItem
) != ItemInfo
.cbSize
)
1287 EngSetLastError(ERROR_INVALID_PARAMETER
);
1290 return IntInsertMenuItem(Menu
, uItem
, fByPosition
, &ItemInfo
, lpstr
);
1293 /* Try to copy without last field (not present in older versions) */
1294 Status
= MmCopyFromCaller(&ItemInfo
, UnsafeItemInfo
, FIELD_OFFSET(MENUITEMINFOW
, hbmpItem
));
1295 if (NT_SUCCESS(Status
))
1297 if (FIELD_OFFSET(MENUITEMINFOW
, hbmpItem
) != ItemInfo
.cbSize
)
1299 EngSetLastError(ERROR_INVALID_PARAMETER
);
1302 ItemInfo
.hbmpItem
= (HBITMAP
)0;
1303 return IntInsertMenuItem(Menu
, uItem
, fByPosition
, &ItemInfo
, lpstr
);
1306 SetLastNtError(Status
);
1310 UINT FASTCALL
IntGetMenuState( HMENU hMenu
, UINT uId
, UINT uFlags
)
1315 if (!(MenuObject
= UserGetMenuObject(hMenu
)))
1320 if (!(pItem
= MENU_FindItem( &MenuObject
, &uId
, uFlags
))) return -1;
1322 if (pItem
->spSubMenu
)
1324 return (pItem
->spSubMenu
->cItems
<< 8) | ((pItem
->fState
|pItem
->fType
) & 0xff);
1327 return (pItem
->fType
| pItem
->fState
);
1330 HMENU FASTCALL
IntGetSubMenu( HMENU hMenu
, int nPos
)
1335 if (!(MenuObject
= UserGetMenuObject(hMenu
)))
1340 if (!(pItem
= MENU_FindItem( &MenuObject
, (UINT
*)&nPos
, MF_BYPOSITION
))) return NULL
;
1342 if (pItem
->spSubMenu
)
1344 HMENU hsubmenu
= UserHMGetHandle(pItem
->spSubMenu
);
1350 UINT FASTCALL
IntFindSubMenu(HMENU
*hMenu
, HMENU hSubTarget
)
1357 if (((*hMenu
)==(HMENU
)0xffff) ||(!(menu
= UserGetMenuObject(*hMenu
))))
1358 return NO_SELECTED_ITEM
;
1360 item
= menu
->rgItems
;
1361 for (i
= 0; i
< menu
->cItems
; i
++, item
++)
1363 if (!item
->spSubMenu
)
1367 hSubMenu
= UserHMGetHandle(item
->spSubMenu
);
1368 if (hSubMenu
== hSubTarget
)
1374 HMENU hsubmenu
= hSubMenu
;
1375 UINT pos
= IntFindSubMenu( &hsubmenu
, hSubTarget
);
1376 if (pos
!= NO_SELECTED_ITEM
)
1384 return NO_SELECTED_ITEM
;
1388 HMENU FASTCALL
UserCreateMenu(PDESKTOP Desktop
, BOOL PopupMenu
)
1390 PWINSTATION_OBJECT WinStaObject
;
1394 PEPROCESS CurrentProcess
= PsGetCurrentProcess();
1396 if (gpepCSRSS
!= CurrentProcess
)
1399 * gpepCSRSS does not have a Win32WindowStation
1402 Status
= IntValidateWindowStationHandle(CurrentProcess
->Win32WindowStation
,
1407 if (!NT_SUCCESS(Status
))
1409 ERR("Validation of window station handle (%p) failed\n",
1410 CurrentProcess
->Win32WindowStation
);
1411 SetLastNtError(Status
);
1414 Menu
= IntCreateMenu(&Handle
, !PopupMenu
, Desktop
, GetW32ProcessInfo());
1415 if (Menu
&& Menu
->head
.rpdesk
->rpwinstaParent
!= WinStaObject
)
1417 ERR("Desktop Window Station does not match Process one!\n");
1419 ObDereferenceObject(WinStaObject
);
1423 Menu
= IntCreateMenu(&Handle
, !PopupMenu
, GetW32ThreadInfo()->rpdesk
, GetW32ProcessInfo());
1426 if (Menu
) UserDereferenceObject(Menu
);
1427 return (HMENU
)Handle
;
1435 PROSMENUITEMINFO ItemInfo
,
1437 PUNICODE_STRING lpstr
)
1442 if (!(MenuItem
= MENU_FindItem( &Menu
, &Item
, (ByPosition
? MF_BYPOSITION
: MF_BYCOMMAND
) )))
1444 EngSetLastError(ERROR_MENU_ITEM_NOT_FOUND
);
1449 Ret
= IntSetMenuItemInfo(Menu
, MenuItem
, ItemInfo
, lpstr
);
1453 Ret
= IntGetMenuItemInfo(Menu
, MenuItem
, ItemInfo
);
1463 PROSMENUITEMINFO UnsafeItemInfo
,
1465 PUNICODE_STRING lpstr
)
1468 ROSMENUITEMINFO ItemInfo
;
1473 Status
= MmCopyFromCaller(&Size
, &UnsafeItemInfo
->cbSize
, sizeof(UINT
));
1474 if (! NT_SUCCESS(Status
))
1476 SetLastNtError(Status
);
1479 if (sizeof(MENUITEMINFOW
) != Size
1480 && FIELD_OFFSET(MENUITEMINFOW
, hbmpItem
) != Size
1481 && sizeof(ROSMENUITEMINFO
) != Size
)
1483 EngSetLastError(ERROR_INVALID_PARAMETER
);
1486 Status
= MmCopyFromCaller(&ItemInfo
, UnsafeItemInfo
, Size
);
1487 if (! NT_SUCCESS(Status
))
1489 SetLastNtError(Status
);
1492 /* If this is a pre-0x0500 _WIN32_WINNT MENUITEMINFOW, you can't
1494 if (FIELD_OFFSET(MENUITEMINFOW
, hbmpItem
) == Size
1495 && 0 != (ItemInfo
.fMask
& MIIM_BITMAP
))
1497 EngSetLastError(ERROR_INVALID_PARAMETER
);
1501 if (!(MenuItem
= MENU_FindItem( &Menu
, &Item
, (ByPosition
? MF_BYPOSITION
: MF_BYCOMMAND
) )))
1503 EngSetLastError(ERROR_MENU_ITEM_NOT_FOUND
);
1509 Ret
= IntSetMenuItemInfo(Menu
, MenuItem
, &ItemInfo
, lpstr
);
1513 Ret
= IntGetMenuItemInfo(Menu
, MenuItem
, &ItemInfo
);
1516 Status
= MmCopyToCaller(UnsafeItemInfo
, &ItemInfo
, Size
);
1517 if (! NT_SUCCESS(Status
))
1519 SetLastNtError(Status
);
1531 PROSMENUINFO UnsafeMenuInfo
,
1537 ROSMENUINFO MenuInfo
;
1539 Status
= MmCopyFromCaller(&Size
, &UnsafeMenuInfo
->cbSize
, sizeof(DWORD
));
1540 if (! NT_SUCCESS(Status
))
1542 SetLastNtError(Status
);
1545 if(Size
< sizeof(MENUINFO
) || sizeof(ROSMENUINFO
) < Size
)
1547 EngSetLastError(ERROR_INVALID_PARAMETER
);
1550 Status
= MmCopyFromCaller(&MenuInfo
, UnsafeMenuInfo
, Size
);
1551 if (! NT_SUCCESS(Status
))
1553 SetLastNtError(Status
);
1560 Res
= IntSetMenuInfo(Menu
, &MenuInfo
);
1565 Res
= IntGetMenuInfo(Menu
, &MenuInfo
);
1568 Status
= MmCopyToCaller(UnsafeMenuInfo
, &MenuInfo
, Size
);
1569 if (! NT_SUCCESS(Status
))
1571 SetLastNtError(Status
);
1581 MENU_AdjustMenuItemRect(PMENU menu
, PRECTL rect
)
1583 if (menu
->dwArrowsOn
)
1585 UINT arrow_bitmap_height
;
1587 //GetObjectW(get_up_arrow_bitmap(), sizeof(bmp), &bmp);
1588 arrow_bitmap_height
= gpsi
->oembmi
[65].cy
; ///// Menu up arrow! OBM_UPARROW DFCS_MENUARROWUP
1589 //arrow_bitmap_height = bmp.bmHeight;
1590 rect
->top
+= arrow_bitmap_height
- menu
->iTop
;
1591 rect
->bottom
+= arrow_bitmap_height
- menu
->iTop
;
1607 HWND hWnd
= Menu
->hWnd
;
1608 if (!(pWnd
= UserGetWindowObject(hWnd
))) return FALSE
;
1611 if ((MenuItem
= MENU_FindItem (&Menu
, &uItem
, MF_BYPOSITION
)))
1613 Rect
->left
= MenuItem
->xItem
;
1614 Rect
->top
= MenuItem
->yItem
;
1615 Rect
->right
= MenuItem
->cxItem
; // Do this for now......
1616 Rect
->bottom
= MenuItem
->cyItem
;
1620 ERR("Failed Item Lookup! %d\n", uItem
);
1624 if (Menu
->fFlags
& MNF_POPUP
)
1626 XMove
= pWnd
->rcClient
.left
;
1627 YMove
= pWnd
->rcClient
.top
;
1631 XMove
= pWnd
->rcWindow
.left
;
1632 YMove
= pWnd
->rcWindow
.top
;
1635 Rect
->left
+= XMove
;
1637 Rect
->right
+= XMove
;
1638 Rect
->bottom
+= YMove
;
1643 PMENU FASTCALL
MENU_GetSystemMenu(PWND Window
, PMENU Popup
)
1645 PMENU Menu
, NewMenu
= NULL
, SysMenu
= NULL
;
1646 HMENU hSysMenu
, hNewMenu
= NULL
;
1647 ROSMENUITEMINFO ItemInfoSet
= {0};
1648 ROSMENUITEMINFO ItemInfo
= {0};
1649 UNICODE_STRING MenuName
;
1651 hSysMenu
= UserCreateMenu(Window
->head
.rpdesk
, FALSE
);
1652 if (NULL
== hSysMenu
)
1656 SysMenu
= IntGetMenuObject(hSysMenu
);
1657 if (NULL
== SysMenu
)
1659 UserDestroyMenu(hSysMenu
);
1663 SysMenu
->fFlags
|= MNF_SYSMENU
;
1664 SysMenu
->hWnd
= Window
->head
.h
;
1668 //hNewMenu = co_IntLoadSysMenuTemplate();
1669 if ( Window
->ExStyle
& WS_EX_MDICHILD
)
1671 RtlInitUnicodeString( &MenuName
, L
"SYSMENUMDI");
1672 hNewMenu
= co_IntCallLoadMenu( hModClient
, &MenuName
);
1676 RtlInitUnicodeString( &MenuName
, L
"SYSMENU");
1677 hNewMenu
= co_IntCallLoadMenu( hModClient
, &MenuName
);
1678 //ERR("%wZ\n",&MenuName);
1683 IntReleaseMenuObject(SysMenu
);
1684 UserDestroyMenu(hSysMenu
);
1687 Menu
= IntGetMenuObject(hNewMenu
);
1690 IntReleaseMenuObject(SysMenu
);
1691 UserDestroyMenu(hSysMenu
);
1695 // Do the rest in here.
1697 Menu
->fFlags
|= MNS_CHECKORBMP
| MNF_SYSMENU
| MNF_POPUP
;
1699 ItemInfoSet
.cbSize
= sizeof( MENUITEMINFOW
);
1700 ItemInfoSet
.fMask
= MIIM_BITMAP
;
1701 ItemInfoSet
.hbmpItem
= HBMMENU_POPUP_CLOSE
;
1702 IntMenuItemInfo(Menu
, SC_CLOSE
, FALSE
, &ItemInfoSet
, TRUE
, NULL
);
1703 ItemInfoSet
.hbmpItem
= HBMMENU_POPUP_RESTORE
;
1704 IntMenuItemInfo(Menu
, SC_RESTORE
, FALSE
, &ItemInfoSet
, TRUE
, NULL
);
1705 ItemInfoSet
.hbmpItem
= HBMMENU_POPUP_MAXIMIZE
;
1706 IntMenuItemInfo(Menu
, SC_MAXIMIZE
, FALSE
, &ItemInfoSet
, TRUE
, NULL
);
1707 ItemInfoSet
.hbmpItem
= HBMMENU_POPUP_MINIMIZE
;
1708 IntMenuItemInfo(Menu
, SC_MINIMIZE
, FALSE
, &ItemInfoSet
, TRUE
, NULL
);
1710 NewMenu
= IntCloneMenu(Menu
);
1712 IntReleaseMenuObject(NewMenu
);
1713 UserSetMenuDefaultItem(NewMenu
, SC_CLOSE
, FALSE
);
1715 IntDestroyMenuObject(Menu
, FALSE
);
1723 NewMenu
->fFlags
|= MNF_SYSMENU
| MNF_POPUP
;
1725 if (Window
->pcls
->style
& CS_NOCLOSE
)
1726 IntRemoveMenuItem(NewMenu
, SC_CLOSE
, MF_BYCOMMAND
, TRUE
);
1728 ItemInfo
.cbSize
= sizeof(MENUITEMINFOW
);
1729 ItemInfo
.fMask
= MIIM_FTYPE
| MIIM_STRING
| MIIM_STATE
| MIIM_SUBMENU
;
1731 ItemInfo
.fState
= MFS_ENABLED
;
1732 ItemInfo
.dwTypeData
= NULL
;
1734 ItemInfo
.hSubMenu
= UserHMGetHandle(NewMenu
);
1735 IntInsertMenuItem(SysMenu
, (UINT
) -1, TRUE
, &ItemInfo
, NULL
);
1739 ERR("failed to load system menu!\n");
1744 IntGetSystemMenu(PWND Window
, BOOL bRevert
)
1750 if (Window
->SystemMenu
)
1752 Menu
= UserGetMenuObject(Window
->SystemMenu
);
1753 if (Menu
&& !(Menu
->fFlags
& MNF_SYSDESKMN
))
1755 IntDestroyMenuObject(Menu
, TRUE
);
1756 Window
->SystemMenu
= NULL
;
1762 Menu
= Window
->SystemMenu
? UserGetMenuObject(Window
->SystemMenu
) : NULL
;
1763 if ((!Window
->SystemMenu
|| Menu
->fFlags
& MNF_SYSDESKMN
) && Window
->style
& WS_SYSMENU
)
1765 Menu
= MENU_GetSystemMenu(Window
, NULL
);
1766 Window
->SystemMenu
= Menu
? UserHMGetHandle(Menu
) : NULL
;
1770 if (Window
->SystemMenu
)
1772 HMENU hMenu
= IntGetSubMenu( Window
->SystemMenu
, 0);
1773 /* Store the dummy sysmenu handle to facilitate the refresh */
1774 /* of the close button if the SC_CLOSE item change */
1775 Menu
= UserGetMenuObject(hMenu
);
1778 Menu
->spwndNotify
= Window
;
1779 Menu
->fFlags
|= MNF_SYSSUBMENU
;
1787 IntSetSystemMenu(PWND Window
, PMENU Menu
)
1791 if (!(Window
->style
& WS_SYSMENU
)) return FALSE
;
1793 if (Window
->SystemMenu
)
1795 OldMenu
= UserGetMenuObject(Window
->SystemMenu
);
1798 OldMenu
->fFlags
&= ~MNF_SYSMENU
;
1799 IntDestroyMenuObject(OldMenu
, TRUE
);
1803 OldMenu
= MENU_GetSystemMenu(Window
, Menu
);
1805 { // Use spmenuSys too!
1806 Window
->SystemMenu
= UserHMGetHandle(OldMenu
);
1809 Window
->SystemMenu
= NULL
;
1811 if (Menu
&& Window
!= Menu
->spwndNotify
)
1813 Menu
->spwndNotify
= Window
;
1820 /* FUNCTIONS *****************************************************************/
1826 NtUserCheckMenuItem(
1832 DECLARE_RETURN(DWORD
);
1834 TRACE("Enter NtUserCheckMenuItem\n");
1835 UserEnterExclusive();
1837 if(!(Menu
= UserGetMenuObject(hMenu
)))
1842 RETURN( IntCheckMenuItem(Menu
, uIDCheckItem
, uCheck
));
1845 TRACE("Leave NtUserCheckMenuItem, ret=%lu\n",_ret_
);
1860 DECLARE_RETURN(BOOL
);
1862 TRACE("Enter NtUserDeleteMenu\n");
1863 UserEnterExclusive();
1865 if(!(Menu
= UserGetMenuObject(hMenu
)))
1870 RETURN( IntRemoveMenuItem(Menu
, uPosition
, uFlags
, TRUE
));
1873 TRACE("Leave NtUserDeleteMenu, ret=%i\n",_ret_
);
1879 * NtUserGetSystemMenu
1881 * The NtUserGetSystemMenu function allows the application to access the
1882 * window menu (also known as the system menu or the control menu) for
1883 * copying and modifying.
1887 * Handle to the window that will own a copy of the window menu.
1889 * Specifies the action to be taken. If this parameter is FALSE,
1890 * NtUserGetSystemMenu returns a handle to the copy of the window menu
1891 * currently in use. The copy is initially identical to the window menu
1892 * but it can be modified.
1893 * If this parameter is TRUE, GetSystemMenu resets the window menu back
1894 * to the default state. The previous window menu, if any, is destroyed.
1897 * If the bRevert parameter is FALSE, the return value is a handle to a
1898 * copy of the window menu. If the bRevert parameter is TRUE, the return
1906 NtUserGetSystemMenu(HWND hWnd
, BOOL bRevert
)
1910 DECLARE_RETURN(HMENU
);
1912 TRACE("Enter NtUserGetSystemMenu\n");
1915 if (!(Window
= UserGetWindowObject(hWnd
)))
1920 if (!(Menu
= IntGetSystemMenu(Window
, bRevert
)))
1925 RETURN(Menu
->head
.h
);
1928 TRACE("Leave NtUserGetSystemMenu, ret=%p\n", _ret_
);
1934 * NtUserSetSystemMenu
1941 NtUserSetSystemMenu(HWND hWnd
, HMENU hMenu
)
1943 BOOL Result
= FALSE
;
1946 DECLARE_RETURN(BOOL
);
1948 TRACE("Enter NtUserSetSystemMenu\n");
1949 UserEnterExclusive();
1951 if (!(Window
= UserGetWindowObject(hWnd
)))
1959 * Assign new menu handle and Up the Lock Count.
1961 if (!(Menu
= IntGetMenuObject(hMenu
)))
1966 Result
= IntSetSystemMenu(Window
, Menu
);
1969 EngSetLastError(ERROR_INVALID_MENU_HANDLE
);
1974 TRACE("Leave NtUserSetSystemMenu, ret=%i\n",_ret_
);
1983 NtUserGetTitleBarInfo(
1988 TITLEBARINFO bartitleinfo
;
1989 DECLARE_RETURN(BOOLEAN
);
1990 BOOLEAN retValue
= TRUE
;
1992 TRACE("Enter NtUserGetTitleBarInfo\n");
1993 UserEnterExclusive();
1995 /* Vaildate the windows handle */
1996 if (!(WindowObject
= UserGetWindowObject(hwnd
)))
1998 EngSetLastError(ERROR_INVALID_WINDOW_HANDLE
);
2004 /* Copy our usermode buffer bti to local buffer bartitleinfo */
2005 ProbeForRead(bti
, sizeof(TITLEBARINFO
), 1);
2006 RtlCopyMemory(&bartitleinfo
, bti
, sizeof(TITLEBARINFO
));
2008 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2010 /* Fail copy the data */
2011 EngSetLastError(ERROR_INVALID_PARAMETER
);
2016 /* Get the tile bar info */
2019 retValue
= intGetTitleBarInfo(WindowObject
, &bartitleinfo
);
2024 /* Copy our buffer to user mode buffer bti */
2025 ProbeForWrite(bti
, sizeof(TITLEBARINFO
), 1);
2026 RtlCopyMemory(bti
, &bartitleinfo
, sizeof(TITLEBARINFO
));
2028 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2030 /* Fail copy the data */
2031 EngSetLastError(ERROR_INVALID_PARAMETER
);
2041 TRACE("Leave NtUserGetTitleBarInfo, ret=%u\n",_ret_
);
2049 BOOL FASTCALL
UserDestroyMenu(HMENU hMenu
)
2052 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
2054 if(!(Menu
= UserGetMenuObject(hMenu
)))
2059 if (Menu
->head
.rpdesk
!= pti
->rpdesk
)
2061 EngSetLastError(ERROR_ACCESS_DENIED
);
2064 return IntDestroyMenuObject(Menu
, FALSE
);
2075 DECLARE_RETURN(BOOL
);
2077 TRACE("Enter NtUserDestroyMenu\n");
2078 UserEnterExclusive();
2080 if(!(Menu
= UserGetMenuObject(hMenu
)))
2084 if (Menu
->head
.rpdesk
!= gptiCurrent
->rpdesk
)
2086 EngSetLastError(ERROR_ACCESS_DENIED
);
2089 RETURN( IntDestroyMenuObject(Menu
, TRUE
));
2092 TRACE("Leave NtUserDestroyMenu, ret=%i\n",_ret_
);
2101 NtUserEnableMenuItem(
2107 DECLARE_RETURN(UINT
);
2109 TRACE("Enter NtUserEnableMenuItem\n");
2110 UserEnterExclusive();
2112 if(!(Menu
= UserGetMenuObject(hMenu
)))
2117 RETURN( IntEnableMenuItem(Menu
, uIDEnableItem
, uEnable
));
2120 TRACE("Leave NtUserEnableMenuItem, ret=%u\n",_ret_
);
2129 NtUserGetMenuBarInfo(
2139 NTSTATUS Status
= STATUS_SUCCESS
;
2141 DECLARE_RETURN(BOOL
);
2143 TRACE("Enter NtUserGetMenuBarInfo\n");
2146 if (!(pWnd
= UserGetWindowObject(hwnd
)))
2148 EngSetLastError(ERROR_INVALID_WINDOW_HANDLE
);
2155 if (!pWnd
->pcls
->fnid
)
2157 if (pWnd
->pcls
->fnid
!= FNID_MENU
)
2159 WARN("called on invalid window: %d\n", pWnd
->pcls
->fnid
);
2160 EngSetLastError(ERROR_INVALID_MENU_HANDLE
);
2163 // Windows does this! Wine checks for Atom and uses GetWindowLongPtrW.
2164 hMenu
= (HMENU
)co_IntSendMessage(hwnd
, MN_GETHMENU
, 0, 0);
2167 hMenu
= UlongToHandle(pWnd
->IDMenu
);
2170 if (!(pWnd
->style
& WS_SYSMENU
)) RETURN(FALSE
);
2171 Menu
= IntGetSystemMenu(pWnd
, FALSE
);
2172 hMenu
= Menu
->head
.h
;
2183 kmbi
.cbSize
= pmbi
->cbSize
;
2185 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2191 if (kmbi
.cbSize
!= sizeof(MENUBARINFO
))
2193 EngSetLastError(ERROR_INVALID_PARAMETER
);
2197 if (!Menu
) Menu
= UserGetMenuObject(hMenu
);
2201 if (idItem
< 0 || idItem
> Menu
->cItems
)
2204 RECTL_vSetEmptyRect(&kmbi
.rcBar
);
2208 Ret
= IntGetMenuItemRect(pWnd
, Menu
, 0, &kmbi
.rcBar
);
2209 kmbi
.rcBar
.right
= kmbi
.rcBar
.left
+ Menu
->cxMenu
;
2210 kmbi
.rcBar
.bottom
= kmbi
.rcBar
.top
+ Menu
->cyMenu
;
2211 TRACE("idItem 0 %d\n",Ret
);
2215 Ret
= IntGetMenuItemRect(pWnd
, Menu
, idItem
-1, &kmbi
.rcBar
);
2216 TRACE("idItem X %d\n", Ret
);
2220 kmbi
.hwndMenu
= NULL
;
2221 kmbi
.fBarFocused
= FALSE
;
2222 kmbi
.fFocused
= FALSE
;
2223 //kmbi.fBarFocused = top_popup_hmenu == hMenu;
2226 kmbi
.fFocused
= Menu
->iItem
== idItem
-1;
2227 if (kmbi
.fFocused
&& (Menu
->rgItems
[idItem
- 1].spSubMenu
))
2229 kmbi
.hwndMenu
= Menu
->rgItems
[idItem
- 1].spSubMenu
->hWnd
;
2234 kmbi.fFocused = kmbi.fBarFocused;
2239 RtlCopyMemory(pmbi
, &kmbi
, sizeof(MENUBARINFO
));
2241 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2243 Status
= _SEH2_GetExceptionCode();
2247 if (!NT_SUCCESS(Status
))
2249 SetLastNtError(Status
);
2256 TRACE("Leave NtUserGetMenuBarInfo, ret=%i\n",_ret_
);
2269 PMENU Menu
, SubMenu
;
2272 DECLARE_RETURN(UINT
);
2274 TRACE("Enter NtUserGetMenuIndex\n");
2277 if ( !(Menu
= UserGetMenuObject(hMenu
)) ||
2278 !(SubMenu
= UserGetMenuObject(hSubMenu
)) )
2281 MenuItem
= Menu
->rgItems
;
2282 for (i
= 0; i
< Menu
->cItems
; i
++, MenuItem
++)
2284 if (MenuItem
->spSubMenu
== SubMenu
)
2285 RETURN(MenuItem
->wID
);
2290 TRACE("Leave NtUserGetMenuIndex, ret=%u\n",_ret_
);
2299 NtUserGetMenuItemRect(
2310 NTSTATUS Status
= STATUS_SUCCESS
;
2311 DECLARE_RETURN(BOOL
);
2313 TRACE("Enter NtUserGetMenuItemRect\n");
2316 if (!(Menu
= UserGetMenuObject(hMenu
)))
2321 if ((MenuItem
= MENU_FindItem (&Menu
, &uItem
, MF_BYPOSITION
)))
2323 Rect
.left
= MenuItem
->xItem
;
2324 Rect
.top
= MenuItem
->yItem
;
2325 Rect
.right
= MenuItem
->cxItem
; // Do this for now......
2326 Rect
.bottom
= MenuItem
->cyItem
;
2336 if (lprcItem
== NULL
) RETURN( FALSE
);
2338 if (!(ReferenceWnd
= UserGetWindowObject(hWnd
))) RETURN( FALSE
);
2340 if (Menu
->fFlags
& MNF_POPUP
)
2342 XMove
= ReferenceWnd
->rcClient
.left
;
2343 YMove
= ReferenceWnd
->rcClient
.top
;
2347 XMove
= ReferenceWnd
->rcWindow
.left
;
2348 YMove
= ReferenceWnd
->rcWindow
.top
;
2353 Rect
.right
+= XMove
;
2354 Rect
.bottom
+= YMove
;
2358 RtlCopyMemory(lprcItem
, &Rect
, sizeof(RECTL
));
2360 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2362 Status
= _SEH2_GetExceptionCode();
2366 if (!NT_SUCCESS(Status
))
2368 SetLastNtError(Status
);
2374 TRACE("Leave NtUserGetMenuItemRect, ret=%i\n",_ret_
);
2383 NtUserHiliteMenuItem(
2391 DECLARE_RETURN(BOOLEAN
);
2393 TRACE("Enter NtUserHiliteMenuItem\n");
2394 UserEnterExclusive();
2396 if(!(Window
= UserGetWindowObject(hWnd
)))
2398 EngSetLastError(ERROR_INVALID_WINDOW_HANDLE
);
2402 if(!(Menu
= UserGetMenuObject(hMenu
)))
2404 EngSetLastError(ERROR_INVALID_MENU_HANDLE
);
2408 RETURN( IntHiliteMenuItem(Window
, Menu
, uItemHilite
, uHilite
));
2411 TRACE("Leave NtUserHiliteMenuItem, ret=%u\n",_ret_
);
2421 NtUserMenuItemFromPoint(
2431 DECLARE_RETURN(int);
2433 TRACE("Enter NtUserMenuItemFromPoint\n");
2434 UserEnterExclusive();
2436 if (!(Menu
= UserGetMenuObject(hMenu
)))
2441 if (!(Window
= UserGetWindowObject(Menu
->hWnd
)))
2446 X
-= Window
->rcWindow
.left
;
2447 Y
-= Window
->rcWindow
.top
;
2450 for (i
= 0; i
< Menu
->cItems
; i
++, mi
++)
2453 Rect
.left
= mi
->xItem
;
2454 Rect
.top
= mi
->yItem
;
2455 Rect
.right
= mi
->cxItem
; // Do this for now......
2456 Rect
.bottom
= mi
->cyItem
;
2457 //MENU_AdjustMenuItemRect(Menu, &Rect); Need gpsi OBMI via callback!
2458 if (RECTL_bPointInRect(&Rect
, X
, Y
))
2464 RETURN( (mi
? i
: NO_SELECTED_ITEM
));
2467 TRACE("Leave NtUserMenuItemFromPoint, ret=%i\n",_ret_
);
2483 DECLARE_RETURN(BOOL
);
2485 TRACE("Enter NtUserRemoveMenu\n");
2486 UserEnterExclusive();
2488 if(!(Menu
= UserGetMenuObject(hMenu
)))
2493 RETURN(IntRemoveMenuItem(Menu
, uPosition
, uFlags
, FALSE
));
2496 TRACE("Leave NtUserRemoveMenu, ret=%i\n",_ret_
);
2506 NtUserSetMenuContextHelpId(
2508 DWORD dwContextHelpId
)
2511 DECLARE_RETURN(BOOL
);
2513 TRACE("Enter NtUserSetMenuContextHelpId\n");
2514 UserEnterExclusive();
2516 if(!(Menu
= UserGetMenuObject(hMenu
)))
2521 RETURN(IntSetMenuContextHelpId(Menu
, dwContextHelpId
));
2524 TRACE("Leave NtUserSetMenuContextHelpId, ret=%i\n",_ret_
);
2533 NtUserSetMenuDefaultItem(
2539 DECLARE_RETURN(BOOL
);
2541 TRACE("Enter NtUserSetMenuDefaultItem\n");
2542 UserEnterExclusive();
2544 if(!(Menu
= UserGetMenuObject(hMenu
)))
2549 RETURN( UserSetMenuDefaultItem(Menu
, uItem
, fByPos
));
2552 TRACE("Leave NtUserSetMenuDefaultItem, ret=%i\n",_ret_
);
2561 NtUserSetMenuFlagRtoL(
2565 DECLARE_RETURN(BOOL
);
2567 TRACE("Enter NtUserSetMenuFlagRtoL\n");
2568 UserEnterExclusive();
2570 if(!(Menu
= UserGetMenuObject(hMenu
)))
2575 RETURN(IntSetMenuFlagRtoL(Menu
));
2578 TRACE("Leave NtUserSetMenuFlagRtoL, ret=%i\n",_ret_
);
2587 NtUserThunkedMenuInfo(
2592 DECLARE_RETURN(BOOL
);
2594 TRACE("Enter NtUserThunkedMenuInfo\n");
2595 UserEnterExclusive();
2597 if (!(Menu
= UserGetMenuObject(hMenu
)))
2602 RETURN(UserMenuInfo(Menu
, (PROSMENUINFO
)lpcmi
, TRUE
));
2605 TRACE("Leave NtUserThunkedMenuInfo, ret=%i\n",_ret_
);
2614 NtUserThunkedMenuItemInfo(
2619 LPMENUITEMINFOW lpmii
,
2620 PUNICODE_STRING lpszCaption
)
2624 UNICODE_STRING lstrCaption
;
2625 DECLARE_RETURN(BOOL
);
2627 TRACE("Enter NtUserThunkedMenuItemInfo\n");
2628 UserEnterExclusive();
2630 /* lpszCaption may be NULL, check for it and call RtlInitUnicodeString()
2631 if bInsert == TRUE call UserInsertMenuItem() else UserSetMenuItemInfo() */
2633 if (!(Menu
= UserGetMenuObject(hMenu
)))
2638 RtlInitUnicodeString(&lstrCaption
, 0);
2640 /* Check if we got a Caption */
2641 if (lpszCaption
&& lpszCaption
->Buffer
)
2643 /* Copy the string to kernel mode */
2644 Status
= ProbeAndCaptureUnicodeString( &lstrCaption
,
2647 if (!NT_SUCCESS(Status
))
2649 ERR("Failed to capture MenuItem Caption (status 0x%08x)\n",Status
);
2650 SetLastNtError(Status
);
2655 if (bInsert
) RETURN( UserInsertMenuItem(Menu
, uItem
, fByPosition
, lpmii
, &lstrCaption
));
2657 RETURN( UserMenuItemInfo(Menu
, uItem
, fByPosition
, (PROSMENUITEMINFO
)lpmii
, TRUE
, &lstrCaption
));
2660 TRACE("Leave NtUserThunkedMenuItemInfo, ret=%i\n",_ret_
);