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.
19 /* $Id: menu.c,v 1.40 2004/01/24 08:26:25 ekohl Exp $
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 ******************************************************************/
31 #include <ddk/ntddk.h>
32 #include <win32k/win32k.h>
33 #include <napi/win32.h>
34 #include <include/menu.h>
35 #include <include/error.h>
36 #include <include/winsta.h>
37 #include <include/object.h>
38 #include <include/guicheck.h>
39 #include <include/window.h>
40 #include <include/color.h>
41 #include <internal/safe.h>
46 /* INTERNAL ******************************************************************/
48 /* maximum number of menu items a menu can contain */
49 #define MAX_MENU_ITEMS (0x4000)
50 #define MAX_GOINTOSUBMENU (0x10)
52 #define UpdateMenuItemState(state, change) \
54 if((change) & MFS_DISABLED) { \
55 (state) |= MFS_DISABLED; \
57 (state) &= ~MFS_DISABLED; \
59 if((change) & MFS_CHECKED) { \
60 (state) |= MFS_CHECKED; \
62 (state) &= ~MFS_CHECKED; \
64 if((change) & MFS_HILITE) { \
65 (state) |= MFS_HILITE; \
67 (state) &= ~MFS_HILITE; \
69 if((change) & MFS_DEFAULT) { \
70 (state) |= MFS_DEFAULT; \
72 (state) &= ~MFS_DEFAULT; \
76 #define FreeMenuText(MenuItem) \
78 if((MENU_ITEM_TYPE((MenuItem)->fType) == MF_STRING) && \
79 (MenuItem)->Text.Length) { \
80 RtlFreeUnicodeString(&(MenuItem)->Text); \
87 return(STATUS_SUCCESS
);
93 return(STATUS_SUCCESS
);
98 DumpMenuItemList(PMENU_ITEM MenuItem
)
103 if(MenuItem
->Text
.Length
)
104 DbgPrint(" %d. %wZ\n", ++cnt
, &MenuItem
->Text
);
106 DbgPrint(" %d. NO TEXT dwTypeData==%d\n", ++cnt
, (DWORD
)MenuItem
->Text
.Buffer
);
108 if(MFT_BITMAP
& MenuItem
->fType
) DbgPrint("MFT_BITMAP ");
109 if(MFT_MENUBARBREAK
& MenuItem
->fType
) DbgPrint("MFT_MENUBARBREAK ");
110 if(MFT_MENUBREAK
& MenuItem
->fType
) DbgPrint("MFT_MENUBREAK ");
111 if(MFT_OWNERDRAW
& MenuItem
->fType
) DbgPrint("MFT_OWNERDRAW ");
112 if(MFT_RADIOCHECK
& MenuItem
->fType
) DbgPrint("MFT_RADIOCHECK ");
113 if(MFT_RIGHTJUSTIFY
& MenuItem
->fType
) DbgPrint("MFT_RIGHTJUSTIFY ");
114 if(MFT_SEPARATOR
& MenuItem
->fType
) DbgPrint("MFT_SEPARATOR ");
115 if(MFT_STRING
& MenuItem
->fType
) DbgPrint("MFT_STRING ");
116 DbgPrint("\n fState=");
117 if(MFS_DISABLED
& MenuItem
->fState
) DbgPrint("MFS_DISABLED ");
118 else DbgPrint("MFS_ENABLED ");
119 if(MFS_CHECKED
& MenuItem
->fState
) DbgPrint("MFS_CHECKED ");
120 else DbgPrint("MFS_UNCHECKED ");
121 if(MFS_HILITE
& MenuItem
->fState
) DbgPrint("MFS_HILITE ");
122 else DbgPrint("MFS_UNHILITE ");
123 if(MFS_DEFAULT
& MenuItem
->fState
) DbgPrint("MFS_DEFAULT ");
124 if(MFS_GRAYED
& MenuItem
->fState
) DbgPrint("MFS_GRAYED ");
125 DbgPrint("\n wId=%d\n", MenuItem
->wID
);
126 MenuItem
= MenuItem
->Next
;
128 DbgPrint("Entries: %d\n", cnt
);
133 PMENU_OBJECT FASTCALL
134 IntGetMenuObject(HMENU hMenu
)
136 PMENU_OBJECT MenuObject
;
137 PW32PROCESS W32Process
= PsGetWin32Process();
144 NTSTATUS Status
= ObmReferenceObjectByHandle(W32Process
->
145 WindowStation
->HandleTable
, hMenu
, otMenu
,
146 (PVOID
*)&MenuObject
);
147 if (!NT_SUCCESS(Status
))
155 IntReleaseMenuObject(PMENU_OBJECT MenuObject
)
157 ObmDereferenceObject(MenuObject
);
161 IntFreeMenuItem(PMENU_OBJECT MenuObject
, PMENU_ITEM MenuItem
,
162 BOOL RemoveFromList
, BOOL bRecurse
)
164 FreeMenuText(MenuItem
);
167 /* FIXME - Remove from List */
168 MenuObject
->MenuItemCount
--;
170 if(bRecurse
&& MenuItem
->hSubMenu
)
172 PMENU_OBJECT SubMenuObject
;
173 SubMenuObject
= IntGetMenuObject(MenuItem
->hSubMenu
);
176 IntDestroyMenuObject(SubMenuObject
, bRecurse
, TRUE
);
177 IntReleaseMenuObject(SubMenuObject
);
182 ExFreePool(MenuItem
);
188 IntRemoveMenuItem(PMENU_OBJECT MenuObject
, UINT uPosition
, UINT uFlags
,
191 PMENU_ITEM PrevMenuItem
, MenuItem
;
192 if(IntGetMenuItemByFlag(MenuObject
, uPosition
, uFlags
, &MenuItem
,
198 PrevMenuItem
->Next
= MenuItem
->Next
;
201 MenuObject
->MenuItemList
= MenuItem
->Next
;
203 return IntFreeMenuItem(MenuObject
, MenuItem
, TRUE
, bRecurse
);
210 IntDeleteMenuItems(PMENU_OBJECT MenuObject
, BOOL bRecurse
)
214 PMENU_ITEM CurItem
= MenuObject
->MenuItemList
;
217 NextItem
= CurItem
->Next
;
218 IntFreeMenuItem(MenuObject
, CurItem
, FALSE
, bRecurse
);
222 MenuObject
->MenuItemCount
= 0;
223 MenuObject
->MenuItemList
= NULL
;
228 IntDestroyMenuObject(PMENU_OBJECT MenuObject
,
229 BOOL bRecurse
, BOOL RemoveFromProcess
)
233 /* remove all menu items */
234 ExAcquireFastMutexUnsafe (&MenuObject
->MenuItemsLock
);
235 IntDeleteMenuItems(MenuObject
, bRecurse
); /* do not destroy submenus */
236 ExReleaseFastMutexUnsafe (&MenuObject
->MenuItemsLock
);
238 if(RemoveFromProcess
)
240 ExAcquireFastMutexUnsafe(&MenuObject
->W32Process
->MenuListLock
);
241 RemoveEntryList(&MenuObject
->ListEntry
);
242 ExReleaseFastMutexUnsafe(&MenuObject
->W32Process
->MenuListLock
);
245 ObmCloseHandle(MenuObject
->W32Process
->WindowStation
->HandleTable
, MenuObject
->Self
);
252 PMENU_OBJECT FASTCALL
253 IntCreateMenu(PHANDLE Handle
)
255 PMENU_OBJECT MenuObject
;
256 PW32PROCESS Win32Process
= PsGetWin32Process();
258 MenuObject
= (PMENU_OBJECT
)ObmCreateObject(
259 Win32Process
->WindowStation
->HandleTable
, Handle
,
260 otMenu
, sizeof(MENU_OBJECT
));
268 MenuObject
->Self
= *Handle
;
269 MenuObject
->W32Process
= Win32Process
;
270 MenuObject
->RtoL
= FALSE
; /* default */
271 MenuObject
->MenuInfo
.cbSize
= sizeof(MENUINFO
); /* not used */
272 MenuObject
->MenuInfo
.fMask
= 0; /* not used */
273 MenuObject
->MenuInfo
.dwStyle
= 0; /* FIXME */
274 MenuObject
->MenuInfo
.cyMax
= 0; /* default */
275 MenuObject
->MenuInfo
.hbrBack
=
276 NtGdiCreateSolidBrush(RGB(192, 192, 192)); /* FIXME: default background color */
277 MenuObject
->MenuInfo
.dwContextHelpID
= 0; /* default */
278 MenuObject
->MenuInfo
.dwMenuData
= 0; /* default */
280 MenuObject
->MenuItemCount
= 0;
281 MenuObject
->MenuItemList
= NULL
;
282 ExInitializeFastMutex(&MenuObject
->MenuItemsLock
);
284 /* Insert menu item into process menu handle list */
285 ExAcquireFastMutexUnsafe(&Win32Process
->MenuListLock
);
286 InsertTailList(&Win32Process
->MenuListHead
, &MenuObject
->ListEntry
);
287 ExReleaseFastMutexUnsafe(&Win32Process
->MenuListLock
);
293 IntCloneMenuItems(PMENU_OBJECT Destination
, PMENU_OBJECT Source
)
295 PMENU_ITEM MenuItem
, NewMenuItem
= NULL
;
296 PMENU_ITEM Old
= NULL
;
298 if(!Source
->MenuItemCount
)
301 ExAcquireFastMutexUnsafe(&Destination
->MenuItemsLock
);
302 ExAcquireFastMutexUnsafe(&Source
->MenuItemsLock
);
304 MenuItem
= Source
->MenuItemList
;
309 NewMenuItem
->Next
= MenuItem
;
310 NewMenuItem
= ExAllocatePool(PagedPool
, sizeof(MENU_ITEM
));
313 NewMenuItem
->fType
= MenuItem
->fType
;
314 NewMenuItem
->fState
= MenuItem
->fState
;
315 NewMenuItem
->wID
= MenuItem
->wID
;
316 NewMenuItem
->hSubMenu
= MenuItem
->hSubMenu
;
317 NewMenuItem
->hbmpChecked
= MenuItem
->hbmpChecked
;
318 NewMenuItem
->hbmpUnchecked
= MenuItem
->hbmpUnchecked
;
319 NewMenuItem
->dwItemData
= MenuItem
->dwItemData
;
320 if((MENU_ITEM_TYPE(NewMenuItem
->fType
) == MF_STRING
))
322 if(MenuItem
->Text
.Length
)
324 NewMenuItem
->Text
.Length
= 0;
325 NewMenuItem
->Text
.MaximumLength
= MenuItem
->Text
.MaximumLength
;
326 NewMenuItem
->Text
.Buffer
= (PWSTR
)ExAllocatePool(PagedPool
, MenuItem
->Text
.MaximumLength
);
327 if(!NewMenuItem
->Text
.Buffer
)
329 ExFreePool(NewMenuItem
);
332 RtlCopyUnicodeString(&NewMenuItem
->Text
, &MenuItem
->Text
);
336 NewMenuItem
->Text
.Buffer
= MenuItem
->Text
.Buffer
;
341 NewMenuItem
->Text
.Buffer
= MenuItem
->Text
.Buffer
;
343 NewMenuItem
->hbmpItem
= MenuItem
->hbmpItem
;
345 NewMenuItem
->Next
= NULL
;
347 Old
->Next
= NewMenuItem
;
349 Destination
->MenuItemList
= NewMenuItem
;
350 Destination
->MenuItemCount
++;
351 MenuItem
= MenuItem
->Next
;
354 ExReleaseFastMutexUnsafe(&Source
->MenuItemsLock
);
355 ExReleaseFastMutexUnsafe(&Destination
->MenuItemsLock
);
359 PMENU_OBJECT FASTCALL
360 IntCloneMenu(PMENU_OBJECT Source
)
363 PMENU_OBJECT MenuObject
;
364 PW32PROCESS Process
= PsGetWin32Process();
369 MenuObject
= (PMENU_OBJECT
)ObmCreateObject(
370 Process
->WindowStation
->HandleTable
, &Handle
,
371 otMenu
, sizeof(MENU_OBJECT
));
375 MenuObject
->Self
= Handle
;
376 MenuObject
->W32Process
= Process
;
377 MenuObject
->RtoL
= Source
->RtoL
;
378 MenuObject
->MenuInfo
.cbSize
= sizeof(MENUINFO
); /* not used */
379 MenuObject
->MenuInfo
.fMask
= Source
->MenuInfo
.fMask
;
380 MenuObject
->MenuInfo
.dwStyle
= Source
->MenuInfo
.dwStyle
;
381 MenuObject
->MenuInfo
.cyMax
= Source
->MenuInfo
.cyMax
;
382 MenuObject
->MenuInfo
.hbrBack
= Source
->MenuInfo
.hbrBack
;
383 MenuObject
->MenuInfo
.dwContextHelpID
= Source
->MenuInfo
.dwContextHelpID
;
384 MenuObject
->MenuInfo
.dwMenuData
= Source
->MenuInfo
.dwMenuData
;
386 MenuObject
->MenuItemCount
= 0;
387 MenuObject
->MenuItemList
= NULL
;
388 ExInitializeFastMutex(&MenuObject
->MenuItemsLock
);
390 /* Insert menu item into process menu handle list */
391 ExAcquireFastMutexUnsafe(&Process
->MenuListLock
);
392 InsertTailList(&Process
->MenuListHead
, &MenuObject
->ListEntry
);
393 ExReleaseFastMutexUnsafe(&Process
->MenuListLock
);
395 IntCloneMenuItems(MenuObject
, Source
);
401 IntSetMenuFlagRtoL(PMENU_OBJECT MenuObject
)
403 MenuObject
->RtoL
= TRUE
;
408 IntSetMenuContextHelpId(PMENU_OBJECT MenuObject
, DWORD dwContextHelpId
)
410 MenuObject
->MenuInfo
.dwContextHelpID
= dwContextHelpId
;
415 IntGetMenuInfo(PMENU_OBJECT MenuObject
, LPMENUINFO lpmi
)
419 if(lpmi
->fMask
& MIM_BACKGROUND
)
420 lpmi
->hbrBack
= MenuObject
->MenuInfo
.hbrBack
;
421 if(lpmi
->fMask
& MIM_HELPID
)
422 lpmi
->dwContextHelpID
= MenuObject
->MenuInfo
.dwContextHelpID
;
423 if(lpmi
->fMask
& MIM_MAXHEIGHT
)
424 lpmi
->cyMax
= MenuObject
->MenuInfo
.cyMax
;
425 if(lpmi
->fMask
& MIM_MENUDATA
)
426 lpmi
->dwMenuData
= MenuObject
->MenuInfo
.dwMenuData
;
427 if(lpmi
->fMask
& MIM_STYLE
)
428 lpmi
->dwStyle
= MenuObject
->MenuInfo
.dwStyle
;
436 IntIsMenu(HMENU hMenu
)
440 if((Menu
= IntGetMenuObject(hMenu
)))
442 IntReleaseMenuObject(Menu
);
450 IntSetMenuInfo(PMENU_OBJECT MenuObject
, LPMENUINFO lpmi
)
452 if(lpmi
->fMask
& MIM_BACKGROUND
)
453 MenuObject
->MenuInfo
.hbrBack
= lpmi
->hbrBack
;
454 if(lpmi
->fMask
& MIM_HELPID
)
455 MenuObject
->MenuInfo
.dwContextHelpID
= lpmi
->dwContextHelpID
;
456 if(lpmi
->fMask
& MIM_MAXHEIGHT
)
457 MenuObject
->MenuInfo
.cyMax
= lpmi
->cyMax
;
458 if(lpmi
->fMask
& MIM_MENUDATA
)
459 MenuObject
->MenuInfo
.dwMenuData
= lpmi
->dwMenuData
;
460 if(lpmi
->fMask
& MIM_STYLE
)
461 MenuObject
->MenuInfo
.dwStyle
= lpmi
->dwStyle
;
462 if(lpmi
->fMask
& MIM_APPLYTOSUBMENUS
)
471 IntGetMenuItemByFlag(PMENU_OBJECT MenuObject
, UINT uSearchBy
, UINT fFlag
,
472 PMENU_ITEM
*MenuItem
, PMENU_ITEM
*PrevMenuItem
)
474 PMENU_ITEM PrevItem
= NULL
;
475 PMENU_ITEM CurItem
= MenuObject
->MenuItemList
;
477 if(MF_BYPOSITION
& fFlag
)
480 while(CurItem
&& (p
> 0))
483 CurItem
= CurItem
->Next
;
488 if(MenuItem
) *MenuItem
= CurItem
;
489 if(PrevMenuItem
) *PrevMenuItem
= PrevItem
;
493 if(MenuItem
) *MenuItem
= NULL
;
494 if(PrevMenuItem
) *PrevMenuItem
= NULL
; /* ? */
498 return uSearchBy
- p
;
505 if(CurItem
->wID
== uSearchBy
)
507 if(MenuItem
) *MenuItem
= CurItem
;
508 if(PrevMenuItem
) *PrevMenuItem
= PrevItem
;
512 CurItem
= CurItem
->Next
;
521 IntInsertMenuItemToList(PMENU_OBJECT MenuObject
, PMENU_ITEM MenuItem
, int pos
)
524 PMENU_ITEM LastItem
= NULL
;
527 CurItem
= MenuObject
->MenuItemList
;
533 CurItem
= CurItem
->Next
;
539 while(CurItem
&& (pos
> 0))
542 CurItem
= CurItem
->Next
;
552 /* insert the item before CurItem */
553 MenuItem
->Next
= LastItem
->Next
;
554 LastItem
->Next
= MenuItem
;
558 /* insert at the beginning */
559 MenuObject
->MenuItemList
= MenuItem
;
560 MenuItem
->Next
= CurItem
;
568 LastItem
->Next
= MenuItem
;
569 MenuItem
->Next
= NULL
;
573 /* insert first item */
574 MenuObject
->MenuItemList
= MenuItem
;
575 MenuItem
->Next
= NULL
;
578 MenuObject
->MenuItemCount
++;
584 IntGetMenuItemInfo(PMENU_OBJECT MenuObject
, PMENU_ITEM MenuItem
, LPMENUITEMINFOW lpmii
)
586 if(!MenuItem
|| !MenuObject
|| !lpmii
)
591 lpmii
->cch
= MenuItem
->Text
.Length
;
593 if(lpmii
->fMask
& MIIM_BITMAP
)
595 lpmii
->hbmpItem
= MenuItem
->hbmpItem
;
597 if(lpmii
->fMask
& MIIM_CHECKMARKS
)
599 lpmii
->hbmpChecked
= MenuItem
->hbmpChecked
;
600 lpmii
->hbmpUnchecked
= MenuItem
->hbmpUnchecked
;
602 if(lpmii
->fMask
& MIIM_DATA
)
604 lpmii
->dwItemData
= MenuItem
->dwItemData
;
606 if(lpmii
->fMask
& (MIIM_FTYPE
| MIIM_TYPE
))
608 lpmii
->fType
= MenuItem
->fType
;
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
;
627 IntSetMenuItemInfo(PMENU_OBJECT MenuObject
, PMENU_ITEM MenuItem
, LPCMENUITEMINFOW lpmii
)
629 PUNICODE_STRING Source
;
632 if(!MenuItem
|| !MenuObject
|| !lpmii
)
637 MenuItem
->fType
= lpmii
->fType
;
639 if(lpmii
->fMask
& MIIM_BITMAP
)
641 MenuItem
->hbmpItem
= lpmii
->hbmpItem
;
643 if(lpmii
->fMask
& MIIM_CHECKMARKS
)
645 MenuItem
->hbmpChecked
= lpmii
->hbmpChecked
;
646 MenuItem
->hbmpUnchecked
= lpmii
->hbmpUnchecked
;
648 if(lpmii
->fMask
& MIIM_DATA
)
650 MenuItem
->dwItemData
= lpmii
->dwItemData
;
652 if(lpmii
->fMask
& (MIIM_FTYPE
| MIIM_TYPE
))
654 MenuItem
->fType
= lpmii
->fType
;
656 if(lpmii
->fMask
& MIIM_ID
)
658 MenuItem
->wID
= lpmii
->wID
;
660 if(lpmii
->fMask
& MIIM_STATE
)
662 /* remove MFS_DEFAULT flag from all other menu items if this item
663 has the MFS_DEFAULT state */
664 if(lpmii
->fState
& MFS_DEFAULT
)
665 IntSetMenuDefaultItem(MenuObject
, -1, 0);
666 /* update the menu item state flags */
667 UpdateMenuItemState(MenuItem
->fState
, lpmii
->fState
);
670 if(lpmii
->fMask
& MIIM_SUBMENU
)
672 MenuItem
->hSubMenu
= lpmii
->hSubMenu
;
674 if((lpmii
->fMask
& (MIIM_TYPE
| MIIM_STRING
)) &&
675 (MENU_ITEM_TYPE(lpmii
->fType
) == MF_STRING
))
677 if(lpmii
->dwTypeData
&& lpmii
->cch
)
679 Source
= (PUNICODE_STRING
)lpmii
->dwTypeData
;
680 FreeMenuText(MenuItem
);
681 copylen
= min((UINT
)Source
->MaximumLength
, (lpmii
->cch
+ 1) * sizeof(WCHAR
));
682 MenuItem
->Text
.Buffer
= (PWSTR
)ExAllocatePool(PagedPool
, copylen
);
683 if(MenuItem
->Text
.Buffer
)
685 MenuItem
->Text
.Length
= 0;
686 MenuItem
->Text
.MaximumLength
= copylen
;
687 RtlCopyUnicodeString(&MenuItem
->Text
, Source
);
691 MenuItem
->Text
.Length
= 0;
692 MenuItem
->Text
.MaximumLength
= 0;
693 MenuItem
->Text
.Buffer
= NULL
;
698 FreeMenuText(MenuItem
);
699 MenuItem
->fType
= MF_SEPARATOR
;
704 RtlInitUnicodeString(&MenuItem
->Text
, NULL
);
711 IntInsertMenuItem(PMENU_OBJECT MenuObject
, UINT uItem
, BOOL fByPosition
,
712 LPCMENUITEMINFOW lpmii
)
714 int pos
= (int)uItem
;
717 if(MenuObject
->MenuItemCount
>= MAX_MENU_ITEMS
)
719 /* FIXME Set last error code? */
720 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
726 /* calculate position */
727 if(pos
> MenuObject
->MenuItemCount
)
728 pos
= MenuObject
->MenuItemCount
;
732 pos
= IntGetMenuItemByFlag(MenuObject
, uItem
, MF_BYCOMMAND
, NULL
, NULL
);
734 if(pos
< -1) pos
= -1;
736 MenuItem
= ExAllocatePool(PagedPool
, sizeof(MENU_ITEM
));
739 /* FIXME Set last error code? */
740 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
744 MenuItem
->fType
= MFT_STRING
;
745 MenuItem
->fState
= MFS_ENABLED
| MFS_UNCHECKED
;
747 MenuItem
->hSubMenu
= (HMENU
)0;
748 MenuItem
->hbmpChecked
= (HBITMAP
)0;
749 MenuItem
->hbmpUnchecked
= (HBITMAP
)0;
750 MenuItem
->dwItemData
= 0;
751 RtlInitUnicodeString(&MenuItem
->Text
, NULL
);
752 MenuItem
->hbmpItem
= (HBITMAP
)0;
754 if(!IntSetMenuItemInfo(MenuObject
, MenuItem
, lpmii
))
756 ExFreePool(MenuItem
);
760 pos
= IntInsertMenuItemToList(MenuObject
, MenuItem
, pos
);
766 IntEnableMenuItem(PMENU_OBJECT MenuObject
, UINT uIDEnableItem
, UINT uEnable
)
769 UINT res
= IntGetMenuItemByFlag(MenuObject
, uIDEnableItem
, uEnable
, &MenuItem
, NULL
);
770 if(!MenuItem
|| (res
== (UINT
)-1))
775 res
= MenuItem
->fState
& (MF_GRAYED
| MF_DISABLED
);
777 if(uEnable
& MF_DISABLED
)
779 if(!(MenuItem
->fState
& MF_DISABLED
))
780 MenuItem
->fState
|= MF_DISABLED
;
781 if(uEnable
& MF_GRAYED
)
783 if(!(MenuItem
->fState
& MF_GRAYED
))
784 MenuItem
->fState
|= MF_GRAYED
;
789 if(uEnable
& MF_GRAYED
)
791 if(!(MenuItem
->fState
& MF_GRAYED
))
792 MenuItem
->fState
|= MF_GRAYED
;
793 if(!(MenuItem
->fState
& MF_DISABLED
))
794 MenuItem
->fState
|= MF_DISABLED
;
798 if(MenuItem
->fState
& MF_DISABLED
)
799 MenuItem
->fState
^= MF_DISABLED
;
800 if(MenuItem
->fState
& MF_GRAYED
)
801 MenuItem
->fState
^= MF_GRAYED
;
810 IntBuildMenuItemList(PMENU_OBJECT MenuObject
, PVOID Buffer
, ULONG nMax
)
816 PMENU_ITEM CurItem
= MenuObject
->MenuItemList
;
819 sz
= sizeof(MENUITEMINFOW
) + sizeof(RECT
);
823 while(CurItem
&& (nMax
>= sz
))
825 mii
.cch
= CurItem
->Text
.Length
/ sizeof(WCHAR
);
826 mii
.dwItemData
= CurItem
->dwItemData
;
827 if(CurItem
->Text
.Length
)
828 mii
.dwTypeData
= NULL
;
830 mii
.dwTypeData
= (LPWSTR
)CurItem
->Text
.Buffer
;
831 mii
.fState
= CurItem
->fState
;
832 mii
.fType
= CurItem
->fType
;
833 mii
.hbmpChecked
= CurItem
->hbmpChecked
;
834 mii
.hbmpItem
= CurItem
->hbmpItem
;
835 mii
.hbmpUnchecked
= CurItem
->hbmpUnchecked
;
836 mii
.hSubMenu
= CurItem
->hSubMenu
;
837 RtlCopyMemory(Buf
, &mii
, sizeof(MENUITEMINFOW
));
838 Buf
+= sizeof(MENUITEMINFOW
);
839 RtlCopyMemory(Buf
, &CurItem
->Rect
, sizeof(RECT
));
843 if(CurItem
->Text
.Length
&& (nMax
>= CurItem
->Text
.Length
+ sizeof(WCHAR
)))
846 RtlCopyMemory(Buf
, (LPWSTR
)CurItem
->Text
.Buffer
, CurItem
->Text
.Length
);
847 Buf
+= CurItem
->Text
.Length
+ sizeof(WCHAR
);
848 nMax
-= CurItem
->Text
.Length
+ sizeof(WCHAR
);
853 CurItem
= CurItem
->Next
;
861 res
+= sizeof(MENUITEMINFOW
) + sizeof(RECT
);
862 res
+= CurItem
->Text
.Length
+ sizeof(WCHAR
);
863 CurItem
= CurItem
->Next
;
871 IntCheckMenuItem(PMENU_OBJECT MenuObject
, UINT uIDCheckItem
, UINT uCheck
)
876 if((IntGetMenuItemByFlag(MenuObject
, uIDCheckItem
, uCheck
, &MenuItem
, NULL
) < 0) || !MenuItem
)
881 res
= (DWORD
)(MenuItem
->fState
& MF_CHECKED
);
882 if(uCheck
& MF_CHECKED
)
884 if(!(MenuItem
->fState
& MF_CHECKED
))
885 MenuItem
->fState
|= MF_CHECKED
;
889 if(MenuItem
->fState
& MF_CHECKED
)
890 MenuItem
->fState
^= MF_CHECKED
;
897 IntHiliteMenuItem(PWINDOW_OBJECT WindowObject
, PMENU_OBJECT MenuObject
,
898 UINT uItemHilite
, UINT uHilite
)
901 BOOL res
= IntGetMenuItemByFlag(MenuObject
, uItemHilite
, uHilite
, &MenuItem
, NULL
);
902 if(!MenuItem
|| !res
)
907 if(uHilite
& MF_HILITE
)
909 if(!(MenuItem
->fState
& MF_HILITE
))
910 MenuItem
->fState
|= MF_HILITE
;
914 if(MenuItem
->fState
& MF_HILITE
)
915 MenuItem
->fState
^= MF_HILITE
;
918 /* FIXME - update the window's menu */
924 IntSetMenuDefaultItem(PMENU_OBJECT MenuObject
, UINT uItem
, UINT fByPos
)
927 PMENU_ITEM MenuItem
= MenuObject
->MenuItemList
;
929 if(uItem
== (UINT
)-1)
933 if(MenuItem
->fState
& MFS_DEFAULT
)
934 MenuItem
->fState
^= MFS_DEFAULT
;
935 MenuItem
= MenuItem
->Next
;
947 if(!(MenuItem
->fState
& MFS_DEFAULT
))
948 MenuItem
->fState
|= MFS_DEFAULT
;
953 if(MenuItem
->fState
& MFS_DEFAULT
)
954 MenuItem
->fState
^= MFS_DEFAULT
;
957 MenuItem
= MenuItem
->Next
;
964 if(!ret
&& (MenuItem
->wID
== uItem
))
966 if(!(MenuItem
->fState
& MFS_DEFAULT
))
967 MenuItem
->fState
|= MFS_DEFAULT
;
972 if(MenuItem
->fState
& MFS_DEFAULT
)
973 MenuItem
->fState
^= MFS_DEFAULT
;
975 MenuItem
= MenuItem
->Next
;
983 IntGetMenuDefaultItem(PMENU_OBJECT MenuObject
, UINT fByPos
, UINT gmdiFlags
,
989 PMENU_OBJECT SubMenuObject
;
990 PMENU_ITEM MenuItem
= MenuObject
->MenuItemList
;
994 if(MenuItem
->fState
& MFS_DEFAULT
)
997 if(!(gmdiFlags
& GMDI_USEDISABLED
) && (MenuItem
->fState
& MFS_DISABLED
))
1000 if(fByPos
& MF_BYPOSITION
)
1003 res
= MenuItem
->wID
;
1005 if((*gismc
< MAX_GOINTOSUBMENU
) && (gmdiFlags
& GMDI_GOINTOPOPUPS
) &&
1009 SubMenuObject
= IntGetMenuObject(MenuItem
->hSubMenu
);
1010 if(!SubMenuObject
|| (SubMenuObject
== MenuObject
))
1013 ExAcquireFastMutexUnsafe(&SubMenuObject
->MenuItemsLock
);
1014 ExReleaseFastMutexUnsafe(&MenuObject
->MenuItemsLock
);
1017 sres
= IntGetMenuDefaultItem(SubMenuObject
, fByPos
, gmdiFlags
, gismc
);
1020 ExReleaseFastMutexUnsafe(&SubMenuObject
->MenuItemsLock
);
1021 ExAcquireFastMutexUnsafe(&MenuObject
->MenuItemsLock
);
1022 IntReleaseMenuObject(SubMenuObject
);
1031 MenuItem
= MenuItem
->Next
;
1040 IntTrackPopupMenu(PMENU_OBJECT MenuObject
, PWINDOW_OBJECT WindowObject
,
1041 UINT Flags
, POINT
*Pos
, UINT MenuPos
, RECT
*ExcludeRect
)
1045 DbgPrint("IntTrackPopupMenu: unimplemented\n");
1046 SetLastWin32Error(ERROR_CALL_NOT_IMPLEMENTED
);
1053 * Internal function. Called when the process is destroyed to free the remaining menu handles.
1056 IntCleanupMenus(struct _EPROCESS
*Process
, PW32PROCESS Win32Process
)
1058 PEPROCESS CurrentProcess
;
1059 PLIST_ENTRY LastHead
= NULL
;
1060 PMENU_OBJECT MenuObject
;
1062 CurrentProcess
= PsGetCurrentProcess();
1063 if (CurrentProcess
!= Process
)
1065 KeAttachProcess(Process
);
1068 ExAcquireFastMutexUnsafe(&Win32Process
->MenuListLock
);
1069 while (Win32Process
->MenuListHead
.Flink
!= &(Win32Process
->MenuListHead
) &&
1070 Win32Process
->MenuListHead
.Flink
!= LastHead
)
1072 LastHead
= Win32Process
->MenuListHead
.Flink
;
1073 MenuObject
= CONTAINING_RECORD(Win32Process
->MenuListHead
.Flink
, MENU_OBJECT
, ListEntry
);
1075 ExReleaseFastMutexUnsafe(&Win32Process
->MenuListLock
);
1076 IntDestroyMenuObject(MenuObject
, FALSE
, TRUE
);
1077 ExAcquireFastMutexUnsafe(&Win32Process
->MenuListLock
);
1079 ExReleaseFastMutexUnsafe(&Win32Process
->MenuListLock
);
1081 if (CurrentProcess
!= Process
)
1088 /* FUNCTIONS *****************************************************************/
1096 NtUserBuildMenuItemList(
1103 PMENU_OBJECT MenuObject
= IntGetMenuObject(hMenu
);
1106 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
1112 ExAcquireFastMutexUnsafe(&MenuObject
->MenuItemsLock
);
1113 res
= IntBuildMenuItemList(MenuObject
, Buffer
, nBufSize
);
1114 ExReleaseFastMutexUnsafe(&MenuObject
->MenuItemsLock
);
1118 res
= MenuObject
->MenuItemCount
;
1121 IntReleaseMenuObject(MenuObject
);
1131 NtUserCheckMenuItem(
1137 PMENU_OBJECT MenuObject
= IntGetMenuObject(hmenu
);
1140 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
1143 ExAcquireFastMutexUnsafe(&MenuObject
->MenuItemsLock
);
1144 res
= IntCheckMenuItem(MenuObject
, uIDCheckItem
, uCheck
);
1145 ExReleaseFastMutexUnsafe(&MenuObject
->MenuItemsLock
);
1146 IntReleaseMenuObject(MenuObject
);
1155 NtUserCreateMenu(VOID
)
1157 PWINSTATION_OBJECT WinStaObject
;
1160 NTSTATUS Status
= IntValidateWindowStationHandle(PROCESS_WINDOW_STATION(),
1165 if (!NT_SUCCESS(Status
))
1167 DPRINT("Validation of window station handle (0x%X) failed\n",
1168 PROCESS_WINDOW_STATION());
1169 SetLastNtError(Status
);
1173 IntCreateMenu(&Handle
);
1175 ObDereferenceObject(WinStaObject
);
1176 return (HMENU
)Handle
;
1190 PMENU_OBJECT MenuObject
= IntGetMenuObject(hMenu
);
1193 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
1197 res
= IntRemoveMenuItem(MenuObject
, uPosition
, uFlags
, TRUE
);
1198 IntReleaseMenuObject(MenuObject
);
1213 PMENU_OBJECT MenuObject
= IntGetMenuObject(hMenu
);
1216 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
1219 if(MenuObject
->W32Process
!= PsGetWin32Process())
1221 IntReleaseMenuObject(MenuObject
);
1222 SetLastWin32Error(ERROR_ACCESS_DENIED
);
1226 Ret
= IntDestroyMenuObject(MenuObject
, FALSE
, TRUE
);
1228 IntReleaseMenuObject(MenuObject
);
1237 NtUserEnableMenuItem(
1242 UINT res
= (UINT
)-1;
1243 PMENU_OBJECT MenuObject
;
1244 MenuObject
= IntGetMenuObject(hMenu
);
1247 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
1250 ExAcquireFastMutexUnsafe(&MenuObject
->MenuItemsLock
);
1251 res
= IntEnableMenuItem(MenuObject
, uIDEnableItem
, uEnable
);
1252 ExReleaseFastMutexUnsafe(&MenuObject
->MenuItemsLock
);
1253 IntReleaseMenuObject(MenuObject
);
1263 NtUserInsertMenuItem(
1267 LPCMENUITEMINFOW lpmii
)
1270 PMENU_OBJECT MenuObject
;
1271 MenuObject
= IntGetMenuObject(hMenu
);
1274 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
1277 ExAcquireFastMutexUnsafe(&MenuObject
->MenuItemsLock
);
1278 res
= IntInsertMenuItem(MenuObject
, uItem
, fByPosition
, lpmii
);
1279 ExReleaseFastMutexUnsafe(&MenuObject
->MenuItemsLock
);
1280 IntReleaseMenuObject(MenuObject
);
1301 NtUserGetMenuDefaultItem(
1306 PMENU_OBJECT MenuObject
;
1309 MenuObject
= IntGetMenuObject(hMenu
);
1312 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
1315 ExAcquireFastMutexUnsafe(&MenuObject
->MenuItemsLock
);
1316 res
= IntGetMenuDefaultItem(MenuObject
, fByPos
, gmdiFlags
, &gismc
);
1317 ExReleaseFastMutexUnsafe(&MenuObject
->MenuItemsLock
);
1318 IntReleaseMenuObject(MenuObject
);
1327 NtUserGetMenuBarInfo(
1357 NtUserGetMenuItemRect(
1373 NtUserHiliteMenuItem(
1380 PMENU_OBJECT MenuObject
;
1381 PWINDOW_OBJECT WindowObject
= IntGetWindowObject(hwnd
);
1384 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1387 MenuObject
= IntGetMenuObject(hmenu
);
1390 IntReleaseWindowObject(WindowObject
);
1391 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
1394 if(WindowObject
->IDMenu
== (UINT
)hmenu
)
1396 ExAcquireFastMutexUnsafe(&MenuObject
->MenuItemsLock
);
1397 res
= IntHiliteMenuItem(WindowObject
, MenuObject
, uItemHilite
, uHilite
);
1398 ExReleaseFastMutexUnsafe(&MenuObject
->MenuItemsLock
);
1400 IntReleaseMenuObject(MenuObject
);
1401 IntReleaseWindowObject(WindowObject
);
1417 PMENU_OBJECT MenuObject
;
1419 if(lpmi
->cbSize
!= sizeof(MENUINFO
))
1421 /* FIXME - Set Last Error */
1424 MenuObject
= IntGetMenuObject(hmenu
);
1427 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
1433 res
= IntSetMenuInfo(MenuObject
, lpmi
);
1438 res
= IntGetMenuInfo(MenuObject
, lpmi
);
1440 IntReleaseMenuObject(MenuObject
);
1449 NtUserMenuItemFromPoint(
1470 LPMENUITEMINFOW lpmii
,
1473 PMENU_OBJECT MenuObject
;
1474 PMENU_ITEM MenuItem
;
1475 MENUITEMINFOW Safemii
;
1478 MenuObject
= IntGetMenuObject(hMenu
);
1481 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
1487 /* Set menu item info */
1491 if((IntGetMenuItemByFlag(MenuObject
, uItem
, (fByPosition
? MF_BYPOSITION
: MF_BYCOMMAND
),
1492 &MenuItem
, NULL
) > -1) &&
1493 IntGetMenuItemInfo(MenuObject
, MenuItem
, &Safemii
))
1495 Status
= MmCopyToCaller(lpmii
, &Safemii
, sizeof(MENUITEMINFOW
));
1496 if(!NT_SUCCESS(Status
))
1498 IntReleaseMenuObject(MenuObject
);
1499 SetLastNtError(Status
);
1503 IntReleaseMenuObject(MenuObject
);
1508 IntReleaseMenuObject(MenuObject
);
1523 PMENU_OBJECT MenuObject
= IntGetMenuObject(hMenu
);
1526 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
1530 res
= IntRemoveMenuItem(MenuObject
, uPosition
, uFlags
, FALSE
);
1531 IntReleaseMenuObject(MenuObject
);
1541 NtUserSetMenuContextHelpId(
1543 DWORD dwContextHelpId
)
1546 PMENU_OBJECT MenuObject
= IntGetMenuObject(hmenu
);
1549 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
1553 res
= IntSetMenuContextHelpId(MenuObject
, dwContextHelpId
);
1554 IntReleaseMenuObject(MenuObject
);
1563 NtUserSetMenuDefaultItem(
1569 PMENU_OBJECT MenuObject
;
1570 MenuObject
= IntGetMenuObject(hMenu
);
1573 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
1576 ExAcquireFastMutexUnsafe(&MenuObject
->MenuItemsLock
);
1577 res
= IntSetMenuDefaultItem(MenuObject
, uItem
, fByPos
);
1578 ExReleaseFastMutexUnsafe(&MenuObject
->MenuItemsLock
);
1579 IntReleaseMenuObject(MenuObject
);
1589 NtUserSetMenuFlagRtoL(
1593 PMENU_OBJECT MenuObject
= IntGetMenuObject(hMenu
);
1596 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
1600 res
= IntSetMenuFlagRtoL(MenuObject
);
1601 IntReleaseMenuObject(MenuObject
);
1610 NtUserThunkedMenuInfo(
1615 /* This function seems just to call SetMenuInfo() */
1624 NtUserThunkedMenuItemInfo(
1629 LPMENUITEMINFOW lpmii
,
1630 PUNICODE_STRING lpszCaption
)
1633 /* lpszCaption may be NULL, check for it and call RtlInitUnicodeString()
1634 if bInsert == TRUE call NtUserInsertMenuItem() else NtUserSetMenuItemInfo()
1644 NtUserTrackPopupMenuEx(
1652 PMENU_OBJECT MenuObject
;
1653 PWINDOW_OBJECT WindowObject
;
1659 MenuObject
= IntGetMenuObject(hmenu
);
1662 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
1666 WindowObject
= IntGetWindowObject(hwnd
);
1669 IntReleaseMenuObject(MenuObject
);
1670 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1676 Status
= MmCopyFromCaller(&Safetpm
, lptpm
, sizeof(TPMPARAMS
));
1677 if(!NT_SUCCESS(Status
))
1679 IntReleaseWindowObject(WindowObject
);
1680 IntReleaseMenuObject(MenuObject
);
1681 SetLastNtError(Status
);
1684 if(Safetpm
.cbSize
!= sizeof(TPMPARAMS
))
1686 IntReleaseWindowObject(WindowObject
);
1687 IntReleaseMenuObject(MenuObject
);
1688 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1696 Ret
= IntTrackPopupMenu(MenuObject
, WindowObject
, fuFlags
, &Pos
, 0,
1697 (lptpm
? &Safetpm
.rcExclude
: NULL
));
1699 IntReleaseWindowObject(WindowObject
);
1700 IntReleaseMenuObject(MenuObject
);