2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 * COPYRIGHT: See COPYING in the top level directory
22 * PROJECT: ReactOS kernel
23 * PURPOSE: Window classes
24 * FILE: subsys/win32k/ntuser/class.c
25 * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
27 * 06-06-2001 CSH Created
31 * Copyright 1993 Martin Ayotte
32 * Copyright 1994 Alexandre Julliard
33 * Copyright 1997 Morten Welinder
35 * This library is free software; you can redistribute it and/or
36 * modify it under the terms of the GNU Lesser General Public
37 * License as published by the Free Software Foundation; either
38 * version 2.1 of the License, or (at your option) any later version.
40 * This library is distributed in the hope that it will be useful,
41 * but WITHOUT ANY WARRANTY; without even the implied warranty of
42 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
43 * Lesser General Public License for more details.
45 * You should have received a copy of the GNU Lesser General Public
46 * License along with this library; if not, write to the Free Software
47 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
50 /* INCLUDES ******************************************************************/
57 /* FUNCTIONS *****************************************************************/
60 InitAcceleratorImpl(VOID
)
62 return(STATUS_SUCCESS
);
66 CleanupAcceleratorImpl(VOID
)
68 return(STATUS_SUCCESS
);
73 PACCELERATOR_TABLE FASTCALL
UserGetAccelObjectNoRef(HACCEL hAccel
)
75 PACCELERATOR_TABLE Accel
=NULL
;
76 NTSTATUS Status
= ObmReferenceObjectByHandle(gHandleTable
,
81 if (!NT_SUCCESS(Status
))
83 SetLastWin32Error(ERROR_INVALID_ACCEL_HANDLE
);
87 ObmDereferenceObject(Accel
);
96 NtUserCopyAcceleratorTable(
101 PWINSTATION_OBJECT WindowStation
;
102 PACCELERATOR_TABLE Accel
;
107 DPRINT("Enter NtUserCopyAcceleratorTable\n");
110 Status
= IntValidateWindowStationHandle(UserGetProcessWindowStation(),
115 if (!NT_SUCCESS(Status
))
117 SetLastNtError(STATUS_ACCESS_DENIED
);
121 if (!(Accel
= UserGetAccelObjectNoRef(hAccel
)))
123 ObDereferenceObject(WindowStation
);
129 Ret
= min(EntriesCount
, Accel
->Count
);
130 Status
= MmCopyToCaller(Entries
, Accel
->Table
, Ret
* sizeof(ACCEL
));
131 if (!NT_SUCCESS(Status
))
133 ObDereferenceObject(WindowStation
);
134 SetLastNtError(Status
);
143 ObDereferenceObject(WindowStation
);
148 DPRINT("Leave NtUserCopyAcceleratorTable, ret=%i\n",_ret_
);
155 NtUserCreateAcceleratorTable(
159 PWINSTATION_OBJECT WindowStation
;
160 PACCELERATOR_TABLE Accel
;
163 DECLARE_RETURN(HACCEL
);
165 DPRINT("Enter NtUserCreateAcceleratorTable(Entries %p, EntriesCount %d)\n",
166 Entries
, EntriesCount
);
167 UserEnterExclusive();
169 Status
= IntValidateWindowStationHandle(UserGetProcessWindowStation(),
174 if (!NT_SUCCESS(Status
))
176 SetLastNtError(STATUS_ACCESS_DENIED
);
180 Accel
= ObmCreateObject(
184 sizeof(ACCELERATOR_TABLE
));
188 ObDereferenceObject(WindowStation
);
189 SetLastNtError(STATUS_NO_MEMORY
);
190 RETURN( (HACCEL
) 0 );
193 Accel
->Count
= EntriesCount
;
194 if (Accel
->Count
> 0)
196 Accel
->Table
= ExAllocatePoolWithTag(PagedPool
, EntriesCount
* sizeof(ACCEL
), TAG_ACCEL
);
197 if (Accel
->Table
== NULL
)
199 ObmCloseHandle(gHandleTable
, hAccel
);
200 ObDereferenceObject(WindowStation
);
201 SetLastNtError(Status
);
205 Status
= MmCopyFromCaller(Accel
->Table
, Entries
, EntriesCount
* sizeof(ACCEL
));
206 if (!NT_SUCCESS(Status
))
208 ExFreePool(Accel
->Table
);
209 ObmCloseHandle(gHandleTable
, hAccel
);
210 ObDereferenceObject(WindowStation
);
211 SetLastNtError(Status
);
216 ObDereferenceObject(WindowStation
);
218 /* FIXME: Save HandleTable in a list somewhere so we can clean it up again */
223 DPRINT("Leave NtUserCreateAcceleratorTable(Entries %p, EntriesCount %d) = %x\n",
224 Entries
, EntriesCount
,_ret_
);
233 NtUserDestroyAcceleratorTable(
236 PWINSTATION_OBJECT WindowStation
;
237 PACCELERATOR_TABLE Accel
;
239 DECLARE_RETURN(BOOLEAN
);
241 /* FIXME: If the handle table is from a call to LoadAcceleratorTable, decrement it's
242 usage count (and return TRUE).
243 FIXME: Destroy only tables created using CreateAcceleratorTable.
246 DPRINT("NtUserDestroyAcceleratorTable(Table %x)\n", hAccel
);
247 UserEnterExclusive();
249 Status
= IntValidateWindowStationHandle(UserGetProcessWindowStation(),
254 if (!NT_SUCCESS(Status
))
256 SetLastNtError(STATUS_ACCESS_DENIED
);
261 if (!(Accel
= UserGetAccelObjectNoRef(hAccel
)))
263 ObDereferenceObject(WindowStation
);
267 ObmCloseHandle(gHandleTable
, hAccel
);
269 if (Accel
->Table
!= NULL
)
271 ExFreePool(Accel
->Table
);
274 ObDereferenceObject(WindowStation
);
279 DPRINT("Leave NtUserDestroyAcceleratorTable(Table %x) = %i\n", hAccel
,_ret_
);
286 co_IntTranslateAccelerator(
287 PWINDOW_OBJECT Window
,
299 DPRINT("IntTranslateAccelerator(hwnd %x, message %x, wParam %x, lParam %x, fVirt %d, key %x, cmd %x)\n",
300 Window
->hSelf
, message
, wParam
, lParam
, fVirt
, key
, cmd
);
308 if (message
== WM_CHAR
)
310 if (!(fVirt
& FALT
) && !(fVirt
& FVIRTKEY
))
312 DPRINT("found accel for WM_CHAR: ('%c')\n", wParam
& 0xff);
318 if ((fVirt
& FVIRTKEY
) > 0)
321 DPRINT("found accel for virt_key %04x (scan %04x)\n",
322 wParam
, 0xff & HIWORD(lParam
));
324 DPRINT("NtUserGetKeyState(VK_SHIFT) = 0x%x\n",
325 UserGetKeyState(VK_SHIFT
));
326 DPRINT("NtUserGetKeyState(VK_CONTROL) = 0x%x\n",
327 UserGetKeyState(VK_CONTROL
));
328 DPRINT("NtUserGetKeyState(VK_MENU) = 0x%x\n",
329 UserGetKeyState(VK_MENU
));
331 if (UserGetKeyState(VK_SHIFT
) & 0x8000) mask
|= FSHIFT
;
332 if (UserGetKeyState(VK_CONTROL
) & 0x8000) mask
|= FCONTROL
;
333 if (UserGetKeyState(VK_MENU
) & 0x8000) mask
|= FALT
;
334 if (mask
== (fVirt
& (FSHIFT
| FCONTROL
| FALT
))) goto found
;
335 DPRINT("but incorrect SHIFT/CTRL/ALT-state\n");
339 if (!(lParam
& 0x01000000)) /* no special_key */
341 if ((fVirt
& FALT
) && (lParam
& 0x20000000))
342 { /* ^^ ALT pressed */
343 DPRINT("found accel for Alt-%c\n", wParam
& 0xff);
350 DPRINT("IntTranslateAccelerator(hwnd %x, message %x, wParam %x, lParam %x, fVirt %d, key %x, cmd %x) = FALSE\n",
351 Window
->hSelf
, message
, wParam
, lParam
, fVirt
, key
, cmd
);
356 if (message
== WM_KEYUP
|| message
== WM_SYSKEYUP
)
358 else if (IntGetCaptureWindow())
360 else if (!IntIsWindowVisible(Window
->hSelf
)) /* FIXME: WINE IsWindowEnabled == IntIsWindowVisible? */
365 HMENU hMenu
, hSubMenu
, hSysMenu
;
366 UINT uSysStat
= (UINT
)-1, uStat
= (UINT
)-1, nPos
;
368 hMenu
= (UserGetWindowLongW(hWnd
, GWL_STYLE
) & WS_CHILD
) ? 0 : GetMenu(hWnd
);
369 hSysMenu
= get_win_sys_menu(hWnd
);
371 /* find menu item and ask application to initialize it */
372 /* 1. in the system menu */
375 if(MENU_FindItem(&hSubMenu
, &nPos
, MF_BYCOMMAND
))
377 co_IntSendMessage(hWnd
, WM_INITMENU
, (WPARAM
)hSysMenu
, 0L);
378 if(hSubMenu
!= hSysMenu
)
380 nPos
= MENU_FindSubMenu(&hSysMenu
, hSubMenu
);
381 TRACE_(accel
)("hSysMenu = %p, hSubMenu = %p, nPos = %d\n", hSysMenu
, hSubMenu
, nPos
);
382 co_IntSendMessage(hWnd
, WM_INITMENUPOPUP
, (WPARAM
)hSubMenu
, MAKELPARAM(nPos
, TRUE
));
384 uSysStat
= GetMenuState(GetSubMenu(hSysMenu
, 0), cmd
, MF_BYCOMMAND
);
386 else /* 2. in the window's menu */
390 if(MENU_FindItem(&hSubMenu
, &nPos
, MF_BYCOMMAND
))
392 co_IntSendMessage(hWnd
, WM_INITMENU
, (WPARAM
)hMenu
, 0L);
393 if(hSubMenu
!= hMenu
)
395 nPos
= MENU_FindSubMenu(&hMenu
, hSubMenu
);
396 TRACE_(accel
)("hMenu = %p, hSubMenu = %p, nPos = %d\n", hMenu
, hSubMenu
, nPos
);
397 co_IntSendMessage(hWnd
, WM_INITMENUPOPUP
, (WPARAM
)hSubMenu
, MAKELPARAM(nPos
, FALSE
));
399 uStat
= GetMenuState(hMenu
, cmd
, MF_BYCOMMAND
);
403 if (uSysStat
!= (UINT
)-1)
405 if (uSysStat
& (MF_DISABLED
|MF_GRAYED
))
412 if (uStat
!= (UINT
)-1)
418 if (uStat
& (MF_DISABLED
|MF_GRAYED
))
430 DPRINT1("menu search not implemented");
435 if (mesg
== WM_COMMAND
)
437 DPRINT(", sending WM_COMMAND, wParam=%0x\n", 0x10000 | cmd
);
438 co_IntSendMessage(Window
->hSelf
, mesg
, 0x10000 | cmd
, 0L);
440 else if (mesg
== WM_SYSCOMMAND
)
442 DPRINT(", sending WM_SYSCOMMAND, wParam=%0x\n", cmd
);
443 co_IntSendMessage(Window
->hSelf
, mesg
, cmd
, 0x00010000L
);
447 /* some reasons for NOT sending the WM_{SYS}COMMAND message:
448 * #0: unknown (please report!)
449 * #1: for WM_KEYUP,WM_SYSKEYUP
450 * #2: mouse is captured
451 * #3: window is disabled
452 * #4: it's a disabled system menu option
453 * #5: it's a menu option, but window is iconic
454 * #6: it's a menu option, but disabled
456 DPRINT(", but won't send WM_{SYS}COMMAND, reason is #%d\n", mesg
);
459 DPRINT1(" unknown reason - please report!");
463 DPRINT("IntTranslateAccelerator(hWnd %x, message %x, wParam %x, lParam %x, fVirt %d, key %x, cmd %x) = TRUE\n",
464 Window
->hSelf
, message
, wParam
, lParam
, fVirt
, key
, cmd
);
471 NtUserTranslateAccelerator(
476 PWINSTATION_OBJECT WindowStation
= NULL
;
477 PWINDOW_OBJECT Window
= NULL
;
478 PACCELERATOR_TABLE Accel
= NULL
;
483 DPRINT("NtUserTranslateAccelerator(hWnd %x, Table %x, Message %p)\n",
484 hWnd
, hAccel
, Message
);
489 SetLastNtError(STATUS_INVALID_PARAMETER
);
493 if ((Message
->message
!= WM_KEYDOWN
) &&
494 (Message
->message
!= WM_SYSKEYDOWN
) &&
495 (Message
->message
!= WM_SYSCHAR
) &&
496 (Message
->message
!= WM_CHAR
))
501 Status
= IntValidateWindowStationHandle(UserGetProcessWindowStation(),
506 if (!NT_SUCCESS(Status
))
508 SetLastNtError(STATUS_ACCESS_DENIED
);
512 if (!(Accel
= UserGetAccelObjectNoRef(hAccel
)))
517 UserReferenceAccelObjectCo(Accel
);
519 if (!(Window
= UserGetWindowObjectNoRef(hWnd
)))
524 UserReferenceWindowObjectCo(Window
);
527 /* FIXME: Associate AcceleratorTable with the current thread */
529 for (i
= 0; i
< Accel
->Count
; i
++)
531 if (co_IntTranslateAccelerator(Window
, Message
->message
, Message
->wParam
, Message
->lParam
,
532 Accel
->Table
[i
].fVirt
, Accel
->Table
[i
].key
,
533 Accel
->Table
[i
].cmd
))
535 DPRINT("NtUserTranslateAccelerator(hWnd %x, Table %x, Message %p) = %i end\n",
536 hWnd
, hAccel
, Message
, 1);
539 if (((Accel
->Table
[i
].fVirt
& 0x80) > 0))
549 if (Window
) UserReferenceWindowObjectCo(Window
);
550 if (Accel
) UserReferenceAccelObjectCo(Accel
);
552 if (WindowStation
) ObDereferenceObject(WindowStation
);
554 DPRINT("NtUserTranslateAccelerator(hWnd %x, Table %x, Message %p) = %i end\n",
555 hWnd
, hAccel
, Message
, 0);