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 /* Maximum number of menu items a menu can contain */
15 #define MAX_MENU_ITEMS (0x4000)
16 #define MAX_GOINTOSUBMENU (0x10)
18 #define UpdateMenuItemState(state, change) \
20 if((change) & MFS_DISABLED) { \
21 (state) |= MFS_DISABLED; \
23 (state) &= ~MFS_DISABLED; \
25 if((change) & MFS_CHECKED) { \
26 (state) |= MFS_CHECKED; \
28 (state) &= ~MFS_CHECKED; \
30 if((change) & MFS_HILITE) { \
31 (state) |= MFS_HILITE; \
33 (state) &= ~MFS_HILITE; \
35 if((change) & MFS_DEFAULT) { \
36 (state) |= MFS_DEFAULT; \
38 (state) &= ~MFS_DEFAULT; \
40 if((change) & MF_MOUSESELECT) { \
41 (state) |= MF_MOUSESELECT; \
43 (state) &= ~MF_MOUSESELECT; \
47 #define FreeMenuText(MenuItem) \
49 if((MENU_ITEM_TYPE((MenuItem)->fType) == MF_STRING) && \
50 (MenuItem)->Text.Length) { \
51 ExFreePoolWithTag((MenuItem)->Text.Buffer, TAG_STRING); \
56 PMENU_OBJECT FASTCALL
UserGetMenuObject(HMENU hMenu
)
62 EngSetLastError(ERROR_INVALID_MENU_HANDLE
);
66 Menu
= (PMENU_OBJECT
)UserGetObject(gHandleTable
, hMenu
, TYPE_MENU
);
69 EngSetLastError(ERROR_INVALID_MENU_HANDLE
);
79 DumpMenuItemList(PMENU_ITEM MenuItem
)
84 if(MenuItem
->Text
.Length
)
85 DbgPrint(" %d. %wZ\n", ++cnt
, &MenuItem
->Text
);
87 DbgPrint(" %d. NO TEXT dwTypeData==%d\n", ++cnt
, (DWORD
)MenuItem
->Text
.Buffer
);
89 if(MFT_BITMAP
& MenuItem
->fType
)
90 DbgPrint("MFT_BITMAP ");
91 if(MFT_MENUBARBREAK
& MenuItem
->fType
)
92 DbgPrint("MFT_MENUBARBREAK ");
93 if(MFT_MENUBREAK
& MenuItem
->fType
)
94 DbgPrint("MFT_MENUBREAK ");
95 if(MFT_OWNERDRAW
& MenuItem
->fType
)
96 DbgPrint("MFT_OWNERDRAW ");
97 if(MFT_RADIOCHECK
& MenuItem
->fType
)
98 DbgPrint("MFT_RADIOCHECK ");
99 if(MFT_RIGHTJUSTIFY
& MenuItem
->fType
)
100 DbgPrint("MFT_RIGHTJUSTIFY ");
101 if(MFT_SEPARATOR
& MenuItem
->fType
)
102 DbgPrint("MFT_SEPARATOR ");
103 if(MFT_STRING
& MenuItem
->fType
)
104 DbgPrint("MFT_STRING ");
105 DbgPrint("\n fState=");
106 if(MFS_DISABLED
& MenuItem
->fState
)
107 DbgPrint("MFS_DISABLED ");
109 DbgPrint("MFS_ENABLED ");
110 if(MFS_CHECKED
& MenuItem
->fState
)
111 DbgPrint("MFS_CHECKED ");
113 DbgPrint("MFS_UNCHECKED ");
114 if(MFS_HILITE
& MenuItem
->fState
)
115 DbgPrint("MFS_HILITE ");
117 DbgPrint("MFS_UNHILITE ");
118 if(MFS_DEFAULT
& MenuItem
->fState
)
119 DbgPrint("MFS_DEFAULT ");
120 if(MFS_GRAYED
& MenuItem
->fState
)
121 DbgPrint("MFS_GRAYED ");
122 DbgPrint("\n wId=%d\n", MenuItem
->wID
);
123 MenuItem
= MenuItem
->Next
;
125 DbgPrint("Entries: %d\n", cnt
);
130 PMENU_OBJECT FASTCALL
131 IntGetMenuObject(HMENU hMenu
)
133 PMENU_OBJECT Menu
= UserGetMenuObject(hMenu
);
135 Menu
->head
.cLockObj
++;
141 IntFreeMenuItem(PMENU_OBJECT Menu
, PMENU_ITEM MenuItem
, BOOL bRecurse
)
143 FreeMenuText(MenuItem
);
144 if(bRecurse
&& MenuItem
->hSubMenu
)
146 PMENU_OBJECT SubMenu
;
147 SubMenu
= UserGetMenuObject(MenuItem
->hSubMenu
);
150 IntDestroyMenuObject(SubMenu
, bRecurse
, TRUE
);
155 ExFreePoolWithTag(MenuItem
, TAG_MENUITEM
);
161 IntRemoveMenuItem(PMENU_OBJECT Menu
, UINT uPosition
, UINT uFlags
,
164 PMENU_ITEM PrevMenuItem
, MenuItem
;
165 if(IntGetMenuItemByFlag(Menu
, uPosition
, uFlags
, &Menu
, &MenuItem
,
171 PrevMenuItem
->Next
= MenuItem
->Next
;
174 Menu
->MenuItemList
= MenuItem
->Next
;
176 Menu
->MenuInfo
.MenuItemCount
--;
177 return IntFreeMenuItem(Menu
, MenuItem
, bRecurse
);
184 IntDeleteMenuItems(PMENU_OBJECT Menu
, BOOL bRecurse
)
188 PMENU_ITEM CurItem
= Menu
->MenuItemList
;
191 NextItem
= CurItem
->Next
;
192 IntFreeMenuItem(Menu
, CurItem
, bRecurse
);
196 Menu
->MenuInfo
.MenuItemCount
= 0;
197 Menu
->MenuItemList
= NULL
;
202 IntDestroyMenuObject(PMENU_OBJECT Menu
,
203 BOOL bRecurse
, BOOL RemoveFromProcess
)
208 PWINSTATION_OBJECT WindowStation
;
211 /* Remove all menu items */
212 IntDeleteMenuItems(Menu
, bRecurse
); /* Do not destroy submenus */
214 if(RemoveFromProcess
)
216 RemoveEntryList(&Menu
->ListEntry
);
219 Status
= ObReferenceObjectByHandle(Menu
->Process
->Win32WindowStation
,
221 ExWindowStationObjectType
,
223 (PVOID
*)&WindowStation
,
225 if(NT_SUCCESS(Status
))
228 if (Menu
->MenuInfo
.Wnd
)
230 Window
= UserGetWindowObject(Menu
->MenuInfo
.Wnd
);
236 // UserDereferenceObject(Menu);
237 ret
= UserDeleteObject(Menu
->MenuInfo
.Self
, TYPE_MENU
);
238 ObDereferenceObject(WindowStation
);
245 PMENU_OBJECT FASTCALL
246 IntCreateMenu(PHANDLE Handle
, BOOL IsMenuBar
)
249 PPROCESSINFO CurrentWin32Process
;
251 Menu
= (PMENU_OBJECT
)UserCreateObject( gHandleTable
,
256 sizeof(MENU_OBJECT
));
263 Menu
->Process
= PsGetCurrentProcess();
264 Menu
->RtoL
= FALSE
; /* Default */
265 Menu
->MenuInfo
.cbSize
= sizeof(MENUINFO
); /* Not used */
266 Menu
->MenuInfo
.fMask
= 0; /* Not used */
267 Menu
->MenuInfo
.dwStyle
= 0; /* FIXME */
268 Menu
->MenuInfo
.cyMax
= 0; /* Default */
269 Menu
->MenuInfo
.hbrBack
= NULL
; /* No brush */
270 Menu
->MenuInfo
.dwContextHelpID
= 0; /* Default */
271 Menu
->MenuInfo
.dwMenuData
= 0; /* Default */
272 Menu
->MenuInfo
.Self
= *Handle
;
273 Menu
->MenuInfo
.FocusedItem
= NO_SELECTED_ITEM
;
274 Menu
->MenuInfo
.Flags
= (IsMenuBar
? 0 : MF_POPUP
);
275 Menu
->MenuInfo
.Wnd
= NULL
;
276 Menu
->MenuInfo
.WndOwner
= NULL
;
277 Menu
->MenuInfo
.Height
= 0;
278 Menu
->MenuInfo
.Width
= 0;
279 Menu
->MenuInfo
.TimeToHide
= FALSE
;
281 Menu
->MenuInfo
.MenuItemCount
= 0;
282 Menu
->MenuItemList
= NULL
;
284 /* Insert menu item into process menu handle list */
285 CurrentWin32Process
= PsGetCurrentProcessWin32Process();
286 InsertTailList(&CurrentWin32Process
->MenuListHead
, &Menu
->ListEntry
);
292 IntCloneMenuItems(PMENU_OBJECT Destination
, PMENU_OBJECT Source
)
294 PMENU_ITEM MenuItem
, NewMenuItem
= NULL
;
295 PMENU_ITEM Old
= NULL
;
297 if(!Source
->MenuInfo
.MenuItemCount
)
300 MenuItem
= Source
->MenuItemList
;
305 NewMenuItem
->Next
= MenuItem
;
306 NewMenuItem
= ExAllocatePoolWithTag(PagedPool
, sizeof(MENU_ITEM
), TAG_MENUITEM
);
309 NewMenuItem
->fType
= MenuItem
->fType
;
310 NewMenuItem
->fState
= MenuItem
->fState
;
311 NewMenuItem
->wID
= MenuItem
->wID
;
312 NewMenuItem
->hSubMenu
= MenuItem
->hSubMenu
;
313 NewMenuItem
->hbmpChecked
= MenuItem
->hbmpChecked
;
314 NewMenuItem
->hbmpUnchecked
= MenuItem
->hbmpUnchecked
;
315 NewMenuItem
->dwItemData
= MenuItem
->dwItemData
;
316 if((MENU_ITEM_TYPE(NewMenuItem
->fType
) == MF_STRING
))
318 if(MenuItem
->Text
.Length
)
320 NewMenuItem
->Text
.Length
= 0;
321 NewMenuItem
->Text
.MaximumLength
= MenuItem
->Text
.MaximumLength
;
322 NewMenuItem
->Text
.Buffer
= (PWSTR
)ExAllocatePoolWithTag(PagedPool
, MenuItem
->Text
.MaximumLength
, TAG_STRING
);
323 if(!NewMenuItem
->Text
.Buffer
)
325 ExFreePoolWithTag(NewMenuItem
, TAG_MENUITEM
);
328 RtlCopyUnicodeString(&NewMenuItem
->Text
, &MenuItem
->Text
);
332 NewMenuItem
->Text
.Buffer
= MenuItem
->Text
.Buffer
;
337 NewMenuItem
->Text
.Buffer
= MenuItem
->Text
.Buffer
;
339 NewMenuItem
->hbmpItem
= MenuItem
->hbmpItem
;
341 NewMenuItem
->Next
= NULL
;
343 Old
->Next
= NewMenuItem
;
345 Destination
->MenuItemList
= NewMenuItem
;
346 Destination
->MenuInfo
.MenuItemCount
++;
347 MenuItem
= MenuItem
->Next
;
353 PMENU_OBJECT FASTCALL
354 IntCloneMenu(PMENU_OBJECT Source
)
356 PPROCESSINFO CurrentWin32Process
;
363 Menu
= (PMENU_OBJECT
)UserCreateObject( gHandleTable
,
368 sizeof(MENU_OBJECT
));
372 Menu
->Process
= PsGetCurrentProcess();
373 Menu
->RtoL
= Source
->RtoL
;
374 Menu
->MenuInfo
.cbSize
= sizeof(MENUINFO
); /* Not used */
375 Menu
->MenuInfo
.fMask
= Source
->MenuInfo
.fMask
;
376 Menu
->MenuInfo
.dwStyle
= Source
->MenuInfo
.dwStyle
;
377 Menu
->MenuInfo
.cyMax
= Source
->MenuInfo
.cyMax
;
378 Menu
->MenuInfo
.hbrBack
= Source
->MenuInfo
.hbrBack
;
379 Menu
->MenuInfo
.dwContextHelpID
= Source
->MenuInfo
.dwContextHelpID
;
380 Menu
->MenuInfo
.dwMenuData
= Source
->MenuInfo
.dwMenuData
;
381 Menu
->MenuInfo
.Self
= hMenu
;
382 Menu
->MenuInfo
.FocusedItem
= NO_SELECTED_ITEM
;
383 Menu
->MenuInfo
.Wnd
= NULL
;
384 Menu
->MenuInfo
.WndOwner
= NULL
;
385 Menu
->MenuInfo
.Height
= 0;
386 Menu
->MenuInfo
.Width
= 0;
387 Menu
->MenuInfo
.TimeToHide
= FALSE
;
389 Menu
->MenuInfo
.MenuItemCount
= 0;
390 Menu
->MenuItemList
= NULL
;
392 /* Insert menu item into process menu handle list */
393 CurrentWin32Process
= PsGetCurrentProcessWin32Process();
394 InsertTailList(&CurrentWin32Process
->MenuListHead
, &Menu
->ListEntry
);
396 IntCloneMenuItems(Menu
, Source
);
402 IntSetMenuFlagRtoL(PMENU_OBJECT Menu
)
409 IntSetMenuContextHelpId(PMENU_OBJECT Menu
, DWORD dwContextHelpId
)
411 Menu
->MenuInfo
.dwContextHelpID
= dwContextHelpId
;
416 IntGetMenuInfo(PMENU_OBJECT Menu
, PROSMENUINFO lpmi
)
418 if(lpmi
->fMask
& MIM_BACKGROUND
)
419 lpmi
->hbrBack
= Menu
->MenuInfo
.hbrBack
;
420 if(lpmi
->fMask
& MIM_HELPID
)
421 lpmi
->dwContextHelpID
= Menu
->MenuInfo
.dwContextHelpID
;
422 if(lpmi
->fMask
& MIM_MAXHEIGHT
)
423 lpmi
->cyMax
= Menu
->MenuInfo
.cyMax
;
424 if(lpmi
->fMask
& MIM_MENUDATA
)
425 lpmi
->dwMenuData
= Menu
->MenuInfo
.dwMenuData
;
426 if(lpmi
->fMask
& MIM_STYLE
)
427 lpmi
->dwStyle
= Menu
->MenuInfo
.dwStyle
;
428 if (sizeof(MENUINFO
) < lpmi
->cbSize
)
430 RtlCopyMemory((char *) lpmi
+ sizeof(MENUINFO
),
431 (char *) &Menu
->MenuInfo
+ sizeof(MENUINFO
),
432 lpmi
->cbSize
- sizeof(MENUINFO
));
434 if (sizeof(ROSMENUINFO
) == lpmi
->cbSize
)
436 lpmi
->maxBmpSize
.cx
= Menu
->MenuInfo
.maxBmpSize
.cx
;
437 lpmi
->maxBmpSize
.cy
= Menu
->MenuInfo
.maxBmpSize
.cy
;
443 IntSetMenuInfo(PMENU_OBJECT Menu
, PROSMENUINFO lpmi
)
445 if(lpmi
->fMask
& MIM_BACKGROUND
)
446 Menu
->MenuInfo
.hbrBack
= lpmi
->hbrBack
;
447 if(lpmi
->fMask
& MIM_HELPID
)
448 Menu
->MenuInfo
.dwContextHelpID
= lpmi
->dwContextHelpID
;
449 if(lpmi
->fMask
& MIM_MAXHEIGHT
)
450 Menu
->MenuInfo
.cyMax
= lpmi
->cyMax
;
451 if(lpmi
->fMask
& MIM_MENUDATA
)
452 Menu
->MenuInfo
.dwMenuData
= lpmi
->dwMenuData
;
453 if(lpmi
->fMask
& MIM_STYLE
)
454 Menu
->MenuInfo
.dwStyle
= lpmi
->dwStyle
;
455 if(lpmi
->fMask
& MIM_APPLYTOSUBMENUS
)
459 if (sizeof(MENUINFO
) < lpmi
->cbSize
)
461 Menu
->MenuInfo
.FocusedItem
= lpmi
->FocusedItem
;
462 Menu
->MenuInfo
.Height
= lpmi
->Height
;
463 Menu
->MenuInfo
.Width
= lpmi
->Width
;
464 Menu
->MenuInfo
.Wnd
= lpmi
->Wnd
;
465 Menu
->MenuInfo
.WndOwner
= lpmi
->WndOwner
;
466 Menu
->MenuInfo
.TimeToHide
= lpmi
->TimeToHide
;
468 if (sizeof(ROSMENUINFO
) == lpmi
->cbSize
)
470 Menu
->MenuInfo
.maxBmpSize
.cx
= lpmi
->maxBmpSize
.cx
;
471 Menu
->MenuInfo
.maxBmpSize
.cy
= lpmi
->maxBmpSize
.cy
;
478 IntGetMenuItemByFlag(PMENU_OBJECT Menu
, UINT uSearchBy
, UINT fFlag
,
479 PMENU_OBJECT
*SubMenu
, PMENU_ITEM
*MenuItem
,
480 PMENU_ITEM
*PrevMenuItem
)
482 PMENU_ITEM PrevItem
= NULL
;
483 PMENU_ITEM CurItem
= Menu
->MenuItemList
;
487 if(MF_BYPOSITION
& fFlag
)
490 while(CurItem
&& (p
> 0))
493 CurItem
= CurItem
->Next
;
501 *PrevMenuItem
= PrevItem
;
508 *PrevMenuItem
= NULL
; /* ? */
512 return uSearchBy
- p
;
519 if(CurItem
->wID
== uSearchBy
)
524 *PrevMenuItem
= PrevItem
;
532 if(CurItem
->fType
& MF_POPUP
)
534 PMENU_OBJECT NewMenu
= UserGetMenuObject(CurItem
->hSubMenu
);
537 ret
= IntGetMenuItemByFlag(NewMenu
, uSearchBy
, fFlag
,
538 SubMenu
, MenuItem
, PrevMenuItem
);
547 CurItem
= CurItem
->Next
;
556 IntInsertMenuItemToList(PMENU_OBJECT Menu
, PMENU_ITEM MenuItem
, int pos
)
559 PMENU_ITEM LastItem
= NULL
;
562 CurItem
= Menu
->MenuItemList
;
563 while(CurItem
&& (pos
!= 0))
566 CurItem
= CurItem
->Next
;
573 /* Insert the item after LastItem */
574 LastItem
->Next
= MenuItem
;
578 /* Insert at the beginning */
579 Menu
->MenuItemList
= MenuItem
;
581 MenuItem
->Next
= CurItem
;
582 Menu
->MenuInfo
.MenuItemCount
++;
588 IntGetMenuItemInfo(PMENU_OBJECT Menu
, /* UNUSED PARAM!! */
589 PMENU_ITEM MenuItem
, PROSMENUITEMINFO lpmii
)
593 if(lpmii
->fMask
& (MIIM_FTYPE
| MIIM_TYPE
))
595 lpmii
->fType
= MenuItem
->fType
;
597 if(lpmii
->fMask
& MIIM_BITMAP
)
599 lpmii
->hbmpItem
= MenuItem
->hbmpItem
;
601 if(lpmii
->fMask
& MIIM_CHECKMARKS
)
603 lpmii
->hbmpChecked
= MenuItem
->hbmpChecked
;
604 lpmii
->hbmpUnchecked
= MenuItem
->hbmpUnchecked
;
606 if(lpmii
->fMask
& MIIM_DATA
)
608 lpmii
->dwItemData
= MenuItem
->dwItemData
;
610 if(lpmii
->fMask
& MIIM_ID
)
612 lpmii
->wID
= MenuItem
->wID
;
614 if(lpmii
->fMask
& MIIM_STATE
)
616 lpmii
->fState
= MenuItem
->fState
;
618 if(lpmii
->fMask
& MIIM_SUBMENU
)
620 lpmii
->hSubMenu
= MenuItem
->hSubMenu
;
623 if ((lpmii
->fMask
& MIIM_STRING
) ||
624 ((lpmii
->fMask
& MIIM_TYPE
) && (MENU_ITEM_TYPE(lpmii
->fType
) == MF_STRING
)))
626 if (lpmii
->dwTypeData
== NULL
)
628 lpmii
->cch
= MenuItem
->Text
.Length
/ sizeof(WCHAR
);
632 Status
= MmCopyToCaller(lpmii
->dwTypeData
, MenuItem
->Text
.Buffer
,
633 min(lpmii
->cch
* sizeof(WCHAR
),
634 MenuItem
->Text
.MaximumLength
));
635 if (! NT_SUCCESS(Status
))
637 SetLastNtError(Status
);
643 if (sizeof(ROSMENUITEMINFO
) == lpmii
->cbSize
)
645 lpmii
->Rect
= MenuItem
->Rect
;
646 lpmii
->dxTab
= MenuItem
->dxTab
;
647 lpmii
->lpstr
= MenuItem
->Text
.Buffer
; // Use DesktopHeap!
654 IntSetMenuItemInfo(PMENU_OBJECT MenuObject
, PMENU_ITEM MenuItem
, PROSMENUITEMINFO lpmii
)
656 PMENU_OBJECT SubMenuObject
;
657 UINT fTypeMask
= (MFT_BITMAP
| MFT_MENUBARBREAK
| MFT_MENUBREAK
| MFT_OWNERDRAW
| MFT_RADIOCHECK
| MFT_RIGHTJUSTIFY
| MFT_SEPARATOR
| MF_POPUP
);
659 if(!MenuItem
|| !MenuObject
|| !lpmii
)
663 if (lpmii
->fType
& ~fTypeMask
)
665 ERR("IntSetMenuItemInfo invalid fType flags %x\n", lpmii
->fType
& ~fTypeMask
);
666 lpmii
->fMask
&= ~(MIIM_TYPE
| MIIM_FTYPE
);
668 if (lpmii
->fMask
& MIIM_TYPE
)
670 if (lpmii
->fMask
& ( MIIM_STRING
| MIIM_FTYPE
| MIIM_BITMAP
))
672 ERR("IntSetMenuItemInfo: Invalid combination of fMask bits used\n");
673 /* This does not happen on Win9x/ME */
674 SetLastNtError( ERROR_INVALID_PARAMETER
);
678 * Delete the menu item type when changing type from
681 if (MenuItem
->fType
!= lpmii
->fType
&&
682 MENU_ITEM_TYPE(MenuItem
->fType
) == MFT_STRING
)
684 FreeMenuText(MenuItem
);
685 RtlInitUnicodeString(&MenuItem
->Text
, NULL
);
687 if(lpmii
->fType
& MFT_BITMAP
)
690 MenuItem
->hbmpItem
= lpmii
->hbmpItem
;
692 { /* Win 9x/Me stuff */
693 MenuItem
->hbmpItem
= (HBITMAP
)((ULONG_PTR
)(LOWORD(lpmii
->dwTypeData
)));
696 MenuItem
->fType
|= lpmii
->fType
;
698 if (lpmii
->fMask
& MIIM_FTYPE
)
700 if(( lpmii
->fType
& MFT_BITMAP
))
702 ERR("IntSetMenuItemInfo: Can not use FTYPE and MFT_BITMAP.\n");
703 SetLastNtError( ERROR_INVALID_PARAMETER
);
706 MenuItem
->fType
|= lpmii
->fType
; /* Need to save all the flags, this fixed MFT_RIGHTJUSTIFY */
708 if(lpmii
->fMask
& MIIM_BITMAP
)
710 MenuItem
->hbmpItem
= lpmii
->hbmpItem
;
712 if(lpmii
->fMask
& MIIM_CHECKMARKS
)
714 MenuItem
->hbmpChecked
= lpmii
->hbmpChecked
;
715 MenuItem
->hbmpUnchecked
= lpmii
->hbmpUnchecked
;
717 if(lpmii
->fMask
& MIIM_DATA
)
719 MenuItem
->dwItemData
= lpmii
->dwItemData
;
721 if(lpmii
->fMask
& MIIM_ID
)
723 MenuItem
->wID
= lpmii
->wID
;
725 if(lpmii
->fMask
& MIIM_STATE
)
727 /* Remove MFS_DEFAULT flag from all other menu items if this item
728 has the MFS_DEFAULT state */
729 if(lpmii
->fState
& MFS_DEFAULT
)
730 UserSetMenuDefaultItem(MenuObject
, -1, 0);
731 /* Update the menu item state flags */
732 UpdateMenuItemState(MenuItem
->fState
, lpmii
->fState
);
735 if(lpmii
->fMask
& MIIM_SUBMENU
)
737 MenuItem
->hSubMenu
= lpmii
->hSubMenu
;
738 /* Make sure the submenu is marked as a popup menu */
739 if (MenuItem
->hSubMenu
)
741 SubMenuObject
= UserGetMenuObject(MenuItem
->hSubMenu
);
742 if (SubMenuObject
!= NULL
)
744 SubMenuObject
->MenuInfo
.Flags
|= MF_POPUP
;
745 MenuItem
->fType
|= MF_POPUP
;
749 MenuItem
->fType
&= ~MF_POPUP
;
754 MenuItem
->fType
&= ~MF_POPUP
;
758 if ((lpmii
->fMask
& MIIM_STRING
) ||
759 ((lpmii
->fMask
& MIIM_TYPE
) && (MENU_ITEM_TYPE(lpmii
->fType
) == MF_STRING
)))
761 FreeMenuText(MenuItem
);
763 if(lpmii
->dwTypeData
&& lpmii
->cch
)
765 UNICODE_STRING Source
;
768 Source
.MaximumLength
= lpmii
->cch
* sizeof(WCHAR
);
769 Source
.Buffer
= lpmii
->dwTypeData
;
771 MenuItem
->Text
.Buffer
= (PWSTR
)ExAllocatePoolWithTag(
772 PagedPool
, Source
.Length
+ sizeof(WCHAR
), TAG_STRING
);
773 if(MenuItem
->Text
.Buffer
!= NULL
)
775 MenuItem
->Text
.Length
= 0;
776 MenuItem
->Text
.MaximumLength
= Source
.Length
+ sizeof(WCHAR
);
777 RtlCopyUnicodeString(&MenuItem
->Text
, &Source
);
778 MenuItem
->Text
.Buffer
[MenuItem
->Text
.Length
/ sizeof(WCHAR
)] = 0;
782 RtlInitUnicodeString(&MenuItem
->Text
, NULL
);
787 if (0 == (MenuObject
->MenuInfo
.Flags
& MF_SYSMENU
))
789 MenuItem
->fType
|= MF_SEPARATOR
;
791 RtlInitUnicodeString(&MenuItem
->Text
, NULL
);
795 if (sizeof(ROSMENUITEMINFO
) == lpmii
->cbSize
)
797 MenuItem
->Rect
= lpmii
->Rect
;
798 MenuItem
->dxTab
= lpmii
->dxTab
;
799 lpmii
->lpstr
= MenuItem
->Text
.Buffer
; /* Use DesktopHeap! Send back new allocated string or zero */
807 _In_ PMENU_OBJECT MenuObject
,
810 PROSMENUITEMINFO ItemInfo
)
814 PMENU_OBJECT SubMenu
= NULL
;
816 NT_ASSERT(MenuObject
!= NULL
);
818 if (MAX_MENU_ITEMS
<= MenuObject
->MenuInfo
.MenuItemCount
)
820 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY
);
826 SubMenu
= MenuObject
;
827 /* calculate position */
829 if(uItem
> MenuObject
->MenuInfo
.MenuItemCount
)
831 pos
= MenuObject
->MenuInfo
.MenuItemCount
;
836 pos
= IntGetMenuItemByFlag(MenuObject
, uItem
, MF_BYCOMMAND
, &SubMenu
, NULL
, NULL
);
840 /* Default to last position of menu */
841 SubMenu
= MenuObject
;
842 pos
= MenuObject
->MenuInfo
.MenuItemCount
;
851 MenuItem
= ExAllocatePoolWithTag(PagedPool
, sizeof(MENU_ITEM
), TAG_MENUITEM
);
852 if (NULL
== MenuItem
)
854 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY
);
858 MenuItem
->fType
= MFT_STRING
;
859 MenuItem
->fState
= MFS_ENABLED
| MFS_UNCHECKED
;
861 MenuItem
->hSubMenu
= (HMENU
)0;
862 MenuItem
->hbmpChecked
= (HBITMAP
)0;
863 MenuItem
->hbmpUnchecked
= (HBITMAP
)0;
864 MenuItem
->dwItemData
= 0;
865 RtlInitUnicodeString(&MenuItem
->Text
, NULL
);
866 MenuItem
->hbmpItem
= (HBITMAP
)0;
868 if(!IntSetMenuItemInfo(SubMenu
, MenuItem
, ItemInfo
))
870 ExFreePoolWithTag(MenuItem
, TAG_MENUITEM
);
874 /* Force size recalculation! */
875 MenuObject
->MenuInfo
.Height
= 0;
877 pos
= IntInsertMenuItemToList(SubMenu
, MenuItem
, pos
);
879 TRACE("IntInsertMenuItemToList = %i\n", pos
);
885 IntEnableMenuItem(PMENU_OBJECT MenuObject
, UINT uIDEnableItem
, UINT uEnable
)
888 UINT res
= IntGetMenuItemByFlag(MenuObject
, uIDEnableItem
, uEnable
, NULL
, &MenuItem
, NULL
);
889 if(!MenuItem
|| (res
== (UINT
)-1))
894 res
= MenuItem
->fState
& (MF_GRAYED
| MF_DISABLED
);
896 if(uEnable
& MF_DISABLED
)
898 MenuItem
->fState
|= MF_DISABLED
;
899 MenuItem
->fState
|= uEnable
& MF_GRAYED
;
903 if(uEnable
& MF_GRAYED
)
905 MenuItem
->fState
|= (MF_GRAYED
| MF_DISABLED
);
909 MenuItem
->fState
&= ~(MF_DISABLED
| MF_GRAYED
);
918 IntBuildMenuItemList(PMENU_OBJECT MenuObject
, PVOID Buffer
, ULONG nMax
)
923 PMENU_ITEM CurItem
= MenuObject
->MenuItemList
;
930 if (nMax
< MenuObject
->MenuInfo
.MenuItemCount
* sizeof(ROSMENUITEMINFO
))
934 StrOut
= (PWCHAR
)((char *) Buffer
+ MenuObject
->MenuInfo
.MenuItemCount
935 * sizeof(ROSMENUITEMINFO
));
936 nMax
-= MenuObject
->MenuInfo
.MenuItemCount
* sizeof(ROSMENUITEMINFO
);
938 mii
.cbSize
= sizeof(ROSMENUITEMINFO
);
942 while (NULL
!= CurItem
)
944 mii
.cch
= CurItem
->Text
.Length
/ sizeof(WCHAR
);
945 mii
.dwItemData
= CurItem
->dwItemData
;
946 if (0 != CurItem
->Text
.Length
)
948 mii
.dwTypeData
= StrOut
;
952 mii
.dwTypeData
= NULL
;
954 mii
.fState
= CurItem
->fState
;
955 mii
.fType
= CurItem
->fType
;
956 mii
.wID
= CurItem
->wID
;
957 mii
.hbmpChecked
= CurItem
->hbmpChecked
;
958 mii
.hbmpItem
= CurItem
->hbmpItem
;
959 mii
.hbmpUnchecked
= CurItem
->hbmpUnchecked
;
960 mii
.hSubMenu
= CurItem
->hSubMenu
;
961 mii
.Rect
= CurItem
->Rect
;
962 mii
.dxTab
= CurItem
->dxTab
;
963 mii
.lpstr
= CurItem
->Text
.Buffer
; // Use DesktopHeap!
965 Status
= MmCopyToCaller(Buf
, &mii
, sizeof(ROSMENUITEMINFO
));
966 if (! NT_SUCCESS(Status
))
968 SetLastNtError(Status
);
971 Buf
= (PVOID
)((ULONG_PTR
)Buf
+ sizeof(ROSMENUITEMINFO
));
973 if (0 != CurItem
->Text
.Length
974 && (nMax
>= CurItem
->Text
.Length
+ sizeof(WCHAR
)))
977 Status
= MmCopyToCaller(StrOut
, CurItem
->Text
.Buffer
,
978 CurItem
->Text
.Length
);
979 if (! NT_SUCCESS(Status
))
981 SetLastNtError(Status
);
984 StrOut
+= CurItem
->Text
.Length
/ sizeof(WCHAR
);
985 Status
= MmCopyToCaller(StrOut
, &NulByte
, sizeof(WCHAR
));
986 if (! NT_SUCCESS(Status
))
988 SetLastNtError(Status
);
992 nMax
-= CurItem
->Text
.Length
+ sizeof(WCHAR
);
994 else if (0 != CurItem
->Text
.Length
)
999 CurItem
= CurItem
->Next
;
1005 while (NULL
!= CurItem
)
1007 res
+= sizeof(ROSMENUITEMINFO
) + CurItem
->Text
.Length
+ sizeof(WCHAR
);
1008 CurItem
= CurItem
->Next
;
1017 IntCheckMenuItem(PMENU_OBJECT MenuObject
, UINT uIDCheckItem
, UINT uCheck
)
1019 PMENU_ITEM MenuItem
;
1022 if((IntGetMenuItemByFlag(MenuObject
, uIDCheckItem
, uCheck
, NULL
, &MenuItem
, NULL
) < 0) || !MenuItem
)
1027 res
= (DWORD
)(MenuItem
->fState
& MF_CHECKED
);
1028 if(uCheck
& MF_CHECKED
)
1030 MenuItem
->fState
|= MF_CHECKED
;
1034 MenuItem
->fState
&= ~MF_CHECKED
;
1041 IntHiliteMenuItem(PWND WindowObject
, PMENU_OBJECT MenuObject
,
1042 UINT uItemHilite
, UINT uHilite
)
1044 PMENU_ITEM MenuItem
;
1045 BOOL res
= IntGetMenuItemByFlag(MenuObject
, uItemHilite
, uHilite
, NULL
, &MenuItem
, NULL
);
1046 if(!MenuItem
|| !res
)
1051 if(uHilite
& MF_HILITE
)
1053 MenuItem
->fState
|= MF_HILITE
;
1057 MenuItem
->fState
&= ~MF_HILITE
;
1060 /* FIXME: Update the window's menu */
1066 UserSetMenuDefaultItem(PMENU_OBJECT MenuObject
, UINT uItem
, UINT fByPos
)
1069 PMENU_ITEM MenuItem
= MenuObject
->MenuItemList
;
1071 if(uItem
== (UINT
)-1)
1075 MenuItem
->fState
&= ~MFS_DEFAULT
;
1076 MenuItem
= MenuItem
->Next
;
1088 MenuItem
->fState
|= MFS_DEFAULT
;
1093 MenuItem
->fState
&= ~MFS_DEFAULT
;
1096 MenuItem
= MenuItem
->Next
;
1103 if(!ret
&& (MenuItem
->wID
== uItem
))
1105 MenuItem
->fState
|= MFS_DEFAULT
;
1110 MenuItem
->fState
&= ~MFS_DEFAULT
;
1112 MenuItem
= MenuItem
->Next
;
1120 IntGetMenuDefaultItem(PMENU_OBJECT MenuObject
, UINT fByPos
, UINT gmdiFlags
,
1126 PMENU_OBJECT SubMenuObject
;
1127 PMENU_ITEM MenuItem
= MenuObject
->MenuItemList
;
1131 if(MenuItem
->fState
& MFS_DEFAULT
)
1134 if(!(gmdiFlags
& GMDI_USEDISABLED
) && (MenuItem
->fState
& MFS_DISABLED
))
1140 res
= MenuItem
->wID
;
1142 if((*gismc
< MAX_GOINTOSUBMENU
) && (gmdiFlags
& GMDI_GOINTOPOPUPS
) &&
1146 SubMenuObject
= UserGetMenuObject(MenuItem
->hSubMenu
);
1147 if(!SubMenuObject
|| (SubMenuObject
== MenuObject
))
1151 sres
= IntGetMenuDefaultItem(SubMenuObject
, fByPos
, gmdiFlags
, gismc
);
1161 MenuItem
= MenuItem
->Next
;
1169 co_IntInitTracking(PWND Window
, PMENU_OBJECT Menu
, BOOL Popup
,
1172 /* FIXME: Hide caret */
1174 if(!(Flags
& TPM_NONOTIFY
))
1175 co_IntSendMessage(Window
->head
.h
, WM_SETCURSOR
, (WPARAM
)Window
->head
.h
, HTCAPTION
);
1177 /* FIXME: Send WM_SETCURSOR message */
1179 if(!(Flags
& TPM_NONOTIFY
))
1180 co_IntSendMessage(Window
->head
.h
, WM_INITMENU
, (WPARAM
)Menu
->MenuInfo
.Self
, 0);
1184 co_IntExitTracking(PWND Window
, PMENU_OBJECT Menu
, BOOL Popup
,
1187 if(!(Flags
& TPM_NONOTIFY
))
1188 co_IntSendMessage(Window
->head
.h
, WM_EXITMENULOOP
, 0 /* FIXME */, 0);
1190 /* FIXME: Show caret again */
1194 IntTrackMenu(PMENU_OBJECT Menu
, PWND Window
, INT x
, INT y
,
1201 co_IntTrackPopupMenu(PMENU_OBJECT Menu
, PWND Window
,
1202 UINT Flags
, POINT
*Pos
, UINT MenuPos
, RECTL
*ExcludeRect
)
1204 co_IntInitTracking(Window
, Menu
, TRUE
, Flags
);
1206 co_IntExitTracking(Window
, Menu
, TRUE
, Flags
);
1212 * Internal function. Called when the process is destroyed to free the remaining menu handles.
1215 IntCleanupMenus(struct _EPROCESS
*Process
, PPROCESSINFO Win32Process
)
1217 PEPROCESS CurrentProcess
;
1218 PLIST_ENTRY LastHead
= NULL
;
1219 PMENU_OBJECT MenuObject
;
1221 CurrentProcess
= PsGetCurrentProcess();
1222 if (CurrentProcess
!= Process
)
1224 KeAttachProcess(&Process
->Pcb
);
1227 while (Win32Process
->MenuListHead
.Flink
!= &(Win32Process
->MenuListHead
) &&
1228 Win32Process
->MenuListHead
.Flink
!= LastHead
)
1230 LastHead
= Win32Process
->MenuListHead
.Flink
;
1231 MenuObject
= CONTAINING_RECORD(Win32Process
->MenuListHead
.Flink
, MENU_OBJECT
, ListEntry
);
1233 IntDestroyMenuObject(MenuObject
, FALSE
, TRUE
);
1236 if (CurrentProcess
!= Process
)
1244 intGetTitleBarInfo(PWND pWindowObject
, PTITLEBARINFO bti
)
1248 DWORD dwExStyle
= 0;
1249 BOOLEAN retValue
= TRUE
;
1251 if (bti
->cbSize
== sizeof(TITLEBARINFO
))
1253 RtlZeroMemory(&bti
->rgstate
[0],sizeof(DWORD
)*(CCHILDREN_TITLEBAR
+1));
1255 bti
->rgstate
[0] = STATE_SYSTEM_FOCUSABLE
;
1257 dwStyle
= pWindowObject
->style
;
1258 dwExStyle
= pWindowObject
->ExStyle
;
1260 bti
->rcTitleBar
.top
= 0;
1261 bti
->rcTitleBar
.left
= 0;
1262 bti
->rcTitleBar
.right
= pWindowObject
->rcWindow
.right
- pWindowObject
->rcWindow
.left
;
1263 bti
->rcTitleBar
.bottom
= pWindowObject
->rcWindow
.bottom
- pWindowObject
->rcWindow
.top
;
1265 /* Is it iconiced ? */
1266 if ((dwStyle
& WS_ICONIC
)!=WS_ICONIC
)
1268 /* Remove frame from rectangle */
1269 if (HAS_THICKFRAME( dwStyle
, dwExStyle
))
1271 /* FIXME: Note this value should exists in pWindowObject for UserGetSystemMetrics(SM_CXFRAME) and UserGetSystemMetrics(SM_CYFRAME) */
1272 RECTL_vInflateRect( &bti
->rcTitleBar
, -UserGetSystemMetrics(SM_CXFRAME
), -UserGetSystemMetrics(SM_CYFRAME
) );
1274 else if (HAS_DLGFRAME( dwStyle
, dwExStyle
))
1276 /* FIXME: Note this value should exists in pWindowObject for UserGetSystemMetrics(SM_CXDLGFRAME) and UserGetSystemMetrics(SM_CYDLGFRAME) */
1277 RECTL_vInflateRect( &bti
->rcTitleBar
, -UserGetSystemMetrics(SM_CXDLGFRAME
), -UserGetSystemMetrics(SM_CYDLGFRAME
));
1279 else if (HAS_THINFRAME( dwStyle
, dwExStyle
))
1281 /* FIXME: Note this value should exists in pWindowObject for UserGetSystemMetrics(SM_CXBORDER) and UserGetSystemMetrics(SM_CYBORDER) */
1282 RECTL_vInflateRect( &bti
->rcTitleBar
, -UserGetSystemMetrics(SM_CXBORDER
), -UserGetSystemMetrics(SM_CYBORDER
) );
1285 /* We have additional border information if the window
1286 * is a child (but not an MDI child) */
1287 if ( (dwStyle
& WS_CHILD
) &&
1288 ((dwExStyle
& WS_EX_MDICHILD
) == 0 ) )
1290 if (dwExStyle
& WS_EX_CLIENTEDGE
)
1292 /* FIXME: Note this value should exists in pWindowObject for UserGetSystemMetrics(SM_CXEDGE) and UserGetSystemMetrics(SM_CYEDGE) */
1293 RECTL_vInflateRect (&bti
->rcTitleBar
, -UserGetSystemMetrics(SM_CXEDGE
), -UserGetSystemMetrics(SM_CYEDGE
));
1296 if (dwExStyle
& WS_EX_STATICEDGE
)
1298 /* FIXME: Note this value should exists in pWindowObject for UserGetSystemMetrics(SM_CXBORDER) and UserGetSystemMetrics(SM_CYBORDER) */
1299 RECTL_vInflateRect (&bti
->rcTitleBar
, -UserGetSystemMetrics(SM_CXBORDER
), -UserGetSystemMetrics(SM_CYBORDER
));
1304 bti
->rcTitleBar
.top
+= pWindowObject
->rcWindow
.top
;
1305 bti
->rcTitleBar
.left
+= pWindowObject
->rcWindow
.left
;
1306 bti
->rcTitleBar
.right
+= pWindowObject
->rcWindow
.left
;
1308 bti
->rcTitleBar
.bottom
= bti
->rcTitleBar
.top
;
1309 if (dwExStyle
& WS_EX_TOOLWINDOW
)
1311 /* FIXME: Note this value should exists in pWindowObject for UserGetSystemMetrics(SM_CYSMCAPTION) */
1312 bti
->rcTitleBar
.bottom
+= UserGetSystemMetrics(SM_CYSMCAPTION
);
1316 /* FIXME: Note this value should exists in pWindowObject for UserGetSystemMetrics(SM_CYCAPTION) and UserGetSystemMetrics(SM_CXSIZE) */
1317 bti
->rcTitleBar
.bottom
+= UserGetSystemMetrics(SM_CYCAPTION
);
1318 bti
->rcTitleBar
.left
+= UserGetSystemMetrics(SM_CXSIZE
);
1321 if (dwStyle
& WS_CAPTION
)
1323 bti
->rgstate
[1] = STATE_SYSTEM_INVISIBLE
;
1324 if (dwStyle
& WS_SYSMENU
)
1326 if (!(dwStyle
& (WS_MINIMIZEBOX
|WS_MAXIMIZEBOX
)))
1328 bti
->rgstate
[2] = STATE_SYSTEM_INVISIBLE
;
1329 bti
->rgstate
[3] = STATE_SYSTEM_INVISIBLE
;
1333 if (!(dwStyle
& WS_MINIMIZEBOX
))
1335 bti
->rgstate
[2] = STATE_SYSTEM_UNAVAILABLE
;
1337 if (!(dwStyle
& WS_MAXIMIZEBOX
))
1339 bti
->rgstate
[3] = STATE_SYSTEM_UNAVAILABLE
;
1343 if (!(dwExStyle
& WS_EX_CONTEXTHELP
))
1345 bti
->rgstate
[4] = STATE_SYSTEM_INVISIBLE
;
1347 if (pWindowObject
->pcls
->style
& CS_NOCLOSE
)
1349 bti
->rgstate
[5] = STATE_SYSTEM_UNAVAILABLE
;
1354 bti
->rgstate
[2] = STATE_SYSTEM_INVISIBLE
;
1355 bti
->rgstate
[3] = STATE_SYSTEM_INVISIBLE
;
1356 bti
->rgstate
[4] = STATE_SYSTEM_INVISIBLE
;
1357 bti
->rgstate
[5] = STATE_SYSTEM_INVISIBLE
;
1362 bti
->rgstate
[0] |= STATE_SYSTEM_INVISIBLE
;
1367 EngSetLastError(ERROR_INVALID_PARAMETER
);
1379 LPCMENUITEMINFOW UnsafeItemInfo
)
1382 ROSMENUITEMINFO ItemInfo
;
1384 /* Try to copy the whole MENUITEMINFOW structure */
1385 Status
= MmCopyFromCaller(&ItemInfo
, UnsafeItemInfo
, sizeof(MENUITEMINFOW
));
1386 if (NT_SUCCESS(Status
))
1388 if (sizeof(MENUITEMINFOW
) != ItemInfo
.cbSize
1389 && FIELD_OFFSET(MENUITEMINFOW
, hbmpItem
) != ItemInfo
.cbSize
)
1391 EngSetLastError(ERROR_INVALID_PARAMETER
);
1394 return IntInsertMenuItem(Menu
, uItem
, fByPosition
, &ItemInfo
);
1397 /* Try to copy without last field (not present in older versions) */
1398 Status
= MmCopyFromCaller(&ItemInfo
, UnsafeItemInfo
, FIELD_OFFSET(MENUITEMINFOW
, hbmpItem
));
1399 if (NT_SUCCESS(Status
))
1401 if (FIELD_OFFSET(MENUITEMINFOW
, hbmpItem
) != ItemInfo
.cbSize
)
1403 EngSetLastError(ERROR_INVALID_PARAMETER
);
1406 ItemInfo
.hbmpItem
= (HBITMAP
)0;
1407 return IntInsertMenuItem(Menu
, uItem
, fByPosition
, &ItemInfo
);
1410 SetLastNtError(Status
);
1414 UINT FASTCALL
IntGetMenuState( HMENU hMenu
, UINT uId
, UINT uFlags
)
1416 PMENU_OBJECT MenuObject
, SubMenu
;
1419 if (!(MenuObject
= UserGetMenuObject(hMenu
)))
1424 if (IntGetMenuItemByFlag(MenuObject
, uId
, uFlags
, &SubMenu
, &mi
, NULL
))
1430 UINT nSubItems
= SubMenu
->MenuInfo
.MenuItemCount
;
1431 return (nSubItems
<< 8) | ((mi
->fState
| mi
->fType
) & 0xff);
1436 return (mi
->fType
| mi
->fState
);
1441 HMENU FASTCALL
IntGetSubMenu( HMENU hMenu
, int nPos
)
1443 PMENU_OBJECT MenuObject
, SubMenu
;
1445 if (!(MenuObject
= UserGetMenuObject(hMenu
)))
1449 if (IntGetMenuItemByFlag(MenuObject
, nPos
, MF_BYPOSITION
, &SubMenu
, NULL
, NULL
))
1451 return SubMenu
? UserHMGetHandle(SubMenu
) : NULL
;
1456 UINT FASTCALL
IntFindSubMenu(HMENU
*hMenu
, HMENU hSubTarget
)
1458 PMENU_OBJECT MenuObject
;
1462 if ( (*hMenu
) == (HMENU
)0xffff || !(MenuObject
= UserGetMenuObject(*hMenu
)) )
1463 return NO_SELECTED_ITEM
;
1465 for (i
= 0; i
< MenuObject
->MenuInfo
.MenuItemCount
; i
++)
1467 if (!IntGetMenuItemByFlag(MenuObject
, i
, MF_BYPOSITION
, NULL
, &mi
, NULL
))
1469 return NO_SELECTED_ITEM
;
1472 if (!(mi
->fType
& MF_POPUP
)) continue;
1474 if (mi
->hSubMenu
== hSubTarget
)
1480 HMENU hsubmenu
= mi
->hSubMenu
;
1481 UINT pos
= IntFindSubMenu(&hsubmenu
, hSubTarget
);
1482 if (pos
!= NO_SELECTED_ITEM
)
1489 return NO_SELECTED_ITEM
;
1492 /* FUNCTIONS *****************************************************************/
1498 NtUserCheckMenuItem(
1504 DECLARE_RETURN(DWORD
);
1506 TRACE("Enter NtUserCheckMenuItem\n");
1507 UserEnterExclusive();
1509 if(!(Menu
= UserGetMenuObject(hMenu
)))
1514 RETURN( IntCheckMenuItem(Menu
, uIDCheckItem
, uCheck
));
1517 TRACE("Leave NtUserCheckMenuItem, ret=%i\n",_ret_
);
1522 HMENU FASTCALL
UserCreateMenu(BOOL PopupMenu
)
1524 PWINSTATION_OBJECT WinStaObject
;
1528 PEPROCESS CurrentProcess
= PsGetCurrentProcess();
1530 if (CsrProcess
!= CurrentProcess
)
1533 * CsrProcess does not have a Win32WindowStation
1537 Status
= IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation
,
1542 if (!NT_SUCCESS(Status
))
1544 ERR("Validation of window station handle (0x%X) failed\n",
1545 CurrentProcess
->Win32WindowStation
);
1546 SetLastNtError(Status
);
1549 Menu
= IntCreateMenu(&Handle
, !PopupMenu
);
1550 ObDereferenceObject(WinStaObject
);
1554 Menu
= IntCreateMenu(&Handle
, !PopupMenu
);
1557 if (Menu
) UserDereferenceObject(Menu
);
1558 return (HMENU
)Handle
;
1571 DECLARE_RETURN(BOOL
);
1573 TRACE("Enter NtUserDeleteMenu\n");
1574 UserEnterExclusive();
1576 if(!(Menu
= UserGetMenuObject(hMenu
)))
1581 RETURN( IntRemoveMenuItem(Menu
, uPosition
, uFlags
, TRUE
));
1584 TRACE("Leave NtUserDeleteMenu, ret=%i\n",_ret_
);
1593 NtUserGetTitleBarInfo(
1598 TITLEBARINFO bartitleinfo
;
1599 DECLARE_RETURN(BOOLEAN
);
1600 BOOLEAN retValue
= TRUE
;
1602 TRACE("Enter NtUserGetTitleBarInfo\n");
1603 UserEnterExclusive();
1605 /* Vaildate the windows handle */
1606 if (!(WindowObject
= UserGetWindowObject(hwnd
)))
1608 EngSetLastError(ERROR_INVALID_WINDOW_HANDLE
);
1614 /* Copy our usermode buffer bti to local buffer bartitleinfo */
1615 ProbeForRead(bti
, sizeof(TITLEBARINFO
), 1);
1616 RtlCopyMemory(&bartitleinfo
, bti
, sizeof(TITLEBARINFO
));
1618 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1620 /* Fail copy the data */
1621 EngSetLastError(ERROR_INVALID_PARAMETER
);
1626 /* Get the tile bar info */
1629 retValue
= intGetTitleBarInfo(WindowObject
, &bartitleinfo
);
1634 /* Copy our buffer to user mode buffer bti */
1635 ProbeForWrite(bti
, sizeof(TITLEBARINFO
), 1);
1636 RtlCopyMemory(bti
, &bartitleinfo
, sizeof(TITLEBARINFO
));
1638 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1640 /* Fail copy the data */
1641 EngSetLastError(ERROR_INVALID_PARAMETER
);
1651 TRACE("Leave NtUserGetTitleBarInfo, ret=%i\n",_ret_
);
1659 BOOL FASTCALL
UserDestroyMenu(HMENU hMenu
)
1663 if(!(Menu
= UserGetMenuObject(hMenu
)))
1668 if(Menu
->Process
!= PsGetCurrentProcess())
1670 EngSetLastError(ERROR_ACCESS_DENIED
);
1674 return IntDestroyMenuObject(Menu
, FALSE
, TRUE
);
1685 DECLARE_RETURN(BOOL
);
1687 TRACE("Enter NtUserDestroyMenu\n");
1688 UserEnterExclusive();
1690 if(!(Menu
= UserGetMenuObject(hMenu
)))
1695 if(Menu
->Process
!= PsGetCurrentProcess())
1697 EngSetLastError(ERROR_ACCESS_DENIED
);
1701 RETURN( IntDestroyMenuObject(Menu
, TRUE
, TRUE
));
1704 TRACE("Leave NtUserDestroyMenu, ret=%i\n",_ret_
);
1713 NtUserEnableMenuItem(
1719 DECLARE_RETURN(UINT
);
1721 TRACE("Enter NtUserEnableMenuItem\n");
1722 UserEnterExclusive();
1724 if(!(Menu
= UserGetMenuObject(hMenu
)))
1729 RETURN( IntEnableMenuItem(Menu
, uIDEnableItem
, uEnable
));
1732 TRACE("Leave NtUserEnableMenuItem, ret=%i\n",_ret_
);
1741 NtUserGetMenuBarInfo(
1748 PMENU_OBJECT MenuObject
;
1755 DECLARE_RETURN(BOOL
);
1757 TRACE("Enter NtUserGetMenuBarInfo\n");
1760 if (!(WindowObject
= UserGetWindowObject(hwnd
)))
1762 EngSetLastError(ERROR_INVALID_WINDOW_HANDLE
);
1766 hMenu
= (HMENU
)(DWORD_PTR
)WindowObject
->IDMenu
;
1768 if (!(MenuObject
= UserGetMenuObject(hMenu
)))
1770 EngSetLastError(ERROR_INVALID_MENU_HANDLE
);
1774 if (pmbi
->cbSize
!= sizeof(MENUBARINFO
))
1776 EngSetLastError(ERROR_INVALID_PARAMETER
);
1780 kmbi
.cbSize
= sizeof(MENUBARINFO
);
1781 kmbi
.fBarFocused
= FALSE
;
1782 kmbi
.fFocused
= FALSE
;
1783 kmbi
.hwndMenu
= NULL
;
1789 PMENU_OBJECT SubMenuObject
;
1791 if (idItem
) /* Non-Zero-Based. */
1793 if (IntGetMenuItemByFlag(MenuObject
, idItem
-1, MF_BYPOSITION
, NULL
, &mi
, NULL
) > -1)
1794 kmbi
.rcBar
= mi
->Rect
;
1803 /* If items is zero we assume info for the menu itself. */
1804 if (!(IntGetClientOrigin(WindowObject
, &Offset
)))
1809 Rect
.left
= Offset
.x
;
1810 Rect
.right
= Offset
.x
+ MenuObject
->MenuInfo
.Width
;
1811 Rect
.bottom
= Offset
.y
;
1812 Rect
.top
= Offset
.y
- MenuObject
->MenuInfo
.Height
;
1814 TRACE("Rect top = %d bottom = %d left = %d right = %d \n",
1815 Rect
.top
, Rect
.bottom
, Rect
.left
, Rect
.right
);
1819 if (idItem
-1 == MenuObject
->MenuInfo
.FocusedItem
)
1820 kmbi
.fFocused
= TRUE
;
1822 if (MenuObject
->MenuInfo
.FocusedItem
!= NO_SELECTED_ITEM
)
1823 kmbi
.fBarFocused
= TRUE
;
1825 if (MenuObject
->MenuItemList
)
1827 SubMenuObject
= UserGetMenuObject(MenuObject
->MenuItemList
->hSubMenu
);
1828 if(SubMenuObject
) kmbi
.hwndMenu
= SubMenuObject
->MenuInfo
.Wnd
;
1830 TRACE("OBJID_MENU, idItem = %d\n",idItem
);
1835 PMENU_OBJECT SubMenuObject
, XSubMenuObject
;
1837 // Windows does this! Wine checks for Atom and uses GetWindowLongPtrW.
1838 hMenuChk
= (HMENU
)co_IntSendMessage(hwnd
, MN_GETHMENU
, 0, 0);
1840 if (!(MenuObject
= UserGetMenuObject(hMenuChk
)))
1842 ERR("Window does not have a Popup Menu!\n");
1843 EngSetLastError(ERROR_INVALID_MENU_HANDLE
);
1847 SubMenuObject
= UserGetMenuObject(MenuObject
->MenuItemList
->hSubMenu
);
1848 if(SubMenuObject
) kmbi
.hMenu
= SubMenuObject
->MenuInfo
.Self
;
1852 ERR("OBJID_CLIENT, No SubMenu!\n");
1857 if (IntGetMenuItemByFlag(SubMenuObject
, idItem
-1, MF_BYPOSITION
, NULL
, &mi
, NULL
) > -1)
1858 kmbi
.rcBar
= mi
->Rect
;
1868 if (!(SubWinObj
= UserGetWindowObject(SubMenuObject
->MenuInfo
.Wnd
)))
1873 if (!(IntGetClientOrigin(SubWinObj
, &Offset
)))
1878 Rect
.left
= Offset
.x
;
1879 Rect
.right
= Offset
.x
+ SubMenuObject
->MenuInfo
.Width
;
1880 Rect
.top
= Offset
.y
;
1881 Rect
.bottom
= Offset
.y
+ SubMenuObject
->MenuInfo
.Height
;
1886 if (idItem
-1 == SubMenuObject
->MenuInfo
.FocusedItem
)
1887 kmbi
.fFocused
= TRUE
;
1889 if (SubMenuObject
->MenuInfo
.FocusedItem
!= NO_SELECTED_ITEM
)
1890 kmbi
.fBarFocused
= TRUE
;
1891 XSubMenuObject
= UserGetMenuObject(SubMenuObject
->MenuItemList
->hSubMenu
);
1892 if (XSubMenuObject
) kmbi
.hwndMenu
= XSubMenuObject
->MenuInfo
.Wnd
;
1893 TRACE("OBJID_CLIENT, idItem = %d\n",idItem
);
1898 PMENU_OBJECT SysMenuObject
, SubMenuObject
;
1899 if(!(SysMenuObject
= IntGetSystemMenu(WindowObject
, FALSE
, FALSE
)))
1904 kmbi
.hMenu
= SysMenuObject
->MenuInfo
.Self
;
1907 if (IntGetMenuItemByFlag(SysMenuObject
, idItem
-1, MF_BYPOSITION
, NULL
, &mi
, NULL
) > -1)
1908 kmbi
.rcBar
= mi
->Rect
;
1918 if (!(SysWinObj
= UserGetWindowObject(SysMenuObject
->MenuInfo
.Wnd
)))
1923 if (!(IntGetClientOrigin(SysWinObj
, &Offset
)))
1928 Rect
.left
= Offset
.x
;
1929 Rect
.right
= Offset
.x
+ SysMenuObject
->MenuInfo
.Width
;
1930 Rect
.top
= Offset
.y
;
1931 Rect
.bottom
= Offset
.y
+ SysMenuObject
->MenuInfo
.Height
;
1936 if (idItem
-1 == SysMenuObject
->MenuInfo
.FocusedItem
)
1937 kmbi
.fFocused
= TRUE
;
1939 if (SysMenuObject
->MenuInfo
.FocusedItem
!= NO_SELECTED_ITEM
)
1940 kmbi
.fBarFocused
= TRUE
;
1941 SubMenuObject
= UserGetMenuObject(SysMenuObject
->MenuItemList
->hSubMenu
);
1942 if(SubMenuObject
) kmbi
.hwndMenu
= SubMenuObject
->MenuInfo
.Wnd
;
1943 TRACE("OBJID_SYSMENU, idItem = %d\n",idItem
);
1948 ERR("Unknown idObject = %d, idItem = %d\n",idObject
,idItem
);
1952 NTSTATUS Status
= MmCopyToCaller(pmbi
, &kmbi
, sizeof(MENUBARINFO
));
1953 if (! NT_SUCCESS(Status
))
1955 SetLastNtError(Status
);
1962 TRACE("Leave NtUserGetMenuBarInfo, ret=%i\n",_ret_
);
1975 PMENU_OBJECT Menu
, SubMenu
;
1976 PMENU_ITEM MenuItem
;
1977 DECLARE_RETURN(UINT
);
1979 TRACE("Enter NtUserGetMenuIndex\n");
1982 if ( !(Menu
= UserGetMenuObject(hMenu
)) ||
1983 !(SubMenu
= UserGetMenuObject(hSubMenu
)) )
1986 MenuItem
= Menu
->MenuItemList
;
1989 if (MenuItem
->hSubMenu
== hSubMenu
)
1990 RETURN(MenuItem
->wID
);
1991 MenuItem
= MenuItem
->Next
;
1997 TRACE("Leave NtUserGetMenuIndex, ret=%i\n",_ret_
);
2006 NtUserGetMenuItemRect(
2017 PMENU_ITEM MenuItem
;
2018 DECLARE_RETURN(BOOL
);
2020 TRACE("Enter NtUserGetMenuItemRect\n");
2023 if (!(Menu
= UserGetMenuObject(hMenu
)))
2028 if (IntGetMenuItemByFlag(Menu
, uItem
, MF_BYPOSITION
, NULL
, &MenuItem
, NULL
) > -1)
2029 Rect
= MenuItem
->Rect
;
2035 hWnd
= Menu
->MenuInfo
.Wnd
;
2038 if (lprcItem
== NULL
) RETURN( FALSE
);
2040 if (!(ReferenceWnd
= UserGetWindowObject(hWnd
))) RETURN( FALSE
);
2042 if(MenuItem
->fType
& MF_POPUP
)
2044 XMove
= ReferenceWnd
->rcClient
.left
;
2045 YMove
= ReferenceWnd
->rcClient
.top
;
2049 XMove
= ReferenceWnd
->rcWindow
.left
;
2050 YMove
= ReferenceWnd
->rcWindow
.top
;
2055 Rect
.right
+= XMove
;
2056 Rect
.bottom
+= YMove
;
2058 Status
= MmCopyToCaller(lprcItem
, &Rect
, sizeof(RECT
));
2059 if (! NT_SUCCESS(Status
))
2061 SetLastNtError(Status
);
2067 TRACE("Leave NtUserGetMenuItemRect, ret=%i\n",_ret_
);
2076 NtUserHiliteMenuItem(
2084 DECLARE_RETURN(BOOLEAN
);
2086 TRACE("Enter NtUserHiliteMenuItem\n");
2087 UserEnterExclusive();
2089 if(!(Window
= UserGetWindowObject(hWnd
)))
2091 EngSetLastError(ERROR_INVALID_WINDOW_HANDLE
);
2095 if(!(Menu
= UserGetMenuObject(hMenu
)))
2097 EngSetLastError(ERROR_INVALID_MENU_HANDLE
);
2101 if(Window
->IDMenu
== (UINT
)(UINT_PTR
)hMenu
)
2103 RETURN( IntHiliteMenuItem(Window
, Menu
, uItemHilite
, uHilite
));
2109 TRACE("Leave NtUserHiliteMenuItem, ret=%i\n",_ret_
);
2118 PROSMENUINFO UnsafeMenuInfo
,
2124 ROSMENUINFO MenuInfo
;
2126 Status
= MmCopyFromCaller(&Size
, &UnsafeMenuInfo
->cbSize
, sizeof(DWORD
));
2127 if (! NT_SUCCESS(Status
))
2129 SetLastNtError(Status
);
2132 if(Size
< sizeof(MENUINFO
) || sizeof(ROSMENUINFO
) < Size
)
2134 EngSetLastError(ERROR_INVALID_PARAMETER
);
2137 Status
= MmCopyFromCaller(&MenuInfo
, UnsafeMenuInfo
, Size
);
2138 if (! NT_SUCCESS(Status
))
2140 SetLastNtError(Status
);
2147 Res
= IntSetMenuInfo(Menu
, &MenuInfo
);
2152 Res
= IntGetMenuInfo(Menu
, &MenuInfo
);
2155 Status
= MmCopyToCaller(UnsafeMenuInfo
, &MenuInfo
, Size
);
2156 if (! NT_SUCCESS(Status
))
2158 SetLastNtError(Status
);
2171 NtUserMenuItemFromPoint(
2181 DECLARE_RETURN(int);
2183 TRACE("Enter NtUserMenuItemFromPoint\n");
2184 UserEnterExclusive();
2186 if (!(Menu
= UserGetMenuObject(hMenu
)))
2191 if (!(Window
= UserGetWindowObject(Menu
->MenuInfo
.Wnd
)))
2196 X
-= Window
->rcWindow
.left
;
2197 Y
-= Window
->rcWindow
.top
;
2199 mi
= Menu
->MenuItemList
;
2200 for (i
= 0; NULL
!= mi
; i
++)
2202 if (RECTL_bPointInRect(&(mi
->Rect
), X
, Y
))
2209 RETURN( (mi
? i
: NO_SELECTED_ITEM
));
2212 TRACE("Leave NtUserMenuItemFromPoint, ret=%i\n",_ret_
);
2223 PROSMENUITEMINFO UnsafeItemInfo
,
2226 PMENU_ITEM MenuItem
;
2227 ROSMENUITEMINFO ItemInfo
;
2232 Status
= MmCopyFromCaller(&Size
, &UnsafeItemInfo
->cbSize
, sizeof(UINT
));
2233 if (! NT_SUCCESS(Status
))
2235 SetLastNtError(Status
);
2238 if (sizeof(MENUITEMINFOW
) != Size
2239 && FIELD_OFFSET(MENUITEMINFOW
, hbmpItem
) != Size
2240 && sizeof(ROSMENUITEMINFO
) != Size
)
2242 EngSetLastError(ERROR_INVALID_PARAMETER
);
2245 Status
= MmCopyFromCaller(&ItemInfo
, UnsafeItemInfo
, Size
);
2246 if (! NT_SUCCESS(Status
))
2248 SetLastNtError(Status
);
2251 /* If this is a pre-0x0500 _WIN32_WINNT MENUITEMINFOW, you can't
2253 if (FIELD_OFFSET(MENUITEMINFOW
, hbmpItem
) == Size
2254 && 0 != (ItemInfo
.fMask
& MIIM_BITMAP
))
2256 EngSetLastError(ERROR_INVALID_PARAMETER
);
2260 if (IntGetMenuItemByFlag(Menu
, Item
,
2261 (ByPosition
? MF_BYPOSITION
: MF_BYCOMMAND
),
2262 NULL
, &MenuItem
, NULL
) < 0)
2264 EngSetLastError(ERROR_INVALID_PARAMETER
);
2265 // This will crash menu (line 80) correct_behavior test!
2266 // "NT4 and below can't handle a bigger MENUITEMINFO struct"
2267 //EngSetLastError(ERROR_MENU_ITEM_NOT_FOUND);
2273 Ret
= IntSetMenuItemInfo(Menu
, MenuItem
, &ItemInfo
);
2277 Ret
= IntGetMenuItemInfo(Menu
, MenuItem
, &ItemInfo
);
2280 Status
= MmCopyToCaller(UnsafeItemInfo
, &ItemInfo
, Size
);
2281 if (! NT_SUCCESS(Status
))
2283 SetLastNtError(Status
);
2302 DECLARE_RETURN(BOOL
);
2304 TRACE("Enter NtUserRemoveMenu\n");
2305 UserEnterExclusive();
2307 if(!(Menu
= UserGetMenuObject(hMenu
)))
2312 RETURN(IntRemoveMenuItem(Menu
, uPosition
, uFlags
, FALSE
));
2315 TRACE("Leave NtUserRemoveMenu, ret=%i\n",_ret_
);
2325 NtUserSetMenuContextHelpId(
2327 DWORD dwContextHelpId
)
2330 DECLARE_RETURN(BOOL
);
2332 TRACE("Enter NtUserSetMenuContextHelpId\n");
2333 UserEnterExclusive();
2335 if(!(Menu
= UserGetMenuObject(hMenu
)))
2340 RETURN(IntSetMenuContextHelpId(Menu
, dwContextHelpId
));
2343 TRACE("Leave NtUserSetMenuContextHelpId, ret=%i\n",_ret_
);
2352 NtUserSetMenuDefaultItem(
2358 DECLARE_RETURN(BOOL
);
2360 TRACE("Enter NtUserSetMenuDefaultItem\n");
2361 UserEnterExclusive();
2363 if(!(Menu
= UserGetMenuObject(hMenu
)))
2368 RETURN( UserSetMenuDefaultItem(Menu
, uItem
, fByPos
));
2371 TRACE("Leave NtUserSetMenuDefaultItem, ret=%i\n",_ret_
);
2380 NtUserSetMenuFlagRtoL(
2384 DECLARE_RETURN(BOOL
);
2386 TRACE("Enter NtUserSetMenuFlagRtoL\n");
2387 UserEnterExclusive();
2389 if(!(Menu
= UserGetMenuObject(hMenu
)))
2394 RETURN(IntSetMenuFlagRtoL(Menu
));
2397 TRACE("Leave NtUserSetMenuFlagRtoL, ret=%i\n",_ret_
);
2406 NtUserThunkedMenuInfo(
2411 DECLARE_RETURN(BOOL
);
2413 TRACE("Enter NtUserThunkedMenuInfo\n");
2414 UserEnterExclusive();
2416 if (!(Menu
= UserGetMenuObject(hMenu
)))
2421 RETURN(UserMenuInfo(Menu
, (PROSMENUINFO
)lpcmi
, TRUE
));
2424 TRACE("Leave NtUserThunkedMenuInfo, ret=%i\n",_ret_
);
2433 NtUserThunkedMenuItemInfo(
2438 LPMENUITEMINFOW lpmii
,
2439 PUNICODE_STRING lpszCaption
)
2443 UNICODE_STRING lstrCaption
;
2444 DECLARE_RETURN(BOOL
);
2446 TRACE("Enter NtUserThunkedMenuItemInfo\n");
2447 UserEnterExclusive();
2449 /* lpszCaption may be NULL, check for it and call RtlInitUnicodeString()
2450 if bInsert == TRUE call UserInsertMenuItem() else UserSetMenuItemInfo() */
2452 if (!(Menu
= UserGetMenuObject(hMenu
)))
2457 lstrCaption
.Buffer
= NULL
;
2459 /* Check if we got a Caption */
2462 /* Copy the string to kernel mode */
2463 Status
= ProbeAndCaptureUnicodeString( &lstrCaption
,
2466 if (!NT_SUCCESS(Status
))
2468 ERR("Failed to capture MenuItem Caption (status 0x%08x)\n",Status
);
2469 SetLastNtError(Status
);
2474 if (bInsert
) RETURN( UserInsertMenuItem(Menu
, uItem
, fByPosition
, lpmii
));
2476 RETURN( UserMenuItemInfo(Menu
, uItem
, fByPosition
, (PROSMENUITEMINFO
)lpmii
, TRUE
));
2479 TRACE("Leave NtUserThunkedMenuItemInfo, ret=%i\n",_ret_
);
2484 ////// ReactOS NtUserBad
2490 NtUserBuildMenuItemList(
2498 DECLARE_RETURN(DWORD
);
2500 TRACE("Enter NtUserBuildMenuItemList\n");
2501 UserEnterExclusive();
2503 if(!(Menu
= UserGetMenuObject(hMenu
)))
2510 res
= IntBuildMenuItemList(Menu
, Buffer
, nBufSize
);
2514 res
= Menu
->MenuInfo
.MenuItemCount
;
2520 TRACE("Leave NtUserBuildMenuItemList, ret=%i\n",_ret_
);
2529 NtUserGetMenuDefaultItem(
2536 DECLARE_RETURN(UINT
);
2538 TRACE("Enter NtUserGetMenuDefaultItem\n");
2539 UserEnterExclusive();
2541 if(!(Menu
= UserGetMenuObject(hMenu
)))
2546 RETURN( IntGetMenuDefaultItem(Menu
, fByPos
, gmdiFlags
, &gismc
));
2549 TRACE("Leave NtUserGetMenuDefaultItem, ret=%i\n",_ret_
);
2561 PROSMENUINFO UnsafeMenuInfo
,
2565 DECLARE_RETURN(BOOL
);
2567 TRACE("Enter NtUserMenuInfo\n");
2570 if (!(Menu
= UserGetMenuObject(hMenu
)))
2575 RETURN(UserMenuInfo(Menu
, UnsafeMenuInfo
, SetOrGet
));
2578 TRACE("Leave NtUserMenuInfo, ret=%i\n",_ret_
);
2592 PROSMENUITEMINFO UnsafeItemInfo
,
2596 DECLARE_RETURN(BOOL
);
2598 TRACE("Enter NtUserMenuItemInfo\n");
2599 UserEnterExclusive();
2601 if (!(Menu
= UserGetMenuObject(hMenu
)))
2606 RETURN( UserMenuItemInfo(Menu
, Item
, ByPosition
, UnsafeItemInfo
, SetOrGet
));
2609 TRACE("Leave NtUserMenuItemInfo, ret=%i\n",_ret_
);