[CMAKE]
[reactos.git] / 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 UINT sz;
963 ROSMENUITEMINFO mii;
964 PVOID Buf;
965 PMENU_ITEM CurItem = MenuObject->MenuItemList;
966 PWCHAR StrOut;
967 NTSTATUS Status;
968 WCHAR NulByte;
969
970 if (0 != nMax)
971 {
972 if (nMax < MenuObject->MenuInfo.MenuItemCount * sizeof(ROSMENUITEMINFO))
973 {
974 return 0;
975 }
976 StrOut = (PWCHAR)((char *) Buffer + MenuObject->MenuInfo.MenuItemCount
977 * sizeof(ROSMENUITEMINFO));
978 nMax -= MenuObject->MenuInfo.MenuItemCount * sizeof(ROSMENUITEMINFO);
979 sz = 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(PWINDOW_OBJECT 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(PWINDOW_OBJECT Window, PMENU_OBJECT Menu, BOOL Popup,
1213 UINT Flags)
1214 {
1215 /* FIXME - hide caret */
1216
1217 if(!(Flags & TPM_NONOTIFY))
1218 co_IntSendMessage(Window->hSelf, WM_SETCURSOR, (WPARAM)Window->hSelf, HTCAPTION);
1219
1220 /* FIXME - send WM_SETCURSOR message */
1221
1222 if(!(Flags & TPM_NONOTIFY))
1223 co_IntSendMessage(Window->hSelf, WM_INITMENU, (WPARAM)Menu->MenuInfo.Self, 0);
1224 }
1225
1226 VOID FASTCALL
1227 co_IntExitTracking(PWINDOW_OBJECT Window, PMENU_OBJECT Menu, BOOL Popup,
1228 UINT Flags)
1229 {
1230 if(!(Flags & TPM_NONOTIFY))
1231 co_IntSendMessage(Window->hSelf, WM_EXITMENULOOP, 0 /* FIXME */, 0);
1232
1233 /* FIXME - Show caret again */
1234 }
1235
1236 INT FASTCALL
1237 IntTrackMenu(PMENU_OBJECT Menu, PWINDOW_OBJECT Window, INT x, INT y,
1238 RECTL lprect)
1239 {
1240 return 0;
1241 }
1242
1243 BOOL FASTCALL
1244 co_IntTrackPopupMenu(PMENU_OBJECT Menu, PWINDOW_OBJECT 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(PWINDOW_OBJECT 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->Wnd->style;
1314 dwExStyle = pWindowObject->Wnd->ExStyle;
1315
1316 bti->rcTitleBar.top = 0;
1317 bti->rcTitleBar.left = 0;
1318 bti->rcTitleBar.right = pWindowObject->Wnd->rcWindow.right - pWindowObject->Wnd->rcWindow.left;
1319 bti->rcTitleBar.bottom = pWindowObject->Wnd->rcWindow.bottom - pWindowObject->Wnd->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->Wnd->rcWindow.top;
1361 bti->rcTitleBar.left += pWindowObject->Wnd->rcWindow.left;
1362 bti->rcTitleBar.right += pWindowObject->Wnd->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->Wnd->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 SetLastWin32Error(ERROR_INVALID_PARAMETER);
1424 retValue = FALSE;
1425 }
1426
1427 return retValue;
1428 }
1429
1430 /* FUNCTIONS *****************************************************************/
1431
1432
1433 /*
1434 * @implemented
1435 */
1436 DWORD
1437 APIENTRY
1438 NtUserBuildMenuItemList(
1439 HMENU hMenu,
1440 VOID* Buffer,
1441 ULONG nBufSize,
1442 DWORD Reserved)
1443 {
1444 DWORD res = -1;
1445 PMENU_OBJECT Menu;
1446 DECLARE_RETURN(DWORD);
1447
1448 DPRINT("Enter NtUserBuildMenuItemList\n");
1449 UserEnterExclusive();
1450
1451 if(!(Menu = UserGetMenuObject(hMenu)))
1452 {
1453 RETURN( (DWORD)-1);
1454 }
1455
1456 if(Buffer)
1457 {
1458 res = IntBuildMenuItemList(Menu, Buffer, nBufSize);
1459 }
1460 else
1461 {
1462 res = Menu->MenuInfo.MenuItemCount;
1463 }
1464
1465 RETURN( res);
1466
1467 CLEANUP:
1468 DPRINT("Leave NtUserBuildMenuItemList, ret=%i\n",_ret_);
1469 UserLeave();
1470 END_CLEANUP;
1471 }
1472
1473
1474 /*
1475 * @implemented
1476 */
1477 DWORD APIENTRY
1478 NtUserCheckMenuItem(
1479 HMENU hMenu,
1480 UINT uIDCheckItem,
1481 UINT uCheck)
1482 {
1483 PMENU_OBJECT Menu;
1484 DECLARE_RETURN(DWORD);
1485
1486 DPRINT("Enter NtUserCheckMenuItem\n");
1487 UserEnterExclusive();
1488
1489 if(!(Menu = UserGetMenuObject(hMenu)))
1490 {
1491 RETURN( (DWORD)-1);
1492 }
1493
1494 RETURN( IntCheckMenuItem(Menu, uIDCheckItem, uCheck));
1495
1496 CLEANUP:
1497 DPRINT("Leave NtUserCheckMenuItem, ret=%i\n",_ret_);
1498 UserLeave();
1499 END_CLEANUP;
1500 }
1501
1502
1503 HMENU FASTCALL UserCreateMenu(BOOL PopupMenu)
1504 {
1505 PWINSTATION_OBJECT WinStaObject;
1506 HANDLE Handle;
1507 PMENU_OBJECT Menu;
1508 NTSTATUS Status;
1509 PEPROCESS CurrentProcess = PsGetCurrentProcess();
1510
1511 if (CsrProcess != CurrentProcess)
1512 {
1513 /*
1514 * CsrProcess does not have a Win32WindowStation
1515 *
1516 */
1517
1518 Status = IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation,
1519 KernelMode,
1520 0,
1521 &WinStaObject);
1522
1523 if (!NT_SUCCESS(Status))
1524 {
1525 DPRINT1("Validation of window station handle (0x%X) failed\n",
1526 CurrentProcess->Win32WindowStation);
1527 SetLastNtError(Status);
1528 return (HMENU)0;
1529 }
1530 Menu = IntCreateMenu(&Handle, !PopupMenu);
1531 ObDereferenceObject(WinStaObject);
1532 }
1533 else
1534 {
1535 Menu = IntCreateMenu(&Handle, !PopupMenu);
1536 }
1537
1538 if (Menu) UserDereferenceObject(Menu);
1539 return (HMENU)Handle;
1540 }
1541
1542
1543 /*
1544 * @implemented
1545 */
1546 BOOL APIENTRY
1547 NtUserDeleteMenu(
1548 HMENU hMenu,
1549 UINT uPosition,
1550 UINT uFlags)
1551 {
1552 PMENU_OBJECT Menu;
1553 DECLARE_RETURN(BOOL);
1554
1555 DPRINT("Enter NtUserDeleteMenu\n");
1556 UserEnterExclusive();
1557
1558 if(!(Menu = UserGetMenuObject(hMenu)))
1559 {
1560 RETURN( FALSE);
1561 }
1562
1563 RETURN( IntRemoveMenuItem(Menu, uPosition, uFlags, TRUE));
1564
1565 CLEANUP:
1566 DPRINT("Leave NtUserDeleteMenu, ret=%i\n",_ret_);
1567 UserLeave();
1568 END_CLEANUP;
1569 }
1570
1571 /*
1572 * @implemented
1573 */
1574 BOOLEAN APIENTRY
1575 NtUserGetTitleBarInfo(
1576 HWND hwnd,
1577 PTITLEBARINFO bti)
1578 {
1579 PWINDOW_OBJECT WindowObject;
1580 TITLEBARINFO bartitleinfo;
1581 DECLARE_RETURN(BOOLEAN);
1582 BOOLEAN retValue = TRUE;
1583
1584 DPRINT("Enter NtUserGetTitleBarInfo\n");
1585 UserEnterExclusive();
1586
1587 /* Vaildate the windows handle */
1588 if (!(WindowObject = UserGetWindowObject(hwnd)))
1589 {
1590 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
1591 retValue = FALSE;
1592 }
1593
1594 _SEH2_TRY
1595 {
1596 /* Copy our usermode buffer bti to local buffer bartitleinfo */
1597 ProbeForRead(bti, sizeof(TITLEBARINFO), 1);
1598 RtlCopyMemory(&bartitleinfo, bti, sizeof(TITLEBARINFO));
1599 }
1600 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1601 {
1602 /* Fail copy the data */
1603 SetLastWin32Error(ERROR_INVALID_PARAMETER);
1604 retValue = FALSE;
1605 }
1606 _SEH2_END
1607
1608 /* Get the tile bar info */
1609 if (retValue)
1610 {
1611 retValue = intGetTitleBarInfo(WindowObject, &bartitleinfo);
1612 if (retValue)
1613 {
1614 _SEH2_TRY
1615 {
1616 /* Copy our buffer to user mode buffer bti */
1617 ProbeForWrite(bti, sizeof(TITLEBARINFO), 1);
1618 RtlCopyMemory(bti, &bartitleinfo, sizeof(TITLEBARINFO));
1619 }
1620 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1621 {
1622 /* Fail copy the data */
1623 SetLastWin32Error(ERROR_INVALID_PARAMETER);
1624 retValue = FALSE;
1625 }
1626 _SEH2_END
1627 }
1628 }
1629
1630 RETURN( retValue );
1631
1632 CLEANUP:
1633 DPRINT("Leave NtUserGetTitleBarInfo, ret=%i\n",_ret_);
1634 UserLeave();
1635 END_CLEANUP;
1636 }
1637
1638
1639
1640 /*
1641 * @implemented
1642 */
1643 BOOL FASTCALL UserDestroyMenu(HMENU hMenu)
1644 {
1645 PMENU_OBJECT Menu;
1646
1647 if(!(Menu = UserGetMenuObject(hMenu)))
1648 {
1649 return FALSE;
1650 }
1651
1652 if(Menu->Process != PsGetCurrentProcess())
1653 {
1654 SetLastWin32Error(ERROR_ACCESS_DENIED);
1655 return FALSE;
1656 }
1657
1658 return IntDestroyMenuObject(Menu, FALSE, TRUE);
1659 }
1660
1661 /*
1662 * @implemented
1663 */
1664 BOOL APIENTRY
1665 NtUserDestroyMenu(
1666 HMENU hMenu)
1667 {
1668 PMENU_OBJECT Menu;
1669 DECLARE_RETURN(BOOL);
1670
1671 DPRINT("Enter NtUserDestroyMenu\n");
1672 UserEnterExclusive();
1673
1674 if(!(Menu = UserGetMenuObject(hMenu)))
1675 {
1676 RETURN( FALSE);
1677 }
1678
1679 if(Menu->Process != PsGetCurrentProcess())
1680 {
1681 SetLastWin32Error(ERROR_ACCESS_DENIED);
1682 RETURN( FALSE);
1683 }
1684
1685 RETURN( IntDestroyMenuObject(Menu, TRUE, TRUE));
1686
1687 CLEANUP:
1688 DPRINT("Leave NtUserDestroyMenu, ret=%i\n",_ret_);
1689 UserLeave();
1690 END_CLEANUP;
1691 }
1692
1693
1694 /*
1695 * @implemented
1696 */
1697 UINT APIENTRY
1698 NtUserEnableMenuItem(
1699 HMENU hMenu,
1700 UINT uIDEnableItem,
1701 UINT uEnable)
1702 {
1703 PMENU_OBJECT Menu;
1704 DECLARE_RETURN(UINT);
1705
1706 DPRINT("Enter NtUserEnableMenuItem\n");
1707 UserEnterExclusive();
1708
1709 if(!(Menu = UserGetMenuObject(hMenu)))
1710 {
1711 RETURN(-1);
1712 }
1713
1714 RETURN( IntEnableMenuItem(Menu, uIDEnableItem, uEnable));
1715
1716 CLEANUP:
1717 DPRINT("Leave NtUserEnableMenuItem, ret=%i\n",_ret_);
1718 UserLeave();
1719 END_CLEANUP;
1720 }
1721
1722
1723 /*
1724 * @implemented
1725 */
1726 DWORD APIENTRY
1727 UserInsertMenuItem(
1728 HMENU hMenu,
1729 UINT uItem,
1730 BOOL fByPosition,
1731 LPCMENUITEMINFOW UnsafeItemInfo)
1732 {
1733 PMENU_OBJECT Menu;
1734 NTSTATUS Status;
1735 ROSMENUITEMINFO ItemInfo;
1736 DECLARE_RETURN(DWORD);
1737
1738 DPRINT("Enter UserInsertMenuItem\n");
1739 UserEnterExclusive();
1740
1741 if(!(Menu = UserGetMenuObject(hMenu)))
1742 {
1743 RETURN( FALSE);
1744 }
1745
1746 /* Try to copy the whole MENUITEMINFOW structure */
1747 Status = MmCopyFromCaller(&ItemInfo, UnsafeItemInfo, sizeof(MENUITEMINFOW));
1748 if (NT_SUCCESS(Status))
1749 {
1750 if (sizeof(MENUITEMINFOW) != ItemInfo.cbSize
1751 && FIELD_OFFSET(MENUITEMINFOW, hbmpItem) != ItemInfo.cbSize)
1752 {
1753 SetLastWin32Error(ERROR_INVALID_PARAMETER);
1754 RETURN( FALSE);
1755 }
1756 RETURN( IntInsertMenuItem(Menu, uItem, fByPosition, &ItemInfo));
1757 }
1758
1759 /* Try to copy without last field (not present in older versions) */
1760 Status = MmCopyFromCaller(&ItemInfo, UnsafeItemInfo, FIELD_OFFSET(MENUITEMINFOW, hbmpItem));
1761 if (NT_SUCCESS(Status))
1762 {
1763 if (FIELD_OFFSET(MENUITEMINFOW, hbmpItem) != ItemInfo.cbSize)
1764 {
1765 SetLastWin32Error(ERROR_INVALID_PARAMETER);
1766 RETURN( FALSE);
1767 }
1768 ItemInfo.hbmpItem = (HBITMAP)0;
1769 RETURN( IntInsertMenuItem(Menu, uItem, fByPosition, &ItemInfo));
1770 }
1771
1772 SetLastNtError(Status);
1773 RETURN( FALSE);
1774
1775 CLEANUP:
1776 DPRINT("Leave UserInsertMenuItem, ret=%i\n",_ret_);
1777 UserLeave();
1778 END_CLEANUP;
1779 }
1780
1781
1782 /*
1783 * @unimplemented
1784 */
1785 BOOL APIENTRY
1786 NtUserEndMenu(VOID)
1787 {
1788 UNIMPLEMENTED
1789
1790 return 0;
1791 }
1792
1793
1794 /*
1795 * @implemented
1796 */
1797 UINT APIENTRY
1798 NtUserGetMenuDefaultItem(
1799 HMENU hMenu,
1800 UINT fByPos,
1801 UINT gmdiFlags)
1802 {
1803 PMENU_OBJECT Menu;
1804 DWORD gismc = 0;
1805 DECLARE_RETURN(UINT);
1806
1807 DPRINT("Enter NtUserGetMenuDefaultItem\n");
1808 UserEnterExclusive();
1809
1810 if(!(Menu = UserGetMenuObject(hMenu)))
1811 {
1812 RETURN(-1);
1813 }
1814
1815 RETURN( IntGetMenuDefaultItem(Menu, fByPos, gmdiFlags, &gismc));
1816
1817 CLEANUP:
1818 DPRINT("Leave NtUserGetMenuDefaultItem, ret=%i\n",_ret_);
1819 UserLeave();
1820 END_CLEANUP;
1821 }
1822
1823
1824 /*
1825 * @implemented
1826 */
1827 BOOL APIENTRY
1828 NtUserGetMenuBarInfo(
1829 HWND hwnd,
1830 LONG idObject,
1831 LONG idItem,
1832 PMENUBARINFO pmbi)
1833 {
1834 BOOL Res = TRUE;
1835 PMENU_OBJECT MenuObject;
1836 PMENU_ITEM mi;
1837 PWINDOW_OBJECT WindowObject;
1838 HMENU hMenu;
1839 POINT Offset;
1840 RECTL Rect;
1841 MENUBARINFO kmbi;
1842 DECLARE_RETURN(BOOL);
1843
1844 DPRINT("Enter NtUserGetMenuBarInfo\n");
1845 UserEnterShared();
1846
1847 if (!(WindowObject = UserGetWindowObject(hwnd)))
1848 {
1849 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
1850 RETURN(FALSE);
1851 }
1852
1853 hMenu = (HMENU)(DWORD_PTR)WindowObject->Wnd->IDMenu;
1854
1855 if (!(MenuObject = UserGetMenuObject(hMenu)))
1856 {
1857 SetLastWin32Error(ERROR_INVALID_MENU_HANDLE);
1858 RETURN(FALSE);
1859 }
1860
1861 if (pmbi->cbSize != sizeof(MENUBARINFO))
1862 {
1863 SetLastWin32Error(ERROR_INVALID_PARAMETER);
1864 RETURN(FALSE);
1865 }
1866
1867 kmbi.cbSize = sizeof(MENUBARINFO);
1868 kmbi.fBarFocused = FALSE;
1869 kmbi.fFocused = FALSE;
1870 kmbi.hwndMenu = NULL;
1871
1872 switch (idObject)
1873 {
1874 case OBJID_MENU:
1875 {
1876 PMENU_OBJECT SubMenuObject;
1877 kmbi.hMenu = hMenu;
1878 if (idItem) /* Non-Zero-Based. */
1879 {
1880 if (IntGetMenuItemByFlag(MenuObject, idItem-1, MF_BYPOSITION, NULL, &mi, NULL) > -1)
1881 kmbi.rcBar = mi->Rect;
1882 else
1883 {
1884 Res = FALSE;
1885 break;
1886 }
1887 }
1888 else
1889 {
1890 /* If items is zero we assume info for the menu itself. */
1891 if (!(IntGetClientOrigin(WindowObject, &Offset)))
1892 {
1893 Res = FALSE;
1894 break;
1895 }
1896 Rect.left = Offset.x;
1897 Rect.right = Offset.x + MenuObject->MenuInfo.Width;
1898 Rect.top = Offset.y;
1899 Rect.bottom = Offset.y + MenuObject->MenuInfo.Height;
1900 kmbi.rcBar = Rect;
1901 DPRINT("Rect top = %d bottom = %d left = %d right = %d \n",
1902 Rect.top, Rect.bottom, Rect.left, Rect.right);
1903 }
1904 if (idItem)
1905 {
1906 if (idItem-1 == MenuObject->MenuInfo.FocusedItem)
1907 kmbi.fFocused = TRUE;
1908 }
1909 if (MenuObject->MenuInfo.FocusedItem != NO_SELECTED_ITEM)
1910 kmbi.fBarFocused = TRUE;
1911 SubMenuObject = UserGetMenuObject(MenuObject->MenuItemList->hSubMenu);
1912 if(SubMenuObject) kmbi.hwndMenu = SubMenuObject->MenuInfo.Wnd;
1913 DPRINT("OBJID_MENU, idItem = %d\n",idItem);
1914 break;
1915 }
1916 case OBJID_CLIENT:
1917 {
1918 PMENU_OBJECT SubMenuObject, XSubMenuObject;
1919 SubMenuObject = UserGetMenuObject(MenuObject->MenuItemList->hSubMenu);
1920 if(SubMenuObject) kmbi.hMenu = SubMenuObject->MenuInfo.Self;
1921 else
1922 {
1923 Res = FALSE;
1924 DPRINT1("OBJID_CLIENT, No SubMenu!\n");
1925 break;
1926 }
1927 if (idItem)
1928 {
1929 if (IntGetMenuItemByFlag(SubMenuObject, idItem-1, MF_BYPOSITION, NULL, &mi, NULL) > -1)
1930 kmbi.rcBar = mi->Rect;
1931 else
1932 {
1933 Res = FALSE;
1934 break;
1935 }
1936 }
1937 else
1938 {
1939 PWINDOW_OBJECT SubWinObj;
1940 if (!(SubWinObj = UserGetWindowObject(SubMenuObject->MenuInfo.Wnd)))
1941 {
1942 Res = FALSE;
1943 break;
1944 }
1945 if (!(IntGetClientOrigin(SubWinObj, &Offset)))
1946 {
1947 Res = FALSE;
1948 break;
1949 }
1950 Rect.left = Offset.x;
1951 Rect.right = Offset.x + SubMenuObject->MenuInfo.Width;
1952 Rect.top = Offset.y;
1953 Rect.bottom = Offset.y + SubMenuObject->MenuInfo.Height;
1954 kmbi.rcBar = Rect;
1955 }
1956 if (idItem)
1957 {
1958 if (idItem-1 == SubMenuObject->MenuInfo.FocusedItem)
1959 kmbi.fFocused = TRUE;
1960 }
1961 if (SubMenuObject->MenuInfo.FocusedItem != NO_SELECTED_ITEM)
1962 kmbi.fBarFocused = TRUE;
1963 XSubMenuObject = UserGetMenuObject(SubMenuObject->MenuItemList->hSubMenu);
1964 if (XSubMenuObject) kmbi.hwndMenu = XSubMenuObject->MenuInfo.Wnd;
1965 DPRINT("OBJID_CLIENT, idItem = %d\n",idItem);
1966 break;
1967 }
1968 case OBJID_SYSMENU:
1969 {
1970 PMENU_OBJECT SysMenuObject, SubMenuObject;
1971 if(!(SysMenuObject = IntGetSystemMenu(WindowObject, FALSE, FALSE)))
1972 {
1973 Res = FALSE;
1974 break;
1975 }
1976 kmbi.hMenu = SysMenuObject->MenuInfo.Self;
1977 if (idItem)
1978 {
1979 if (IntGetMenuItemByFlag(SysMenuObject, idItem-1, MF_BYPOSITION, NULL, &mi, NULL) > -1)
1980 kmbi.rcBar = mi->Rect;
1981 else
1982 {
1983 Res = FALSE;
1984 break;
1985 }
1986 }
1987 else
1988 {
1989 PWINDOW_OBJECT SysWinObj;
1990 if (!(SysWinObj = UserGetWindowObject(SysMenuObject->MenuInfo.Wnd)))
1991 {
1992 Res = FALSE;
1993 break;
1994 }
1995 if (!(IntGetClientOrigin(SysWinObj, &Offset)))
1996 {
1997 Res = FALSE;
1998 break;
1999 }
2000 Rect.left = Offset.x;
2001 Rect.right = Offset.x + SysMenuObject->MenuInfo.Width;
2002 Rect.top = Offset.y;
2003 Rect.bottom = Offset.y + SysMenuObject->MenuInfo.Height;
2004 kmbi.rcBar = Rect;
2005 }
2006 if (idItem)
2007 {
2008 if (idItem-1 == SysMenuObject->MenuInfo.FocusedItem)
2009 kmbi.fFocused = TRUE;
2010 }
2011 if (SysMenuObject->MenuInfo.FocusedItem != NO_SELECTED_ITEM)
2012 kmbi.fBarFocused = TRUE;
2013 SubMenuObject = UserGetMenuObject(SysMenuObject->MenuItemList->hSubMenu);
2014 if(SubMenuObject) kmbi.hwndMenu = SubMenuObject->MenuInfo.Wnd;
2015 DPRINT("OBJID_SYSMENU, idItem = %d\n",idItem);
2016 break;
2017 }
2018 default:
2019 Res = FALSE;
2020 DPRINT1("Unknown idObject = %d, idItem = %d\n",idObject,idItem);
2021 }
2022 if (Res)
2023 {
2024 NTSTATUS Status = MmCopyToCaller(pmbi, &kmbi, sizeof(MENUBARINFO));
2025 if (! NT_SUCCESS(Status))
2026 {
2027 SetLastNtError(Status);
2028 RETURN(FALSE);
2029 }
2030 }
2031 RETURN(Res);
2032
2033 CLEANUP:
2034 DPRINT("Leave NtUserGetMenuBarInfo, ret=%i\n",_ret_);
2035 UserLeave();
2036 END_CLEANUP;
2037 }
2038
2039
2040 /*
2041 * @unimplemented
2042 */
2043 UINT APIENTRY
2044 NtUserGetMenuIndex(
2045 HMENU hMenu,
2046 UINT wID)
2047 {
2048 UNIMPLEMENTED
2049
2050 return 0;
2051 }
2052
2053
2054 /*
2055 * @implemented
2056 */
2057 BOOL APIENTRY
2058 NtUserGetMenuItemRect(
2059 HWND hWnd,
2060 HMENU hMenu,
2061 UINT uItem,
2062 PRECTL lprcItem)
2063 {
2064 ROSMENUINFO mi;
2065 PWINDOW_OBJECT ReferenceWnd;
2066 LONG XMove, YMove;
2067 RECTL Rect;
2068 NTSTATUS Status;
2069 PMENU_OBJECT Menu;
2070 PMENU_ITEM MenuItem;
2071 DECLARE_RETURN(BOOL);
2072
2073 DPRINT("Enter NtUserGetMenuItemRect\n");
2074 UserEnterShared();
2075
2076 if (!(Menu = UserGetMenuObject(hMenu)))
2077 {
2078 RETURN(FALSE);
2079 }
2080
2081 if (IntGetMenuItemByFlag(Menu, uItem, MF_BYPOSITION, NULL, &MenuItem, NULL) > -1)
2082 Rect = MenuItem->Rect;
2083 else
2084 RETURN(FALSE);
2085
2086 if(!hWnd)
2087 {
2088 if(!UserMenuInfo(Menu, &mi, FALSE))
2089 RETURN( FALSE);
2090 if(mi.Wnd == 0)
2091 RETURN( FALSE);
2092 }
2093
2094 if (lprcItem == NULL) RETURN( FALSE);
2095
2096 if (!(ReferenceWnd = UserGetWindowObject(mi.Wnd))) RETURN( FALSE);
2097
2098 if(MenuItem->fType & MF_POPUP)
2099 {
2100 XMove = ReferenceWnd->Wnd->rcClient.left;
2101 YMove = ReferenceWnd->Wnd->rcClient.top;
2102 }
2103 else
2104 {
2105 XMove = ReferenceWnd->Wnd->rcWindow.left;
2106 YMove = ReferenceWnd->Wnd->rcWindow.top;
2107 }
2108
2109 Rect.left += XMove;
2110 Rect.top += YMove;
2111 Rect.right += XMove;
2112 Rect.bottom += YMove;
2113
2114 Status = MmCopyToCaller(lprcItem, &Rect, sizeof(RECT));
2115 if (! NT_SUCCESS(Status))
2116 {
2117 SetLastNtError(Status);
2118 RETURN( FALSE);
2119 }
2120 RETURN( TRUE);
2121
2122 CLEANUP:
2123 DPRINT("Leave NtUserGetMenuItemRect, ret=%i\n",_ret_);
2124 UserLeave();
2125 END_CLEANUP;
2126 }
2127
2128
2129 /*
2130 * @implemented
2131 */
2132 BOOL APIENTRY
2133 NtUserHiliteMenuItem(
2134 HWND hWnd,
2135 HMENU hMenu,
2136 UINT uItemHilite,
2137 UINT uHilite)
2138 {
2139 PMENU_OBJECT Menu;
2140 PWINDOW_OBJECT Window;
2141 DECLARE_RETURN(BOOLEAN);
2142
2143 DPRINT("Enter NtUserHiliteMenuItem\n");
2144 UserEnterExclusive();
2145
2146 if(!(Window = UserGetWindowObject(hWnd)))
2147 {
2148 RETURN(FALSE);
2149 }
2150
2151 if(!(Menu = UserGetMenuObject(hMenu)))
2152 {
2153 RETURN(FALSE);
2154 }
2155
2156 if(Window->Wnd->IDMenu == (UINT)(UINT_PTR)hMenu)
2157 {
2158 RETURN( IntHiliteMenuItem(Window, Menu, uItemHilite, uHilite));
2159 }
2160
2161 RETURN(FALSE);
2162
2163 CLEANUP:
2164 DPRINT("Leave NtUserHiliteMenuItem, ret=%i\n",_ret_);
2165 UserLeave();
2166 END_CLEANUP;
2167 }
2168
2169
2170 static
2171 BOOL FASTCALL
2172 UserMenuInfo(
2173 PMENU_OBJECT Menu,
2174 PROSMENUINFO UnsafeMenuInfo,
2175 BOOL SetOrGet)
2176 {
2177 BOOL Res;
2178 DWORD Size;
2179 NTSTATUS Status;
2180 ROSMENUINFO MenuInfo;
2181
2182 Status = MmCopyFromCaller(&Size, &UnsafeMenuInfo->cbSize, sizeof(DWORD));
2183 if (! NT_SUCCESS(Status))
2184 {
2185 SetLastNtError(Status);
2186 return( FALSE);
2187 }
2188 if(Size < sizeof(MENUINFO) || sizeof(ROSMENUINFO) < Size)
2189 {
2190 SetLastWin32Error(ERROR_INVALID_PARAMETER);
2191 return( FALSE);
2192 }
2193 Status = MmCopyFromCaller(&MenuInfo, UnsafeMenuInfo, Size);
2194 if (! NT_SUCCESS(Status))
2195 {
2196 SetLastNtError(Status);
2197 return( FALSE);
2198 }
2199
2200 if(SetOrGet)
2201 {
2202 /* Set MenuInfo */
2203 Res = IntSetMenuInfo(Menu, &MenuInfo);
2204 }
2205 else
2206 {
2207 /* Get MenuInfo */
2208 Res = IntGetMenuInfo(Menu, &MenuInfo);
2209 if (Res)
2210 {
2211 Status = MmCopyToCaller(UnsafeMenuInfo, &MenuInfo, Size);
2212 if (! NT_SUCCESS(Status))
2213 {
2214 SetLastNtError(Status);
2215 return( FALSE);
2216 }
2217 }
2218 }
2219
2220 return( Res);
2221 }
2222
2223
2224
2225
2226
2227 /*
2228 * @implemented
2229 */
2230 BOOL
2231 APIENTRY
2232 NtUserMenuInfo(
2233 HMENU hMenu,
2234 PROSMENUINFO UnsafeMenuInfo,
2235 BOOL SetOrGet)
2236 {
2237 PMENU_OBJECT Menu;
2238 DECLARE_RETURN(BOOL);
2239
2240 DPRINT("Enter NtUserMenuInfo\n");
2241 UserEnterShared();
2242
2243 if (!(Menu = UserGetMenuObject(hMenu)))
2244 {
2245 RETURN(FALSE);
2246 }
2247
2248 RETURN(UserMenuInfo(Menu, UnsafeMenuInfo, SetOrGet));
2249
2250 CLEANUP:
2251 DPRINT("Leave NtUserMenuInfo, ret=%i\n",_ret_);
2252 UserLeave();
2253 END_CLEANUP;
2254 }
2255
2256
2257
2258 /*
2259 * @implemented
2260 */
2261 int APIENTRY
2262 NtUserMenuItemFromPoint(
2263 HWND hWnd,
2264 HMENU hMenu,
2265 DWORD X,
2266 DWORD Y)
2267 {
2268 PMENU_OBJECT Menu;
2269 PWINDOW_OBJECT Window = NULL;
2270 PMENU_ITEM mi;
2271 int i;
2272 DECLARE_RETURN(int);
2273
2274 DPRINT("Enter NtUserMenuItemFromPoint\n");
2275 UserEnterExclusive();
2276
2277 if (!(Menu = UserGetMenuObject(hMenu)))
2278 {
2279 RETURN( -1);
2280 }
2281
2282 if (!(Window = UserGetWindowObject(Menu->MenuInfo.Wnd)))
2283 {
2284 RETURN( -1);
2285 }
2286
2287 X -= Window->Wnd->rcWindow.left;
2288 Y -= Window->Wnd->rcWindow.top;
2289
2290 mi = Menu->MenuItemList;
2291 for (i = 0; NULL != mi; i++)
2292 {
2293 if (InRect(mi->Rect, X, Y))
2294 {
2295 break;
2296 }
2297 mi = mi->Next;
2298 }
2299
2300 RETURN( (mi ? i : NO_SELECTED_ITEM));
2301
2302 CLEANUP:
2303 DPRINT("Leave NtUserMenuItemFromPoint, ret=%i\n",_ret_);
2304 UserLeave();
2305 END_CLEANUP;
2306 }
2307
2308
2309
2310 static
2311 BOOL FASTCALL
2312 UserMenuItemInfo(
2313 PMENU_OBJECT Menu,
2314 UINT Item,
2315 BOOL ByPosition,
2316 PROSMENUITEMINFO UnsafeItemInfo,
2317 BOOL SetOrGet)
2318 {
2319 PMENU_ITEM MenuItem;
2320 ROSMENUITEMINFO ItemInfo;
2321 NTSTATUS Status;
2322 UINT Size;
2323 BOOL Ret;
2324
2325 Status = MmCopyFromCaller(&Size, &UnsafeItemInfo->cbSize, sizeof(UINT));
2326 if (! NT_SUCCESS(Status))
2327 {
2328 SetLastNtError(Status);
2329 return( FALSE);
2330 }
2331 if (sizeof(MENUITEMINFOW) != Size
2332 && FIELD_OFFSET(MENUITEMINFOW, hbmpItem) != Size
2333 && sizeof(ROSMENUITEMINFO) != Size)
2334 {
2335 SetLastWin32Error(ERROR_INVALID_PARAMETER);
2336 return( FALSE);
2337 }
2338 Status = MmCopyFromCaller(&ItemInfo, UnsafeItemInfo, Size);
2339 if (! NT_SUCCESS(Status))
2340 {
2341 SetLastNtError(Status);
2342 return( FALSE);
2343 }
2344 /* If this is a pre-0x0500 _WIN32_WINNT MENUITEMINFOW, you can't
2345 set/get hbmpItem */
2346 if (FIELD_OFFSET(MENUITEMINFOW, hbmpItem) == Size
2347 && 0 != (ItemInfo.fMask & MIIM_BITMAP))
2348 {
2349 SetLastWin32Error(ERROR_INVALID_PARAMETER);
2350 return( FALSE);
2351 }
2352
2353 if (IntGetMenuItemByFlag(Menu, Item,
2354 (ByPosition ? MF_BYPOSITION : MF_BYCOMMAND),
2355 NULL, &MenuItem, NULL) < 0)
2356 {
2357 SetLastWin32Error(ERROR_INVALID_PARAMETER);
2358 return( FALSE);
2359 }
2360
2361 if (SetOrGet)
2362 {
2363 Ret = IntSetMenuItemInfo(Menu, MenuItem, &ItemInfo);
2364 }
2365 else
2366 {
2367 Ret = IntGetMenuItemInfo(Menu, MenuItem, &ItemInfo);
2368 if (Ret)
2369 {
2370 Status = MmCopyToCaller(UnsafeItemInfo, &ItemInfo, Size);
2371 if (! NT_SUCCESS(Status))
2372 {
2373 SetLastNtError(Status);
2374 return( FALSE);
2375 }
2376 }
2377 }
2378
2379 return( Ret);
2380 }
2381
2382
2383
2384 /*
2385 * @implemented
2386 */
2387 BOOL
2388 APIENTRY
2389 NtUserMenuItemInfo(
2390 HMENU hMenu,
2391 UINT Item,
2392 BOOL ByPosition,
2393 PROSMENUITEMINFO UnsafeItemInfo,
2394 BOOL SetOrGet)
2395 {
2396 PMENU_OBJECT Menu;
2397 DECLARE_RETURN(BOOL);
2398
2399 DPRINT("Enter NtUserMenuItemInfo\n");
2400 UserEnterExclusive();
2401
2402 if (!(Menu = UserGetMenuObject(hMenu)))
2403 {
2404 RETURN(FALSE);
2405 }
2406
2407 RETURN( UserMenuItemInfo(Menu, Item, ByPosition, UnsafeItemInfo, SetOrGet));
2408
2409 CLEANUP:
2410 DPRINT("Leave NtUserMenuItemInfo, ret=%i\n",_ret_);
2411 UserLeave();
2412 END_CLEANUP;
2413
2414 }
2415
2416
2417 /*
2418 * @implemented
2419 */
2420 BOOL APIENTRY
2421 NtUserRemoveMenu(
2422 HMENU hMenu,
2423 UINT uPosition,
2424 UINT uFlags)
2425 {
2426 PMENU_OBJECT Menu;
2427 DECLARE_RETURN(BOOL);
2428
2429 DPRINT("Enter NtUserRemoveMenu\n");
2430 UserEnterExclusive();
2431
2432 if(!(Menu = UserGetMenuObject(hMenu)))
2433 {
2434 RETURN( FALSE);
2435 }
2436
2437 RETURN(IntRemoveMenuItem(Menu, uPosition, uFlags, FALSE));
2438
2439 CLEANUP:
2440 DPRINT("Leave NtUserRemoveMenu, ret=%i\n",_ret_);
2441 UserLeave();
2442 END_CLEANUP;
2443
2444 }
2445
2446
2447 /*
2448 * @implemented
2449 */
2450 BOOL APIENTRY
2451 NtUserSetMenuContextHelpId(
2452 HMENU hMenu,
2453 DWORD dwContextHelpId)
2454 {
2455 PMENU_OBJECT Menu;
2456 DECLARE_RETURN(BOOL);
2457
2458 DPRINT("Enter NtUserSetMenuContextHelpId\n");
2459 UserEnterExclusive();
2460
2461 if(!(Menu = UserGetMenuObject(hMenu)))
2462 {
2463 RETURN( FALSE);
2464 }
2465
2466 RETURN(IntSetMenuContextHelpId(Menu, dwContextHelpId));
2467
2468 CLEANUP:
2469 DPRINT("Leave NtUserSetMenuContextHelpId, ret=%i\n",_ret_);
2470 UserLeave();
2471 END_CLEANUP;
2472 }
2473
2474
2475
2476 /*
2477 * @implemented
2478 */
2479 BOOL APIENTRY
2480 NtUserSetMenuDefaultItem(
2481 HMENU hMenu,
2482 UINT uItem,
2483 UINT fByPos)
2484 {
2485 PMENU_OBJECT Menu;
2486 DECLARE_RETURN(BOOL);
2487
2488 DPRINT("Enter NtUserSetMenuDefaultItem\n");
2489 UserEnterExclusive();
2490
2491 if(!(Menu = UserGetMenuObject(hMenu)))
2492 {
2493 RETURN( FALSE);
2494 }
2495
2496 RETURN( UserSetMenuDefaultItem(Menu, uItem, fByPos));
2497
2498 CLEANUP:
2499 DPRINT("Leave NtUserSetMenuDefaultItem, ret=%i\n",_ret_);
2500 UserLeave();
2501 END_CLEANUP;
2502 }
2503
2504
2505 /*
2506 * @implemented
2507 */
2508 BOOL APIENTRY
2509 NtUserSetMenuFlagRtoL(
2510 HMENU hMenu)
2511 {
2512 PMENU_OBJECT Menu;
2513 DECLARE_RETURN(BOOL);
2514
2515 DPRINT("Enter NtUserSetMenuFlagRtoL\n");
2516 UserEnterExclusive();
2517
2518 if(!(Menu = UserGetMenuObject(hMenu)))
2519 {
2520 RETURN( FALSE);
2521 }
2522
2523 RETURN(IntSetMenuFlagRtoL(Menu));
2524
2525 CLEANUP:
2526 DPRINT("Leave NtUserSetMenuFlagRtoL, ret=%i\n",_ret_);
2527 UserLeave();
2528 END_CLEANUP;
2529 }
2530
2531
2532 /*
2533 * @unimplemented
2534 */
2535 DWORD APIENTRY
2536 NtUserThunkedMenuInfo(
2537 HMENU hMenu,
2538 LPCMENUINFO lpcmi)
2539 {
2540 UNIMPLEMENTED
2541 /* This function seems just to call SetMenuInfo() */
2542 return 0;
2543 }
2544
2545
2546 /*
2547 * @unimplemented
2548 */
2549 DWORD APIENTRY
2550 NtUserThunkedMenuItemInfo(
2551 HMENU hMenu,
2552 UINT uItem,
2553 BOOL fByPosition,
2554 BOOL bInsert,
2555 LPMENUITEMINFOW lpmii,
2556 PUNICODE_STRING lpszCaption)
2557 {
2558
2559 /* lpszCaption may be NULL, check for it and call RtlInitUnicodeString()
2560 if bInsert == TRUE call NtUserInsertMenuItem() else NtUserSetMenuItemInfo() */
2561
2562 if (bInsert) return UserInsertMenuItem(hMenu, uItem, fByPosition, lpmii);
2563
2564 UNIMPLEMENTED
2565 return 0;
2566 }
2567
2568
2569 /*
2570 * @implemented
2571 */
2572 /* NOTE: unused function */
2573 BOOL APIENTRY
2574 NtUserTrackPopupMenuEx(
2575 HMENU hMenu,
2576 UINT fuFlags,
2577 int x,
2578 int y,
2579 HWND hWnd,
2580 LPTPMPARAMS lptpm)
2581 {
2582 UNIMPLEMENTED
2583
2584 return FALSE;
2585 }
2586
2587
2588 /* EOF */