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 if (UserObjectInDestroy(Menu
->head
.h
))
257 ERR("Menu already dead!\n");
260 ret
= UserDeleteObject(Menu
->head
.h
, TYPE_MENU
);
262 { // Make sure it is really dead or just marked for deletion.
263 ret
= UserObjectInDestroy(Menu
->head
.h
);
264 if (ret
&& EngGetLastError() == ERROR_INVALID_HANDLE
) ret
= FALSE
;
265 } // See test_subpopup_locked_by_menu tests....
272 /**********************************************************************
275 * detect if there are loops in the menu tree (or the depth is too large)
277 int FASTCALL
MENU_depth( PMENU pmenu
, int depth
)
283 if (!pmenu
) return depth
;
286 if( depth
> MAXMENUDEPTH
) return depth
;
287 item
= pmenu
->rgItems
;
289 for( i
= 0; item
, i
< pmenu
->cItems
&& subdepth
<= MAXMENUDEPTH
; i
++, item
++)
291 if( item
->spSubMenu
)//VerifyMenu(item->spSubMenu))
293 int bdepth
= MENU_depth( item
->spSubMenu
, depth
);
294 if( bdepth
> subdepth
) subdepth
= bdepth
;
296 if( subdepth
> MAXMENUDEPTH
)
297 TRACE("<- hmenu %p\n", item
->spSubMenu
);
302 /***********************************************************************
305 * Find a menu item. Return a pointer on the item, and modifies *hmenu
306 * in case the item was in a sub-menu.
308 PITEM FASTCALL
MENU_FindItem( PMENU
*pmenu
, UINT
*nPos
, UINT wFlags
)
311 ITEM
*fallback
= NULL
;
312 UINT fallback_pos
= 0;
315 if (!menu
) return NULL
;
317 if (wFlags
& MF_BYPOSITION
)
319 if (!menu
->cItems
) return NULL
;
320 if (*nPos
>= menu
->cItems
) return NULL
;
321 return &menu
->rgItems
[*nPos
];
325 PITEM item
= menu
->rgItems
;
326 for (i
= 0; item
, i
< menu
->cItems
; i
++, item
++)
330 PMENU psubmenu
= item
->spSubMenu
;//VerifyMenu(item->spSubMenu);
331 PITEM subitem
= MENU_FindItem( &psubmenu
, nPos
, wFlags
);
337 else if (item
->wID
== *nPos
)
339 /* fallback to this item if nothing else found */
344 else if (item
->wID
== *nPos
)
353 *nPos
= fallback_pos
;
359 IntRemoveMenuItem( PMENU pMenu
, UINT nPos
, UINT wFlags
, BOOL bRecurse
)
363 TRACE("(menu=%p pos=%04x flags=%04x)\n",pMenu
, nPos
, wFlags
);
364 if (!(item
= MENU_FindItem( &pMenu
, &nPos
, wFlags
))) return FALSE
;
368 FreeMenuText(pMenu
,item
);
369 if (bRecurse
&& item
->spSubMenu
)
371 IntDestroyMenuObject(item
->spSubMenu
, bRecurse
);
373 ////// Use cAlloced with inc's of 8's....
374 if (--pMenu
->cItems
== 0)
376 DesktopHeapFree(pMenu
->head
.rpdesk
, pMenu
->rgItems
);
377 pMenu
->rgItems
= NULL
;
381 while(nPos
< pMenu
->cItems
)
387 pMenu
->rgItems
= DesktopHeapReAlloc(pMenu
->head
.rpdesk
, pMenu
->rgItems
, pMenu
->cItems
* sizeof(ITEM
));
392 /**********************************************************************
395 * Insert (allocate) a new item into a menu.
397 ITEM
*MENU_InsertItem( PMENU menu
, UINT pos
, UINT flags
, PMENU
*submenu
, UINT
*npos
)
401 /* Find where to insert new item */
403 if (flags
& MF_BYPOSITION
) {
404 if (pos
> menu
->cItems
)
407 if (!MENU_FindItem( &menu
, &pos
, flags
))
409 if (submenu
) *submenu
= menu
;
410 if (npos
) *npos
= pos
;
415 /* Make sure that MDI system buttons stay on the right side.
416 * Note: XP treats only bitmap handles 1 - 6 as "magic" ones
417 * regardless of their id.
420 (INT_PTR
)menu
->rgItems
[pos
- 1].hbmp
>= (INT_PTR
)HBMMENU_SYSTEM
&&
421 (INT_PTR
)menu
->rgItems
[pos
- 1].hbmp
<= (INT_PTR
)HBMMENU_MBAR_CLOSE_D
)
424 TRACE("inserting at %u flags %x\n", pos
, flags
);
426 /* Create new items array */
428 newItems
= DesktopHeapAlloc(menu
->head
.rpdesk
, sizeof(ITEM
) * (menu
->cItems
+1) );
431 WARN("allocation failed\n" );
434 if (menu
->cItems
> 0)
436 /* Copy the old array into the new one */
437 if (pos
> 0) RtlCopyMemory( newItems
, menu
->rgItems
, pos
* sizeof(ITEM
) );
438 if (pos
< menu
->cItems
) RtlCopyMemory( &newItems
[pos
+1], &menu
->rgItems
[pos
], (menu
->cItems
-pos
)*sizeof(ITEM
) );
439 DesktopHeapFree(menu
->head
.rpdesk
, menu
->rgItems
);
441 menu
->rgItems
= newItems
;
443 RtlZeroMemory( &newItems
[pos
], sizeof(*newItems
) );
444 menu
->cyMenu
= 0; /* force size recalculate */
445 return &newItems
[pos
];
450 _In_ PMENU MenuObject
,
453 PROSMENUITEMINFO ItemInfo
,
454 PUNICODE_STRING lpstr
)
457 PMENU SubMenu
= NULL
;
459 NT_ASSERT(MenuObject
!= NULL
);
461 if (MAX_MENU_ITEMS
<= MenuObject
->cItems
)
463 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY
);
467 SubMenu
= MenuObject
;
469 if(!(MenuItem
= MENU_InsertItem( SubMenu
, uItem
, fByPosition
? MF_BYPOSITION
: MF_BYCOMMAND
, &SubMenu
, &uItem
))) return FALSE
;
471 if(!IntSetMenuItemInfo(SubMenu
, MenuItem
, ItemInfo
, lpstr
))
473 IntRemoveMenuItem(SubMenu
, uItem
, fByPosition
? MF_BYPOSITION
: MF_BYCOMMAND
, FALSE
);
477 /* Force size recalculation! */
479 MenuItem
->hbmpChecked
= MenuItem
->hbmpUnchecked
= 0;
481 TRACE("IntInsertMenuItemToList = %i %d\n", uItem
, (BOOL
)((INT
)uItem
>= 0));
488 _Out_ PHANDLE Handle
,
490 _In_ PDESKTOP Desktop
,
491 _In_ PPROCESSINFO ppi
)
495 Menu
= (PMENU
)UserCreateObject( gHandleTable
,
507 Menu
->cyMax
= 0; /* Default */
508 Menu
->hbrBack
= NULL
; /* No brush */
509 Menu
->dwContextHelpId
= 0; /* Default */
510 Menu
->dwMenuData
= 0; /* Default */
511 Menu
->iItem
= NO_SELECTED_ITEM
; // Focused item
512 Menu
->fFlags
= (IsMenuBar
? 0 : MNF_POPUP
);
513 Menu
->spwndNotify
= NULL
;
514 Menu
->cyMenu
= 0; // Height
515 Menu
->cxMenu
= 0; // Width
516 Menu
->cItems
= 0; // Item count
519 Menu
->cxTextAlign
= 0;
520 Menu
->rgItems
= NULL
;
523 Menu
->TimeToHide
= FALSE
;
529 IntCloneMenuItems(PMENU Destination
, PMENU Source
)
531 PITEM MenuItem
, NewMenuItem
= NULL
;
537 NewMenuItem
= DesktopHeapAlloc(Destination
->head
.rpdesk
, (Source
->cItems
+1) * sizeof(ITEM
));
538 if(!NewMenuItem
) return FALSE
;
540 RtlZeroMemory(NewMenuItem
, (Source
->cItems
+1) * sizeof(ITEM
));
542 Destination
->rgItems
= NewMenuItem
;
544 MenuItem
= Source
->rgItems
;
545 for (i
= 0; i
< Source
->cItems
; i
++, MenuItem
++, NewMenuItem
++)
547 NewMenuItem
->fType
= MenuItem
->fType
;
548 NewMenuItem
->fState
= MenuItem
->fState
;
549 NewMenuItem
->wID
= MenuItem
->wID
;
550 NewMenuItem
->spSubMenu
= MenuItem
->spSubMenu
;
551 NewMenuItem
->hbmpChecked
= MenuItem
->hbmpChecked
;
552 NewMenuItem
->hbmpUnchecked
= MenuItem
->hbmpUnchecked
;
553 NewMenuItem
->dwItemData
= MenuItem
->dwItemData
;
554 if (MenuItem
->lpstr
.Length
)
556 NewMenuItem
->lpstr
.Length
= 0;
557 NewMenuItem
->lpstr
.MaximumLength
= MenuItem
->lpstr
.MaximumLength
;
558 NewMenuItem
->lpstr
.Buffer
= DesktopHeapAlloc(Destination
->head
.rpdesk
, MenuItem
->lpstr
.MaximumLength
);
559 if (!NewMenuItem
->lpstr
.Buffer
)
561 DesktopHeapFree(Destination
->head
.rpdesk
, NewMenuItem
);
564 RtlCopyUnicodeString(&NewMenuItem
->lpstr
, &MenuItem
->lpstr
);
565 NewMenuItem
->lpstr
.Buffer
[MenuItem
->lpstr
.Length
/ sizeof(WCHAR
)] = 0;
566 NewMenuItem
->Xlpstr
= NewMenuItem
->lpstr
.Buffer
;
570 NewMenuItem
->lpstr
.Buffer
= MenuItem
->lpstr
.Buffer
;
571 NewMenuItem
->Xlpstr
= NewMenuItem
->lpstr
.Buffer
;
573 NewMenuItem
->hbmp
= MenuItem
->hbmp
;
579 IntCloneMenu(PMENU Source
)
587 /* A menu is valid process wide. We can pass to the object manager any thread ptr */
588 Menu
= (PMENU
)UserCreateObject( gHandleTable
,
590 ((PPROCESSINFO
)Source
->head
.hTaskWow
)->ptiList
,
597 Menu
->fFlags
= Source
->fFlags
;
598 Menu
->cyMax
= Source
->cyMax
;
599 Menu
->hbrBack
= Source
->hbrBack
;
600 Menu
->dwContextHelpId
= Source
->dwContextHelpId
;
601 Menu
->dwMenuData
= Source
->dwMenuData
;
602 Menu
->iItem
= NO_SELECTED_ITEM
;
603 Menu
->spwndNotify
= NULL
;
606 Menu
->cItems
= Source
->cItems
;
609 Menu
->cxTextAlign
= 0;
610 Menu
->rgItems
= NULL
;
613 Menu
->TimeToHide
= FALSE
;
615 IntCloneMenuItems(Menu
, Source
);
621 IntSetMenuFlagRtoL(PMENU Menu
)
623 Menu
->fFlags
|= MNF_RTOL
;
628 IntSetMenuContextHelpId(PMENU Menu
, DWORD dwContextHelpId
)
630 Menu
->dwContextHelpId
= dwContextHelpId
;
635 IntGetMenuInfo(PMENU Menu
, PROSMENUINFO lpmi
)
637 if(lpmi
->fMask
& MIM_BACKGROUND
)
638 lpmi
->hbrBack
= Menu
->hbrBack
;
639 if(lpmi
->fMask
& MIM_HELPID
)
640 lpmi
->dwContextHelpID
= Menu
->dwContextHelpId
;
641 if(lpmi
->fMask
& MIM_MAXHEIGHT
)
642 lpmi
->cyMax
= Menu
->cyMax
;
643 if(lpmi
->fMask
& MIM_MENUDATA
)
644 lpmi
->dwMenuData
= Menu
->dwMenuData
;
645 if(lpmi
->fMask
& MIM_STYLE
)
646 lpmi
->dwStyle
= Menu
->fFlags
& MNS_STYLE_MASK
;
648 if (sizeof(MENUINFO
) < lpmi
->cbSize
)
650 lpmi
->cItems
= Menu
->cItems
;
652 lpmi
->iItem
= Menu
->iItem
;
653 lpmi
->cxMenu
= Menu
->cxMenu
;
654 lpmi
->cyMenu
= Menu
->cyMenu
;
655 lpmi
->spwndNotify
= Menu
->spwndNotify
;
656 lpmi
->cxTextAlign
= Menu
->cxTextAlign
;
657 lpmi
->iTop
= Menu
->iTop
;
658 lpmi
->iMaxTop
= Menu
->iMaxTop
;
659 lpmi
->dwArrowsOn
= Menu
->dwArrowsOn
;
661 lpmi
->fFlags
= Menu
->fFlags
;
662 lpmi
->Self
= Menu
->head
.h
;
663 lpmi
->TimeToHide
= Menu
->TimeToHide
;
664 lpmi
->Wnd
= Menu
->hWnd
;
670 IntSetMenuInfo(PMENU Menu
, PROSMENUINFO lpmi
)
672 if(lpmi
->fMask
& MIM_BACKGROUND
)
673 Menu
->hbrBack
= lpmi
->hbrBack
;
674 if(lpmi
->fMask
& MIM_HELPID
)
675 Menu
->dwContextHelpId
= lpmi
->dwContextHelpID
;
676 if(lpmi
->fMask
& MIM_MAXHEIGHT
)
677 Menu
->cyMax
= lpmi
->cyMax
;
678 if(lpmi
->fMask
& MIM_MENUDATA
)
679 Menu
->dwMenuData
= lpmi
->dwMenuData
;
680 if(lpmi
->fMask
& MIM_STYLE
)
681 Menu
->fFlags
^= (Menu
->fFlags
^ lpmi
->dwStyle
) & MNS_STYLE_MASK
;
682 if(lpmi
->fMask
& MIM_APPLYTOSUBMENUS
)
685 PITEM item
= Menu
->rgItems
;
686 for ( i
= Menu
->cItems
; i
; i
--, item
++)
688 if ( item
->spSubMenu
)
690 IntSetMenuInfo( item
->spSubMenu
, lpmi
);
694 if (sizeof(MENUINFO
) < lpmi
->cbSize
)
696 Menu
->iItem
= lpmi
->iItem
;
697 Menu
->cyMenu
= lpmi
->cyMenu
;
698 Menu
->cxMenu
= lpmi
->cxMenu
;
699 Menu
->spwndNotify
= lpmi
->spwndNotify
;
700 Menu
->cxTextAlign
= lpmi
->cxTextAlign
;
701 Menu
->iTop
= lpmi
->iTop
;
702 Menu
->iMaxTop
= lpmi
->iMaxTop
;
703 Menu
->dwArrowsOn
= lpmi
->dwArrowsOn
;
705 Menu
->TimeToHide
= lpmi
->TimeToHide
;
706 Menu
->hWnd
= lpmi
->Wnd
;
712 IntGetMenuItemInfo(PMENU Menu
, /* UNUSED PARAM!! */
713 PITEM MenuItem
, PROSMENUITEMINFO lpmii
)
717 if(lpmii
->fMask
& (MIIM_FTYPE
| MIIM_TYPE
))
719 lpmii
->fType
= MenuItem
->fType
;
721 if(lpmii
->fMask
& MIIM_BITMAP
)
723 lpmii
->hbmpItem
= MenuItem
->hbmp
;
725 if(lpmii
->fMask
& MIIM_CHECKMARKS
)
727 lpmii
->hbmpChecked
= MenuItem
->hbmpChecked
;
728 lpmii
->hbmpUnchecked
= MenuItem
->hbmpUnchecked
;
730 if(lpmii
->fMask
& MIIM_DATA
)
732 lpmii
->dwItemData
= MenuItem
->dwItemData
;
734 if(lpmii
->fMask
& MIIM_ID
)
736 lpmii
->wID
= MenuItem
->wID
;
738 if(lpmii
->fMask
& MIIM_STATE
)
740 lpmii
->fState
= MenuItem
->fState
;
742 if(lpmii
->fMask
& MIIM_SUBMENU
)
744 lpmii
->hSubMenu
= MenuItem
->spSubMenu
? MenuItem
->spSubMenu
->head
.h
: NULL
;
747 if ((lpmii
->fMask
& MIIM_STRING
) ||
748 ((lpmii
->fMask
& MIIM_TYPE
) && (MENU_ITEM_TYPE(lpmii
->fType
) == MF_STRING
)))
750 if (lpmii
->dwTypeData
== NULL
)
752 lpmii
->cch
= MenuItem
->lpstr
.Length
/ sizeof(WCHAR
);
755 { //// lpmii->lpstr can be read in user mode!!!!
756 Status
= MmCopyToCaller(lpmii
->dwTypeData
, MenuItem
->lpstr
.Buffer
,
757 min(lpmii
->cch
* sizeof(WCHAR
),
758 MenuItem
->lpstr
.MaximumLength
));
759 if (! NT_SUCCESS(Status
))
761 SetLastNtError(Status
);
767 if (sizeof(ROSMENUITEMINFO
) == lpmii
->cbSize
)
769 lpmii
->Rect
.left
= MenuItem
->xItem
;
770 lpmii
->Rect
.top
= MenuItem
->yItem
;
771 lpmii
->Rect
.right
= MenuItem
->cxItem
; // Do this for now......
772 lpmii
->Rect
.bottom
= MenuItem
->cyItem
;
773 lpmii
->dxTab
= MenuItem
->dxTab
;
774 lpmii
->lpstr
= MenuItem
->lpstr
.Buffer
;
775 lpmii
->maxBmpSize
.cx
= MenuItem
->cxBmp
;
776 lpmii
->maxBmpSize
.cy
= MenuItem
->cyBmp
;
783 IntSetMenuItemInfo(PMENU MenuObject
, PITEM MenuItem
, PROSMENUITEMINFO lpmii
, PUNICODE_STRING lpstr
)
786 BOOL circref
= FALSE
;
788 if(!MenuItem
|| !MenuObject
|| !lpmii
)
792 if ( lpmii
->fMask
& MIIM_FTYPE
)
794 MenuItem
->fType
&= ~MENUITEMINFO_TYPE_MASK
;
795 MenuItem
->fType
|= lpmii
->fType
& MENUITEMINFO_TYPE_MASK
;
797 if (lpmii
->fMask
& MIIM_TYPE
)
799 #if 0 //// Done in User32.
800 if (lpmii
->fMask
& ( MIIM_STRING
| MIIM_FTYPE
| MIIM_BITMAP
))
802 ERR("IntSetMenuItemInfo: Invalid combination of fMask bits used\n");
803 KeRosDumpStackFrames(NULL
, 20);
804 /* This does not happen on Win9x/ME */
805 SetLastNtError( ERROR_INVALID_PARAMETER
);
810 * Delete the menu item type when changing type from
813 if (MenuItem
->fType
!= lpmii
->fType
&&
814 MENU_ITEM_TYPE(MenuItem
->fType
) == MFT_STRING
)
816 FreeMenuText(MenuObject
,MenuItem
);
817 RtlInitUnicodeString(&MenuItem
->lpstr
, NULL
);
818 MenuItem
->Xlpstr
= NULL
;
820 if(lpmii
->fType
& MFT_BITMAP
)
823 MenuItem
->hbmp
= lpmii
->hbmpItem
;
825 { /* Win 9x/Me stuff */
826 MenuItem
->hbmp
= (HBITMAP
)((ULONG_PTR
)(LOWORD(lpmii
->dwTypeData
)));
828 lpmii
->dwTypeData
= 0;
831 if(lpmii
->fMask
& MIIM_BITMAP
)
833 MenuItem
->hbmp
= lpmii
->hbmpItem
;
834 if (MenuItem
->hbmp
<= HBMMENU_POPUP_MINIMIZE
&& MenuItem
->hbmp
>= HBMMENU_CALLBACK
)
835 MenuItem
->fState
|= MFS_HBMMENUBMP
;
837 MenuItem
->fState
&= ~MFS_HBMMENUBMP
;
839 if(lpmii
->fMask
& MIIM_CHECKMARKS
)
841 MenuItem
->hbmpChecked
= lpmii
->hbmpChecked
;
842 MenuItem
->hbmpUnchecked
= lpmii
->hbmpUnchecked
;
844 if(lpmii
->fMask
& MIIM_DATA
)
846 MenuItem
->dwItemData
= lpmii
->dwItemData
;
848 if(lpmii
->fMask
& MIIM_ID
)
850 MenuItem
->wID
= lpmii
->wID
;
852 if(lpmii
->fMask
& MIIM_STATE
)
854 /* Remove MFS_DEFAULT flag from all other menu items if this item
855 has the MFS_DEFAULT state */
856 if(lpmii
->fState
& MFS_DEFAULT
)
857 UserSetMenuDefaultItem(MenuObject
, -1, 0);
858 /* Update the menu item state flags */
859 UpdateMenuItemState(MenuItem
->fState
, lpmii
->fState
);
862 if(lpmii
->fMask
& MIIM_SUBMENU
)
866 SubMenuObject
= UserGetMenuObject(lpmii
->hSubMenu
);
867 if ( SubMenuObject
&& !(UserObjectInDestroy(lpmii
->hSubMenu
)) )
869 //// wine Bug 12171 : Adding Popup Menu to itself! Could create endless loops.
871 if (MenuObject
== SubMenuObject
)
874 ERR("Pop Up Menu Double Trouble!\n");
875 SubMenuObject
= IntCreateMenu(&hMenu
,
877 MenuObject
->head
.rpdesk
,
878 (PPROCESSINFO
)MenuObject
->head
.hTaskWow
); // It will be marked.
879 if (!SubMenuObject
) return FALSE
;
880 IntReleaseMenuObject(SubMenuObject
); // This will be referenced again after insertion.
883 if ( MENU_depth( SubMenuObject
, 0) > MAXMENUDEPTH
)
885 ERR( "Loop detected in menu hierarchy or maximum menu depth exceeded!\n");
886 if (circref
) IntDestroyMenuObject(SubMenuObject
, FALSE
);
889 /* Make sure the submenu is marked as a popup menu */
890 SubMenuObject
->fFlags
|= MNF_POPUP
;
891 // Now fix the test_subpopup_locked_by_menu tests....
892 if (MenuItem
->spSubMenu
) IntReleaseMenuObject(MenuItem
->spSubMenu
);
893 MenuItem
->spSubMenu
= SubMenuObject
;
894 UserReferenceObject(SubMenuObject
);
898 EngSetLastError( ERROR_INVALID_PARAMETER
);
903 { // If submenu just dereference it.
904 if (MenuItem
->spSubMenu
) IntReleaseMenuObject(MenuItem
->spSubMenu
);
905 MenuItem
->spSubMenu
= NULL
;
909 if ((lpmii
->fMask
& MIIM_STRING
) ||
910 ((lpmii
->fMask
& MIIM_TYPE
) && (MENU_ITEM_TYPE(lpmii
->fType
) == MF_STRING
)))
912 /* free the string when used */
913 FreeMenuText(MenuObject
,MenuItem
);
914 RtlInitUnicodeString(&MenuItem
->lpstr
, NULL
);
915 MenuItem
->Xlpstr
= NULL
;
917 if(lpmii
->dwTypeData
&& lpmii
->cch
&& lpstr
&& lpstr
->Buffer
)
919 UNICODE_STRING Source
;
921 Source
.Length
= Source
.MaximumLength
= lpmii
->cch
* sizeof(WCHAR
);
922 Source
.Buffer
= lpmii
->dwTypeData
;
924 MenuItem
->lpstr
.Buffer
= DesktopHeapAlloc( MenuObject
->head
.rpdesk
, Source
.Length
+ sizeof(WCHAR
));
925 if(MenuItem
->lpstr
.Buffer
!= NULL
)
927 MenuItem
->lpstr
.Length
= 0;
928 MenuItem
->lpstr
.MaximumLength
= Source
.Length
+ sizeof(WCHAR
);
929 RtlCopyUnicodeString(&MenuItem
->lpstr
, &Source
);
930 MenuItem
->lpstr
.Buffer
[MenuItem
->lpstr
.Length
/ sizeof(WCHAR
)] = 0;
932 MenuItem
->cch
= MenuItem
->lpstr
.Length
/ sizeof(WCHAR
);
933 MenuItem
->Xlpstr
= (USHORT
*)MenuItem
->lpstr
.Buffer
;
938 if( !(MenuObject
->fFlags
& MNF_SYSMENU
) &&
940 !lpmii
->dwTypeData
&&
941 !(MenuItem
->fType
& MFT_OWNERDRAW
) &&
943 MenuItem
->fType
|= MFT_SEPARATOR
;
945 if (sizeof(ROSMENUITEMINFO
) == lpmii
->cbSize
)
947 MenuItem
->xItem
= lpmii
->Rect
.left
;
948 MenuItem
->yItem
= lpmii
->Rect
.top
;
949 MenuItem
->cxItem
= lpmii
->Rect
.right
; // Do this for now......
950 MenuItem
->cyItem
= lpmii
->Rect
.bottom
;
951 MenuItem
->dxTab
= lpmii
->dxTab
;
952 lpmii
->lpstr
= MenuItem
->lpstr
.Buffer
; /* Send back new allocated string or zero */
953 MenuItem
->cxBmp
= lpmii
->maxBmpSize
.cx
;
954 MenuItem
->cyBmp
= lpmii
->maxBmpSize
.cy
;
962 IntEnableMenuItem(PMENU MenuObject
, UINT uIDEnableItem
, UINT uEnable
)
967 if (!(MenuItem
= MENU_FindItem( &MenuObject
, &uIDEnableItem
, uEnable
))) return (UINT
)-1;
969 res
= MenuItem
->fState
& (MF_GRAYED
| MF_DISABLED
);
971 MenuItem
->fState
^= (res
^ uEnable
) & (MF_GRAYED
| MF_DISABLED
);
973 /* If the close item in the system menu change update the close button */
974 if((MenuItem
->wID
== SC_CLOSE
) && (res
!= uEnable
))
976 if (MenuObject
->fFlags
& MNF_SYSSUBMENU
&& MenuObject
->spwndNotify
!= 0)
978 RECTL rc
= MenuObject
->spwndNotify
->rcWindow
;
980 /* Refresh the frame to reflect the change */
981 IntMapWindowPoints(0, MenuObject
->spwndNotify
, (POINT
*)&rc
, 2);
983 co_UserRedrawWindow(MenuObject
->spwndNotify
, &rc
, 0, RDW_FRAME
| RDW_INVALIDATE
| RDW_NOCHILDREN
);
990 IntCheckMenuItem(PMENU MenuObject
, UINT uIDCheckItem
, UINT uCheck
)
995 if (!(MenuItem
= MENU_FindItem( &MenuObject
, &uIDCheckItem
, uCheck
))) return -1;
997 res
= (DWORD
)(MenuItem
->fState
& MF_CHECKED
);
999 MenuItem
->fState
^= (res
^ uCheck
) & MF_CHECKED
;
1005 IntHiliteMenuItem(PWND WindowObject
,
1012 if (!(MenuItem
= MENU_FindItem( &MenuObject
, &uItemHilite
, uHilite
))) return FALSE
;
1014 if (uHilite
& MF_HILITE
)
1016 MenuItem
->fState
|= MF_HILITE
;
1020 MenuItem
->fState
&= ~MF_HILITE
;
1022 /* FIXME: Update the window's menu */
1024 return TRUE
; // Always returns true!!!!
1028 UserSetMenuDefaultItem(PMENU MenuObject
, UINT uItem
, UINT fByPos
)
1031 PITEM MenuItem
= MenuObject
->rgItems
;
1033 if (!MenuItem
) return FALSE
;
1035 /* reset all default-item flags */
1036 for (i
= 0; MenuItem
, i
< MenuObject
->cItems
; i
++, MenuItem
++)
1038 MenuItem
->fState
&= ~MFS_DEFAULT
;
1041 /* no default item */
1042 if(uItem
== (UINT
)-1)
1046 MenuItem
= MenuObject
->rgItems
;
1049 if ( uItem
>= MenuObject
->cItems
) return FALSE
;
1050 MenuItem
[uItem
].fState
|= MFS_DEFAULT
;
1055 for (i
= 0; MenuItem
, i
< MenuObject
->cItems
; i
++, MenuItem
++)
1057 if (MenuItem
->wID
== uItem
)
1059 MenuItem
->fState
|= MFS_DEFAULT
;
1070 IntGetMenuDefaultItem(PMENU MenuObject
, UINT fByPos
, UINT gmdiFlags
, DWORD
*gismc
)
1073 PITEM MenuItem
= MenuObject
->rgItems
;
1076 if (!MenuItem
) return -1;
1078 while ( !( MenuItem
->fState
& MFS_DEFAULT
) )
1081 if (i
>= MenuObject
->cItems
) return -1;
1084 /* default: don't return disabled items */
1085 if ( (!(GMDI_USEDISABLED
& gmdiFlags
)) && (MenuItem
->fState
& MFS_DISABLED
)) return -1;
1087 /* search rekursiv when needed */
1088 if ( (MenuItem
->fType
& MF_POPUP
) && (gmdiFlags
& GMDI_GOINTOPOPUPS
) && MenuItem
->spSubMenu
)
1092 ret
= IntGetMenuDefaultItem( MenuItem
->spSubMenu
, fByPos
, gmdiFlags
, gismc
);
1094 if ( -1 != ret
) return ret
;
1096 /* when item not found in submenu, return the popup item */
1098 return ( fByPos
) ? i
: MenuItem
->wID
;
1102 co_IntInitTracking(PWND Window
, PMENU Menu
, BOOL Popup
,
1105 /* FIXME: Hide caret */
1107 if(!(Flags
& TPM_NONOTIFY
))
1108 co_IntSendMessage(Window
->head
.h
, WM_SETCURSOR
, (WPARAM
)Window
->head
.h
, HTCAPTION
);
1110 /* FIXME: Send WM_SETCURSOR message */
1112 if(!(Flags
& TPM_NONOTIFY
))
1113 co_IntSendMessage(Window
->head
.h
, WM_INITMENU
, (WPARAM
)Menu
->head
.h
, 0);
1117 co_IntExitTracking(PWND Window
, PMENU Menu
, BOOL Popup
,
1120 if(!(Flags
& TPM_NONOTIFY
))
1121 co_IntSendMessage(Window
->head
.h
, WM_EXITMENULOOP
, 0 /* FIXME */, 0);
1123 /* FIXME: Show caret again */
1127 IntTrackMenu(PMENU Menu
, PWND Window
, INT x
, INT y
,
1134 co_IntTrackPopupMenu(PMENU Menu
, PWND Window
,
1135 UINT Flags
, POINT
*Pos
, UINT MenuPos
, RECTL
*ExcludeRect
)
1137 co_IntInitTracking(Window
, Menu
, TRUE
, Flags
);
1139 co_IntExitTracking(Window
, Menu
, TRUE
, Flags
);
1144 intGetTitleBarInfo(PWND pWindowObject
, PTITLEBARINFO bti
)
1148 DWORD dwExStyle
= 0;
1149 BOOLEAN retValue
= TRUE
;
1151 if (bti
->cbSize
== sizeof(TITLEBARINFO
))
1153 RtlZeroMemory(&bti
->rgstate
[0],sizeof(DWORD
)*(CCHILDREN_TITLEBAR
+1));
1155 bti
->rgstate
[0] = STATE_SYSTEM_FOCUSABLE
;
1157 dwStyle
= pWindowObject
->style
;
1158 dwExStyle
= pWindowObject
->ExStyle
;
1160 bti
->rcTitleBar
.top
= 0;
1161 bti
->rcTitleBar
.left
= 0;
1162 bti
->rcTitleBar
.right
= pWindowObject
->rcWindow
.right
- pWindowObject
->rcWindow
.left
;
1163 bti
->rcTitleBar
.bottom
= pWindowObject
->rcWindow
.bottom
- pWindowObject
->rcWindow
.top
;
1165 /* Is it iconiced ? */
1166 if ((dwStyle
& WS_ICONIC
)!=WS_ICONIC
)
1168 /* Remove frame from rectangle */
1169 if (HAS_THICKFRAME( dwStyle
, dwExStyle
))
1171 /* FIXME: Note this value should exists in pWindowObject for UserGetSystemMetrics(SM_CXFRAME) and UserGetSystemMetrics(SM_CYFRAME) */
1172 RECTL_vInflateRect( &bti
->rcTitleBar
, -UserGetSystemMetrics(SM_CXFRAME
), -UserGetSystemMetrics(SM_CYFRAME
) );
1174 else if (HAS_DLGFRAME( dwStyle
, dwExStyle
))
1176 /* FIXME: Note this value should exists in pWindowObject for UserGetSystemMetrics(SM_CXDLGFRAME) and UserGetSystemMetrics(SM_CYDLGFRAME) */
1177 RECTL_vInflateRect( &bti
->rcTitleBar
, -UserGetSystemMetrics(SM_CXDLGFRAME
), -UserGetSystemMetrics(SM_CYDLGFRAME
));
1179 else if (HAS_THINFRAME( dwStyle
, dwExStyle
))
1181 /* FIXME: Note this value should exists in pWindowObject for UserGetSystemMetrics(SM_CXBORDER) and UserGetSystemMetrics(SM_CYBORDER) */
1182 RECTL_vInflateRect( &bti
->rcTitleBar
, -UserGetSystemMetrics(SM_CXBORDER
), -UserGetSystemMetrics(SM_CYBORDER
) );
1185 /* We have additional border information if the window
1186 * is a child (but not an MDI child) */
1187 if ( (dwStyle
& WS_CHILD
) &&
1188 ((dwExStyle
& WS_EX_MDICHILD
) == 0 ) )
1190 if (dwExStyle
& WS_EX_CLIENTEDGE
)
1192 /* FIXME: Note this value should exists in pWindowObject for UserGetSystemMetrics(SM_CXEDGE) and UserGetSystemMetrics(SM_CYEDGE) */
1193 RECTL_vInflateRect (&bti
->rcTitleBar
, -UserGetSystemMetrics(SM_CXEDGE
), -UserGetSystemMetrics(SM_CYEDGE
));
1196 if (dwExStyle
& WS_EX_STATICEDGE
)
1198 /* FIXME: Note this value should exists in pWindowObject for UserGetSystemMetrics(SM_CXBORDER) and UserGetSystemMetrics(SM_CYBORDER) */
1199 RECTL_vInflateRect (&bti
->rcTitleBar
, -UserGetSystemMetrics(SM_CXBORDER
), -UserGetSystemMetrics(SM_CYBORDER
));
1204 bti
->rcTitleBar
.top
+= pWindowObject
->rcWindow
.top
;
1205 bti
->rcTitleBar
.left
+= pWindowObject
->rcWindow
.left
;
1206 bti
->rcTitleBar
.right
+= pWindowObject
->rcWindow
.left
;
1208 bti
->rcTitleBar
.bottom
= bti
->rcTitleBar
.top
;
1209 if (dwExStyle
& WS_EX_TOOLWINDOW
)
1211 /* FIXME: Note this value should exists in pWindowObject for UserGetSystemMetrics(SM_CYSMCAPTION) */
1212 bti
->rcTitleBar
.bottom
+= UserGetSystemMetrics(SM_CYSMCAPTION
);
1216 /* FIXME: Note this value should exists in pWindowObject for UserGetSystemMetrics(SM_CYCAPTION) and UserGetSystemMetrics(SM_CXSIZE) */
1217 bti
->rcTitleBar
.bottom
+= UserGetSystemMetrics(SM_CYCAPTION
);
1218 bti
->rcTitleBar
.left
+= UserGetSystemMetrics(SM_CXSIZE
);
1221 if (dwStyle
& WS_CAPTION
)
1223 bti
->rgstate
[1] = STATE_SYSTEM_INVISIBLE
;
1224 if (dwStyle
& WS_SYSMENU
)
1226 if (!(dwStyle
& (WS_MINIMIZEBOX
|WS_MAXIMIZEBOX
)))
1228 bti
->rgstate
[2] = STATE_SYSTEM_INVISIBLE
;
1229 bti
->rgstate
[3] = STATE_SYSTEM_INVISIBLE
;
1233 if (!(dwStyle
& WS_MINIMIZEBOX
))
1235 bti
->rgstate
[2] = STATE_SYSTEM_UNAVAILABLE
;
1237 if (!(dwStyle
& WS_MAXIMIZEBOX
))
1239 bti
->rgstate
[3] = STATE_SYSTEM_UNAVAILABLE
;
1243 if (!(dwExStyle
& WS_EX_CONTEXTHELP
))
1245 bti
->rgstate
[4] = STATE_SYSTEM_INVISIBLE
;
1247 if (pWindowObject
->pcls
->style
& CS_NOCLOSE
)
1249 bti
->rgstate
[5] = STATE_SYSTEM_UNAVAILABLE
;
1254 bti
->rgstate
[2] = STATE_SYSTEM_INVISIBLE
;
1255 bti
->rgstate
[3] = STATE_SYSTEM_INVISIBLE
;
1256 bti
->rgstate
[4] = STATE_SYSTEM_INVISIBLE
;
1257 bti
->rgstate
[5] = STATE_SYSTEM_INVISIBLE
;
1262 bti
->rgstate
[0] |= STATE_SYSTEM_INVISIBLE
;
1267 EngSetLastError(ERROR_INVALID_PARAMETER
);
1279 LPCMENUITEMINFOW UnsafeItemInfo
,
1280 PUNICODE_STRING lpstr
)
1283 ROSMENUITEMINFO ItemInfo
;
1285 /* Try to copy the whole MENUITEMINFOW structure */
1286 Status
= MmCopyFromCaller(&ItemInfo
, UnsafeItemInfo
, sizeof(MENUITEMINFOW
));
1287 if (NT_SUCCESS(Status
))
1289 if (sizeof(MENUITEMINFOW
) != ItemInfo
.cbSize
1290 && FIELD_OFFSET(MENUITEMINFOW
, hbmpItem
) != ItemInfo
.cbSize
)
1292 EngSetLastError(ERROR_INVALID_PARAMETER
);
1295 return IntInsertMenuItem(Menu
, uItem
, fByPosition
, &ItemInfo
, lpstr
);
1298 /* Try to copy without last field (not present in older versions) */
1299 Status
= MmCopyFromCaller(&ItemInfo
, UnsafeItemInfo
, FIELD_OFFSET(MENUITEMINFOW
, hbmpItem
));
1300 if (NT_SUCCESS(Status
))
1302 if (FIELD_OFFSET(MENUITEMINFOW
, hbmpItem
) != ItemInfo
.cbSize
)
1304 EngSetLastError(ERROR_INVALID_PARAMETER
);
1307 ItemInfo
.hbmpItem
= (HBITMAP
)0;
1308 return IntInsertMenuItem(Menu
, uItem
, fByPosition
, &ItemInfo
, lpstr
);
1311 SetLastNtError(Status
);
1315 UINT FASTCALL
IntGetMenuState( HMENU hMenu
, UINT uId
, UINT uFlags
)
1320 if (!(MenuObject
= UserGetMenuObject(hMenu
)))
1325 if (!(pItem
= MENU_FindItem( &MenuObject
, &uId
, uFlags
))) return -1;
1327 if (pItem
->spSubMenu
)
1329 return (pItem
->spSubMenu
->cItems
<< 8) | ((pItem
->fState
|pItem
->fType
) & 0xff);
1332 return (pItem
->fType
| pItem
->fState
);
1335 HMENU FASTCALL
IntGetSubMenu( HMENU hMenu
, int nPos
)
1340 if (!(MenuObject
= UserGetMenuObject(hMenu
)))
1345 if (!(pItem
= MENU_FindItem( &MenuObject
, (UINT
*)&nPos
, MF_BYPOSITION
))) return NULL
;
1347 if (pItem
->spSubMenu
)
1349 HMENU hsubmenu
= UserHMGetHandle(pItem
->spSubMenu
);
1355 UINT FASTCALL
IntFindSubMenu(HMENU
*hMenu
, HMENU hSubTarget
)
1362 if (((*hMenu
)==(HMENU
)0xffff) ||(!(menu
= UserGetMenuObject(*hMenu
))))
1363 return NO_SELECTED_ITEM
;
1365 item
= menu
->rgItems
;
1366 for (i
= 0; i
< menu
->cItems
; i
++, item
++)
1368 if (!item
->spSubMenu
)
1372 hSubMenu
= UserHMGetHandle(item
->spSubMenu
);
1373 if (hSubMenu
== hSubTarget
)
1379 HMENU hsubmenu
= hSubMenu
;
1380 UINT pos
= IntFindSubMenu( &hsubmenu
, hSubTarget
);
1381 if (pos
!= NO_SELECTED_ITEM
)
1389 return NO_SELECTED_ITEM
;
1393 HMENU FASTCALL
UserCreateMenu(PDESKTOP Desktop
, BOOL PopupMenu
)
1395 PWINSTATION_OBJECT WinStaObject
;
1399 PEPROCESS CurrentProcess
= PsGetCurrentProcess();
1401 if (gpepCSRSS
!= CurrentProcess
)
1404 * gpepCSRSS does not have a Win32WindowStation
1407 Status
= IntValidateWindowStationHandle(CurrentProcess
->Win32WindowStation
,
1412 if (!NT_SUCCESS(Status
))
1414 ERR("Validation of window station handle (%p) failed\n",
1415 CurrentProcess
->Win32WindowStation
);
1416 SetLastNtError(Status
);
1419 Menu
= IntCreateMenu(&Handle
, !PopupMenu
, Desktop
, GetW32ProcessInfo());
1420 if (Menu
&& Menu
->head
.rpdesk
->rpwinstaParent
!= WinStaObject
)
1422 ERR("Desktop Window Station does not match Process one!\n");
1424 ObDereferenceObject(WinStaObject
);
1428 Menu
= IntCreateMenu(&Handle
, !PopupMenu
, GetW32ThreadInfo()->rpdesk
, GetW32ProcessInfo());
1431 if (Menu
) UserDereferenceObject(Menu
);
1432 return (HMENU
)Handle
;
1440 PROSMENUITEMINFO ItemInfo
,
1442 PUNICODE_STRING lpstr
)
1447 if (!(MenuItem
= MENU_FindItem( &Menu
, &Item
, (ByPosition
? MF_BYPOSITION
: MF_BYCOMMAND
) )))
1449 EngSetLastError(ERROR_MENU_ITEM_NOT_FOUND
);
1454 Ret
= IntSetMenuItemInfo(Menu
, MenuItem
, ItemInfo
, lpstr
);
1458 Ret
= IntGetMenuItemInfo(Menu
, MenuItem
, ItemInfo
);
1468 PROSMENUITEMINFO UnsafeItemInfo
,
1470 PUNICODE_STRING lpstr
)
1473 ROSMENUITEMINFO ItemInfo
;
1478 Status
= MmCopyFromCaller(&Size
, &UnsafeItemInfo
->cbSize
, sizeof(UINT
));
1479 if (! NT_SUCCESS(Status
))
1481 SetLastNtError(Status
);
1484 if (sizeof(MENUITEMINFOW
) != Size
1485 && FIELD_OFFSET(MENUITEMINFOW
, hbmpItem
) != Size
1486 && sizeof(ROSMENUITEMINFO
) != Size
)
1488 EngSetLastError(ERROR_INVALID_PARAMETER
);
1491 Status
= MmCopyFromCaller(&ItemInfo
, UnsafeItemInfo
, Size
);
1492 if (! NT_SUCCESS(Status
))
1494 SetLastNtError(Status
);
1497 /* If this is a pre-0x0500 _WIN32_WINNT MENUITEMINFOW, you can't
1499 if (FIELD_OFFSET(MENUITEMINFOW
, hbmpItem
) == Size
1500 && 0 != (ItemInfo
.fMask
& MIIM_BITMAP
))
1502 EngSetLastError(ERROR_INVALID_PARAMETER
);
1506 if (!(MenuItem
= MENU_FindItem( &Menu
, &Item
, (ByPosition
? MF_BYPOSITION
: MF_BYCOMMAND
) )))
1508 EngSetLastError(ERROR_MENU_ITEM_NOT_FOUND
);
1514 Ret
= IntSetMenuItemInfo(Menu
, MenuItem
, &ItemInfo
, lpstr
);
1518 Ret
= IntGetMenuItemInfo(Menu
, MenuItem
, &ItemInfo
);
1521 Status
= MmCopyToCaller(UnsafeItemInfo
, &ItemInfo
, Size
);
1522 if (! NT_SUCCESS(Status
))
1524 SetLastNtError(Status
);
1536 PROSMENUINFO UnsafeMenuInfo
,
1542 ROSMENUINFO MenuInfo
;
1544 Status
= MmCopyFromCaller(&Size
, &UnsafeMenuInfo
->cbSize
, sizeof(DWORD
));
1545 if (! NT_SUCCESS(Status
))
1547 SetLastNtError(Status
);
1550 if(Size
< sizeof(MENUINFO
) || sizeof(ROSMENUINFO
) < Size
)
1552 EngSetLastError(ERROR_INVALID_PARAMETER
);
1555 Status
= MmCopyFromCaller(&MenuInfo
, UnsafeMenuInfo
, Size
);
1556 if (! NT_SUCCESS(Status
))
1558 SetLastNtError(Status
);
1565 Res
= IntSetMenuInfo(Menu
, &MenuInfo
);
1570 Res
= IntGetMenuInfo(Menu
, &MenuInfo
);
1573 Status
= MmCopyToCaller(UnsafeMenuInfo
, &MenuInfo
, Size
);
1574 if (! NT_SUCCESS(Status
))
1576 SetLastNtError(Status
);
1586 MENU_AdjustMenuItemRect(PMENU menu
, PRECTL rect
)
1588 if (menu
->dwArrowsOn
)
1590 UINT arrow_bitmap_height
;
1592 //GetObjectW(get_up_arrow_bitmap(), sizeof(bmp), &bmp);
1593 arrow_bitmap_height
= gpsi
->oembmi
[65].cy
; ///// Menu up arrow! OBM_UPARROW DFCS_MENUARROWUP
1594 //arrow_bitmap_height = bmp.bmHeight;
1595 rect
->top
+= arrow_bitmap_height
- menu
->iTop
;
1596 rect
->bottom
+= arrow_bitmap_height
- menu
->iTop
;
1612 HWND hWnd
= Menu
->hWnd
;
1613 if (!(pWnd
= UserGetWindowObject(hWnd
))) return FALSE
;
1616 if ((MenuItem
= MENU_FindItem (&Menu
, &uItem
, MF_BYPOSITION
)))
1618 Rect
->left
= MenuItem
->xItem
;
1619 Rect
->top
= MenuItem
->yItem
;
1620 Rect
->right
= MenuItem
->cxItem
; // Do this for now......
1621 Rect
->bottom
= MenuItem
->cyItem
;
1625 ERR("Failed Item Lookup! %d\n", uItem
);
1629 if (Menu
->fFlags
& MNF_POPUP
)
1631 XMove
= pWnd
->rcClient
.left
;
1632 YMove
= pWnd
->rcClient
.top
;
1636 XMove
= pWnd
->rcWindow
.left
;
1637 YMove
= pWnd
->rcWindow
.top
;
1640 Rect
->left
+= XMove
;
1642 Rect
->right
+= XMove
;
1643 Rect
->bottom
+= YMove
;
1648 PMENU FASTCALL
MENU_GetSystemMenu(PWND Window
, PMENU Popup
)
1650 PMENU Menu
, NewMenu
= NULL
, SysMenu
= NULL
;
1651 HMENU hSysMenu
, hNewMenu
= NULL
;
1652 ROSMENUITEMINFO ItemInfoSet
= {0};
1653 ROSMENUITEMINFO ItemInfo
= {0};
1654 UNICODE_STRING MenuName
;
1656 hSysMenu
= UserCreateMenu(Window
->head
.rpdesk
, FALSE
);
1657 if (NULL
== hSysMenu
)
1661 SysMenu
= UserGetMenuObject(hSysMenu
);
1662 if (NULL
== SysMenu
)
1664 UserDestroyMenu(hSysMenu
);
1668 SysMenu
->fFlags
|= MNF_SYSMENU
;
1669 SysMenu
->hWnd
= Window
->head
.h
;
1673 //hNewMenu = co_IntLoadSysMenuTemplate();
1674 if ( Window
->ExStyle
& WS_EX_MDICHILD
)
1676 RtlInitUnicodeString( &MenuName
, L
"SYSMENUMDI");
1677 hNewMenu
= co_IntCallLoadMenu( hModClient
, &MenuName
);
1681 RtlInitUnicodeString( &MenuName
, L
"SYSMENU");
1682 hNewMenu
= co_IntCallLoadMenu( hModClient
, &MenuName
);
1683 //ERR("%wZ\n",&MenuName);
1688 IntReleaseMenuObject(SysMenu
);
1689 UserDestroyMenu(hSysMenu
);
1692 Menu
= UserGetMenuObject(hNewMenu
);
1695 IntReleaseMenuObject(SysMenu
);
1696 UserDestroyMenu(hSysMenu
);
1700 // Do the rest in here.
1702 Menu
->fFlags
|= MNS_CHECKORBMP
| MNF_SYSMENU
| MNF_POPUP
;
1704 ItemInfoSet
.cbSize
= sizeof( MENUITEMINFOW
);
1705 ItemInfoSet
.fMask
= MIIM_BITMAP
;
1706 ItemInfoSet
.hbmpItem
= HBMMENU_POPUP_CLOSE
;
1707 IntMenuItemInfo(Menu
, SC_CLOSE
, FALSE
, &ItemInfoSet
, TRUE
, NULL
);
1708 ItemInfoSet
.hbmpItem
= HBMMENU_POPUP_RESTORE
;
1709 IntMenuItemInfo(Menu
, SC_RESTORE
, FALSE
, &ItemInfoSet
, TRUE
, NULL
);
1710 ItemInfoSet
.hbmpItem
= HBMMENU_POPUP_MAXIMIZE
;
1711 IntMenuItemInfo(Menu
, SC_MAXIMIZE
, FALSE
, &ItemInfoSet
, TRUE
, NULL
);
1712 ItemInfoSet
.hbmpItem
= HBMMENU_POPUP_MINIMIZE
;
1713 IntMenuItemInfo(Menu
, SC_MINIMIZE
, FALSE
, &ItemInfoSet
, TRUE
, NULL
);
1715 NewMenu
= IntCloneMenu(Menu
);
1717 IntReleaseMenuObject(NewMenu
);
1718 UserSetMenuDefaultItem(NewMenu
, SC_CLOSE
, FALSE
);
1720 IntDestroyMenuObject(Menu
, FALSE
);
1728 NewMenu
->fFlags
|= MNF_SYSMENU
| MNF_POPUP
;
1730 if (Window
->pcls
->style
& CS_NOCLOSE
)
1731 IntRemoveMenuItem(NewMenu
, SC_CLOSE
, MF_BYCOMMAND
, TRUE
);
1733 ItemInfo
.cbSize
= sizeof(MENUITEMINFOW
);
1734 ItemInfo
.fMask
= MIIM_FTYPE
| MIIM_STRING
| MIIM_STATE
| MIIM_SUBMENU
;
1736 ItemInfo
.fState
= MFS_ENABLED
;
1737 ItemInfo
.dwTypeData
= NULL
;
1739 ItemInfo
.hSubMenu
= UserHMGetHandle(NewMenu
);
1740 IntInsertMenuItem(SysMenu
, (UINT
) -1, TRUE
, &ItemInfo
, NULL
);
1744 ERR("failed to load system menu!\n");
1749 IntGetSystemMenu(PWND Window
, BOOL bRevert
)
1755 if (Window
->SystemMenu
)
1757 Menu
= UserGetMenuObject(Window
->SystemMenu
);
1758 if (Menu
&& !(Menu
->fFlags
& MNF_SYSDESKMN
))
1760 IntDestroyMenuObject(Menu
, TRUE
);
1761 Window
->SystemMenu
= NULL
;
1767 Menu
= Window
->SystemMenu
? UserGetMenuObject(Window
->SystemMenu
) : NULL
;
1768 if ((!Window
->SystemMenu
|| Menu
->fFlags
& MNF_SYSDESKMN
) && Window
->style
& WS_SYSMENU
)
1770 Menu
= MENU_GetSystemMenu(Window
, NULL
);
1771 Window
->SystemMenu
= Menu
? UserHMGetHandle(Menu
) : NULL
;
1775 if (Window
->SystemMenu
)
1777 HMENU hMenu
= IntGetSubMenu( Window
->SystemMenu
, 0);
1778 /* Store the dummy sysmenu handle to facilitate the refresh */
1779 /* of the close button if the SC_CLOSE item change */
1780 Menu
= UserGetMenuObject(hMenu
);
1783 Menu
->spwndNotify
= Window
;
1784 Menu
->fFlags
|= MNF_SYSSUBMENU
;
1792 IntSetSystemMenu(PWND Window
, PMENU Menu
)
1796 if (!(Window
->style
& WS_SYSMENU
)) return FALSE
;
1798 if (Window
->SystemMenu
)
1800 OldMenu
= UserGetMenuObject(Window
->SystemMenu
);
1803 OldMenu
->fFlags
&= ~MNF_SYSMENU
;
1804 IntDestroyMenuObject(OldMenu
, TRUE
);
1808 OldMenu
= MENU_GetSystemMenu(Window
, Menu
);
1810 { // Use spmenuSys too!
1811 Window
->SystemMenu
= UserHMGetHandle(OldMenu
);
1814 Window
->SystemMenu
= NULL
;
1816 if (Menu
&& Window
!= Menu
->spwndNotify
)
1818 Menu
->spwndNotify
= Window
;
1825 /* FUNCTIONS *****************************************************************/
1831 NtUserCheckMenuItem(
1837 DECLARE_RETURN(DWORD
);
1839 TRACE("Enter NtUserCheckMenuItem\n");
1840 UserEnterExclusive();
1842 if(!(Menu
= UserGetMenuObject(hMenu
)))
1847 RETURN( IntCheckMenuItem(Menu
, uIDCheckItem
, uCheck
));
1850 TRACE("Leave NtUserCheckMenuItem, ret=%lu\n",_ret_
);
1865 DECLARE_RETURN(BOOL
);
1867 TRACE("Enter NtUserDeleteMenu\n");
1868 UserEnterExclusive();
1870 if(!(Menu
= UserGetMenuObject(hMenu
)))
1875 RETURN( IntRemoveMenuItem(Menu
, uPosition
, uFlags
, TRUE
));
1878 TRACE("Leave NtUserDeleteMenu, ret=%i\n",_ret_
);
1884 * NtUserGetSystemMenu
1886 * The NtUserGetSystemMenu function allows the application to access the
1887 * window menu (also known as the system menu or the control menu) for
1888 * copying and modifying.
1892 * Handle to the window that will own a copy of the window menu.
1894 * Specifies the action to be taken. If this parameter is FALSE,
1895 * NtUserGetSystemMenu returns a handle to the copy of the window menu
1896 * currently in use. The copy is initially identical to the window menu
1897 * but it can be modified.
1898 * If this parameter is TRUE, GetSystemMenu resets the window menu back
1899 * to the default state. The previous window menu, if any, is destroyed.
1902 * If the bRevert parameter is FALSE, the return value is a handle to a
1903 * copy of the window menu. If the bRevert parameter is TRUE, the return
1911 NtUserGetSystemMenu(HWND hWnd
, BOOL bRevert
)
1915 DECLARE_RETURN(HMENU
);
1917 TRACE("Enter NtUserGetSystemMenu\n");
1920 if (!(Window
= UserGetWindowObject(hWnd
)))
1925 if (!(Menu
= IntGetSystemMenu(Window
, bRevert
)))
1930 RETURN(Menu
->head
.h
);
1933 TRACE("Leave NtUserGetSystemMenu, ret=%p\n", _ret_
);
1939 * NtUserSetSystemMenu
1946 NtUserSetSystemMenu(HWND hWnd
, HMENU hMenu
)
1948 BOOL Result
= FALSE
;
1951 DECLARE_RETURN(BOOL
);
1953 TRACE("Enter NtUserSetSystemMenu\n");
1954 UserEnterExclusive();
1956 if (!(Window
= UserGetWindowObject(hWnd
)))
1964 * Assign new menu handle and Up the Lock Count.
1966 if (!(Menu
= IntGetMenuObject(hMenu
)))
1971 Result
= IntSetSystemMenu(Window
, Menu
);
1974 EngSetLastError(ERROR_INVALID_MENU_HANDLE
);
1979 TRACE("Leave NtUserSetSystemMenu, ret=%i\n",_ret_
);
1988 NtUserGetTitleBarInfo(
1993 TITLEBARINFO bartitleinfo
;
1994 DECLARE_RETURN(BOOLEAN
);
1995 BOOLEAN retValue
= TRUE
;
1997 TRACE("Enter NtUserGetTitleBarInfo\n");
1998 UserEnterExclusive();
2000 /* Vaildate the windows handle */
2001 if (!(WindowObject
= UserGetWindowObject(hwnd
)))
2003 EngSetLastError(ERROR_INVALID_WINDOW_HANDLE
);
2009 /* Copy our usermode buffer bti to local buffer bartitleinfo */
2010 ProbeForRead(bti
, sizeof(TITLEBARINFO
), 1);
2011 RtlCopyMemory(&bartitleinfo
, bti
, sizeof(TITLEBARINFO
));
2013 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2015 /* Fail copy the data */
2016 EngSetLastError(ERROR_INVALID_PARAMETER
);
2021 /* Get the tile bar info */
2024 retValue
= intGetTitleBarInfo(WindowObject
, &bartitleinfo
);
2029 /* Copy our buffer to user mode buffer bti */
2030 ProbeForWrite(bti
, sizeof(TITLEBARINFO
), 1);
2031 RtlCopyMemory(bti
, &bartitleinfo
, sizeof(TITLEBARINFO
));
2033 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2035 /* Fail copy the data */
2036 EngSetLastError(ERROR_INVALID_PARAMETER
);
2046 TRACE("Leave NtUserGetTitleBarInfo, ret=%u\n",_ret_
);
2054 BOOL FASTCALL
UserDestroyMenu(HMENU hMenu
)
2057 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
2059 if(!(Menu
= UserGetMenuObject(hMenu
)))
2064 if (Menu
->head
.rpdesk
!= pti
->rpdesk
)
2066 EngSetLastError(ERROR_ACCESS_DENIED
);
2069 return IntDestroyMenuObject(Menu
, FALSE
);
2080 DECLARE_RETURN(BOOL
);
2082 TRACE("Enter NtUserDestroyMenu\n");
2083 UserEnterExclusive();
2085 if(!(Menu
= UserGetMenuObject(hMenu
)))
2089 if (Menu
->head
.rpdesk
!= gptiCurrent
->rpdesk
)
2091 EngSetLastError(ERROR_ACCESS_DENIED
);
2094 RETURN( IntDestroyMenuObject(Menu
, TRUE
));
2097 TRACE("Leave NtUserDestroyMenu, ret=%i\n",_ret_
);
2106 NtUserEnableMenuItem(
2112 DECLARE_RETURN(UINT
);
2114 TRACE("Enter NtUserEnableMenuItem\n");
2115 UserEnterExclusive();
2117 if(!(Menu
= UserGetMenuObject(hMenu
)))
2122 RETURN( IntEnableMenuItem(Menu
, uIDEnableItem
, uEnable
));
2125 TRACE("Leave NtUserEnableMenuItem, ret=%u\n",_ret_
);
2134 NtUserGetMenuBarInfo(
2144 NTSTATUS Status
= STATUS_SUCCESS
;
2146 DECLARE_RETURN(BOOL
);
2148 TRACE("Enter NtUserGetMenuBarInfo\n");
2151 if (!(pWnd
= UserGetWindowObject(hwnd
)))
2153 EngSetLastError(ERROR_INVALID_WINDOW_HANDLE
);
2160 if (!pWnd
->pcls
->fnid
)
2162 if (pWnd
->pcls
->fnid
!= FNID_MENU
)
2164 WARN("called on invalid window: %d\n", pWnd
->pcls
->fnid
);
2165 EngSetLastError(ERROR_INVALID_MENU_HANDLE
);
2168 // Windows does this! Wine checks for Atom and uses GetWindowLongPtrW.
2169 hMenu
= (HMENU
)co_IntSendMessage(hwnd
, MN_GETHMENU
, 0, 0);
2172 hMenu
= UlongToHandle(pWnd
->IDMenu
);
2175 if (!(pWnd
->style
& WS_SYSMENU
)) RETURN(FALSE
);
2176 Menu
= IntGetSystemMenu(pWnd
, FALSE
);
2177 hMenu
= Menu
->head
.h
;
2188 kmbi
.cbSize
= pmbi
->cbSize
;
2190 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2196 if (kmbi
.cbSize
!= sizeof(MENUBARINFO
))
2198 EngSetLastError(ERROR_INVALID_PARAMETER
);
2202 if (!Menu
) Menu
= UserGetMenuObject(hMenu
);
2206 if ((idItem
< 0) || ((ULONG
)idItem
> Menu
->cItems
))
2209 RECTL_vSetEmptyRect(&kmbi
.rcBar
);
2213 Ret
= IntGetMenuItemRect(pWnd
, Menu
, 0, &kmbi
.rcBar
);
2214 kmbi
.rcBar
.right
= kmbi
.rcBar
.left
+ Menu
->cxMenu
;
2215 kmbi
.rcBar
.bottom
= kmbi
.rcBar
.top
+ Menu
->cyMenu
;
2216 TRACE("idItem 0 %d\n",Ret
);
2220 Ret
= IntGetMenuItemRect(pWnd
, Menu
, idItem
-1, &kmbi
.rcBar
);
2221 TRACE("idItem X %d\n", Ret
);
2225 kmbi
.hwndMenu
= NULL
;
2226 kmbi
.fBarFocused
= FALSE
;
2227 kmbi
.fFocused
= FALSE
;
2228 //kmbi.fBarFocused = top_popup_hmenu == hMenu;
2231 kmbi
.fFocused
= Menu
->iItem
== idItem
-1;
2232 if (kmbi
.fFocused
&& (Menu
->rgItems
[idItem
- 1].spSubMenu
))
2234 kmbi
.hwndMenu
= Menu
->rgItems
[idItem
- 1].spSubMenu
->hWnd
;
2239 kmbi.fFocused = kmbi.fBarFocused;
2244 RtlCopyMemory(pmbi
, &kmbi
, sizeof(MENUBARINFO
));
2246 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2248 Status
= _SEH2_GetExceptionCode();
2252 if (!NT_SUCCESS(Status
))
2254 SetLastNtError(Status
);
2261 TRACE("Leave NtUserGetMenuBarInfo, ret=%i\n",_ret_
);
2274 PMENU Menu
, SubMenu
;
2277 DECLARE_RETURN(UINT
);
2279 TRACE("Enter NtUserGetMenuIndex\n");
2282 if ( !(Menu
= UserGetMenuObject(hMenu
)) ||
2283 !(SubMenu
= UserGetMenuObject(hSubMenu
)) )
2286 MenuItem
= Menu
->rgItems
;
2287 for (i
= 0; i
< Menu
->cItems
; i
++, MenuItem
++)
2289 if (MenuItem
->spSubMenu
== SubMenu
)
2290 RETURN(MenuItem
->wID
);
2295 TRACE("Leave NtUserGetMenuIndex, ret=%u\n",_ret_
);
2304 NtUserGetMenuItemRect(
2315 NTSTATUS Status
= STATUS_SUCCESS
;
2316 DECLARE_RETURN(BOOL
);
2318 TRACE("Enter NtUserGetMenuItemRect\n");
2321 if (!(Menu
= UserGetMenuObject(hMenu
)))
2326 if ((MenuItem
= MENU_FindItem (&Menu
, &uItem
, MF_BYPOSITION
)))
2328 Rect
.left
= MenuItem
->xItem
;
2329 Rect
.top
= MenuItem
->yItem
;
2330 Rect
.right
= MenuItem
->cxItem
; // Do this for now......
2331 Rect
.bottom
= MenuItem
->cyItem
;
2341 if (lprcItem
== NULL
) RETURN( FALSE
);
2343 if (!(ReferenceWnd
= UserGetWindowObject(hWnd
))) RETURN( FALSE
);
2345 if (Menu
->fFlags
& MNF_POPUP
)
2347 XMove
= ReferenceWnd
->rcClient
.left
;
2348 YMove
= ReferenceWnd
->rcClient
.top
;
2352 XMove
= ReferenceWnd
->rcWindow
.left
;
2353 YMove
= ReferenceWnd
->rcWindow
.top
;
2358 Rect
.right
+= XMove
;
2359 Rect
.bottom
+= YMove
;
2363 RtlCopyMemory(lprcItem
, &Rect
, sizeof(RECTL
));
2365 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2367 Status
= _SEH2_GetExceptionCode();
2371 if (!NT_SUCCESS(Status
))
2373 SetLastNtError(Status
);
2379 TRACE("Leave NtUserGetMenuItemRect, ret=%i\n",_ret_
);
2388 NtUserHiliteMenuItem(
2396 DECLARE_RETURN(BOOLEAN
);
2398 TRACE("Enter NtUserHiliteMenuItem\n");
2399 UserEnterExclusive();
2401 if(!(Window
= UserGetWindowObject(hWnd
)))
2403 EngSetLastError(ERROR_INVALID_WINDOW_HANDLE
);
2407 if(!(Menu
= UserGetMenuObject(hMenu
)))
2409 EngSetLastError(ERROR_INVALID_MENU_HANDLE
);
2413 RETURN( IntHiliteMenuItem(Window
, Menu
, uItemHilite
, uHilite
));
2416 TRACE("Leave NtUserHiliteMenuItem, ret=%u\n",_ret_
);
2426 NtUserMenuItemFromPoint(
2436 DECLARE_RETURN(int);
2438 TRACE("Enter NtUserMenuItemFromPoint\n");
2439 UserEnterExclusive();
2441 if (!(Menu
= UserGetMenuObject(hMenu
)))
2446 if (!(Window
= UserGetWindowObject(Menu
->hWnd
)))
2451 X
-= Window
->rcWindow
.left
;
2452 Y
-= Window
->rcWindow
.top
;
2455 for (i
= 0; i
< Menu
->cItems
; i
++, mi
++)
2458 Rect
.left
= mi
->xItem
;
2459 Rect
.top
= mi
->yItem
;
2460 Rect
.right
= mi
->cxItem
; // Do this for now......
2461 Rect
.bottom
= mi
->cyItem
;
2462 //MENU_AdjustMenuItemRect(Menu, &Rect); Need gpsi OBMI via callback!
2463 if (RECTL_bPointInRect(&Rect
, X
, Y
))
2469 RETURN( (mi
? i
: NO_SELECTED_ITEM
));
2472 TRACE("Leave NtUserMenuItemFromPoint, ret=%i\n",_ret_
);
2488 DECLARE_RETURN(BOOL
);
2490 TRACE("Enter NtUserRemoveMenu\n");
2491 UserEnterExclusive();
2493 if(!(Menu
= UserGetMenuObject(hMenu
)))
2498 RETURN(IntRemoveMenuItem(Menu
, uPosition
, uFlags
, FALSE
));
2501 TRACE("Leave NtUserRemoveMenu, ret=%i\n",_ret_
);
2511 NtUserSetMenuContextHelpId(
2513 DWORD dwContextHelpId
)
2516 DECLARE_RETURN(BOOL
);
2518 TRACE("Enter NtUserSetMenuContextHelpId\n");
2519 UserEnterExclusive();
2521 if(!(Menu
= UserGetMenuObject(hMenu
)))
2526 RETURN(IntSetMenuContextHelpId(Menu
, dwContextHelpId
));
2529 TRACE("Leave NtUserSetMenuContextHelpId, ret=%i\n",_ret_
);
2538 NtUserSetMenuDefaultItem(
2544 DECLARE_RETURN(BOOL
);
2546 TRACE("Enter NtUserSetMenuDefaultItem\n");
2547 UserEnterExclusive();
2549 if(!(Menu
= UserGetMenuObject(hMenu
)))
2554 RETURN( UserSetMenuDefaultItem(Menu
, uItem
, fByPos
));
2557 TRACE("Leave NtUserSetMenuDefaultItem, ret=%i\n",_ret_
);
2566 NtUserSetMenuFlagRtoL(
2570 DECLARE_RETURN(BOOL
);
2572 TRACE("Enter NtUserSetMenuFlagRtoL\n");
2573 UserEnterExclusive();
2575 if(!(Menu
= UserGetMenuObject(hMenu
)))
2580 RETURN(IntSetMenuFlagRtoL(Menu
));
2583 TRACE("Leave NtUserSetMenuFlagRtoL, ret=%i\n",_ret_
);
2592 NtUserThunkedMenuInfo(
2597 DECLARE_RETURN(BOOL
);
2599 TRACE("Enter NtUserThunkedMenuInfo\n");
2600 UserEnterExclusive();
2602 if (!(Menu
= UserGetMenuObject(hMenu
)))
2607 RETURN(UserMenuInfo(Menu
, (PROSMENUINFO
)lpcmi
, TRUE
));
2610 TRACE("Leave NtUserThunkedMenuInfo, ret=%i\n",_ret_
);
2619 NtUserThunkedMenuItemInfo(
2624 LPMENUITEMINFOW lpmii
,
2625 PUNICODE_STRING lpszCaption
)
2629 UNICODE_STRING lstrCaption
;
2630 DECLARE_RETURN(BOOL
);
2632 TRACE("Enter NtUserThunkedMenuItemInfo\n");
2633 UserEnterExclusive();
2635 /* lpszCaption may be NULL, check for it and call RtlInitUnicodeString()
2636 if bInsert == TRUE call UserInsertMenuItem() else UserSetMenuItemInfo() */
2638 if (!(Menu
= UserGetMenuObject(hMenu
)))
2643 RtlInitUnicodeString(&lstrCaption
, 0);
2645 /* Check if we got a Caption */
2646 if (lpszCaption
&& lpszCaption
->Buffer
)
2648 /* Copy the string to kernel mode */
2649 Status
= ProbeAndCaptureUnicodeString( &lstrCaption
,
2652 if (!NT_SUCCESS(Status
))
2654 ERR("Failed to capture MenuItem Caption (status 0x%08x)\n",Status
);
2655 SetLastNtError(Status
);
2660 if (bInsert
) RETURN( UserInsertMenuItem(Menu
, uItem
, fByPosition
, lpmii
, &lstrCaption
));
2662 RETURN( UserMenuItemInfo(Menu
, uItem
, fByPosition
, (PROSMENUITEMINFO
)lpmii
, TRUE
, &lstrCaption
));
2665 TRACE("Leave NtUserThunkedMenuItemInfo, ret=%i\n",_ret_
);