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