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 ******************************************************************/
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 ExFreePoolWithTag((MenuItem)->Text.Buffer, TAG_STRING); \
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
, BOOL bRecurse
)
211 FreeMenuText(MenuItem
);
212 if(bRecurse
&& MenuItem
->hSubMenu
)
214 PMENU_OBJECT SubMenu
;
215 SubMenu
= UserGetMenuObject(MenuItem
->hSubMenu
);
218 IntDestroyMenuObject(SubMenu
, bRecurse
, TRUE
);
223 ExFreePool(MenuItem
);
229 IntRemoveMenuItem(PMENU_OBJECT Menu
, UINT uPosition
, UINT uFlags
,
232 PMENU_ITEM PrevMenuItem
, MenuItem
;
233 if(IntGetMenuItemByFlag(Menu
, uPosition
, uFlags
, &Menu
, &MenuItem
,
239 PrevMenuItem
->Next
= MenuItem
->Next
;
242 Menu
->MenuItemList
= MenuItem
->Next
;
244 Menu
->MenuInfo
.MenuItemCount
--;
245 return IntFreeMenuItem(Menu
, MenuItem
, bRecurse
);
252 IntDeleteMenuItems(PMENU_OBJECT Menu
, BOOL bRecurse
)
256 PMENU_ITEM CurItem
= Menu
->MenuItemList
;
259 NextItem
= CurItem
->Next
;
260 IntFreeMenuItem(Menu
, CurItem
, bRecurse
);
264 Menu
->MenuInfo
.MenuItemCount
= 0;
265 Menu
->MenuItemList
= NULL
;
270 IntDestroyMenuObject(PMENU_OBJECT Menu
,
271 BOOL bRecurse
, BOOL RemoveFromProcess
)
275 PWINDOW_OBJECT Window
;
276 PWINSTATION_OBJECT WindowStation
;
279 /* remove all menu items */
280 IntDeleteMenuItems(Menu
, bRecurse
); /* do not destroy submenus */
282 if(RemoveFromProcess
)
284 RemoveEntryList(&Menu
->ListEntry
);
287 Status
= ObReferenceObjectByHandle(Menu
->Process
->Win32WindowStation
,
289 ExWindowStationObjectType
,
291 (PVOID
*)&WindowStation
,
293 if(NT_SUCCESS(Status
))
295 if (Menu
->MenuInfo
.Wnd
)
297 Window
= UserGetWindowObject(Menu
->MenuInfo
.Wnd
);
300 Window
->Wnd
->IDMenu
= 0;
303 // UserDereferenceObject(Menu);
304 BOOL ret
= UserDeleteObject(Menu
->MenuInfo
.Self
, otMenu
);
305 ObDereferenceObject(WindowStation
);
312 PMENU_OBJECT FASTCALL
313 IntCreateMenu(PHANDLE Handle
, BOOL IsMenuBar
)
316 PW32PROCESS CurrentWin32Process
;
318 Menu
= (PMENU_OBJECT
)UserCreateObject(
319 gHandleTable
, Handle
,
320 otMenu
, sizeof(MENU_OBJECT
));
328 Menu
->Process
= PsGetCurrentProcess();
329 Menu
->RtoL
= FALSE
; /* default */
330 Menu
->MenuInfo
.cbSize
= sizeof(MENUINFO
); /* not used */
331 Menu
->MenuInfo
.fMask
= 0; /* not used */
332 Menu
->MenuInfo
.dwStyle
= 0; /* FIXME */
333 Menu
->MenuInfo
.cyMax
= 0; /* default */
334 Menu
->MenuInfo
.hbrBack
= NULL
; /* no brush */
335 Menu
->MenuInfo
.dwContextHelpID
= 0; /* default */
336 Menu
->MenuInfo
.dwMenuData
= 0; /* default */
337 Menu
->MenuInfo
.Self
= *Handle
;
338 Menu
->MenuInfo
.FocusedItem
= NO_SELECTED_ITEM
;
339 Menu
->MenuInfo
.Flags
= (IsMenuBar
? 0 : MF_POPUP
);
340 Menu
->MenuInfo
.Wnd
= NULL
;
341 Menu
->MenuInfo
.WndOwner
= NULL
;
342 Menu
->MenuInfo
.Height
= 0;
343 Menu
->MenuInfo
.Width
= 0;
344 Menu
->MenuInfo
.TimeToHide
= FALSE
;
346 Menu
->MenuInfo
.MenuItemCount
= 0;
347 Menu
->MenuItemList
= NULL
;
349 /* Insert menu item into process menu handle list */
350 CurrentWin32Process
= PsGetCurrentProcessWin32Process();
351 InsertTailList(&CurrentWin32Process
->MenuListHead
, &Menu
->ListEntry
);
357 IntCloneMenuItems(PMENU_OBJECT Destination
, PMENU_OBJECT Source
)
359 PMENU_ITEM MenuItem
, NewMenuItem
= NULL
;
360 PMENU_ITEM Old
= NULL
;
362 if(!Source
->MenuInfo
.MenuItemCount
)
365 MenuItem
= Source
->MenuItemList
;
370 NewMenuItem
->Next
= MenuItem
;
371 NewMenuItem
= ExAllocatePoolWithTag(PagedPool
, sizeof(MENU_ITEM
), TAG_MENUITEM
);
374 NewMenuItem
->fType
= MenuItem
->fType
;
375 NewMenuItem
->fState
= MenuItem
->fState
;
376 NewMenuItem
->wID
= MenuItem
->wID
;
377 NewMenuItem
->hSubMenu
= MenuItem
->hSubMenu
;
378 NewMenuItem
->hbmpChecked
= MenuItem
->hbmpChecked
;
379 NewMenuItem
->hbmpUnchecked
= MenuItem
->hbmpUnchecked
;
380 NewMenuItem
->dwItemData
= MenuItem
->dwItemData
;
381 if((MENU_ITEM_TYPE(NewMenuItem
->fType
) == MF_STRING
))
383 if(MenuItem
->Text
.Length
)
385 NewMenuItem
->Text
.Length
= 0;
386 NewMenuItem
->Text
.MaximumLength
= MenuItem
->Text
.MaximumLength
;
387 NewMenuItem
->Text
.Buffer
= (PWSTR
)ExAllocatePoolWithTag(PagedPool
, MenuItem
->Text
.MaximumLength
, TAG_STRING
);
388 if(!NewMenuItem
->Text
.Buffer
)
390 ExFreePoolWithTag(NewMenuItem
, TAG_MENUITEM
);
393 RtlCopyUnicodeString(&NewMenuItem
->Text
, &MenuItem
->Text
);
397 NewMenuItem
->Text
.Buffer
= MenuItem
->Text
.Buffer
;
402 NewMenuItem
->Text
.Buffer
= MenuItem
->Text
.Buffer
;
404 NewMenuItem
->hbmpItem
= MenuItem
->hbmpItem
;
406 NewMenuItem
->Next
= NULL
;
408 Old
->Next
= NewMenuItem
;
410 Destination
->MenuItemList
= NewMenuItem
;
411 Destination
->MenuInfo
.MenuItemCount
++;
412 MenuItem
= MenuItem
->Next
;
418 PMENU_OBJECT FASTCALL
419 IntCloneMenu(PMENU_OBJECT Source
)
421 PW32PROCESS CurrentWin32Process
;
428 Menu
= (PMENU_OBJECT
)UserCreateObject(
429 gHandleTable
, &hMenu
,
430 otMenu
, sizeof(MENU_OBJECT
));
435 Menu
->Process
= PsGetCurrentProcess();
436 Menu
->RtoL
= Source
->RtoL
;
437 Menu
->MenuInfo
.cbSize
= sizeof(MENUINFO
); /* not used */
438 Menu
->MenuInfo
.fMask
= Source
->MenuInfo
.fMask
;
439 Menu
->MenuInfo
.dwStyle
= Source
->MenuInfo
.dwStyle
;
440 Menu
->MenuInfo
.cyMax
= Source
->MenuInfo
.cyMax
;
441 Menu
->MenuInfo
.hbrBack
= Source
->MenuInfo
.hbrBack
;
442 Menu
->MenuInfo
.dwContextHelpID
= Source
->MenuInfo
.dwContextHelpID
;
443 Menu
->MenuInfo
.dwMenuData
= Source
->MenuInfo
.dwMenuData
;
444 Menu
->MenuInfo
.Self
= hMenu
;
445 Menu
->MenuInfo
.FocusedItem
= NO_SELECTED_ITEM
;
446 Menu
->MenuInfo
.Wnd
= NULL
;
447 Menu
->MenuInfo
.WndOwner
= NULL
;
448 Menu
->MenuInfo
.Height
= 0;
449 Menu
->MenuInfo
.Width
= 0;
450 Menu
->MenuInfo
.TimeToHide
= FALSE
;
452 Menu
->MenuInfo
.MenuItemCount
= 0;
453 Menu
->MenuItemList
= NULL
;
455 /* Insert menu item into process menu handle list */
456 CurrentWin32Process
= PsGetCurrentProcessWin32Process();
457 InsertTailList(&CurrentWin32Process
->MenuListHead
, &Menu
->ListEntry
);
459 IntCloneMenuItems(Menu
, Source
);
465 IntSetMenuFlagRtoL(PMENU_OBJECT Menu
)
472 IntSetMenuContextHelpId(PMENU_OBJECT Menu
, DWORD dwContextHelpId
)
474 Menu
->MenuInfo
.dwContextHelpID
= dwContextHelpId
;
479 IntGetMenuInfo(PMENU_OBJECT Menu
, PROSMENUINFO lpmi
)
481 if(lpmi
->fMask
& MIM_BACKGROUND
)
482 lpmi
->hbrBack
= Menu
->MenuInfo
.hbrBack
;
483 if(lpmi
->fMask
& MIM_HELPID
)
484 lpmi
->dwContextHelpID
= Menu
->MenuInfo
.dwContextHelpID
;
485 if(lpmi
->fMask
& MIM_MAXHEIGHT
)
486 lpmi
->cyMax
= Menu
->MenuInfo
.cyMax
;
487 if(lpmi
->fMask
& MIM_MENUDATA
)
488 lpmi
->dwMenuData
= Menu
->MenuInfo
.dwMenuData
;
489 if(lpmi
->fMask
& MIM_STYLE
)
490 lpmi
->dwStyle
= Menu
->MenuInfo
.dwStyle
;
491 if (sizeof(MENUINFO
) < lpmi
->cbSize
)
493 RtlCopyMemory((char *) lpmi
+ sizeof(MENUINFO
),
494 (char *) &Menu
->MenuInfo
+ sizeof(MENUINFO
),
495 lpmi
->cbSize
- sizeof(MENUINFO
));
497 if (sizeof(ROSMENUINFO
) == lpmi
->cbSize
)
499 lpmi
->maxBmpSize
.cx
= Menu
->MenuInfo
.maxBmpSize
.cx
;
500 lpmi
->maxBmpSize
.cy
= Menu
->MenuInfo
.maxBmpSize
.cy
;
507 IntIsMenu(HMENU hMenu
)
511 if((Menu
= UserGetMenuObject(hMenu
)))
520 IntSetMenuInfo(PMENU_OBJECT Menu
, PROSMENUINFO lpmi
)
522 if(lpmi
->fMask
& MIM_BACKGROUND
)
523 Menu
->MenuInfo
.hbrBack
= lpmi
->hbrBack
;
524 if(lpmi
->fMask
& MIM_HELPID
)
525 Menu
->MenuInfo
.dwContextHelpID
= lpmi
->dwContextHelpID
;
526 if(lpmi
->fMask
& MIM_MAXHEIGHT
)
527 Menu
->MenuInfo
.cyMax
= lpmi
->cyMax
;
528 if(lpmi
->fMask
& MIM_MENUDATA
)
529 Menu
->MenuInfo
.dwMenuData
= lpmi
->dwMenuData
;
530 if(lpmi
->fMask
& MIM_STYLE
)
531 Menu
->MenuInfo
.dwStyle
= lpmi
->dwStyle
;
532 if(lpmi
->fMask
& MIM_APPLYTOSUBMENUS
)
536 if (sizeof(MENUINFO
) < lpmi
->cbSize
)
538 Menu
->MenuInfo
.FocusedItem
= lpmi
->FocusedItem
;
539 Menu
->MenuInfo
.Height
= lpmi
->Height
;
540 Menu
->MenuInfo
.Width
= lpmi
->Width
;
541 Menu
->MenuInfo
.Wnd
= lpmi
->Wnd
;
542 Menu
->MenuInfo
.WndOwner
= lpmi
->WndOwner
;
543 Menu
->MenuInfo
.TimeToHide
= lpmi
->TimeToHide
;
545 if (sizeof(ROSMENUINFO
) == lpmi
->cbSize
)
547 Menu
->MenuInfo
.maxBmpSize
.cx
= lpmi
->maxBmpSize
.cx
;
548 Menu
->MenuInfo
.maxBmpSize
.cy
= lpmi
->maxBmpSize
.cy
;
555 IntGetMenuItemByFlag(PMENU_OBJECT Menu
, UINT uSearchBy
, UINT fFlag
,
556 PMENU_OBJECT
*SubMenu
, PMENU_ITEM
*MenuItem
,
557 PMENU_ITEM
*PrevMenuItem
)
559 PMENU_ITEM PrevItem
= NULL
;
560 PMENU_ITEM CurItem
= Menu
->MenuItemList
;
564 if(MF_BYPOSITION
& fFlag
)
567 while(CurItem
&& (p
> 0))
570 CurItem
= CurItem
->Next
;
578 *PrevMenuItem
= PrevItem
;
585 *PrevMenuItem
= NULL
; /* ? */
589 return uSearchBy
- p
;
596 if(CurItem
->wID
== uSearchBy
)
601 *PrevMenuItem
= PrevItem
;
609 if(CurItem
->fType
& MF_POPUP
)
611 PMENU_OBJECT NewMenu
= UserGetMenuObject(CurItem
->hSubMenu
);
614 ret
= IntGetMenuItemByFlag(NewMenu
, uSearchBy
, fFlag
,
615 SubMenu
, MenuItem
, PrevMenuItem
);
624 CurItem
= CurItem
->Next
;
633 IntInsertMenuItemToList(PMENU_OBJECT Menu
, PMENU_ITEM MenuItem
, int pos
)
636 PMENU_ITEM LastItem
= NULL
;
639 CurItem
= Menu
->MenuItemList
;
640 while(CurItem
&& (pos
!= 0))
643 CurItem
= CurItem
->Next
;
650 /* insert the item after LastItem */
651 LastItem
->Next
= MenuItem
;
655 /* insert at the beginning */
656 Menu
->MenuItemList
= MenuItem
;
658 MenuItem
->Next
= CurItem
;
659 Menu
->MenuInfo
.MenuItemCount
++;
665 IntGetMenuItemInfo(PMENU_OBJECT Menu
, /* UNUSED PARAM!! */
666 PMENU_ITEM MenuItem
, PROSMENUITEMINFO lpmii
)
670 if(lpmii
->fMask
& (MIIM_FTYPE
| MIIM_TYPE
))
672 lpmii
->fType
= MenuItem
->fType
;
674 if(lpmii
->fMask
& MIIM_BITMAP
)
676 lpmii
->hbmpItem
= MenuItem
->hbmpItem
;
678 if(lpmii
->fMask
& MIIM_CHECKMARKS
)
680 lpmii
->hbmpChecked
= MenuItem
->hbmpChecked
;
681 lpmii
->hbmpUnchecked
= MenuItem
->hbmpUnchecked
;
683 if(lpmii
->fMask
& MIIM_DATA
)
685 lpmii
->dwItemData
= MenuItem
->dwItemData
;
687 if(lpmii
->fMask
& MIIM_ID
)
689 lpmii
->wID
= MenuItem
->wID
;
691 if(lpmii
->fMask
& MIIM_STATE
)
693 lpmii
->fState
= MenuItem
->fState
;
695 if(lpmii
->fMask
& MIIM_SUBMENU
)
697 lpmii
->hSubMenu
= MenuItem
->hSubMenu
;
700 if ((lpmii
->fMask
& MIIM_STRING
) ||
701 ((lpmii
->fMask
& MIIM_TYPE
) && (MENU_ITEM_TYPE(lpmii
->fType
) == MF_STRING
)))
703 if (lpmii
->dwTypeData
== NULL
)
705 lpmii
->cch
= MenuItem
->Text
.Length
/ sizeof(WCHAR
);
709 Status
= MmCopyToCaller(lpmii
->dwTypeData
, MenuItem
->Text
.Buffer
,
710 min(lpmii
->cch
* sizeof(WCHAR
),
711 MenuItem
->Text
.MaximumLength
));
712 if (! NT_SUCCESS(Status
))
714 SetLastNtError(Status
);
720 if (sizeof(ROSMENUITEMINFO
) == lpmii
->cbSize
)
722 lpmii
->Rect
= MenuItem
->Rect
;
723 lpmii
->XTab
= MenuItem
->XTab
;
724 lpmii
->Text
= MenuItem
->Text
.Buffer
;
731 IntSetMenuItemInfo(PMENU_OBJECT MenuObject
, PMENU_ITEM MenuItem
, PROSMENUITEMINFO lpmii
)
733 PMENU_OBJECT SubMenuObject
;
734 UINT fTypeMask
= (MFT_BITMAP
| MFT_MENUBARBREAK
| MFT_MENUBREAK
| MFT_OWNERDRAW
| MFT_RADIOCHECK
| MFT_RIGHTJUSTIFY
| MFT_SEPARATOR
| MF_POPUP
);
736 if(!MenuItem
|| !MenuObject
|| !lpmii
)
740 if( lpmii
->fType
& ~fTypeMask
)
742 DbgPrint("IntSetMenuItemInfo invalid fType flags %x\n", lpmii
->fType
& ~fTypeMask
);
743 lpmii
->fMask
&= ~(MIIM_TYPE
| MIIM_FTYPE
);
745 if(lpmii
->fMask
& MIIM_TYPE
)
747 if(lpmii
->fMask
& ( MIIM_STRING
| MIIM_FTYPE
| MIIM_BITMAP
))
749 DbgPrint("IntSetMenuItemInfo: Invalid combination of fMask bits used\n");
750 /* this does not happen on Win9x/ME */
751 SetLastNtError( ERROR_INVALID_PARAMETER
);
755 * Delete the menu item type when changing type from
758 if (MenuItem
->fType
!= lpmii
->fType
&&
759 MENU_ITEM_TYPE(MenuItem
->fType
) == MFT_STRING
)
761 FreeMenuText(MenuItem
);
762 RtlInitUnicodeString(&MenuItem
->Text
, NULL
);
764 if(lpmii
->fType
& MFT_BITMAP
)
767 MenuItem
->hbmpItem
= lpmii
->hbmpItem
;
769 { /* Win 9x/Me stuff */
770 MenuItem
->hbmpItem
= (HBITMAP
)((ULONG_PTR
)(LOWORD(lpmii
->dwTypeData
)));
773 MenuItem
->fType
|= lpmii
->fType
;
775 if (lpmii
->fMask
& MIIM_FTYPE
)
777 if(( lpmii
->fType
& MFT_BITMAP
))
779 DbgPrint("IntSetMenuItemInfo: Can not use FTYPE and MFT_BITMAP.\n");
780 SetLastNtError( ERROR_INVALID_PARAMETER
);
783 MenuItem
->fType
|= lpmii
->fType
; /* Need to save all the flags, this fixed MFT_RIGHTJUSTIFY */
785 if(lpmii
->fMask
& MIIM_BITMAP
)
787 MenuItem
->hbmpItem
= lpmii
->hbmpItem
;
789 if(lpmii
->fMask
& MIIM_CHECKMARKS
)
791 MenuItem
->hbmpChecked
= lpmii
->hbmpChecked
;
792 MenuItem
->hbmpUnchecked
= lpmii
->hbmpUnchecked
;
794 if(lpmii
->fMask
& MIIM_DATA
)
796 MenuItem
->dwItemData
= lpmii
->dwItemData
;
798 if(lpmii
->fMask
& MIIM_ID
)
800 MenuItem
->wID
= lpmii
->wID
;
802 if(lpmii
->fMask
& MIIM_STATE
)
804 /* remove MFS_DEFAULT flag from all other menu items if this item
805 has the MFS_DEFAULT state */
806 if(lpmii
->fState
& MFS_DEFAULT
)
807 UserSetMenuDefaultItem(MenuObject
, -1, 0);
808 /* update the menu item state flags */
809 UpdateMenuItemState(MenuItem
->fState
, lpmii
->fState
);
812 if(lpmii
->fMask
& MIIM_SUBMENU
)
814 MenuItem
->hSubMenu
= lpmii
->hSubMenu
;
815 /* Make sure the submenu is marked as a popup menu */
816 if (MenuItem
->hSubMenu
)
818 SubMenuObject
= UserGetMenuObject(MenuItem
->hSubMenu
);
819 if (SubMenuObject
!= NULL
)
821 SubMenuObject
->MenuInfo
.Flags
|= MF_POPUP
;
822 MenuItem
->fType
|= MF_POPUP
;
826 MenuItem
->fType
&= ~MF_POPUP
;
831 MenuItem
->fType
&= ~MF_POPUP
;
835 if ((lpmii
->fMask
& MIIM_STRING
) ||
836 ((lpmii
->fMask
& MIIM_TYPE
) && (MENU_ITEM_TYPE(lpmii
->fType
) == MF_STRING
)))
838 FreeMenuText(MenuItem
);
840 if(lpmii
->dwTypeData
&& lpmii
->cch
)
842 UNICODE_STRING Source
;
845 Source
.MaximumLength
= lpmii
->cch
* sizeof(WCHAR
);
846 Source
.Buffer
= lpmii
->dwTypeData
;
848 MenuItem
->Text
.Buffer
= (PWSTR
)ExAllocatePoolWithTag(
849 PagedPool
, Source
.Length
+ sizeof(WCHAR
), TAG_STRING
);
850 if(MenuItem
->Text
.Buffer
!= NULL
)
852 MenuItem
->Text
.Length
= 0;
853 MenuItem
->Text
.MaximumLength
= Source
.Length
+ sizeof(WCHAR
);
854 RtlCopyUnicodeString(&MenuItem
->Text
, &Source
);
855 MenuItem
->Text
.Buffer
[MenuItem
->Text
.Length
/ sizeof(WCHAR
)] = 0;
859 RtlInitUnicodeString(&MenuItem
->Text
, NULL
);
864 if (0 == (MenuObject
->MenuInfo
.Flags
& MF_SYSMENU
))
866 MenuItem
->fType
|= MF_SEPARATOR
;
868 RtlInitUnicodeString(&MenuItem
->Text
, NULL
);
872 if (sizeof(ROSMENUITEMINFO
) == lpmii
->cbSize
)
874 MenuItem
->Rect
= lpmii
->Rect
;
875 MenuItem
->XTab
= lpmii
->XTab
;
876 lpmii
->Text
= MenuItem
->Text
.Buffer
; /* Send back new allocated string or zero */
883 IntInsertMenuItem(PMENU_OBJECT MenuObject
, UINT uItem
, BOOL fByPosition
,
884 PROSMENUITEMINFO ItemInfo
)
886 int pos
= (int)uItem
;
888 PMENU_OBJECT SubMenu
= NULL
;
890 if (MAX_MENU_ITEMS
<= MenuObject
->MenuInfo
.MenuItemCount
)
892 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
898 SubMenu
= MenuObject
;
899 /* calculate position */
900 if(MenuObject
->MenuInfo
.MenuItemCount
< pos
)
902 pos
= MenuObject
->MenuInfo
.MenuItemCount
;
907 pos
= IntGetMenuItemByFlag(MenuObject
, uItem
, MF_BYCOMMAND
, &SubMenu
, NULL
, NULL
);
911 /* default to last position of menu */
912 SubMenu
= MenuObject
;
913 pos
= MenuObject
->MenuInfo
.MenuItemCount
;
922 MenuItem
= ExAllocatePoolWithTag(PagedPool
, sizeof(MENU_ITEM
), TAG_MENUITEM
);
923 if (NULL
== MenuItem
)
925 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
929 MenuItem
->fType
= MFT_STRING
;
930 MenuItem
->fState
= MFS_ENABLED
| MFS_UNCHECKED
;
932 MenuItem
->hSubMenu
= (HMENU
)0;
933 MenuItem
->hbmpChecked
= (HBITMAP
)0;
934 MenuItem
->hbmpUnchecked
= (HBITMAP
)0;
935 MenuItem
->dwItemData
= 0;
936 RtlInitUnicodeString(&MenuItem
->Text
, NULL
);
937 MenuItem
->hbmpItem
= (HBITMAP
)0;
939 if(!IntSetMenuItemInfo(SubMenu
, MenuItem
, ItemInfo
))
941 ExFreePoolWithTag(MenuItem
, TAG_MENUITEM
);
945 /* Force size recalculation! */
946 MenuObject
->MenuInfo
.Height
= 0;
948 pos
= IntInsertMenuItemToList(SubMenu
, MenuItem
, pos
);
950 DPRINT("IntInsertMenuItemToList = %i\n", pos
);
956 IntEnableMenuItem(PMENU_OBJECT MenuObject
, UINT uIDEnableItem
, UINT uEnable
)
959 UINT res
= IntGetMenuItemByFlag(MenuObject
, uIDEnableItem
, uEnable
, NULL
, &MenuItem
, NULL
);
960 if(!MenuItem
|| (res
== (UINT
)-1))
965 res
= MenuItem
->fState
& (MF_GRAYED
| MF_DISABLED
);
967 if(uEnable
& MF_DISABLED
)
969 MenuItem
->fState
|= MF_DISABLED
;
970 MenuItem
->fState
|= uEnable
& MF_GRAYED
;
974 if(uEnable
& MF_GRAYED
)
976 MenuItem
->fState
|= (MF_GRAYED
| MF_DISABLED
);
980 MenuItem
->fState
&= ~(MF_DISABLED
| MF_GRAYED
);
989 IntBuildMenuItemList(PMENU_OBJECT MenuObject
, PVOID Buffer
, ULONG nMax
)
995 PMENU_ITEM CurItem
= MenuObject
->MenuItemList
;
1002 if (nMax
< MenuObject
->MenuInfo
.MenuItemCount
* sizeof(ROSMENUITEMINFO
))
1006 StrOut
= (PWCHAR
)((char *) Buffer
+ MenuObject
->MenuInfo
.MenuItemCount
1007 * sizeof(ROSMENUITEMINFO
));
1008 nMax
-= MenuObject
->MenuInfo
.MenuItemCount
* sizeof(ROSMENUITEMINFO
);
1009 sz
= sizeof(ROSMENUITEMINFO
);
1011 mii
.cbSize
= sizeof(ROSMENUITEMINFO
);
1015 while (NULL
!= CurItem
)
1017 mii
.cch
= CurItem
->Text
.Length
/ sizeof(WCHAR
);
1018 mii
.dwItemData
= CurItem
->dwItemData
;
1019 if (0 != CurItem
->Text
.Length
)
1021 mii
.dwTypeData
= StrOut
;
1025 mii
.dwTypeData
= NULL
;
1027 mii
.fState
= CurItem
->fState
;
1028 mii
.fType
= CurItem
->fType
;
1029 mii
.wID
= CurItem
->wID
;
1030 mii
.hbmpChecked
= CurItem
->hbmpChecked
;
1031 mii
.hbmpItem
= CurItem
->hbmpItem
;
1032 mii
.hbmpUnchecked
= CurItem
->hbmpUnchecked
;
1033 mii
.hSubMenu
= CurItem
->hSubMenu
;
1034 mii
.Rect
= CurItem
->Rect
;
1035 mii
.XTab
= CurItem
->XTab
;
1036 mii
.Text
= CurItem
->Text
.Buffer
;
1038 Status
= MmCopyToCaller(Buf
, &mii
, sizeof(ROSMENUITEMINFO
));
1039 if (! NT_SUCCESS(Status
))
1041 SetLastNtError(Status
);
1044 Buf
= (PVOID
)((ULONG_PTR
)Buf
+ sizeof(ROSMENUITEMINFO
));
1046 if (0 != CurItem
->Text
.Length
1047 && (nMax
>= CurItem
->Text
.Length
+ sizeof(WCHAR
)))
1050 Status
= MmCopyToCaller(StrOut
, CurItem
->Text
.Buffer
,
1051 CurItem
->Text
.Length
);
1052 if (! NT_SUCCESS(Status
))
1054 SetLastNtError(Status
);
1057 StrOut
+= CurItem
->Text
.Length
/ sizeof(WCHAR
);
1058 Status
= MmCopyToCaller(StrOut
, &NulByte
, sizeof(WCHAR
));
1059 if (! NT_SUCCESS(Status
))
1061 SetLastNtError(Status
);
1065 nMax
-= CurItem
->Text
.Length
+ sizeof(WCHAR
);
1067 else if (0 != CurItem
->Text
.Length
)
1072 CurItem
= CurItem
->Next
;
1078 while (NULL
!= CurItem
)
1080 res
+= sizeof(ROSMENUITEMINFO
) + CurItem
->Text
.Length
+ sizeof(WCHAR
);
1081 CurItem
= CurItem
->Next
;
1090 IntCheckMenuItem(PMENU_OBJECT MenuObject
, UINT uIDCheckItem
, UINT uCheck
)
1092 PMENU_ITEM MenuItem
;
1095 if((IntGetMenuItemByFlag(MenuObject
, uIDCheckItem
, uCheck
, NULL
, &MenuItem
, NULL
) < 0) || !MenuItem
)
1100 res
= (DWORD
)(MenuItem
->fState
& MF_CHECKED
);
1101 if(uCheck
& MF_CHECKED
)
1103 MenuItem
->fState
|= MF_CHECKED
;
1107 MenuItem
->fState
&= ~MF_CHECKED
;
1114 IntHiliteMenuItem(PWINDOW_OBJECT WindowObject
, PMENU_OBJECT MenuObject
,
1115 UINT uItemHilite
, UINT uHilite
)
1117 PMENU_ITEM MenuItem
;
1118 BOOL res
= IntGetMenuItemByFlag(MenuObject
, uItemHilite
, uHilite
, NULL
, &MenuItem
, NULL
);
1119 if(!MenuItem
|| !res
)
1124 if(uHilite
& MF_HILITE
)
1126 MenuItem
->fState
|= MF_HILITE
;
1130 MenuItem
->fState
&= ~MF_HILITE
;
1133 /* FIXME - update the window's menu */
1139 UserSetMenuDefaultItem(PMENU_OBJECT MenuObject
, UINT uItem
, UINT fByPos
)
1142 PMENU_ITEM MenuItem
= MenuObject
->MenuItemList
;
1144 if(uItem
== (UINT
)-1)
1148 MenuItem
->fState
&= ~MFS_DEFAULT
;
1149 MenuItem
= MenuItem
->Next
;
1161 MenuItem
->fState
|= MFS_DEFAULT
;
1166 MenuItem
->fState
&= ~MFS_DEFAULT
;
1169 MenuItem
= MenuItem
->Next
;
1176 if(!ret
&& (MenuItem
->wID
== uItem
))
1178 MenuItem
->fState
|= MFS_DEFAULT
;
1183 MenuItem
->fState
&= ~MFS_DEFAULT
;
1185 MenuItem
= MenuItem
->Next
;
1193 IntGetMenuDefaultItem(PMENU_OBJECT MenuObject
, UINT fByPos
, UINT gmdiFlags
,
1199 PMENU_OBJECT SubMenuObject
;
1200 PMENU_ITEM MenuItem
= MenuObject
->MenuItemList
;
1204 if(MenuItem
->fState
& MFS_DEFAULT
)
1207 if(!(gmdiFlags
& GMDI_USEDISABLED
) && (MenuItem
->fState
& MFS_DISABLED
))
1213 res
= MenuItem
->wID
;
1215 if((*gismc
< MAX_GOINTOSUBMENU
) && (gmdiFlags
& GMDI_GOINTOPOPUPS
) &&
1219 SubMenuObject
= UserGetMenuObject(MenuItem
->hSubMenu
);
1220 if(!SubMenuObject
|| (SubMenuObject
== MenuObject
))
1224 sres
= IntGetMenuDefaultItem(SubMenuObject
, fByPos
, gmdiFlags
, gismc
);
1234 MenuItem
= MenuItem
->Next
;
1242 co_IntInitTracking(PWINDOW_OBJECT Window
, PMENU_OBJECT Menu
, BOOL Popup
,
1245 /* FIXME - hide caret */
1247 if(!(Flags
& TPM_NONOTIFY
))
1248 co_IntSendMessage(Window
->hSelf
, WM_SETCURSOR
, (WPARAM
)Window
->hSelf
, HTCAPTION
);
1250 /* FIXME - send WM_SETCURSOR message */
1252 if(!(Flags
& TPM_NONOTIFY
))
1253 co_IntSendMessage(Window
->hSelf
, WM_INITMENU
, (WPARAM
)Menu
->MenuInfo
.Self
, 0);
1257 co_IntExitTracking(PWINDOW_OBJECT Window
, PMENU_OBJECT Menu
, BOOL Popup
,
1260 if(!(Flags
& TPM_NONOTIFY
))
1261 co_IntSendMessage(Window
->hSelf
, WM_EXITMENULOOP
, 0 /* FIXME */, 0);
1263 /* FIXME - Show caret again */
1267 IntTrackMenu(PMENU_OBJECT Menu
, PWINDOW_OBJECT Window
, INT x
, INT y
,
1274 co_IntTrackPopupMenu(PMENU_OBJECT Menu
, PWINDOW_OBJECT Window
,
1275 UINT Flags
, POINT
*Pos
, UINT MenuPos
, RECT
*ExcludeRect
)
1277 co_IntInitTracking(Window
, Menu
, TRUE
, Flags
);
1279 co_IntExitTracking(Window
, Menu
, TRUE
, Flags
);
1284 IntSetMenuItemRect(PMENU_OBJECT Menu
, UINT Item
, BOOL fByPos
, RECT
*rcRect
)
1287 if(IntGetMenuItemByFlag(Menu
, Item
, (fByPos
? MF_BYPOSITION
: MF_BYCOMMAND
),
1288 NULL
, &mi
, NULL
) > -1)
1298 * Internal function. Called when the process is destroyed to free the remaining menu handles.
1301 IntCleanupMenus(struct _EPROCESS
*Process
, PW32PROCESS Win32Process
)
1303 PEPROCESS CurrentProcess
;
1304 PLIST_ENTRY LastHead
= NULL
;
1305 PMENU_OBJECT MenuObject
;
1307 CurrentProcess
= PsGetCurrentProcess();
1308 if (CurrentProcess
!= Process
)
1310 KeAttachProcess(&Process
->Pcb
);
1313 while (Win32Process
->MenuListHead
.Flink
!= &(Win32Process
->MenuListHead
) &&
1314 Win32Process
->MenuListHead
.Flink
!= LastHead
)
1316 LastHead
= Win32Process
->MenuListHead
.Flink
;
1317 MenuObject
= CONTAINING_RECORD(Win32Process
->MenuListHead
.Flink
, MENU_OBJECT
, ListEntry
);
1319 IntDestroyMenuObject(MenuObject
, FALSE
, TRUE
);
1322 if (CurrentProcess
!= Process
)
1330 co_InflateRect(LPRECT rect
, int dx
, int dy
)
1339 intGetTitleBarInfo(PWINDOW_OBJECT pWindowObject
, PTITLEBARINFO bti
)
1343 DWORD dwExStyle
= 0;
1344 BOOLEAN retValue
= TRUE
;
1346 if (bti
->cbSize
== sizeof(TITLEBARINFO
))
1348 RtlZeroMemory(&bti
->rgstate
[0],sizeof(DWORD
)*(CCHILDREN_TITLEBAR
+1));
1350 bti
->rgstate
[0] = STATE_SYSTEM_FOCUSABLE
;
1352 dwStyle
= pWindowObject
->Wnd
->Style
;
1353 dwExStyle
= pWindowObject
->Wnd
->ExStyle
;
1355 bti
->rcTitleBar
.top
= 0;
1356 bti
->rcTitleBar
.left
= 0;
1357 bti
->rcTitleBar
.right
= pWindowObject
->Wnd
->WindowRect
.right
- pWindowObject
->Wnd
->WindowRect
.left
;
1358 bti
->rcTitleBar
.bottom
= pWindowObject
->Wnd
->WindowRect
.bottom
- pWindowObject
->Wnd
->WindowRect
.top
;
1360 /* is it iconiced ? */
1361 if ((dwStyle
& WS_ICONIC
)!=WS_ICONIC
)
1363 /* Remove frame from rectangle */
1364 if (HAS_THICKFRAME( dwStyle
, dwExStyle
))
1366 /* FIXME : Note this value should exists in pWindowObject for UserGetSystemMetrics(SM_CXFRAME) and UserGetSystemMetrics(SM_CYFRAME) */
1367 co_InflateRect( &bti
->rcTitleBar
, -UserGetSystemMetrics(SM_CXFRAME
), -UserGetSystemMetrics(SM_CYFRAME
) );
1369 else if (HAS_DLGFRAME( dwStyle
, dwExStyle
))
1371 /* FIXME : Note this value should exists in pWindowObject for UserGetSystemMetrics(SM_CXDLGFRAME) and UserGetSystemMetrics(SM_CYDLGFRAME) */
1372 co_InflateRect( &bti
->rcTitleBar
, -UserGetSystemMetrics(SM_CXDLGFRAME
), -UserGetSystemMetrics(SM_CYDLGFRAME
));
1374 else if (HAS_THINFRAME( dwStyle
, dwExStyle
))
1376 /* FIXME : Note this value should exists in pWindowObject for UserGetSystemMetrics(SM_CXBORDER) and UserGetSystemMetrics(SM_CYBORDER) */
1377 co_InflateRect( &bti
->rcTitleBar
, -UserGetSystemMetrics(SM_CXBORDER
), -UserGetSystemMetrics(SM_CYBORDER
) );
1380 /* We have additional border information if the window
1381 * is a child (but not an MDI child) */
1382 if ( (dwStyle
& WS_CHILD
) &&
1383 ((dwExStyle
& WS_EX_MDICHILD
) == 0 ) )
1385 if (dwExStyle
& WS_EX_CLIENTEDGE
)
1387 /* FIXME : Note this value should exists in pWindowObject for UserGetSystemMetrics(SM_CXEDGE) and UserGetSystemMetrics(SM_CYEDGE) */
1388 co_InflateRect (&bti
->rcTitleBar
, -UserGetSystemMetrics(SM_CXEDGE
), -UserGetSystemMetrics(SM_CYEDGE
));
1391 if (dwExStyle
& WS_EX_STATICEDGE
)
1393 /* FIXME : Note this value should exists in pWindowObject for UserGetSystemMetrics(SM_CXBORDER) and UserGetSystemMetrics(SM_CYBORDER) */
1394 co_InflateRect (&bti
->rcTitleBar
, -UserGetSystemMetrics(SM_CXBORDER
), -UserGetSystemMetrics(SM_CYBORDER
));
1399 bti
->rcTitleBar
.top
+= pWindowObject
->Wnd
->WindowRect
.top
;
1400 bti
->rcTitleBar
.left
+= pWindowObject
->Wnd
->WindowRect
.left
;
1401 bti
->rcTitleBar
.right
+= pWindowObject
->Wnd
->WindowRect
.left
;
1403 bti
->rcTitleBar
.bottom
= bti
->rcTitleBar
.top
;
1404 if (dwExStyle
& WS_EX_TOOLWINDOW
)
1406 /* FIXME : Note this value should exists in pWindowObject for UserGetSystemMetrics(SM_CYSMCAPTION) */
1407 bti
->rcTitleBar
.bottom
+= UserGetSystemMetrics(SM_CYSMCAPTION
);
1411 /* FIXME : Note this value should exists in pWindowObject for UserGetSystemMetrics(SM_CYCAPTION) and UserGetSystemMetrics(SM_CXSIZE) */
1412 bti
->rcTitleBar
.bottom
+= UserGetSystemMetrics(SM_CYCAPTION
);
1413 bti
->rcTitleBar
.left
+= UserGetSystemMetrics(SM_CXSIZE
);
1416 if (dwStyle
& WS_CAPTION
)
1418 bti
->rgstate
[1] = STATE_SYSTEM_INVISIBLE
;
1419 if (dwStyle
& WS_SYSMENU
)
1421 if (!(dwStyle
& (WS_MINIMIZEBOX
|WS_MAXIMIZEBOX
)))
1423 bti
->rgstate
[2] = STATE_SYSTEM_INVISIBLE
;
1424 bti
->rgstate
[3] = STATE_SYSTEM_INVISIBLE
;
1428 if (!(dwStyle
& WS_MINIMIZEBOX
))
1430 bti
->rgstate
[2] = STATE_SYSTEM_UNAVAILABLE
;
1432 if (!(dwStyle
& WS_MAXIMIZEBOX
))
1434 bti
->rgstate
[3] = STATE_SYSTEM_UNAVAILABLE
;
1438 if (!(dwExStyle
& WS_EX_CONTEXTHELP
))
1440 bti
->rgstate
[4] = STATE_SYSTEM_INVISIBLE
;
1442 if (pWindowObject
->Wnd
->Class
->Style
& CS_NOCLOSE
)
1444 bti
->rgstate
[5] = STATE_SYSTEM_UNAVAILABLE
;
1449 bti
->rgstate
[2] = STATE_SYSTEM_INVISIBLE
;
1450 bti
->rgstate
[3] = STATE_SYSTEM_INVISIBLE
;
1451 bti
->rgstate
[4] = STATE_SYSTEM_INVISIBLE
;
1452 bti
->rgstate
[5] = STATE_SYSTEM_INVISIBLE
;
1457 bti
->rgstate
[0] |= STATE_SYSTEM_INVISIBLE
;
1462 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1469 /* FUNCTIONS *****************************************************************/
1477 NtUserBuildMenuItemList(
1485 DECLARE_RETURN(DWORD
);
1487 DPRINT("Enter NtUserBuildMenuItemList\n");
1488 UserEnterExclusive();
1490 if(!(Menu
= UserGetMenuObject(hMenu
)))
1497 res
= IntBuildMenuItemList(Menu
, Buffer
, nBufSize
);
1501 res
= Menu
->MenuInfo
.MenuItemCount
;
1507 DPRINT("Leave NtUserBuildMenuItemList, ret=%i\n",_ret_
);
1517 NtUserCheckMenuItem(
1523 DECLARE_RETURN(DWORD
);
1525 DPRINT("Enter NtUserCheckMenuItem\n");
1526 UserEnterExclusive();
1528 if(!(Menu
= UserGetMenuObject(hMenu
)))
1533 RETURN( IntCheckMenuItem(Menu
, uIDCheckItem
, uCheck
));
1536 DPRINT("Leave NtUserCheckMenuItem, ret=%i\n",_ret_
);
1542 HMENU FASTCALL
UserCreateMenu(BOOL PopupMenu
)
1544 PWINSTATION_OBJECT WinStaObject
;
1548 PEPROCESS CurrentProcess
= PsGetCurrentProcess();
1550 if (CsrProcess
!= CurrentProcess
)
1553 * CsrProcess does not have a Win32WindowStation
1557 Status
= IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation
,
1562 if (!NT_SUCCESS(Status
))
1564 DPRINT1("Validation of window station handle (0x%X) failed\n",
1565 CurrentProcess
->Win32WindowStation
);
1566 SetLastNtError(Status
);
1569 Menu
= IntCreateMenu(&Handle
, !PopupMenu
);
1570 ObDereferenceObject(WinStaObject
);
1574 Menu
= IntCreateMenu(&Handle
, !PopupMenu
);
1577 if (Menu
) UserDereferenceObject(Menu
);
1578 return (HMENU
)Handle
;
1592 DECLARE_RETURN(BOOL
);
1594 DPRINT("Enter NtUserDeleteMenu\n");
1595 UserEnterExclusive();
1597 if(!(Menu
= UserGetMenuObject(hMenu
)))
1602 RETURN( IntRemoveMenuItem(Menu
, uPosition
, uFlags
, TRUE
));
1605 DPRINT("Leave NtUserDeleteMenu, ret=%i\n",_ret_
);
1614 NtUserGetTitleBarInfo(
1618 PWINDOW_OBJECT WindowObject
;
1619 TITLEBARINFO bartitleinfo
;
1620 DECLARE_RETURN(BOOLEAN
);
1621 BOOLEAN retValue
= TRUE
;
1623 DPRINT("Enter NtUserGetTitleBarInfo\n");
1624 UserEnterExclusive();
1626 /* Vaildate the windows handle */
1627 if (!(WindowObject
= UserGetWindowObject(hwnd
)))
1629 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
1635 /* Copy our usermode buffer bti to local buffer bartitleinfo */
1636 ProbeForRead(bti
, sizeof(TITLEBARINFO
), 1);
1637 RtlCopyMemory(&bartitleinfo
, bti
, sizeof(TITLEBARINFO
));
1639 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1641 /* Fail copy the data */
1642 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1647 /* Get the tile bar info */
1650 retValue
= intGetTitleBarInfo(WindowObject
, &bartitleinfo
);
1655 /* Copy our buffer to user mode buffer bti */
1656 ProbeForWrite(bti
, sizeof(TITLEBARINFO
), 1);
1657 RtlCopyMemory(bti
, &bartitleinfo
, sizeof(TITLEBARINFO
));
1659 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1661 /* Fail copy the data */
1662 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1672 DPRINT("Leave NtUserGetTitleBarInfo, ret=%i\n",_ret_
);
1682 BOOL FASTCALL
UserDestroyMenu(HMENU hMenu
)
1686 if(!(Menu
= UserGetMenuObject(hMenu
)))
1691 if(Menu
->Process
!= PsGetCurrentProcess())
1693 SetLastWin32Error(ERROR_ACCESS_DENIED
);
1697 return IntDestroyMenuObject(Menu
, FALSE
, TRUE
);
1708 DECLARE_RETURN(BOOL
);
1710 DPRINT("Enter NtUserDestroyMenu\n");
1711 UserEnterExclusive();
1713 if(!(Menu
= UserGetMenuObject(hMenu
)))
1718 if(Menu
->Process
!= PsGetCurrentProcess())
1720 SetLastWin32Error(ERROR_ACCESS_DENIED
);
1724 RETURN( IntDestroyMenuObject(Menu
, TRUE
, TRUE
));
1727 DPRINT("Leave NtUserDestroyMenu, ret=%i\n",_ret_
);
1737 NtUserEnableMenuItem(
1743 DECLARE_RETURN(UINT
);
1745 DPRINT("Enter NtUserEnableMenuItem\n");
1746 UserEnterExclusive();
1748 if(!(Menu
= UserGetMenuObject(hMenu
)))
1753 RETURN( IntEnableMenuItem(Menu
, uIDEnableItem
, uEnable
));
1756 DPRINT("Leave NtUserEnableMenuItem, ret=%i\n",_ret_
);
1770 LPCMENUITEMINFOW UnsafeItemInfo
)
1774 ROSMENUITEMINFO ItemInfo
;
1775 DECLARE_RETURN(DWORD
);
1777 DPRINT("Enter UserInsertMenuItem\n");
1778 UserEnterExclusive();
1780 if(!(Menu
= UserGetMenuObject(hMenu
)))
1785 /* Try to copy the whole MENUITEMINFOW structure */
1786 Status
= MmCopyFromCaller(&ItemInfo
, UnsafeItemInfo
, sizeof(MENUITEMINFOW
));
1787 if (NT_SUCCESS(Status
))
1789 if (sizeof(MENUITEMINFOW
) != ItemInfo
.cbSize
1790 && FIELD_OFFSET(MENUITEMINFOW
, hbmpItem
) != ItemInfo
.cbSize
)
1792 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1795 RETURN( IntInsertMenuItem(Menu
, uItem
, fByPosition
, &ItemInfo
));
1798 /* Try to copy without last field (not present in older versions) */
1799 Status
= MmCopyFromCaller(&ItemInfo
, UnsafeItemInfo
, FIELD_OFFSET(MENUITEMINFOW
, hbmpItem
));
1800 if (NT_SUCCESS(Status
))
1802 if (FIELD_OFFSET(MENUITEMINFOW
, hbmpItem
) != ItemInfo
.cbSize
)
1804 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1807 ItemInfo
.hbmpItem
= (HBITMAP
)0;
1808 RETURN( IntInsertMenuItem(Menu
, uItem
, fByPosition
, &ItemInfo
));
1811 SetLastNtError(Status
);
1815 DPRINT("Leave UserInsertMenuItem, ret=%i\n",_ret_
);
1837 NtUserGetMenuDefaultItem(
1844 DECLARE_RETURN(UINT
);
1846 DPRINT("Enter NtUserGetMenuDefaultItem\n");
1847 UserEnterExclusive();
1849 if(!(Menu
= UserGetMenuObject(hMenu
)))
1854 RETURN( IntGetMenuDefaultItem(Menu
, fByPos
, gmdiFlags
, &gismc
));
1857 DPRINT("Leave NtUserGetMenuDefaultItem, ret=%i\n",_ret_
);
1867 NtUserGetMenuBarInfo(
1874 PMENU_OBJECT MenuObject
;
1876 PWINDOW_OBJECT WindowObject
;
1881 DECLARE_RETURN(BOOL
);
1883 DPRINT("Enter NtUserGetMenuBarInfo\n");
1886 if (!(WindowObject
= UserGetWindowObject(hwnd
)))
1888 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
1892 hMenu
= (HMENU
)WindowObject
->Wnd
->IDMenu
;
1894 if (!(MenuObject
= UserGetMenuObject(hMenu
)))
1896 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
1900 if (pmbi
->cbSize
!= sizeof(MENUBARINFO
))
1902 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1906 kmbi
.cbSize
= sizeof(MENUBARINFO
);
1907 kmbi
.fBarFocused
= FALSE
;
1908 kmbi
.fFocused
= FALSE
;
1909 kmbi
.hwndMenu
= NULL
;
1915 PMENU_OBJECT SubMenuObject
;
1917 if (idItem
) /* Non-Zero-Based. */
1919 if (IntGetMenuItemByFlag(MenuObject
, idItem
-1, MF_BYPOSITION
, NULL
, &mi
, NULL
) > -1)
1920 kmbi
.rcBar
= mi
->Rect
;
1929 /* If items is zero we assume info for the menu itself. */
1930 if (!(IntGetClientOrigin(WindowObject
, &Offset
)))
1935 Rect
.left
= Offset
.x
;
1936 Rect
.right
= Offset
.x
+ MenuObject
->MenuInfo
.Width
;
1937 Rect
.top
= Offset
.y
;
1938 Rect
.bottom
= Offset
.y
+ MenuObject
->MenuInfo
.Height
;
1940 DPRINT("Rect top = %d bottom = %d left = %d right = %d \n",
1941 Rect
.top
, Rect
.bottom
, Rect
.left
, Rect
.right
);
1945 if (idItem
-1 == MenuObject
->MenuInfo
.FocusedItem
)
1946 kmbi
.fFocused
= TRUE
;
1948 if (MenuObject
->MenuInfo
.FocusedItem
!= NO_SELECTED_ITEM
)
1949 kmbi
.fBarFocused
= TRUE
;
1950 SubMenuObject
= UserGetMenuObject(MenuObject
->MenuItemList
->hSubMenu
);
1951 if(SubMenuObject
) kmbi
.hwndMenu
= SubMenuObject
->MenuInfo
.Wnd
;
1952 DPRINT("OBJID_MENU, idItem = %d\n",idItem
);
1957 PMENU_OBJECT SubMenuObject
, XSubMenuObject
;
1958 SubMenuObject
= UserGetMenuObject(MenuObject
->MenuItemList
->hSubMenu
);
1959 if(SubMenuObject
) kmbi
.hMenu
= SubMenuObject
->MenuInfo
.Self
;
1963 DPRINT1("OBJID_CLIENT, No SubMenu!\n");
1968 if (IntGetMenuItemByFlag(SubMenuObject
, idItem
-1, MF_BYPOSITION
, NULL
, &mi
, NULL
) > -1)
1969 kmbi
.rcBar
= mi
->Rect
;
1978 PWINDOW_OBJECT SubWinObj
;
1979 if (!(SubWinObj
= UserGetWindowObject(SubMenuObject
->MenuInfo
.Wnd
)))
1984 if (!(IntGetClientOrigin(SubWinObj
, &Offset
)))
1989 Rect
.left
= Offset
.x
;
1990 Rect
.right
= Offset
.x
+ SubMenuObject
->MenuInfo
.Width
;
1991 Rect
.top
= Offset
.y
;
1992 Rect
.bottom
= Offset
.y
+ SubMenuObject
->MenuInfo
.Height
;
1997 if (idItem
-1 == SubMenuObject
->MenuInfo
.FocusedItem
)
1998 kmbi
.fFocused
= TRUE
;
2000 if (SubMenuObject
->MenuInfo
.FocusedItem
!= NO_SELECTED_ITEM
)
2001 kmbi
.fBarFocused
= TRUE
;
2002 XSubMenuObject
= UserGetMenuObject(SubMenuObject
->MenuItemList
->hSubMenu
);
2003 if (XSubMenuObject
) kmbi
.hwndMenu
= XSubMenuObject
->MenuInfo
.Wnd
;
2004 DPRINT("OBJID_CLIENT, idItem = %d\n",idItem
);
2009 PMENU_OBJECT SysMenuObject
, SubMenuObject
;
2010 if(!(SysMenuObject
= IntGetSystemMenu(WindowObject
, FALSE
, FALSE
)))
2015 kmbi
.hMenu
= SysMenuObject
->MenuInfo
.Self
;
2018 if (IntGetMenuItemByFlag(SysMenuObject
, idItem
-1, MF_BYPOSITION
, NULL
, &mi
, NULL
) > -1)
2019 kmbi
.rcBar
= mi
->Rect
;
2028 PWINDOW_OBJECT SysWinObj
;
2029 if (!(SysWinObj
= UserGetWindowObject(SysMenuObject
->MenuInfo
.Wnd
)))
2034 if (!(IntGetClientOrigin(SysWinObj
, &Offset
)))
2039 Rect
.left
= Offset
.x
;
2040 Rect
.right
= Offset
.x
+ SysMenuObject
->MenuInfo
.Width
;
2041 Rect
.top
= Offset
.y
;
2042 Rect
.bottom
= Offset
.y
+ SysMenuObject
->MenuInfo
.Height
;
2047 if (idItem
-1 == SysMenuObject
->MenuInfo
.FocusedItem
)
2048 kmbi
.fFocused
= TRUE
;
2050 if (SysMenuObject
->MenuInfo
.FocusedItem
!= NO_SELECTED_ITEM
)
2051 kmbi
.fBarFocused
= TRUE
;
2052 SubMenuObject
= UserGetMenuObject(SysMenuObject
->MenuItemList
->hSubMenu
);
2053 if(SubMenuObject
) kmbi
.hwndMenu
= SubMenuObject
->MenuInfo
.Wnd
;
2054 DPRINT("OBJID_SYSMENU, idItem = %d\n",idItem
);
2059 DPRINT1("Unknown idObject = %d, idItem = %d\n",idObject
,idItem
);
2063 NTSTATUS Status
= MmCopyToCaller(pmbi
, &kmbi
, sizeof(MENUBARINFO
));
2064 if (! NT_SUCCESS(Status
))
2066 SetLastNtError(Status
);
2073 DPRINT("Leave NtUserGetMenuBarInfo, ret=%i\n",_ret_
);
2097 NtUserGetMenuItemRect(
2104 PWINDOW_OBJECT ReferenceWnd
;
2109 PMENU_ITEM MenuItem
;
2110 DECLARE_RETURN(BOOL
);
2112 DPRINT("Enter NtUserGetMenuItemRect\n");
2115 if (!(Menu
= UserGetMenuObject(hMenu
)))
2120 if (IntGetMenuItemByFlag(Menu
, uItem
, MF_BYPOSITION
, NULL
, &MenuItem
, NULL
) > -1)
2121 Rect
= MenuItem
->Rect
;
2127 if(!UserMenuInfo(Menu
, &mi
, FALSE
))
2133 if (lprcItem
== NULL
) RETURN( FALSE
);
2135 if (!(ReferenceWnd
= UserGetWindowObject(mi
.Wnd
))) RETURN( FALSE
);
2137 if(MenuItem
->fType
& MF_POPUP
)
2139 XMove
= ReferenceWnd
->Wnd
->ClientRect
.left
;
2140 YMove
= ReferenceWnd
->Wnd
->ClientRect
.top
;
2144 XMove
= ReferenceWnd
->Wnd
->WindowRect
.left
;
2145 YMove
= ReferenceWnd
->Wnd
->WindowRect
.top
;
2150 Rect
.right
+= XMove
;
2151 Rect
.bottom
+= YMove
;
2153 Status
= MmCopyToCaller(lprcItem
, &Rect
, sizeof(RECT
));
2154 if (! NT_SUCCESS(Status
))
2156 SetLastNtError(Status
);
2162 DPRINT("Leave NtUserGetMenuItemRect, ret=%i\n",_ret_
);
2172 NtUserHiliteMenuItem(
2179 PWINDOW_OBJECT Window
;
2180 DECLARE_RETURN(BOOLEAN
);
2182 DPRINT("Enter NtUserHiliteMenuItem\n");
2183 UserEnterExclusive();
2185 if(!(Window
= UserGetWindowObject(hWnd
)))
2190 if(!(Menu
= UserGetMenuObject(hMenu
)))
2195 if(Window
->Wnd
->IDMenu
== (UINT
)hMenu
)
2197 RETURN( IntHiliteMenuItem(Window
, Menu
, uItemHilite
, uHilite
));
2203 DPRINT("Leave NtUserHiliteMenuItem, ret=%i\n",_ret_
);
2213 PROSMENUINFO UnsafeMenuInfo
,
2219 ROSMENUINFO MenuInfo
;
2221 Status
= MmCopyFromCaller(&Size
, &UnsafeMenuInfo
->cbSize
, sizeof(DWORD
));
2222 if (! NT_SUCCESS(Status
))
2224 SetLastNtError(Status
);
2227 if(Size
< sizeof(MENUINFO
) || sizeof(ROSMENUINFO
) < Size
)
2229 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
2232 Status
= MmCopyFromCaller(&MenuInfo
, UnsafeMenuInfo
, Size
);
2233 if (! NT_SUCCESS(Status
))
2235 SetLastNtError(Status
);
2242 Res
= IntSetMenuInfo(Menu
, &MenuInfo
);
2247 Res
= IntGetMenuInfo(Menu
, &MenuInfo
);
2250 Status
= MmCopyToCaller(UnsafeMenuInfo
, &MenuInfo
, Size
);
2251 if (! NT_SUCCESS(Status
))
2253 SetLastNtError(Status
);
2273 PROSMENUINFO UnsafeMenuInfo
,
2277 DECLARE_RETURN(BOOL
);
2279 DPRINT("Enter NtUserMenuInfo\n");
2282 if (!(Menu
= UserGetMenuObject(hMenu
)))
2287 RETURN(UserMenuInfo(Menu
, UnsafeMenuInfo
, SetOrGet
));
2290 DPRINT("Leave NtUserMenuInfo, ret=%i\n",_ret_
);
2301 NtUserMenuItemFromPoint(
2308 PWINDOW_OBJECT Window
= NULL
;
2311 DECLARE_RETURN(int);
2313 DPRINT("Enter NtUserMenuItemFromPoint\n");
2314 UserEnterExclusive();
2316 if (!(Menu
= UserGetMenuObject(hMenu
)))
2321 if (!(Window
= UserGetWindowObject(Menu
->MenuInfo
.Wnd
)))
2326 X
-= Window
->Wnd
->WindowRect
.left
;
2327 Y
-= Window
->Wnd
->WindowRect
.top
;
2329 mi
= Menu
->MenuItemList
;
2330 for (i
= 0; NULL
!= mi
; i
++)
2332 if (InRect(mi
->Rect
, X
, Y
))
2339 RETURN( (mi
? i
: NO_SELECTED_ITEM
));
2342 DPRINT("Leave NtUserMenuItemFromPoint, ret=%i\n",_ret_
);
2355 PROSMENUITEMINFO UnsafeItemInfo
,
2358 PMENU_ITEM MenuItem
;
2359 ROSMENUITEMINFO ItemInfo
;
2364 Status
= MmCopyFromCaller(&Size
, &UnsafeItemInfo
->cbSize
, sizeof(UINT
));
2365 if (! NT_SUCCESS(Status
))
2367 SetLastNtError(Status
);
2370 if (sizeof(MENUITEMINFOW
) != Size
2371 && FIELD_OFFSET(MENUITEMINFOW
, hbmpItem
) != Size
2372 && sizeof(ROSMENUITEMINFO
) != Size
)
2374 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
2377 Status
= MmCopyFromCaller(&ItemInfo
, UnsafeItemInfo
, Size
);
2378 if (! NT_SUCCESS(Status
))
2380 SetLastNtError(Status
);
2383 /* If this is a pre-0x0500 _WIN32_WINNT MENUITEMINFOW, you can't
2385 if (FIELD_OFFSET(MENUITEMINFOW
, hbmpItem
) == Size
2386 && 0 != (ItemInfo
.fMask
& MIIM_BITMAP
))
2388 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
2392 if (IntGetMenuItemByFlag(Menu
, Item
,
2393 (ByPosition
? MF_BYPOSITION
: MF_BYCOMMAND
),
2394 NULL
, &MenuItem
, NULL
) < 0)
2396 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
2402 Ret
= IntSetMenuItemInfo(Menu
, MenuItem
, &ItemInfo
);
2406 Ret
= IntGetMenuItemInfo(Menu
, MenuItem
, &ItemInfo
);
2409 Status
= MmCopyToCaller(UnsafeItemInfo
, &ItemInfo
, Size
);
2410 if (! NT_SUCCESS(Status
))
2412 SetLastNtError(Status
);
2432 PROSMENUITEMINFO UnsafeItemInfo
,
2436 DECLARE_RETURN(BOOL
);
2438 DPRINT("Enter NtUserMenuItemInfo\n");
2439 UserEnterExclusive();
2441 if (!(Menu
= UserGetMenuObject(hMenu
)))
2446 RETURN( UserMenuItemInfo(Menu
, Item
, ByPosition
, UnsafeItemInfo
, SetOrGet
));
2449 DPRINT("Leave NtUserMenuItemInfo, ret=%i\n",_ret_
);
2466 DECLARE_RETURN(BOOL
);
2468 DPRINT("Enter NtUserRemoveMenu\n");
2469 UserEnterExclusive();
2471 if(!(Menu
= UserGetMenuObject(hMenu
)))
2476 RETURN(IntRemoveMenuItem(Menu
, uPosition
, uFlags
, FALSE
));
2479 DPRINT("Leave NtUserRemoveMenu, ret=%i\n",_ret_
);
2490 NtUserSetMenuContextHelpId(
2492 DWORD dwContextHelpId
)
2495 DECLARE_RETURN(BOOL
);
2497 DPRINT("Enter NtUserSetMenuContextHelpId\n");
2498 UserEnterExclusive();
2500 if(!(Menu
= UserGetMenuObject(hMenu
)))
2505 RETURN(IntSetMenuContextHelpId(Menu
, dwContextHelpId
));
2508 DPRINT("Leave NtUserSetMenuContextHelpId, ret=%i\n",_ret_
);
2519 NtUserSetMenuDefaultItem(
2525 DECLARE_RETURN(BOOL
);
2527 DPRINT("Enter NtUserSetMenuDefaultItem\n");
2528 UserEnterExclusive();
2530 if(!(Menu
= UserGetMenuObject(hMenu
)))
2535 RETURN( UserSetMenuDefaultItem(Menu
, uItem
, fByPos
));
2538 DPRINT("Leave NtUserSetMenuDefaultItem, ret=%i\n",_ret_
);
2548 NtUserSetMenuFlagRtoL(
2552 DECLARE_RETURN(BOOL
);
2554 DPRINT("Enter NtUserSetMenuFlagRtoL\n");
2555 UserEnterExclusive();
2557 if(!(Menu
= UserGetMenuObject(hMenu
)))
2562 RETURN(IntSetMenuFlagRtoL(Menu
));
2565 DPRINT("Leave NtUserSetMenuFlagRtoL, ret=%i\n",_ret_
);
2575 NtUserThunkedMenuInfo(
2580 /* This function seems just to call SetMenuInfo() */
2589 NtUserThunkedMenuItemInfo(
2594 LPMENUITEMINFOW lpmii
,
2595 PUNICODE_STRING lpszCaption
)
2598 /* lpszCaption may be NULL, check for it and call RtlInitUnicodeString()
2599 if bInsert == TRUE call NtUserInsertMenuItem() else NtUserSetMenuItemInfo() */
2601 if (bInsert
) return UserInsertMenuItem(hMenu
, uItem
, fByPosition
, lpmii
);
2611 /* NOTE: unused function */
2613 NtUserTrackPopupMenuEx(