ReactOS  0.4.13-dev-101-g0ca4b50
accelerator.c
Go to the documentation of this file.
1 /*
2  * COPYRIGHT: See COPYING in the top level directory
3  * PROJECT: ReactOS kernel
4  * PURPOSE: Window accelerator
5  * FILE: win32ss/user/ntuser/accelerator.c
6  * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
7  * Copyright 1993 Martin Ayotte
8  * Copyright 1994 Alexandre Julliard
9  * Copyright 1997 Morten Welinder
10  * Copyright 2011 Rafal Harabien
11  */
12 
13 #include <win32k.h>
14 DBG_DEFAULT_CHANNEL(UserAccel);
15 
16 #define FVIRT_TBL_END 0x80
17 #define FVIRT_MASK 0x7F
18 
19 /* FUNCTIONS *****************************************************************/
20 
22 {
23  PACCELERATOR_TABLE Accel;
24 
25  if (!hAccel)
26  {
28  return NULL;
29  }
30 
32  if (!Accel)
33  {
35  return NULL;
36  }
37 
38  return Accel;
39 }
40 
41 
42 static
45  PWND Window,
46  CONST MSG *pMsg,
47  CONST ACCEL *pAccel)
48 {
49  BOOL bFound = FALSE;
50  UINT Mask = 0, nPos;
51  HWND hWnd;
52  HMENU hMenu, hSubMenu;
53  PMENU MenuObject;
54 
56 
57  hWnd = Window->head.h;
58 
59  TRACE("IntTranslateAccelerator(hwnd %p, message %x, wParam %x, lParam %x, fVirt 0x%x, key %x, cmd %x)\n",
60  hWnd, pMsg->message, pMsg->wParam, pMsg->lParam, pAccel->fVirt, pAccel->key, pAccel->cmd);
61 
62  if (UserGetKeyState(VK_CONTROL) & 0x8000) Mask |= FCONTROL;
63  if (UserGetKeyState(VK_MENU) & 0x8000) Mask |= FALT; // FIXME: VK_LMENU (msg winetest!)
64  if (UserGetKeyState(VK_SHIFT) & 0x8000) Mask |= FSHIFT;
65  TRACE("Mask 0x%x\n", Mask);
66 
67  if (pAccel->fVirt & FVIRTKEY)
68  {
69  /* This is a virtual key. Process WM_(SYS)KEYDOWN messages. */
70  if (pMsg->message == WM_KEYDOWN || pMsg->message == WM_SYSKEYDOWN)
71  {
72  /* Check virtual key and SHIFT, CTRL, LALT state */
73  if (pMsg->wParam == pAccel->key && Mask == (pAccel->fVirt & (FSHIFT | FCONTROL | FALT)))
74  {
75  bFound = TRUE;
76  }
77  }
78  }
79  else
80  {
81  /* This is a char code. Process WM_(SYS)CHAR messages. */
82  if (pMsg->message == WM_CHAR || pMsg->message == WM_SYSCHAR)
83  {
84  /* Check char code and LALT state only */
85  if (pMsg->wParam == pAccel->key && (Mask & FALT) == (pAccel->fVirt & FALT))
86  {
87  bFound = TRUE;
88  }
89  }
90  }
91 
92  if (!bFound)
93  {
94  /* Don't translate this msg */
95  TRACE("IntTranslateAccelerator returns FALSE\n");
96  return FALSE;
97  }
98 
99  /* Check if accelerator is associated with menu command */
100  hMenu = (Window->style & WS_CHILD) ? 0 : (HMENU)Window->IDMenu;
101  hSubMenu = NULL;
102  MenuObject = UserGetMenuObject(hMenu);
103  nPos = pAccel->cmd;
104  if (MenuObject)
105  {
106  if ((MENU_FindItem (&MenuObject, &nPos, MF_BYPOSITION)))
107  hSubMenu = MenuObject->head.h;
108  else
109  hMenu = NULL;
110  }
111  if (!hMenu)
112  {
113  /* Check system menu now */
114  hMenu = Window->SystemMenu;
115  hSubMenu = hMenu; /* system menu is a popup menu */
116  MenuObject = UserGetMenuObject(hMenu);
117  nPos = pAccel->cmd;
118  if (MenuObject)
119  {
120  if ((MENU_FindItem (&MenuObject, &nPos, MF_BYPOSITION)))
121  hSubMenu = MenuObject->head.h;
122  else
123  hMenu = NULL;
124  }
125  }
126 
127  /* If this is a menu item, there is no capturing enabled and
128  window is not disabled, send WM_INITMENU */
129  if (hMenu && !IntGetCaptureWindow())
130  {
132  if (hSubMenu)
133  {
134  nPos = IntFindSubMenu(&hMenu, hSubMenu);
135  TRACE("hSysMenu = %p, hSubMenu = %p, nPos = %u\n", hMenu, hSubMenu, nPos);
137  }
138  }
139 
140  /* Don't send any message if:
141  - window is disabled
142  - menu item is disabled
143  - this is window menu and window is minimized */
144  if (!(Window->style & WS_DISABLED) &&
145  !(hMenu && IntGetMenuState(hMenu, pAccel->cmd, MF_BYCOMMAND) & (MF_DISABLED | MF_GRAYED)) &&
146  !(hMenu && hMenu == (HMENU)Window->IDMenu && (Window->style & WS_MINIMIZED)))
147  {
148  /* If this is system menu item, send WM_SYSCOMMAND, otherwise send WM_COMMAND */
149  if (hMenu && hMenu == Window->SystemMenu)
150  {
151  TRACE("Sending WM_SYSCOMMAND, wParam=%0x\n", pAccel->cmd);
152  co_IntSendMessage(hWnd, WM_SYSCOMMAND, pAccel->cmd, 0x00010000L);
153  }
154  else
155  {
156  TRACE("Sending WM_COMMAND, wParam=%0x\n", 0x10000 | pAccel->cmd);
157  co_IntSendMessage(hWnd, WM_COMMAND, 0x10000 | pAccel->cmd, 0L);
158  }
159  }
160 
161  TRACE("IntTranslateAccelerator returns TRUE\n");
162  return TRUE;
163 }
164 
165 
166 /* SYSCALLS *****************************************************************/
167 
168 
169 ULONG
170 APIENTRY
172  HACCEL hAccel,
174  ULONG EntriesCount)
175 {
176  PACCELERATOR_TABLE Accel;
177  ULONG Ret;
178  DECLARE_RETURN(int);
179 
180  TRACE("Enter NtUserCopyAcceleratorTable\n");
181  UserEnterShared();
182 
183  Accel = UserGetAccelObject(hAccel);
184  if (!Accel)
185  {
186  RETURN(0);
187  }
188 
189  /* If Entries is NULL return table size */
190  if (!Entries)
191  {
192  RETURN(Accel->Count);
193  }
194 
195  /* Don't overrun */
196  if (Accel->Count < EntriesCount)
197  EntriesCount = Accel->Count;
198 
199  Ret = 0;
200 
201  _SEH2_TRY
202  {
203  ProbeForWrite(Entries, EntriesCount*sizeof(Entries[0]), 4);
204 
205  for (Ret = 0; Ret < EntriesCount; Ret++)
206  {
207  Entries[Ret].fVirt = Accel->Table[Ret].fVirt;
208  Entries[Ret].key = Accel->Table[Ret].key;
209  Entries[Ret].cmd = Accel->Table[Ret].cmd;
210  }
211  }
213  {
215  Ret = 0;
216  }
217  _SEH2_END;
218 
219  RETURN(Ret);
220 
221 CLEANUP:
222  TRACE("Leave NtUserCopyAcceleratorTable, ret=%i\n", _ret_);
223  UserLeave();
224  END_CLEANUP;
225 }
226 
227 HACCEL
228 APIENTRY
231  ULONG EntriesCount)
232 {
233  PACCELERATOR_TABLE Accel;
234  HACCEL hAccel;
235  ULONG Index;
237  DECLARE_RETURN(HACCEL);
238  PTHREADINFO pti;
239 
240  TRACE("Enter NtUserCreateAcceleratorTable(Entries %p, EntriesCount %u)\n",
241  Entries, EntriesCount);
243 
244  if (!Entries || EntriesCount <= 0)
245  {
247  RETURN( (HACCEL) NULL );
248  }
249 
251 
253  pti->rpdesk,
254  pti,
255  (PHANDLE)&hAccel,
257  sizeof(ACCELERATOR_TABLE));
258 
259  if (Accel == NULL)
260  {
262  RETURN( (HACCEL) NULL );
263  }
264 
265  Accel->Count = EntriesCount;
266  Accel->Table = ExAllocatePoolWithTag(PagedPool, EntriesCount * sizeof(ACCEL), USERTAG_ACCEL);
267  if (Accel->Table == NULL)
268  {
269  UserDereferenceObject(Accel);
272  RETURN( (HACCEL) NULL);
273  }
274 
275  _SEH2_TRY
276  {
277  ProbeForRead(Entries, EntriesCount * sizeof(ACCEL), 4);
278 
279  for (Index = 0; Index < EntriesCount; Index++)
280  {
281  Accel->Table[Index].fVirt = Entries[Index].fVirt & FVIRT_MASK;
282  if(Accel->Table[Index].fVirt & FVIRTKEY)
283  {
284  Accel->Table[Index].key = Entries[Index].key;
285  }
286  else
287  {
289  sizeof(WCHAR),
290  NULL,
291  (PCSTR)&Entries[Index].key,
292  sizeof(CHAR));
293  }
294 
295  Accel->Table[Index].cmd = Entries[Index].cmd;
296  }
297  }
299  {
301  }
302  _SEH2_END;
303 
304  if (!NT_SUCCESS(Status))
305  {
307  UserDereferenceObject(Accel);
310  RETURN( (HACCEL) NULL);
311  }
312 
313  /* FIXME: Save HandleTable in a list somewhere so we can clean it up again */
314 
315  /* Release the extra reference (UserCreateObject added 2 references) */
316  UserDereferenceObject(Accel);
317 
318  RETURN(hAccel);
319 
320 CLEANUP:
321  TRACE("Leave NtUserCreateAcceleratorTable(Entries %p, EntriesCount %u) = %p\n",
322  Entries, EntriesCount, _ret_);
323  UserLeave();
324  END_CLEANUP;
325 }
326 
327 BOOLEAN
329 {
330  PACCELERATOR_TABLE Accel = Object;
331 
332  if (Accel->Table != NULL)
333  {
335  Accel->Table = NULL;
336  }
337 
339  return TRUE;
340 }
341 
342 BOOLEAN
343 APIENTRY
345  HACCEL hAccel)
346 {
347  PACCELERATOR_TABLE Accel;
349 
350  /* FIXME: If the handle table is from a call to LoadAcceleratorTable, decrement it's
351  usage count (and return TRUE).
352  FIXME: Destroy only tables created using CreateAcceleratorTable.
353  */
354 
355  TRACE("NtUserDestroyAcceleratorTable(Table %p)\n", hAccel);
357 
358  if (!(Accel = UserGetAccelObject(hAccel)))
359  {
360  RETURN( FALSE);
361  }
362 
363  UserDestroyAccelTable(Accel);
364 
365  RETURN( TRUE);
366 
367 CLEANUP:
368  TRACE("Leave NtUserDestroyAcceleratorTable(Table %p) = %u\n", hAccel, _ret_);
369  UserLeave();
370  END_CLEANUP;
371 }
372 
373 int
374 APIENTRY
376  HWND hWnd,
377  HACCEL hAccel,
378  LPMSG pUnsafeMessage)
379 {
380  PWND Window = NULL;
381  PACCELERATOR_TABLE Accel = NULL;
382  ULONG i;
383  MSG Message;
384  USER_REFERENCE_ENTRY AccelRef, WindowRef;
385  DECLARE_RETURN(int);
386 
387  TRACE("NtUserTranslateAccelerator(hWnd %p, hAccel %p, Message %p)\n",
388  hWnd, hAccel, pUnsafeMessage);
389  UserEnterShared();
390 
391  if (hWnd == NULL)
392  {
393  RETURN( 0);
394  }
395 
396  _SEH2_TRY
397  {
398  ProbeForRead(pUnsafeMessage, sizeof(MSG), 4);
399  RtlCopyMemory(&Message, pUnsafeMessage, sizeof(MSG));
400  }
402  {
404  _SEH2_YIELD(RETURN( 0));
405  }
406  _SEH2_END;
407 
408  if ((Message.message != WM_KEYDOWN) &&
409  (Message.message != WM_SYSKEYDOWN) &&
410  (Message.message != WM_SYSCHAR) &&
411  (Message.message != WM_CHAR))
412  {
413  RETURN( 0);
414  }
415 
416  Accel = UserGetAccelObject(hAccel);
417  if (!Accel)
418  {
419  RETURN( 0);
420  }
421 
422  UserRefObjectCo(Accel, &AccelRef);
423 
425  if (!Window)
426  {
427  RETURN( 0);
428  }
429 
430  UserRefObjectCo(Window, &WindowRef);
431 
432  /* FIXME: Associate AcceleratorTable with the current thread */
433 
434  for (i = 0; i < Accel->Count; i++)
435  {
437  {
438  RETURN( 1);
439  }
440 
441  /* Undocumented feature... */
442  if (Accel->Table[i].fVirt & FVIRT_TBL_END)
443  break;
444  }
445 
446  RETURN( 0);
447 
448 CLEANUP:
450  if (Accel) UserDerefObjectCo(Accel);
451 
452  TRACE("NtUserTranslateAccelerator returns %d\n", _ret_);
453  UserLeave();
454  END_CLEANUP;
455 }
#define WS_DISABLED
Definition: pedump.c:621
VOID FASTCALL UserEnterShared(VOID)
Definition: ntuser.c:241
#define ERROR_INVALID_ACCEL_HANDLE
Definition: winerror.h:884
#define MF_DISABLED
Definition: winuser.h:130
BOOL FASTCALL UserDeleteObject(HANDLE h, HANDLE_TYPE type)
Definition: object.c:683
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define CLEANUP
Definition: ntuser.h:5
#define MF_BYCOMMAND
Definition: winuser.h:202
#define WM_CHAR
Definition: winuser.h:1693
#define USERTAG_ACCEL
Definition: tags.h:195
NTSYSAPI NTSTATUS WINAPI RtlMultiByteToUnicodeN(LPWSTR, DWORD, LPDWORD, LPCSTR, DWORD)
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define WM_INITMENUPOPUP
Definition: winuser.h:1722
BYTE fVirt
Definition: winuser.h:2876
#define ASSERT_REFS_CO(_obj_)
Definition: userfuncs.h:13
char CHAR
Definition: xmlstorage.h:175
TW_UINT32 TW_UINT16 TW_UINT16 MSG
Definition: twain.h:1827
WORD cmd
Definition: winuser.h:2878
#define MAKELPARAM(l, h)
Definition: winuser.h:3915
PVOID NTAPI PsGetCurrentThreadWin32Thread(VOID)
Definition: thread.c:805
LONG NTSTATUS
Definition: precomp.h:26
HWND hWnd
Definition: settings.c:17
PITEM FASTCALL MENU_FindItem(PMENU *pmenu, UINT *nPos, UINT wFlags)
Definition: menu.c:511
static __inline VOID UserRefObjectCo(PVOID obj, PUSER_REFERENCE_ENTRY UserReferenceEntry)
Definition: object.h:25
BOOL FASTCALL UserDereferenceObject(PVOID Object)
Definition: object.c:610
static BOOLEAN FASTCALL co_IntTranslateAccelerator(PWND Window, CONST MSG *pMsg, CONST ACCEL *pAccel)
Definition: accelerator.c:44
UINT_PTR WPARAM
Definition: windef.h:207
#define WS_CHILD
Definition: pedump.c:617
#define VK_MENU
Definition: winuser.h:2158
BOOLEAN APIENTRY NtUserDestroyAcceleratorTable(HACCEL hAccel)
Definition: accelerator.c:344
HWND FASTCALL IntGetCaptureWindow(VOID)
Definition: focus.c:32
#define FASTCALL
Definition: nt_native.h:50
struct _DESKTOP * rpdesk
Definition: win32.h:91
VOID NTAPI ProbeForWrite(IN PVOID Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:143
BOOLEAN UserDestroyAccelTable(PVOID Object)
Definition: accelerator.c:328
PVOID FASTCALL UserCreateObject(PUSER_HANDLE_TABLE ht, PDESKTOP pDesktop, PTHREADINFO pti, HANDLE *h, HANDLE_TYPE type, ULONG size)
Definition: object.c:535
DWORD FASTCALL UserGetKeyState(DWORD dwKey)
Definition: msgqueue.c:221
#define FALT
Definition: winuser.h:20
_SEH2_TRY
Definition: create.c:4250
FORCEINLINE PMENU UserGetMenuObject(HMENU hMenu)
Definition: userfuncs.h:3
Definition: window.c:29
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
HACCEL APIENTRY NtUserCreateAcceleratorTable(LPACCEL Entries, ULONG EntriesCount)
Definition: accelerator.c:229
PROCDESKHEAD head
Definition: ntuser.h:385
HACCEL hAccel
Definition: main.c:47
unsigned int BOOL
Definition: ntddk_ex.h:94
static __inline VOID UserDerefObjectCo(PVOID obj)
Definition: object.h:38
#define MF_BYPOSITION
Definition: winuser.h:203
#define WM_SYSCHAR
Definition: winuser.h:1697
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
#define VK_SHIFT
Definition: winuser.h:2156
Definition: object.h:3
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
#define WM_KEYDOWN
Definition: winuser.h:1691
WORD key
Definition: winuser.h:2877
PWND FASTCALL UserGetWindowObject(HWND hWnd)
Definition: window.c:103
#define WS_MINIMIZED
Definition: undocuser.h:18
VOID FASTCALL UserEnterExclusive(VOID)
Definition: ntuser.c:247
#define FSHIFT
Definition: winuser.h:23
#define TRACE(s)
Definition: solgame.cpp:4
int APIENTRY NtUserTranslateAccelerator(HWND hWnd, HACCEL hAccel, LPMSG pUnsafeMessage)
Definition: accelerator.c:375
#define _SEH2_YIELD(STMT_)
Definition: pseh2_64.h:8
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
static const UCHAR Index[8]
Definition: usbohci.c:18
#define DECLARE_RETURN(type)
Definition: ntuser.h:3
static IUnknown Object
Definition: main.c:512
CHAR Message[80]
Definition: alive.c:5
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
PACCELERATOR_TABLE FASTCALL UserGetAccelObject(HACCEL hAccel)
Definition: accelerator.c:21
#define FCONTROL
Definition: winuser.h:21
VOID NTAPI ProbeForRead(IN CONST VOID *Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:102
static const WCHAR L[]
Definition: oid.c:1250
LRESULT FASTCALL co_IntSendMessage(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
Definition: message.c:1281
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:414
ULONG APIENTRY NtUserCopyAcceleratorTable(HACCEL hAccel, LPACCEL Entries, ULONG EntriesCount)
Definition: accelerator.c:171
#define WM_COMMAND
Definition: winuser.h:1716
#define FVIRT_MASK
Definition: accelerator.c:17
VOID FASTCALL SetLastNtError(NTSTATUS Status)
Definition: error.c:36
UINT FASTCALL IntFindSubMenu(HMENU *hMenu, HMENU hSubTarget)
Definition: menu.c:4870
Status
Definition: gdiplustypes.h:24
Definition: ntuser.h:657
VOID FASTCALL UserLeave(VOID)
Definition: ntuser.c:255
PROCMARKHEAD head
Definition: accelerator.h:5
_SEH2_END
Definition: create.c:4424
#define WM_INITMENU
Definition: winuser.h:1721
PVOID UserGetObject(PUSER_HANDLE_TABLE ht, HANDLE handle, HANDLE_TYPE type)
Definition: object.c:462
LIST_ENTRY Entries[5]
Definition: ExDoubleList.c:8
#define STATUS_NO_MEMORY
Definition: ntstatus.h:246
unsigned int UINT
Definition: ndis.h:50
#define VK_CONTROL
Definition: winuser.h:2157
#define WM_SYSKEYDOWN
Definition: winuser.h:1695
unsigned int ULONG
Definition: retypes.h:1
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
const char * PCSTR
Definition: typedefs.h:51
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:12
#define MF_GRAYED
Definition: winuser.h:129
DBG_DEFAULT_CHANNEL(UserAccel)
return STATUS_SUCCESS
Definition: btrfs.c:2725
PUSER_HANDLE_TABLE gHandleTable
Definition: object.c:13
#define FVIRT_TBL_END
Definition: accelerator.c:16
#define FVIRTKEY
Definition: winuser.h:24
static const CLSID *static CLSID *static const GUID VARIANT VARIANT *static IServiceProvider DWORD *static HMENU
Definition: ordinal.c:60
#define WM_SYSCOMMAND
Definition: winuser.h:1717
#define CONST
Definition: pedump.c:81
ENGAPI VOID APIENTRY EngSetLastError(_In_ ULONG iError)
Definition: error.c:27
#define RETURN(rrr)
Definition: decompress.c:40
#define APIENTRY
Definition: api.h:79
#define END_CLEANUP
Definition: ntuser.h:6
UINT FASTCALL IntGetMenuState(HMENU hMenu, UINT uId, UINT uFlags)
Definition: menu.c:4830