2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
5 * FILE: subsys/win32k/ntuser/menu.c
6 * PROGRAMER: Thomas Weidenmueller (w3seek@users.sourceforge.net)
10 DBG_DEFAULT_CHANNEL(UserMenu
);
12 /* INTERNAL ******************************************************************/
14 /* maximum allowed depth of any branch in the menu tree.
15 * This value is slightly larger than in windows (25) to
16 * stay on the safe side. */
17 #define MAXMENUDEPTH 30
19 #define MNS_STYLE_MASK (MNS_NOCHECK|MNS_MODELESS|MNS_DRAGDROP|MNS_AUTODISMISS|MNS_NOTIFYBYPOS|MNS_CHECKORBMP)
21 #define MENUITEMINFO_TYPE_MASK \
22 (MFT_STRING | MFT_BITMAP | MFT_OWNERDRAW | MFT_SEPARATOR | \
23 MFT_MENUBARBREAK | MFT_MENUBREAK | MFT_RADIOCHECK | \
24 MFT_RIGHTORDER | MFT_RIGHTJUSTIFY /* same as MF_HELP */ )
26 /* Maximum number of menu items a menu can contain */
27 #define MAX_MENU_ITEMS (0x4000)
28 #define MAX_GOINTOSUBMENU (0x10)
30 #define UpdateMenuItemState(state, change) \
32 if((change) & MFS_DISABLED) { \
33 (state) |= MFS_DISABLED; \
35 (state) &= ~MFS_DISABLED; \
37 if((change) & MFS_CHECKED) { \
38 (state) |= MFS_CHECKED; \
40 (state) &= ~MFS_CHECKED; \
42 if((change) & MFS_HILITE) { \
43 (state) |= MFS_HILITE; \
45 (state) &= ~MFS_HILITE; \
47 if((change) & MFS_DEFAULT) { \
48 (state) |= MFS_DEFAULT; \
50 (state) &= ~MFS_DEFAULT; \
52 if((change) & MF_MOUSESELECT) { \
53 (state) |= MF_MOUSESELECT; \
55 (state) &= ~MF_MOUSESELECT; \
59 #define FreeMenuText(Menu,MenuItem) \
61 if((MENU_ITEM_TYPE((MenuItem)->fType) == MF_STRING) && \
62 (MenuItem)->lpstr.Length) { \
63 DesktopHeapFree(((PMENU)Menu)->head.rpdesk, (MenuItem)->lpstr.Buffer); \
68 PMENU FASTCALL
UserGetMenuObject(HMENU hMenu
)
74 EngSetLastError(ERROR_INVALID_MENU_HANDLE
);
78 Menu
= (PMENU
)UserGetObject(gHandleTable
, hMenu
, TYPE_MENU
);
81 EngSetLastError(ERROR_INVALID_MENU_HANDLE
);
91 DumpMenuItemList(PITEM MenuItem
)
96 if(MenuItem
->lpstr
.Length
)
97 DbgPrint(" %d. %wZ\n", ++cnt
, &MenuItem
->lpstr
);
99 DbgPrint(" %d. NO TEXT dwTypeData==%d\n", ++cnt
, (DWORD
)MenuItem
->lpstr
.Buffer
);
101 if(MFT_BITMAP
& MenuItem
->fType
)
102 DbgPrint("MFT_BITMAP ");
103 if(MFT_MENUBARBREAK
& MenuItem
->fType
)
104 DbgPrint("MFT_MENUBARBREAK ");
105 if(MFT_MENUBREAK
& MenuItem
->fType
)
106 DbgPrint("MFT_MENUBREAK ");
107 if(MFT_OWNERDRAW
& MenuItem
->fType
)
108 DbgPrint("MFT_OWNERDRAW ");
109 if(MFT_RADIOCHECK
& MenuItem
->fType
)
110 DbgPrint("MFT_RADIOCHECK ");
111 if(MFT_RIGHTJUSTIFY
& MenuItem
->fType
)
112 DbgPrint("MFT_RIGHTJUSTIFY ");
113 if(MFT_SEPARATOR
& MenuItem
->fType
)
114 DbgPrint("MFT_SEPARATOR ");
115 if(MFT_STRING
& MenuItem
->fType
)
116 DbgPrint("MFT_STRING ");
117 DbgPrint("\n fState=");
118 if(MFS_DISABLED
& MenuItem
->fState
)
119 DbgPrint("MFS_DISABLED ");
121 DbgPrint("MFS_ENABLED ");
122 if(MFS_CHECKED
& MenuItem
->fState
)
123 DbgPrint("MFS_CHECKED ");
125 DbgPrint("MFS_UNCHECKED ");
126 if(MFS_HILITE
& MenuItem
->fState
)
127 DbgPrint("MFS_HILITE ");
129 DbgPrint("MFS_UNHILITE ");
130 if(MFS_DEFAULT
& MenuItem
->fState
)
131 DbgPrint("MFS_DEFAULT ");
132 if(MFS_GRAYED
& MenuItem
->fState
)
133 DbgPrint("MFS_GRAYED ");
134 DbgPrint("\n wId=%d\n", MenuItem
->wID
);
135 MenuItem
= MenuItem
->Next
;
137 DbgPrint("Entries: %d\n", cnt
);
143 IntGetMenuObject(HMENU hMenu
)
145 PMENU Menu
= UserGetMenuObject(hMenu
);
147 Menu
->head
.cLockObj
++;
153 IntFreeMenuItem(PMENU Menu
, PITEM MenuItem
, BOOL bRecurse
)
155 FreeMenuText(Menu
,MenuItem
);
156 if(bRecurse
&& MenuItem
->spSubMenu
)
158 IntDestroyMenuObject(MenuItem
->spSubMenu
, bRecurse
, TRUE
);
162 DesktopHeapFree(Menu
->head
.rpdesk
, MenuItem
);
168 IntRemoveMenuItem(PMENU Menu
, UINT uPosition
, UINT uFlags
, BOOL bRecurse
)
170 PITEM PrevMenuItem
, MenuItem
= NULL
;
171 if(IntGetMenuItemByFlag(Menu
, uPosition
, uFlags
, &Menu
, &MenuItem
, &PrevMenuItem
) > -1)
176 PrevMenuItem
->Next
= MenuItem
->Next
;
179 Menu
->rgItems
= MenuItem
->Next
;
182 return IntFreeMenuItem(Menu
, MenuItem
, bRecurse
);
189 IntDeleteMenuItems(PMENU Menu
, BOOL bRecurse
)
193 PITEM CurItem
= Menu
->rgItems
;
194 while(CurItem
&& Menu
->cItems
)
196 Menu
->cItems
--; //// This is the last of this mess~! Removal requires new start up sequence. Do it like windows and wine!
197 //// wine MENU_CopySysPopup and ReactOS User32LoadSysMenuTemplateForKernel.
198 //// SC_CLOSE First and SC_CLOSED Last
199 //// Use menu item blocks not chain.
200 /// So do it like windows~!
201 NextItem
= CurItem
->Next
;
202 IntFreeMenuItem(Menu
, CurItem
, bRecurse
);
203 CurItem
->Next
= 0; // mark the item as end of the list!!!
208 Menu
->rgItems
= NULL
;
213 IntDestroyMenuObject(PMENU Menu
,
214 BOOL bRecurse
, BOOL RemoveFromProcess
)
219 //PWINSTATION_OBJECT WindowStation;
222 /* Remove all menu items */
223 IntDeleteMenuItems(Menu
, bRecurse
); /* Do not destroy submenus */
225 if(RemoveFromProcess
)
227 RemoveEntryList(&Menu
->ListEntry
);
230 /*Status = ObReferenceObjectByHandle(Menu->Process->Win32WindowStation,
232 ExWindowStationObjectType,
234 (PVOID*)&WindowStation,
236 if(NT_SUCCESS(Status))*/
237 if (PsGetCurrentProcessSessionId() == Menu
->head
.rpdesk
->rpwinstaParent
->dwSessionId
)
242 Window
= UserGetWindowObject(Menu
->hWnd
);
248 //UserDereferenceObject(Menu);
249 ret
= UserDeleteObject(Menu
->head
.h
, TYPE_MENU
);
251 { // Make sure it is really dead or just marked for deletion.
252 ret
= UserObjectInDestroy(Menu
->head
.h
);
253 if (ret
&& EngGetLastError() == ERROR_INVALID_HANDLE
) ret
= FALSE
;
254 } // See test_subpopup_locked_by_menu tests....
255 //ObDereferenceObject(WindowStation);
262 BOOL
IntDestroyMenu( PMENU pMenu
, BOOL RemoveFromProcess
)
264 /* DestroyMenu should not destroy system menu popup owner */
265 if ((pMenu
->fFlags
& (MNF_POPUP
| MNF_SYSSUBMENU
)) == MNF_POPUP
)//&& pMenu->hWnd)
267 //DestroyWindow( pMenu->hWnd );
271 if (pMenu
->rgItems
) /* recursively destroy submenus */
274 ITEM
*item
= pMenu
->rgItems
;
275 for (i
= pMenu
->cItems
; i
> 0; i
--, item
++)
277 if (item
->spSubMenu
) IntDestroyMenu(item
->spSubMenu
, RemoveFromProcess
);
278 //FreeMenuText(pMenu,item);
280 DesktopHeapFree(pMenu
->head
.rpdesk
, pMenu
->rgItems
);
282 //IntDestroyMenuObject(pMenu, bRecurse, RemoveFromProcess);
286 /**********************************************************************
289 * detect if there are loops in the menu tree (or the depth is too large)
291 int MENU_depth( PMENU pmenu
, int depth
)
298 if( depth
> MAXMENUDEPTH
) return depth
;
299 item
= pmenu
->rgItems
;
301 for( i
= 0; i
< pmenu
->cItems
&& subdepth
<= MAXMENUDEPTH
; i
++, item
++)
305 int bdepth
= MENU_depth( item
->spSubMenu
, depth
);
306 if( bdepth
> subdepth
) subdepth
= bdepth
;
308 if( subdepth
> MAXMENUDEPTH
)
309 TRACE("<- hmenu %p\n", item
->spSubMenu
);
314 /***********************************************************************
317 * Find a menu item. Return a pointer on the item, and modifies *hmenu
318 * in case the item was in a sub-menu.
320 ITEM
*MENU_FindItem( PMENU
*pmenu
, UINT
*nPos
, UINT wFlags
)
323 ITEM
*fallback
= NULL
;
324 UINT fallback_pos
= 0;
328 if (wFlags
& MF_BYPOSITION
)
330 if (*nPos
>= menu
->cItems
) return NULL
;
331 pItem
= menu
->rgItems
;
332 //pItem = &menu->rgItems[*nPos];
334 while(pItem
) // Do this for now.
336 if (i
< (INT
)menu
->cItems
)
338 if ( *nPos
== i
) return pItem
;
346 PITEM item
= menu
->rgItems
;
347 for (i
= 0; item
,i
< menu
->cItems
; i
++, item
= item
->Next
)//, item++)
351 PMENU psubmenu
= item
->spSubMenu
;
352 PITEM subitem
= MENU_FindItem( &psubmenu
, nPos
, wFlags
);
358 else if (item
->wID
== *nPos
)
360 /* fallback to this item if nothing else found */
365 else if (item
->wID
== *nPos
)
374 *nPos
= fallback_pos
;
379 BOOL
IntRemoveMenu( PMENU pMenu
, UINT nPos
, UINT wFlags
, BOOL bRecurse
)
381 PITEM item
, NewItems
;
383 TRACE("(menu=%p pos=%04x flags=%04x)\n",pMenu
, nPos
, wFlags
);
384 if (!(item
= MENU_FindItem( &pMenu
, &nPos
, wFlags
))) return FALSE
;
388 //FreeMenuText(pMenu,item);
390 if (bRecurse
&& item
->spSubMenu
)
392 IntDestroyMenu(item
->spSubMenu
, TRUE
);
394 ////// Use cAlloced with inc's of 8's....
395 if (--pMenu
->cItems
== 0)
397 DesktopHeapFree(pMenu
->head
.rpdesk
, pMenu
->rgItems
);
398 pMenu
->rgItems
= NULL
;
402 while(nPos
< pMenu
->cItems
)
408 NewItems
= DesktopHeapAlloc(pMenu
->head
.rpdesk
, pMenu
->cItems
* sizeof(ITEM
));
409 RtlCopyMemory(NewItems
, pMenu
->rgItems
, pMenu
->cItems
* sizeof(ITEM
));
410 DesktopHeapFree(pMenu
->head
.rpdesk
, pMenu
->rgItems
);
411 pMenu
->rgItems
= NewItems
;
417 IntCreateMenu(PHANDLE Handle
, BOOL IsMenuBar
)
420 PPROCESSINFO CurrentWin32Process
;
422 Menu
= (PMENU
)UserCreateObject( gHandleTable
,
434 Menu
->cyMax
= 0; /* Default */
435 Menu
->hbrBack
= NULL
; /* No brush */
436 Menu
->dwContextHelpId
= 0; /* Default */
437 Menu
->dwMenuData
= 0; /* Default */
438 Menu
->iItem
= NO_SELECTED_ITEM
; // Focused item
439 Menu
->fFlags
= (IsMenuBar
? 0 : MNF_POPUP
);
440 Menu
->spwndNotify
= NULL
;
441 Menu
->cyMenu
= 0; // Height
442 Menu
->cxMenu
= 0; // Width
443 Menu
->cItems
= 0; // Item count
446 Menu
->cxTextAlign
= 0;
447 Menu
->rgItems
= NULL
;
450 Menu
->TimeToHide
= FALSE
;
452 /* Insert menu item into process menu handle list */
453 CurrentWin32Process
= PsGetCurrentProcessWin32Process();
454 InsertTailList(&CurrentWin32Process
->MenuListHead
, &Menu
->ListEntry
);
460 IntCloneMenuItems(PMENU Destination
, PMENU Source
)
462 PITEM MenuItem
, NewMenuItem
= NULL
;
468 MenuItem
= Source
->rgItems
;
473 NewMenuItem
->Next
= MenuItem
;
474 NewMenuItem
= DesktopHeapAlloc(Destination
->head
.rpdesk
, sizeof(ITEM
));
477 RtlZeroMemory(NewMenuItem
, sizeof(NewMenuItem
));
478 NewMenuItem
->fType
= MenuItem
->fType
;
479 NewMenuItem
->fState
= MenuItem
->fState
;
480 NewMenuItem
->wID
= MenuItem
->wID
;
481 NewMenuItem
->spSubMenu
= MenuItem
->spSubMenu
;
482 NewMenuItem
->hbmpChecked
= MenuItem
->hbmpChecked
;
483 NewMenuItem
->hbmpUnchecked
= MenuItem
->hbmpUnchecked
;
484 NewMenuItem
->dwItemData
= MenuItem
->dwItemData
;
485 if((MENU_ITEM_TYPE(NewMenuItem
->fType
) == MF_STRING
))
487 if(MenuItem
->lpstr
.Length
)
489 NewMenuItem
->lpstr
.Length
= 0;
490 NewMenuItem
->lpstr
.MaximumLength
= MenuItem
->lpstr
.MaximumLength
;
491 NewMenuItem
->lpstr
.Buffer
= DesktopHeapAlloc(Destination
->head
.rpdesk
, MenuItem
->lpstr
.MaximumLength
);
492 if(!NewMenuItem
->lpstr
.Buffer
)
494 DesktopHeapFree(Destination
->head
.rpdesk
, NewMenuItem
);
497 RtlCopyUnicodeString(&NewMenuItem
->lpstr
, &MenuItem
->lpstr
);
501 NewMenuItem
->lpstr
.Buffer
= MenuItem
->lpstr
.Buffer
;
506 NewMenuItem
->lpstr
.Buffer
= MenuItem
->lpstr
.Buffer
;
508 NewMenuItem
->hbmp
= MenuItem
->hbmp
;
510 NewMenuItem
->Next
= NULL
;
512 Old
->Next
= NewMenuItem
;
514 Destination
->rgItems
= NewMenuItem
;
515 Destination
->cItems
++;
516 MenuItem
= MenuItem
->Next
;
523 IntCloneMenu(PMENU Source
)
525 PPROCESSINFO CurrentWin32Process
;
532 Menu
= (PMENU
)UserCreateObject( gHandleTable
,
541 Menu
->fFlags
= Source
->fFlags
;
542 Menu
->cyMax
= Source
->cyMax
;
543 Menu
->hbrBack
= Source
->hbrBack
;
544 Menu
->dwContextHelpId
= Source
->dwContextHelpId
;
545 Menu
->dwMenuData
= Source
->dwMenuData
;
546 Menu
->iItem
= NO_SELECTED_ITEM
;
547 Menu
->spwndNotify
= NULL
;
553 Menu
->cxTextAlign
= 0;
554 Menu
->rgItems
= NULL
;
557 Menu
->TimeToHide
= FALSE
;
559 /* Insert menu item into process menu handle list */
560 CurrentWin32Process
= PsGetCurrentProcessWin32Process();
561 InsertTailList(&CurrentWin32Process
->MenuListHead
, &Menu
->ListEntry
);
563 IntCloneMenuItems(Menu
, Source
);
569 IntSetMenuFlagRtoL(PMENU Menu
)
571 Menu
->fFlags
|= MNF_RTOL
;
576 IntSetMenuContextHelpId(PMENU Menu
, DWORD dwContextHelpId
)
578 Menu
->dwContextHelpId
= dwContextHelpId
;
583 IntGetMenuInfo(PMENU Menu
, PROSMENUINFO lpmi
)
585 if(lpmi
->fMask
& MIM_BACKGROUND
)
586 lpmi
->hbrBack
= Menu
->hbrBack
;
587 if(lpmi
->fMask
& MIM_HELPID
)
588 lpmi
->dwContextHelpID
= Menu
->dwContextHelpId
;
589 if(lpmi
->fMask
& MIM_MAXHEIGHT
)
590 lpmi
->cyMax
= Menu
->cyMax
;
591 if(lpmi
->fMask
& MIM_MENUDATA
)
592 lpmi
->dwMenuData
= Menu
->dwMenuData
;
593 if(lpmi
->fMask
& MIM_STYLE
)
594 lpmi
->dwStyle
= Menu
->fFlags
& MNS_STYLE_MASK
;
596 if (sizeof(MENUINFO
) < lpmi
->cbSize
)
598 lpmi
->cItems
= Menu
->cItems
;
600 lpmi
->iItem
= Menu
->iItem
;
601 lpmi
->cxMenu
= Menu
->cxMenu
;
602 lpmi
->cyMenu
= Menu
->cyMenu
;
603 lpmi
->spwndNotify
= Menu
->spwndNotify
;
604 lpmi
->cxTextAlign
= Menu
->cxTextAlign
;
605 lpmi
->iTop
= Menu
->iMaxTop
;
606 lpmi
->iMaxTop
= Menu
->iMaxTop
;
607 lpmi
->dwArrowsOn
= Menu
->dwArrowsOn
;
609 lpmi
->fFlags
= Menu
->fFlags
;
610 lpmi
->Self
= Menu
->head
.h
;
611 lpmi
->TimeToHide
= Menu
->TimeToHide
;
612 lpmi
->Wnd
= Menu
->hWnd
;
618 IntSetMenuInfo(PMENU Menu
, PROSMENUINFO lpmi
)
620 if(lpmi
->fMask
& MIM_BACKGROUND
)
621 Menu
->hbrBack
= lpmi
->hbrBack
;
622 if(lpmi
->fMask
& MIM_HELPID
)
623 Menu
->dwContextHelpId
= lpmi
->dwContextHelpID
;
624 if(lpmi
->fMask
& MIM_MAXHEIGHT
)
625 Menu
->cyMax
= lpmi
->cyMax
;
626 if(lpmi
->fMask
& MIM_MENUDATA
)
627 Menu
->dwMenuData
= lpmi
->dwMenuData
;
628 if(lpmi
->fMask
& MIM_STYLE
)
629 Menu
->fFlags
^= (Menu
->fFlags
^ lpmi
->dwStyle
) & MNS_STYLE_MASK
;
630 if(lpmi
->fMask
& MIM_APPLYTOSUBMENUS
)
633 PITEM item
= Menu
->rgItems
;
634 for ( i
= Menu
->cItems
; i
; i
--, item
= item
->Next
)
636 if ( item
->spSubMenu
)
638 IntSetMenuInfo( item
->spSubMenu
, lpmi
);
641 /* PITEM item = Menu->rgItems;
642 for ( i = Menu->cItems; i; i--, item++)
644 if ( item->spSubMenu )
646 IntSetMenuInfo( item->spSubMenu, lpmi);
650 if (sizeof(MENUINFO
) < lpmi
->cbSize
)
652 Menu
->iItem
= lpmi
->iItem
;
653 Menu
->cyMenu
= lpmi
->cyMenu
;
654 Menu
->cxMenu
= lpmi
->cxMenu
;
655 Menu
->spwndNotify
= lpmi
->spwndNotify
;
656 Menu
->cxTextAlign
= lpmi
->cxTextAlign
;
657 Menu
->iTop
= lpmi
->iTop
;
658 Menu
->iMaxTop
= lpmi
->iMaxTop
;
659 Menu
->dwArrowsOn
= lpmi
->dwArrowsOn
;
661 Menu
->TimeToHide
= lpmi
->TimeToHide
;
662 Menu
->hWnd
= lpmi
->Wnd
;
668 // Old and yeah~..... Why start with a -1 for position search?
671 IntGetMenuItemByFlag(PMENU Menu
,
678 PITEM PrevItem
= NULL
;
679 PITEM CurItem
= Menu
->rgItems
;
683 if(MF_BYPOSITION
& fFlag
)
686 while(CurItem
&& (p
> 0))
689 CurItem
= CurItem
->Next
;
697 *PrevMenuItem
= PrevItem
;
704 *PrevMenuItem
= NULL
; /* ? */
708 return uSearchBy
- p
;
715 if(CurItem
->wID
== uSearchBy
)
720 *PrevMenuItem
= PrevItem
;
728 if(CurItem
->spSubMenu
)
730 ret
= IntGetMenuItemByFlag(CurItem
->spSubMenu
, uSearchBy
, fFlag
, SubMenu
, MenuItem
, PrevMenuItem
);
738 CurItem
= CurItem
->Next
;
747 IntInsertMenuItemToList(PMENU Menu
, PITEM MenuItem
, int pos
)
750 PITEM LastItem
= NULL
;
753 CurItem
= Menu
->rgItems
;
754 while(CurItem
&& (pos
!= 0))
757 CurItem
= CurItem
->Next
;
764 /* Insert the item after LastItem */
765 LastItem
->Next
= MenuItem
;
769 /* Insert at the beginning */
770 Menu
->rgItems
= MenuItem
;
772 MenuItem
->Next
= CurItem
;
779 IntGetMenuItemInfo(PMENU Menu
, /* UNUSED PARAM!! */
780 PITEM MenuItem
, PROSMENUITEMINFO lpmii
)
784 if(lpmii
->fMask
& (MIIM_FTYPE
| MIIM_TYPE
))
786 lpmii
->fType
= MenuItem
->fType
;
788 if(lpmii
->fMask
& MIIM_BITMAP
)
790 lpmii
->hbmpItem
= MenuItem
->hbmp
;
792 if(lpmii
->fMask
& MIIM_CHECKMARKS
)
794 lpmii
->hbmpChecked
= MenuItem
->hbmpChecked
;
795 lpmii
->hbmpUnchecked
= MenuItem
->hbmpUnchecked
;
797 if(lpmii
->fMask
& MIIM_DATA
)
799 lpmii
->dwItemData
= MenuItem
->dwItemData
;
801 if(lpmii
->fMask
& MIIM_ID
)
803 lpmii
->wID
= MenuItem
->wID
;
805 if(lpmii
->fMask
& MIIM_STATE
)
807 lpmii
->fState
= MenuItem
->fState
;
809 if(lpmii
->fMask
& MIIM_SUBMENU
)
811 lpmii
->hSubMenu
= MenuItem
->spSubMenu
? MenuItem
->spSubMenu
->head
.h
: NULL
;
814 if ((lpmii
->fMask
& MIIM_STRING
) ||
815 ((lpmii
->fMask
& MIIM_TYPE
) && (MENU_ITEM_TYPE(lpmii
->fType
) == MF_STRING
)))
817 if (lpmii
->dwTypeData
== NULL
)
819 lpmii
->cch
= MenuItem
->lpstr
.Length
/ sizeof(WCHAR
);
822 { //// lpmii->lpstr can be read in user mode!!!!
823 Status
= MmCopyToCaller(lpmii
->dwTypeData
, MenuItem
->lpstr
.Buffer
,
824 min(lpmii
->cch
* sizeof(WCHAR
),
825 MenuItem
->lpstr
.MaximumLength
));
826 if (! NT_SUCCESS(Status
))
828 SetLastNtError(Status
);
834 if (sizeof(ROSMENUITEMINFO
) == lpmii
->cbSize
)
836 lpmii
->Rect
.left
= MenuItem
->xItem
;
837 lpmii
->Rect
.top
= MenuItem
->yItem
;
838 lpmii
->Rect
.right
= MenuItem
->cxItem
; // Do this for now......
839 lpmii
->Rect
.bottom
= MenuItem
->cyItem
;
840 lpmii
->dxTab
= MenuItem
->dxTab
;
841 lpmii
->lpstr
= MenuItem
->lpstr
.Buffer
;
842 lpmii
->maxBmpSize
.cx
= MenuItem
->cxBmp
;
843 lpmii
->maxBmpSize
.cy
= MenuItem
->cyBmp
;
850 IntSetMenuItemInfo(PMENU MenuObject
, PITEM MenuItem
, PROSMENUITEMINFO lpmii
, PUNICODE_STRING lpstr
)
853 UINT fTypeMask
= (MFT_BITMAP
| MFT_MENUBARBREAK
| MFT_MENUBREAK
| MFT_OWNERDRAW
| MFT_RADIOCHECK
| MFT_RIGHTJUSTIFY
| MFT_SEPARATOR
);
855 if(!MenuItem
|| !MenuObject
|| !lpmii
)
859 if (lpmii
->fType
& ~fTypeMask
)
861 ERR("IntSetMenuItemInfo invalid fType flags %x\n", lpmii
->fType
& ~fTypeMask
);
862 lpmii
->fMask
&= ~(MIIM_TYPE
| MIIM_FTYPE
);
864 if (lpmii
->fMask
& MIIM_TYPE
)
866 #if 0 //// Done in User32.
867 if (lpmii
->fMask
& ( MIIM_STRING
| MIIM_FTYPE
| MIIM_BITMAP
))
869 ERR("IntSetMenuItemInfo: Invalid combination of fMask bits used\n");
870 KeRosDumpStackFrames(NULL
, 20);
871 /* This does not happen on Win9x/ME */
872 SetLastNtError( ERROR_INVALID_PARAMETER
);
877 * Delete the menu item type when changing type from
880 if (MenuItem
->fType
!= lpmii
->fType
&&
881 MENU_ITEM_TYPE(MenuItem
->fType
) == MFT_STRING
)
883 FreeMenuText(MenuObject
,MenuItem
);
884 RtlInitUnicodeString(&MenuItem
->lpstr
, NULL
);
886 if(lpmii
->fType
& MFT_BITMAP
)
889 MenuItem
->hbmp
= lpmii
->hbmpItem
;
891 { /* Win 9x/Me stuff */
892 MenuItem
->hbmp
= (HBITMAP
)((ULONG_PTR
)(LOWORD(lpmii
->dwTypeData
)));
895 MenuItem
->fType
|= lpmii
->fType
;
897 if (lpmii
->fMask
& MIIM_FTYPE
)
900 if(( lpmii
->fType
& MFT_BITMAP
))
902 ERR("IntSetMenuItemInfo: Can not use FTYPE and MFT_BITMAP.\n");
903 SetLastNtError( ERROR_INVALID_PARAMETER
);
907 MenuItem
->fType
&= ~MENUITEMINFO_TYPE_MASK
;
908 MenuItem
->fType
|= lpmii
->fType
& MENUITEMINFO_TYPE_MASK
;
910 if(lpmii
->fMask
& MIIM_BITMAP
)
912 MenuItem
->hbmp
= lpmii
->hbmpItem
;
914 if(lpmii
->fMask
& MIIM_CHECKMARKS
)
916 MenuItem
->hbmpChecked
= lpmii
->hbmpChecked
;
917 MenuItem
->hbmpUnchecked
= lpmii
->hbmpUnchecked
;
919 if(lpmii
->fMask
& MIIM_DATA
)
921 MenuItem
->dwItemData
= lpmii
->dwItemData
;
923 if(lpmii
->fMask
& MIIM_ID
)
925 MenuItem
->wID
= lpmii
->wID
;
927 if(lpmii
->fMask
& MIIM_STATE
)
929 /* Remove MFS_DEFAULT flag from all other menu items if this item
930 has the MFS_DEFAULT state */
931 if(lpmii
->fState
& MFS_DEFAULT
)
932 UserSetMenuDefaultItem(MenuObject
, -1, 0);
933 /* Update the menu item state flags */
934 UpdateMenuItemState(MenuItem
->fState
, lpmii
->fState
);
937 if(lpmii
->fMask
& MIIM_SUBMENU
)
939 /* Make sure the submenu is marked as a popup menu */
942 SubMenuObject
= UserGetMenuObject(lpmii
->hSubMenu
);
943 if (SubMenuObject
!= NULL
)
945 SubMenuObject
->fFlags
|= MNF_POPUP
;
946 // Now fix the test_subpopup_locked_by_menu tests....
947 if (MenuItem
->spSubMenu
) UserDereferenceObject(MenuItem
->spSubMenu
);
948 MenuItem
->spSubMenu
= SubMenuObject
;
949 UserReferenceObject(SubMenuObject
);
953 EngSetLastError( ERROR_INVALID_PARAMETER
);
958 { // If submenu just dereference it.
959 if (MenuItem
->spSubMenu
) UserDereferenceObject(MenuItem
->spSubMenu
);
960 MenuItem
->spSubMenu
= NULL
;
964 if ((lpmii
->fMask
& MIIM_STRING
) ||
965 ((lpmii
->fMask
& MIIM_TYPE
) && (MENU_ITEM_TYPE(lpmii
->fType
) == MF_STRING
)))
967 FreeMenuText(MenuObject
,MenuItem
);
969 if(lpmii
->dwTypeData
&& lpmii
->cch
)
971 UNICODE_STRING Source
;
973 Source
.Length
= Source
.MaximumLength
= lpmii
->cch
* sizeof(WCHAR
);
974 Source
.Buffer
= lpmii
->dwTypeData
;
976 MenuItem
->lpstr
.Buffer
= DesktopHeapAlloc( MenuObject
->head
.rpdesk
, Source
.Length
+ sizeof(WCHAR
));
977 if(MenuItem
->lpstr
.Buffer
!= NULL
)
979 MenuItem
->lpstr
.Length
= 0;
980 MenuItem
->lpstr
.MaximumLength
= Source
.Length
+ sizeof(WCHAR
);
981 RtlCopyUnicodeString(&MenuItem
->lpstr
, &Source
);
982 MenuItem
->lpstr
.Buffer
[MenuItem
->lpstr
.Length
/ sizeof(WCHAR
)] = 0;
984 MenuItem
->cch
= MenuItem
->lpstr
.Length
/ sizeof(WCHAR
);
985 MenuItem
->Xlpstr
= (USHORT
*)MenuItem
->lpstr
.Buffer
;
989 RtlInitUnicodeString(&MenuItem
->lpstr
, NULL
);
990 MenuItem
->Xlpstr
= NULL
;
995 if (0 == (MenuObject
->fFlags
& MNF_SYSDESKMN
))
997 MenuItem
->fType
|= MF_SEPARATOR
;
999 RtlInitUnicodeString(&MenuItem
->lpstr
, NULL
);
1003 //if( !MenuItem->lpstr.Buffer && !(MenuItem->fType & MFT_OWNERDRAW) && !MenuItem->hbmp)
1004 // MenuItem->fType |= MFT_SEPARATOR; break system menu.....
1006 /* Force size recalculation! */
1007 MenuObject
->cyMenu
= 0;
1009 if (sizeof(ROSMENUITEMINFO
) == lpmii
->cbSize
)
1011 MenuItem
->xItem
= lpmii
->Rect
.left
;
1012 MenuItem
->yItem
= lpmii
->Rect
.top
;
1013 MenuItem
->cxItem
= lpmii
->Rect
.right
; // Do this for now......
1014 MenuItem
->cyItem
= lpmii
->Rect
.bottom
;
1015 MenuItem
->dxTab
= lpmii
->dxTab
;
1016 lpmii
->lpstr
= MenuItem
->lpstr
.Buffer
; /* Send back new allocated string or zero */
1017 MenuItem
->cxBmp
= lpmii
->maxBmpSize
.cx
;
1018 MenuItem
->cyBmp
= lpmii
->maxBmpSize
.cy
;
1025 /**********************************************************************
1028 * Insert (allocate) a new item into a menu.
1030 ITEM
*MENU_InsertItem( PMENU menu
, UINT pos
, UINT flags
)
1034 /* Find where to insert new item */
1036 if (flags
& MF_BYPOSITION
) {
1037 if (pos
> menu
->cItems
)
1040 if (!MENU_FindItem( &menu
, &pos
, flags
))
1044 /* Make sure that MDI system buttons stay on the right side.
1045 * Note: XP treats only bitmap handles 1 - 6 as "magic" ones
1046 * regardless of their id.
1049 (INT_PTR
)menu
->rgItems
[pos
- 1].hbmp
>= (INT_PTR
)HBMMENU_SYSTEM
&&
1050 (INT_PTR
)menu
->rgItems
[pos
- 1].hbmp
<= (INT_PTR
)HBMMENU_MBAR_CLOSE_D
)
1053 TRACE("inserting at %u flags %x\n", pos
, flags
);
1055 /* Create new items array */
1057 newItems
= DesktopHeapAlloc(menu
->head
.rpdesk
, sizeof(ITEM
) * (menu
->cItems
+1) );
1060 WARN("allocation failed\n" );
1063 if (menu
->cItems
> 0)
1065 /* Copy the old array into the new one */
1066 if (pos
> 0) RtlCopyMemory( newItems
, menu
->rgItems
, pos
* sizeof(ITEM
) );
1067 if (pos
< menu
->cItems
) RtlCopyMemory( &newItems
[pos
+1], &menu
->rgItems
[pos
], (menu
->cItems
-pos
)*sizeof(ITEM
) );
1068 DesktopHeapFree(menu
->head
.rpdesk
, menu
->rgItems
);
1070 menu
->rgItems
= newItems
;
1072 RtlZeroMemory( &newItems
[pos
], sizeof(*newItems
) );
1073 menu
->cyMenu
= 0; /* force size recalculate */
1074 return &newItems
[pos
];
1079 _In_ PMENU MenuObject
,
1082 PROSMENUITEMINFO ItemInfo
)
1086 PMENU SubMenu
= NULL
;
1088 NT_ASSERT(MenuObject
!= NULL
);
1089 //ERR("InsertMenuItem\n");
1090 if (MAX_MENU_ITEMS
<= MenuObject
->cItems
)
1092 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1098 SubMenu
= MenuObject
;
1099 /* calculate position */
1101 if(uItem
> MenuObject
->cItems
)
1103 pos
= MenuObject
->cItems
;
1108 pos
= IntGetMenuItemByFlag(MenuObject
, uItem
, MF_BYCOMMAND
, &SubMenu
, NULL
, NULL
);
1110 if (SubMenu
== NULL
)
1112 /* Default to last position of menu */
1113 SubMenu
= MenuObject
;
1114 pos
= MenuObject
->cItems
;
1123 MenuItem
= DesktopHeapAlloc(MenuObject
->head
.rpdesk
, sizeof(ITEM
));
1124 if (NULL
== MenuItem
)
1126 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1130 RtlZeroMemory(MenuItem
, sizeof(MenuItem
));
1132 if(!IntSetMenuItemInfo(SubMenu
, MenuItem
, ItemInfo
, NULL
))
1134 DesktopHeapFree(MenuObject
->head
.rpdesk
, MenuItem
);
1138 /* Force size recalculation! */
1139 MenuObject
->cyMenu
= 0;
1140 MenuItem
->hbmpChecked
= MenuItem
->hbmpUnchecked
= 0;
1142 pos
= IntInsertMenuItemToList(SubMenu
, MenuItem
, pos
);
1144 TRACE("IntInsertMenuItemToList = %i\n", pos
);
1150 IntEnableMenuItem(PMENU MenuObject
, UINT uIDEnableItem
, UINT uEnable
)
1155 if (!(MenuItem
= MENU_FindItem( &MenuObject
, &uIDEnableItem
, uEnable
))) return (UINT
)-1;
1157 res
= MenuItem
->fState
& (MF_GRAYED
| MF_DISABLED
);
1159 MenuItem
->fState
^= (res
^ uEnable
) & (MF_GRAYED
| MF_DISABLED
);
1161 /* If the close item in the system menu change update the close button */
1162 if((MenuItem
->wID
== SC_CLOSE
) && (res
!= uEnable
))
1164 if (MenuObject
->fFlags
& MNF_SYSSUBMENU
&& MenuObject
->spwndNotify
!= 0)
1166 RECTL rc
= MenuObject
->spwndNotify
->rcWindow
;
1168 /* Refresh the frame to reflect the change */
1169 IntMapWindowPoints(0, MenuObject
->spwndNotify
, (POINT
*)&rc
, 2);
1171 co_UserRedrawWindow(MenuObject
->spwndNotify
, &rc
, 0, RDW_FRAME
| RDW_INVALIDATE
| RDW_NOCHILDREN
);
1176 #if 0 // Moved to User32.
1178 IntBuildMenuItemList(PMENU MenuObject
, PVOID Buffer
, ULONG nMax
)
1181 ROSMENUITEMINFO mii
;
1183 PITEM CurItem
= MenuObject
->rgItems
;
1190 if (nMax
< MenuObject
->cItems
* sizeof(ROSMENUITEMINFO
))
1194 StrOut
= (PWCHAR
)((char *) Buffer
+ MenuObject
->cItems
1195 * sizeof(ROSMENUITEMINFO
));
1196 nMax
-= MenuObject
->cItems
* sizeof(ROSMENUITEMINFO
);
1198 mii
.cbSize
= sizeof(ROSMENUITEMINFO
);
1202 while (NULL
!= CurItem
)
1204 mii
.cch
= CurItem
->lpstr
.Length
/ sizeof(WCHAR
);
1205 mii
.dwItemData
= CurItem
->dwItemData
;
1206 if (0 != CurItem
->lpstr
.Length
)
1208 mii
.dwTypeData
= StrOut
;
1212 mii
.dwTypeData
= NULL
;
1214 mii
.fState
= CurItem
->fState
;
1215 mii
.fType
= CurItem
->fType
;
1216 mii
.wID
= CurItem
->wID
;
1217 mii
.hbmpChecked
= CurItem
->hbmpChecked
;
1218 mii
.hbmpItem
= CurItem
->hbmp
;
1219 mii
.hbmpUnchecked
= CurItem
->hbmpUnchecked
;
1220 mii
.hSubMenu
= CurItem
->spSubMenu
? CurItem
->spSubMenu
->head
.h
: NULL
;
1221 mii
.Rect
.left
= CurItem
->xItem
;
1222 mii
.Rect
.top
= CurItem
->yItem
;
1223 mii
.Rect
.right
= CurItem
->cxItem
; // Do this for now......
1224 mii
.Rect
.bottom
= CurItem
->cyItem
;
1225 mii
.dxTab
= CurItem
->dxTab
;
1226 mii
.lpstr
= CurItem
->lpstr
.Buffer
; // Can be read from user side!
1227 //mii.maxBmpSize.cx = CurItem->cxBmp;
1228 //mii.maxBmpSize.cy = CurItem->cyBmp;
1230 Status
= MmCopyToCaller(Buf
, &mii
, sizeof(ROSMENUITEMINFO
));
1231 if (! NT_SUCCESS(Status
))
1233 SetLastNtError(Status
);
1236 Buf
= (PVOID
)((ULONG_PTR
)Buf
+ sizeof(ROSMENUITEMINFO
));
1238 if (0 != CurItem
->lpstr
.Length
1239 && (nMax
>= CurItem
->lpstr
.Length
+ sizeof(WCHAR
)))
1242 Status
= MmCopyToCaller(StrOut
, CurItem
->lpstr
.Buffer
,
1243 CurItem
->lpstr
.Length
);
1244 if (! NT_SUCCESS(Status
))
1246 SetLastNtError(Status
);
1249 StrOut
+= CurItem
->lpstr
.Length
/ sizeof(WCHAR
);
1250 Status
= MmCopyToCaller(StrOut
, &NulByte
, sizeof(WCHAR
));
1251 if (! NT_SUCCESS(Status
))
1253 SetLastNtError(Status
);
1257 nMax
-= CurItem
->lpstr
.Length
+ sizeof(WCHAR
);
1259 else if (0 != CurItem
->lpstr
.Length
)
1264 CurItem
= CurItem
->Next
;
1270 while (NULL
!= CurItem
)
1272 res
+= sizeof(ROSMENUITEMINFO
) + CurItem
->lpstr
.Length
+ sizeof(WCHAR
);
1273 CurItem
= CurItem
->Next
;
1280 IntCheckMenuItem(PMENU MenuObject
, UINT uIDCheckItem
, UINT uCheck
)
1285 if (!(MenuItem
= MENU_FindItem( &MenuObject
, &uIDCheckItem
, uCheck
))) return -1;
1287 res
= (DWORD
)(MenuItem
->fState
& MF_CHECKED
);
1289 MenuItem
->fState
^= (res
^ uCheck
) & MF_CHECKED
;
1295 IntHiliteMenuItem(PWND WindowObject
,
1302 if (!(MenuItem
= MENU_FindItem( &MenuObject
, &uItemHilite
, uHilite
))) return FALSE
;
1306 if (uHilite
& MF_HILITE
)
1308 MenuItem
->fState
|= MF_HILITE
;
1312 MenuItem
->fState
&= ~MF_HILITE
;
1315 /* FIXME: Update the window's menu */
1321 UserSetMenuDefaultItem(PMENU MenuObject
, UINT uItem
, UINT fByPos
)
1324 PITEM MenuItem
= MenuObject
->rgItems
;
1328 MenuItem
->fState
&= ~MFS_DEFAULT
;
1329 MenuItem
= MenuItem
->Next
;
1332 /* no default item */
1333 if(uItem
== (UINT
)-1)
1345 MenuItem
->fState
|= MFS_DEFAULT
;
1350 MenuItem
->fState
&= ~MFS_DEFAULT
;
1353 MenuItem
= MenuItem
->Next
;
1360 if(!ret
&& (MenuItem
->wID
== uItem
))
1362 MenuItem
->fState
|= MFS_DEFAULT
;
1367 MenuItem
->fState
&= ~MFS_DEFAULT
;
1369 MenuItem
= MenuItem
->Next
;
1377 IntGetMenuDefaultItem(PMENU MenuObject
, UINT fByPos
, UINT gmdiFlags
,
1383 PITEM MenuItem
= MenuObject
->rgItems
;
1387 if(MenuItem
->fState
& MFS_DEFAULT
)
1390 if(!(gmdiFlags
& GMDI_USEDISABLED
) && (MenuItem
->fState
& MFS_DISABLED
))
1396 res
= MenuItem
->wID
;
1398 if((*gismc
< MAX_GOINTOSUBMENU
) && (gmdiFlags
& GMDI_GOINTOPOPUPS
) &&
1399 MenuItem
->spSubMenu
)
1402 if(MenuItem
->spSubMenu
== MenuObject
)
1406 sres
= IntGetMenuDefaultItem(MenuItem
->spSubMenu
, fByPos
, gmdiFlags
, gismc
);
1416 MenuItem
= MenuItem
->Next
;
1424 co_IntInitTracking(PWND Window
, PMENU Menu
, BOOL Popup
,
1427 /* FIXME: Hide caret */
1429 if(!(Flags
& TPM_NONOTIFY
))
1430 co_IntSendMessage(Window
->head
.h
, WM_SETCURSOR
, (WPARAM
)Window
->head
.h
, HTCAPTION
);
1432 /* FIXME: Send WM_SETCURSOR message */
1434 if(!(Flags
& TPM_NONOTIFY
))
1435 co_IntSendMessage(Window
->head
.h
, WM_INITMENU
, (WPARAM
)Menu
->head
.h
, 0);
1439 co_IntExitTracking(PWND Window
, PMENU Menu
, BOOL Popup
,
1442 if(!(Flags
& TPM_NONOTIFY
))
1443 co_IntSendMessage(Window
->head
.h
, WM_EXITMENULOOP
, 0 /* FIXME */, 0);
1445 /* FIXME: Show caret again */
1449 IntTrackMenu(PMENU Menu
, PWND Window
, INT x
, INT y
,
1456 co_IntTrackPopupMenu(PMENU Menu
, PWND Window
,
1457 UINT Flags
, POINT
*Pos
, UINT MenuPos
, RECTL
*ExcludeRect
)
1459 co_IntInitTracking(Window
, Menu
, TRUE
, Flags
);
1461 co_IntExitTracking(Window
, Menu
, TRUE
, Flags
);
1467 * Internal function. Called when the process is destroyed to free the remaining menu handles.
1470 IntCleanupMenus(struct _EPROCESS
*Process
, PPROCESSINFO Win32Process
)
1472 PEPROCESS CurrentProcess
;
1473 PLIST_ENTRY LastHead
= NULL
;
1476 CurrentProcess
= PsGetCurrentProcess();
1477 if (CurrentProcess
!= Process
)
1479 KeAttachProcess(&Process
->Pcb
);
1482 while (Win32Process
->MenuListHead
.Flink
!= &(Win32Process
->MenuListHead
) &&
1483 Win32Process
->MenuListHead
.Flink
!= LastHead
)
1485 LastHead
= Win32Process
->MenuListHead
.Flink
;
1486 MenuObject
= CONTAINING_RECORD(Win32Process
->MenuListHead
.Flink
, MENU
, ListEntry
);
1487 ERR("Menus are stuck on the process list!\n");
1488 IntDestroyMenuObject(MenuObject
, FALSE
, TRUE
);
1491 if (CurrentProcess
!= Process
)
1499 intGetTitleBarInfo(PWND pWindowObject
, PTITLEBARINFO bti
)
1503 DWORD dwExStyle
= 0;
1504 BOOLEAN retValue
= TRUE
;
1506 if (bti
->cbSize
== sizeof(TITLEBARINFO
))
1508 RtlZeroMemory(&bti
->rgstate
[0],sizeof(DWORD
)*(CCHILDREN_TITLEBAR
+1));
1510 bti
->rgstate
[0] = STATE_SYSTEM_FOCUSABLE
;
1512 dwStyle
= pWindowObject
->style
;
1513 dwExStyle
= pWindowObject
->ExStyle
;
1515 bti
->rcTitleBar
.top
= 0;
1516 bti
->rcTitleBar
.left
= 0;
1517 bti
->rcTitleBar
.right
= pWindowObject
->rcWindow
.right
- pWindowObject
->rcWindow
.left
;
1518 bti
->rcTitleBar
.bottom
= pWindowObject
->rcWindow
.bottom
- pWindowObject
->rcWindow
.top
;
1520 /* Is it iconiced ? */
1521 if ((dwStyle
& WS_ICONIC
)!=WS_ICONIC
)
1523 /* Remove frame from rectangle */
1524 if (HAS_THICKFRAME( dwStyle
, dwExStyle
))
1526 /* FIXME: Note this value should exists in pWindowObject for UserGetSystemMetrics(SM_CXFRAME) and UserGetSystemMetrics(SM_CYFRAME) */
1527 RECTL_vInflateRect( &bti
->rcTitleBar
, -UserGetSystemMetrics(SM_CXFRAME
), -UserGetSystemMetrics(SM_CYFRAME
) );
1529 else if (HAS_DLGFRAME( dwStyle
, dwExStyle
))
1531 /* FIXME: Note this value should exists in pWindowObject for UserGetSystemMetrics(SM_CXDLGFRAME) and UserGetSystemMetrics(SM_CYDLGFRAME) */
1532 RECTL_vInflateRect( &bti
->rcTitleBar
, -UserGetSystemMetrics(SM_CXDLGFRAME
), -UserGetSystemMetrics(SM_CYDLGFRAME
));
1534 else if (HAS_THINFRAME( dwStyle
, dwExStyle
))
1536 /* FIXME: Note this value should exists in pWindowObject for UserGetSystemMetrics(SM_CXBORDER) and UserGetSystemMetrics(SM_CYBORDER) */
1537 RECTL_vInflateRect( &bti
->rcTitleBar
, -UserGetSystemMetrics(SM_CXBORDER
), -UserGetSystemMetrics(SM_CYBORDER
) );
1540 /* We have additional border information if the window
1541 * is a child (but not an MDI child) */
1542 if ( (dwStyle
& WS_CHILD
) &&
1543 ((dwExStyle
& WS_EX_MDICHILD
) == 0 ) )
1545 if (dwExStyle
& WS_EX_CLIENTEDGE
)
1547 /* FIXME: Note this value should exists in pWindowObject for UserGetSystemMetrics(SM_CXEDGE) and UserGetSystemMetrics(SM_CYEDGE) */
1548 RECTL_vInflateRect (&bti
->rcTitleBar
, -UserGetSystemMetrics(SM_CXEDGE
), -UserGetSystemMetrics(SM_CYEDGE
));
1551 if (dwExStyle
& WS_EX_STATICEDGE
)
1553 /* FIXME: Note this value should exists in pWindowObject for UserGetSystemMetrics(SM_CXBORDER) and UserGetSystemMetrics(SM_CYBORDER) */
1554 RECTL_vInflateRect (&bti
->rcTitleBar
, -UserGetSystemMetrics(SM_CXBORDER
), -UserGetSystemMetrics(SM_CYBORDER
));
1559 bti
->rcTitleBar
.top
+= pWindowObject
->rcWindow
.top
;
1560 bti
->rcTitleBar
.left
+= pWindowObject
->rcWindow
.left
;
1561 bti
->rcTitleBar
.right
+= pWindowObject
->rcWindow
.left
;
1563 bti
->rcTitleBar
.bottom
= bti
->rcTitleBar
.top
;
1564 if (dwExStyle
& WS_EX_TOOLWINDOW
)
1566 /* FIXME: Note this value should exists in pWindowObject for UserGetSystemMetrics(SM_CYSMCAPTION) */
1567 bti
->rcTitleBar
.bottom
+= UserGetSystemMetrics(SM_CYSMCAPTION
);
1571 /* FIXME: Note this value should exists in pWindowObject for UserGetSystemMetrics(SM_CYCAPTION) and UserGetSystemMetrics(SM_CXSIZE) */
1572 bti
->rcTitleBar
.bottom
+= UserGetSystemMetrics(SM_CYCAPTION
);
1573 bti
->rcTitleBar
.left
+= UserGetSystemMetrics(SM_CXSIZE
);
1576 if (dwStyle
& WS_CAPTION
)
1578 bti
->rgstate
[1] = STATE_SYSTEM_INVISIBLE
;
1579 if (dwStyle
& WS_SYSMENU
)
1581 if (!(dwStyle
& (WS_MINIMIZEBOX
|WS_MAXIMIZEBOX
)))
1583 bti
->rgstate
[2] = STATE_SYSTEM_INVISIBLE
;
1584 bti
->rgstate
[3] = STATE_SYSTEM_INVISIBLE
;
1588 if (!(dwStyle
& WS_MINIMIZEBOX
))
1590 bti
->rgstate
[2] = STATE_SYSTEM_UNAVAILABLE
;
1592 if (!(dwStyle
& WS_MAXIMIZEBOX
))
1594 bti
->rgstate
[3] = STATE_SYSTEM_UNAVAILABLE
;
1598 if (!(dwExStyle
& WS_EX_CONTEXTHELP
))
1600 bti
->rgstate
[4] = STATE_SYSTEM_INVISIBLE
;
1602 if (pWindowObject
->pcls
->style
& CS_NOCLOSE
)
1604 bti
->rgstate
[5] = STATE_SYSTEM_UNAVAILABLE
;
1609 bti
->rgstate
[2] = STATE_SYSTEM_INVISIBLE
;
1610 bti
->rgstate
[3] = STATE_SYSTEM_INVISIBLE
;
1611 bti
->rgstate
[4] = STATE_SYSTEM_INVISIBLE
;
1612 bti
->rgstate
[5] = STATE_SYSTEM_INVISIBLE
;
1617 bti
->rgstate
[0] |= STATE_SYSTEM_INVISIBLE
;
1622 EngSetLastError(ERROR_INVALID_PARAMETER
);
1634 LPCMENUITEMINFOW UnsafeItemInfo
)
1637 ROSMENUITEMINFO ItemInfo
;
1639 /* Try to copy the whole MENUITEMINFOW structure */
1640 Status
= MmCopyFromCaller(&ItemInfo
, UnsafeItemInfo
, sizeof(MENUITEMINFOW
));
1641 if (NT_SUCCESS(Status
))
1643 if (sizeof(MENUITEMINFOW
) != ItemInfo
.cbSize
1644 && FIELD_OFFSET(MENUITEMINFOW
, hbmpItem
) != ItemInfo
.cbSize
)
1646 EngSetLastError(ERROR_INVALID_PARAMETER
);
1649 return IntInsertMenuItem(Menu
, uItem
, fByPosition
, &ItemInfo
);
1652 /* Try to copy without last field (not present in older versions) */
1653 Status
= MmCopyFromCaller(&ItemInfo
, UnsafeItemInfo
, FIELD_OFFSET(MENUITEMINFOW
, hbmpItem
));
1654 if (NT_SUCCESS(Status
))
1656 if (FIELD_OFFSET(MENUITEMINFOW
, hbmpItem
) != ItemInfo
.cbSize
)
1658 EngSetLastError(ERROR_INVALID_PARAMETER
);
1661 ItemInfo
.hbmpItem
= (HBITMAP
)0;
1662 return IntInsertMenuItem(Menu
, uItem
, fByPosition
, &ItemInfo
);
1665 SetLastNtError(Status
);
1669 UINT FASTCALL
IntGetMenuState( HMENU hMenu
, UINT uId
, UINT uFlags
)
1674 if (!(MenuObject
= UserGetMenuObject(hMenu
)))
1679 if (!(pItem
= MENU_FindItem( &MenuObject
, &uId
, uFlags
))) return -1;
1681 if (pItem
->spSubMenu
)
1683 return (pItem
->spSubMenu
->cItems
<< 8) | ((pItem
->fState
|pItem
->fType
) & 0xff);
1686 return (pItem
->fType
| pItem
->fState
);
1689 HMENU FASTCALL
IntGetSubMenu( HMENU hMenu
, int nPos
)
1694 if (!(MenuObject
= UserGetMenuObject(hMenu
)))
1699 if (!(pItem
= MENU_FindItem( &MenuObject
, (UINT
*)&nPos
, MF_BYPOSITION
))) return NULL
;
1701 if (pItem
->spSubMenu
)
1703 HMENU hsubmenu
= UserHMGetHandle(pItem
->spSubMenu
);
1709 UINT FASTCALL
IntFindSubMenu(HMENU
*hMenu
, HMENU hSubTarget
)
1716 if (((*hMenu
)==(HMENU
)0xffff) ||(!(menu
= UserGetMenuObject(*hMenu
))))
1717 return NO_SELECTED_ITEM
;
1719 item
= menu
->rgItems
;
1720 for (i
= 0; i
< menu
->cItems
; i
++, item
= item
->Next
)//item++)
1722 if (!item
->spSubMenu
)
1726 hSubMenu
= UserHMGetHandle(item
->spSubMenu
);
1727 if (hSubMenu
== hSubTarget
)
1733 HMENU hsubmenu
= hSubMenu
;
1734 UINT pos
= IntFindSubMenu( &hsubmenu
, hSubTarget
);
1735 if (pos
!= NO_SELECTED_ITEM
)
1743 return NO_SELECTED_ITEM
;
1747 HMENU FASTCALL
UserCreateMenu(BOOL PopupMenu
)
1749 PWINSTATION_OBJECT WinStaObject
;
1753 PEPROCESS CurrentProcess
= PsGetCurrentProcess();
1755 if (gpepCSRSS
!= CurrentProcess
)
1758 * gpepCSRSS does not have a Win32WindowStation
1761 Status
= IntValidateWindowStationHandle(CurrentProcess
->Win32WindowStation
,
1766 if (!NT_SUCCESS(Status
))
1768 ERR("Validation of window station handle (%p) failed\n",
1769 CurrentProcess
->Win32WindowStation
);
1770 SetLastNtError(Status
);
1773 Menu
= IntCreateMenu(&Handle
, !PopupMenu
);
1774 if (Menu
->head
.rpdesk
->rpwinstaParent
!= WinStaObject
)
1776 ERR("Desktop Window Station does not match Process one!\n");
1778 ObDereferenceObject(WinStaObject
);
1782 Menu
= IntCreateMenu(&Handle
, !PopupMenu
);
1785 if (Menu
) UserDereferenceObject(Menu
);
1786 return (HMENU
)Handle
;
1794 PROSMENUITEMINFO UnsafeItemInfo
,
1798 ROSMENUITEMINFO ItemInfo
;
1803 Status
= MmCopyFromCaller(&Size
, &UnsafeItemInfo
->cbSize
, sizeof(UINT
));
1804 if (! NT_SUCCESS(Status
))
1806 SetLastNtError(Status
);
1809 if (sizeof(MENUITEMINFOW
) != Size
1810 && FIELD_OFFSET(MENUITEMINFOW
, hbmpItem
) != Size
1811 && sizeof(ROSMENUITEMINFO
) != Size
)
1813 EngSetLastError(ERROR_INVALID_PARAMETER
);
1816 Status
= MmCopyFromCaller(&ItemInfo
, UnsafeItemInfo
, Size
);
1817 if (! NT_SUCCESS(Status
))
1819 SetLastNtError(Status
);
1822 /* If this is a pre-0x0500 _WIN32_WINNT MENUITEMINFOW, you can't
1824 if (FIELD_OFFSET(MENUITEMINFOW
, hbmpItem
) == Size
1825 && 0 != (ItemInfo
.fMask
& MIIM_BITMAP
))
1827 EngSetLastError(ERROR_INVALID_PARAMETER
);
1831 if (!(MenuItem
= MENU_FindItem( &Menu
, &Item
, (ByPosition
? MF_BYPOSITION
: MF_BYCOMMAND
) )))
1833 EngSetLastError(ERROR_MENU_ITEM_NOT_FOUND
);
1839 Ret
= IntSetMenuItemInfo(Menu
, MenuItem
, &ItemInfo
, NULL
);
1843 Ret
= IntGetMenuItemInfo(Menu
, MenuItem
, &ItemInfo
);
1846 Status
= MmCopyToCaller(UnsafeItemInfo
, &ItemInfo
, Size
);
1847 if (! NT_SUCCESS(Status
))
1849 SetLastNtError(Status
);
1861 PROSMENUINFO UnsafeMenuInfo
,
1867 ROSMENUINFO MenuInfo
;
1869 Status
= MmCopyFromCaller(&Size
, &UnsafeMenuInfo
->cbSize
, sizeof(DWORD
));
1870 if (! NT_SUCCESS(Status
))
1872 SetLastNtError(Status
);
1875 if(Size
< sizeof(MENUINFO
) || sizeof(ROSMENUINFO
) < Size
)
1877 EngSetLastError(ERROR_INVALID_PARAMETER
);
1880 Status
= MmCopyFromCaller(&MenuInfo
, UnsafeMenuInfo
, Size
);
1881 if (! NT_SUCCESS(Status
))
1883 SetLastNtError(Status
);
1890 Res
= IntSetMenuInfo(Menu
, &MenuInfo
);
1895 Res
= IntGetMenuInfo(Menu
, &MenuInfo
);
1898 Status
= MmCopyToCaller(UnsafeMenuInfo
, &MenuInfo
, Size
);
1899 if (! NT_SUCCESS(Status
))
1901 SetLastNtError(Status
);
1911 MENU_AdjustMenuItemRect(PMENU menu
, PRECTL rect
)
1913 if (menu
->dwArrowsOn
)
1915 UINT arrow_bitmap_height
;
1917 //GetObjectW(get_up_arrow_bitmap(), sizeof(bmp), &bmp);
1918 arrow_bitmap_height
= gpsi
->oembmi
[65].cy
; ///// Menu up arrow! OBM_UPARROW DFCS_MENUARROWUP
1919 //arrow_bitmap_height = bmp.bmHeight;
1920 rect
->top
+= arrow_bitmap_height
- menu
->iTop
;
1921 rect
->bottom
+= arrow_bitmap_height
- menu
->iTop
;
1938 HWND hWnd
= Menu
->hWnd
;
1939 if (!(pWnd
= UserGetWindowObject(hWnd
))) return FALSE
;
1942 if ((MenuItem
= MENU_FindItem (&Menu
, &uItem
, MF_BYPOSITION
)))
1944 Rect
->left
= MenuItem
->xItem
;
1945 Rect
->top
= MenuItem
->yItem
;
1946 Rect
->right
= MenuItem
->cxItem
; // Do this for now......
1947 Rect
->bottom
= MenuItem
->cyItem
;
1951 ERR("Failed Item Lookup! %d\n", uItem
);
1955 if (Menu
->fFlags
& MNF_POPUP
)
1957 XMove
= pWnd
->rcClient
.left
;
1958 YMove
= pWnd
->rcClient
.top
;
1962 XMove
= pWnd
->rcWindow
.left
;
1963 YMove
= pWnd
->rcWindow
.top
;
1966 Rect
->left
+= XMove
;
1968 Rect
->right
+= XMove
;
1969 Rect
->bottom
+= YMove
;
1974 /* FUNCTIONS *****************************************************************/
1980 NtUserCheckMenuItem(
1986 DECLARE_RETURN(DWORD
);
1988 TRACE("Enter NtUserCheckMenuItem\n");
1989 UserEnterExclusive();
1991 if(!(Menu
= UserGetMenuObject(hMenu
)))
1996 RETURN( IntCheckMenuItem(Menu
, uIDCheckItem
, uCheck
));
1999 TRACE("Leave NtUserCheckMenuItem, ret=%lu\n",_ret_
);
2014 DECLARE_RETURN(BOOL
);
2016 TRACE("Enter NtUserDeleteMenu\n");
2017 UserEnterExclusive();
2019 if(!(Menu
= UserGetMenuObject(hMenu
)))
2024 RETURN( IntRemoveMenuItem(Menu
, uPosition
, uFlags
, TRUE
));
2027 TRACE("Leave NtUserDeleteMenu, ret=%i\n",_ret_
);
2036 NtUserGetTitleBarInfo(
2041 TITLEBARINFO bartitleinfo
;
2042 DECLARE_RETURN(BOOLEAN
);
2043 BOOLEAN retValue
= TRUE
;
2045 TRACE("Enter NtUserGetTitleBarInfo\n");
2046 UserEnterExclusive();
2048 /* Vaildate the windows handle */
2049 if (!(WindowObject
= UserGetWindowObject(hwnd
)))
2051 EngSetLastError(ERROR_INVALID_WINDOW_HANDLE
);
2057 /* Copy our usermode buffer bti to local buffer bartitleinfo */
2058 ProbeForRead(bti
, sizeof(TITLEBARINFO
), 1);
2059 RtlCopyMemory(&bartitleinfo
, bti
, sizeof(TITLEBARINFO
));
2061 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2063 /* Fail copy the data */
2064 EngSetLastError(ERROR_INVALID_PARAMETER
);
2069 /* Get the tile bar info */
2072 retValue
= intGetTitleBarInfo(WindowObject
, &bartitleinfo
);
2077 /* Copy our buffer to user mode buffer bti */
2078 ProbeForWrite(bti
, sizeof(TITLEBARINFO
), 1);
2079 RtlCopyMemory(bti
, &bartitleinfo
, sizeof(TITLEBARINFO
));
2081 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2083 /* Fail copy the data */
2084 EngSetLastError(ERROR_INVALID_PARAMETER
);
2094 TRACE("Leave NtUserGetTitleBarInfo, ret=%u\n",_ret_
);
2102 BOOL FASTCALL
UserDestroyMenu(HMENU hMenu
)
2105 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
2107 if(!(Menu
= UserGetMenuObject(hMenu
)))
2112 //if(Menu->Process != PsGetCurrentProcess())
2113 if (Menu
->head
.rpdesk
!= pti
->rpdesk
)
2115 EngSetLastError(ERROR_ACCESS_DENIED
);
2118 return IntDestroyMenuObject(Menu
, FALSE
, TRUE
);
2129 DECLARE_RETURN(BOOL
);
2131 TRACE("Enter NtUserDestroyMenu\n");
2132 UserEnterExclusive();
2134 if(!(Menu
= UserGetMenuObject(hMenu
)))
2138 if (Menu
->head
.rpdesk
!= gptiCurrent
->rpdesk
)
2140 EngSetLastError(ERROR_ACCESS_DENIED
);
2143 RETURN( IntDestroyMenuObject(Menu
, TRUE
, TRUE
));
2146 TRACE("Leave NtUserDestroyMenu, ret=%i\n",_ret_
);
2155 NtUserEnableMenuItem(
2161 DECLARE_RETURN(UINT
);
2163 TRACE("Enter NtUserEnableMenuItem\n");
2164 UserEnterExclusive();
2166 if(!(Menu
= UserGetMenuObject(hMenu
)))
2171 RETURN( IntEnableMenuItem(Menu
, uIDEnableItem
, uEnable
));
2174 TRACE("Leave NtUserEnableMenuItem, ret=%u\n",_ret_
);
2183 NtUserGetMenuBarInfo(
2193 NTSTATUS Status
= STATUS_SUCCESS
;
2195 DECLARE_RETURN(BOOL
);
2197 TRACE("Enter NtUserGetMenuBarInfo\n");
2200 if (!(pWnd
= UserGetWindowObject(hwnd
)))
2202 EngSetLastError(ERROR_INVALID_WINDOW_HANDLE
);
2209 if (!pWnd
->pcls
->fnid
)
2211 if (pWnd
->pcls
->fnid
!= FNID_MENU
)
2213 WARN("called on invalid window: %d\n", pWnd
->pcls
->fnid
);
2214 EngSetLastError(ERROR_INVALID_MENU_HANDLE
);
2217 // Windows does this! Wine checks for Atom and uses GetWindowLongPtrW.
2218 hMenu
= (HMENU
)co_IntSendMessage(hwnd
, MN_GETHMENU
, 0, 0);
2221 hMenu
= UlongToHandle(pWnd
->IDMenu
);
2224 if (!(pWnd
->style
& WS_SYSMENU
)) RETURN(FALSE
);
2225 Menu
= IntGetSystemMenu(pWnd
, FALSE
, FALSE
);
2226 hMenu
= Menu
->head
.h
;
2237 kmbi
.cbSize
= pmbi
->cbSize
;
2239 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2245 if (kmbi
.cbSize
!= sizeof(MENUBARINFO
))
2247 EngSetLastError(ERROR_INVALID_PARAMETER
);
2251 if (!Menu
) Menu
= UserGetMenuObject(hMenu
);
2255 if (idItem
< 0 || idItem
> Menu
->cItems
)
2258 RECTL_vSetEmptyRect(&kmbi
.rcBar
);
2262 Ret
= IntGetMenuItemRect(pWnd
, Menu
, 0, &kmbi
.rcBar
);
2263 kmbi
.rcBar
.right
= kmbi
.rcBar
.left
+ Menu
->cxMenu
;
2264 kmbi
.rcBar
.bottom
= kmbi
.rcBar
.top
+ Menu
->cyMenu
;
2265 ERR("idItem 0 %d\n",Ret
);
2269 Ret
= IntGetMenuItemRect(pWnd
, Menu
, idItem
-1, &kmbi
.rcBar
);
2270 ERR("idItem X %d\n", Ret
);
2274 kmbi
.hwndMenu
= NULL
;
2275 kmbi
.fBarFocused
= FALSE
;
2276 kmbi
.fFocused
= FALSE
;
2277 //kmbi.fBarFocused = top_popup_hmenu == hMenu;
2281 UINT nPos
= idItem
-1;
2282 kmbi
.fFocused
= Menu
->iItem
== idItem
-1;
2283 //if (kmbi->fFocused && (Menu->rgItems[idItem - 1].spSubMenu))
2284 MenuItem
= MENU_FindItem (&Menu
, &nPos
, MF_BYPOSITION
);
2285 if ( MenuItem
&& kmbi
.fFocused
&& MenuItem
->spSubMenu
)
2287 //kmbi.hwndMenu = Menu->rgItems[idItem - 1].spSubMenu->hWnd;
2288 kmbi
.hwndMenu
= MenuItem
->spSubMenu
->hWnd
;
2293 kmbi.fFocused = kmbi.fBarFocused;
2298 RtlCopyMemory(pmbi
, &kmbi
, sizeof(MENUBARINFO
));
2300 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2302 Status
= _SEH2_GetExceptionCode();
2306 if (!NT_SUCCESS(Status
))
2308 SetLastNtError(Status
);
2315 TRACE("Leave NtUserGetMenuBarInfo, ret=%i\n",_ret_
);
2328 PMENU Menu
, SubMenu
;
2330 DECLARE_RETURN(UINT
);
2332 TRACE("Enter NtUserGetMenuIndex\n");
2335 if ( !(Menu
= UserGetMenuObject(hMenu
)) ||
2336 !(SubMenu
= UserGetMenuObject(hSubMenu
)) )
2339 MenuItem
= Menu
->rgItems
;
2342 if (MenuItem
->spSubMenu
== SubMenu
)
2343 RETURN(MenuItem
->wID
);
2344 MenuItem
= MenuItem
->Next
;
2350 TRACE("Leave NtUserGetMenuIndex, ret=%u\n",_ret_
);
2359 NtUserGetMenuItemRect(
2370 NTSTATUS Status
= STATUS_SUCCESS
;
2371 DECLARE_RETURN(BOOL
);
2373 TRACE("Enter NtUserGetMenuItemRect\n");
2376 if (!(Menu
= UserGetMenuObject(hMenu
)))
2381 if ((MenuItem
= MENU_FindItem (&Menu
, &uItem
, MF_BYPOSITION
)))
2383 Rect
.left
= MenuItem
->xItem
;
2384 Rect
.top
= MenuItem
->yItem
;
2385 Rect
.right
= MenuItem
->cxItem
; // Do this for now......
2386 Rect
.bottom
= MenuItem
->cyItem
;
2396 if (lprcItem
== NULL
) RETURN( FALSE
);
2398 if (!(ReferenceWnd
= UserGetWindowObject(hWnd
))) RETURN( FALSE
);
2400 if (Menu
->fFlags
& MNF_POPUP
)
2402 XMove
= ReferenceWnd
->rcClient
.left
;
2403 YMove
= ReferenceWnd
->rcClient
.top
;
2407 XMove
= ReferenceWnd
->rcWindow
.left
;
2408 YMove
= ReferenceWnd
->rcWindow
.top
;
2413 Rect
.right
+= XMove
;
2414 Rect
.bottom
+= YMove
;
2418 RtlCopyMemory(lprcItem
, &Rect
, sizeof(RECTL
));
2420 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2422 Status
= _SEH2_GetExceptionCode();
2426 if (!NT_SUCCESS(Status
))
2428 SetLastNtError(Status
);
2434 TRACE("Leave NtUserGetMenuItemRect, ret=%i\n",_ret_
);
2443 NtUserHiliteMenuItem(
2451 DECLARE_RETURN(BOOLEAN
);
2453 TRACE("Enter NtUserHiliteMenuItem\n");
2454 UserEnterExclusive();
2456 if(!(Window
= UserGetWindowObject(hWnd
)))
2458 EngSetLastError(ERROR_INVALID_WINDOW_HANDLE
);
2462 if(!(Menu
= UserGetMenuObject(hMenu
)))
2464 EngSetLastError(ERROR_INVALID_MENU_HANDLE
);
2468 RETURN( IntHiliteMenuItem(Window
, Menu
, uItemHilite
, uHilite
));
2471 TRACE("Leave NtUserHiliteMenuItem, ret=%u\n",_ret_
);
2481 NtUserMenuItemFromPoint(
2491 DECLARE_RETURN(int);
2493 TRACE("Enter NtUserMenuItemFromPoint\n");
2494 UserEnterExclusive();
2496 if (!(Menu
= UserGetMenuObject(hMenu
)))
2501 if (!(Window
= UserGetWindowObject(Menu
->hWnd
)))
2506 X
-= Window
->rcWindow
.left
;
2507 Y
-= Window
->rcWindow
.top
;
2510 for (i
= 0; NULL
!= mi
; i
++)//, mi++)
2513 Rect
.left
= mi
->xItem
;
2514 Rect
.top
= mi
->yItem
;
2515 Rect
.right
= mi
->cxItem
; // Do this for now......
2516 Rect
.bottom
= mi
->cyItem
;
2517 //MENU_AdjustMenuItemRect(Menu, &Rect); Need gpsi OBMI via callback!
2518 if (RECTL_bPointInRect(&Rect
, X
, Y
))
2525 RETURN( (mi
? i
: NO_SELECTED_ITEM
));
2528 TRACE("Leave NtUserMenuItemFromPoint, ret=%i\n",_ret_
);
2544 DECLARE_RETURN(BOOL
);
2546 TRACE("Enter NtUserRemoveMenu\n");
2547 UserEnterExclusive();
2549 if(!(Menu
= UserGetMenuObject(hMenu
)))
2554 RETURN(IntRemoveMenuItem(Menu
, uPosition
, uFlags
, FALSE
));
2557 TRACE("Leave NtUserRemoveMenu, ret=%i\n",_ret_
);
2567 NtUserSetMenuContextHelpId(
2569 DWORD dwContextHelpId
)
2572 DECLARE_RETURN(BOOL
);
2574 TRACE("Enter NtUserSetMenuContextHelpId\n");
2575 UserEnterExclusive();
2577 if(!(Menu
= UserGetMenuObject(hMenu
)))
2582 RETURN(IntSetMenuContextHelpId(Menu
, dwContextHelpId
));
2585 TRACE("Leave NtUserSetMenuContextHelpId, ret=%i\n",_ret_
);
2594 NtUserSetMenuDefaultItem(
2600 DECLARE_RETURN(BOOL
);
2602 TRACE("Enter NtUserSetMenuDefaultItem\n");
2603 UserEnterExclusive();
2605 if(!(Menu
= UserGetMenuObject(hMenu
)))
2610 RETURN( UserSetMenuDefaultItem(Menu
, uItem
, fByPos
));
2613 TRACE("Leave NtUserSetMenuDefaultItem, ret=%i\n",_ret_
);
2622 NtUserSetMenuFlagRtoL(
2626 DECLARE_RETURN(BOOL
);
2628 TRACE("Enter NtUserSetMenuFlagRtoL\n");
2629 UserEnterExclusive();
2631 if(!(Menu
= UserGetMenuObject(hMenu
)))
2636 RETURN(IntSetMenuFlagRtoL(Menu
));
2639 TRACE("Leave NtUserSetMenuFlagRtoL, ret=%i\n",_ret_
);
2648 NtUserThunkedMenuInfo(
2653 DECLARE_RETURN(BOOL
);
2655 TRACE("Enter NtUserThunkedMenuInfo\n");
2656 UserEnterExclusive();
2658 if (!(Menu
= UserGetMenuObject(hMenu
)))
2663 RETURN(UserMenuInfo(Menu
, (PROSMENUINFO
)lpcmi
, TRUE
));
2666 TRACE("Leave NtUserThunkedMenuInfo, ret=%i\n",_ret_
);
2675 NtUserThunkedMenuItemInfo(
2680 LPMENUITEMINFOW lpmii
,
2681 PUNICODE_STRING lpszCaption
)
2685 UNICODE_STRING lstrCaption
;
2686 DECLARE_RETURN(BOOL
);
2688 TRACE("Enter NtUserThunkedMenuItemInfo\n");
2689 UserEnterExclusive();
2691 /* lpszCaption may be NULL, check for it and call RtlInitUnicodeString()
2692 if bInsert == TRUE call UserInsertMenuItem() else UserSetMenuItemInfo() */
2694 if (!(Menu
= UserGetMenuObject(hMenu
)))
2699 lstrCaption
.Buffer
= NULL
;
2701 /* Check if we got a Caption */
2702 if (lpszCaption
&& lpszCaption
->Buffer
)
2704 /* Copy the string to kernel mode */
2705 Status
= ProbeAndCaptureUnicodeString( &lstrCaption
,
2708 if (!NT_SUCCESS(Status
))
2710 ERR("Failed to capture MenuItem Caption (status 0x%08x)\n",Status
);
2711 SetLastNtError(Status
);
2717 if (bInsert
) RETURN( UserInsertMenuItem(Menu
, uItem
, fByPosition
, lpmii
));
2719 RETURN( UserMenuItemInfo(Menu
, uItem
, fByPosition
, (PROSMENUITEMINFO
)lpmii
, TRUE
));
2722 TRACE("Leave NtUserThunkedMenuItemInfo, ret=%i\n",_ret_
);