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