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