ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

accelerator.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.