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