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