Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenaccelerator.c
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: ReactOS kernel 00004 * PURPOSE: Window accelerator 00005 * FILE: subsystems/win32/win32k/ntuser/accelerator.c 00006 * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net) 00007 * Copyright 1993 Martin Ayotte 00008 * Copyright 1994 Alexandre Julliard 00009 * Copyright 1997 Morten Welinder 00010 * Copyright 2011 Rafal Harabien 00011 */ 00012 00013 #include <win32k.h> 00014 DBG_DEFAULT_CHANNEL(UserAccel); 00015 00016 #define FVIRT_TBL_END 0x80 00017 #define FVIRT_MASK 0x7F 00018 00019 /* FUNCTIONS *****************************************************************/ 00020 00021 PACCELERATOR_TABLE FASTCALL UserGetAccelObject(HACCEL hAccel) 00022 { 00023 PACCELERATOR_TABLE Accel; 00024 00025 if (!hAccel) 00026 { 00027 EngSetLastError(ERROR_INVALID_ACCEL_HANDLE); 00028 return NULL; 00029 } 00030 00031 Accel = UserGetObject(gHandleTable, hAccel, otAccel); 00032 if (!Accel) 00033 { 00034 EngSetLastError(ERROR_INVALID_ACCEL_HANDLE); 00035 return NULL; 00036 } 00037 00038 return Accel; 00039 } 00040 00041 00042 static 00043 BOOLEAN FASTCALL 00044 co_IntTranslateAccelerator( 00045 PWND Window, 00046 CONST MSG *pMsg, 00047 CONST ACCEL *pAccel) 00048 { 00049 BOOL bFound = FALSE; 00050 UINT Mask = 0, nPos; 00051 HWND hWnd; 00052 HMENU hMenu, hSubMenu; 00053 PMENU_OBJECT MenuObject, SubMenu; 00054 PMENU_ITEM MenuItem; 00055 00056 ASSERT_REFS_CO(Window); 00057 00058 hWnd = Window->head.h; 00059 00060 TRACE("IntTranslateAccelerator(hwnd %x, message %x, wParam %x, lParam %x, fVirt %d, key %x, cmd %x)\n", 00061 hWnd, pMsg->message, pMsg->wParam, pMsg->lParam, pAccel->fVirt, pAccel->key, pAccel->cmd); 00062 00063 if (UserGetKeyState(VK_CONTROL) & 0x8000) Mask |= FCONTROL; 00064 if (UserGetKeyState(VK_MENU) & 0x8000) Mask |= FALT; // FIXME: VK_LMENU (msg winetest!) 00065 if (UserGetKeyState(VK_SHIFT) & 0x8000) Mask |= FSHIFT; 00066 TRACE("Mask 0x%x\n", Mask); 00067 00068 if (pAccel->fVirt & FVIRTKEY) 00069 { 00070 /* This is a virtual key. Process WM_(SYS)KEYDOWN messages. */ 00071 if (pMsg->message == WM_KEYDOWN || pMsg->message == WM_SYSKEYDOWN) 00072 { 00073 /* Check virtual key and SHIFT, CTRL, LALT state */ 00074 if (pMsg->wParam == pAccel->key && Mask == (pAccel->fVirt & (FSHIFT | FCONTROL | FALT))) 00075 { 00076 bFound = TRUE; 00077 } 00078 } 00079 } 00080 else 00081 { 00082 /* This is a char code. Process WM_(SYS)CHAR messages. */ 00083 if (pMsg->message == WM_CHAR || pMsg->message == WM_SYSCHAR) 00084 { 00085 /* Check char code and LALT state only */ 00086 if (pMsg->wParam == pAccel->key && (Mask & FALT) == (pAccel->fVirt & FALT)) 00087 { 00088 bFound = TRUE; 00089 } 00090 } 00091 } 00092 00093 if (!bFound) 00094 { 00095 /* Don't translate this msg */ 00096 TRACE("IntTranslateAccelerator returns FALSE\n"); 00097 return FALSE; 00098 } 00099 00100 /* Check if accelerator is associated with menu command */ 00101 hMenu = (Window->style & WS_CHILD) ? 0 : (HMENU)Window->IDMenu; 00102 hSubMenu = NULL; 00103 MenuObject = IntGetMenuObject(hMenu); 00104 if (MenuObject) 00105 { 00106 nPos = IntGetMenuItemByFlag(MenuObject, 00107 pAccel->cmd, 00108 MF_BYCOMMAND, 00109 &SubMenu, 00110 &MenuItem, 00111 NULL); 00112 if (nPos != (UINT) - 1) 00113 hSubMenu = SubMenu->head.h; 00114 else 00115 hMenu = NULL; 00116 } 00117 if (!hMenu) 00118 { 00119 /* Check system menu now */ 00120 hMenu = Window->SystemMenu; 00121 hSubMenu = hMenu; /* system menu is a popup menu */ 00122 MenuObject = IntGetMenuObject(hMenu); 00123 if (MenuObject) 00124 { 00125 nPos = IntGetMenuItemByFlag(MenuObject, 00126 pAccel->cmd, 00127 MF_BYCOMMAND, 00128 &SubMenu, 00129 &MenuItem, 00130 NULL); 00131 if (nPos != (UINT) - 1) 00132 hSubMenu = SubMenu->head.h; 00133 else 00134 hMenu = NULL; 00135 } 00136 } 00137 00138 /* If this is a menu item, there is no capturing enabled and 00139 window is not disabled, send WM_INITMENU */ 00140 if (hMenu && !IntGetCaptureWindow()) 00141 { 00142 co_IntSendMessage(hWnd, WM_INITMENU, (WPARAM)hMenu, 0L); 00143 if (hSubMenu) 00144 { 00145 nPos = IntFindSubMenu(&hMenu, hSubMenu); 00146 TRACE("hSysMenu = %p, hSubMenu = %p, nPos = %d\n", hMenu, hSubMenu, nPos); 00147 co_IntSendMessage(hWnd, WM_INITMENUPOPUP, (WPARAM)hSubMenu, MAKELPARAM(nPos, TRUE)); 00148 } 00149 } 00150 00151 /* Don't send any message if: 00152 - window is disabled 00153 - menu item is disabled 00154 - this is window menu and window is minimized */ 00155 if (!(Window->style & WS_DISABLED) && 00156 !(hMenu && IntGetMenuState(hMenu, pAccel->cmd, MF_BYCOMMAND) & (MF_DISABLED | MF_GRAYED)) && 00157 !(hMenu && hMenu == (HMENU)Window->IDMenu && (Window->style & WS_MINIMIZED))) 00158 { 00159 /* If this is system menu item, send WM_SYSCOMMAND, otherwise send WM_COMMAND */ 00160 if (hMenu && hMenu == Window->SystemMenu) 00161 { 00162 TRACE("Sending WM_SYSCOMMAND, wParam=%0x\n", pAccel->cmd); 00163 co_IntSendMessage(hWnd, WM_SYSCOMMAND, pAccel->cmd, 0x00010000L); 00164 } 00165 else 00166 { 00167 TRACE("Sending WM_COMMAND, wParam=%0x\n", 0x10000 | pAccel->cmd); 00168 co_IntSendMessage(hWnd, WM_COMMAND, 0x10000 | pAccel->cmd, 0L); 00169 } 00170 } 00171 00172 TRACE("IntTranslateAccelerator returns TRUE\n"); 00173 return TRUE; 00174 } 00175 00176 00177 /* SYSCALLS *****************************************************************/ 00178 00179 00180 ULONG 00181 APIENTRY 00182 NtUserCopyAcceleratorTable( 00183 HACCEL hAccel, 00184 LPACCEL Entries, 00185 ULONG EntriesCount) 00186 { 00187 PACCELERATOR_TABLE Accel; 00188 ULONG Ret; 00189 DECLARE_RETURN(int); 00190 00191 TRACE("Enter NtUserCopyAcceleratorTable\n"); 00192 UserEnterShared(); 00193 00194 Accel = UserGetAccelObject(hAccel); 00195 if (!Accel) 00196 { 00197 RETURN(0); 00198 } 00199 00200 /* If Entries is NULL return table size */ 00201 if (!Entries) 00202 { 00203 RETURN(Accel->Count); 00204 } 00205 00206 /* Don't overrun */ 00207 if (Accel->Count < EntriesCount) 00208 EntriesCount = Accel->Count; 00209 00210 Ret = 0; 00211 00212 _SEH2_TRY 00213 { 00214 ProbeForWrite(Entries, EntriesCount*sizeof(Entries[0]), 4); 00215 00216 for (Ret = 0; Ret < EntriesCount; Ret++) 00217 { 00218 Entries[Ret].fVirt = Accel->Table[Ret].fVirt; 00219 Entries[Ret].key = Accel->Table[Ret].key; 00220 Entries[Ret].cmd = Accel->Table[Ret].cmd; 00221 } 00222 } 00223 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00224 { 00225 SetLastNtError(_SEH2_GetExceptionCode()); 00226 Ret = 0; 00227 } 00228 _SEH2_END; 00229 00230 RETURN(Ret); 00231 00232 CLEANUP: 00233 TRACE("Leave NtUserCopyAcceleratorTable, ret=%i\n", _ret_); 00234 UserLeave(); 00235 END_CLEANUP; 00236 } 00237 00238 HACCEL 00239 APIENTRY 00240 NtUserCreateAcceleratorTable( 00241 LPACCEL Entries, 00242 ULONG EntriesCount) 00243 { 00244 PACCELERATOR_TABLE Accel; 00245 HACCEL hAccel; 00246 ULONG Index; 00247 NTSTATUS Status = STATUS_SUCCESS; 00248 DECLARE_RETURN(HACCEL); 00249 00250 TRACE("Enter NtUserCreateAcceleratorTable(Entries %p, EntriesCount %d)\n", 00251 Entries, EntriesCount); 00252 UserEnterExclusive(); 00253 00254 if (!Entries || EntriesCount <= 0) 00255 { 00256 SetLastNtError(STATUS_INVALID_PARAMETER); 00257 RETURN( (HACCEL) NULL ); 00258 } 00259 00260 Accel = UserCreateObject(gHandleTable, NULL, (PHANDLE)&hAccel, otAccel, sizeof(ACCELERATOR_TABLE)); 00261 00262 if (Accel == NULL) 00263 { 00264 SetLastNtError(STATUS_NO_MEMORY); 00265 RETURN( (HACCEL) NULL ); 00266 } 00267 00268 Accel->Count = EntriesCount; 00269 Accel->Table = ExAllocatePoolWithTag(PagedPool, EntriesCount * sizeof(ACCEL), USERTAG_ACCEL); 00270 if (Accel->Table == NULL) 00271 { 00272 UserDereferenceObject(Accel); 00273 UserDeleteObject(hAccel, otAccel); 00274 SetLastNtError(STATUS_NO_MEMORY); 00275 RETURN( (HACCEL) NULL); 00276 } 00277 00278 _SEH2_TRY 00279 { 00280 ProbeForRead(Entries, EntriesCount * sizeof(ACCEL), 4); 00281 00282 for (Index = 0; Index < EntriesCount; Index++) 00283 { 00284 Accel->Table[Index].fVirt = Entries[Index].fVirt & FVIRT_MASK; 00285 if(Accel->Table[Index].fVirt & FVIRTKEY) 00286 { 00287 Accel->Table[Index].key = Entries[Index].key; 00288 } 00289 else 00290 { 00291 RtlMultiByteToUnicodeN(&Accel->Table[Index].key, 00292 sizeof(WCHAR), 00293 NULL, 00294 (PCSTR)&Entries[Index].key, 00295 sizeof(CHAR)); 00296 } 00297 00298 Accel->Table[Index].cmd = Entries[Index].cmd; 00299 } 00300 } 00301 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00302 { 00303 Status = _SEH2_GetExceptionCode(); 00304 } 00305 _SEH2_END; 00306 00307 if (!NT_SUCCESS(Status)) 00308 { 00309 ExFreePoolWithTag(Accel->Table, USERTAG_ACCEL); 00310 UserDereferenceObject(Accel); 00311 UserDeleteObject(hAccel, otAccel); 00312 SetLastNtError(Status); 00313 RETURN( (HACCEL) NULL); 00314 } 00315 00316 /* FIXME: Save HandleTable in a list somewhere so we can clean it up again */ 00317 00318 RETURN(hAccel); 00319 00320 CLEANUP: 00321 TRACE("Leave NtUserCreateAcceleratorTable(Entries %p, EntriesCount %d) = %x\n", 00322 Entries, EntriesCount, _ret_); 00323 UserLeave(); 00324 END_CLEANUP; 00325 } 00326 00327 BOOLEAN 00328 APIENTRY 00329 NtUserDestroyAcceleratorTable( 00330 HACCEL hAccel) 00331 { 00332 PACCELERATOR_TABLE Accel; 00333 DECLARE_RETURN(BOOLEAN); 00334 00335 /* FIXME: If the handle table is from a call to LoadAcceleratorTable, decrement it's 00336 usage count (and return TRUE). 00337 FIXME: Destroy only tables created using CreateAcceleratorTable. 00338 */ 00339 00340 TRACE("NtUserDestroyAcceleratorTable(Table %x)\n", hAccel); 00341 UserEnterExclusive(); 00342 00343 if (!(Accel = UserGetAccelObject(hAccel))) 00344 { 00345 RETURN( FALSE); 00346 } 00347 00348 if (Accel->Table != NULL) 00349 { 00350 ExFreePoolWithTag(Accel->Table, USERTAG_ACCEL); 00351 Accel->Table = NULL; 00352 } 00353 00354 UserDeleteObject(hAccel, otAccel); 00355 00356 RETURN( TRUE); 00357 00358 CLEANUP: 00359 TRACE("Leave NtUserDestroyAcceleratorTable(Table %x) = %i\n", hAccel, _ret_); 00360 UserLeave(); 00361 END_CLEANUP; 00362 } 00363 00364 int 00365 APIENTRY 00366 NtUserTranslateAccelerator( 00367 HWND hWnd, 00368 HACCEL hAccel, 00369 LPMSG pUnsafeMessage) 00370 { 00371 PWND Window = NULL; 00372 PACCELERATOR_TABLE Accel = NULL; 00373 ULONG i; 00374 MSG Message; 00375 USER_REFERENCE_ENTRY AccelRef, WindowRef; 00376 DECLARE_RETURN(int); 00377 00378 TRACE("NtUserTranslateAccelerator(hWnd %x, Table %x, Message %p)\n", 00379 hWnd, hAccel, pUnsafeMessage); 00380 UserEnterShared(); 00381 00382 if (hWnd == NULL) 00383 { 00384 RETURN( 0); 00385 } 00386 00387 _SEH2_TRY 00388 { 00389 ProbeForRead(pUnsafeMessage, sizeof(MSG), 4); 00390 RtlCopyMemory(&Message, pUnsafeMessage, sizeof(MSG)); 00391 } 00392 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00393 { 00394 SetLastNtError(_SEH2_GetExceptionCode()); 00395 _SEH2_YIELD(RETURN( 0)); 00396 } 00397 _SEH2_END; 00398 00399 if ((Message.message != WM_KEYDOWN) && 00400 (Message.message != WM_SYSKEYDOWN) && 00401 (Message.message != WM_SYSCHAR) && 00402 (Message.message != WM_CHAR)) 00403 { 00404 RETURN( 0); 00405 } 00406 00407 Accel = UserGetAccelObject(hAccel); 00408 if (!Accel) 00409 { 00410 RETURN( 0); 00411 } 00412 00413 UserRefObjectCo(Accel, &AccelRef); 00414 00415 Window = UserGetWindowObject(hWnd); 00416 if (!Window) 00417 { 00418 RETURN( 0); 00419 } 00420 00421 UserRefObjectCo(Window, &WindowRef); 00422 00423 /* FIXME: Associate AcceleratorTable with the current thread */ 00424 00425 for (i = 0; i < Accel->Count; i++) 00426 { 00427 if (co_IntTranslateAccelerator(Window, &Message, &Accel->Table[i])) 00428 { 00429 RETURN( 1); 00430 } 00431 00432 /* Undocumented feature... */ 00433 if (Accel->Table[i].fVirt & FVIRT_TBL_END) 00434 break; 00435 } 00436 00437 RETURN( 0); 00438 00439 CLEANUP: 00440 if (Window) UserDerefObjectCo(Window); 00441 if (Accel) UserDerefObjectCo(Accel); 00442 00443 TRACE("NtUserTranslateAccelerator returns %d\n", _ret_); 00444 UserLeave(); 00445 END_CLEANUP; 00446 } Generated on Sun May 27 2012 04:38:29 for ReactOS by
1.7.6.1
|