[PATCH 2/3] server: add calls to get/set menu info Makefile.in | 1 menu.c | 211 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ protocol.def | 42 +++++++++++ user.h | 4 - 4 files changed, 257 insertions(+), 1 deletion(-) --- Index: server/Makefile.in =================================================================== RCS file: /home/wine/wine/server/Makefile.in,v retrieving revision 1.62 diff -u -r1.62 Makefile.in --- server/Makefile.in 20 Feb 2006 11:43:12 -0000 1.62 +++ server/Makefile.in 15 Jun 2006 02:47:18 -0000 @@ -26,6 +26,7 @@ mailslot.c \ main.c \ mapping.c \ + menu.c \ mutex.c \ named_pipe.c \ object.c \ Index: server/protocol.def =================================================================== RCS file: /home/wine/wine/server/protocol.def,v retrieving revision 1.200 diff -u -r1.200 protocol.def --- server/protocol.def 7 Jun 2006 12:51:16 -0000 1.200 +++ server/protocol.def 15 Jun 2006 02:47:18 -0000 @@ -2456,6 +2456,48 @@ #define SET_GLOBAL_PROGMAN_WINDOW 0x02 #define SET_GLOBAL_TASKMAN_WINDOW 0x04 +/* Get menu info */ +@REQ(get_menu_info) + user_handle_t handle; +@REPLY + VARARG(data,bytes); +@END + +/* Set menu info */ +@REQ(set_menu_info) + user_handle_t handle; + unsigned int mask; + VARARG(data,bytes); +@REPLY +@END + +/* create a menu */ +@REQ(create_menu) +@REPLY + user_handle_t handle; +@END + +/* destroy menu */ +@REQ(destroy_menu) + user_handle_t handle; +@REPLY +@END + +#define SET_MI_FLAGS 0x80000000 +#define SET_MI_HWND 0x40000000 +#define SET_MI_SYSMENU 0x20000000 +#define SET_MI_OWNER 0x10000000 +#define SET_MI_FOCUSITEM 0x08000000 +#define SET_MI_TIMETOHIDE 0x04000000 +#define SET_MI_WIDTH 0x02000000 +#define SET_MI_HEIGHT 0x01000000 +#define SET_MI_SCROLLING 0x00800000 +#define SET_MI_SCROLLPOS 0x00400000 +#define SET_MI_TOTALHEIGHT 0x00200000 +#define SET_MI_MAXBMPSIZE 0x00100000 +#define SET_MI_ITEMS 0x00080000 +#define SET_MI_NITEMS 0x00040000 + /* Adjust the privileges held by a token */ @REQ(adjust_token_privileges) obj_handle_t handle; /* handle to the token */ Index: server/user.h =================================================================== RCS file: /home/wine/wine/server/user.h,v retrieving revision 1.43 diff -u -r1.43 user.h --- server/user.h 8 Jun 2006 10:07:25 -0000 1.43 +++ server/user.h 15 Jun 2006 02:47:18 -0000 @@ -32,10 +32,12 @@ struct atom_table; struct clipboard; +/* from http://www.ddj.com/dept/windows/184416526?pgno=3 */ enum user_object { USER_WINDOW = 1, - USER_HOOK + USER_MENU = 2, + USER_HOOK = 5 }; #define DESKTOP_ATOM ((atom_t)32769) --- /dev/null 2006-05-31 09:29:03.272380500 -0700 +++ server/menu.c 2006-06-14 18:46:13.000000000 -0700 @@ -0,0 +1,211 @@ +/* + * Server-side menu handling + * + * Copyright (C) 2004 Ulrich Czekalla for CodeWeavers Inc. + * Copyright (C) 2006 Google (Thomas Kho) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "config.h" +#include "wine/port.h" + +#include + +#include "ntstatus.h" +#define WIN32_NO_STATUS +#include "windef.h" +#include "winbase.h" +#include "wingdi.h" +#include "winuser.h" +#include "winternl.h" + +#include "object.h" +#include "request.h" +#include "user.h" +#include "unicode.h" + +/* MENUITEM and POPUPMENU duplicated in dlls/user/menu.c */ +/* Menu item structure */ +typedef struct { + /* ----------- MENUITEMINFO Stuff ----------- */ + UINT fType; /* Item type. */ + UINT fState; /* Item state. */ + UINT_PTR wID; /* Item id. */ + HMENU hSubMenu; /* Pop-up menu. */ + HBITMAP hCheckBit; /* Bitmap when checked. */ + HBITMAP hUnCheckBit; /* Bitmap when unchecked. */ + LPWSTR text; /* Item text. */ + ULONG_PTR dwItemData; /* Application defined. */ + LPWSTR dwTypeData; /* depends on fMask */ + HBITMAP hbmpItem; /* bitmap */ + /* ----------- Wine stuff ----------- */ + RECT rect; /* Item area (relative to menu window) */ + UINT xTab; /* X position of text after Tab */ + SIZE bmpsize; /* size needed for the HBMMENU_CALLBACK + * bitmap */ +} MENUITEM; + +/* Popup menu structure */ +typedef struct { + WORD wFlags; /* Menu flags (MF_POPUP, MF_SYSMENU) */ + WORD wMagic; /* Magic number */ + WORD Width; /* Width of the whole menu */ + WORD Height; /* Height of the whole menu */ + UINT nItems; /* Number of items in the menu */ + HWND hWnd; /* Window containing the menu */ + MENUITEM *items; /* Array of menu items */ + UINT FocusedItem; /* Currently focused item */ + HWND hwndOwner; /* window receiving the messages for ownerdraw */ + BOOL bTimeToHide; /* Request hiding when receiving a second click in the top-level menu item */ + BOOL bScrolling; /* Scroll arrows are active */ + UINT nScrollPos; /* Current scroll position */ + UINT nTotalHeight; /* Total height of menu items inside menu */ + /* ------------ MENUINFO members ------ */ + DWORD dwStyle; /* Extended menu style */ + UINT cyMax; /* max height of the whole menu, 0 is screen height */ + HBRUSH hbrBack; /* brush for menu background */ + DWORD dwContextHelpID; + DWORD dwMenuData; /* application defined value */ + HMENU hSysMenuOwner; /* Handle to the dummy sys menu holder */ + SIZE maxBmpSize; /* Maximum size of the bitmap items */ +} POPUPMENU, *LPPOPUPMENU; + +struct menu +{ + user_handle_t handle; + POPUPMENU p; +}; + + +/* (other menu->FocusedItem values give the position of the focused item) */ +#define NO_SELECTED_ITEM 0xffff + + +/* retrive a pointer to a menu given its handle */ +static struct menu *get_menu(user_handle_t handle) +{ + struct menu *ret = get_user_object(handle, USER_MENU); + if (!ret) set_error(STATUS_INVALID_HANDLE); + return ret; +} + + +/* create a new menu structure */ +static struct menu *create_menu() +{ + struct menu *menu; + + if (!(menu = mem_alloc(sizeof(struct menu)))) + return NULL; + + memset(menu, 0, sizeof(struct menu)); + + if (!(menu->handle = alloc_user_handle(menu, USER_MENU))) + { + free(menu); + return NULL; + } + + return menu; +} + + +/* destroy a menu */ +static void destroy_menu(struct menu *menu) +{ + free_user_handle(menu->handle); + free(menu); +} + + +/* create a menu */ +DECL_HANDLER(create_menu) +{ + struct menu *menu; + + reply->handle = 0; + + if ((menu = create_menu())) + { + menu->p.FocusedItem = NO_SELECTED_ITEM; + menu->p.bTimeToHide = FALSE; + reply->handle = menu->handle; + } +} + + +/* destroy a menu */ +DECL_HANDLER(destroy_menu) +{ + struct menu *menu = get_menu(req->handle); + + if (menu) + destroy_menu(menu); +} + + +/* validate the given menu handle and get menu info */ +DECL_HANDLER(get_menu_info) +{ + struct menu *menu = get_menu(req->handle); + + if (menu && get_reply_max_size() == sizeof(POPUPMENU)) + set_reply_data(&menu->p, sizeof(POPUPMENU)); + else + set_error( STATUS_INVALID_HANDLE ); +} + +/* validate the given menu handle and set menu info */ +DECL_HANDLER(set_menu_info) +{ + struct menu *menu = get_menu(req->handle); + + if (menu && req->mask && get_req_data_size() == sizeof(POPUPMENU)) + { + const POPUPMENU *p = get_req_data(); + + if (req->mask & SET_MI_FLAGS) menu->p.wFlags = p->wFlags; + if (req->mask & SET_MI_WIDTH) menu->p.Width = p->Width; + if (req->mask & SET_MI_HEIGHT) menu->p.Height = p->Height; + if (req->mask & SET_MI_NITEMS) menu->p.nItems = p->nItems; + if (req->mask & SET_MI_HWND) menu->p.hWnd = p->hWnd; + if (req->mask & SET_MI_ITEMS) menu->p.items = p->items; + if (req->mask & SET_MI_FOCUSITEM) + menu->p.FocusedItem = p->FocusedItem; + if (req->mask & SET_MI_OWNER) menu->p.hwndOwner = p->hwndOwner; + if (req->mask & SET_MI_TIMETOHIDE) + menu->p.bTimeToHide = p->bTimeToHide; + if (req->mask & SET_MI_SCROLLING) + menu->p.bScrolling = p->bScrolling; + if (req->mask & SET_MI_SCROLLPOS) + menu->p.nScrollPos = p->nScrollPos; + if (req->mask & SET_MI_TOTALHEIGHT) + menu->p.nTotalHeight = p->nTotalHeight; + + if (req->mask & MIM_STYLE) menu->p.dwStyle = p->dwStyle; + if (req->mask & MIM_MAXHEIGHT) menu->p.cyMax = p->cyMax; + if (req->mask & MIM_BACKGROUND) menu->p.hbrBack = p->hbrBack; + if (req->mask & MIM_HELPID) + menu->p.dwContextHelpID= p->dwContextHelpID; + if (req->mask & MIM_MENUDATA) menu->p.dwMenuData = p->dwMenuData; + if (req->mask & SET_MI_SYSMENU) + menu->p.hSysMenuOwner = p->hSysMenuOwner; + if (req->mask & SET_MI_MAXBMPSIZE) + menu->p.maxBmpSize = p->maxBmpSize; + } + else + set_error( STATUS_INVALID_HANDLE ); +}