ReactOS 0.4.15-dev-8344-g0574987
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
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 = UserHMGetHandle(MenuObject);
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 = UserHMGetHandle(MenuObject);
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 = 0;
178
179 TRACE("Enter NtUserCopyAcceleratorTable\n");
181
182 Accel = UserGetAccelObject(hAccel);
183 if (!Accel)
184 {
185 goto Exit; // Return 0
186 }
187
188 /* If Entries is NULL return table size */
189 if (!Entries)
190 {
191 Ret = Accel->Count;
192 goto Exit;
193 }
194
195 /* Don't overrun */
196 if (Accel->Count < EntriesCount)
197 EntriesCount = Accel->Count;
198
200 {
201 ProbeForWrite(Entries, EntriesCount*sizeof(Entries[0]), 4);
202
203 for (Ret = 0; Ret < EntriesCount; Ret++)
204 {
205 Entries[Ret].fVirt = Accel->Table[Ret].fVirt;
206 Entries[Ret].key = Accel->Table[Ret].key;
207 Entries[Ret].cmd = Accel->Table[Ret].cmd;
208 }
209 }
211 {
213 Ret = 0;
214 }
215 _SEH2_END;
216
217Exit:
218 TRACE("Leave NtUserCopyAcceleratorTable, ret=%lu\n", Ret);
219 UserLeave();
220 return Ret;
221}
222
223HACCEL
227 ULONG EntriesCount)
228{
229 PACCELERATOR_TABLE Accel;
230 HACCEL hAccel;
231 ULONG Index;
233 HACCEL Ret = NULL;
234 PTHREADINFO pti;
235
236 TRACE("Enter NtUserCreateAcceleratorTable(Entries %p, EntriesCount %u)\n",
237 Entries, EntriesCount);
239
240 if (!Entries || EntriesCount <= 0)
241 {
243 goto Exit; // Return NULL
244 }
245
247
249 pti->rpdesk,
250 pti,
251 (PHANDLE)&hAccel,
253 sizeof(ACCELERATOR_TABLE));
254
255 if (Accel == NULL)
256 {
258 goto Exit; // Return NULL
259 }
260
261 Accel->Count = EntriesCount;
262 Accel->Table = ExAllocatePoolWithTag(PagedPool, EntriesCount * sizeof(ACCEL), USERTAG_ACCEL);
263 if (Accel->Table == NULL)
264 {
268 goto Exit; // Return NULL
269 }
270
272 {
273 ProbeForRead(Entries, EntriesCount * sizeof(ACCEL), 4);
274
275 for (Index = 0; Index < EntriesCount; Index++)
276 {
277 Accel->Table[Index].fVirt = Entries[Index].fVirt & FVIRT_MASK;
278 if(Accel->Table[Index].fVirt & FVIRTKEY)
279 {
280 Accel->Table[Index].key = Entries[Index].key;
281 }
282 else
283 {
285 sizeof(WCHAR),
286 NULL,
287 (PCSTR)&Entries[Index].key,
288 sizeof(CHAR));
289 }
290
291 Accel->Table[Index].cmd = Entries[Index].cmd;
292 }
293 }
295 {
297 }
298 _SEH2_END;
299
300 if (!NT_SUCCESS(Status))
301 {
306 goto Exit; // Return NULL
307 }
308
309 /* FIXME: Save HandleTable in a list somewhere so we can clean it up again */
310
311 /* Release the extra reference (UserCreateObject added 2 references) */
313
314 Ret = hAccel;
315
316Exit:
317 TRACE("Leave NtUserCreateAcceleratorTable(Entries %p, EntriesCount %u) = %p\n",
318 Entries, EntriesCount, Ret);
319 UserLeave();
320 return Ret;
321}
322
325{
327
328 if (Accel->Table != NULL)
329 {
331 Accel->Table = NULL;
332 }
333
335 return TRUE;
336}
337
341 HACCEL hAccel)
342{
343 PACCELERATOR_TABLE Accel;
344 BOOLEAN Ret = FALSE;
345
346 /* FIXME: If the handle table is from a call to LoadAcceleratorTable, decrement it's
347 usage count (and return TRUE).
348 FIXME: Destroy only tables created using CreateAcceleratorTable.
349 */
350
351 TRACE("NtUserDestroyAcceleratorTable(Table %p)\n", hAccel);
353
354 Accel = UserGetAccelObject(hAccel);
355 if (Accel)
356 {
357 Ret = UserDestroyAccelTable(Accel);
358 }
359
360 TRACE("Leave NtUserDestroyAcceleratorTable(Table %p) = %u\n", hAccel, Ret);
361 UserLeave();
362 return Ret;
363}
364
365int
368 HWND hWnd,
369 HACCEL hAccel,
370 LPMSG pUnsafeMessage)
371{
372 PWND Window = NULL;
373 PACCELERATOR_TABLE Accel = NULL;
374 ULONG i;
375 MSG Message;
376 USER_REFERENCE_ENTRY AccelRef, WindowRef;
377 int Ret = 0;
378
379 TRACE("NtUserTranslateAccelerator(hWnd %p, hAccel %p, Message %p)\n",
380 hWnd, hAccel, pUnsafeMessage);
382
383 if (hWnd == NULL)
384 {
385 goto Cleanup; // Return 0
386 }
387
389 {
390 ProbeForRead(pUnsafeMessage, sizeof(MSG), 4);
391 RtlCopyMemory(&Message, pUnsafeMessage, sizeof(MSG));
392 }
394 {
396 _SEH2_YIELD(goto Cleanup); // Return 0
397 }
398 _SEH2_END;
399
400 if ((Message.message != WM_KEYDOWN) &&
401 (Message.message != WM_SYSKEYDOWN) &&
402 (Message.message != WM_SYSCHAR) &&
403 (Message.message != WM_CHAR))
404 {
405 goto Cleanup; // Return 0
406 }
407
408 Accel = UserGetAccelObject(hAccel);
409 if (!Accel)
410 {
411 goto Cleanup; // Return 0
412 }
413
414 UserRefObjectCo(Accel, &AccelRef);
415
417 if (!Window)
418 {
419 goto Cleanup; // Return 0
420 }
421
422 UserRefObjectCo(Window, &WindowRef);
423
424 /* FIXME: Associate AcceleratorTable with the current thread */
425
426 for (i = 0; i < Accel->Count; i++)
427 {
429 {
430 Ret = 1;
431 break;
432 }
433
434 /* Undocumented feature... */
435 if (Accel->Table[i].fVirt & FVIRT_TBL_END)
436 break;
437 }
438
439Cleanup:
441 if (Accel) UserDerefObjectCo(Accel);
442
443 TRACE("NtUserTranslateAccelerator returns %d\n", Ret);
444 UserLeave();
445 return Ret;
446}
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:106
#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:33
#define APIENTRY
Definition: api.h:79
static const WCHAR Message[]
Definition: register.c:74
static const WCHAR Cleanup[]
Definition: register.c:80
#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
#define UserHMGetHandle(obj)
Definition: ntuser.h:230
@ 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:258
VOID FASTCALL UserEnterShared(VOID)
Definition: ntuser.c:242
VOID FASTCALL UserEnterExclusive(VOID)
Definition: ntuser.c:249
#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:165
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:66
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:168
#define STATUS_SUCCESS
Definition: shellext.h:65
static void Exit(void)
Definition: sock.c:1330
#define TRACE(s)
Definition: solgame.cpp:4
Definition: window.c:28
struct _DESKTOP * rpdesk
Definition: win32.h:92
Definition: object.h:4
Definition: ntuser.h:694
WORD cmd
Definition: winuser.h:2925
BYTE fVirt
Definition: winuser.h:2923
WORD key
Definition: winuser.h:2924
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
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(_In_ NTSTATUS Status)
Definition: error.c:31
int APIENTRY NtUserTranslateAccelerator(HWND hWnd, HACCEL hAccel, LPMSG pUnsafeMessage)
Definition: accelerator.c:367
HACCEL APIENTRY NtUserCreateAcceleratorTable(LPACCEL Entries, ULONG EntriesCount)
Definition: accelerator.c:225
#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:340
BOOLEAN UserDestroyAccelTable(PVOID Object)
Definition: accelerator.c:324
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:5033
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:4993
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:22
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:1741
#define MAKELPARAM(l, h)
Definition: winuser.h:4008
#define WM_COMMAND
Definition: winuser.h:1740
#define VK_CONTROL
Definition: winuser.h:2203
#define WM_INITMENU
Definition: winuser.h:1745
#define FVIRTKEY
Definition: winuser.h:24
#define FSHIFT
Definition: winuser.h:23
#define WM_SYSCHAR
Definition: winuser.h:1721
#define WM_INITMENUPOPUP
Definition: winuser.h:1746
#define MF_BYPOSITION
Definition: winuser.h:203
#define FCONTROL
Definition: winuser.h:21
#define WM_CHAR
Definition: winuser.h:1717
#define VK_SHIFT
Definition: winuser.h:2202
#define WM_KEYDOWN
Definition: winuser.h:1715
#define FALT
Definition: winuser.h:20
#define WM_SYSKEYDOWN
Definition: winuser.h:1719
#define VK_MENU
Definition: winuser.h:2204
#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