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