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.20 2003/08/20 13:02:32 weiden 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>
45 /* INTERNAL ******************************************************************/
47 /* maximum number of menu items a menu can contain */
48 #define MAX_MENU_ITEMS (0x4000)
49 #define MAX_GOINTOSUBMENU (0x10)
52 #define MIIM_STRING (0x00000040)
55 #define MIIM_BITMAP (0x00000080)
58 #define MIIM_FTYPE (0x00000100)
61 #define UpdateMenuItemState(state, change) \
63 if((change) & MFS_DISABLED) { \
64 if(!((state) & MFS_DISABLED)) (state) |= MFS_DISABLED; \
66 if((state) & MFS_DISABLED) (state) ^= MFS_DISABLED; \
68 if((change) & MFS_CHECKED) { \
69 if(!((state) & MFS_CHECKED)) (state) |= MFS_CHECKED; \
71 if((state) & MFS_CHECKED) (state) ^= MFS_CHECKED; \
73 if((change) & MFS_HILITE) { \
74 if(!((state) & MFS_HILITE)) (state) |= MFS_HILITE; \
76 if((state) & MFS_HILITE) (state) ^= MFS_HILITE; \
78 if(((change) & MFS_DEFAULT) && !((state) & MFS_DEFAULT)) { \
79 (state) |= MFS_DEFAULT; \
80 } else if(((state) & MFS_DEFAULT) && !((change) & MFS_DEFAULT)) { \
81 (state) ^= MFS_DEFAULT; \
85 #define FreeMenuText(MenuItem) \
87 if((MENU_ITEM_TYPE((MenuItem)->fType) == MF_STRING) && \
88 (MenuItem)->dwTypeData) { \
89 ExFreePool((MenuItem)->dwTypeData); \
90 (MenuItem)->dwTypeData = 0; \
91 (MenuItem)->cch = 0; \
98 return(STATUS_SUCCESS
);
102 CleanupMenuImpl(VOID
)
104 return(STATUS_SUCCESS
);
109 DumpMenuItemList(PMENU_ITEM MenuItem
)
114 if(MenuItem
->dwTypeData
)
115 DbgPrint(" %d. %ws\n", ++cnt
, (LPWSTR
)MenuItem
->dwTypeData
);
117 DbgPrint(" %d. NO TEXT dwTypeData==%d\n", ++cnt
, MenuItem
->dwTypeData
);
119 if(MFT_BITMAP
& MenuItem
->fType
) DbgPrint("MFT_BITMAP ");
120 if(MFT_MENUBARBREAK
& MenuItem
->fType
) DbgPrint("MFT_MENUBARBREAK ");
121 if(MFT_MENUBREAK
& MenuItem
->fType
) DbgPrint("MFT_MENUBREAK ");
122 if(MFT_OWNERDRAW
& MenuItem
->fType
) DbgPrint("MFT_OWNERDRAW ");
123 if(MFT_RADIOCHECK
& MenuItem
->fType
) DbgPrint("MFT_RADIOCHECK ");
124 if(MFT_RIGHTJUSTIFY
& MenuItem
->fType
) DbgPrint("MFT_RIGHTJUSTIFY ");
125 if(MFT_SEPARATOR
& MenuItem
->fType
) DbgPrint("MFT_SEPARATOR ");
126 if(MFT_STRING
& MenuItem
->fType
) DbgPrint("MFT_STRING ");
127 DbgPrint("\n fState=");
128 if(MFS_DISABLED
& MenuItem
->fState
) DbgPrint("MFS_DISABLED ");
129 else DbgPrint("MFS_ENABLED ");
130 if(MFS_CHECKED
& MenuItem
->fState
) DbgPrint("MFS_CHECKED ");
131 else DbgPrint("MFS_UNCHECKED ");
132 if(MFS_HILITE
& MenuItem
->fState
) DbgPrint("MFS_HILITE ");
133 else DbgPrint("MFS_UNHILITE ");
134 if(MFS_DEFAULT
& MenuItem
->fState
) DbgPrint("MFS_DEFAULT ");
135 if(MFS_GRAYED
& MenuItem
->fState
) DbgPrint("MFS_GRAYED ");
136 DbgPrint("\n wId=%d\n", MenuItem
->wID
);
137 MenuItem
= MenuItem
->Next
;
139 DbgPrint("Entries: %d\n", cnt
);
144 PMENU_OBJECT FASTCALL
145 IntGetMenuObject(HMENU hMenu
)
147 PMENU_OBJECT MenuObject
;
148 NTSTATUS Status
= ObmReferenceObjectByHandle(PsGetWin32Process()->
149 WindowStation
->HandleTable
, hMenu
, otMenu
,
150 (PVOID
*)&MenuObject
);
151 if (!NT_SUCCESS(Status
))
159 IntReleaseMenuObject(PMENU_OBJECT MenuObject
)
161 ObmDereferenceObject(MenuObject
);
165 IntFreeMenuItem(PMENU_OBJECT MenuObject
, PMENU_ITEM MenuItem
,
166 BOOL RemoveFromList
, BOOL bRecurse
)
168 FreeMenuText(MenuItem
);
171 /* FIXME - Remove from List */
172 MenuObject
->MenuItemCount
--;
174 if(bRecurse
&& MenuItem
->hSubMenu
)
176 PMENU_OBJECT SubMenuObject
;
177 SubMenuObject
= (PMENU_OBJECT
)IntGetWindowObject(
178 MenuItem
->hSubMenu
);
181 IntDestroyMenuObject(SubMenuObject
, bRecurse
);
186 ExFreePool(MenuItem
);
192 IntRemoveMenuItem(PMENU_OBJECT MenuObject
, UINT uPosition
, UINT uFlags
,
195 PMENU_ITEM PrevMenuItem
, MenuItem
;
196 if(IntGetMenuItemByFlag(MenuObject
, uPosition
, uFlags
, &MenuItem
,
202 PrevMenuItem
->Next
= MenuItem
->Next
;
205 MenuObject
->MenuItemList
= MenuItem
->Next
;
207 return IntFreeMenuItem(MenuObject
, MenuItem
, TRUE
, bRecurse
);
214 IntDeleteMenuItems(PMENU_OBJECT MenuObject
, BOOL bRecurse
)
218 PMENU_ITEM CurItem
= MenuObject
->MenuItemList
;
221 NextItem
= CurItem
->Next
;
222 IntFreeMenuItem(MenuObject
, CurItem
, FALSE
, bRecurse
);
226 MenuObject
->MenuItemCount
= 0;
227 MenuObject
->MenuItemList
= NULL
;
232 IntDestroyMenuObject(PMENU_OBJECT MenuObject
, BOOL bRecurse
)
234 PW32PROCESS W32Process
;
238 W32Process
= PsGetWin32Process();
239 /* remove all menu items */
240 ExAcquireFastMutexUnsafe (&MenuObject
->MenuItemsLock
);
241 IntDeleteMenuItems(MenuObject
, bRecurse
); /* do not destroy submenus */
242 ExReleaseFastMutexUnsafe (&MenuObject
->MenuItemsLock
);
244 ExAcquireFastMutexUnsafe(&W32Process
->MenuListLock
);
245 RemoveEntryList(&MenuObject
->ListEntry
);
246 ExReleaseFastMutexUnsafe(&W32Process
->MenuListLock
);
248 IntReleaseMenuObject(MenuObject
); // needed?
250 ObmCloseHandle(W32Process
->WindowStation
->HandleTable
, MenuObject
->Self
);
257 PMENU_OBJECT FASTCALL
258 IntCreateMenu(PHANDLE Handle
)
260 PW32PROCESS Win32Process
= PsGetWin32Process();
262 PMENU_OBJECT MenuObject
= (PMENU_OBJECT
)ObmCreateObject(
263 Win32Process
->WindowStation
->HandleTable
, Handle
,
264 otMenu
, sizeof(MENU_OBJECT
));
272 MenuObject
->Self
= *Handle
;
273 MenuObject
->RtoL
= FALSE
; /* default */
274 MenuObject
->MenuInfo
.cbSize
= sizeof(MENUINFO
); /* not used */
275 MenuObject
->MenuInfo
.fMask
= 0; /* not used */
276 MenuObject
->MenuInfo
.dwStyle
= 0; /* FIXME */
277 MenuObject
->MenuInfo
.cyMax
= 0; /* default */
278 MenuObject
->MenuInfo
.hbrBack
= NtGdiGetSysColorBrush(COLOR_MENU
); /*default background color */
279 MenuObject
->MenuInfo
.dwContextHelpID
= 0; /* default */
280 MenuObject
->MenuInfo
.dwMenuData
= 0; /* default */
282 MenuObject
->MenuItemCount
= 0;
283 MenuObject
->MenuItemList
= NULL
;
284 ExInitializeFastMutex(&MenuObject
->MenuItemsLock
);
286 /* Insert menu item into process menu handle list */
287 ExAcquireFastMutexUnsafe (&Win32Process
->MenuListLock
);
288 InsertTailList (&Win32Process
->MenuListHead
, &MenuObject
->ListEntry
);
289 ExReleaseFastMutexUnsafe (&Win32Process
->MenuListLock
);
295 IntSetMenuFlagRtoL(PMENU_OBJECT MenuObject
)
299 MenuObject
->RtoL
= TRUE
;
306 IntSetMenuContextHelpId(PMENU_OBJECT MenuObject
, DWORD dwContextHelpId
)
310 MenuObject
->MenuInfo
.dwContextHelpID
= dwContextHelpId
;
317 IntGetMenuInfo(PMENU_OBJECT MenuObject
, LPMENUINFO lpmi
)
321 if(lpmi
->fMask
& MIM_BACKGROUND
)
322 lpmi
->hbrBack
= MenuObject
->MenuInfo
.hbrBack
;
323 if(lpmi
->fMask
& MIM_HELPID
)
324 lpmi
->dwContextHelpID
= MenuObject
->MenuInfo
.dwContextHelpID
;
325 if(lpmi
->fMask
& MIM_MAXHEIGHT
)
326 lpmi
->cyMax
= MenuObject
->MenuInfo
.cyMax
;
327 if(lpmi
->fMask
& MIM_MENUDATA
)
328 lpmi
->dwMenuData
= MenuObject
->MenuInfo
.dwMenuData
;
329 if(lpmi
->fMask
& MIM_STYLE
)
330 lpmi
->dwStyle
= MenuObject
->MenuInfo
.dwStyle
;
337 IntSetMenuInfo(PMENU_OBJECT MenuObject
, LPMENUINFO lpmi
)
341 if(lpmi
->fMask
& MIM_BACKGROUND
)
342 MenuObject
->MenuInfo
.hbrBack
= lpmi
->hbrBack
;
343 if(lpmi
->fMask
& MIM_HELPID
)
344 MenuObject
->MenuInfo
.dwContextHelpID
= lpmi
->dwContextHelpID
;
345 if(lpmi
->fMask
& MIM_MAXHEIGHT
)
346 MenuObject
->MenuInfo
.cyMax
= lpmi
->cyMax
;
347 if(lpmi
->fMask
& MIM_MENUDATA
)
348 MenuObject
->MenuInfo
.dwMenuData
= lpmi
->dwMenuData
;
349 if(lpmi
->fMask
& MIM_STYLE
)
350 MenuObject
->MenuInfo
.dwStyle
= lpmi
->dwStyle
;
351 if(lpmi
->fMask
& MIM_APPLYTOSUBMENUS
)
362 IntGetMenuItemByFlag(PMENU_OBJECT MenuObject
, UINT uSearchBy
, UINT fFlag
,
363 PMENU_ITEM
*MenuItem
, PMENU_ITEM
*PrevMenuItem
)
365 PMENU_ITEM PrevItem
= NULL
;
366 PMENU_ITEM CurItem
= MenuObject
->MenuItemList
;
368 if(MF_BYPOSITION
& fFlag
)
371 while(CurItem
&& (p
> 0))
374 CurItem
= CurItem
->Next
;
379 if(MenuItem
) *MenuItem
= CurItem
;
380 if(PrevMenuItem
) *PrevMenuItem
= PrevItem
;
384 if(MenuItem
) *MenuItem
= NULL
;
385 if(PrevMenuItem
) *PrevMenuItem
= NULL
; /* ? */
389 return uSearchBy
- p
;
396 if(CurItem
->wID
== uSearchBy
)
398 if(MenuItem
) *MenuItem
= CurItem
;
399 if(PrevMenuItem
) *PrevMenuItem
= PrevItem
;
403 CurItem
= CurItem
->Next
;
412 IntInsertMenuItemToList(PMENU_OBJECT MenuObject
, PMENU_ITEM MenuItem
, int pos
)
415 PMENU_ITEM LastItem
= NULL
;
418 CurItem
= MenuObject
->MenuItemList
;
424 CurItem
= CurItem
->Next
;
430 while(CurItem
&& (pos
> 0))
433 CurItem
= CurItem
->Next
;
443 /* insert the item before CurItem */
444 MenuItem
->Next
= LastItem
->Next
;
445 LastItem
->Next
= MenuItem
;
449 /* insert at the beginning */
450 MenuObject
->MenuItemList
= MenuItem
;
451 MenuItem
->Next
= CurItem
;
458 /* insert at the end */
459 LastItem
->Next
= MenuItem
;
460 MenuItem
->Next
= NULL
;
464 /* insert first item */
465 MenuObject
->MenuItemList
= MenuItem
;
466 MenuItem
->Next
= NULL
;
469 MenuObject
->MenuItemCount
++;
475 IntSetMenuItemInfo(PMENU_OBJECT MenuObject
, PMENU_ITEM MenuItem
, LPCMENUITEMINFOW lpmii
)
477 if(!MenuItem
|| !MenuObject
|| !lpmii
)
482 /*if((MenuItem->fMask & (MIIM_TYPE | MIIM_STRING)) &&
483 (MENU_ITEM_TYPE(MenuItem->fType) == MF_STRING) &&
484 MenuItem->dwTypeData)
487 ExFreePool(MenuItem->dwTypeData);
488 MenuItem->dwTypeData = 0;
492 MenuItem
->fType
= lpmii
->fType
;
493 MenuItem
->cch
= lpmii
->cch
;
495 if(lpmii
->fMask
& MIIM_BITMAP
)
497 MenuItem
->hbmpItem
= lpmii
->hbmpItem
;
499 if(lpmii
->fMask
& MIIM_CHECKMARKS
)
501 MenuItem
->hbmpChecked
= lpmii
->hbmpChecked
;
502 MenuItem
->hbmpUnchecked
= lpmii
->hbmpUnchecked
;
504 if(lpmii
->fMask
& MIIM_DATA
)
506 MenuItem
->dwItemData
= lpmii
->dwItemData
;
508 if(lpmii
->fMask
& (MIIM_FTYPE
| MIIM_TYPE
))
510 MenuItem
->fType
= lpmii
->fType
;
512 if(lpmii
->fMask
& MIIM_ID
)
514 MenuItem
->wID
= lpmii
->wID
;
516 if(lpmii
->fMask
& MIIM_STATE
)
518 if(lpmii
->fState
& MFS_DEFAULT
)
519 IntSetMenuDefaultItem(MenuObject
, -1, 0);
520 UpdateMenuItemState(MenuItem
->fState
, lpmii
->fState
);
523 if(lpmii
->fMask
& MIIM_SUBMENU
)
525 MenuItem
->hSubMenu
= lpmii
->hSubMenu
;
527 if((lpmii
->fMask
& (MIIM_TYPE
| MIIM_STRING
)) &&
528 (MENU_ITEM_TYPE(lpmii
->fType
) == MF_STRING
) && lpmii
->dwTypeData
)
530 FreeMenuText(MenuItem
);
531 MenuItem
->dwTypeData
= (LPWSTR
)ExAllocatePool(PagedPool
, (lpmii
->cch
+ 1) * sizeof(WCHAR
));
532 if(!MenuItem
->dwTypeData
)
535 /* FIXME Set last error code? */
536 SetLastWin32Error(STATUS_NO_MEMORY
);
539 MenuItem
->cch
= lpmii
->cch
;
540 memcpy(MenuItem
->dwTypeData
, lpmii
->dwTypeData
, (lpmii
->cch
+ 1) * sizeof(WCHAR
));
547 IntInsertMenuItem(PMENU_OBJECT MenuObject
, UINT uItem
, WINBOOL fByPosition
,
548 LPCMENUITEMINFOW lpmii
)
550 int pos
= (int)uItem
;
553 if(MenuObject
->MenuItemCount
>= MAX_MENU_ITEMS
)
555 /* FIXME Set last error code? */
556 SetLastWin32Error(STATUS_NO_MEMORY
);
562 /* calculate position */
563 if(pos
> MenuObject
->MenuItemCount
)
564 pos
= MenuObject
->MenuItemCount
;
568 pos
= IntGetMenuItemByFlag(MenuObject
, uItem
, MF_BYCOMMAND
, NULL
, NULL
);
570 if(pos
< -1) pos
= -1;
572 MenuItem
= ExAllocatePool(PagedPool
, sizeof(MENU_ITEM
));
575 /* FIXME Set last error code? */
576 SetLastWin32Error(STATUS_NO_MEMORY
);
580 MenuItem
->fType
= MFT_STRING
;
581 MenuItem
->fState
= MFS_ENABLED
| MFS_UNCHECKED
;
583 MenuItem
->hSubMenu
= (HMENU
)0;
584 MenuItem
->hbmpChecked
= (HBITMAP
)0;
585 MenuItem
->hbmpUnchecked
= (HBITMAP
)0;
586 MenuItem
->dwItemData
= (ULONG_PTR
)NULL
;
588 MenuItem
->hbmpItem
= (HBITMAP
)0;
590 if(!IntSetMenuItemInfo(MenuObject
, MenuItem
, lpmii
))
592 ExFreePool(MenuItem
);
596 pos
= IntInsertMenuItemToList(MenuObject
, MenuItem
, pos
);
602 IntEnableMenuItem(PMENU_OBJECT MenuObject
, UINT uIDEnableItem
, UINT uEnable
)
605 UINT res
= IntGetMenuItemByFlag(MenuObject
, uIDEnableItem
, uEnable
, &MenuItem
, NULL
);
606 if(!MenuItem
|| (res
== (UINT
)-1))
611 res
= MenuItem
->fState
& (MF_GRAYED
| MF_DISABLED
);
613 if(uEnable
& MF_DISABLED
)
615 if(!(MenuItem
->fState
& MF_DISABLED
))
616 MenuItem
->fState
|= MF_DISABLED
;
617 if(uEnable
& MF_GRAYED
)
619 if(!(MenuItem
->fState
& MF_GRAYED
))
620 MenuItem
->fState
|= MF_GRAYED
;
625 if(uEnable
& MF_GRAYED
)
627 if(!(MenuItem
->fState
& MF_GRAYED
))
628 MenuItem
->fState
|= MF_GRAYED
;
629 if(!(MenuItem
->fState
& MF_DISABLED
))
630 MenuItem
->fState
|= MF_DISABLED
;
634 if(MenuItem
->fState
& MF_DISABLED
)
635 MenuItem
->fState
^= MF_DISABLED
;
636 if(MenuItem
->fState
& MF_GRAYED
)
637 MenuItem
->fState
^= MF_GRAYED
;
646 IntBuildMenuItemList(PMENU_OBJECT MenuObject, MENUITEMINFOW *lpmiil, ULONG nMax)
649 PMENU_ITEM CurItem = MenuObject->MenuItemList;
650 while(CurItem && (nMax > 0))
652 memcpy(&lpmiil[Index], &CurItem->MenuItem, sizeof(MENUITEMINFOW));
653 CurItem = CurItem->Next;
662 IntCheckMenuItem(PMENU_OBJECT MenuObject
, UINT uIDCheckItem
, UINT uCheck
)
667 if((IntGetMenuItemByFlag(MenuObject
, uIDCheckItem
, uCheck
, &MenuItem
, NULL
) < 0) || !MenuItem
)
672 res
= (DWORD
)(MenuItem
->fState
& MF_CHECKED
);
673 if(uCheck
& MF_CHECKED
)
675 if(!(MenuItem
->fState
& MF_CHECKED
))
676 MenuItem
->fState
|= MF_CHECKED
;
680 if(MenuItem
->fState
& MF_CHECKED
)
681 MenuItem
->fState
^= MF_CHECKED
;
688 IntHiliteMenuItem(PWINDOW_OBJECT WindowObject
, PMENU_OBJECT MenuObject
,
689 UINT uItemHilite
, UINT uHilite
)
692 BOOL res
= IntGetMenuItemByFlag(MenuObject
, uItemHilite
, uHilite
, &MenuItem
, NULL
);
693 if(!MenuItem
|| !res
)
698 if(uHilite
& MF_HILITE
)
700 if(!(MenuItem
->fState
& MF_HILITE
))
701 MenuItem
->fState
|= MF_HILITE
;
705 if(MenuItem
->fState
& MF_HILITE
)
706 MenuItem
->fState
^= MF_HILITE
;
709 /* FIXME - update the window's menu */
715 IntSetMenuDefaultItem(PMENU_OBJECT MenuObject
, UINT uItem
, UINT fByPos
)
718 PMENU_ITEM MenuItem
= MenuObject
->MenuItemList
;
724 if(MenuItem
->fState
& MFS_DEFAULT
)
725 MenuItem
->fState
^= MFS_DEFAULT
;
726 MenuItem
= MenuItem
->Next
;
738 if(!(MenuItem
->fState
& MFS_DEFAULT
))
739 MenuItem
->fState
|= MFS_DEFAULT
;
744 if(MenuItem
->fState
& MFS_DEFAULT
)
745 MenuItem
->fState
^= MFS_DEFAULT
;
748 MenuItem
= MenuItem
->Next
;
755 if(!ret
&& (MenuItem
->wID
== uItem
))
757 if(!(MenuItem
->fState
& MFS_DEFAULT
))
758 MenuItem
->fState
|= MFS_DEFAULT
;
763 if(MenuItem
->fState
& MFS_DEFAULT
)
764 MenuItem
->fState
^= MFS_DEFAULT
;
766 MenuItem
= MenuItem
->Next
;
774 IntGetMenuDefaultItem(PMENU_OBJECT MenuObject
, UINT fByPos
, UINT gmdiFlags
,
780 PMENU_OBJECT SubMenuObject
;
781 PMENU_ITEM MenuItem
= MenuObject
->MenuItemList
;
785 if(MenuItem
->fState
& MFS_DEFAULT
)
787 if(!(gmdiFlags
& GMDI_USEDISABLED
) && (MenuItem
->fState
& MFS_DISABLED
))
790 if(fByPos
& MF_BYPOSITION
)
796 if((*gismc
< MAX_GOINTOSUBMENU
) && (gmdiFlags
& GMDI_GOINTOPOPUPS
) &&
800 SubMenuObject
= IntGetMenuObject(MenuItem
->hSubMenu
);
801 if(!SubMenuObject
|| (SubMenuObject
== MenuObject
))
804 ExAcquireFastMutexUnsafe(&SubMenuObject
->MenuItemsLock
);
805 ExReleaseFastMutexUnsafe(&MenuObject
->MenuItemsLock
);
808 sres
= IntGetMenuDefaultItem(SubMenuObject
, fByPos
, gmdiFlags
, gismc
);
811 ExReleaseFastMutexUnsafe(&SubMenuObject
->MenuItemsLock
);
812 ExAcquireFastMutexUnsafe(&MenuObject
->MenuItemsLock
);
813 IntReleaseMenuObject(SubMenuObject
);
822 MenuItem
= MenuItem
->Next
;
830 * Internal function. Called when the process is destroyed to free the remaining menu handles.
833 IntCleanupMenus(struct _EPROCESS
*Process
, PW32PROCESS Win32Process
)
835 PEPROCESS CurrentProcess
;
836 PLIST_ENTRY LastHead
= NULL
;
837 PMENU_OBJECT MenuObject
;
839 CurrentProcess
= PsGetCurrentProcess();
840 if (CurrentProcess
!= Process
)
842 KeAttachProcess(Process
);
845 ExAcquireFastMutexUnsafe(&Win32Process
->MenuListLock
);
846 while (Win32Process
->MenuListHead
.Flink
!= &(Win32Process
->MenuListHead
) &&
847 Win32Process
->MenuListHead
.Flink
!= LastHead
)
849 LastHead
= Win32Process
->MenuListHead
.Flink
;
850 MenuObject
= CONTAINING_RECORD(Win32Process
->MenuListHead
.Flink
, MENU_OBJECT
, ListEntry
);
852 ExReleaseFastMutexUnsafe(&Win32Process
->MenuListLock
);
853 IntDestroyMenuObject(MenuObject
, FALSE
);
854 ExAcquireFastMutexUnsafe(&Win32Process
->MenuListLock
);
856 ExReleaseFastMutexUnsafe(&Win32Process
->MenuListLock
);
858 if (CurrentProcess
!= Process
)
865 /* FUNCTIONS *****************************************************************/
873 NtUserBuildMenuItemList(
875 LPCMENUITEMINFOW
* lpmiil
,
880 PMENU_OBJECT MenuObject
= IntGetMenuObject(hMenu
);
883 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
889 /* FIXME need to pass the menu strings to user32 somehow....
891 ExAcquireFastMutexUnsafe(&MenuObject->MenuItemsLock);
892 res = IntBuildMenuItemList(MenuObject, lpmiil, nBufSize / sizeof(LPCMENUITEMINFO));
893 ExReleaseFastMutexUnsafe(&MenuObject->MenuItemsLock);
898 res
= MenuObject
->MenuItemCount
;
901 IntReleaseMenuObject(MenuObject
);
917 PMENU_OBJECT MenuObject
= IntGetMenuObject(hmenu
);
920 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
923 ExAcquireFastMutexUnsafe(&MenuObject
->MenuItemsLock
);
924 res
= IntCheckMenuItem(MenuObject
, uIDCheckItem
, uCheck
);
925 ExReleaseFastMutexUnsafe(&MenuObject
->MenuItemsLock
);
926 IntReleaseMenuObject(MenuObject
);
935 NtUserCreateMenu(VOID
)
937 PWINSTATION_OBJECT WinStaObject
;
940 NTSTATUS Status
= ValidateWindowStationHandle(PROCESS_WINDOW_STATION(),
945 if (!NT_SUCCESS(Status
))
947 DPRINT("Validation of window station handle (0x%X) failed\n",
948 PROCESS_WINDOW_STATION());
949 SetLastWin32Error(Status
);
953 IntCreateMenu(&Handle
);
954 ObDereferenceObject(WinStaObject
);
955 return (HMENU
)Handle
;
969 PMENU_OBJECT MenuObject
= IntGetMenuObject(hMenu
);
972 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
976 res
= IntRemoveMenuItem(MenuObject
, uPosition
, uFlags
, TRUE
);
977 IntReleaseMenuObject(MenuObject
);
990 /* FIXME, check if menu belongs to the process */
992 PMENU_OBJECT MenuObject
= IntGetMenuObject(hMenu
);
995 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
999 return IntDestroyMenuObject(MenuObject
, FALSE
);
1007 NtUserEnableMenuItem(
1012 UINT res
= (UINT
)-1;
1013 PMENU_OBJECT MenuObject
;
1014 MenuObject
= IntGetMenuObject(hMenu
);
1017 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
1020 ExAcquireFastMutexUnsafe(&MenuObject
->MenuItemsLock
);
1021 res
= IntEnableMenuItem(MenuObject
, uIDEnableItem
, uEnable
);
1022 ExReleaseFastMutexUnsafe(&MenuObject
->MenuItemsLock
);
1023 IntReleaseMenuObject(MenuObject
);
1033 NtUserInsertMenuItem(
1036 WINBOOL fByPosition
,
1037 LPCMENUITEMINFOW lpmii
)
1040 PMENU_OBJECT MenuObject
;
1041 MenuObject
= IntGetMenuObject(hMenu
);
1044 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
1047 ExAcquireFastMutexUnsafe(&MenuObject
->MenuItemsLock
);
1048 res
= IntInsertMenuItem(MenuObject
, uItem
, fByPosition
, lpmii
);
1049 ExReleaseFastMutexUnsafe(&MenuObject
->MenuItemsLock
);
1050 IntReleaseMenuObject(MenuObject
);
1071 NtUserGetMenuDefaultItem(
1076 PMENU_OBJECT MenuObject
;
1079 MenuObject
= IntGetMenuObject(hMenu
);
1082 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
1085 ExAcquireFastMutexUnsafe(&MenuObject
->MenuItemsLock
);
1086 res
= IntGetMenuDefaultItem(MenuObject
, fByPos
, gmdiFlags
, &gismc
);
1087 ExReleaseFastMutexUnsafe(&MenuObject
->MenuItemsLock
);
1088 IntReleaseMenuObject(MenuObject
);
1097 NtUserGetMenuBarInfo(
1127 NtUserGetMenuItemRect(
1143 NtUserHiliteMenuItem(
1150 PMENU_OBJECT MenuObject
;
1151 PWINDOW_OBJECT WindowObject
= IntGetWindowObject(hwnd
);
1154 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1157 MenuObject
= IntGetMenuObject(hmenu
);
1160 IntReleaseWindowObject(WindowObject
);
1161 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
1164 if(WindowObject
->Menu
== hmenu
)
1166 ExAcquireFastMutexUnsafe(&MenuObject
->MenuItemsLock
);
1167 res
= IntHiliteMenuItem(WindowObject
, MenuObject
, uItemHilite
, uHilite
);
1168 ExReleaseFastMutexUnsafe(&MenuObject
->MenuItemsLock
);
1170 IntReleaseMenuObject(MenuObject
);
1171 IntReleaseWindowObject(WindowObject
);
1187 PMENU_OBJECT MenuObject
;
1189 if(lpmi
->cbSize
!= sizeof(MENUINFO
))
1191 /* FIXME - Set Last Error */
1194 MenuObject
= IntGetMenuObject(hmenu
);
1197 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
1203 res
= IntSetMenuInfo(MenuObject
, lpmi
);
1208 res
= IntGetMenuInfo(MenuObject
, lpmi
);
1210 IntReleaseMenuObject(MenuObject
);
1219 NtUserMenuItemFromPoint(
1240 LPMENUITEMINFOW lpmii
,
1259 PMENU_OBJECT MenuObject
= IntGetMenuObject(hMenu
);
1262 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
1266 res
= IntRemoveMenuItem(MenuObject
, uPosition
, uFlags
, FALSE
);
1267 IntReleaseMenuObject(MenuObject
);
1277 NtUserSetMenuContextHelpId(
1279 DWORD dwContextHelpId
)
1282 PMENU_OBJECT MenuObject
= IntGetMenuObject(hmenu
);
1285 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
1289 res
= IntSetMenuContextHelpId(MenuObject
, dwContextHelpId
);
1290 IntReleaseMenuObject(MenuObject
);
1299 NtUserSetMenuDefaultItem(
1305 PMENU_OBJECT MenuObject
;
1306 MenuObject
= IntGetMenuObject(hMenu
);
1309 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
1312 ExAcquireFastMutexUnsafe(&MenuObject
->MenuItemsLock
);
1313 res
= IntSetMenuDefaultItem(MenuObject
, uItem
, fByPos
);
1314 ExReleaseFastMutexUnsafe(&MenuObject
->MenuItemsLock
);
1315 IntReleaseMenuObject(MenuObject
);
1325 NtUserSetMenuFlagRtoL(
1329 PMENU_OBJECT MenuObject
= IntGetMenuObject(hMenu
);
1332 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE
);
1336 res
= IntSetMenuFlagRtoL(MenuObject
);
1337 IntReleaseMenuObject(MenuObject
);
1346 NtUserThunkedMenuInfo(
1351 /* This function seems just to call SetMenuInfo() */
1360 NtUserThunkedMenuItemInfo(
1365 LPMENUITEMINFOW lpmii
,
1366 PUNICODE_STRING lpszCaption
)
1369 /* lpszCaption may be NULL, check for it and call RtlInitUnicodeString()
1370 if bInsert == TRUE call NtUserInsertMenuItem() else NtUserSetMenuItemInfo()
1380 NtUserTrackPopupMenuEx(