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