ReactOS 0.4.15-dev-7108-g1cf6ce6
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>
15
16#define FVIRT_TBL_END 0x80
17#define FVIRT_MASK 0x7F
18
19/* FUNCTIONS *****************************************************************/
20
22{
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
42static
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
169ULONG
172 HACCEL hAccel,
174 ULONG EntriesCount)
175{
176 PACCELERATOR_TABLE Accel;
177 ULONG Ret;
178 DECLARE_RETURN(int);
179
180 TRACE("Enter NtUserCopyAcceleratorTable\n");
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
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
221CLEANUP:
222 TRACE("Leave NtUserCopyAcceleratorTable, ret=%i\n", _ret_);
223 UserLeave();
225}
226
227HACCEL
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 {
272 RETURN( (HACCEL) NULL);
273 }
274
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 {
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) */
317
318 RETURN(hAccel);
319
320CLEANUP:
321 TRACE("Leave NtUserCreateAcceleratorTable(Entries %p, EntriesCount %u) = %p\n",
322 Entries, EntriesCount, _ret_);
323 UserLeave();
325}
326
329{
331
332 if (Accel->Table != NULL)
333 {
335 Accel->Table = NULL;
336 }
337
339 return TRUE;
340}
341
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
364
365 RETURN( TRUE);
366
367CLEANUP:
368 TRACE("Leave NtUserDestroyAcceleratorTable(Table %p) = %u\n", hAccel, _ret_);
369 UserLeave();
371}
372
373int
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);
390
391 if (hWnd == NULL)
392 {
393 RETURN( 0);
394 }
395
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
448CLEANUP:
450 if (Accel) UserDerefObjectCo(Accel);
451
452 TRACE("NtUserTranslateAccelerator returns %d\n", _ret_);
453 UserLeave();
455}
#define RETURN(x)
static const ENTRY Entries[]
unsigned char BOOLEAN
HWND hWnd
Definition: settings.c:17
LONG NTSTATUS
Definition: precomp.h:26
#define DBG_DEFAULT_CHANNEL(ch)
Definition: debug.h:103
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define APIENTRY
Definition: api.h:79
static const WCHAR Message[]
Definition: register.c:74
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define PagedPool
Definition: env_spec_w32.h:308
VOID NTAPI ProbeForRead(IN CONST VOID *Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:102
VOID NTAPI ProbeForWrite(IN PVOID Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:143
#define _SEH2_END
Definition: filesup.c:22
#define _SEH2_TRY
Definition: filesup.c:19
unsigned int BOOL
Definition: ntddk_ex.h:94
HWND FASTCALL IntGetCaptureWindow(VOID)
Definition: focus.c:34
unsigned int Mask
Definition: fpcontrol.c:82
Status
Definition: gdiplustypes.h:25
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
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
@ TYPE_ACCELTABLE
Definition: ntuser.h:48
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
HACCEL hAccel
Definition: main.c:47
static const CLSID *static CLSID *static const GUID VARIANT VARIANT *static IServiceProvider DWORD *static HMENU
Definition: ordinal.c:63
DWORD FASTCALL UserGetKeyState(DWORD dwKey)
Definition: msgqueue.c:221
unsigned int UINT
Definition: ndis.h:50
_Use_decl_annotations_ NTSTATUS NTAPI RtlMultiByteToUnicodeN(_Out_ PWCH UnicodeString, _In_ ULONG UnicodeSize, _Out_opt_ PULONG ResultSize, _In_ PCCH MbString, _In_ ULONG MbSize)
Definition: nlsboot.c:62
#define FASTCALL
Definition: nt_native.h:50
PVOID NTAPI PsGetCurrentThreadWin32Thread(VOID)
Definition: thread.c:805
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:455
#define STATUS_NO_MEMORY
Definition: ntstatus.h:260
VOID FASTCALL UserLeave(VOID)
Definition: ntuser.c:251
VOID FASTCALL UserEnterShared(VOID)
Definition: ntuser.c:235
VOID FASTCALL UserEnterExclusive(VOID)
Definition: ntuser.c:242
#define L(x)
Definition: ntvdm.h:50
static __inline VOID UserDerefObjectCo(PVOID obj)
Definition: object.h:40
static __inline VOID UserRefObjectCo(PVOID obj, PUSER_REFERENCE_ENTRY UserReferenceEntry)
Definition: object.h:27
#define WS_CHILD
Definition: pedump.c:617
#define CONST
Definition: pedump.c:81
#define WS_DISABLED
Definition: pedump.c:621
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:159
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:34
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:162
#define STATUS_SUCCESS
Definition: shellext.h:65
#define TRACE(s)
Definition: solgame.cpp:4
Definition: window.c:28
PROCMARKHEAD head
Definition: accelerator.h:5
struct _DESKTOP * rpdesk
Definition: win32.h:92
Definition: object.h:4
Definition: ntuser.h:692
WORD cmd
Definition: winuser.h:2924
BYTE fVirt
Definition: winuser.h:2922
WORD key
Definition: winuser.h:2923
PROCDESKHEAD head
Definition: ntuser.h:415
TW_UINT32 TW_UINT16 TW_UINT16 MSG
Definition: twain.h:1829
const char * PCSTR
Definition: typedefs.h:52
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define WS_MINIMIZED
Definition: undocuser.h:18
#define CLEANUP
Definition: ntuser.h:5
#define DECLARE_RETURN(type)
Definition: ntuser.h:3
#define END_CLEANUP
Definition: ntuser.h:6
FORCEINLINE PMENU UserGetMenuObject(HMENU hMenu)
Definition: userfuncs.h:4
PWND FASTCALL UserGetWindowObject(HWND hWnd)
Definition: window.c:122
#define ASSERT_REFS_CO(_obj_)
Definition: userfuncs.h:14
_Must_inspect_result_ _In_ WDFCOLLECTION _In_ WDFOBJECT Object
_In_ WDFCOLLECTION _In_ ULONG Index
VOID FASTCALL SetLastNtError(NTSTATUS Status)
Definition: error.c:37
int APIENTRY NtUserTranslateAccelerator(HWND hWnd, HACCEL hAccel, LPMSG pUnsafeMessage)
Definition: accelerator.c:375
HACCEL APIENTRY NtUserCreateAcceleratorTable(LPACCEL Entries, ULONG EntriesCount)
Definition: accelerator.c:229
#define FVIRT_TBL_END
Definition: accelerator.c:16
ULONG APIENTRY NtUserCopyAcceleratorTable(HACCEL hAccel, LPACCEL Entries, ULONG EntriesCount)
Definition: accelerator.c:171
BOOLEAN APIENTRY NtUserDestroyAcceleratorTable(HACCEL hAccel)
Definition: accelerator.c:344
BOOLEAN UserDestroyAccelTable(PVOID Object)
Definition: accelerator.c:328
PACCELERATOR_TABLE FASTCALL UserGetAccelObject(HACCEL hAccel)
Definition: accelerator.c:21
static BOOLEAN FASTCALL co_IntTranslateAccelerator(PWND Window, CONST MSG *pMsg, CONST ACCEL *pAccel)
Definition: accelerator.c:44
#define FVIRT_MASK
Definition: accelerator.c:17
UINT FASTCALL IntFindSubMenu(HMENU *hMenu, HMENU hSubTarget)
Definition: menu.c:5003
PITEM FASTCALL MENU_FindItem(PMENU *pmenu, UINT *nPos, UINT wFlags)
Definition: menu.c:507
UINT FASTCALL IntGetMenuState(HMENU hMenu, UINT uId, UINT uFlags)
Definition: menu.c:4963
LRESULT FASTCALL co_IntSendMessage(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
Definition: message.c:1445
PVOID UserGetObject(PUSER_HANDLE_TABLE ht, HANDLE handle, HANDLE_TYPE type)
Definition: object.c:495
BOOL FASTCALL UserDereferenceObject(PVOID Object)
Definition: object.c:644
BOOL FASTCALL UserDeleteObject(HANDLE h, HANDLE_TYPE type)
Definition: object.c:717
PUSER_HANDLE_TABLE gHandleTable
Definition: object.c:13
PVOID FASTCALL UserCreateObject(PUSER_HANDLE_TABLE ht, PDESKTOP pDesktop, PTHREADINFO pti, HANDLE *h, HANDLE_TYPE type, ULONG size)
Definition: object.c:568
#define USERTAG_ACCEL
Definition: tags.h:196
ENGAPI VOID APIENTRY EngSetLastError(_In_ ULONG iError)
Definition: error.c:28
UINT_PTR WPARAM
Definition: windef.h:207
#define ERROR_INVALID_ACCEL_HANDLE
Definition: winerror.h:884
#define MF_BYCOMMAND
Definition: winuser.h:202
#define WM_SYSCOMMAND
Definition: winuser.h:1740
#define MAKELPARAM(l, h)
Definition: winuser.h:4007
#define WM_COMMAND
Definition: winuser.h:1739
#define VK_CONTROL
Definition: winuser.h:2202
#define WM_INITMENU
Definition: winuser.h:1744
#define FVIRTKEY
Definition: winuser.h:24
#define FSHIFT
Definition: winuser.h:23
#define WM_SYSCHAR
Definition: winuser.h:1720
#define WM_INITMENUPOPUP
Definition: winuser.h:1745
#define MF_BYPOSITION
Definition: winuser.h:203
#define FCONTROL
Definition: winuser.h:21
#define WM_CHAR
Definition: winuser.h:1716
#define VK_SHIFT
Definition: winuser.h:2201
#define WM_KEYDOWN
Definition: winuser.h:1714
#define FALT
Definition: winuser.h:20
#define WM_SYSKEYDOWN
Definition: winuser.h:1718
#define VK_MENU
Definition: winuser.h:2203
#define MF_GRAYED
Definition: winuser.h:129
#define MF_DISABLED
Definition: winuser.h:130
__wchar_t WCHAR
Definition: xmlstorage.h:180
char CHAR
Definition: xmlstorage.h:175