Implement NtUserGetMenuBarInfo. Tested with MPlayerC with OBJID_MENU only, the rest...
[reactos.git] / reactos / subsys / win32k / ntuser / menu.c
1 /*
2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
4 *
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.
9 *
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.
14 *
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.
18 */
19 /* $Id$
20 *
21 * COPYRIGHT: See COPYING in the top level directory
22 * PROJECT: ReactOS kernel
23 * PURPOSE: Menus
24 * FILE: subsys/win32k/ntuser/menu.c
25 * PROGRAMER: Thomas Weidenmueller (w3seek@users.sourceforge.net)
26 * REVISION HISTORY:
27 * 07/30/2003 CSH Created
28 */
29 /* INCLUDES ******************************************************************/
30
31 #include <w32k.h>
32
33 #define NDEBUG
34 #include <debug.h>
35
36
37 /* STATIC FUNCTION ***********************************************************/
38
39 static
40 BOOL FASTCALL
41 UserMenuItemInfo(
42 PMENU_OBJECT Menu,
43 UINT Item,
44 BOOL ByPosition,
45 PROSMENUITEMINFO UnsafeItemInfo,
46 BOOL SetOrGet);
47
48 static
49 BOOL FASTCALL
50 UserMenuInfo(
51 PMENU_OBJECT Menu,
52 PROSMENUINFO UnsafeMenuInfo,
53 BOOL SetOrGet);
54
55 /* INTERNAL ******************************************************************/
56
57 /* maximum number of menu items a menu can contain */
58 #define MAX_MENU_ITEMS (0x4000)
59 #define MAX_GOINTOSUBMENU (0x10)
60
61 #define UpdateMenuItemState(state, change) \
62 {\
63 if((change) & MFS_DISABLED) { \
64 (state) |= MFS_DISABLED; \
65 } else { \
66 (state) &= ~MFS_DISABLED; \
67 } \
68 if((change) & MFS_CHECKED) { \
69 (state) |= MFS_CHECKED; \
70 } else { \
71 (state) &= ~MFS_CHECKED; \
72 } \
73 if((change) & MFS_HILITE) { \
74 (state) |= MFS_HILITE; \
75 } else { \
76 (state) &= ~MFS_HILITE; \
77 } \
78 if((change) & MFS_DEFAULT) { \
79 (state) |= MFS_DEFAULT; \
80 } else { \
81 (state) &= ~MFS_DEFAULT; \
82 } \
83 if((change) & MF_MOUSESELECT) { \
84 (state) |= MF_MOUSESELECT; \
85 } else { \
86 (state) &= ~MF_MOUSESELECT; \
87 } \
88 }
89
90 #define FreeMenuText(MenuItem) \
91 { \
92 if((MENU_ITEM_TYPE((MenuItem)->fType) == MF_STRING) && \
93 (MenuItem)->Text.Length) { \
94 RtlFreeUnicodeString(&(MenuItem)->Text); \
95 } \
96 }
97
98 #define InRect(r, x, y) \
99 ( ( ((r).right >= x)) && \
100 ( ((r).left <= x)) && \
101 ( ((r).bottom >= y)) && \
102 ( ((r).top <= y)) )
103
104 NTSTATUS FASTCALL
105 InitMenuImpl(VOID)
106 {
107 return(STATUS_SUCCESS);
108 }
109
110 NTSTATUS FASTCALL
111 CleanupMenuImpl(VOID)
112 {
113 return(STATUS_SUCCESS);
114 }
115
116 PMENU_OBJECT FASTCALL UserGetMenuObject(HMENU hMenu)
117 {
118 PMENU_OBJECT Menu;
119
120 if (!hMenu)
121 {
122 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE);
123 return NULL;
124 }
125
126 Menu = (PMENU_OBJECT)UserGetObject(&gHandleTable, hMenu, otMenu);
127 if (!Menu)
128 {
129 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE);
130 return NULL;
131 }
132
133 ASSERT(USER_BODY_TO_HEADER(Menu)->RefCount >= 0);
134 return Menu;
135 }
136
137
138 #if 0
139 void FASTCALL
140 DumpMenuItemList(PMENU_ITEM MenuItem)
141 {
142 UINT cnt = 0;
143 while(MenuItem)
144 {
145 if(MenuItem->Text.Length)
146 DbgPrint(" %d. %wZ\n", ++cnt, &MenuItem->Text);
147 else
148 DbgPrint(" %d. NO TEXT dwTypeData==%d\n", ++cnt, (DWORD)MenuItem->Text.Buffer);
149 DbgPrint(" fType=");
150 if(MFT_BITMAP & MenuItem->fType)
151 DbgPrint("MFT_BITMAP ");
152 if(MFT_MENUBARBREAK & MenuItem->fType)
153 DbgPrint("MFT_MENUBARBREAK ");
154 if(MFT_MENUBREAK & MenuItem->fType)
155 DbgPrint("MFT_MENUBREAK ");
156 if(MFT_OWNERDRAW & MenuItem->fType)
157 DbgPrint("MFT_OWNERDRAW ");
158 if(MFT_RADIOCHECK & MenuItem->fType)
159 DbgPrint("MFT_RADIOCHECK ");
160 if(MFT_RIGHTJUSTIFY & MenuItem->fType)
161 DbgPrint("MFT_RIGHTJUSTIFY ");
162 if(MFT_SEPARATOR & MenuItem->fType)
163 DbgPrint("MFT_SEPARATOR ");
164 if(MFT_STRING & MenuItem->fType)
165 DbgPrint("MFT_STRING ");
166 DbgPrint("\n fState=");
167 if(MFS_DISABLED & MenuItem->fState)
168 DbgPrint("MFS_DISABLED ");
169 else
170 DbgPrint("MFS_ENABLED ");
171 if(MFS_CHECKED & MenuItem->fState)
172 DbgPrint("MFS_CHECKED ");
173 else
174 DbgPrint("MFS_UNCHECKED ");
175 if(MFS_HILITE & MenuItem->fState)
176 DbgPrint("MFS_HILITE ");
177 else
178 DbgPrint("MFS_UNHILITE ");
179 if(MFS_DEFAULT & MenuItem->fState)
180 DbgPrint("MFS_DEFAULT ");
181 if(MFS_GRAYED & MenuItem->fState)
182 DbgPrint("MFS_GRAYED ");
183 DbgPrint("\n wId=%d\n", MenuItem->wID);
184 MenuItem = MenuItem->Next;
185 }
186 DbgPrint("Entries: %d\n", cnt);
187 return;
188 }
189 #endif
190
191 PMENU_OBJECT FASTCALL
192 IntGetMenuObject(HMENU hMenu)
193 {
194 PMENU_OBJECT Menu = UserGetMenuObject(hMenu);
195 if (Menu)
196 {
197 ASSERT(USER_BODY_TO_HEADER(Menu)->RefCount >= 0);
198
199 USER_BODY_TO_HEADER(Menu)->RefCount++;
200 }
201 return Menu;
202 }
203
204 BOOL FASTCALL
205 IntFreeMenuItem(PMENU_OBJECT Menu, PMENU_ITEM MenuItem,
206 BOOL RemoveFromList, BOOL bRecurse)
207 {
208 FreeMenuText(MenuItem);
209 if(RemoveFromList)
210 {
211 /* FIXME - Remove from List */
212 Menu->MenuInfo.MenuItemCount--;
213 }
214 if(bRecurse && MenuItem->hSubMenu)
215 {
216 PMENU_OBJECT SubMenu;
217 SubMenu = UserGetMenuObject(MenuItem->hSubMenu );
218 if(SubMenu)
219 {
220 IntDestroyMenuObject(SubMenu, bRecurse, TRUE);
221 }
222 }
223
224 /* Free memory */
225 ExFreePool(MenuItem);
226
227 return TRUE;
228 }
229
230 BOOL FASTCALL
231 IntRemoveMenuItem(PMENU_OBJECT Menu, UINT uPosition, UINT uFlags,
232 BOOL bRecurse)
233 {
234 PMENU_ITEM PrevMenuItem, MenuItem;
235 if(IntGetMenuItemByFlag(Menu, uPosition, uFlags, &MenuItem,
236 &PrevMenuItem) > -1)
237 {
238 if(MenuItem)
239 {
240 if(PrevMenuItem)
241 PrevMenuItem->Next = MenuItem->Next;
242 else
243 {
244 Menu->MenuItemList = MenuItem->Next;
245 }
246 return IntFreeMenuItem(Menu, MenuItem, TRUE, bRecurse);
247 }
248 }
249 return FALSE;
250 }
251
252 UINT FASTCALL
253 IntDeleteMenuItems(PMENU_OBJECT Menu, BOOL bRecurse)
254 {
255 UINT res = 0;
256 PMENU_ITEM NextItem;
257 PMENU_ITEM CurItem = Menu->MenuItemList;
258 while(CurItem)
259 {
260 NextItem = CurItem->Next;
261 IntFreeMenuItem(Menu, CurItem, FALSE, bRecurse);
262 CurItem = NextItem;
263 res++;
264 }
265 Menu->MenuInfo.MenuItemCount = 0;
266 Menu->MenuItemList = NULL;
267 return res;
268 }
269
270 BOOL FASTCALL
271 IntDestroyMenuObject(PMENU_OBJECT Menu,
272 BOOL bRecurse, BOOL RemoveFromProcess)
273 {
274 if(Menu)
275 {
276 PWINSTATION_OBJECT WindowStation;
277 NTSTATUS Status;
278
279 /* remove all menu items */
280 IntDeleteMenuItems(Menu, bRecurse); /* do not destroy submenus */
281
282 if(RemoveFromProcess)
283 {
284 RemoveEntryList(&Menu->ListEntry);
285 }
286
287 Status = ObReferenceObjectByHandle(Menu->Process->Win32WindowStation,
288 0,
289 ExWindowStationObjectType,
290 KernelMode,
291 (PVOID*)&WindowStation,
292 NULL);
293 if(NT_SUCCESS(Status))
294 {
295 ObmDeleteObject(Menu->MenuInfo.Self, otMenu);
296 ObDereferenceObject(WindowStation);
297 return TRUE;
298 }
299 }
300 return FALSE;
301 }
302
303 PMENU_OBJECT FASTCALL
304 IntCreateMenu(PHANDLE Handle, BOOL IsMenuBar)
305 {
306 PMENU_OBJECT Menu;
307
308 Menu = (PMENU_OBJECT)ObmCreateObject(
309 &gHandleTable, Handle,
310 otMenu, sizeof(MENU_OBJECT));
311
312 if(!Menu)
313 {
314 *Handle = 0;
315 return NULL;
316 }
317
318 Menu->Process = PsGetCurrentProcess();
319 Menu->RtoL = FALSE; /* default */
320 Menu->MenuInfo.cbSize = sizeof(MENUINFO); /* not used */
321 Menu->MenuInfo.fMask = 0; /* not used */
322 Menu->MenuInfo.dwStyle = 0; /* FIXME */
323 Menu->MenuInfo.cyMax = 0; /* default */
324 Menu->MenuInfo.hbrBack =
325 NtGdiCreateSolidBrush(RGB(192, 192, 192), 0); /* FIXME: default background color */
326 Menu->MenuInfo.dwContextHelpID = 0; /* default */
327 Menu->MenuInfo.dwMenuData = 0; /* default */
328 Menu->MenuInfo.Self = *Handle;
329 Menu->MenuInfo.FocusedItem = NO_SELECTED_ITEM;
330 Menu->MenuInfo.Flags = (IsMenuBar ? 0 : MF_POPUP);
331 Menu->MenuInfo.Wnd = NULL;
332 Menu->MenuInfo.WndOwner = NULL;
333 Menu->MenuInfo.Height = 0;
334 Menu->MenuInfo.Width = 0;
335 Menu->MenuInfo.TimeToHide = FALSE;
336
337 Menu->MenuInfo.MenuItemCount = 0;
338 Menu->MenuItemList = NULL;
339
340 /* Insert menu item into process menu handle list */
341 InsertTailList(&PsGetWin32Process()->MenuListHead, &Menu->ListEntry);
342
343 return Menu;
344 }
345
346 BOOL FASTCALL
347 IntCloneMenuItems(PMENU_OBJECT Destination, PMENU_OBJECT Source)
348 {
349 PMENU_ITEM MenuItem, NewMenuItem = NULL;
350 PMENU_ITEM Old = NULL;
351
352 if(!Source->MenuInfo.MenuItemCount)
353 return FALSE;
354
355 MenuItem = Source->MenuItemList;
356 while(MenuItem)
357 {
358 Old = NewMenuItem;
359 if(NewMenuItem)
360 NewMenuItem->Next = MenuItem;
361 NewMenuItem = ExAllocatePoolWithTag(PagedPool, sizeof(MENU_ITEM), TAG_MENUITEM);
362 if(!NewMenuItem)
363 break;
364 NewMenuItem->fType = MenuItem->fType;
365 NewMenuItem->fState = MenuItem->fState;
366 NewMenuItem->wID = MenuItem->wID;
367 NewMenuItem->hSubMenu = MenuItem->hSubMenu;
368 NewMenuItem->hbmpChecked = MenuItem->hbmpChecked;
369 NewMenuItem->hbmpUnchecked = MenuItem->hbmpUnchecked;
370 NewMenuItem->dwItemData = MenuItem->dwItemData;
371 if((MENU_ITEM_TYPE(NewMenuItem->fType) == MF_STRING))
372 {
373 if(MenuItem->Text.Length)
374 {
375 NewMenuItem->Text.Length = 0;
376 NewMenuItem->Text.MaximumLength = MenuItem->Text.MaximumLength;
377 NewMenuItem->Text.Buffer = (PWSTR)ExAllocatePoolWithTag(PagedPool, MenuItem->Text.MaximumLength, TAG_STRING);
378 if(!NewMenuItem->Text.Buffer)
379 {
380 ExFreePool(NewMenuItem);
381 break;
382 }
383 RtlCopyUnicodeString(&NewMenuItem->Text, &MenuItem->Text);
384 }
385 else
386 {
387 NewMenuItem->Text.Buffer = MenuItem->Text.Buffer;
388 }
389 }
390 else
391 {
392 NewMenuItem->Text.Buffer = MenuItem->Text.Buffer;
393 }
394 NewMenuItem->hbmpItem = MenuItem->hbmpItem;
395
396 NewMenuItem->Next = NULL;
397 if(Old)
398 Old->Next = NewMenuItem;
399 else
400 Destination->MenuItemList = NewMenuItem;
401 Destination->MenuInfo.MenuItemCount++;
402 MenuItem = MenuItem->Next;
403 }
404
405 return TRUE;
406 }
407
408 PMENU_OBJECT FASTCALL
409 IntCloneMenu(PMENU_OBJECT Source)
410 {
411 HANDLE hMenu;
412 PMENU_OBJECT Menu;
413
414 if(!Source)
415 return NULL;
416
417 Menu = (PMENU_OBJECT)ObmCreateObject(
418 &gHandleTable, &hMenu,
419 otMenu, sizeof(MENU_OBJECT));
420
421 if(!Menu)
422 return NULL;
423
424 Menu->Process = PsGetCurrentProcess();
425 Menu->RtoL = Source->RtoL;
426 Menu->MenuInfo.cbSize = sizeof(MENUINFO); /* not used */
427 Menu->MenuInfo.fMask = Source->MenuInfo.fMask;
428 Menu->MenuInfo.dwStyle = Source->MenuInfo.dwStyle;
429 Menu->MenuInfo.cyMax = Source->MenuInfo.cyMax;
430 Menu->MenuInfo.hbrBack = Source->MenuInfo.hbrBack;
431 Menu->MenuInfo.dwContextHelpID = Source->MenuInfo.dwContextHelpID;
432 Menu->MenuInfo.dwMenuData = Source->MenuInfo.dwMenuData;
433 Menu->MenuInfo.Self = hMenu;
434 Menu->MenuInfo.FocusedItem = NO_SELECTED_ITEM;
435 Menu->MenuInfo.Wnd = NULL;
436 Menu->MenuInfo.WndOwner = NULL;
437 Menu->MenuInfo.Height = 0;
438 Menu->MenuInfo.Width = 0;
439 Menu->MenuInfo.TimeToHide = FALSE;
440
441 Menu->MenuInfo.MenuItemCount = 0;
442 Menu->MenuItemList = NULL;
443
444 /* Insert menu item into process menu handle list */
445 InsertTailList(&PsGetWin32Process()->MenuListHead, &Menu->ListEntry);
446
447 IntCloneMenuItems(Menu, Source);
448
449 return Menu;
450 }
451
452 BOOL FASTCALL
453 IntSetMenuFlagRtoL(PMENU_OBJECT Menu)
454 {
455 Menu->RtoL = TRUE;
456 return TRUE;
457 }
458
459 BOOL FASTCALL
460 IntSetMenuContextHelpId(PMENU_OBJECT Menu, DWORD dwContextHelpId)
461 {
462 Menu->MenuInfo.dwContextHelpID = dwContextHelpId;
463 return TRUE;
464 }
465
466 BOOL FASTCALL
467 IntGetMenuInfo(PMENU_OBJECT Menu, PROSMENUINFO lpmi)
468 {
469 if(lpmi->fMask & MIM_BACKGROUND)
470 lpmi->hbrBack = Menu->MenuInfo.hbrBack;
471 if(lpmi->fMask & MIM_HELPID)
472 lpmi->dwContextHelpID = Menu->MenuInfo.dwContextHelpID;
473 if(lpmi->fMask & MIM_MAXHEIGHT)
474 lpmi->cyMax = Menu->MenuInfo.cyMax;
475 if(lpmi->fMask & MIM_MENUDATA)
476 lpmi->dwMenuData = Menu->MenuInfo.dwMenuData;
477 if(lpmi->fMask & MIM_STYLE)
478 lpmi->dwStyle = Menu->MenuInfo.dwStyle;
479 if (sizeof(MENUINFO) < lpmi->cbSize)
480 {
481 RtlCopyMemory((char *) lpmi + sizeof(MENUINFO),
482 (char *) &Menu->MenuInfo + sizeof(MENUINFO),
483 lpmi->cbSize - sizeof(MENUINFO));
484 }
485
486 return TRUE;
487 }
488
489
490 BOOL FASTCALL
491 IntIsMenu(HMENU hMenu)
492 {
493 PMENU_OBJECT Menu;
494
495 if((Menu = UserGetMenuObject(hMenu)))
496 {
497 return TRUE;
498 }
499 return FALSE;
500 }
501
502
503 BOOL FASTCALL
504 IntSetMenuInfo(PMENU_OBJECT Menu, PROSMENUINFO lpmi)
505 {
506 if(lpmi->fMask & MIM_BACKGROUND)
507 Menu->MenuInfo.hbrBack = lpmi->hbrBack;
508 if(lpmi->fMask & MIM_HELPID)
509 Menu->MenuInfo.dwContextHelpID = lpmi->dwContextHelpID;
510 if(lpmi->fMask & MIM_MAXHEIGHT)
511 Menu->MenuInfo.cyMax = lpmi->cyMax;
512 if(lpmi->fMask & MIM_MENUDATA)
513 Menu->MenuInfo.dwMenuData = lpmi->dwMenuData;
514 if(lpmi->fMask & MIM_STYLE)
515 Menu->MenuInfo.dwStyle = lpmi->dwStyle;
516 if(lpmi->fMask & MIM_APPLYTOSUBMENUS)
517 {
518 /* FIXME */
519 }
520 if (sizeof(MENUINFO) < lpmi->cbSize)
521 {
522 Menu->MenuInfo.FocusedItem = lpmi->FocusedItem;
523 Menu->MenuInfo.Height = lpmi->Height;
524 Menu->MenuInfo.Width = lpmi->Width;
525 Menu->MenuInfo.Wnd = lpmi->Wnd;
526 Menu->MenuInfo.WndOwner = lpmi->WndOwner;
527 Menu->MenuInfo.TimeToHide = lpmi->TimeToHide;
528 }
529
530 return TRUE;
531 }
532
533
534 int FASTCALL
535 IntGetMenuItemByFlag(PMENU_OBJECT Menu, UINT uSearchBy, UINT fFlag,
536 PMENU_ITEM *MenuItem, PMENU_ITEM *PrevMenuItem)
537 {
538 PMENU_ITEM PrevItem = NULL;
539 PMENU_ITEM CurItem = Menu->MenuItemList;
540 int p;
541 int ret;
542
543 if(MF_BYPOSITION & fFlag)
544 {
545 p = uSearchBy;
546 while(CurItem && (p > 0))
547 {
548 PrevItem = CurItem;
549 CurItem = CurItem->Next;
550 p--;
551 }
552 if(CurItem)
553 {
554 if(MenuItem)
555 *MenuItem = CurItem;
556 if(PrevMenuItem)
557 *PrevMenuItem = PrevItem;
558 }
559 else
560 {
561 if(MenuItem)
562 *MenuItem = NULL;
563 if(PrevMenuItem)
564 *PrevMenuItem = NULL; /* ? */
565 return -1;
566 }
567
568 return uSearchBy - p;
569 }
570 else
571 {
572 p = 0;
573 while(CurItem)
574 {
575 if(CurItem->wID == uSearchBy)
576 {
577 if(MenuItem)
578 *MenuItem = CurItem;
579 if(PrevMenuItem)
580 *PrevMenuItem = PrevItem;
581 return p;
582 }
583 else if (0 != (CurItem->fType & MF_POPUP))
584 {
585 Menu = UserGetMenuObject(CurItem->hSubMenu);
586 if (NULL != Menu)
587 {
588 ret = IntGetMenuItemByFlag(Menu, uSearchBy, fFlag,
589 MenuItem, PrevMenuItem);
590 if (-1 != ret)
591 {
592 return ret;
593 }
594 }
595 }
596 PrevItem = CurItem;
597 CurItem = CurItem->Next;
598 p++;
599 }
600 }
601 return -1;
602 }
603
604
605 int FASTCALL
606 IntInsertMenuItemToList(PMENU_OBJECT Menu, PMENU_ITEM MenuItem, int pos)
607 {
608 PMENU_ITEM CurItem;
609 PMENU_ITEM LastItem = NULL;
610 UINT npos = 0;
611
612 CurItem = Menu->MenuItemList;
613 if(pos <= -1)
614 {
615 while(CurItem)
616 {
617 LastItem = CurItem;
618 CurItem = CurItem->Next;
619 npos++;
620 }
621 }
622 else
623 {
624 while(CurItem && (pos > 0))
625 {
626 LastItem = CurItem;
627 CurItem = CurItem->Next;
628 pos--;
629 npos++;
630 }
631 }
632
633 if(CurItem)
634 {
635 if(LastItem)
636 {
637 /* insert the item before CurItem */
638 MenuItem->Next = LastItem->Next;
639 LastItem->Next = MenuItem;
640 }
641 else
642 {
643 /* insert at the beginning */
644 Menu->MenuItemList = MenuItem;
645 MenuItem->Next = CurItem;
646 }
647 }
648 else
649 {
650 if(LastItem)
651 {
652 /* append item */
653 LastItem->Next = MenuItem;
654 MenuItem->Next = NULL;
655 }
656 else
657 {
658 /* insert first item */
659 Menu->MenuItemList = MenuItem;
660 MenuItem->Next = NULL;
661 }
662 }
663 Menu->MenuInfo.MenuItemCount++;
664
665 return npos;
666 }
667
668 BOOL FASTCALL
669 IntGetMenuItemInfo(PMENU_OBJECT Menu, /* UNUSED PARAM!! */
670 PMENU_ITEM MenuItem, PROSMENUITEMINFO lpmii)
671 {
672 NTSTATUS Status;
673
674 if(lpmii->fMask & MIIM_BITMAP)
675 {
676 lpmii->hbmpItem = MenuItem->hbmpItem;
677 }
678 if(lpmii->fMask & MIIM_CHECKMARKS)
679 {
680 lpmii->hbmpChecked = MenuItem->hbmpChecked;
681 lpmii->hbmpUnchecked = MenuItem->hbmpUnchecked;
682 }
683 if(lpmii->fMask & MIIM_DATA)
684 {
685 lpmii->dwItemData = MenuItem->dwItemData;
686 }
687 if(lpmii->fMask & (MIIM_FTYPE | MIIM_TYPE))
688 {
689 lpmii->fType = MenuItem->fType;
690 }
691 if(lpmii->fMask & MIIM_ID)
692 {
693 lpmii->wID = MenuItem->wID;
694 }
695 if(lpmii->fMask & MIIM_STATE)
696 {
697 lpmii->fState = MenuItem->fState;
698 }
699 if(lpmii->fMask & MIIM_SUBMENU)
700 {
701 lpmii->hSubMenu = MenuItem->hSubMenu;
702 }
703 if (lpmii->fMask & (MIIM_STRING | MIIM_TYPE))
704 {
705 if (lpmii->dwTypeData == NULL)
706 {
707 lpmii->cch = MenuItem->Text.Length / sizeof(WCHAR);
708 }
709 else
710 {
711 Status = MmCopyToCaller(lpmii->dwTypeData, MenuItem->Text.Buffer,
712 min(lpmii->cch * sizeof(WCHAR),
713 MenuItem->Text.MaximumLength));
714 if (! NT_SUCCESS(Status))
715 {
716 SetLastNtError(Status);
717 return FALSE;
718 }
719 }
720 }
721
722 if (sizeof(ROSMENUITEMINFO) == lpmii->cbSize)
723 {
724 lpmii->Rect = MenuItem->Rect;
725 lpmii->XTab = MenuItem->XTab;
726 }
727
728 return TRUE;
729 }
730
731 BOOL FASTCALL
732 IntSetMenuItemInfo(PMENU_OBJECT MenuObject, PMENU_ITEM MenuItem, PROSMENUITEMINFO lpmii)
733 {
734 PMENU_OBJECT SubMenuObject;
735
736 if(!MenuItem || !MenuObject || !lpmii)
737 {
738 return FALSE;
739 }
740
741 MenuItem->fType = lpmii->fType;
742
743 if(lpmii->fMask & MIIM_BITMAP)
744 {
745 MenuItem->hbmpItem = lpmii->hbmpItem;
746 }
747 if(lpmii->fMask & MIIM_CHECKMARKS)
748 {
749 MenuItem->hbmpChecked = lpmii->hbmpChecked;
750 MenuItem->hbmpUnchecked = lpmii->hbmpUnchecked;
751 }
752 if(lpmii->fMask & MIIM_DATA)
753 {
754 MenuItem->dwItemData = lpmii->dwItemData;
755 }
756 if(lpmii->fMask & (MIIM_FTYPE | MIIM_TYPE))
757 {
758 /*
759 * Delete the menu item type when changing type from
760 * MF_STRING.
761 */
762 if (MenuItem->fType != lpmii->fType &&
763 MENU_ITEM_TYPE(MenuItem->fType) == MF_STRING)
764 {
765 FreeMenuText(MenuItem);
766 RtlInitUnicodeString(&MenuItem->Text, NULL);
767 }
768 MenuItem->fType = lpmii->fType;
769 }
770 if(lpmii->fMask & MIIM_ID)
771 {
772 MenuItem->wID = lpmii->wID;
773 }
774 if(lpmii->fMask & MIIM_STATE)
775 {
776 /* remove MFS_DEFAULT flag from all other menu items if this item
777 has the MFS_DEFAULT state */
778 if(lpmii->fState & MFS_DEFAULT)
779 UserSetMenuDefaultItem(MenuObject, -1, 0);
780 /* update the menu item state flags */
781 UpdateMenuItemState(MenuItem->fState, lpmii->fState);
782 }
783
784 if(lpmii->fMask & MIIM_SUBMENU)
785 {
786 MenuItem->hSubMenu = lpmii->hSubMenu;
787 /* Make sure the submenu is marked as a popup menu */
788 if (MenuItem->hSubMenu)
789 {
790 SubMenuObject = UserGetMenuObject(MenuItem->hSubMenu);
791 if (SubMenuObject != NULL)
792 {
793 SubMenuObject->MenuInfo.Flags |= MF_POPUP;
794 MenuItem->fType |= MF_POPUP;
795 }
796 else
797 {
798 MenuItem->fType &= ~MF_POPUP;
799 }
800 }
801 else
802 {
803 MenuItem->fType &= ~MF_POPUP;
804 }
805 }
806 if ((lpmii->fMask & (MIIM_TYPE | MIIM_STRING)) &&
807 (MENU_ITEM_TYPE(lpmii->fType) == MF_STRING))
808 {
809 FreeMenuText(MenuItem);
810
811 if(lpmii->dwTypeData && lpmii->cch)
812 {
813 UNICODE_STRING Source;
814
815 Source.Length =
816 Source.MaximumLength = lpmii->cch * sizeof(WCHAR);
817 Source.Buffer = lpmii->dwTypeData;
818
819 MenuItem->Text.Buffer = (PWSTR)ExAllocatePoolWithTag(
820 PagedPool, Source.Length + sizeof(WCHAR), TAG_STRING);
821 if(MenuItem->Text.Buffer != NULL)
822 {
823 MenuItem->Text.Length = 0;
824 MenuItem->Text.MaximumLength = Source.Length + sizeof(WCHAR);
825 RtlCopyUnicodeString(&MenuItem->Text, &Source);
826 MenuItem->Text.Buffer[MenuItem->Text.Length / sizeof(WCHAR)] = 0;
827 }
828 else
829 {
830 RtlInitUnicodeString(&MenuItem->Text, NULL);
831 }
832 }
833 else
834 {
835 if (0 == (MenuObject->MenuInfo.Flags & MF_SYSMENU))
836 {
837 MenuItem->fType |= MF_SEPARATOR;
838 }
839 RtlInitUnicodeString(&MenuItem->Text, NULL);
840 }
841 }
842
843 if (sizeof(ROSMENUITEMINFO) == lpmii->cbSize)
844 {
845 MenuItem->Rect = lpmii->Rect;
846 MenuItem->XTab = lpmii->XTab;
847 }
848
849 return TRUE;
850 }
851
852 BOOL FASTCALL
853 IntInsertMenuItem(PMENU_OBJECT MenuObject, UINT uItem, BOOL fByPosition,
854 PROSMENUITEMINFO ItemInfo)
855 {
856 int pos = (int)uItem;
857 PMENU_ITEM MenuItem;
858
859 if (MAX_MENU_ITEMS <= MenuObject->MenuInfo.MenuItemCount)
860 {
861 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
862 return FALSE;
863 }
864
865 if (fByPosition)
866 {
867 /* calculate position */
868 if(MenuObject->MenuInfo.MenuItemCount < pos)
869 {
870 pos = MenuObject->MenuInfo.MenuItemCount;
871 }
872 }
873 else
874 {
875 pos = IntGetMenuItemByFlag(MenuObject, uItem, MF_BYCOMMAND, NULL, NULL);
876 }
877 if (pos < -1)
878 {
879 pos = -1;
880 }
881
882 MenuItem = ExAllocatePoolWithTag(PagedPool, sizeof(MENU_ITEM), TAG_MENUITEM);
883 if (NULL == MenuItem)
884 {
885 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
886 return FALSE;
887 }
888
889 MenuItem->fType = MFT_STRING;
890 MenuItem->fState = MFS_ENABLED | MFS_UNCHECKED;
891 MenuItem->wID = 0;
892 MenuItem->hSubMenu = (HMENU)0;
893 MenuItem->hbmpChecked = (HBITMAP)0;
894 MenuItem->hbmpUnchecked = (HBITMAP)0;
895 MenuItem->dwItemData = 0;
896 RtlInitUnicodeString(&MenuItem->Text, NULL);
897 MenuItem->hbmpItem = (HBITMAP)0;
898
899 if (! IntSetMenuItemInfo(MenuObject, MenuItem, ItemInfo))
900 {
901 ExFreePool(MenuItem);
902 return FALSE;
903 }
904
905 /* Force size recalculation! */
906 MenuObject->MenuInfo.Height = 0;
907
908 pos = IntInsertMenuItemToList(MenuObject, MenuItem, pos);
909
910 DPRINT("IntInsertMenuItemToList = %i\n", pos);
911
912 return (pos >= 0);
913 }
914
915 UINT FASTCALL
916 IntEnableMenuItem(PMENU_OBJECT MenuObject, UINT uIDEnableItem, UINT uEnable)
917 {
918 PMENU_ITEM MenuItem;
919 UINT res = IntGetMenuItemByFlag(MenuObject, uIDEnableItem, uEnable, &MenuItem, NULL);
920 if(!MenuItem || (res == (UINT)-1))
921 {
922 return (UINT)-1;
923 }
924
925 res = MenuItem->fState & (MF_GRAYED | MF_DISABLED);
926
927 if(uEnable & MF_DISABLED)
928 {
929 if(!(MenuItem->fState & MF_DISABLED))
930 MenuItem->fState |= MF_DISABLED;
931 if(uEnable & MF_GRAYED)
932 {
933 if(!(MenuItem->fState & MF_GRAYED))
934 MenuItem->fState |= MF_GRAYED;
935 }
936 }
937 else
938 {
939 if(uEnable & MF_GRAYED)
940 {
941 if(!(MenuItem->fState & MF_GRAYED))
942 MenuItem->fState |= MF_GRAYED;
943 if(!(MenuItem->fState & MF_DISABLED))
944 MenuItem->fState |= MF_DISABLED;
945 }
946 else
947 {
948 if(MenuItem->fState & MF_DISABLED)
949 MenuItem->fState ^= MF_DISABLED;
950 if(MenuItem->fState & MF_GRAYED)
951 MenuItem->fState ^= MF_GRAYED;
952 }
953 }
954
955 return res;
956 }
957
958
959 DWORD FASTCALL
960 IntBuildMenuItemList(PMENU_OBJECT MenuObject, PVOID Buffer, ULONG nMax)
961 {
962 DWORD res = 0;
963 UINT sz;
964 ROSMENUITEMINFO mii;
965 PVOID Buf;
966 PMENU_ITEM CurItem = MenuObject->MenuItemList;
967 PWCHAR StrOut;
968 NTSTATUS Status;
969 WCHAR NulByte;
970
971 if (0 != nMax)
972 {
973 if (nMax < MenuObject->MenuInfo.MenuItemCount * sizeof(ROSMENUITEMINFO))
974 {
975 return 0;
976 }
977 StrOut = (PWCHAR)((char *) Buffer + MenuObject->MenuInfo.MenuItemCount
978 * sizeof(ROSMENUITEMINFO));
979 nMax -= MenuObject->MenuInfo.MenuItemCount * sizeof(ROSMENUITEMINFO);
980 sz = sizeof(ROSMENUITEMINFO);
981 Buf = Buffer;
982 mii.cbSize = sizeof(ROSMENUITEMINFO);
983 mii.fMask = 0;
984 NulByte = L'\0';
985
986 while (NULL != CurItem)
987 {
988 mii.cch = CurItem->Text.Length / sizeof(WCHAR);
989 mii.dwItemData = CurItem->dwItemData;
990 if (0 != CurItem->Text.Length)
991 {
992 mii.dwTypeData = StrOut;
993 }
994 else
995 {
996 mii.dwTypeData = NULL;
997 }
998 mii.fState = CurItem->fState;
999 mii.fType = CurItem->fType;
1000 mii.hbmpChecked = CurItem->hbmpChecked;
1001 mii.hbmpItem = CurItem->hbmpItem;
1002 mii.hbmpUnchecked = CurItem->hbmpUnchecked;
1003 mii.hSubMenu = CurItem->hSubMenu;
1004 mii.Rect = CurItem->Rect;
1005 mii.XTab = CurItem->XTab;
1006
1007 Status = MmCopyToCaller(Buf, &mii, sizeof(ROSMENUITEMINFO));
1008 if (! NT_SUCCESS(Status))
1009 {
1010 SetLastNtError(Status);
1011 return 0;
1012 }
1013 Buf = (PVOID)((ULONG_PTR)Buf + sizeof(ROSMENUITEMINFO));
1014
1015 if (0 != CurItem->Text.Length
1016 && (nMax >= CurItem->Text.Length + sizeof(WCHAR)))
1017 {
1018 /* copy string */
1019 Status = MmCopyToCaller(StrOut, CurItem->Text.Buffer,
1020 CurItem->Text.Length);
1021 if (! NT_SUCCESS(Status))
1022 {
1023 SetLastNtError(Status);
1024 return 0;
1025 }
1026 StrOut += CurItem->Text.Length / sizeof(WCHAR);
1027 Status = MmCopyToCaller(StrOut, &NulByte, sizeof(WCHAR));
1028 if (! NT_SUCCESS(Status))
1029 {
1030 SetLastNtError(Status);
1031 return 0;
1032 }
1033 StrOut++;
1034 nMax -= CurItem->Text.Length + sizeof(WCHAR);
1035 }
1036 else if (0 != CurItem->Text.Length)
1037 {
1038 break;
1039 }
1040
1041 CurItem = CurItem->Next;
1042 res++;
1043 }
1044 }
1045 else
1046 {
1047 while (NULL != CurItem)
1048 {
1049 res += sizeof(ROSMENUITEMINFO) + CurItem->Text.Length + sizeof(WCHAR);
1050 CurItem = CurItem->Next;
1051 }
1052 }
1053
1054 return res;
1055 }
1056
1057
1058 DWORD FASTCALL
1059 IntCheckMenuItem(PMENU_OBJECT MenuObject, UINT uIDCheckItem, UINT uCheck)
1060 {
1061 PMENU_ITEM MenuItem;
1062 int res = -1;
1063
1064 if((IntGetMenuItemByFlag(MenuObject, uIDCheckItem, uCheck, &MenuItem, NULL) < 0) || !MenuItem)
1065 {
1066 return -1;
1067 }
1068
1069 res = (DWORD)(MenuItem->fState & MF_CHECKED);
1070 if(uCheck & MF_CHECKED)
1071 {
1072 if(!(MenuItem->fState & MF_CHECKED))
1073 MenuItem->fState |= MF_CHECKED;
1074 }
1075 else
1076 {
1077 if(MenuItem->fState & MF_CHECKED)
1078 MenuItem->fState ^= MF_CHECKED;
1079 }
1080
1081 return (DWORD)res;
1082 }
1083
1084 BOOL FASTCALL
1085 IntHiliteMenuItem(PWINDOW_OBJECT WindowObject, PMENU_OBJECT MenuObject,
1086 UINT uItemHilite, UINT uHilite)
1087 {
1088 PMENU_ITEM MenuItem;
1089 BOOL res = IntGetMenuItemByFlag(MenuObject, uItemHilite, uHilite, &MenuItem, NULL);
1090 if(!MenuItem || !res)
1091 {
1092 return FALSE;
1093 }
1094
1095 if(uHilite & MF_HILITE)
1096 {
1097 if(!(MenuItem->fState & MF_HILITE))
1098 MenuItem->fState |= MF_HILITE;
1099 }
1100 else
1101 {
1102 if(MenuItem->fState & MF_HILITE)
1103 MenuItem->fState ^= MF_HILITE;
1104 }
1105
1106 /* FIXME - update the window's menu */
1107
1108 return TRUE;
1109 }
1110
1111 BOOL FASTCALL
1112 UserSetMenuDefaultItem(PMENU_OBJECT MenuObject, UINT uItem, UINT fByPos)
1113 {
1114 BOOL ret = FALSE;
1115 PMENU_ITEM MenuItem = MenuObject->MenuItemList;
1116
1117 if(uItem == (UINT)-1)
1118 {
1119 while(MenuItem)
1120 {
1121 if(MenuItem->fState & MFS_DEFAULT)
1122 MenuItem->fState ^= MFS_DEFAULT;
1123 MenuItem = MenuItem->Next;
1124 }
1125 return TRUE;
1126 }
1127
1128 if(fByPos)
1129 {
1130 UINT pos = 0;
1131 while(MenuItem)
1132 {
1133 if(pos == uItem)
1134 {
1135 if(!(MenuItem->fState & MFS_DEFAULT))
1136 MenuItem->fState |= MFS_DEFAULT;
1137 ret = TRUE;
1138 }
1139 else
1140 {
1141 if(MenuItem->fState & MFS_DEFAULT)
1142 MenuItem->fState ^= MFS_DEFAULT;
1143 }
1144 pos++;
1145 MenuItem = MenuItem->Next;
1146 }
1147 }
1148 else
1149 {
1150 while(MenuItem)
1151 {
1152 if(!ret && (MenuItem->wID == uItem))
1153 {
1154 if(!(MenuItem->fState & MFS_DEFAULT))
1155 MenuItem->fState |= MFS_DEFAULT;
1156 ret = TRUE;
1157 }
1158 else
1159 {
1160 if(MenuItem->fState & MFS_DEFAULT)
1161 MenuItem->fState ^= MFS_DEFAULT;
1162 }
1163 MenuItem = MenuItem->Next;
1164 }
1165 }
1166 return ret;
1167 }
1168
1169
1170 UINT FASTCALL
1171 IntGetMenuDefaultItem(PMENU_OBJECT MenuObject, UINT fByPos, UINT gmdiFlags,
1172 DWORD *gismc)
1173 {
1174 UINT x = 0;
1175 UINT res = -1;
1176 UINT sres;
1177 PMENU_OBJECT SubMenuObject;
1178 PMENU_ITEM MenuItem = MenuObject->MenuItemList;
1179
1180 while(MenuItem)
1181 {
1182 if(MenuItem->fState & MFS_DEFAULT)
1183 {
1184
1185 if(!(gmdiFlags & GMDI_USEDISABLED) && (MenuItem->fState & MFS_DISABLED))
1186 break;
1187
1188 if(fByPos & MF_BYPOSITION)
1189 res = x;
1190 else
1191 res = MenuItem->wID;
1192
1193 if((*gismc < MAX_GOINTOSUBMENU) && (gmdiFlags & GMDI_GOINTOPOPUPS) &&
1194 MenuItem->hSubMenu)
1195 {
1196
1197 SubMenuObject = UserGetMenuObject(MenuItem->hSubMenu);
1198 if(!SubMenuObject || (SubMenuObject == MenuObject))
1199 break;
1200
1201 (*gismc)++;
1202 sres = IntGetMenuDefaultItem(SubMenuObject, fByPos, gmdiFlags, gismc);
1203 (*gismc)--;
1204
1205 if(sres > (UINT)-1)
1206 res = sres;
1207 }
1208
1209 break;
1210 }
1211
1212 MenuItem = MenuItem->Next;
1213 x++;
1214 }
1215
1216 return res;
1217 }
1218
1219 VOID FASTCALL
1220 co_IntInitTracking(PWINDOW_OBJECT Window, PMENU_OBJECT Menu, BOOL Popup,
1221 UINT Flags)
1222 {
1223 /* FIXME - hide caret */
1224
1225 if(!(Flags & TPM_NONOTIFY))
1226 co_IntSendMessage(Window->hSelf, WM_SETCURSOR, (WPARAM)Window->hSelf, HTCAPTION);
1227
1228 /* FIXME - send WM_SETCURSOR message */
1229
1230 if(!(Flags & TPM_NONOTIFY))
1231 co_IntSendMessage(Window->hSelf, WM_INITMENU, (WPARAM)Menu->MenuInfo.Self, 0);
1232 }
1233
1234 VOID FASTCALL
1235 co_IntExitTracking(PWINDOW_OBJECT Window, PMENU_OBJECT Menu, BOOL Popup,
1236 UINT Flags)
1237 {
1238 if(!(Flags & TPM_NONOTIFY))
1239 co_IntSendMessage(Window->hSelf, WM_EXITMENULOOP, 0 /* FIXME */, 0);
1240
1241 /* FIXME - Show caret again */
1242 }
1243
1244 INT FASTCALL
1245 IntTrackMenu(PMENU_OBJECT Menu, PWINDOW_OBJECT Window, INT x, INT y,
1246 RECT lprect)
1247 {
1248 return 0;
1249 }
1250
1251 BOOL FASTCALL
1252 co_IntTrackPopupMenu(PMENU_OBJECT Menu, PWINDOW_OBJECT Window,
1253 UINT Flags, POINT *Pos, UINT MenuPos, RECT *ExcludeRect)
1254 {
1255 co_IntInitTracking(Window, Menu, TRUE, Flags);
1256
1257 co_IntExitTracking(Window, Menu, TRUE, Flags);
1258 return FALSE;
1259 }
1260
1261 BOOL FASTCALL
1262 IntSetMenuItemRect(PMENU_OBJECT Menu, UINT Item, BOOL fByPos, RECT *rcRect)
1263 {
1264 PMENU_ITEM mi;
1265 if(IntGetMenuItemByFlag(Menu, Item, (fByPos ? MF_BYPOSITION : MF_BYCOMMAND),
1266 &mi, NULL) > -1)
1267 {
1268 mi->Rect = *rcRect;
1269 return TRUE;
1270 }
1271 return FALSE;
1272 }
1273
1274
1275 /*!
1276 * Internal function. Called when the process is destroyed to free the remaining menu handles.
1277 */
1278 BOOL FASTCALL
1279 IntCleanupMenus(struct _EPROCESS *Process, PW32PROCESS Win32Process)
1280 {
1281 PEPROCESS CurrentProcess;
1282 PLIST_ENTRY LastHead = NULL;
1283 PMENU_OBJECT MenuObject;
1284
1285 CurrentProcess = PsGetCurrentProcess();
1286 if (CurrentProcess != Process)
1287 {
1288 KeAttachProcess(&Process->Pcb);
1289 }
1290
1291 while (Win32Process->MenuListHead.Flink != &(Win32Process->MenuListHead) &&
1292 Win32Process->MenuListHead.Flink != LastHead)
1293 {
1294 LastHead = Win32Process->MenuListHead.Flink;
1295 MenuObject = CONTAINING_RECORD(Win32Process->MenuListHead.Flink, MENU_OBJECT, ListEntry);
1296
1297 IntDestroyMenuObject(MenuObject, FALSE, TRUE);
1298 }
1299
1300 if (CurrentProcess != Process)
1301 {
1302 KeDetachProcess();
1303 }
1304 return TRUE;
1305 }
1306
1307 /* FUNCTIONS *****************************************************************/
1308
1309
1310 /*
1311 * @implemented
1312 */
1313 DWORD
1314 STDCALL
1315 NtUserBuildMenuItemList(
1316 HMENU hMenu,
1317 VOID* Buffer,
1318 ULONG nBufSize,
1319 DWORD Reserved)
1320 {
1321 DWORD res = -1;
1322 PMENU_OBJECT Menu;
1323 DECLARE_RETURN(DWORD);
1324
1325 DPRINT("Enter NtUserBuildMenuItemList\n");
1326 UserEnterExclusive();
1327
1328 if(!(Menu = UserGetMenuObject(hMenu)))
1329 {
1330 RETURN( (DWORD)-1);
1331 }
1332
1333 if(Buffer)
1334 {
1335 res = IntBuildMenuItemList(Menu, Buffer, nBufSize);
1336 }
1337 else
1338 {
1339 res = Menu->MenuInfo.MenuItemCount;
1340 }
1341
1342 RETURN( res);
1343
1344 CLEANUP:
1345 DPRINT("Leave NtUserBuildMenuItemList, ret=%i\n",_ret_);
1346 UserLeave();
1347 END_CLEANUP;
1348 }
1349
1350
1351 /*
1352 * @implemented
1353 */
1354 DWORD STDCALL
1355 NtUserCheckMenuItem(
1356 HMENU hMenu,
1357 UINT uIDCheckItem,
1358 UINT uCheck)
1359 {
1360 PMENU_OBJECT Menu;
1361 DECLARE_RETURN(DWORD);
1362
1363 DPRINT("Enter NtUserCheckMenuItem\n");
1364 UserEnterExclusive();
1365
1366 if(!(Menu = UserGetMenuObject(hMenu)))
1367 {
1368 RETURN( (DWORD)-1);
1369 }
1370
1371 RETURN( IntCheckMenuItem(Menu, uIDCheckItem, uCheck));
1372
1373 CLEANUP:
1374 DPRINT("Leave NtUserCheckMenuItem, ret=%i\n",_ret_);
1375 UserLeave();
1376 END_CLEANUP;
1377 }
1378
1379
1380 HMENU FASTCALL UserCreateMenu(BOOL PopupMenu)
1381 {
1382 PWINSTATION_OBJECT WinStaObject;
1383 HANDLE Handle;
1384
1385 NTSTATUS Status = IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation,
1386 KernelMode,
1387 0,
1388 &WinStaObject);
1389
1390 if (!NT_SUCCESS(Status))
1391 {
1392 DPRINT("Validation of window station handle (0x%X) failed\n",
1393 PsGetCurrentProcess()->Win32WindowStation);
1394 SetLastNtError(Status);
1395 return (HMENU)0;
1396 }
1397
1398 IntCreateMenu(&Handle, !PopupMenu);
1399
1400 ObDereferenceObject(WinStaObject);
1401 return (HMENU)Handle;
1402 }
1403
1404
1405
1406 HMENU STDCALL
1407 NtUserCreateMenu(BOOL PopupMenu)
1408 {
1409 DECLARE_RETURN(HMENU);
1410
1411 DPRINT("Enter NtUserCreateMenu\n");
1412 UserEnterExclusive();
1413
1414 RETURN(UserCreateMenu(PopupMenu));
1415
1416 CLEANUP:
1417 DPRINT("Leave NtUserCreateMenu, ret=%i\n",_ret_);
1418 UserLeave();
1419 END_CLEANUP;
1420 }
1421
1422
1423
1424 /*
1425 * @implemented
1426 */
1427 BOOL STDCALL
1428 NtUserDeleteMenu(
1429 HMENU hMenu,
1430 UINT uPosition,
1431 UINT uFlags)
1432 {
1433 PMENU_OBJECT Menu;
1434 DECLARE_RETURN(BOOL);
1435
1436 DPRINT("Enter NtUserDeleteMenu\n");
1437 UserEnterExclusive();
1438
1439 if(!(Menu = UserGetMenuObject(hMenu)))
1440 {
1441 RETURN( FALSE);
1442 }
1443
1444 RETURN( IntRemoveMenuItem(Menu, uPosition, uFlags, TRUE));
1445
1446 CLEANUP:
1447 DPRINT("Leave NtUserDeleteMenu, ret=%i\n",_ret_);
1448 UserLeave();
1449 END_CLEANUP;
1450 }
1451
1452
1453
1454 /*
1455 * @implemented
1456 */
1457 BOOL FASTCALL UserDestroyMenu(HMENU hMenu)
1458 {
1459 PMENU_OBJECT Menu;
1460
1461 if(!(Menu = UserGetMenuObject(hMenu)))
1462 {
1463 return FALSE;
1464 }
1465
1466 if(Menu->Process != PsGetCurrentProcess())
1467 {
1468 SetLastWin32Error(ERROR_ACCESS_DENIED);
1469 return FALSE;
1470 }
1471
1472 return IntDestroyMenuObject(Menu, FALSE, TRUE);
1473 }
1474
1475 /*
1476 * @implemented
1477 */
1478 BOOL STDCALL
1479 NtUserDestroyMenu(
1480 HMENU hMenu)
1481 {
1482 PMENU_OBJECT Menu;
1483 DECLARE_RETURN(BOOL);
1484
1485 DPRINT("Enter NtUserDestroyMenu\n");
1486 UserEnterExclusive();
1487
1488 if(!(Menu = UserGetMenuObject(hMenu)))
1489 {
1490 RETURN( FALSE);
1491 }
1492
1493 if(Menu->Process != PsGetCurrentProcess())
1494 {
1495 SetLastWin32Error(ERROR_ACCESS_DENIED);
1496 RETURN( FALSE);
1497 }
1498
1499 RETURN( IntDestroyMenuObject(Menu, FALSE, TRUE));
1500
1501 CLEANUP:
1502 DPRINT("Leave NtUserDestroyMenu, ret=%i\n",_ret_);
1503 UserLeave();
1504 END_CLEANUP;
1505 }
1506
1507
1508 /*
1509 * @implemented
1510 */
1511 UINT STDCALL
1512 NtUserEnableMenuItem(
1513 HMENU hMenu,
1514 UINT uIDEnableItem,
1515 UINT uEnable)
1516 {
1517 PMENU_OBJECT Menu;
1518 DECLARE_RETURN(UINT);
1519
1520 DPRINT("Enter NtUserEnableMenuItem\n");
1521 UserEnterExclusive();
1522
1523 if(!(Menu = UserGetMenuObject(hMenu)))
1524 {
1525 RETURN(-1);
1526 }
1527
1528 RETURN( IntEnableMenuItem(Menu, uIDEnableItem, uEnable));
1529
1530 CLEANUP:
1531 DPRINT("Leave NtUserEnableMenuItem, ret=%i\n",_ret_);
1532 UserLeave();
1533 END_CLEANUP;
1534 }
1535
1536
1537 /*
1538 * @implemented
1539 */
1540 DWORD STDCALL
1541 NtUserInsertMenuItem(
1542 HMENU hMenu,
1543 UINT uItem,
1544 BOOL fByPosition,
1545 LPCMENUITEMINFOW UnsafeItemInfo)
1546 {
1547 PMENU_OBJECT Menu;
1548 NTSTATUS Status;
1549 ROSMENUITEMINFO ItemInfo;
1550 DECLARE_RETURN(DWORD);
1551
1552 DPRINT("Enter NtUserInsertMenuItem\n");
1553 UserEnterExclusive();
1554
1555 if(!(Menu = UserGetMenuObject(hMenu)))
1556 {
1557 RETURN( FALSE);
1558 }
1559
1560 /* Try to copy the whole MENUITEMINFOW structure */
1561 Status = MmCopyFromCaller(&ItemInfo, UnsafeItemInfo, sizeof(MENUITEMINFOW));
1562 if (NT_SUCCESS(Status))
1563 {
1564 if (sizeof(MENUITEMINFOW) != ItemInfo.cbSize
1565 && FIELD_OFFSET(MENUITEMINFOW, hbmpItem) != ItemInfo.cbSize)
1566 {
1567 SetLastWin32Error(ERROR_INVALID_PARAMETER);
1568 RETURN( FALSE);
1569 }
1570 RETURN( IntInsertMenuItem(Menu, uItem, fByPosition, &ItemInfo));
1571 }
1572
1573 /* Try to copy without last field (not present in older versions) */
1574 Status = MmCopyFromCaller(&ItemInfo, UnsafeItemInfo, FIELD_OFFSET(MENUITEMINFOW, hbmpItem));
1575 if (NT_SUCCESS(Status))
1576 {
1577 if (FIELD_OFFSET(MENUITEMINFOW, hbmpItem) != ItemInfo.cbSize)
1578 {
1579 SetLastWin32Error(ERROR_INVALID_PARAMETER);
1580 RETURN( FALSE);
1581 }
1582 ItemInfo.hbmpItem = (HBITMAP)0;
1583 RETURN( IntInsertMenuItem(Menu, uItem, fByPosition, &ItemInfo));
1584 }
1585
1586 SetLastNtError(Status);
1587 RETURN( FALSE);
1588
1589 CLEANUP:
1590 DPRINT("Leave NtUserInsertMenuItem, ret=%i\n",_ret_);
1591 UserLeave();
1592 END_CLEANUP;
1593 }
1594
1595
1596 /*
1597 * @unimplemented
1598 */
1599 BOOL STDCALL
1600 NtUserEndMenu(VOID)
1601 {
1602 UNIMPLEMENTED
1603
1604 return 0;
1605 }
1606
1607
1608 /*
1609 * @implemented
1610 */
1611 UINT STDCALL
1612 NtUserGetMenuDefaultItem(
1613 HMENU hMenu,
1614 UINT fByPos,
1615 UINT gmdiFlags)
1616 {
1617 PMENU_OBJECT Menu;
1618 DWORD gismc = 0;
1619 DECLARE_RETURN(UINT);
1620
1621 DPRINT("Enter NtUserGetMenuDefaultItem\n");
1622 UserEnterExclusive();
1623
1624 if(!(Menu = UserGetMenuObject(hMenu)))
1625 {
1626 RETURN(-1);
1627 }
1628
1629 RETURN( IntGetMenuDefaultItem(Menu, fByPos, gmdiFlags, &gismc));
1630
1631 CLEANUP:
1632 DPRINT("Leave NtUserGetMenuDefaultItem, ret=%i\n",_ret_);
1633 UserLeave();
1634 END_CLEANUP;
1635 }
1636
1637
1638 /*
1639 * @implemented
1640 */
1641 BOOL STDCALL
1642 NtUserGetMenuBarInfo(
1643 HWND hwnd,
1644 LONG idObject,
1645 LONG idItem,
1646 PMENUBARINFO pmbi)
1647 {
1648 BOOL Res = TRUE;
1649 PMENU_OBJECT MenuObject;
1650 PMENU_ITEM mi;
1651 PWINDOW_OBJECT WindowObject;
1652 HMENU hMenu;
1653 POINT Offset;
1654 RECT Rect;
1655 MENUBARINFO kmbi;
1656 DECLARE_RETURN(BOOL);
1657
1658 DPRINT("Enter NtUserGetMenuBarInfo\n");
1659 UserEnterShared();
1660
1661 if (!(WindowObject = UserGetWindowObject(hwnd)))
1662 {
1663 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
1664 RETURN(FALSE);
1665 }
1666
1667 hMenu = (HMENU)WindowObject->IDMenu;
1668
1669 if (!(MenuObject = UserGetMenuObject(hMenu)))
1670 {
1671 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE);
1672 RETURN(FALSE);
1673 }
1674
1675 if (pmbi->cbSize != sizeof(MENUBARINFO))
1676 {
1677 SetLastWin32Error(ERROR_INVALID_PARAMETER);
1678 RETURN(FALSE);
1679 }
1680
1681 kmbi.cbSize = sizeof(MENUBARINFO);
1682 kmbi.fBarFocused = FALSE;
1683 kmbi.fFocused = FALSE;
1684 kmbi.hwndMenu = NULL;
1685
1686 switch (idObject)
1687 {
1688 case OBJID_MENU:
1689 {
1690 PMENU_OBJECT SubMenuObject;
1691 kmbi.hMenu = hMenu;
1692 if (idItem) /* Non-Zero-Based. */
1693 {
1694 if (IntGetMenuItemByFlag(MenuObject, idItem-1, MF_BYPOSITION, &mi, NULL) > -1)
1695 kmbi.rcBar = mi->Rect;
1696 else
1697 {
1698 Res = FALSE;
1699 break;
1700 }
1701 }
1702 else
1703 {
1704 /* If items is zero we assume info for the menu itself. */
1705 if (!(IntGetClientOrigin(WindowObject, &Offset)))
1706 {
1707 Res = FALSE;
1708 break;
1709 }
1710 Rect.left = Offset.x;
1711 Rect.right = Offset.x + MenuObject->MenuInfo.Width;
1712 Rect.top = Offset.y;
1713 Rect.bottom = Offset.y + MenuObject->MenuInfo.Height;
1714 kmbi.rcBar = Rect;
1715 DPRINT("Rect top = %d bottom = %d left = %d right = %d \n",
1716 Rect.top, Rect.bottom, Rect.left, Rect.right);
1717 }
1718 if (idItem)
1719 {
1720 if (idItem-1 == MenuObject->MenuInfo.FocusedItem)
1721 kmbi.fFocused = TRUE;
1722 }
1723 if (MenuObject->MenuInfo.FocusedItem != NO_SELECTED_ITEM)
1724 kmbi.fBarFocused = TRUE;
1725 SubMenuObject = UserGetMenuObject(MenuObject->MenuItemList->hSubMenu);
1726 if(SubMenuObject) kmbi.hwndMenu = SubMenuObject->MenuInfo.Wnd;
1727 DPRINT("OBJID_MENU, idItem = %d\n",idItem);
1728 break;
1729 }
1730 case OBJID_CLIENT:
1731 {
1732 PMENU_OBJECT SubMenuObject, XSubMenuObject;
1733 SubMenuObject = UserGetMenuObject(MenuObject->MenuItemList->hSubMenu);
1734 if(SubMenuObject) kmbi.hMenu = SubMenuObject->MenuInfo.Self;
1735 else
1736 {
1737 Res = FALSE;
1738 DPRINT1("OBJID_CLIENT, No SubMenu!\n");
1739 break;
1740 }
1741 if (idItem)
1742 {
1743 if (IntGetMenuItemByFlag(SubMenuObject, idItem-1, MF_BYPOSITION, &mi, NULL) > -1)
1744 kmbi.rcBar = mi->Rect;
1745 else
1746 {
1747 Res = FALSE;
1748 break;
1749 }
1750 }
1751 else
1752 {
1753 PWINDOW_OBJECT SubWinObj;
1754 if (!(SubWinObj = UserGetWindowObject(SubMenuObject->MenuInfo.Wnd)))
1755 {
1756 Res = FALSE;
1757 break;
1758 }
1759 if (!(IntGetClientOrigin(SubWinObj, &Offset)))
1760 {
1761 Res = FALSE;
1762 break;
1763 }
1764 Rect.left = Offset.x;
1765 Rect.right = Offset.x + SubMenuObject->MenuInfo.Width;
1766 Rect.top = Offset.y;
1767 Rect.bottom = Offset.y + SubMenuObject->MenuInfo.Height;
1768 kmbi.rcBar = Rect;
1769 }
1770 if (idItem)
1771 {
1772 if (idItem-1 == SubMenuObject->MenuInfo.FocusedItem)
1773 kmbi.fFocused = TRUE;
1774 }
1775 if (SubMenuObject->MenuInfo.FocusedItem != NO_SELECTED_ITEM)
1776 kmbi.fBarFocused = TRUE;
1777 XSubMenuObject = UserGetMenuObject(SubMenuObject->MenuItemList->hSubMenu);
1778 if (XSubMenuObject) kmbi.hwndMenu = XSubMenuObject->MenuInfo.Wnd;
1779 DPRINT("OBJID_CLIENT, idItem = %d\n",idItem);
1780 break;
1781 }
1782 case OBJID_SYSMENU:
1783 {
1784 PMENU_OBJECT SysMenuObject, SubMenuObject;
1785 if(!(SysMenuObject = IntGetSystemMenu(WindowObject, FALSE, FALSE)))
1786 {
1787 Res = FALSE;
1788 break;
1789 }
1790 kmbi.hMenu = SysMenuObject->MenuInfo.Self;
1791 if (idItem)
1792 {
1793 if (IntGetMenuItemByFlag(SysMenuObject, idItem-1, MF_BYPOSITION, &mi, NULL) > -1)
1794 kmbi.rcBar = mi->Rect;
1795 else
1796 {
1797 Res = FALSE;
1798 break;
1799 }
1800 }
1801 else
1802 {
1803 PWINDOW_OBJECT SysWinObj;
1804 if (!(SysWinObj = UserGetWindowObject(SysMenuObject->MenuInfo.Wnd)))
1805 {
1806 Res = FALSE;
1807 break;
1808 }
1809 if (!(IntGetClientOrigin(SysWinObj, &Offset)))
1810 {
1811 Res = FALSE;
1812 break;
1813 }
1814 Rect.left = Offset.x;
1815 Rect.right = Offset.x + SysMenuObject->MenuInfo.Width;
1816 Rect.top = Offset.y;
1817 Rect.bottom = Offset.y + SysMenuObject->MenuInfo.Height;
1818 kmbi.rcBar = Rect;
1819 }
1820 if (idItem)
1821 {
1822 if (idItem-1 == SysMenuObject->MenuInfo.FocusedItem)
1823 kmbi.fFocused = TRUE;
1824 }
1825 if (SysMenuObject->MenuInfo.FocusedItem != NO_SELECTED_ITEM)
1826 kmbi.fBarFocused = TRUE;
1827 SubMenuObject = UserGetMenuObject(SysMenuObject->MenuItemList->hSubMenu);
1828 if(SubMenuObject) kmbi.hwndMenu = SubMenuObject->MenuInfo.Wnd;
1829 DPRINT("OBJID_SYSMENU, idItem = %d\n",idItem);
1830 break;
1831 }
1832 default:
1833 Res = FALSE;
1834 DPRINT1("Unknown idObject = %d, idItem = %d\n",idObject,idItem);
1835 }
1836 if (Res)
1837 {
1838 NTSTATUS Status = MmCopyToCaller(pmbi, &kmbi, sizeof(MENUBARINFO));
1839 if (! NT_SUCCESS(Status))
1840 {
1841 SetLastNtError(Status);
1842 RETURN(FALSE);
1843 }
1844 }
1845 RETURN(Res);
1846
1847 CLEANUP:
1848 DPRINT("Leave NtUserGetMenuBarInfo, ret=%i\n",_ret_);
1849 UserLeave();
1850 END_CLEANUP;
1851 }
1852
1853
1854 /*
1855 * @unimplemented
1856 */
1857 UINT STDCALL
1858 NtUserGetMenuIndex(
1859 HMENU hMenu,
1860 UINT wID)
1861 {
1862 UNIMPLEMENTED
1863
1864 return 0;
1865 }
1866
1867
1868 /*
1869 * @implemented
1870 */
1871 BOOL STDCALL
1872 NtUserGetMenuItemRect(
1873 HWND hWnd,
1874 HMENU hMenu,
1875 UINT uItem,
1876 LPRECT lprcItem)
1877 {
1878 ROSMENUINFO mi;
1879 HWND referenceHwnd;
1880 RECT Rect;
1881 NTSTATUS Status;
1882 PMENU_OBJECT Menu;
1883 PMENU_ITEM MenuItem;
1884 DECLARE_RETURN(BOOL);
1885
1886 DPRINT("Enter NtUserGetMenuItemRect\n");
1887 UserEnterShared();
1888
1889 if (!(Menu = UserGetMenuObject(hMenu)))
1890 {
1891 RETURN(FALSE);
1892 }
1893
1894 if (IntGetMenuItemByFlag(Menu, uItem, MF_BYPOSITION, &MenuItem, NULL) > -1)
1895 Rect = MenuItem->Rect;
1896 else
1897 RETURN(FALSE);
1898
1899 referenceHwnd = hWnd;
1900
1901 if(!hWnd)
1902 {
1903 if(!UserMenuInfo(Menu, &mi, FALSE))
1904 RETURN( FALSE);
1905 if(mi.Wnd == 0)
1906 RETURN( FALSE);
1907 referenceHwnd = mi.Wnd; /* Okay we found it, so now what do we do? */
1908 }
1909
1910 if (lprcItem == NULL)
1911 RETURN( FALSE);
1912
1913 Status = MmCopyToCaller(lprcItem, &Rect, sizeof(RECT));
1914 if (! NT_SUCCESS(Status))
1915 {
1916 SetLastNtError(Status);
1917 RETURN( FALSE);
1918 }
1919 RETURN( TRUE);
1920
1921 CLEANUP:
1922 DPRINT("Leave NtUserGetMenuItemRect, ret=%i\n",_ret_);
1923 UserLeave();
1924 END_CLEANUP;
1925 }
1926
1927
1928 /*
1929 * @implemented
1930 */
1931 BOOL STDCALL
1932 NtUserHiliteMenuItem(
1933 HWND hWnd,
1934 HMENU hMenu,
1935 UINT uItemHilite,
1936 UINT uHilite)
1937 {
1938 PMENU_OBJECT Menu;
1939 PWINDOW_OBJECT Window;
1940 DECLARE_RETURN(BOOLEAN);
1941
1942 DPRINT("Enter NtUserHiliteMenuItem\n");
1943 UserEnterExclusive();
1944
1945 if(!(Window = UserGetWindowObject(hWnd)))
1946 {
1947 RETURN(FALSE);
1948 }
1949
1950 if(!(Menu = UserGetMenuObject(hMenu)))
1951 {
1952 RETURN(FALSE);
1953 }
1954
1955 if(Window->IDMenu == (UINT)hMenu)
1956 {
1957 RETURN( IntHiliteMenuItem(Window, Menu, uItemHilite, uHilite));
1958 }
1959
1960 RETURN(FALSE);
1961
1962 CLEANUP:
1963 DPRINT("Leave NtUserHiliteMenuItem, ret=%i\n",_ret_);
1964 UserLeave();
1965 END_CLEANUP;
1966 }
1967
1968
1969 static
1970 BOOL FASTCALL
1971 UserMenuInfo(
1972 PMENU_OBJECT Menu,
1973 PROSMENUINFO UnsafeMenuInfo,
1974 BOOL SetOrGet)
1975 {
1976 BOOL Res;
1977 DWORD Size;
1978 NTSTATUS Status;
1979 ROSMENUINFO MenuInfo;
1980
1981 Status = MmCopyFromCaller(&Size, &UnsafeMenuInfo->cbSize, sizeof(DWORD));
1982 if (! NT_SUCCESS(Status))
1983 {
1984 SetLastNtError(Status);
1985 return( FALSE);
1986 }
1987 if(Size < sizeof(MENUINFO) || sizeof(ROSMENUINFO) < Size)
1988 {
1989 SetLastWin32Error(ERROR_INVALID_PARAMETER);
1990 return( FALSE);
1991 }
1992 Status = MmCopyFromCaller(&MenuInfo, UnsafeMenuInfo, Size);
1993 if (! NT_SUCCESS(Status))
1994 {
1995 SetLastNtError(Status);
1996 return( FALSE);
1997 }
1998
1999 if(SetOrGet)
2000 {
2001 /* Set MenuInfo */
2002 Res = IntSetMenuInfo(Menu, &MenuInfo);
2003 }
2004 else
2005 {
2006 /* Get MenuInfo */
2007 Res = IntGetMenuInfo(Menu, &MenuInfo);
2008 if (Res)
2009 {
2010 Status = MmCopyToCaller(UnsafeMenuInfo, &MenuInfo, Size);
2011 if (! NT_SUCCESS(Status))
2012 {
2013 SetLastNtError(Status);
2014 return( FALSE);
2015 }
2016 }
2017 }
2018
2019 return( Res);
2020 }
2021
2022
2023
2024
2025
2026 /*
2027 * @implemented
2028 */
2029 BOOL
2030 STDCALL
2031 NtUserMenuInfo(
2032 HMENU hMenu,
2033 PROSMENUINFO UnsafeMenuInfo,
2034 BOOL SetOrGet)
2035 {
2036 PMENU_OBJECT Menu;
2037 DECLARE_RETURN(BOOL);
2038
2039 DPRINT("Enter NtUserMenuInfo\n");
2040 UserEnterShared();
2041
2042 if (!(Menu = UserGetMenuObject(hMenu)))
2043 {
2044 RETURN(FALSE);
2045 }
2046
2047 RETURN(UserMenuInfo(Menu, UnsafeMenuInfo, SetOrGet));
2048
2049 CLEANUP:
2050 DPRINT("Leave NtUserMenuInfo, ret=%i\n",_ret_);
2051 UserLeave();
2052 END_CLEANUP;
2053 }
2054
2055
2056
2057 /*
2058 * @implemented
2059 */
2060 int STDCALL
2061 NtUserMenuItemFromPoint(
2062 HWND hWnd,
2063 HMENU hMenu,
2064 DWORD X,
2065 DWORD Y)
2066 {
2067 PMENU_OBJECT Menu;
2068 PWINDOW_OBJECT Window = NULL;
2069 PMENU_ITEM mi;
2070 int i;
2071 DECLARE_RETURN(int);
2072
2073 DPRINT("Enter NtUserMenuItemFromPoint\n");
2074 UserEnterExclusive();
2075
2076 if (!(Menu = UserGetMenuObject(hMenu)))
2077 {
2078 RETURN( -1);
2079 }
2080
2081 if (!(Window = UserGetWindowObject(Menu->MenuInfo.Wnd)))
2082 {
2083 RETURN( -1);
2084 }
2085
2086 X -= Window->WindowRect.left;
2087 Y -= Window->WindowRect.top;
2088
2089 mi = Menu->MenuItemList;
2090 for (i = 0; NULL != mi; i++)
2091 {
2092 if (InRect(mi->Rect, X, Y))
2093 {
2094 break;
2095 }
2096 mi = mi->Next;
2097 }
2098
2099 RETURN( (mi ? i : NO_SELECTED_ITEM));
2100
2101 CLEANUP:
2102 DPRINT("Leave NtUserMenuItemFromPoint, ret=%i\n",_ret_);
2103 UserLeave();
2104 END_CLEANUP;
2105 }
2106
2107
2108
2109 static
2110 BOOL FASTCALL
2111 UserMenuItemInfo(
2112 PMENU_OBJECT Menu,
2113 UINT Item,
2114 BOOL ByPosition,
2115 PROSMENUITEMINFO UnsafeItemInfo,
2116 BOOL SetOrGet)
2117 {
2118 PMENU_ITEM MenuItem;
2119 ROSMENUITEMINFO ItemInfo;
2120 NTSTATUS Status;
2121 UINT Size;
2122 BOOL Ret;
2123
2124 Status = MmCopyFromCaller(&Size, &UnsafeItemInfo->cbSize, sizeof(UINT));
2125 if (! NT_SUCCESS(Status))
2126 {
2127 SetLastNtError(Status);
2128 return( FALSE);
2129 }
2130 if (sizeof(MENUITEMINFOW) != Size
2131 && FIELD_OFFSET(MENUITEMINFOW, hbmpItem) != Size
2132 && sizeof(ROSMENUITEMINFO) != Size)
2133 {
2134 SetLastWin32Error(ERROR_INVALID_PARAMETER);
2135 return( FALSE);
2136 }
2137 Status = MmCopyFromCaller(&ItemInfo, UnsafeItemInfo, Size);
2138 if (! NT_SUCCESS(Status))
2139 {
2140 SetLastNtError(Status);
2141 return( FALSE);
2142 }
2143 /* If this is a pre-0x0500 _WIN32_WINNT MENUITEMINFOW, you can't
2144 set/get hbmpItem */
2145 if (FIELD_OFFSET(MENUITEMINFOW, hbmpItem) == Size
2146 && 0 != (ItemInfo.fMask & MIIM_BITMAP))
2147 {
2148 SetLastWin32Error(ERROR_INVALID_PARAMETER);
2149 return( FALSE);
2150 }
2151
2152 if (IntGetMenuItemByFlag(Menu, Item,
2153 (ByPosition ? MF_BYPOSITION : MF_BYCOMMAND),
2154 &MenuItem, NULL) < 0)
2155 {
2156 SetLastWin32Error(ERROR_INVALID_PARAMETER);
2157 return( FALSE);
2158 }
2159
2160 if (SetOrGet)
2161 {
2162 Ret = IntSetMenuItemInfo(Menu, MenuItem, &ItemInfo);
2163 }
2164 else
2165 {
2166 Ret = IntGetMenuItemInfo(Menu, MenuItem, &ItemInfo);
2167 if (Ret)
2168 {
2169 Status = MmCopyToCaller(UnsafeItemInfo, &ItemInfo, Size);
2170 if (! NT_SUCCESS(Status))
2171 {
2172 SetLastNtError(Status);
2173 return( FALSE);
2174 }
2175 }
2176 }
2177
2178 return( Ret);
2179 }
2180
2181
2182
2183 /*
2184 * @implemented
2185 */
2186 BOOL
2187 STDCALL
2188 NtUserMenuItemInfo(
2189 HMENU hMenu,
2190 UINT Item,
2191 BOOL ByPosition,
2192 PROSMENUITEMINFO UnsafeItemInfo,
2193 BOOL SetOrGet)
2194 {
2195 PMENU_OBJECT Menu;
2196 DECLARE_RETURN(BOOL);
2197
2198 DPRINT("Enter NtUserMenuItemInfo\n");
2199 UserEnterExclusive();
2200
2201 if (!(Menu = UserGetMenuObject(hMenu)))
2202 {
2203 RETURN(FALSE);
2204 }
2205
2206 RETURN( UserMenuItemInfo(Menu, Item, ByPosition, UnsafeItemInfo, SetOrGet));
2207
2208 CLEANUP:
2209 DPRINT("Leave NtUserMenuItemInfo, ret=%i\n",_ret_);
2210 UserLeave();
2211 END_CLEANUP;
2212
2213 }
2214
2215
2216 /*
2217 * @implemented
2218 */
2219 BOOL STDCALL
2220 NtUserRemoveMenu(
2221 HMENU hMenu,
2222 UINT uPosition,
2223 UINT uFlags)
2224 {
2225 PMENU_OBJECT Menu;
2226 DECLARE_RETURN(BOOL);
2227
2228 DPRINT("Enter NtUserRemoveMenu\n");
2229 UserEnterExclusive();
2230
2231 if(!(Menu = UserGetMenuObject(hMenu)))
2232 {
2233 RETURN( FALSE);
2234 }
2235
2236 RETURN(IntRemoveMenuItem(Menu, uPosition, uFlags, FALSE));
2237
2238 CLEANUP:
2239 DPRINT("Leave NtUserRemoveMenu, ret=%i\n",_ret_);
2240 UserLeave();
2241 END_CLEANUP;
2242
2243 }
2244
2245
2246 /*
2247 * @implemented
2248 */
2249 BOOL STDCALL
2250 NtUserSetMenuContextHelpId(
2251 HMENU hMenu,
2252 DWORD dwContextHelpId)
2253 {
2254 PMENU_OBJECT Menu;
2255 DECLARE_RETURN(BOOL);
2256
2257 DPRINT("Enter NtUserSetMenuContextHelpId\n");
2258 UserEnterExclusive();
2259
2260 if(!(Menu = UserGetMenuObject(hMenu)))
2261 {
2262 RETURN( FALSE);
2263 }
2264
2265 RETURN(IntSetMenuContextHelpId(Menu, dwContextHelpId));
2266
2267 CLEANUP:
2268 DPRINT("Leave NtUserSetMenuContextHelpId, ret=%i\n",_ret_);
2269 UserLeave();
2270 END_CLEANUP;
2271 }
2272
2273
2274
2275 /*
2276 * @implemented
2277 */
2278 BOOL STDCALL
2279 NtUserSetMenuDefaultItem(
2280 HMENU hMenu,
2281 UINT uItem,
2282 UINT fByPos)
2283 {
2284 PMENU_OBJECT Menu;
2285 DECLARE_RETURN(BOOL);
2286
2287 DPRINT("Enter NtUserSetMenuDefaultItem\n");
2288 UserEnterExclusive();
2289
2290 if(!(Menu = UserGetMenuObject(hMenu)))
2291 {
2292 RETURN( FALSE);
2293 }
2294
2295 RETURN( UserSetMenuDefaultItem(Menu, uItem, fByPos));
2296
2297 CLEANUP:
2298 DPRINT("Leave NtUserSetMenuDefaultItem, ret=%i\n",_ret_);
2299 UserLeave();
2300 END_CLEANUP;
2301 }
2302
2303
2304 /*
2305 * @implemented
2306 */
2307 BOOL STDCALL
2308 NtUserSetMenuFlagRtoL(
2309 HMENU hMenu)
2310 {
2311 PMENU_OBJECT Menu;
2312 DECLARE_RETURN(BOOL);
2313
2314 DPRINT("Enter NtUserSetMenuFlagRtoL\n");
2315 UserEnterExclusive();
2316
2317 if(!(Menu = UserGetMenuObject(hMenu)))
2318 {
2319 RETURN( FALSE);
2320 }
2321
2322 RETURN(IntSetMenuFlagRtoL(Menu));
2323
2324 CLEANUP:
2325 DPRINT("Leave NtUserSetMenuFlagRtoL, ret=%i\n",_ret_);
2326 UserLeave();
2327 END_CLEANUP;
2328 }
2329
2330
2331 /*
2332 * @unimplemented
2333 */
2334 DWORD STDCALL
2335 NtUserThunkedMenuInfo(
2336 HMENU hMenu,
2337 LPCMENUINFO lpcmi)
2338 {
2339 UNIMPLEMENTED
2340 /* This function seems just to call SetMenuInfo() */
2341 return 0;
2342 }
2343
2344
2345 /*
2346 * @unimplemented
2347 */
2348 DWORD STDCALL
2349 NtUserThunkedMenuItemInfo(
2350 HMENU hMenu,
2351 UINT uItem,
2352 BOOL fByPosition,
2353 BOOL bInsert,
2354 LPMENUITEMINFOW lpmii,
2355 PUNICODE_STRING lpszCaption)
2356 {
2357 UNIMPLEMENTED
2358 /* lpszCaption may be NULL, check for it and call RtlInitUnicodeString()
2359 if bInsert == TRUE call NtUserInsertMenuItem() else NtUserSetMenuItemInfo()
2360 */
2361 return 0;
2362 }
2363
2364
2365 /*
2366 * @implemented
2367 */
2368 /* NOTE: unused function */
2369 BOOL STDCALL
2370 NtUserTrackPopupMenuEx(
2371 HMENU hMenu,
2372 UINT fuFlags,
2373 int x,
2374 int y,
2375 HWND hWnd,
2376 LPTPMPARAMS lptpm)
2377 {
2378 UNIMPLEMENTED
2379
2380 return FALSE;
2381 }
2382
2383
2384 /* EOF */