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