2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
5 * FILE: subsys/win32k/ntuser/menu.c
6 * PROGRAMER: Thomas Weidenmueller (w3seek@users.sourceforge.net)
10 DBG_DEFAULT_CHANNEL(UserMenu
);
12 /* INTERNAL ******************************************************************/
14 BOOL FASTCALL
IntSetMenuItemInfo(PMENU
, PITEM
, PROSMENUITEMINFO
, PUNICODE_STRING
);
16 /* maximum allowed depth of any branch in the menu tree.
17 * This value is slightly larger than in windows (25) to
18 * stay on the safe side. */
19 #define MAXMENUDEPTH 30
21 #define MNS_STYLE_MASK (MNS_NOCHECK|MNS_MODELESS|MNS_DRAGDROP|MNS_AUTODISMISS|MNS_NOTIFYBYPOS|MNS_CHECKORBMP)
23 #define MENUITEMINFO_TYPE_MASK \
24 (MFT_STRING | MFT_BITMAP | MFT_OWNERDRAW | MFT_SEPARATOR | \
25 MFT_MENUBARBREAK | MFT_MENUBREAK | MFT_RADIOCHECK | \
26 MFT_RIGHTORDER | MFT_RIGHTJUSTIFY /* same as MF_HELP */ )
28 #define TYPE_MASK (MENUITEMINFO_TYPE_MASK | MF_POPUP | MF_SYSMENU)
30 #define STATE_MASK (~TYPE_MASK)
32 #define MENUITEMINFO_STATE_MASK (STATE_MASK & ~(MF_BYPOSITION | MF_MOUSESELECT))
34 #define MII_STATE_MASK (MFS_GRAYED|MFS_CHECKED|MFS_HILITE|MFS_DEFAULT)
36 /* Maximum number of menu items a menu can contain */
37 #define MAX_MENU_ITEMS (0x4000)
38 #define MAX_GOINTOSUBMENU (0x10)
40 #define UpdateMenuItemState(state, change) \
42 if((change) & MF_GRAYED) { \
43 (state) |= MF_GRAYED; \
45 (state) &= ~MF_GRAYED; \
46 } /* Separate the two for test_menu_resource_layout.*/ \
47 if((change) & MF_DISABLED) { \
48 (state) |= MF_DISABLED; \
50 (state) &= ~MF_DISABLED; \
52 if((change) & MFS_CHECKED) { \
53 (state) |= MFS_CHECKED; \
55 (state) &= ~MFS_CHECKED; \
57 if((change) & MFS_HILITE) { \
58 (state) |= MFS_HILITE; \
60 (state) &= ~MFS_HILITE; \
62 if((change) & MFS_DEFAULT) { \
63 (state) |= MFS_DEFAULT; \
65 (state) &= ~MFS_DEFAULT; \
67 if((change) & MF_MOUSESELECT) { \
68 (state) |= MF_MOUSESELECT; \
70 (state) &= ~MF_MOUSESELECT; \
76 DumpMenuItemList(PMENU Menu
, PITEM MenuItem
)
78 UINT cnt
= 0, i
= Menu
->cItems
;
81 if(MenuItem
->lpstr
.Length
)
82 DbgPrint(" %d. %wZ\n", ++cnt
, &MenuItem
->lpstr
);
84 DbgPrint(" %d. NO TEXT dwTypeData==%d\n", ++cnt
, (DWORD
)MenuItem
->lpstr
.Buffer
);
86 if(MFT_BITMAP
& MenuItem
->fType
)
87 DbgPrint("MFT_BITMAP ");
88 if(MFT_MENUBARBREAK
& MenuItem
->fType
)
89 DbgPrint("MFT_MENUBARBREAK ");
90 if(MFT_MENUBREAK
& MenuItem
->fType
)
91 DbgPrint("MFT_MENUBREAK ");
92 if(MFT_OWNERDRAW
& MenuItem
->fType
)
93 DbgPrint("MFT_OWNERDRAW ");
94 if(MFT_RADIOCHECK
& MenuItem
->fType
)
95 DbgPrint("MFT_RADIOCHECK ");
96 if(MFT_RIGHTJUSTIFY
& MenuItem
->fType
)
97 DbgPrint("MFT_RIGHTJUSTIFY ");
98 if(MFT_SEPARATOR
& MenuItem
->fType
)
99 DbgPrint("MFT_SEPARATOR ");
100 if(MFT_STRING
& MenuItem
->fType
)
101 DbgPrint("MFT_STRING ");
102 DbgPrint("\n fState=");
103 if(MFS_DISABLED
& MenuItem
->fState
)
104 DbgPrint("MFS_DISABLED ");
106 DbgPrint("MFS_ENABLED ");
107 if(MFS_CHECKED
& MenuItem
->fState
)
108 DbgPrint("MFS_CHECKED ");
110 DbgPrint("MFS_UNCHECKED ");
111 if(MFS_HILITE
& MenuItem
->fState
)
112 DbgPrint("MFS_HILITE ");
114 DbgPrint("MFS_UNHILITE ");
115 if(MFS_DEFAULT
& MenuItem
->fState
)
116 DbgPrint("MFS_DEFAULT ");
117 if(MFS_GRAYED
& MenuItem
->fState
)
118 DbgPrint("MFS_GRAYED ");
119 DbgPrint("\n wId=%d\n", MenuItem
->wID
);
123 DbgPrint("Entries: %d\n", cnt
);
128 #define FreeMenuText(Menu,MenuItem) \
130 if((MENU_ITEM_TYPE((MenuItem)->fType) == MF_STRING) && \
131 (MenuItem)->lpstr.Length) { \
132 DesktopHeapFree(((PMENU)Menu)->head.rpdesk, (MenuItem)->lpstr.Buffer); \
137 IntGetMenuObject(HMENU hMenu
)
139 PMENU Menu
= UserGetMenuObject(hMenu
);
141 Menu
->head
.cLockObj
++;
146 PMENU FASTCALL
VerifyMenu(PMENU pMenu
)
151 if (!pMenu
) return NULL
;
155 hMenu
= UserHMGetHandle(pMenu
);
156 pItem
= pMenu
->rgItems
;
163 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
165 ERR("Run away LOOP!\n");
166 _SEH2_YIELD(return NULL
);
170 if ( UserObjectInDestroy(hMenu
))
172 ERR("Menu is marked for destruction!\n");
179 BOOL
IntDestroyMenu( PMENU pMenu
, BOOL bRecurse
, BOOL RemoveFromProcess
)
183 if (pMenu
->rgItems
) /* recursively destroy submenus */
186 ITEM
*item
= pMenu
->rgItems
;
187 for (i
= pMenu
->cItems
; i
> 0; i
--, item
++)
189 SubMenu
= item
->spSubMenu
;
190 item
->spSubMenu
= NULL
;
192 /* Remove Item Text */
193 FreeMenuText(pMenu
,item
);
195 /* Remove Item Bitmap and set it for this process */
196 if (item
->hbmp
&& !(item
->fState
& MFS_HBMMENUBMP
))
198 GreSetObjectOwner(item
->hbmp
, GDI_OBJ_HMGR_POWNED
);
202 /* Remove Item submenu */
203 if (bRecurse
&& SubMenu
)//VerifyMenu(SubMenu))
205 /* Release submenu since it was referenced when inserted */
206 IntReleaseMenuObject(SubMenu
);
207 IntDestroyMenuObject(SubMenu
, bRecurse
, RemoveFromProcess
);
211 DesktopHeapFree(pMenu
->head
.rpdesk
, pMenu
->rgItems
);
212 pMenu
->rgItems
= NULL
;
219 IntDestroyMenuObject(PMENU Menu
, BOOL bRecurse
, BOOL RemoveFromProcess
)
225 /* Remove all menu items */
226 IntDestroyMenu( Menu
, bRecurse
, RemoveFromProcess
);
228 if (RemoveFromProcess
)
230 RemoveEntryList(&Menu
->ListEntry
);
233 if (PsGetCurrentProcessSessionId() == Menu
->head
.rpdesk
->rpwinstaParent
->dwSessionId
)
238 Window
= UserGetWindowObject(Menu
->hWnd
);
243 /* DestroyMenu should not destroy system menu popup owner */
244 if ((Menu
->fFlags
& (MNF_POPUP
| MNF_SYSSUBMENU
)) == MNF_POPUP
)
246 // Should we check it to see if it has Class?
247 ERR("FIXME Pop up menu window thing'ie\n");
248 //co_UserDestroyWindow( Window );
253 ret
= UserDeleteObject(Menu
->head
.h
, TYPE_MENU
);
255 { // Make sure it is really dead or just marked for deletion.
256 ret
= UserObjectInDestroy(Menu
->head
.h
);
257 if (ret
&& EngGetLastError() == ERROR_INVALID_HANDLE
) ret
= FALSE
;
258 } // See test_subpopup_locked_by_menu tests....
265 /**********************************************************************
268 * detect if there are loops in the menu tree (or the depth is too large)
270 int FASTCALL
MENU_depth( PMENU pmenu
, int depth
)
276 if (!pmenu
) return depth
;
279 if( depth
> MAXMENUDEPTH
) return depth
;
280 item
= pmenu
->rgItems
;
282 for( i
= 0; item
, i
< pmenu
->cItems
&& subdepth
<= MAXMENUDEPTH
; i
++, item
++)
284 if( item
->spSubMenu
)//VerifyMenu(item->spSubMenu))
286 int bdepth
= MENU_depth( item
->spSubMenu
, depth
);
287 if( bdepth
> subdepth
) subdepth
= bdepth
;
289 if( subdepth
> MAXMENUDEPTH
)
290 TRACE("<- hmenu %p\n", item
->spSubMenu
);
295 /***********************************************************************
298 * Find a menu item. Return a pointer on the item, and modifies *hmenu
299 * in case the item was in a sub-menu.
301 PITEM FASTCALL
MENU_FindItem( PMENU
*pmenu
, UINT
*nPos
, UINT wFlags
)
304 ITEM
*fallback
= NULL
;
305 UINT fallback_pos
= 0;
308 if (!menu
) return NULL
;
310 if (wFlags
& MF_BYPOSITION
)
312 if (!menu
->cItems
) return NULL
;
313 if (*nPos
>= menu
->cItems
) return NULL
;
314 return &menu
->rgItems
[*nPos
];
318 PITEM item
= menu
->rgItems
;
319 for (i
= 0; item
, i
< menu
->cItems
; i
++, item
++)
323 PMENU psubmenu
= item
->spSubMenu
;//VerifyMenu(item->spSubMenu);
324 PITEM subitem
= MENU_FindItem( &psubmenu
, nPos
, wFlags
);
330 else if (item
->wID
== *nPos
)
332 /* fallback to this item if nothing else found */
337 else if (item
->wID
== *nPos
)
346 *nPos
= fallback_pos
;
352 IntRemoveMenuItem( PMENU pMenu
, UINT nPos
, UINT wFlags
, BOOL bRecurse
)
356 TRACE("(menu=%p pos=%04x flags=%04x)\n",pMenu
, nPos
, wFlags
);
357 if (!(item
= MENU_FindItem( &pMenu
, &nPos
, wFlags
))) return FALSE
;
361 FreeMenuText(pMenu
,item
);
362 if (bRecurse
&& item
->spSubMenu
)
364 IntDestroyMenuObject(item
->spSubMenu
, bRecurse
, TRUE
);
366 ////// Use cAlloced with inc's of 8's....
367 if (--pMenu
->cItems
== 0)
369 DesktopHeapFree(pMenu
->head
.rpdesk
, pMenu
->rgItems
);
370 pMenu
->rgItems
= NULL
;
374 while(nPos
< pMenu
->cItems
)
380 pMenu
->rgItems
= DesktopHeapReAlloc(pMenu
->head
.rpdesk
, pMenu
->rgItems
, pMenu
->cItems
* sizeof(ITEM
));
385 /**********************************************************************
388 * Insert (allocate) a new item into a menu.
390 ITEM
*MENU_InsertItem( PMENU menu
, UINT pos
, UINT flags
, PMENU
*submenu
, UINT
*npos
)
394 /* Find where to insert new item */
396 if (flags
& MF_BYPOSITION
) {
397 if (pos
> menu
->cItems
)
400 if (!MENU_FindItem( &menu
, &pos
, flags
))
402 if (submenu
) *submenu
= menu
;
403 if (npos
) *npos
= pos
;
408 /* Make sure that MDI system buttons stay on the right side.
409 * Note: XP treats only bitmap handles 1 - 6 as "magic" ones
410 * regardless of their id.
413 (INT_PTR
)menu
->rgItems
[pos
- 1].hbmp
>= (INT_PTR
)HBMMENU_SYSTEM
&&
414 (INT_PTR
)menu
->rgItems
[pos
- 1].hbmp
<= (INT_PTR
)HBMMENU_MBAR_CLOSE_D
)
417 TRACE("inserting at %u flags %x\n", pos
, flags
);
419 /* Create new items array */
421 newItems
= DesktopHeapAlloc(menu
->head
.rpdesk
, sizeof(ITEM
) * (menu
->cItems
+1) );
424 WARN("allocation failed\n" );
427 if (menu
->cItems
> 0)
429 /* Copy the old array into the new one */
430 if (pos
> 0) RtlCopyMemory( newItems
, menu
->rgItems
, pos
* sizeof(ITEM
) );
431 if (pos
< menu
->cItems
) RtlCopyMemory( &newItems
[pos
+1], &menu
->rgItems
[pos
], (menu
->cItems
-pos
)*sizeof(ITEM
) );
432 DesktopHeapFree(menu
->head
.rpdesk
, menu
->rgItems
);
434 menu
->rgItems
= newItems
;
436 RtlZeroMemory( &newItems
[pos
], sizeof(*newItems
) );
437 menu
->cyMenu
= 0; /* force size recalculate */
438 return &newItems
[pos
];
443 _In_ PMENU MenuObject
,
446 PROSMENUITEMINFO ItemInfo
,
447 PUNICODE_STRING lpstr
)
450 PMENU SubMenu
= NULL
;
452 NT_ASSERT(MenuObject
!= NULL
);
454 if (MAX_MENU_ITEMS
<= MenuObject
->cItems
)
456 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY
);
460 SubMenu
= MenuObject
;
462 if(!(MenuItem
= MENU_InsertItem( SubMenu
, uItem
, fByPosition
? MF_BYPOSITION
: MF_BYCOMMAND
, &SubMenu
, &uItem
))) return FALSE
;
464 if(!IntSetMenuItemInfo(SubMenu
, MenuItem
, ItemInfo
, lpstr
))
466 IntRemoveMenuItem(SubMenu
, uItem
, fByPosition
? MF_BYPOSITION
: MF_BYCOMMAND
, FALSE
);
470 /* Force size recalculation! */
472 MenuItem
->hbmpChecked
= MenuItem
->hbmpUnchecked
= 0;
474 TRACE("IntInsertMenuItemToList = %i %d\n", uItem
, (BOOL
)((INT
)uItem
>= 0));
480 IntCreateMenu(PHANDLE Handle
, BOOL IsMenuBar
)
483 PPROCESSINFO CurrentWin32Process
;
485 Menu
= (PMENU
)UserCreateObject( gHandleTable
,
497 Menu
->cyMax
= 0; /* Default */
498 Menu
->hbrBack
= NULL
; /* No brush */
499 Menu
->dwContextHelpId
= 0; /* Default */
500 Menu
->dwMenuData
= 0; /* Default */
501 Menu
->iItem
= NO_SELECTED_ITEM
; // Focused item
502 Menu
->fFlags
= (IsMenuBar
? 0 : MNF_POPUP
);
503 Menu
->spwndNotify
= NULL
;
504 Menu
->cyMenu
= 0; // Height
505 Menu
->cxMenu
= 0; // Width
506 Menu
->cItems
= 0; // Item count
509 Menu
->cxTextAlign
= 0;
510 Menu
->rgItems
= NULL
;
513 Menu
->TimeToHide
= FALSE
;
515 /* Insert menu item into process menu handle list */
516 CurrentWin32Process
= PsGetCurrentProcessWin32Process();
517 InsertTailList(&CurrentWin32Process
->MenuListHead
, &Menu
->ListEntry
);
523 IntCloneMenuItems(PMENU Destination
, PMENU Source
)
525 PITEM MenuItem
, NewMenuItem
= NULL
;
531 NewMenuItem
= DesktopHeapAlloc(Destination
->head
.rpdesk
, (Source
->cItems
+1) * sizeof(ITEM
));
532 if(!NewMenuItem
) return FALSE
;
534 RtlZeroMemory(NewMenuItem
, (Source
->cItems
+1) * sizeof(ITEM
));
536 Destination
->rgItems
= NewMenuItem
;
538 MenuItem
= Source
->rgItems
;
539 for (i
= 0; i
< Source
->cItems
; i
++, MenuItem
++, NewMenuItem
++)
541 NewMenuItem
->fType
= MenuItem
->fType
;
542 NewMenuItem
->fState
= MenuItem
->fState
;
543 NewMenuItem
->wID
= MenuItem
->wID
;
544 NewMenuItem
->spSubMenu
= MenuItem
->spSubMenu
;
545 NewMenuItem
->hbmpChecked
= MenuItem
->hbmpChecked
;
546 NewMenuItem
->hbmpUnchecked
= MenuItem
->hbmpUnchecked
;
547 NewMenuItem
->dwItemData
= MenuItem
->dwItemData
;
548 if (MenuItem
->lpstr
.Length
)
550 NewMenuItem
->lpstr
.Length
= 0;
551 NewMenuItem
->lpstr
.MaximumLength
= MenuItem
->lpstr
.MaximumLength
;
552 NewMenuItem
->lpstr
.Buffer
= DesktopHeapAlloc(Destination
->head
.rpdesk
, MenuItem
->lpstr
.MaximumLength
);
553 if (!NewMenuItem
->lpstr
.Buffer
)
555 DesktopHeapFree(Destination
->head
.rpdesk
, NewMenuItem
);
558 RtlCopyUnicodeString(&NewMenuItem
->lpstr
, &MenuItem
->lpstr
);
559 NewMenuItem
->lpstr
.Buffer
[MenuItem
->lpstr
.Length
/ sizeof(WCHAR
)] = 0;
560 NewMenuItem
->Xlpstr
= NewMenuItem
->lpstr
.Buffer
;
564 NewMenuItem
->lpstr
.Buffer
= MenuItem
->lpstr
.Buffer
;
565 NewMenuItem
->Xlpstr
= NewMenuItem
->lpstr
.Buffer
;
567 NewMenuItem
->hbmp
= MenuItem
->hbmp
;
573 IntCloneMenu(PMENU Source
)
575 PPROCESSINFO CurrentWin32Process
;
582 Menu
= (PMENU
)UserCreateObject( gHandleTable
,
591 Menu
->fFlags
= Source
->fFlags
;
592 Menu
->cyMax
= Source
->cyMax
;
593 Menu
->hbrBack
= Source
->hbrBack
;
594 Menu
->dwContextHelpId
= Source
->dwContextHelpId
;
595 Menu
->dwMenuData
= Source
->dwMenuData
;
596 Menu
->iItem
= NO_SELECTED_ITEM
;
597 Menu
->spwndNotify
= NULL
;
600 Menu
->cItems
= Source
->cItems
;
603 Menu
->cxTextAlign
= 0;
604 Menu
->rgItems
= NULL
;
607 Menu
->TimeToHide
= FALSE
;
609 /* Insert menu item into process menu handle list */
610 CurrentWin32Process
= PsGetCurrentProcessWin32Process();
611 InsertTailList(&CurrentWin32Process
->MenuListHead
, &Menu
->ListEntry
);
613 IntCloneMenuItems(Menu
, Source
);
619 IntSetMenuFlagRtoL(PMENU Menu
)
621 Menu
->fFlags
|= MNF_RTOL
;
626 IntSetMenuContextHelpId(PMENU Menu
, DWORD dwContextHelpId
)
628 Menu
->dwContextHelpId
= dwContextHelpId
;
633 IntGetMenuInfo(PMENU Menu
, PROSMENUINFO lpmi
)
635 if(lpmi
->fMask
& MIM_BACKGROUND
)
636 lpmi
->hbrBack
= Menu
->hbrBack
;
637 if(lpmi
->fMask
& MIM_HELPID
)
638 lpmi
->dwContextHelpID
= Menu
->dwContextHelpId
;
639 if(lpmi
->fMask
& MIM_MAXHEIGHT
)
640 lpmi
->cyMax
= Menu
->cyMax
;
641 if(lpmi
->fMask
& MIM_MENUDATA
)
642 lpmi
->dwMenuData
= Menu
->dwMenuData
;
643 if(lpmi
->fMask
& MIM_STYLE
)
644 lpmi
->dwStyle
= Menu
->fFlags
& MNS_STYLE_MASK
;
646 if (sizeof(MENUINFO
) < lpmi
->cbSize
)
648 lpmi
->cItems
= Menu
->cItems
;
650 lpmi
->iItem
= Menu
->iItem
;
651 lpmi
->cxMenu
= Menu
->cxMenu
;
652 lpmi
->cyMenu
= Menu
->cyMenu
;
653 lpmi
->spwndNotify
= Menu
->spwndNotify
;
654 lpmi
->cxTextAlign
= Menu
->cxTextAlign
;
655 lpmi
->iTop
= Menu
->iMaxTop
;
656 lpmi
->iMaxTop
= Menu
->iMaxTop
;
657 lpmi
->dwArrowsOn
= Menu
->dwArrowsOn
;
659 lpmi
->fFlags
= Menu
->fFlags
;
660 lpmi
->Self
= Menu
->head
.h
;
661 lpmi
->TimeToHide
= Menu
->TimeToHide
;
662 lpmi
->Wnd
= Menu
->hWnd
;
668 IntSetMenuInfo(PMENU Menu
, PROSMENUINFO lpmi
)
670 if(lpmi
->fMask
& MIM_BACKGROUND
)
671 Menu
->hbrBack
= lpmi
->hbrBack
;
672 if(lpmi
->fMask
& MIM_HELPID
)
673 Menu
->dwContextHelpId
= lpmi
->dwContextHelpID
;
674 if(lpmi
->fMask
& MIM_MAXHEIGHT
)
675 Menu
->cyMax
= lpmi
->cyMax
;
676 if(lpmi
->fMask
& MIM_MENUDATA
)
677 Menu
->dwMenuData
= lpmi
->dwMenuData
;
678 if(lpmi
->fMask
& MIM_STYLE
)
679 Menu
->fFlags
^= (Menu
->fFlags
^ lpmi
->dwStyle
) & MNS_STYLE_MASK
;
680 if(lpmi
->fMask
& MIM_APPLYTOSUBMENUS
)
683 PITEM item
= Menu
->rgItems
;
684 for ( i
= Menu
->cItems
; i
; i
--, item
++)
686 if ( item
->spSubMenu
)
688 IntSetMenuInfo( item
->spSubMenu
, lpmi
);
692 if (sizeof(MENUINFO
) < lpmi
->cbSize
)
694 Menu
->iItem
= lpmi
->iItem
;
695 Menu
->cyMenu
= lpmi
->cyMenu
;
696 Menu
->cxMenu
= lpmi
->cxMenu
;
697 Menu
->spwndNotify
= lpmi
->spwndNotify
;
698 Menu
->cxTextAlign
= lpmi
->cxTextAlign
;
699 Menu
->iTop
= lpmi
->iTop
;
700 Menu
->iMaxTop
= lpmi
->iMaxTop
;
701 Menu
->dwArrowsOn
= lpmi
->dwArrowsOn
;
703 Menu
->TimeToHide
= lpmi
->TimeToHide
;
704 Menu
->hWnd
= lpmi
->Wnd
;
710 IntGetMenuItemInfo(PMENU Menu
, /* UNUSED PARAM!! */
711 PITEM MenuItem
, PROSMENUITEMINFO lpmii
)
715 if(lpmii
->fMask
& (MIIM_FTYPE
| MIIM_TYPE
))
717 lpmii
->fType
= MenuItem
->fType
;
719 if(lpmii
->fMask
& MIIM_BITMAP
)
721 lpmii
->hbmpItem
= MenuItem
->hbmp
;
723 if(lpmii
->fMask
& MIIM_CHECKMARKS
)
725 lpmii
->hbmpChecked
= MenuItem
->hbmpChecked
;
726 lpmii
->hbmpUnchecked
= MenuItem
->hbmpUnchecked
;
728 if(lpmii
->fMask
& MIIM_DATA
)
730 lpmii
->dwItemData
= MenuItem
->dwItemData
;
732 if(lpmii
->fMask
& MIIM_ID
)
734 lpmii
->wID
= MenuItem
->wID
;
736 if(lpmii
->fMask
& MIIM_STATE
)
738 lpmii
->fState
= MenuItem
->fState
;
740 if(lpmii
->fMask
& MIIM_SUBMENU
)
742 lpmii
->hSubMenu
= MenuItem
->spSubMenu
? MenuItem
->spSubMenu
->head
.h
: NULL
;
745 if ((lpmii
->fMask
& MIIM_STRING
) ||
746 ((lpmii
->fMask
& MIIM_TYPE
) && (MENU_ITEM_TYPE(lpmii
->fType
) == MF_STRING
)))
748 if (lpmii
->dwTypeData
== NULL
)
750 lpmii
->cch
= MenuItem
->lpstr
.Length
/ sizeof(WCHAR
);
753 { //// lpmii->lpstr can be read in user mode!!!!
754 Status
= MmCopyToCaller(lpmii
->dwTypeData
, MenuItem
->lpstr
.Buffer
,
755 min(lpmii
->cch
* sizeof(WCHAR
),
756 MenuItem
->lpstr
.MaximumLength
));
757 if (! NT_SUCCESS(Status
))
759 SetLastNtError(Status
);
765 if (sizeof(ROSMENUITEMINFO
) == lpmii
->cbSize
)
767 lpmii
->Rect
.left
= MenuItem
->xItem
;
768 lpmii
->Rect
.top
= MenuItem
->yItem
;
769 lpmii
->Rect
.right
= MenuItem
->cxItem
; // Do this for now......
770 lpmii
->Rect
.bottom
= MenuItem
->cyItem
;
771 lpmii
->dxTab
= MenuItem
->dxTab
;
772 lpmii
->lpstr
= MenuItem
->lpstr
.Buffer
;
773 lpmii
->maxBmpSize
.cx
= MenuItem
->cxBmp
;
774 lpmii
->maxBmpSize
.cy
= MenuItem
->cyBmp
;
781 IntSetMenuItemInfo(PMENU MenuObject
, PITEM MenuItem
, PROSMENUITEMINFO lpmii
, PUNICODE_STRING lpstr
)
784 BOOL circref
= FALSE
;
786 if(!MenuItem
|| !MenuObject
|| !lpmii
)
790 if ( lpmii
->fMask
& MIIM_FTYPE
)
792 MenuItem
->fType
&= ~MENUITEMINFO_TYPE_MASK
;
793 MenuItem
->fType
|= lpmii
->fType
& MENUITEMINFO_TYPE_MASK
;
795 if (lpmii
->fMask
& MIIM_TYPE
)
797 #if 0 //// Done in User32.
798 if (lpmii
->fMask
& ( MIIM_STRING
| MIIM_FTYPE
| MIIM_BITMAP
))
800 ERR("IntSetMenuItemInfo: Invalid combination of fMask bits used\n");
801 KeRosDumpStackFrames(NULL
, 20);
802 /* This does not happen on Win9x/ME */
803 SetLastNtError( ERROR_INVALID_PARAMETER
);
808 * Delete the menu item type when changing type from
811 if (MenuItem
->fType
!= lpmii
->fType
&&
812 MENU_ITEM_TYPE(MenuItem
->fType
) == MFT_STRING
)
814 FreeMenuText(MenuObject
,MenuItem
);
815 RtlInitUnicodeString(&MenuItem
->lpstr
, NULL
);
816 MenuItem
->Xlpstr
= NULL
;
818 if(lpmii
->fType
& MFT_BITMAP
)
821 MenuItem
->hbmp
= lpmii
->hbmpItem
;
823 { /* Win 9x/Me stuff */
824 MenuItem
->hbmp
= (HBITMAP
)((ULONG_PTR
)(LOWORD(lpmii
->dwTypeData
)));
826 lpmii
->dwTypeData
= 0;
829 if(lpmii
->fMask
& MIIM_BITMAP
)
831 MenuItem
->hbmp
= lpmii
->hbmpItem
;
832 if (MenuItem
->hbmp
<= HBMMENU_POPUP_MINIMIZE
&& MenuItem
->hbmp
>= HBMMENU_CALLBACK
)
833 MenuItem
->fState
|= MFS_HBMMENUBMP
;
835 MenuItem
->fState
&= ~MFS_HBMMENUBMP
;
837 if(lpmii
->fMask
& MIIM_CHECKMARKS
)
839 MenuItem
->hbmpChecked
= lpmii
->hbmpChecked
;
840 MenuItem
->hbmpUnchecked
= lpmii
->hbmpUnchecked
;
842 if(lpmii
->fMask
& MIIM_DATA
)
844 MenuItem
->dwItemData
= lpmii
->dwItemData
;
846 if(lpmii
->fMask
& MIIM_ID
)
848 MenuItem
->wID
= lpmii
->wID
;
850 if(lpmii
->fMask
& MIIM_STATE
)
852 /* Remove MFS_DEFAULT flag from all other menu items if this item
853 has the MFS_DEFAULT state */
854 if(lpmii
->fState
& MFS_DEFAULT
)
855 UserSetMenuDefaultItem(MenuObject
, -1, 0);
856 /* Update the menu item state flags */
857 UpdateMenuItemState(MenuItem
->fState
, lpmii
->fState
);
860 if(lpmii
->fMask
& MIIM_SUBMENU
)
864 SubMenuObject
= UserGetMenuObject(lpmii
->hSubMenu
);
865 if ( SubMenuObject
&& !(UserObjectInDestroy(lpmii
->hSubMenu
)) )
867 //// wine Bug 12171 : Adding Popup Menu to itself! Could create endless loops.
869 if (MenuObject
== SubMenuObject
)
872 ERR("Pop Up Menu Double Trouble!\n");
873 SubMenuObject
= IntCreateMenu(&hMenu
, FALSE
); // It will be marked.
874 if (!SubMenuObject
) return FALSE
;
875 IntReleaseMenuObject(SubMenuObject
); // This will be referenced again after insertion.
878 if ( MENU_depth( SubMenuObject
, 0) > MAXMENUDEPTH
)
880 ERR( "Loop detected in menu hierarchy or maximum menu depth exceeded!\n");
881 if (circref
) IntDestroyMenuObject(SubMenuObject
, FALSE
, TRUE
);
884 /* Make sure the submenu is marked as a popup menu */
885 SubMenuObject
->fFlags
|= MNF_POPUP
;
886 // Now fix the test_subpopup_locked_by_menu tests....
887 if (MenuItem
->spSubMenu
) IntReleaseMenuObject(MenuItem
->spSubMenu
);
888 MenuItem
->spSubMenu
= SubMenuObject
;
889 UserReferenceObject(SubMenuObject
);
893 EngSetLastError( ERROR_INVALID_PARAMETER
);
898 { // If submenu just dereference it.
899 if (MenuItem
->spSubMenu
) IntReleaseMenuObject(MenuItem
->spSubMenu
);
900 MenuItem
->spSubMenu
= NULL
;
904 if ((lpmii
->fMask
& MIIM_STRING
) ||
905 ((lpmii
->fMask
& MIIM_TYPE
) && (MENU_ITEM_TYPE(lpmii
->fType
) == MF_STRING
)))
907 /* free the string when used */
908 FreeMenuText(MenuObject
,MenuItem
);
909 RtlInitUnicodeString(&MenuItem
->lpstr
, NULL
);
910 MenuItem
->Xlpstr
= NULL
;
912 if(lpmii
->dwTypeData
&& lpmii
->cch
&& lpstr
&& lpstr
->Buffer
)
914 UNICODE_STRING Source
;
916 Source
.Length
= Source
.MaximumLength
= lpmii
->cch
* sizeof(WCHAR
);
917 Source
.Buffer
= lpmii
->dwTypeData
;
919 MenuItem
->lpstr
.Buffer
= DesktopHeapAlloc( MenuObject
->head
.rpdesk
, Source
.Length
+ sizeof(WCHAR
));
920 if(MenuItem
->lpstr
.Buffer
!= NULL
)
922 MenuItem
->lpstr
.Length
= 0;
923 MenuItem
->lpstr
.MaximumLength
= Source
.Length
+ sizeof(WCHAR
);
924 RtlCopyUnicodeString(&MenuItem
->lpstr
, &Source
);
925 MenuItem
->lpstr
.Buffer
[MenuItem
->lpstr
.Length
/ sizeof(WCHAR
)] = 0;
927 MenuItem
->cch
= MenuItem
->lpstr
.Length
/ sizeof(WCHAR
);
928 MenuItem
->Xlpstr
= (USHORT
*)MenuItem
->lpstr
.Buffer
;
933 if( !(MenuObject
->fFlags
& MNF_SYSMENU
) &&
935 !lpmii
->dwTypeData
&&
936 !(MenuItem
->fType
& MFT_OWNERDRAW
) &&
938 MenuItem
->fType
|= MFT_SEPARATOR
;
940 if (sizeof(ROSMENUITEMINFO
) == lpmii
->cbSize
)
942 MenuItem
->xItem
= lpmii
->Rect
.left
;
943 MenuItem
->yItem
= lpmii
->Rect
.top
;
944 MenuItem
->cxItem
= lpmii
->Rect
.right
; // Do this for now......
945 MenuItem
->cyItem
= lpmii
->Rect
.bottom
;
946 MenuItem
->dxTab
= lpmii
->dxTab
;
947 lpmii
->lpstr
= MenuItem
->lpstr
.Buffer
; /* Send back new allocated string or zero */
948 MenuItem
->cxBmp
= lpmii
->maxBmpSize
.cx
;
949 MenuItem
->cyBmp
= lpmii
->maxBmpSize
.cy
;
957 IntEnableMenuItem(PMENU MenuObject
, UINT uIDEnableItem
, UINT uEnable
)
962 if (!(MenuItem
= MENU_FindItem( &MenuObject
, &uIDEnableItem
, uEnable
))) return (UINT
)-1;
964 res
= MenuItem
->fState
& (MF_GRAYED
| MF_DISABLED
);
966 MenuItem
->fState
^= (res
^ uEnable
) & (MF_GRAYED
| MF_DISABLED
);
968 /* If the close item in the system menu change update the close button */
969 if((MenuItem
->wID
== SC_CLOSE
) && (res
!= uEnable
))
971 if (MenuObject
->fFlags
& MNF_SYSSUBMENU
&& MenuObject
->spwndNotify
!= 0)
973 RECTL rc
= MenuObject
->spwndNotify
->rcWindow
;
975 /* Refresh the frame to reflect the change */
976 IntMapWindowPoints(0, MenuObject
->spwndNotify
, (POINT
*)&rc
, 2);
978 co_UserRedrawWindow(MenuObject
->spwndNotify
, &rc
, 0, RDW_FRAME
| RDW_INVALIDATE
| RDW_NOCHILDREN
);
985 IntCheckMenuItem(PMENU MenuObject
, UINT uIDCheckItem
, UINT uCheck
)
990 if (!(MenuItem
= MENU_FindItem( &MenuObject
, &uIDCheckItem
, uCheck
))) return -1;
992 res
= (DWORD
)(MenuItem
->fState
& MF_CHECKED
);
994 MenuItem
->fState
^= (res
^ uCheck
) & MF_CHECKED
;
1000 IntHiliteMenuItem(PWND WindowObject
,
1007 if (!(MenuItem
= MENU_FindItem( &MenuObject
, &uItemHilite
, uHilite
))) return FALSE
;
1009 if (uHilite
& MF_HILITE
)
1011 MenuItem
->fState
|= MF_HILITE
;
1015 MenuItem
->fState
&= ~MF_HILITE
;
1017 /* FIXME: Update the window's menu */
1019 return TRUE
; // Always returns true!!!!
1023 UserSetMenuDefaultItem(PMENU MenuObject
, UINT uItem
, UINT fByPos
)
1026 PITEM MenuItem
= MenuObject
->rgItems
;
1028 if (!MenuItem
) return FALSE
;
1030 /* reset all default-item flags */
1031 for (i
= 0; MenuItem
, i
< MenuObject
->cItems
; i
++, MenuItem
++)
1033 MenuItem
->fState
&= ~MFS_DEFAULT
;
1036 /* no default item */
1037 if(uItem
== (UINT
)-1)
1041 MenuItem
= MenuObject
->rgItems
;
1044 if ( uItem
>= MenuObject
->cItems
) return FALSE
;
1045 MenuItem
[uItem
].fState
|= MFS_DEFAULT
;
1050 for (i
= 0; MenuItem
, i
< MenuObject
->cItems
; i
++, MenuItem
++)
1052 if (MenuItem
->wID
== uItem
)
1054 MenuItem
->fState
|= MFS_DEFAULT
;
1065 IntGetMenuDefaultItem(PMENU MenuObject
, UINT fByPos
, UINT gmdiFlags
, DWORD
*gismc
)
1068 PITEM MenuItem
= MenuObject
->rgItems
;
1071 if (!MenuItem
) return -1;
1073 while ( !( MenuItem
->fState
& MFS_DEFAULT
) )
1076 if (i
>= MenuObject
->cItems
) return -1;
1079 /* default: don't return disabled items */
1080 if ( (!(GMDI_USEDISABLED
& gmdiFlags
)) && (MenuItem
->fState
& MFS_DISABLED
)) return -1;
1082 /* search rekursiv when needed */
1083 if ( (MenuItem
->fType
& MF_POPUP
) && (gmdiFlags
& GMDI_GOINTOPOPUPS
) && MenuItem
->spSubMenu
)
1087 ret
= IntGetMenuDefaultItem( MenuItem
->spSubMenu
, fByPos
, gmdiFlags
, gismc
);
1089 if ( -1 != ret
) return ret
;
1091 /* when item not found in submenu, return the popup item */
1093 return ( fByPos
) ? i
: MenuItem
->wID
;
1097 co_IntInitTracking(PWND Window
, PMENU Menu
, BOOL Popup
,
1100 /* FIXME: Hide caret */
1102 if(!(Flags
& TPM_NONOTIFY
))
1103 co_IntSendMessage(Window
->head
.h
, WM_SETCURSOR
, (WPARAM
)Window
->head
.h
, HTCAPTION
);
1105 /* FIXME: Send WM_SETCURSOR message */
1107 if(!(Flags
& TPM_NONOTIFY
))
1108 co_IntSendMessage(Window
->head
.h
, WM_INITMENU
, (WPARAM
)Menu
->head
.h
, 0);
1112 co_IntExitTracking(PWND Window
, PMENU Menu
, BOOL Popup
,
1115 if(!(Flags
& TPM_NONOTIFY
))
1116 co_IntSendMessage(Window
->head
.h
, WM_EXITMENULOOP
, 0 /* FIXME */, 0);
1118 /* FIXME: Show caret again */
1122 IntTrackMenu(PMENU Menu
, PWND Window
, INT x
, INT y
,
1129 co_IntTrackPopupMenu(PMENU Menu
, PWND Window
,
1130 UINT Flags
, POINT
*Pos
, UINT MenuPos
, RECTL
*ExcludeRect
)
1132 co_IntInitTracking(Window
, Menu
, TRUE
, Flags
);
1134 co_IntExitTracking(Window
, Menu
, TRUE
, Flags
);
1140 * Internal function. Called when the process is destroyed to free the remaining menu handles.
1143 IntCleanupMenus(struct _EPROCESS
*Process
, PPROCESSINFO Win32Process
)
1145 PEPROCESS CurrentProcess
;
1146 PLIST_ENTRY LastHead
= NULL
;
1149 CurrentProcess
= PsGetCurrentProcess();
1150 if (CurrentProcess
!= Process
)
1152 KeAttachProcess(&Process
->Pcb
);
1155 while (Win32Process
->MenuListHead
.Flink
!= &(Win32Process
->MenuListHead
) &&
1156 Win32Process
->MenuListHead
.Flink
!= LastHead
)
1158 LastHead
= Win32Process
->MenuListHead
.Flink
;
1159 MenuObject
= CONTAINING_RECORD(Win32Process
->MenuListHead
.Flink
, MENU
, ListEntry
);
1160 TRACE("Menus are stuck on the process list!\n");
1161 IntDestroyMenuObject(MenuObject
, FALSE
, TRUE
);
1164 if (CurrentProcess
!= Process
)
1172 intGetTitleBarInfo(PWND pWindowObject
, PTITLEBARINFO bti
)
1176 DWORD dwExStyle
= 0;
1177 BOOLEAN retValue
= TRUE
;
1179 if (bti
->cbSize
== sizeof(TITLEBARINFO
))
1181 RtlZeroMemory(&bti
->rgstate
[0],sizeof(DWORD
)*(CCHILDREN_TITLEBAR
+1));
1183 bti
->rgstate
[0] = STATE_SYSTEM_FOCUSABLE
;
1185 dwStyle
= pWindowObject
->style
;
1186 dwExStyle
= pWindowObject
->ExStyle
;
1188 bti
->rcTitleBar
.top
= 0;
1189 bti
->rcTitleBar
.left
= 0;
1190 bti
->rcTitleBar
.right
= pWindowObject
->rcWindow
.right
- pWindowObject
->rcWindow
.left
;
1191 bti
->rcTitleBar
.bottom
= pWindowObject
->rcWindow
.bottom
- pWindowObject
->rcWindow
.top
;
1193 /* Is it iconiced ? */
1194 if ((dwStyle
& WS_ICONIC
)!=WS_ICONIC
)
1196 /* Remove frame from rectangle */
1197 if (HAS_THICKFRAME( dwStyle
, dwExStyle
))
1199 /* FIXME: Note this value should exists in pWindowObject for UserGetSystemMetrics(SM_CXFRAME) and UserGetSystemMetrics(SM_CYFRAME) */
1200 RECTL_vInflateRect( &bti
->rcTitleBar
, -UserGetSystemMetrics(SM_CXFRAME
), -UserGetSystemMetrics(SM_CYFRAME
) );
1202 else if (HAS_DLGFRAME( dwStyle
, dwExStyle
))
1204 /* FIXME: Note this value should exists in pWindowObject for UserGetSystemMetrics(SM_CXDLGFRAME) and UserGetSystemMetrics(SM_CYDLGFRAME) */
1205 RECTL_vInflateRect( &bti
->rcTitleBar
, -UserGetSystemMetrics(SM_CXDLGFRAME
), -UserGetSystemMetrics(SM_CYDLGFRAME
));
1207 else if (HAS_THINFRAME( dwStyle
, dwExStyle
))
1209 /* FIXME: Note this value should exists in pWindowObject for UserGetSystemMetrics(SM_CXBORDER) and UserGetSystemMetrics(SM_CYBORDER) */
1210 RECTL_vInflateRect( &bti
->rcTitleBar
, -UserGetSystemMetrics(SM_CXBORDER
), -UserGetSystemMetrics(SM_CYBORDER
) );
1213 /* We have additional border information if the window
1214 * is a child (but not an MDI child) */
1215 if ( (dwStyle
& WS_CHILD
) &&
1216 ((dwExStyle
& WS_EX_MDICHILD
) == 0 ) )
1218 if (dwExStyle
& WS_EX_CLIENTEDGE
)
1220 /* FIXME: Note this value should exists in pWindowObject for UserGetSystemMetrics(SM_CXEDGE) and UserGetSystemMetrics(SM_CYEDGE) */
1221 RECTL_vInflateRect (&bti
->rcTitleBar
, -UserGetSystemMetrics(SM_CXEDGE
), -UserGetSystemMetrics(SM_CYEDGE
));
1224 if (dwExStyle
& WS_EX_STATICEDGE
)
1226 /* FIXME: Note this value should exists in pWindowObject for UserGetSystemMetrics(SM_CXBORDER) and UserGetSystemMetrics(SM_CYBORDER) */
1227 RECTL_vInflateRect (&bti
->rcTitleBar
, -UserGetSystemMetrics(SM_CXBORDER
), -UserGetSystemMetrics(SM_CYBORDER
));
1232 bti
->rcTitleBar
.top
+= pWindowObject
->rcWindow
.top
;
1233 bti
->rcTitleBar
.left
+= pWindowObject
->rcWindow
.left
;
1234 bti
->rcTitleBar
.right
+= pWindowObject
->rcWindow
.left
;
1236 bti
->rcTitleBar
.bottom
= bti
->rcTitleBar
.top
;
1237 if (dwExStyle
& WS_EX_TOOLWINDOW
)
1239 /* FIXME: Note this value should exists in pWindowObject for UserGetSystemMetrics(SM_CYSMCAPTION) */
1240 bti
->rcTitleBar
.bottom
+= UserGetSystemMetrics(SM_CYSMCAPTION
);
1244 /* FIXME: Note this value should exists in pWindowObject for UserGetSystemMetrics(SM_CYCAPTION) and UserGetSystemMetrics(SM_CXSIZE) */
1245 bti
->rcTitleBar
.bottom
+= UserGetSystemMetrics(SM_CYCAPTION
);
1246 bti
->rcTitleBar
.left
+= UserGetSystemMetrics(SM_CXSIZE
);
1249 if (dwStyle
& WS_CAPTION
)
1251 bti
->rgstate
[1] = STATE_SYSTEM_INVISIBLE
;
1252 if (dwStyle
& WS_SYSMENU
)
1254 if (!(dwStyle
& (WS_MINIMIZEBOX
|WS_MAXIMIZEBOX
)))
1256 bti
->rgstate
[2] = STATE_SYSTEM_INVISIBLE
;
1257 bti
->rgstate
[3] = STATE_SYSTEM_INVISIBLE
;
1261 if (!(dwStyle
& WS_MINIMIZEBOX
))
1263 bti
->rgstate
[2] = STATE_SYSTEM_UNAVAILABLE
;
1265 if (!(dwStyle
& WS_MAXIMIZEBOX
))
1267 bti
->rgstate
[3] = STATE_SYSTEM_UNAVAILABLE
;
1271 if (!(dwExStyle
& WS_EX_CONTEXTHELP
))
1273 bti
->rgstate
[4] = STATE_SYSTEM_INVISIBLE
;
1275 if (pWindowObject
->pcls
->style
& CS_NOCLOSE
)
1277 bti
->rgstate
[5] = STATE_SYSTEM_UNAVAILABLE
;
1282 bti
->rgstate
[2] = STATE_SYSTEM_INVISIBLE
;
1283 bti
->rgstate
[3] = STATE_SYSTEM_INVISIBLE
;
1284 bti
->rgstate
[4] = STATE_SYSTEM_INVISIBLE
;
1285 bti
->rgstate
[5] = STATE_SYSTEM_INVISIBLE
;
1290 bti
->rgstate
[0] |= STATE_SYSTEM_INVISIBLE
;
1295 EngSetLastError(ERROR_INVALID_PARAMETER
);
1307 LPCMENUITEMINFOW UnsafeItemInfo
,
1308 PUNICODE_STRING lpstr
)
1311 ROSMENUITEMINFO ItemInfo
;
1313 /* Try to copy the whole MENUITEMINFOW structure */
1314 Status
= MmCopyFromCaller(&ItemInfo
, UnsafeItemInfo
, sizeof(MENUITEMINFOW
));
1315 if (NT_SUCCESS(Status
))
1317 if (sizeof(MENUITEMINFOW
) != ItemInfo
.cbSize
1318 && FIELD_OFFSET(MENUITEMINFOW
, hbmpItem
) != ItemInfo
.cbSize
)
1320 EngSetLastError(ERROR_INVALID_PARAMETER
);
1323 return IntInsertMenuItem(Menu
, uItem
, fByPosition
, &ItemInfo
, lpstr
);
1326 /* Try to copy without last field (not present in older versions) */
1327 Status
= MmCopyFromCaller(&ItemInfo
, UnsafeItemInfo
, FIELD_OFFSET(MENUITEMINFOW
, hbmpItem
));
1328 if (NT_SUCCESS(Status
))
1330 if (FIELD_OFFSET(MENUITEMINFOW
, hbmpItem
) != ItemInfo
.cbSize
)
1332 EngSetLastError(ERROR_INVALID_PARAMETER
);
1335 ItemInfo
.hbmpItem
= (HBITMAP
)0;
1336 return IntInsertMenuItem(Menu
, uItem
, fByPosition
, &ItemInfo
, lpstr
);
1339 SetLastNtError(Status
);
1343 UINT FASTCALL
IntGetMenuState( HMENU hMenu
, UINT uId
, UINT uFlags
)
1348 if (!(MenuObject
= UserGetMenuObject(hMenu
)))
1353 if (!(pItem
= MENU_FindItem( &MenuObject
, &uId
, uFlags
))) return -1;
1355 if (pItem
->spSubMenu
)
1357 return (pItem
->spSubMenu
->cItems
<< 8) | ((pItem
->fState
|pItem
->fType
) & 0xff);
1360 return (pItem
->fType
| pItem
->fState
);
1363 HMENU FASTCALL
IntGetSubMenu( HMENU hMenu
, int nPos
)
1368 if (!(MenuObject
= UserGetMenuObject(hMenu
)))
1373 if (!(pItem
= MENU_FindItem( &MenuObject
, (UINT
*)&nPos
, MF_BYPOSITION
))) return NULL
;
1375 if (pItem
->spSubMenu
)
1377 HMENU hsubmenu
= UserHMGetHandle(pItem
->spSubMenu
);
1383 UINT FASTCALL
IntFindSubMenu(HMENU
*hMenu
, HMENU hSubTarget
)
1390 if (((*hMenu
)==(HMENU
)0xffff) ||(!(menu
= UserGetMenuObject(*hMenu
))))
1391 return NO_SELECTED_ITEM
;
1393 item
= menu
->rgItems
;
1394 for (i
= 0; i
< menu
->cItems
; i
++, item
++)
1396 if (!item
->spSubMenu
)
1400 hSubMenu
= UserHMGetHandle(item
->spSubMenu
);
1401 if (hSubMenu
== hSubTarget
)
1407 HMENU hsubmenu
= hSubMenu
;
1408 UINT pos
= IntFindSubMenu( &hsubmenu
, hSubTarget
);
1409 if (pos
!= NO_SELECTED_ITEM
)
1417 return NO_SELECTED_ITEM
;
1421 HMENU FASTCALL
UserCreateMenu(BOOL PopupMenu
)
1423 PWINSTATION_OBJECT WinStaObject
;
1427 PEPROCESS CurrentProcess
= PsGetCurrentProcess();
1429 if (gpepCSRSS
!= CurrentProcess
)
1432 * gpepCSRSS does not have a Win32WindowStation
1435 Status
= IntValidateWindowStationHandle(CurrentProcess
->Win32WindowStation
,
1440 if (!NT_SUCCESS(Status
))
1442 ERR("Validation of window station handle (%p) failed\n",
1443 CurrentProcess
->Win32WindowStation
);
1444 SetLastNtError(Status
);
1447 Menu
= IntCreateMenu(&Handle
, !PopupMenu
);
1448 if (Menu
&& Menu
->head
.rpdesk
->rpwinstaParent
!= WinStaObject
)
1450 ERR("Desktop Window Station does not match Process one!\n");
1452 ObDereferenceObject(WinStaObject
);
1456 Menu
= IntCreateMenu(&Handle
, !PopupMenu
);
1459 if (Menu
) UserDereferenceObject(Menu
);
1460 return (HMENU
)Handle
;
1468 PROSMENUITEMINFO ItemInfo
,
1470 PUNICODE_STRING lpstr
)
1475 if (!(MenuItem
= MENU_FindItem( &Menu
, &Item
, (ByPosition
? MF_BYPOSITION
: MF_BYCOMMAND
) )))
1477 EngSetLastError(ERROR_MENU_ITEM_NOT_FOUND
);
1482 Ret
= IntSetMenuItemInfo(Menu
, MenuItem
, ItemInfo
, lpstr
);
1486 Ret
= IntGetMenuItemInfo(Menu
, MenuItem
, ItemInfo
);
1496 PROSMENUITEMINFO UnsafeItemInfo
,
1498 PUNICODE_STRING lpstr
)
1501 ROSMENUITEMINFO ItemInfo
;
1506 Status
= MmCopyFromCaller(&Size
, &UnsafeItemInfo
->cbSize
, sizeof(UINT
));
1507 if (! NT_SUCCESS(Status
))
1509 SetLastNtError(Status
);
1512 if (sizeof(MENUITEMINFOW
) != Size
1513 && FIELD_OFFSET(MENUITEMINFOW
, hbmpItem
) != Size
1514 && sizeof(ROSMENUITEMINFO
) != Size
)
1516 EngSetLastError(ERROR_INVALID_PARAMETER
);
1519 Status
= MmCopyFromCaller(&ItemInfo
, UnsafeItemInfo
, Size
);
1520 if (! NT_SUCCESS(Status
))
1522 SetLastNtError(Status
);
1525 /* If this is a pre-0x0500 _WIN32_WINNT MENUITEMINFOW, you can't
1527 if (FIELD_OFFSET(MENUITEMINFOW
, hbmpItem
) == Size
1528 && 0 != (ItemInfo
.fMask
& MIIM_BITMAP
))
1530 EngSetLastError(ERROR_INVALID_PARAMETER
);
1534 if (!(MenuItem
= MENU_FindItem( &Menu
, &Item
, (ByPosition
? MF_BYPOSITION
: MF_BYCOMMAND
) )))
1536 EngSetLastError(ERROR_MENU_ITEM_NOT_FOUND
);
1542 Ret
= IntSetMenuItemInfo(Menu
, MenuItem
, &ItemInfo
, lpstr
);
1546 Ret
= IntGetMenuItemInfo(Menu
, MenuItem
, &ItemInfo
);
1549 Status
= MmCopyToCaller(UnsafeItemInfo
, &ItemInfo
, Size
);
1550 if (! NT_SUCCESS(Status
))
1552 SetLastNtError(Status
);
1564 PROSMENUINFO UnsafeMenuInfo
,
1570 ROSMENUINFO MenuInfo
;
1572 Status
= MmCopyFromCaller(&Size
, &UnsafeMenuInfo
->cbSize
, sizeof(DWORD
));
1573 if (! NT_SUCCESS(Status
))
1575 SetLastNtError(Status
);
1578 if(Size
< sizeof(MENUINFO
) || sizeof(ROSMENUINFO
) < Size
)
1580 EngSetLastError(ERROR_INVALID_PARAMETER
);
1583 Status
= MmCopyFromCaller(&MenuInfo
, UnsafeMenuInfo
, Size
);
1584 if (! NT_SUCCESS(Status
))
1586 SetLastNtError(Status
);
1593 Res
= IntSetMenuInfo(Menu
, &MenuInfo
);
1598 Res
= IntGetMenuInfo(Menu
, &MenuInfo
);
1601 Status
= MmCopyToCaller(UnsafeMenuInfo
, &MenuInfo
, Size
);
1602 if (! NT_SUCCESS(Status
))
1604 SetLastNtError(Status
);
1614 MENU_AdjustMenuItemRect(PMENU menu
, PRECTL rect
)
1616 if (menu
->dwArrowsOn
)
1618 UINT arrow_bitmap_height
;
1620 //GetObjectW(get_up_arrow_bitmap(), sizeof(bmp), &bmp);
1621 arrow_bitmap_height
= gpsi
->oembmi
[65].cy
; ///// Menu up arrow! OBM_UPARROW DFCS_MENUARROWUP
1622 //arrow_bitmap_height = bmp.bmHeight;
1623 rect
->top
+= arrow_bitmap_height
- menu
->iTop
;
1624 rect
->bottom
+= arrow_bitmap_height
- menu
->iTop
;
1640 HWND hWnd
= Menu
->hWnd
;
1641 if (!(pWnd
= UserGetWindowObject(hWnd
))) return FALSE
;
1644 if ((MenuItem
= MENU_FindItem (&Menu
, &uItem
, MF_BYPOSITION
)))
1646 Rect
->left
= MenuItem
->xItem
;
1647 Rect
->top
= MenuItem
->yItem
;
1648 Rect
->right
= MenuItem
->cxItem
; // Do this for now......
1649 Rect
->bottom
= MenuItem
->cyItem
;
1653 ERR("Failed Item Lookup! %d\n", uItem
);
1657 if (Menu
->fFlags
& MNF_POPUP
)
1659 XMove
= pWnd
->rcClient
.left
;
1660 YMove
= pWnd
->rcClient
.top
;
1664 XMove
= pWnd
->rcWindow
.left
;
1665 YMove
= pWnd
->rcWindow
.top
;
1668 Rect
->left
+= XMove
;
1670 Rect
->right
+= XMove
;
1671 Rect
->bottom
+= YMove
;
1676 PMENU FASTCALL
MENU_GetSystemMenu(PWND Window
, PMENU Popup
)
1678 PMENU Menu
, NewMenu
= NULL
, SysMenu
= NULL
;
1679 HMENU hSysMenu
, hNewMenu
= NULL
;
1680 ROSMENUITEMINFO ItemInfoSet
= {0};
1681 ROSMENUITEMINFO ItemInfo
= {0};
1682 UNICODE_STRING MenuName
;
1684 hSysMenu
= UserCreateMenu(FALSE
);
1685 if (NULL
== hSysMenu
)
1689 SysMenu
= IntGetMenuObject(hSysMenu
);
1690 if (NULL
== SysMenu
)
1692 UserDestroyMenu(hSysMenu
);
1696 SysMenu
->fFlags
|= MNF_SYSMENU
;
1697 SysMenu
->hWnd
= Window
->head
.h
;
1701 //hNewMenu = co_IntLoadSysMenuTemplate();
1702 if ( Window
->ExStyle
& WS_EX_MDICHILD
)
1704 RtlInitUnicodeString( &MenuName
, L
"SYSMENUMDI");
1705 hNewMenu
= co_IntCallLoadMenu( hModClient
, &MenuName
);
1709 RtlInitUnicodeString( &MenuName
, L
"SYSMENU");
1710 hNewMenu
= co_IntCallLoadMenu( hModClient
, &MenuName
);
1711 //ERR("%wZ\n",&MenuName);
1716 IntReleaseMenuObject(SysMenu
);
1717 UserDestroyMenu(hSysMenu
);
1720 Menu
= IntGetMenuObject(hNewMenu
);
1723 IntReleaseMenuObject(SysMenu
);
1724 UserDestroyMenu(hSysMenu
);
1728 // Do the rest in here.
1730 Menu
->fFlags
|= MNS_CHECKORBMP
| MNF_SYSMENU
| MNF_POPUP
;
1732 ItemInfoSet
.cbSize
= sizeof( MENUITEMINFOW
);
1733 ItemInfoSet
.fMask
= MIIM_BITMAP
;
1734 ItemInfoSet
.hbmpItem
= HBMMENU_POPUP_CLOSE
;
1735 IntMenuItemInfo(Menu
, SC_CLOSE
, FALSE
, &ItemInfoSet
, TRUE
, NULL
);
1736 ItemInfoSet
.hbmpItem
= HBMMENU_POPUP_RESTORE
;
1737 IntMenuItemInfo(Menu
, SC_RESTORE
, FALSE
, &ItemInfoSet
, TRUE
, NULL
);
1738 ItemInfoSet
.hbmpItem
= HBMMENU_POPUP_MAXIMIZE
;
1739 IntMenuItemInfo(Menu
, SC_MAXIMIZE
, FALSE
, &ItemInfoSet
, TRUE
, NULL
);
1740 ItemInfoSet
.hbmpItem
= HBMMENU_POPUP_MINIMIZE
;
1741 IntMenuItemInfo(Menu
, SC_MINIMIZE
, FALSE
, &ItemInfoSet
, TRUE
, NULL
);
1743 NewMenu
= IntCloneMenu(Menu
);
1745 IntReleaseMenuObject(NewMenu
);
1746 UserSetMenuDefaultItem(NewMenu
, SC_CLOSE
, FALSE
);
1748 IntDestroyMenuObject(Menu
, FALSE
, TRUE
);
1756 NewMenu
->fFlags
|= MNF_SYSMENU
| MNF_POPUP
;
1758 if (Window
->pcls
->style
& CS_NOCLOSE
)
1759 IntRemoveMenuItem(NewMenu
, SC_CLOSE
, MF_BYCOMMAND
, TRUE
);
1761 ItemInfo
.cbSize
= sizeof(MENUITEMINFOW
);
1762 ItemInfo
.fMask
= MIIM_FTYPE
| MIIM_STRING
| MIIM_STATE
| MIIM_SUBMENU
;
1764 ItemInfo
.fState
= MFS_ENABLED
;
1765 ItemInfo
.dwTypeData
= NULL
;
1767 ItemInfo
.hSubMenu
= UserHMGetHandle(NewMenu
);
1768 IntInsertMenuItem(SysMenu
, (UINT
) -1, TRUE
, &ItemInfo
, NULL
);
1772 ERR("failed to load system menu!\n");
1777 IntGetSystemMenu(PWND Window
, BOOL bRevert
)
1783 if (Window
->SystemMenu
)
1785 Menu
= UserGetMenuObject(Window
->SystemMenu
);
1786 if (Menu
&& !(Menu
->fFlags
& MNF_SYSDESKMN
))
1788 IntDestroyMenuObject(Menu
, TRUE
, TRUE
);
1789 Window
->SystemMenu
= NULL
;
1795 Menu
= Window
->SystemMenu
? UserGetMenuObject(Window
->SystemMenu
) : NULL
;
1796 if ((!Window
->SystemMenu
|| Menu
->fFlags
& MNF_SYSDESKMN
) && Window
->style
& WS_SYSMENU
)
1798 Menu
= MENU_GetSystemMenu(Window
, NULL
);
1799 Window
->SystemMenu
= Menu
? UserHMGetHandle(Menu
) : NULL
;
1803 if (Window
->SystemMenu
)
1805 HMENU hMenu
= IntGetSubMenu( Window
->SystemMenu
, 0);
1806 /* Store the dummy sysmenu handle to facilitate the refresh */
1807 /* of the close button if the SC_CLOSE item change */
1808 Menu
= UserGetMenuObject(hMenu
);
1811 Menu
->spwndNotify
= Window
;
1812 Menu
->fFlags
|= MNF_SYSSUBMENU
;
1820 IntSetSystemMenu(PWND Window
, PMENU Menu
)
1824 if (!(Window
->style
& WS_SYSMENU
)) return FALSE
;
1826 if (Window
->SystemMenu
)
1828 OldMenu
= UserGetMenuObject(Window
->SystemMenu
);
1831 OldMenu
->fFlags
&= ~MNF_SYSMENU
;
1832 IntDestroyMenuObject(OldMenu
, TRUE
, TRUE
);
1836 OldMenu
= MENU_GetSystemMenu(Window
, Menu
);
1838 { // Use spmenuSys too!
1839 Window
->SystemMenu
= UserHMGetHandle(OldMenu
);
1842 Window
->SystemMenu
= NULL
;
1844 if (Menu
&& Window
!= Menu
->spwndNotify
)
1846 Menu
->spwndNotify
= Window
;
1853 /* FUNCTIONS *****************************************************************/
1859 NtUserCheckMenuItem(
1865 DECLARE_RETURN(DWORD
);
1867 TRACE("Enter NtUserCheckMenuItem\n");
1868 UserEnterExclusive();
1870 if(!(Menu
= UserGetMenuObject(hMenu
)))
1875 RETURN( IntCheckMenuItem(Menu
, uIDCheckItem
, uCheck
));
1878 TRACE("Leave NtUserCheckMenuItem, ret=%lu\n",_ret_
);
1893 DECLARE_RETURN(BOOL
);
1895 TRACE("Enter NtUserDeleteMenu\n");
1896 UserEnterExclusive();
1898 if(!(Menu
= UserGetMenuObject(hMenu
)))
1903 RETURN( IntRemoveMenuItem(Menu
, uPosition
, uFlags
, TRUE
));
1906 TRACE("Leave NtUserDeleteMenu, ret=%i\n",_ret_
);
1912 * NtUserGetSystemMenu
1914 * The NtUserGetSystemMenu function allows the application to access the
1915 * window menu (also known as the system menu or the control menu) for
1916 * copying and modifying.
1920 * Handle to the window that will own a copy of the window menu.
1922 * Specifies the action to be taken. If this parameter is FALSE,
1923 * NtUserGetSystemMenu returns a handle to the copy of the window menu
1924 * currently in use. The copy is initially identical to the window menu
1925 * but it can be modified.
1926 * If this parameter is TRUE, GetSystemMenu resets the window menu back
1927 * to the default state. The previous window menu, if any, is destroyed.
1930 * If the bRevert parameter is FALSE, the return value is a handle to a
1931 * copy of the window menu. If the bRevert parameter is TRUE, the return
1939 NtUserGetSystemMenu(HWND hWnd
, BOOL bRevert
)
1943 DECLARE_RETURN(HMENU
);
1945 TRACE("Enter NtUserGetSystemMenu\n");
1948 if (!(Window
= UserGetWindowObject(hWnd
)))
1953 if (!(Menu
= IntGetSystemMenu(Window
, bRevert
)))
1958 RETURN(Menu
->head
.h
);
1961 TRACE("Leave NtUserGetSystemMenu, ret=%p\n", _ret_
);
1967 * NtUserSetSystemMenu
1974 NtUserSetSystemMenu(HWND hWnd
, HMENU hMenu
)
1976 BOOL Result
= FALSE
;
1979 DECLARE_RETURN(BOOL
);
1981 TRACE("Enter NtUserSetSystemMenu\n");
1982 UserEnterExclusive();
1984 if (!(Window
= UserGetWindowObject(hWnd
)))
1992 * Assign new menu handle and Up the Lock Count.
1994 if (!(Menu
= IntGetMenuObject(hMenu
)))
1999 Result
= IntSetSystemMenu(Window
, Menu
);
2002 EngSetLastError(ERROR_INVALID_MENU_HANDLE
);
2007 TRACE("Leave NtUserSetSystemMenu, ret=%i\n",_ret_
);
2016 NtUserGetTitleBarInfo(
2021 TITLEBARINFO bartitleinfo
;
2022 DECLARE_RETURN(BOOLEAN
);
2023 BOOLEAN retValue
= TRUE
;
2025 TRACE("Enter NtUserGetTitleBarInfo\n");
2026 UserEnterExclusive();
2028 /* Vaildate the windows handle */
2029 if (!(WindowObject
= UserGetWindowObject(hwnd
)))
2031 EngSetLastError(ERROR_INVALID_WINDOW_HANDLE
);
2037 /* Copy our usermode buffer bti to local buffer bartitleinfo */
2038 ProbeForRead(bti
, sizeof(TITLEBARINFO
), 1);
2039 RtlCopyMemory(&bartitleinfo
, bti
, sizeof(TITLEBARINFO
));
2041 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2043 /* Fail copy the data */
2044 EngSetLastError(ERROR_INVALID_PARAMETER
);
2049 /* Get the tile bar info */
2052 retValue
= intGetTitleBarInfo(WindowObject
, &bartitleinfo
);
2057 /* Copy our buffer to user mode buffer bti */
2058 ProbeForWrite(bti
, sizeof(TITLEBARINFO
), 1);
2059 RtlCopyMemory(bti
, &bartitleinfo
, sizeof(TITLEBARINFO
));
2061 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2063 /* Fail copy the data */
2064 EngSetLastError(ERROR_INVALID_PARAMETER
);
2074 TRACE("Leave NtUserGetTitleBarInfo, ret=%u\n",_ret_
);
2082 BOOL FASTCALL
UserDestroyMenu(HMENU hMenu
)
2085 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
2087 if(!(Menu
= UserGetMenuObject(hMenu
)))
2092 if (Menu
->head
.rpdesk
!= pti
->rpdesk
)
2094 EngSetLastError(ERROR_ACCESS_DENIED
);
2097 return IntDestroyMenuObject(Menu
, FALSE
, TRUE
);
2108 DECLARE_RETURN(BOOL
);
2110 TRACE("Enter NtUserDestroyMenu\n");
2111 UserEnterExclusive();
2113 if(!(Menu
= UserGetMenuObject(hMenu
)))
2117 if (Menu
->head
.rpdesk
!= gptiCurrent
->rpdesk
)
2119 EngSetLastError(ERROR_ACCESS_DENIED
);
2122 RETURN( IntDestroyMenuObject(Menu
, TRUE
, TRUE
));
2125 TRACE("Leave NtUserDestroyMenu, ret=%i\n",_ret_
);
2134 NtUserEnableMenuItem(
2140 DECLARE_RETURN(UINT
);
2142 TRACE("Enter NtUserEnableMenuItem\n");
2143 UserEnterExclusive();
2145 if(!(Menu
= UserGetMenuObject(hMenu
)))
2150 RETURN( IntEnableMenuItem(Menu
, uIDEnableItem
, uEnable
));
2153 TRACE("Leave NtUserEnableMenuItem, ret=%u\n",_ret_
);
2162 NtUserGetMenuBarInfo(
2172 NTSTATUS Status
= STATUS_SUCCESS
;
2174 DECLARE_RETURN(BOOL
);
2176 TRACE("Enter NtUserGetMenuBarInfo\n");
2179 if (!(pWnd
= UserGetWindowObject(hwnd
)))
2181 EngSetLastError(ERROR_INVALID_WINDOW_HANDLE
);
2188 if (!pWnd
->pcls
->fnid
)
2190 if (pWnd
->pcls
->fnid
!= FNID_MENU
)
2192 WARN("called on invalid window: %d\n", pWnd
->pcls
->fnid
);
2193 EngSetLastError(ERROR_INVALID_MENU_HANDLE
);
2196 // Windows does this! Wine checks for Atom and uses GetWindowLongPtrW.
2197 hMenu
= (HMENU
)co_IntSendMessage(hwnd
, MN_GETHMENU
, 0, 0);
2200 hMenu
= UlongToHandle(pWnd
->IDMenu
);
2203 if (!(pWnd
->style
& WS_SYSMENU
)) RETURN(FALSE
);
2204 Menu
= IntGetSystemMenu(pWnd
, FALSE
);
2205 hMenu
= Menu
->head
.h
;
2216 kmbi
.cbSize
= pmbi
->cbSize
;
2218 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2224 if (kmbi
.cbSize
!= sizeof(MENUBARINFO
))
2226 EngSetLastError(ERROR_INVALID_PARAMETER
);
2230 if (!Menu
) Menu
= UserGetMenuObject(hMenu
);
2234 if (idItem
< 0 || idItem
> Menu
->cItems
)
2237 RECTL_vSetEmptyRect(&kmbi
.rcBar
);
2241 Ret
= IntGetMenuItemRect(pWnd
, Menu
, 0, &kmbi
.rcBar
);
2242 kmbi
.rcBar
.right
= kmbi
.rcBar
.left
+ Menu
->cxMenu
;
2243 kmbi
.rcBar
.bottom
= kmbi
.rcBar
.top
+ Menu
->cyMenu
;
2244 TRACE("idItem 0 %d\n",Ret
);
2248 Ret
= IntGetMenuItemRect(pWnd
, Menu
, idItem
-1, &kmbi
.rcBar
);
2249 TRACE("idItem X %d\n", Ret
);
2253 kmbi
.hwndMenu
= NULL
;
2254 kmbi
.fBarFocused
= FALSE
;
2255 kmbi
.fFocused
= FALSE
;
2256 //kmbi.fBarFocused = top_popup_hmenu == hMenu;
2259 kmbi
.fFocused
= Menu
->iItem
== idItem
-1;
2260 if (kmbi
.fFocused
&& (Menu
->rgItems
[idItem
- 1].spSubMenu
))
2262 kmbi
.hwndMenu
= Menu
->rgItems
[idItem
- 1].spSubMenu
->hWnd
;
2267 kmbi.fFocused = kmbi.fBarFocused;
2272 RtlCopyMemory(pmbi
, &kmbi
, sizeof(MENUBARINFO
));
2274 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2276 Status
= _SEH2_GetExceptionCode();
2280 if (!NT_SUCCESS(Status
))
2282 SetLastNtError(Status
);
2289 TRACE("Leave NtUserGetMenuBarInfo, ret=%i\n",_ret_
);
2302 PMENU Menu
, SubMenu
;
2305 DECLARE_RETURN(UINT
);
2307 TRACE("Enter NtUserGetMenuIndex\n");
2310 if ( !(Menu
= UserGetMenuObject(hMenu
)) ||
2311 !(SubMenu
= UserGetMenuObject(hSubMenu
)) )
2314 MenuItem
= Menu
->rgItems
;
2315 for (i
= 0; i
< Menu
->cItems
; i
++, MenuItem
++)
2317 if (MenuItem
->spSubMenu
== SubMenu
)
2318 RETURN(MenuItem
->wID
);
2323 TRACE("Leave NtUserGetMenuIndex, ret=%u\n",_ret_
);
2332 NtUserGetMenuItemRect(
2343 NTSTATUS Status
= STATUS_SUCCESS
;
2344 DECLARE_RETURN(BOOL
);
2346 TRACE("Enter NtUserGetMenuItemRect\n");
2349 if (!(Menu
= UserGetMenuObject(hMenu
)))
2354 if ((MenuItem
= MENU_FindItem (&Menu
, &uItem
, MF_BYPOSITION
)))
2356 Rect
.left
= MenuItem
->xItem
;
2357 Rect
.top
= MenuItem
->yItem
;
2358 Rect
.right
= MenuItem
->cxItem
; // Do this for now......
2359 Rect
.bottom
= MenuItem
->cyItem
;
2369 if (lprcItem
== NULL
) RETURN( FALSE
);
2371 if (!(ReferenceWnd
= UserGetWindowObject(hWnd
))) RETURN( FALSE
);
2373 if (Menu
->fFlags
& MNF_POPUP
)
2375 XMove
= ReferenceWnd
->rcClient
.left
;
2376 YMove
= ReferenceWnd
->rcClient
.top
;
2380 XMove
= ReferenceWnd
->rcWindow
.left
;
2381 YMove
= ReferenceWnd
->rcWindow
.top
;
2386 Rect
.right
+= XMove
;
2387 Rect
.bottom
+= YMove
;
2391 RtlCopyMemory(lprcItem
, &Rect
, sizeof(RECTL
));
2393 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2395 Status
= _SEH2_GetExceptionCode();
2399 if (!NT_SUCCESS(Status
))
2401 SetLastNtError(Status
);
2407 TRACE("Leave NtUserGetMenuItemRect, ret=%i\n",_ret_
);
2416 NtUserHiliteMenuItem(
2424 DECLARE_RETURN(BOOLEAN
);
2426 TRACE("Enter NtUserHiliteMenuItem\n");
2427 UserEnterExclusive();
2429 if(!(Window
= UserGetWindowObject(hWnd
)))
2431 EngSetLastError(ERROR_INVALID_WINDOW_HANDLE
);
2435 if(!(Menu
= UserGetMenuObject(hMenu
)))
2437 EngSetLastError(ERROR_INVALID_MENU_HANDLE
);
2441 RETURN( IntHiliteMenuItem(Window
, Menu
, uItemHilite
, uHilite
));
2444 TRACE("Leave NtUserHiliteMenuItem, ret=%u\n",_ret_
);
2454 NtUserMenuItemFromPoint(
2464 DECLARE_RETURN(int);
2466 TRACE("Enter NtUserMenuItemFromPoint\n");
2467 UserEnterExclusive();
2469 if (!(Menu
= UserGetMenuObject(hMenu
)))
2474 if (!(Window
= UserGetWindowObject(Menu
->hWnd
)))
2479 X
-= Window
->rcWindow
.left
;
2480 Y
-= Window
->rcWindow
.top
;
2483 for (i
= 0; i
< Menu
->cItems
; i
++, mi
++)
2486 Rect
.left
= mi
->xItem
;
2487 Rect
.top
= mi
->yItem
;
2488 Rect
.right
= mi
->cxItem
; // Do this for now......
2489 Rect
.bottom
= mi
->cyItem
;
2490 //MENU_AdjustMenuItemRect(Menu, &Rect); Need gpsi OBMI via callback!
2491 if (RECTL_bPointInRect(&Rect
, X
, Y
))
2497 RETURN( (mi
? i
: NO_SELECTED_ITEM
));
2500 TRACE("Leave NtUserMenuItemFromPoint, ret=%i\n",_ret_
);
2516 DECLARE_RETURN(BOOL
);
2518 TRACE("Enter NtUserRemoveMenu\n");
2519 UserEnterExclusive();
2521 if(!(Menu
= UserGetMenuObject(hMenu
)))
2526 RETURN(IntRemoveMenuItem(Menu
, uPosition
, uFlags
, FALSE
));
2529 TRACE("Leave NtUserRemoveMenu, ret=%i\n",_ret_
);
2539 NtUserSetMenuContextHelpId(
2541 DWORD dwContextHelpId
)
2544 DECLARE_RETURN(BOOL
);
2546 TRACE("Enter NtUserSetMenuContextHelpId\n");
2547 UserEnterExclusive();
2549 if(!(Menu
= UserGetMenuObject(hMenu
)))
2554 RETURN(IntSetMenuContextHelpId(Menu
, dwContextHelpId
));
2557 TRACE("Leave NtUserSetMenuContextHelpId, ret=%i\n",_ret_
);
2566 NtUserSetMenuDefaultItem(
2572 DECLARE_RETURN(BOOL
);
2574 TRACE("Enter NtUserSetMenuDefaultItem\n");
2575 UserEnterExclusive();
2577 if(!(Menu
= UserGetMenuObject(hMenu
)))
2582 RETURN( UserSetMenuDefaultItem(Menu
, uItem
, fByPos
));
2585 TRACE("Leave NtUserSetMenuDefaultItem, ret=%i\n",_ret_
);
2594 NtUserSetMenuFlagRtoL(
2598 DECLARE_RETURN(BOOL
);
2600 TRACE("Enter NtUserSetMenuFlagRtoL\n");
2601 UserEnterExclusive();
2603 if(!(Menu
= UserGetMenuObject(hMenu
)))
2608 RETURN(IntSetMenuFlagRtoL(Menu
));
2611 TRACE("Leave NtUserSetMenuFlagRtoL, ret=%i\n",_ret_
);
2620 NtUserThunkedMenuInfo(
2625 DECLARE_RETURN(BOOL
);
2627 TRACE("Enter NtUserThunkedMenuInfo\n");
2628 UserEnterExclusive();
2630 if (!(Menu
= UserGetMenuObject(hMenu
)))
2635 RETURN(UserMenuInfo(Menu
, (PROSMENUINFO
)lpcmi
, TRUE
));
2638 TRACE("Leave NtUserThunkedMenuInfo, ret=%i\n",_ret_
);
2647 NtUserThunkedMenuItemInfo(
2652 LPMENUITEMINFOW lpmii
,
2653 PUNICODE_STRING lpszCaption
)
2657 UNICODE_STRING lstrCaption
;
2658 DECLARE_RETURN(BOOL
);
2660 TRACE("Enter NtUserThunkedMenuItemInfo\n");
2661 UserEnterExclusive();
2663 /* lpszCaption may be NULL, check for it and call RtlInitUnicodeString()
2664 if bInsert == TRUE call UserInsertMenuItem() else UserSetMenuItemInfo() */
2666 if (!(Menu
= UserGetMenuObject(hMenu
)))
2671 RtlInitUnicodeString(&lstrCaption
, 0);
2673 /* Check if we got a Caption */
2674 if (lpszCaption
&& lpszCaption
->Buffer
)
2676 /* Copy the string to kernel mode */
2677 Status
= ProbeAndCaptureUnicodeString( &lstrCaption
,
2680 if (!NT_SUCCESS(Status
))
2682 ERR("Failed to capture MenuItem Caption (status 0x%08x)\n",Status
);
2683 SetLastNtError(Status
);
2688 if (bInsert
) RETURN( UserInsertMenuItem(Menu
, uItem
, fByPosition
, lpmii
, &lstrCaption
));
2690 RETURN( UserMenuItemInfo(Menu
, uItem
, fByPosition
, (PROSMENUITEMINFO
)lpmii
, TRUE
, &lstrCaption
));
2693 TRACE("Leave NtUserThunkedMenuItemInfo, ret=%i\n",_ret_
);