2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 * COPYRIGHT: See COPYING in the top level directory
22 * PROJECT: ReactOS kernel
24 * FILE: subsys/win32k/ntuser/menu.c
25 * PROGRAMER: Thomas Weidenmueller (w3seek@users.sourceforge.net)
27 * 07/30/2003 CSH Created
29 /* INCLUDES ******************************************************************/
36 extern PMENU_OBJECT FASTCALL
37 IntGetSystemMenu(PWINDOW_OBJECT Window
, BOOL bRevert
, BOOL RetMenu
);
41 /* STATIC FUNCTION ***********************************************************/
49 PROSMENUITEMINFO UnsafeItemInfo
,
56 PROSMENUINFO UnsafeMenuInfo
,
59 /* INTERNAL ******************************************************************/
61 /* maximum number of menu items a menu can contain */
62 #define MAX_MENU_ITEMS (0x4000)
63 #define MAX_GOINTOSUBMENU (0x10)
65 #define UpdateMenuItemState(state, change) \
67 if((change) & MFS_DISABLED) { \
68 (state) |= MFS_DISABLED; \
70 (state) &= ~MFS_DISABLED; \
72 if((change) & MFS_CHECKED) { \
73 (state) |= MFS_CHECKED; \
75 (state) &= ~MFS_CHECKED; \
77 if((change) & MFS_HILITE) { \
78 (state) |= MFS_HILITE; \
80 (state) &= ~MFS_HILITE; \
82 if((change) & MFS_DEFAULT) { \
83 (state) |= MFS_DEFAULT; \
85 (state) &= ~MFS_DEFAULT; \
87 if((change) & MF_MOUSESELECT) { \
88 (state) |= MF_MOUSESELECT; \
90 (state) &= ~MF_MOUSESELECT; \
94 #define FreeMenuText(MenuItem) \
96 if((MENU_ITEM_TYPE((MenuItem)->fType) == MF_STRING) && \
97 (MenuItem)->Text.Length) { \
98 RtlFreeUnicodeString(&(MenuItem)->Text); \
102 #define InRect(r, x, y) \
103 ( ( ((r).right >= x)) && \
104 ( ((r).left <= x)) && \
105 ( ((r).bottom >= y)) && \
111 return(STATUS_SUCCESS
);
115 CleanupMenuImpl(VOID
)
117 return(STATUS_SUCCESS
);
120 PMENU_OBJECT FASTCALL
UserGetMenuObject(HMENU hMenu
)
126 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
130 Menu
= (PMENU_OBJECT
)UserGetObject(&gHandleTable
, hMenu
, otMenu
);
133 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
137 ASSERT(USER_BODY_TO_HEADER(Menu
)->RefCount
>= 0);
144 DumpMenuItemList(PMENU_ITEM MenuItem
)
149 if(MenuItem
->Text
.Length
)
150 DbgPrint(" %d. %wZ\n", ++cnt
, &MenuItem
->Text
);
152 DbgPrint(" %d. NO TEXT dwTypeData==%d\n", ++cnt
, (DWORD
)MenuItem
->Text
.Buffer
);
154 if(MFT_BITMAP
& MenuItem
->fType
)
155 DbgPrint("MFT_BITMAP ");
156 if(MFT_MENUBARBREAK
& MenuItem
->fType
)
157 DbgPrint("MFT_MENUBARBREAK ");
158 if(MFT_MENUBREAK
& MenuItem
->fType
)
159 DbgPrint("MFT_MENUBREAK ");
160 if(MFT_OWNERDRAW
& MenuItem
->fType
)
161 DbgPrint("MFT_OWNERDRAW ");
162 if(MFT_RADIOCHECK
& MenuItem
->fType
)
163 DbgPrint("MFT_RADIOCHECK ");
164 if(MFT_RIGHTJUSTIFY
& MenuItem
->fType
)
165 DbgPrint("MFT_RIGHTJUSTIFY ");
166 if(MFT_SEPARATOR
& MenuItem
->fType
)
167 DbgPrint("MFT_SEPARATOR ");
168 if(MFT_STRING
& MenuItem
->fType
)
169 DbgPrint("MFT_STRING ");
170 DbgPrint("\n fState=");
171 if(MFS_DISABLED
& MenuItem
->fState
)
172 DbgPrint("MFS_DISABLED ");
174 DbgPrint("MFS_ENABLED ");
175 if(MFS_CHECKED
& MenuItem
->fState
)
176 DbgPrint("MFS_CHECKED ");
178 DbgPrint("MFS_UNCHECKED ");
179 if(MFS_HILITE
& MenuItem
->fState
)
180 DbgPrint("MFS_HILITE ");
182 DbgPrint("MFS_UNHILITE ");
183 if(MFS_DEFAULT
& MenuItem
->fState
)
184 DbgPrint("MFS_DEFAULT ");
185 if(MFS_GRAYED
& MenuItem
->fState
)
186 DbgPrint("MFS_GRAYED ");
187 DbgPrint("\n wId=%d\n", MenuItem
->wID
);
188 MenuItem
= MenuItem
->Next
;
190 DbgPrint("Entries: %d\n", cnt
);
195 PMENU_OBJECT FASTCALL
196 IntGetMenuObject(HMENU hMenu
)
198 PMENU_OBJECT Menu
= UserGetMenuObject(hMenu
);
201 ASSERT(USER_BODY_TO_HEADER(Menu
)->RefCount
>= 0);
203 USER_BODY_TO_HEADER(Menu
)->RefCount
++;
209 IntFreeMenuItem(PMENU_OBJECT Menu
, PMENU_ITEM MenuItem
,
210 BOOL RemoveFromList
, BOOL bRecurse
)
212 FreeMenuText(MenuItem
);
215 /* FIXME - Remove from List */
216 Menu
->MenuInfo
.MenuItemCount
--;
218 if(bRecurse
&& MenuItem
->hSubMenu
)
220 PMENU_OBJECT SubMenu
;
221 SubMenu
= UserGetMenuObject(MenuItem
->hSubMenu
);
224 IntDestroyMenuObject(SubMenu
, bRecurse
, TRUE
);
229 ExFreePool(MenuItem
);
235 IntRemoveMenuItem(PMENU_OBJECT Menu
, UINT uPosition
, UINT uFlags
,
238 PMENU_ITEM PrevMenuItem
, MenuItem
;
239 if(IntGetMenuItemByFlag(Menu
, uPosition
, uFlags
, &MenuItem
,
245 PrevMenuItem
->Next
= MenuItem
->Next
;
248 Menu
->MenuItemList
= MenuItem
->Next
;
250 return IntFreeMenuItem(Menu
, MenuItem
, TRUE
, bRecurse
);
257 IntDeleteMenuItems(PMENU_OBJECT Menu
, BOOL bRecurse
)
261 PMENU_ITEM CurItem
= Menu
->MenuItemList
;
264 NextItem
= CurItem
->Next
;
265 IntFreeMenuItem(Menu
, CurItem
, FALSE
, bRecurse
);
269 Menu
->MenuInfo
.MenuItemCount
= 0;
270 Menu
->MenuItemList
= NULL
;
275 IntDestroyMenuObject(PMENU_OBJECT Menu
,
276 BOOL bRecurse
, BOOL RemoveFromProcess
)
280 PWINSTATION_OBJECT WindowStation
;
283 /* remove all menu items */
284 IntDeleteMenuItems(Menu
, bRecurse
); /* do not destroy submenus */
286 if(RemoveFromProcess
)
288 RemoveEntryList(&Menu
->ListEntry
);
291 Status
= ObReferenceObjectByHandle(Menu
->Process
->Win32WindowStation
,
293 ExWindowStationObjectType
,
295 (PVOID
*)&WindowStation
,
297 if(NT_SUCCESS(Status
))
299 ObmDeleteObject(Menu
->MenuInfo
.Self
, otMenu
);
300 ObDereferenceObject(WindowStation
);
307 PMENU_OBJECT FASTCALL
308 IntCreateMenu(PHANDLE Handle
, BOOL IsMenuBar
)
312 Menu
= (PMENU_OBJECT
)ObmCreateObject(
313 &gHandleTable
, Handle
,
314 otMenu
, sizeof(MENU_OBJECT
));
322 Menu
->Process
= PsGetCurrentProcess();
323 Menu
->RtoL
= FALSE
; /* default */
324 Menu
->MenuInfo
.cbSize
= sizeof(MENUINFO
); /* not used */
325 Menu
->MenuInfo
.fMask
= 0; /* not used */
326 Menu
->MenuInfo
.dwStyle
= 0; /* FIXME */
327 Menu
->MenuInfo
.cyMax
= 0; /* default */
328 Menu
->MenuInfo
.hbrBack
=
329 NtGdiCreateSolidBrush(RGB(192, 192, 192), 0); /* FIXME: default background color */
330 Menu
->MenuInfo
.dwContextHelpID
= 0; /* default */
331 Menu
->MenuInfo
.dwMenuData
= 0; /* default */
332 Menu
->MenuInfo
.Self
= *Handle
;
333 Menu
->MenuInfo
.FocusedItem
= NO_SELECTED_ITEM
;
334 Menu
->MenuInfo
.Flags
= (IsMenuBar
? 0 : MF_POPUP
);
335 Menu
->MenuInfo
.Wnd
= NULL
;
336 Menu
->MenuInfo
.WndOwner
= NULL
;
337 Menu
->MenuInfo
.Height
= 0;
338 Menu
->MenuInfo
.Width
= 0;
339 Menu
->MenuInfo
.TimeToHide
= FALSE
;
341 Menu
->MenuInfo
.MenuItemCount
= 0;
342 Menu
->MenuItemList
= NULL
;
344 /* Insert menu item into process menu handle list */
345 InsertTailList(&PsGetWin32Process()->MenuListHead
, &Menu
->ListEntry
);
351 IntCloneMenuItems(PMENU_OBJECT Destination
, PMENU_OBJECT Source
)
353 PMENU_ITEM MenuItem
, NewMenuItem
= NULL
;
354 PMENU_ITEM Old
= NULL
;
356 if(!Source
->MenuInfo
.MenuItemCount
)
359 MenuItem
= Source
->MenuItemList
;
364 NewMenuItem
->Next
= MenuItem
;
365 NewMenuItem
= ExAllocatePoolWithTag(PagedPool
, sizeof(MENU_ITEM
), TAG_MENUITEM
);
368 NewMenuItem
->fType
= MenuItem
->fType
;
369 NewMenuItem
->fState
= MenuItem
->fState
;
370 NewMenuItem
->wID
= MenuItem
->wID
;
371 NewMenuItem
->hSubMenu
= MenuItem
->hSubMenu
;
372 NewMenuItem
->hbmpChecked
= MenuItem
->hbmpChecked
;
373 NewMenuItem
->hbmpUnchecked
= MenuItem
->hbmpUnchecked
;
374 NewMenuItem
->dwItemData
= MenuItem
->dwItemData
;
375 if((MENU_ITEM_TYPE(NewMenuItem
->fType
) == MF_STRING
))
377 if(MenuItem
->Text
.Length
)
379 NewMenuItem
->Text
.Length
= 0;
380 NewMenuItem
->Text
.MaximumLength
= MenuItem
->Text
.MaximumLength
;
381 NewMenuItem
->Text
.Buffer
= (PWSTR
)ExAllocatePoolWithTag(PagedPool
, MenuItem
->Text
.MaximumLength
, TAG_STRING
);
382 if(!NewMenuItem
->Text
.Buffer
)
384 ExFreePool(NewMenuItem
);
387 RtlCopyUnicodeString(&NewMenuItem
->Text
, &MenuItem
->Text
);
391 NewMenuItem
->Text
.Buffer
= MenuItem
->Text
.Buffer
;
396 NewMenuItem
->Text
.Buffer
= MenuItem
->Text
.Buffer
;
398 NewMenuItem
->hbmpItem
= MenuItem
->hbmpItem
;
400 NewMenuItem
->Next
= NULL
;
402 Old
->Next
= NewMenuItem
;
404 Destination
->MenuItemList
= NewMenuItem
;
405 Destination
->MenuInfo
.MenuItemCount
++;
406 MenuItem
= MenuItem
->Next
;
412 PMENU_OBJECT FASTCALL
413 IntCloneMenu(PMENU_OBJECT Source
)
421 Menu
= (PMENU_OBJECT
)ObmCreateObject(
422 &gHandleTable
, &hMenu
,
423 otMenu
, sizeof(MENU_OBJECT
));
428 Menu
->Process
= PsGetCurrentProcess();
429 Menu
->RtoL
= Source
->RtoL
;
430 Menu
->MenuInfo
.cbSize
= sizeof(MENUINFO
); /* not used */
431 Menu
->MenuInfo
.fMask
= Source
->MenuInfo
.fMask
;
432 Menu
->MenuInfo
.dwStyle
= Source
->MenuInfo
.dwStyle
;
433 Menu
->MenuInfo
.cyMax
= Source
->MenuInfo
.cyMax
;
434 Menu
->MenuInfo
.hbrBack
= Source
->MenuInfo
.hbrBack
;
435 Menu
->MenuInfo
.dwContextHelpID
= Source
->MenuInfo
.dwContextHelpID
;
436 Menu
->MenuInfo
.dwMenuData
= Source
->MenuInfo
.dwMenuData
;
437 Menu
->MenuInfo
.Self
= hMenu
;
438 Menu
->MenuInfo
.FocusedItem
= NO_SELECTED_ITEM
;
439 Menu
->MenuInfo
.Wnd
= NULL
;
440 Menu
->MenuInfo
.WndOwner
= NULL
;
441 Menu
->MenuInfo
.Height
= 0;
442 Menu
->MenuInfo
.Width
= 0;
443 Menu
->MenuInfo
.TimeToHide
= FALSE
;
445 Menu
->MenuInfo
.MenuItemCount
= 0;
446 Menu
->MenuItemList
= NULL
;
448 /* Insert menu item into process menu handle list */
449 InsertTailList(&PsGetWin32Process()->MenuListHead
, &Menu
->ListEntry
);
451 IntCloneMenuItems(Menu
, Source
);
457 IntSetMenuFlagRtoL(PMENU_OBJECT Menu
)
464 IntSetMenuContextHelpId(PMENU_OBJECT Menu
, DWORD dwContextHelpId
)
466 Menu
->MenuInfo
.dwContextHelpID
= dwContextHelpId
;
471 IntGetMenuInfo(PMENU_OBJECT Menu
, PROSMENUINFO lpmi
)
473 if(lpmi
->fMask
& MIM_BACKGROUND
)
474 lpmi
->hbrBack
= Menu
->MenuInfo
.hbrBack
;
475 if(lpmi
->fMask
& MIM_HELPID
)
476 lpmi
->dwContextHelpID
= Menu
->MenuInfo
.dwContextHelpID
;
477 if(lpmi
->fMask
& MIM_MAXHEIGHT
)
478 lpmi
->cyMax
= Menu
->MenuInfo
.cyMax
;
479 if(lpmi
->fMask
& MIM_MENUDATA
)
480 lpmi
->dwMenuData
= Menu
->MenuInfo
.dwMenuData
;
481 if(lpmi
->fMask
& MIM_STYLE
)
482 lpmi
->dwStyle
= Menu
->MenuInfo
.dwStyle
;
483 if (sizeof(MENUINFO
) < lpmi
->cbSize
)
485 RtlCopyMemory((char *) lpmi
+ sizeof(MENUINFO
),
486 (char *) &Menu
->MenuInfo
+ sizeof(MENUINFO
),
487 lpmi
->cbSize
- sizeof(MENUINFO
));
495 IntIsMenu(HMENU hMenu
)
499 if((Menu
= UserGetMenuObject(hMenu
)))
508 IntSetMenuInfo(PMENU_OBJECT Menu
, PROSMENUINFO lpmi
)
510 if(lpmi
->fMask
& MIM_BACKGROUND
)
511 Menu
->MenuInfo
.hbrBack
= lpmi
->hbrBack
;
512 if(lpmi
->fMask
& MIM_HELPID
)
513 Menu
->MenuInfo
.dwContextHelpID
= lpmi
->dwContextHelpID
;
514 if(lpmi
->fMask
& MIM_MAXHEIGHT
)
515 Menu
->MenuInfo
.cyMax
= lpmi
->cyMax
;
516 if(lpmi
->fMask
& MIM_MENUDATA
)
517 Menu
->MenuInfo
.dwMenuData
= lpmi
->dwMenuData
;
518 if(lpmi
->fMask
& MIM_STYLE
)
519 Menu
->MenuInfo
.dwStyle
= lpmi
->dwStyle
;
520 if(lpmi
->fMask
& MIM_APPLYTOSUBMENUS
)
524 if (sizeof(MENUINFO
) < lpmi
->cbSize
)
526 Menu
->MenuInfo
.FocusedItem
= lpmi
->FocusedItem
;
527 Menu
->MenuInfo
.Height
= lpmi
->Height
;
528 Menu
->MenuInfo
.Width
= lpmi
->Width
;
529 Menu
->MenuInfo
.Wnd
= lpmi
->Wnd
;
530 Menu
->MenuInfo
.WndOwner
= lpmi
->WndOwner
;
531 Menu
->MenuInfo
.TimeToHide
= lpmi
->TimeToHide
;
539 IntGetMenuItemByFlag(PMENU_OBJECT Menu
, UINT uSearchBy
, UINT fFlag
,
540 PMENU_ITEM
*MenuItem
, PMENU_ITEM
*PrevMenuItem
)
542 PMENU_ITEM PrevItem
= NULL
;
543 PMENU_ITEM CurItem
= Menu
->MenuItemList
;
547 if(MF_BYPOSITION
& fFlag
)
550 while(CurItem
&& (p
> 0))
553 CurItem
= CurItem
->Next
;
561 *PrevMenuItem
= PrevItem
;
568 *PrevMenuItem
= NULL
; /* ? */
572 return uSearchBy
- p
;
579 if(CurItem
->wID
== uSearchBy
)
584 *PrevMenuItem
= PrevItem
;
587 else if (0 != (CurItem
->fType
& MF_POPUP
))
589 Menu
= UserGetMenuObject(CurItem
->hSubMenu
);
592 ret
= IntGetMenuItemByFlag(Menu
, uSearchBy
, fFlag
,
593 MenuItem
, PrevMenuItem
);
601 CurItem
= CurItem
->Next
;
610 IntInsertMenuItemToList(PMENU_OBJECT Menu
, PMENU_ITEM MenuItem
, int pos
)
613 PMENU_ITEM LastItem
= NULL
;
616 CurItem
= Menu
->MenuItemList
;
622 CurItem
= CurItem
->Next
;
628 while(CurItem
&& (pos
> 0))
631 CurItem
= CurItem
->Next
;
641 /* insert the item before CurItem */
642 MenuItem
->Next
= LastItem
->Next
;
643 LastItem
->Next
= MenuItem
;
647 /* insert at the beginning */
648 Menu
->MenuItemList
= MenuItem
;
649 MenuItem
->Next
= CurItem
;
657 LastItem
->Next
= MenuItem
;
658 MenuItem
->Next
= NULL
;
662 /* insert first item */
663 Menu
->MenuItemList
= MenuItem
;
664 MenuItem
->Next
= NULL
;
667 Menu
->MenuInfo
.MenuItemCount
++;
673 IntGetMenuItemInfo(PMENU_OBJECT Menu
, /* UNUSED PARAM!! */
674 PMENU_ITEM MenuItem
, PROSMENUITEMINFO lpmii
)
678 if(lpmii
->fMask
& MIIM_BITMAP
)
680 lpmii
->hbmpItem
= MenuItem
->hbmpItem
;
682 if(lpmii
->fMask
& MIIM_CHECKMARKS
)
684 lpmii
->hbmpChecked
= MenuItem
->hbmpChecked
;
685 lpmii
->hbmpUnchecked
= MenuItem
->hbmpUnchecked
;
687 if(lpmii
->fMask
& MIIM_DATA
)
689 lpmii
->dwItemData
= MenuItem
->dwItemData
;
691 if(lpmii
->fMask
& (MIIM_FTYPE
| MIIM_TYPE
))
693 lpmii
->fType
= MenuItem
->fType
;
695 if(lpmii
->fMask
& MIIM_ID
)
697 lpmii
->wID
= MenuItem
->wID
;
699 if(lpmii
->fMask
& MIIM_STATE
)
701 lpmii
->fState
= MenuItem
->fState
;
703 if(lpmii
->fMask
& MIIM_SUBMENU
)
705 lpmii
->hSubMenu
= MenuItem
->hSubMenu
;
707 if (lpmii
->fMask
& (MIIM_STRING
| MIIM_TYPE
))
709 if (lpmii
->dwTypeData
== NULL
)
711 lpmii
->cch
= MenuItem
->Text
.Length
/ sizeof(WCHAR
);
715 Status
= MmCopyToCaller(lpmii
->dwTypeData
, MenuItem
->Text
.Buffer
,
716 min(lpmii
->cch
* sizeof(WCHAR
),
717 MenuItem
->Text
.MaximumLength
));
718 if (! NT_SUCCESS(Status
))
720 SetLastNtError(Status
);
726 if (sizeof(ROSMENUITEMINFO
) == lpmii
->cbSize
)
728 lpmii
->Rect
= MenuItem
->Rect
;
729 lpmii
->XTab
= MenuItem
->XTab
;
736 IntSetMenuItemInfo(PMENU_OBJECT MenuObject
, PMENU_ITEM MenuItem
, PROSMENUITEMINFO lpmii
)
738 PMENU_OBJECT SubMenuObject
;
740 if(!MenuItem
|| !MenuObject
|| !lpmii
)
745 MenuItem
->fType
= lpmii
->fType
;
747 if(lpmii
->fMask
& MIIM_BITMAP
)
749 MenuItem
->hbmpItem
= lpmii
->hbmpItem
;
751 if(lpmii
->fMask
& MIIM_CHECKMARKS
)
753 MenuItem
->hbmpChecked
= lpmii
->hbmpChecked
;
754 MenuItem
->hbmpUnchecked
= lpmii
->hbmpUnchecked
;
756 if(lpmii
->fMask
& MIIM_DATA
)
758 MenuItem
->dwItemData
= lpmii
->dwItemData
;
760 if(lpmii
->fMask
& (MIIM_FTYPE
| MIIM_TYPE
))
763 * Delete the menu item type when changing type from
766 if (MenuItem
->fType
!= lpmii
->fType
&&
767 MENU_ITEM_TYPE(MenuItem
->fType
) == MF_STRING
)
769 FreeMenuText(MenuItem
);
770 RtlInitUnicodeString(&MenuItem
->Text
, NULL
);
772 MenuItem
->fType
= lpmii
->fType
;
774 if(lpmii
->fMask
& MIIM_ID
)
776 MenuItem
->wID
= lpmii
->wID
;
778 if(lpmii
->fMask
& MIIM_STATE
)
780 /* remove MFS_DEFAULT flag from all other menu items if this item
781 has the MFS_DEFAULT state */
782 if(lpmii
->fState
& MFS_DEFAULT
)
783 UserSetMenuDefaultItem(MenuObject
, -1, 0);
784 /* update the menu item state flags */
785 UpdateMenuItemState(MenuItem
->fState
, lpmii
->fState
);
788 if(lpmii
->fMask
& MIIM_SUBMENU
)
790 MenuItem
->hSubMenu
= lpmii
->hSubMenu
;
791 /* Make sure the submenu is marked as a popup menu */
792 if (MenuItem
->hSubMenu
)
794 SubMenuObject
= UserGetMenuObject(MenuItem
->hSubMenu
);
795 if (SubMenuObject
!= NULL
)
797 SubMenuObject
->MenuInfo
.Flags
|= MF_POPUP
;
798 MenuItem
->fType
|= MF_POPUP
;
802 MenuItem
->fType
&= ~MF_POPUP
;
807 MenuItem
->fType
&= ~MF_POPUP
;
810 if ((lpmii
->fMask
& (MIIM_TYPE
| MIIM_STRING
)) &&
811 (MENU_ITEM_TYPE(lpmii
->fType
) == MF_STRING
))
813 FreeMenuText(MenuItem
);
815 if(lpmii
->dwTypeData
&& lpmii
->cch
)
817 UNICODE_STRING Source
;
820 Source
.MaximumLength
= lpmii
->cch
* sizeof(WCHAR
);
821 Source
.Buffer
= lpmii
->dwTypeData
;
823 MenuItem
->Text
.Buffer
= (PWSTR
)ExAllocatePoolWithTag(
824 PagedPool
, Source
.Length
+ sizeof(WCHAR
), TAG_STRING
);
825 if(MenuItem
->Text
.Buffer
!= NULL
)
827 MenuItem
->Text
.Length
= 0;
828 MenuItem
->Text
.MaximumLength
= Source
.Length
+ sizeof(WCHAR
);
829 RtlCopyUnicodeString(&MenuItem
->Text
, &Source
);
830 MenuItem
->Text
.Buffer
[MenuItem
->Text
.Length
/ sizeof(WCHAR
)] = 0;
834 RtlInitUnicodeString(&MenuItem
->Text
, NULL
);
839 if (0 == (MenuObject
->MenuInfo
.Flags
& MF_SYSMENU
))
841 MenuItem
->fType
|= MF_SEPARATOR
;
843 RtlInitUnicodeString(&MenuItem
->Text
, NULL
);
847 if (sizeof(ROSMENUITEMINFO
) == lpmii
->cbSize
)
849 MenuItem
->Rect
= lpmii
->Rect
;
850 MenuItem
->XTab
= lpmii
->XTab
;
857 IntInsertMenuItem(PMENU_OBJECT MenuObject
, UINT uItem
, BOOL fByPosition
,
858 PROSMENUITEMINFO ItemInfo
)
860 int pos
= (int)uItem
;
863 if (MAX_MENU_ITEMS
<= MenuObject
->MenuInfo
.MenuItemCount
)
865 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
871 /* calculate position */
872 if(MenuObject
->MenuInfo
.MenuItemCount
< pos
)
874 pos
= MenuObject
->MenuInfo
.MenuItemCount
;
879 pos
= IntGetMenuItemByFlag(MenuObject
, uItem
, MF_BYCOMMAND
, NULL
, NULL
);
886 MenuItem
= ExAllocatePoolWithTag(PagedPool
, sizeof(MENU_ITEM
), TAG_MENUITEM
);
887 if (NULL
== MenuItem
)
889 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
893 MenuItem
->fType
= MFT_STRING
;
894 MenuItem
->fState
= MFS_ENABLED
| MFS_UNCHECKED
;
896 MenuItem
->hSubMenu
= (HMENU
)0;
897 MenuItem
->hbmpChecked
= (HBITMAP
)0;
898 MenuItem
->hbmpUnchecked
= (HBITMAP
)0;
899 MenuItem
->dwItemData
= 0;
900 RtlInitUnicodeString(&MenuItem
->Text
, NULL
);
901 MenuItem
->hbmpItem
= (HBITMAP
)0;
903 if (! IntSetMenuItemInfo(MenuObject
, MenuItem
, ItemInfo
))
905 ExFreePool(MenuItem
);
909 /* Force size recalculation! */
910 MenuObject
->MenuInfo
.Height
= 0;
912 pos
= IntInsertMenuItemToList(MenuObject
, MenuItem
, pos
);
914 DPRINT("IntInsertMenuItemToList = %i\n", pos
);
920 IntEnableMenuItem(PMENU_OBJECT MenuObject
, UINT uIDEnableItem
, UINT uEnable
)
923 UINT res
= IntGetMenuItemByFlag(MenuObject
, uIDEnableItem
, uEnable
, &MenuItem
, NULL
);
924 if(!MenuItem
|| (res
== (UINT
)-1))
929 res
= MenuItem
->fState
& (MF_GRAYED
| MF_DISABLED
);
931 if(uEnable
& MF_DISABLED
)
933 if(!(MenuItem
->fState
& MF_DISABLED
))
934 MenuItem
->fState
|= MF_DISABLED
;
935 if(uEnable
& MF_GRAYED
)
937 if(!(MenuItem
->fState
& MF_GRAYED
))
938 MenuItem
->fState
|= MF_GRAYED
;
943 if(uEnable
& MF_GRAYED
)
945 if(!(MenuItem
->fState
& MF_GRAYED
))
946 MenuItem
->fState
|= MF_GRAYED
;
947 if(!(MenuItem
->fState
& MF_DISABLED
))
948 MenuItem
->fState
|= MF_DISABLED
;
952 if(MenuItem
->fState
& MF_DISABLED
)
953 MenuItem
->fState
^= MF_DISABLED
;
954 if(MenuItem
->fState
& MF_GRAYED
)
955 MenuItem
->fState
^= MF_GRAYED
;
964 IntBuildMenuItemList(PMENU_OBJECT MenuObject
, PVOID Buffer
, ULONG nMax
)
970 PMENU_ITEM CurItem
= MenuObject
->MenuItemList
;
977 if (nMax
< MenuObject
->MenuInfo
.MenuItemCount
* sizeof(ROSMENUITEMINFO
))
981 StrOut
= (PWCHAR
)((char *) Buffer
+ MenuObject
->MenuInfo
.MenuItemCount
982 * sizeof(ROSMENUITEMINFO
));
983 nMax
-= MenuObject
->MenuInfo
.MenuItemCount
* sizeof(ROSMENUITEMINFO
);
984 sz
= sizeof(ROSMENUITEMINFO
);
986 mii
.cbSize
= sizeof(ROSMENUITEMINFO
);
990 while (NULL
!= CurItem
)
992 mii
.cch
= CurItem
->Text
.Length
/ sizeof(WCHAR
);
993 mii
.dwItemData
= CurItem
->dwItemData
;
994 if (0 != CurItem
->Text
.Length
)
996 mii
.dwTypeData
= StrOut
;
1000 mii
.dwTypeData
= NULL
;
1002 mii
.fState
= CurItem
->fState
;
1003 mii
.fType
= CurItem
->fType
;
1004 mii
.hbmpChecked
= CurItem
->hbmpChecked
;
1005 mii
.hbmpItem
= CurItem
->hbmpItem
;
1006 mii
.hbmpUnchecked
= CurItem
->hbmpUnchecked
;
1007 mii
.hSubMenu
= CurItem
->hSubMenu
;
1008 mii
.Rect
= CurItem
->Rect
;
1009 mii
.XTab
= CurItem
->XTab
;
1011 Status
= MmCopyToCaller(Buf
, &mii
, sizeof(ROSMENUITEMINFO
));
1012 if (! NT_SUCCESS(Status
))
1014 SetLastNtError(Status
);
1017 Buf
= (PVOID
)((ULONG_PTR
)Buf
+ sizeof(ROSMENUITEMINFO
));
1019 if (0 != CurItem
->Text
.Length
1020 && (nMax
>= CurItem
->Text
.Length
+ sizeof(WCHAR
)))
1023 Status
= MmCopyToCaller(StrOut
, CurItem
->Text
.Buffer
,
1024 CurItem
->Text
.Length
);
1025 if (! NT_SUCCESS(Status
))
1027 SetLastNtError(Status
);
1030 StrOut
+= CurItem
->Text
.Length
/ sizeof(WCHAR
);
1031 Status
= MmCopyToCaller(StrOut
, &NulByte
, sizeof(WCHAR
));
1032 if (! NT_SUCCESS(Status
))
1034 SetLastNtError(Status
);
1038 nMax
-= CurItem
->Text
.Length
+ sizeof(WCHAR
);
1040 else if (0 != CurItem
->Text
.Length
)
1045 CurItem
= CurItem
->Next
;
1051 while (NULL
!= CurItem
)
1053 res
+= sizeof(ROSMENUITEMINFO
) + CurItem
->Text
.Length
+ sizeof(WCHAR
);
1054 CurItem
= CurItem
->Next
;
1063 IntCheckMenuItem(PMENU_OBJECT MenuObject
, UINT uIDCheckItem
, UINT uCheck
)
1065 PMENU_ITEM MenuItem
;
1068 if((IntGetMenuItemByFlag(MenuObject
, uIDCheckItem
, uCheck
, &MenuItem
, NULL
) < 0) || !MenuItem
)
1073 res
= (DWORD
)(MenuItem
->fState
& MF_CHECKED
);
1074 if(uCheck
& MF_CHECKED
)
1076 if(!(MenuItem
->fState
& MF_CHECKED
))
1077 MenuItem
->fState
|= MF_CHECKED
;
1081 if(MenuItem
->fState
& MF_CHECKED
)
1082 MenuItem
->fState
^= MF_CHECKED
;
1089 IntHiliteMenuItem(PWINDOW_OBJECT WindowObject
, PMENU_OBJECT MenuObject
,
1090 UINT uItemHilite
, UINT uHilite
)
1092 PMENU_ITEM MenuItem
;
1093 BOOL res
= IntGetMenuItemByFlag(MenuObject
, uItemHilite
, uHilite
, &MenuItem
, NULL
);
1094 if(!MenuItem
|| !res
)
1099 if(uHilite
& MF_HILITE
)
1101 if(!(MenuItem
->fState
& MF_HILITE
))
1102 MenuItem
->fState
|= MF_HILITE
;
1106 if(MenuItem
->fState
& MF_HILITE
)
1107 MenuItem
->fState
^= MF_HILITE
;
1110 /* FIXME - update the window's menu */
1116 UserSetMenuDefaultItem(PMENU_OBJECT MenuObject
, UINT uItem
, UINT fByPos
)
1119 PMENU_ITEM MenuItem
= MenuObject
->MenuItemList
;
1121 if(uItem
== (UINT
)-1)
1125 if(MenuItem
->fState
& MFS_DEFAULT
)
1126 MenuItem
->fState
^= MFS_DEFAULT
;
1127 MenuItem
= MenuItem
->Next
;
1139 if(!(MenuItem
->fState
& MFS_DEFAULT
))
1140 MenuItem
->fState
|= MFS_DEFAULT
;
1145 if(MenuItem
->fState
& MFS_DEFAULT
)
1146 MenuItem
->fState
^= MFS_DEFAULT
;
1149 MenuItem
= MenuItem
->Next
;
1156 if(!ret
&& (MenuItem
->wID
== uItem
))
1158 if(!(MenuItem
->fState
& MFS_DEFAULT
))
1159 MenuItem
->fState
|= MFS_DEFAULT
;
1164 if(MenuItem
->fState
& MFS_DEFAULT
)
1165 MenuItem
->fState
^= MFS_DEFAULT
;
1167 MenuItem
= MenuItem
->Next
;
1175 IntGetMenuDefaultItem(PMENU_OBJECT MenuObject
, UINT fByPos
, UINT gmdiFlags
,
1181 PMENU_OBJECT SubMenuObject
;
1182 PMENU_ITEM MenuItem
= MenuObject
->MenuItemList
;
1186 if(MenuItem
->fState
& MFS_DEFAULT
)
1189 if(!(gmdiFlags
& GMDI_USEDISABLED
) && (MenuItem
->fState
& MFS_DISABLED
))
1192 if(fByPos
& MF_BYPOSITION
)
1195 res
= MenuItem
->wID
;
1197 if((*gismc
< MAX_GOINTOSUBMENU
) && (gmdiFlags
& GMDI_GOINTOPOPUPS
) &&
1201 SubMenuObject
= UserGetMenuObject(MenuItem
->hSubMenu
);
1202 if(!SubMenuObject
|| (SubMenuObject
== MenuObject
))
1206 sres
= IntGetMenuDefaultItem(SubMenuObject
, fByPos
, gmdiFlags
, gismc
);
1216 MenuItem
= MenuItem
->Next
;
1224 co_IntInitTracking(PWINDOW_OBJECT Window
, PMENU_OBJECT Menu
, BOOL Popup
,
1227 /* FIXME - hide caret */
1229 if(!(Flags
& TPM_NONOTIFY
))
1230 co_IntSendMessage(Window
->hSelf
, WM_SETCURSOR
, (WPARAM
)Window
->hSelf
, HTCAPTION
);
1232 /* FIXME - send WM_SETCURSOR message */
1234 if(!(Flags
& TPM_NONOTIFY
))
1235 co_IntSendMessage(Window
->hSelf
, WM_INITMENU
, (WPARAM
)Menu
->MenuInfo
.Self
, 0);
1239 co_IntExitTracking(PWINDOW_OBJECT Window
, PMENU_OBJECT Menu
, BOOL Popup
,
1242 if(!(Flags
& TPM_NONOTIFY
))
1243 co_IntSendMessage(Window
->hSelf
, WM_EXITMENULOOP
, 0 /* FIXME */, 0);
1245 /* FIXME - Show caret again */
1249 IntTrackMenu(PMENU_OBJECT Menu
, PWINDOW_OBJECT Window
, INT x
, INT y
,
1256 co_IntTrackPopupMenu(PMENU_OBJECT Menu
, PWINDOW_OBJECT Window
,
1257 UINT Flags
, POINT
*Pos
, UINT MenuPos
, RECT
*ExcludeRect
)
1259 co_IntInitTracking(Window
, Menu
, TRUE
, Flags
);
1261 co_IntExitTracking(Window
, Menu
, TRUE
, Flags
);
1266 IntSetMenuItemRect(PMENU_OBJECT Menu
, UINT Item
, BOOL fByPos
, RECT
*rcRect
)
1269 if(IntGetMenuItemByFlag(Menu
, Item
, (fByPos
? MF_BYPOSITION
: MF_BYCOMMAND
),
1280 * Internal function. Called when the process is destroyed to free the remaining menu handles.
1283 IntCleanupMenus(struct _EPROCESS
*Process
, PW32PROCESS Win32Process
)
1285 PEPROCESS CurrentProcess
;
1286 PLIST_ENTRY LastHead
= NULL
;
1287 PMENU_OBJECT MenuObject
;
1289 CurrentProcess
= PsGetCurrentProcess();
1290 if (CurrentProcess
!= Process
)
1292 KeAttachProcess(&Process
->Pcb
);
1295 while (Win32Process
->MenuListHead
.Flink
!= &(Win32Process
->MenuListHead
) &&
1296 Win32Process
->MenuListHead
.Flink
!= LastHead
)
1298 LastHead
= Win32Process
->MenuListHead
.Flink
;
1299 MenuObject
= CONTAINING_RECORD(Win32Process
->MenuListHead
.Flink
, MENU_OBJECT
, ListEntry
);
1301 IntDestroyMenuObject(MenuObject
, FALSE
, TRUE
);
1304 if (CurrentProcess
!= Process
)
1311 /* FUNCTIONS *****************************************************************/
1319 NtUserBuildMenuItemList(
1327 DECLARE_RETURN(DWORD
);
1329 DPRINT("Enter NtUserBuildMenuItemList\n");
1330 UserEnterExclusive();
1332 if(!(Menu
= UserGetMenuObject(hMenu
)))
1339 res
= IntBuildMenuItemList(Menu
, Buffer
, nBufSize
);
1343 res
= Menu
->MenuInfo
.MenuItemCount
;
1349 DPRINT("Leave NtUserBuildMenuItemList, ret=%i\n",_ret_
);
1359 NtUserCheckMenuItem(
1365 DECLARE_RETURN(DWORD
);
1367 DPRINT("Enter NtUserCheckMenuItem\n");
1368 UserEnterExclusive();
1370 if(!(Menu
= UserGetMenuObject(hMenu
)))
1375 RETURN( IntCheckMenuItem(Menu
, uIDCheckItem
, uCheck
));
1378 DPRINT("Leave NtUserCheckMenuItem, ret=%i\n",_ret_
);
1384 HMENU FASTCALL
UserCreateMenu(BOOL PopupMenu
)
1386 PWINSTATION_OBJECT WinStaObject
;
1389 NTSTATUS Status
= IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation
,
1394 if (!NT_SUCCESS(Status
))
1396 DPRINT("Validation of window station handle (0x%X) failed\n",
1397 PsGetCurrentProcess()->Win32WindowStation
);
1398 SetLastNtError(Status
);
1402 IntCreateMenu(&Handle
, !PopupMenu
);
1404 ObDereferenceObject(WinStaObject
);
1405 return (HMENU
)Handle
;
1411 NtUserCreateMenu(BOOL PopupMenu
)
1413 DECLARE_RETURN(HMENU
);
1415 DPRINT("Enter NtUserCreateMenu\n");
1416 UserEnterExclusive();
1418 RETURN(UserCreateMenu(PopupMenu
));
1421 DPRINT("Leave NtUserCreateMenu, ret=%i\n",_ret_
);
1438 DECLARE_RETURN(BOOL
);
1440 DPRINT("Enter NtUserDeleteMenu\n");
1441 UserEnterExclusive();
1443 if(!(Menu
= UserGetMenuObject(hMenu
)))
1448 RETURN( IntRemoveMenuItem(Menu
, uPosition
, uFlags
, TRUE
));
1451 DPRINT("Leave NtUserDeleteMenu, ret=%i\n",_ret_
);
1461 BOOL FASTCALL
UserDestroyMenu(HMENU hMenu
)
1465 if(!(Menu
= UserGetMenuObject(hMenu
)))
1470 if(Menu
->Process
!= PsGetCurrentProcess())
1472 SetLastWin32Error(ERROR_ACCESS_DENIED
);
1476 return IntDestroyMenuObject(Menu
, FALSE
, TRUE
);
1487 DECLARE_RETURN(BOOL
);
1489 DPRINT("Enter NtUserDestroyMenu\n");
1490 UserEnterExclusive();
1492 if(!(Menu
= UserGetMenuObject(hMenu
)))
1497 if(Menu
->Process
!= PsGetCurrentProcess())
1499 SetLastWin32Error(ERROR_ACCESS_DENIED
);
1503 RETURN( IntDestroyMenuObject(Menu
, FALSE
, TRUE
));
1506 DPRINT("Leave NtUserDestroyMenu, ret=%i\n",_ret_
);
1516 NtUserEnableMenuItem(
1522 DECLARE_RETURN(UINT
);
1524 DPRINT("Enter NtUserEnableMenuItem\n");
1525 UserEnterExclusive();
1527 if(!(Menu
= UserGetMenuObject(hMenu
)))
1532 RETURN( IntEnableMenuItem(Menu
, uIDEnableItem
, uEnable
));
1535 DPRINT("Leave NtUserEnableMenuItem, ret=%i\n",_ret_
);
1545 NtUserInsertMenuItem(
1549 LPCMENUITEMINFOW UnsafeItemInfo
)
1553 ROSMENUITEMINFO ItemInfo
;
1554 DECLARE_RETURN(DWORD
);
1556 DPRINT("Enter NtUserInsertMenuItem\n");
1557 UserEnterExclusive();
1559 if(!(Menu
= UserGetMenuObject(hMenu
)))
1564 /* Try to copy the whole MENUITEMINFOW structure */
1565 Status
= MmCopyFromCaller(&ItemInfo
, UnsafeItemInfo
, sizeof(MENUITEMINFOW
));
1566 if (NT_SUCCESS(Status
))
1568 if (sizeof(MENUITEMINFOW
) != ItemInfo
.cbSize
1569 && FIELD_OFFSET(MENUITEMINFOW
, hbmpItem
) != ItemInfo
.cbSize
)
1571 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1574 RETURN( IntInsertMenuItem(Menu
, uItem
, fByPosition
, &ItemInfo
));
1577 /* Try to copy without last field (not present in older versions) */
1578 Status
= MmCopyFromCaller(&ItemInfo
, UnsafeItemInfo
, FIELD_OFFSET(MENUITEMINFOW
, hbmpItem
));
1579 if (NT_SUCCESS(Status
))
1581 if (FIELD_OFFSET(MENUITEMINFOW
, hbmpItem
) != ItemInfo
.cbSize
)
1583 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1586 ItemInfo
.hbmpItem
= (HBITMAP
)0;
1587 RETURN( IntInsertMenuItem(Menu
, uItem
, fByPosition
, &ItemInfo
));
1590 SetLastNtError(Status
);
1594 DPRINT("Leave NtUserInsertMenuItem, ret=%i\n",_ret_
);
1616 NtUserGetMenuDefaultItem(
1623 DECLARE_RETURN(UINT
);
1625 DPRINT("Enter NtUserGetMenuDefaultItem\n");
1626 UserEnterExclusive();
1628 if(!(Menu
= UserGetMenuObject(hMenu
)))
1633 RETURN( IntGetMenuDefaultItem(Menu
, fByPos
, gmdiFlags
, &gismc
));
1636 DPRINT("Leave NtUserGetMenuDefaultItem, ret=%i\n",_ret_
);
1646 NtUserGetMenuBarInfo(
1653 PMENU_OBJECT MenuObject
;
1655 PWINDOW_OBJECT WindowObject
;
1660 DECLARE_RETURN(BOOL
);
1662 DPRINT("Enter NtUserGetMenuBarInfo\n");
1665 if (!(WindowObject
= UserGetWindowObject(hwnd
)))
1667 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
1671 hMenu
= (HMENU
)WindowObject
->IDMenu
;
1673 if (!(MenuObject
= UserGetMenuObject(hMenu
)))
1675 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
1679 if (pmbi
->cbSize
!= sizeof(MENUBARINFO
))
1681 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1685 kmbi
.cbSize
= sizeof(MENUBARINFO
);
1686 kmbi
.fBarFocused
= FALSE
;
1687 kmbi
.fFocused
= FALSE
;
1688 kmbi
.hwndMenu
= NULL
;
1694 PMENU_OBJECT SubMenuObject
;
1696 if (idItem
) /* Non-Zero-Based. */
1698 if (IntGetMenuItemByFlag(MenuObject
, idItem
-1, MF_BYPOSITION
, &mi
, NULL
) > -1)
1699 kmbi
.rcBar
= mi
->Rect
;
1708 /* If items is zero we assume info for the menu itself. */
1709 if (!(IntGetClientOrigin(WindowObject
, &Offset
)))
1714 Rect
.left
= Offset
.x
;
1715 Rect
.right
= Offset
.x
+ MenuObject
->MenuInfo
.Width
;
1716 Rect
.top
= Offset
.y
;
1717 Rect
.bottom
= Offset
.y
+ MenuObject
->MenuInfo
.Height
;
1719 DPRINT("Rect top = %d bottom = %d left = %d right = %d \n",
1720 Rect
.top
, Rect
.bottom
, Rect
.left
, Rect
.right
);
1724 if (idItem
-1 == MenuObject
->MenuInfo
.FocusedItem
)
1725 kmbi
.fFocused
= TRUE
;
1727 if (MenuObject
->MenuInfo
.FocusedItem
!= NO_SELECTED_ITEM
)
1728 kmbi
.fBarFocused
= TRUE
;
1729 SubMenuObject
= UserGetMenuObject(MenuObject
->MenuItemList
->hSubMenu
);
1730 if(SubMenuObject
) kmbi
.hwndMenu
= SubMenuObject
->MenuInfo
.Wnd
;
1731 DPRINT("OBJID_MENU, idItem = %d\n",idItem
);
1736 PMENU_OBJECT SubMenuObject
, XSubMenuObject
;
1737 SubMenuObject
= UserGetMenuObject(MenuObject
->MenuItemList
->hSubMenu
);
1738 if(SubMenuObject
) kmbi
.hMenu
= SubMenuObject
->MenuInfo
.Self
;
1742 DPRINT1("OBJID_CLIENT, No SubMenu!\n");
1747 if (IntGetMenuItemByFlag(SubMenuObject
, idItem
-1, MF_BYPOSITION
, &mi
, NULL
) > -1)
1748 kmbi
.rcBar
= mi
->Rect
;
1757 PWINDOW_OBJECT SubWinObj
;
1758 if (!(SubWinObj
= UserGetWindowObject(SubMenuObject
->MenuInfo
.Wnd
)))
1763 if (!(IntGetClientOrigin(SubWinObj
, &Offset
)))
1768 Rect
.left
= Offset
.x
;
1769 Rect
.right
= Offset
.x
+ SubMenuObject
->MenuInfo
.Width
;
1770 Rect
.top
= Offset
.y
;
1771 Rect
.bottom
= Offset
.y
+ SubMenuObject
->MenuInfo
.Height
;
1776 if (idItem
-1 == SubMenuObject
->MenuInfo
.FocusedItem
)
1777 kmbi
.fFocused
= TRUE
;
1779 if (SubMenuObject
->MenuInfo
.FocusedItem
!= NO_SELECTED_ITEM
)
1780 kmbi
.fBarFocused
= TRUE
;
1781 XSubMenuObject
= UserGetMenuObject(SubMenuObject
->MenuItemList
->hSubMenu
);
1782 if (XSubMenuObject
) kmbi
.hwndMenu
= XSubMenuObject
->MenuInfo
.Wnd
;
1783 DPRINT("OBJID_CLIENT, idItem = %d\n",idItem
);
1788 PMENU_OBJECT SysMenuObject
, SubMenuObject
;
1789 if(!(SysMenuObject
= IntGetSystemMenu(WindowObject
, FALSE
, FALSE
)))
1794 kmbi
.hMenu
= SysMenuObject
->MenuInfo
.Self
;
1797 if (IntGetMenuItemByFlag(SysMenuObject
, idItem
-1, MF_BYPOSITION
, &mi
, NULL
) > -1)
1798 kmbi
.rcBar
= mi
->Rect
;
1807 PWINDOW_OBJECT SysWinObj
;
1808 if (!(SysWinObj
= UserGetWindowObject(SysMenuObject
->MenuInfo
.Wnd
)))
1813 if (!(IntGetClientOrigin(SysWinObj
, &Offset
)))
1818 Rect
.left
= Offset
.x
;
1819 Rect
.right
= Offset
.x
+ SysMenuObject
->MenuInfo
.Width
;
1820 Rect
.top
= Offset
.y
;
1821 Rect
.bottom
= Offset
.y
+ SysMenuObject
->MenuInfo
.Height
;
1826 if (idItem
-1 == SysMenuObject
->MenuInfo
.FocusedItem
)
1827 kmbi
.fFocused
= TRUE
;
1829 if (SysMenuObject
->MenuInfo
.FocusedItem
!= NO_SELECTED_ITEM
)
1830 kmbi
.fBarFocused
= TRUE
;
1831 SubMenuObject
= UserGetMenuObject(SysMenuObject
->MenuItemList
->hSubMenu
);
1832 if(SubMenuObject
) kmbi
.hwndMenu
= SubMenuObject
->MenuInfo
.Wnd
;
1833 DPRINT("OBJID_SYSMENU, idItem = %d\n",idItem
);
1838 DPRINT1("Unknown idObject = %d, idItem = %d\n",idObject
,idItem
);
1842 NTSTATUS Status
= MmCopyToCaller(pmbi
, &kmbi
, sizeof(MENUBARINFO
));
1843 if (! NT_SUCCESS(Status
))
1845 SetLastNtError(Status
);
1852 DPRINT("Leave NtUserGetMenuBarInfo, ret=%i\n",_ret_
);
1876 NtUserGetMenuItemRect(
1887 PMENU_ITEM MenuItem
;
1888 DECLARE_RETURN(BOOL
);
1890 DPRINT("Enter NtUserGetMenuItemRect\n");
1893 if (!(Menu
= UserGetMenuObject(hMenu
)))
1898 if (IntGetMenuItemByFlag(Menu
, uItem
, MF_BYPOSITION
, &MenuItem
, NULL
) > -1)
1899 Rect
= MenuItem
->Rect
;
1903 referenceHwnd
= hWnd
;
1907 if(!UserMenuInfo(Menu
, &mi
, FALSE
))
1911 referenceHwnd
= mi
.Wnd
; /* Okay we found it, so now what do we do? */
1914 if (lprcItem
== NULL
)
1917 Status
= MmCopyToCaller(lprcItem
, &Rect
, sizeof(RECT
));
1918 if (! NT_SUCCESS(Status
))
1920 SetLastNtError(Status
);
1926 DPRINT("Leave NtUserGetMenuItemRect, ret=%i\n",_ret_
);
1936 NtUserHiliteMenuItem(
1943 PWINDOW_OBJECT Window
;
1944 DECLARE_RETURN(BOOLEAN
);
1946 DPRINT("Enter NtUserHiliteMenuItem\n");
1947 UserEnterExclusive();
1949 if(!(Window
= UserGetWindowObject(hWnd
)))
1954 if(!(Menu
= UserGetMenuObject(hMenu
)))
1959 if(Window
->IDMenu
== (UINT
)hMenu
)
1961 RETURN( IntHiliteMenuItem(Window
, Menu
, uItemHilite
, uHilite
));
1967 DPRINT("Leave NtUserHiliteMenuItem, ret=%i\n",_ret_
);
1977 PROSMENUINFO UnsafeMenuInfo
,
1983 ROSMENUINFO MenuInfo
;
1985 Status
= MmCopyFromCaller(&Size
, &UnsafeMenuInfo
->cbSize
, sizeof(DWORD
));
1986 if (! NT_SUCCESS(Status
))
1988 SetLastNtError(Status
);
1991 if(Size
< sizeof(MENUINFO
) || sizeof(ROSMENUINFO
) < Size
)
1993 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1996 Status
= MmCopyFromCaller(&MenuInfo
, UnsafeMenuInfo
, Size
);
1997 if (! NT_SUCCESS(Status
))
1999 SetLastNtError(Status
);
2006 Res
= IntSetMenuInfo(Menu
, &MenuInfo
);
2011 Res
= IntGetMenuInfo(Menu
, &MenuInfo
);
2014 Status
= MmCopyToCaller(UnsafeMenuInfo
, &MenuInfo
, Size
);
2015 if (! NT_SUCCESS(Status
))
2017 SetLastNtError(Status
);
2037 PROSMENUINFO UnsafeMenuInfo
,
2041 DECLARE_RETURN(BOOL
);
2043 DPRINT("Enter NtUserMenuInfo\n");
2046 if (!(Menu
= UserGetMenuObject(hMenu
)))
2051 RETURN(UserMenuInfo(Menu
, UnsafeMenuInfo
, SetOrGet
));
2054 DPRINT("Leave NtUserMenuInfo, ret=%i\n",_ret_
);
2065 NtUserMenuItemFromPoint(
2072 PWINDOW_OBJECT Window
= NULL
;
2075 DECLARE_RETURN(int);
2077 DPRINT("Enter NtUserMenuItemFromPoint\n");
2078 UserEnterExclusive();
2080 if (!(Menu
= UserGetMenuObject(hMenu
)))
2085 if (!(Window
= UserGetWindowObject(Menu
->MenuInfo
.Wnd
)))
2090 X
-= Window
->WindowRect
.left
;
2091 Y
-= Window
->WindowRect
.top
;
2093 mi
= Menu
->MenuItemList
;
2094 for (i
= 0; NULL
!= mi
; i
++)
2096 if (InRect(mi
->Rect
, X
, Y
))
2103 RETURN( (mi
? i
: NO_SELECTED_ITEM
));
2106 DPRINT("Leave NtUserMenuItemFromPoint, ret=%i\n",_ret_
);
2119 PROSMENUITEMINFO UnsafeItemInfo
,
2122 PMENU_ITEM MenuItem
;
2123 ROSMENUITEMINFO ItemInfo
;
2128 Status
= MmCopyFromCaller(&Size
, &UnsafeItemInfo
->cbSize
, sizeof(UINT
));
2129 if (! NT_SUCCESS(Status
))
2131 SetLastNtError(Status
);
2134 if (sizeof(MENUITEMINFOW
) != Size
2135 && FIELD_OFFSET(MENUITEMINFOW
, hbmpItem
) != Size
2136 && sizeof(ROSMENUITEMINFO
) != Size
)
2138 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
2141 Status
= MmCopyFromCaller(&ItemInfo
, UnsafeItemInfo
, Size
);
2142 if (! NT_SUCCESS(Status
))
2144 SetLastNtError(Status
);
2147 /* If this is a pre-0x0500 _WIN32_WINNT MENUITEMINFOW, you can't
2149 if (FIELD_OFFSET(MENUITEMINFOW
, hbmpItem
) == Size
2150 && 0 != (ItemInfo
.fMask
& MIIM_BITMAP
))
2152 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
2156 if (IntGetMenuItemByFlag(Menu
, Item
,
2157 (ByPosition
? MF_BYPOSITION
: MF_BYCOMMAND
),
2158 &MenuItem
, NULL
) < 0)
2160 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
2166 Ret
= IntSetMenuItemInfo(Menu
, MenuItem
, &ItemInfo
);
2170 Ret
= IntGetMenuItemInfo(Menu
, MenuItem
, &ItemInfo
);
2173 Status
= MmCopyToCaller(UnsafeItemInfo
, &ItemInfo
, Size
);
2174 if (! NT_SUCCESS(Status
))
2176 SetLastNtError(Status
);
2196 PROSMENUITEMINFO UnsafeItemInfo
,
2200 DECLARE_RETURN(BOOL
);
2202 DPRINT("Enter NtUserMenuItemInfo\n");
2203 UserEnterExclusive();
2205 if (!(Menu
= UserGetMenuObject(hMenu
)))
2210 RETURN( UserMenuItemInfo(Menu
, Item
, ByPosition
, UnsafeItemInfo
, SetOrGet
));
2213 DPRINT("Leave NtUserMenuItemInfo, ret=%i\n",_ret_
);
2230 DECLARE_RETURN(BOOL
);
2232 DPRINT("Enter NtUserRemoveMenu\n");
2233 UserEnterExclusive();
2235 if(!(Menu
= UserGetMenuObject(hMenu
)))
2240 RETURN(IntRemoveMenuItem(Menu
, uPosition
, uFlags
, FALSE
));
2243 DPRINT("Leave NtUserRemoveMenu, ret=%i\n",_ret_
);
2254 NtUserSetMenuContextHelpId(
2256 DWORD dwContextHelpId
)
2259 DECLARE_RETURN(BOOL
);
2261 DPRINT("Enter NtUserSetMenuContextHelpId\n");
2262 UserEnterExclusive();
2264 if(!(Menu
= UserGetMenuObject(hMenu
)))
2269 RETURN(IntSetMenuContextHelpId(Menu
, dwContextHelpId
));
2272 DPRINT("Leave NtUserSetMenuContextHelpId, ret=%i\n",_ret_
);
2283 NtUserSetMenuDefaultItem(
2289 DECLARE_RETURN(BOOL
);
2291 DPRINT("Enter NtUserSetMenuDefaultItem\n");
2292 UserEnterExclusive();
2294 if(!(Menu
= UserGetMenuObject(hMenu
)))
2299 RETURN( UserSetMenuDefaultItem(Menu
, uItem
, fByPos
));
2302 DPRINT("Leave NtUserSetMenuDefaultItem, ret=%i\n",_ret_
);
2312 NtUserSetMenuFlagRtoL(
2316 DECLARE_RETURN(BOOL
);
2318 DPRINT("Enter NtUserSetMenuFlagRtoL\n");
2319 UserEnterExclusive();
2321 if(!(Menu
= UserGetMenuObject(hMenu
)))
2326 RETURN(IntSetMenuFlagRtoL(Menu
));
2329 DPRINT("Leave NtUserSetMenuFlagRtoL, ret=%i\n",_ret_
);
2339 NtUserThunkedMenuInfo(
2344 /* This function seems just to call SetMenuInfo() */
2353 NtUserThunkedMenuItemInfo(
2358 LPMENUITEMINFOW lpmii
,
2359 PUNICODE_STRING lpszCaption
)
2362 /* lpszCaption may be NULL, check for it and call RtlInitUnicodeString()
2363 if bInsert == TRUE call NtUserInsertMenuItem() else NtUserSetMenuItemInfo()
2372 /* NOTE: unused function */
2374 NtUserTrackPopupMenuEx(