6da6f21680a30300ed77fe8ee830f22a7f6f9955
[reactos.git] / reactos / subsys / win32k / ntuser / hotkey.c
1 /*
2 * ReactOS W32 Subsystem
3 * Copyright (C) 2003 ReactOS Team
4 *
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.
9 *
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.
14 *
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.
18 */
19 /* $Id$
20 *
21 * COPYRIGHT: See COPYING in the top level directory
22 * PROJECT: ReactOS kernel
23 * PURPOSE: HotKey support
24 * FILE: subsys/win32k/ntuser/hotkey.c
25 * PROGRAMER: Eric Kohl
26 * REVISION HISTORY:
27 * 02-11-2003 EK Created
28 */
29
30 /* INCLUDES ******************************************************************/
31
32 #include <w32k.h>
33
34 #define NDEBUG
35 #include <debug.h>
36
37 /* GLOBALS *******************************************************************/
38
39 /* FUNCTIONS *****************************************************************/
40
41 NTSTATUS FASTCALL
42 InitHotKeys(PWINSTATION_OBJECT WinStaObject)
43 {
44 InitializeListHead(&WinStaObject->HotKeyListHead);
45 ExInitializeFastMutex(&WinStaObject->HotKeyListLock);
46
47 return STATUS_SUCCESS;
48 }
49
50
51 NTSTATUS FASTCALL
52 CleanupHotKeys(PWINSTATION_OBJECT WinStaObject)
53 {
54
55 return STATUS_SUCCESS;
56 }
57
58
59 BOOL
60 GetHotKey (PWINSTATION_OBJECT WinStaObject,
61 UINT fsModifiers,
62 UINT vk,
63 struct _ETHREAD **Thread,
64 HWND *hWnd,
65 int *id)
66 {
67 PLIST_ENTRY Entry;
68 PHOT_KEY_ITEM HotKeyItem;
69
70 if(!WinStaObject)
71 {
72 return FALSE;
73 }
74
75 IntLockHotKeys(WinStaObject);
76
77 Entry = WinStaObject->HotKeyListHead.Flink;
78 while (Entry != &WinStaObject->HotKeyListHead)
79 {
80 HotKeyItem = (PHOT_KEY_ITEM) CONTAINING_RECORD(Entry,
81 HOT_KEY_ITEM,
82 ListEntry);
83 if (HotKeyItem->fsModifiers == fsModifiers &&
84 HotKeyItem->vk == vk)
85 {
86 if (Thread != NULL)
87 *Thread = HotKeyItem->Thread;
88
89 if (hWnd != NULL)
90 *hWnd = HotKeyItem->hWnd;
91
92 if (id != NULL)
93 *id = HotKeyItem->id;
94
95 IntUnLockHotKeys(WinStaObject);
96
97 return TRUE;
98 }
99
100 Entry = Entry->Flink;
101 }
102
103 IntUnLockHotKeys(WinStaObject);
104
105 return FALSE;
106 }
107
108
109 VOID
110 UnregisterWindowHotKeys(PWINDOW_OBJECT Window)
111 {
112 PLIST_ENTRY Entry;
113 PHOT_KEY_ITEM HotKeyItem;
114 PWINSTATION_OBJECT WinStaObject = NULL;
115
116 if(Window->OwnerThread && Window->OwnerThread->ThreadsProcess)
117 WinStaObject = Window->OwnerThread->Tcb.Win32Thread->Desktop->WindowStation;
118
119 if(!WinStaObject)
120 return;
121
122 IntLockHotKeys(WinStaObject);
123
124 Entry = WinStaObject->HotKeyListHead.Flink;
125 while (Entry != &WinStaObject->HotKeyListHead)
126 {
127 HotKeyItem = (PHOT_KEY_ITEM) CONTAINING_RECORD (Entry,
128 HOT_KEY_ITEM,
129 ListEntry);
130 Entry = Entry->Flink;
131 if (HotKeyItem->hWnd == Window->hSelf)
132 {
133 RemoveEntryList (&HotKeyItem->ListEntry);
134 ExFreePool (HotKeyItem);
135 }
136 }
137
138 IntUnLockHotKeys(WinStaObject);
139 }
140
141
142 VOID
143 UnregisterThreadHotKeys(struct _ETHREAD *Thread)
144 {
145 PLIST_ENTRY Entry;
146 PHOT_KEY_ITEM HotKeyItem;
147 PWINSTATION_OBJECT WinStaObject = NULL;
148
149 if(Thread->Tcb.Win32Thread && Thread->Tcb.Win32Thread->Desktop)
150 WinStaObject = Thread->Tcb.Win32Thread->Desktop->WindowStation;
151
152 if(!WinStaObject)
153 return;
154
155 IntLockHotKeys(WinStaObject);
156
157 Entry = WinStaObject->HotKeyListHead.Flink;
158 while (Entry != &WinStaObject->HotKeyListHead)
159 {
160 HotKeyItem = (PHOT_KEY_ITEM) CONTAINING_RECORD (Entry,
161 HOT_KEY_ITEM,
162 ListEntry);
163 Entry = Entry->Flink;
164 if (HotKeyItem->Thread == Thread)
165 {
166 RemoveEntryList (&HotKeyItem->ListEntry);
167 ExFreePool (HotKeyItem);
168 }
169 }
170
171 IntUnLockHotKeys(WinStaObject);
172 }
173
174
175 static BOOL
176 IsHotKey (PWINSTATION_OBJECT WinStaObject,
177 UINT fsModifiers,
178 UINT vk)
179 {
180 PLIST_ENTRY Entry;
181 PHOT_KEY_ITEM HotKeyItem;
182
183 Entry = WinStaObject->HotKeyListHead.Flink;
184 while (Entry != &WinStaObject->HotKeyListHead)
185 {
186 HotKeyItem = (PHOT_KEY_ITEM) CONTAINING_RECORD (Entry,
187 HOT_KEY_ITEM,
188 ListEntry);
189 if (HotKeyItem->fsModifiers == fsModifiers &&
190 HotKeyItem->vk == vk)
191 {
192 return TRUE;
193 }
194
195 Entry = Entry->Flink;
196 }
197
198 return FALSE;
199 }
200
201
202 BOOL STDCALL
203 NtUserRegisterHotKey(HWND hWnd,
204 int id,
205 UINT fsModifiers,
206 UINT vk)
207 {
208 PHOT_KEY_ITEM HotKeyItem;
209 PWINDOW_OBJECT Window;
210 PWINSTATION_OBJECT WinStaObject = NULL;
211 PETHREAD HotKeyThread;
212 DECLARE_RETURN(BOOL);
213
214 DPRINT("Enter NtUserRegisterHotKey\n");
215 UserEnterExclusive();
216
217 if (hWnd == NULL)
218 {
219 HotKeyThread = PsGetCurrentThread();
220 }
221 else
222 {
223 Window = IntGetWindowObject(hWnd);
224 if(!Window)
225 {
226 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
227 RETURN( FALSE);
228 }
229 HotKeyThread = Window->OwnerThread;
230 IntReleaseWindowObject(Window);
231 }
232
233
234 if(HotKeyThread->ThreadsProcess && HotKeyThread->ThreadsProcess->Win32Process)
235 WinStaObject = HotKeyThread->Tcb.Win32Thread->Desktop->WindowStation;
236
237 if(!WinStaObject)
238 {
239 RETURN( FALSE);
240 }
241
242 IntLockHotKeys(WinStaObject);
243
244 /* Check for existing hotkey */
245 if (IsHotKey (WinStaObject, fsModifiers, vk))
246 {
247 IntUnLockHotKeys(WinStaObject);
248 RETURN( FALSE);
249 }
250
251 HotKeyItem = ExAllocatePoolWithTag (PagedPool, sizeof(HOT_KEY_ITEM), TAG_HOTKEY);
252 if (HotKeyItem == NULL)
253 {
254 IntUnLockHotKeys(WinStaObject);
255 RETURN( FALSE);
256 }
257
258 HotKeyItem->Thread = HotKeyThread;
259 HotKeyItem->hWnd = hWnd;
260 HotKeyItem->id = id;
261 HotKeyItem->fsModifiers = fsModifiers;
262 HotKeyItem->vk = vk;
263
264 InsertHeadList (&WinStaObject->HotKeyListHead,
265 &HotKeyItem->ListEntry);
266
267 IntUnLockHotKeys(WinStaObject);
268
269 RETURN( TRUE);
270
271 CLEANUP:
272 DPRINT("Leave NtUserRegisterHotKey, ret=%i\n",_ret_);
273 UserLeave();
274 END_CLEANUP;
275 }
276
277
278 BOOL STDCALL
279 NtUserUnregisterHotKey(HWND hWnd,
280 int id)
281 {
282 PLIST_ENTRY Entry;
283 PHOT_KEY_ITEM HotKeyItem;
284 PWINDOW_OBJECT Window;
285 PWINSTATION_OBJECT WinStaObject = NULL;
286 DECLARE_RETURN(BOOL);
287
288 DPRINT("Enter NtUserUnregisterHotKey\n");
289 UserEnterExclusive();
290
291 Window = IntGetWindowObject(hWnd);
292 if(!Window)
293 {
294 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
295 RETURN( FALSE);
296 }
297
298 if(Window->OwnerThread->ThreadsProcess && Window->OwnerThread->ThreadsProcess->Win32Process)
299 WinStaObject = Window->OwnerThread->Tcb.Win32Thread->Desktop->WindowStation;
300
301 if(!WinStaObject)
302 {
303 IntReleaseWindowObject(Window);
304 RETURN( FALSE);
305 }
306
307 IntLockHotKeys(WinStaObject);
308
309 Entry = WinStaObject->HotKeyListHead.Flink;
310 while (Entry != &WinStaObject->HotKeyListHead)
311 {
312 HotKeyItem = (PHOT_KEY_ITEM) CONTAINING_RECORD (Entry,
313 HOT_KEY_ITEM,
314 ListEntry);
315 if (HotKeyItem->hWnd == hWnd &&
316 HotKeyItem->id == id)
317 {
318 RemoveEntryList (&HotKeyItem->ListEntry);
319 ExFreePool (HotKeyItem);
320 IntUnLockHotKeys(WinStaObject);
321
322 IntReleaseWindowObject(Window);
323 RETURN( TRUE);
324 }
325
326 Entry = Entry->Flink;
327 }
328
329 IntUnLockHotKeys(WinStaObject);
330
331 IntReleaseWindowObject(Window);
332 RETURN( FALSE);
333
334 CLEANUP:
335 DPRINT("Leave NtUserUnregisterHotKey, ret=%i\n",_ret_);
336 UserLeave();
337 END_CLEANUP;
338 }
339
340 /* EOF */