Sync to trunk (r47832)
[reactos.git] / dll / win32 / user32 / windows / hook.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 1998, 1999, 2000, 2001 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 /*
20 *
21 * PROJECT: ReactOS user32.dll
22 * FILE: lib/user32/windows/input.c
23 * PURPOSE: Input
24 * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
25 * UPDATE HISTORY:
26 * 09-05-2001 CSH Created
27 */
28
29 /* INCLUDES ******************************************************************/
30
31 #include <user32.h>
32
33 #include <wine/debug.h>
34
35 WINE_DEFAULT_DEBUG_CHANNEL(user32);
36
37 /* PRIVATE FUNCTIONS *********************************************************/
38
39 static
40 DWORD
41 FASTCALL
42 GetMaskFromEvent(DWORD Event)
43 {
44 DWORD Ret = 0;
45
46 if ( Event > EVENT_OBJECT_STATECHANGE )
47 {
48 if ( Event == EVENT_OBJECT_LOCATIONCHANGE ) return SRV_EVENT_LOCATIONCHANGE;
49 if ( Event == EVENT_OBJECT_NAMECHANGE ) return SRV_EVENT_NAMECHANGE;
50 if ( Event == EVENT_OBJECT_VALUECHANGE ) return SRV_EVENT_VALUECHANGE;
51 return SRV_EVENT_CREATE;
52 }
53
54 if ( Event == EVENT_OBJECT_STATECHANGE ) return SRV_EVENT_STATECHANGE;
55
56 Ret = SRV_EVENT_RUNNING;
57
58 if ( Event < EVENT_SYSTEM_MENUSTART ) return SRV_EVENT_CREATE;
59
60 if ( Event <= EVENT_SYSTEM_MENUPOPUPEND )
61 {
62 Ret = SRV_EVENT_MENU;
63 }
64 else
65 {
66 if ( Event <= EVENT_CONSOLE_CARET-1 ) return SRV_EVENT_CREATE;
67 if ( Event <= EVENT_CONSOLE_END_APPLICATION ) return SRV_EVENT_END_APPLICATION;
68 if ( Event != EVENT_OBJECT_FOCUS ) return SRV_EVENT_CREATE;
69 }
70 return Ret;
71 }
72
73 static
74 HHOOK
75 FASTCALL
76 IntSetWindowsHook(
77 int idHook,
78 HOOKPROC lpfn,
79 HINSTANCE hMod,
80 DWORD dwThreadId,
81 BOOL bAnsi)
82 {
83 WCHAR ModuleName[MAX_PATH];
84 UNICODE_STRING USModuleName;
85
86 if (NULL != hMod)
87 {
88 if (0 == GetModuleFileNameW(hMod, ModuleName, MAX_PATH))
89 {
90 return NULL;
91 }
92 RtlInitUnicodeString(&USModuleName, ModuleName);
93 }
94 else
95 {
96 RtlInitUnicodeString(&USModuleName, NULL);
97 }
98
99 return NtUserSetWindowsHookEx(hMod, &USModuleName, dwThreadId, idHook, lpfn, bAnsi);
100 }
101
102
103 /* FUNCTIONS *****************************************************************/
104
105 #if 0
106 BOOL
107 WINAPI
108 CallMsgFilter(
109 LPMSG lpMsg,
110 int nCode)
111 {
112 UNIMPLEMENTED;
113 return FALSE;
114 }
115 #endif
116
117 /*
118 * @implemented
119 */
120 BOOL
121 WINAPI
122 CallMsgFilterA(
123 LPMSG lpMsg,
124 int nCode)
125 {
126 BOOL ret = FALSE;
127
128 if (nCode != HCBT_CREATEWND) ret = NtUserCallMsgFilter((LPMSG) lpMsg, nCode);
129 else
130 {
131 UNICODE_STRING usBuffer;
132 CBT_CREATEWNDA *cbtcwA = (CBT_CREATEWNDA *)lpMsg->lParam;
133 CBT_CREATEWNDW cbtcwW;
134 CREATESTRUCTW csW;
135 MSG Msg;
136
137 Msg.hwnd = lpMsg->hwnd;
138 Msg.message = lpMsg->message;
139 Msg.time = lpMsg->time;
140 Msg.pt = lpMsg->pt;
141 Msg.wParam = lpMsg->wParam;
142
143 cbtcwW.lpcs = &csW;
144 cbtcwW.hwndInsertAfter = cbtcwA->hwndInsertAfter;
145 csW = *(CREATESTRUCTW *)cbtcwA->lpcs;
146
147 if (HIWORD(cbtcwA->lpcs->lpszName))
148 {
149 RtlCreateUnicodeStringFromAsciiz(&usBuffer,cbtcwA->lpcs->lpszName);
150 csW.lpszName = usBuffer.Buffer;
151 }
152 if (HIWORD(cbtcwA->lpcs->lpszClass))
153 {
154 RtlCreateUnicodeStringFromAsciiz(&usBuffer,cbtcwA->lpcs->lpszClass);
155 csW.lpszClass = usBuffer.Buffer;
156 }
157 Msg.lParam =(LPARAM) &cbtcwW;
158
159 ret = NtUserCallMsgFilter((LPMSG)&Msg, nCode);
160
161 lpMsg->time = Msg.time;
162 lpMsg->pt = Msg.pt;
163
164 cbtcwA->hwndInsertAfter = cbtcwW.hwndInsertAfter;
165 if (HIWORD(csW.lpszName)) HeapFree( GetProcessHeap(), 0, (LPWSTR)csW.lpszName );
166 if (HIWORD(csW.lpszClass)) HeapFree( GetProcessHeap(), 0, (LPWSTR)csW.lpszClass );
167 }
168 return ret;
169 }
170
171
172 /*
173 * @implemented
174 */
175 BOOL
176 WINAPI
177 CallMsgFilterW(
178 LPMSG lpMsg,
179 int nCode)
180 {
181 return NtUserCallMsgFilter((LPMSG) lpMsg, nCode);
182 }
183
184
185 /*
186 * @implemented
187 */
188 LRESULT
189 WINAPI
190 CallNextHookEx(
191 HHOOK Hook, // Windows NT/XP/2003: Ignored.
192 int Code,
193 WPARAM wParam,
194 LPARAM lParam)
195 {
196 PCLIENTINFO ClientInfo;
197 DWORD Flags, Save;
198 PHOOK pHook;
199 LRESULT lResult = 0;
200
201 GetConnected();
202
203 ClientInfo = GetWin32ClientInfo();
204
205 if (!ClientInfo->phkCurrent) return 0;
206
207 pHook = SharedPtrToUser(ClientInfo->phkCurrent);
208
209 if (pHook->HookId == WH_CALLWNDPROC || pHook->HookId == WH_CALLWNDPROCRET)
210 {
211 Save = ClientInfo->dwHookData;
212 Flags = ClientInfo->CI_flags & CI_CURTHPRHOOK;
213 // wParam: If the message was sent by the current thread/process, it is
214 // nonzero; otherwise, it is zero.
215 if (wParam) ClientInfo->CI_flags |= CI_CURTHPRHOOK;
216 else ClientInfo->CI_flags &= ~CI_CURTHPRHOOK;
217
218 if (pHook->HookId == WH_CALLWNDPROC)
219 {
220 PCWPSTRUCT pCWP = (PCWPSTRUCT)lParam;
221
222 NtUserMessageCall( pCWP->hwnd,
223 pCWP->message,
224 pCWP->wParam,
225 pCWP->lParam,
226 (ULONG_PTR)&lResult,
227 FNID_CALLWNDPROC,
228 pHook->Ansi);
229 }
230 else
231 {
232 PCWPRETSTRUCT pCWPR = (PCWPRETSTRUCT)lParam;
233
234 ClientInfo->dwHookData = pCWPR->lResult;
235
236 NtUserMessageCall( pCWPR->hwnd,
237 pCWPR->message,
238 pCWPR->wParam,
239 pCWPR->lParam,
240 (ULONG_PTR)&lResult,
241 FNID_CALLWNDPROCRET,
242 pHook->Ansi);
243 }
244 ClientInfo->CI_flags ^= ((ClientInfo->CI_flags ^ Flags) & CI_CURTHPRHOOK);
245 ClientInfo->dwHookData = Save;
246 }
247 else
248 lResult = NtUserCallNextHookEx(Code, wParam, lParam, pHook->Ansi);
249
250 return lResult;
251 }
252
253
254 /*
255 * @unimplemented
256 */
257 HHOOK
258 WINAPI
259 SetWindowsHookW(int idHook, HOOKPROC lpfn)
260 {
261 return IntSetWindowsHook(idHook, lpfn, NULL, 0, FALSE);
262 }
263
264 /*
265 * @unimplemented
266 */
267 HHOOK
268 WINAPI
269 SetWindowsHookA(int idHook, HOOKPROC lpfn)
270 {
271 return IntSetWindowsHook(idHook, lpfn, NULL, 0, TRUE);
272 }
273
274 /*
275 * @unimplemented
276 */
277 BOOL
278 WINAPI
279 DeregisterShellHookWindow(HWND hWnd)
280 {
281 return NtUserCallHwnd(hWnd, HWND_ROUTINE_DEREGISTERSHELLHOOKWINDOW);
282 }
283
284 /*
285 * @unimplemented
286 */
287 BOOL
288 WINAPI
289 RegisterShellHookWindow(HWND hWnd)
290 {
291 return NtUserCallHwnd(hWnd, HWND_ROUTINE_REGISTERSHELLHOOKWINDOW);
292 }
293
294 /*
295 * @implemented
296 */
297 BOOL
298 WINAPI
299 UnhookWindowsHook ( int nCode, HOOKPROC pfnFilterProc )
300 {
301 return NtUserCallTwoParam(nCode, (DWORD_PTR)pfnFilterProc, TWOPARAM_ROUTINE_UNHOOKWINDOWSHOOK);
302 }
303
304 /*
305 * @implemented
306 */
307 VOID
308 WINAPI
309 NotifyWinEvent(
310 DWORD event,
311 HWND hwnd,
312 LONG idObject,
313 LONG idChild
314 )
315 {
316 // "Servers call NotifyWinEvent to announce the event to the system after the
317 // event has occurred; they must never notify the system of an event before
318 // the event has occurred." msdn on NotifyWinEvent.
319 if (gpsi->dwInstalledEventHooks & GetMaskFromEvent(event)) // Check to see.
320 NtUserNotifyWinEvent(event, hwnd, idObject, idChild);
321 }
322
323 /*
324 * @implemented
325 */
326 HWINEVENTHOOK
327 WINAPI
328 SetWinEventHook(
329 UINT eventMin,
330 UINT eventMax,
331 HMODULE hmodWinEventProc,
332 WINEVENTPROC pfnWinEventProc,
333 DWORD idProcess,
334 DWORD idThread,
335 UINT dwFlags
336 )
337 {
338 WCHAR ModuleName[MAX_PATH];
339 UNICODE_STRING USModuleName;
340
341 if ((hmodWinEventProc != NULL) && (dwFlags & WINEVENT_INCONTEXT))
342 {
343 if (0 == GetModuleFileNameW(hmodWinEventProc, ModuleName, MAX_PATH))
344 {
345 return NULL;
346 }
347 RtlInitUnicodeString(&USModuleName, ModuleName);
348 }
349 else
350 {
351 RtlInitUnicodeString(&USModuleName, NULL);
352 }
353
354 return NtUserSetWinEventHook(eventMin,
355 eventMax,
356 hmodWinEventProc,
357 &USModuleName,
358 pfnWinEventProc,
359 idProcess,
360 idThread,
361 dwFlags);
362 }
363
364 /*
365 * @implemented
366 */
367 BOOL
368 WINAPI
369 IsWinEventHookInstalled(
370 DWORD event)
371 {
372 if ((PTHREADINFO)NtCurrentTeb()->Win32ThreadInfo)
373 {
374 return (gpsi->dwInstalledEventHooks & GetMaskFromEvent(event)) != 0;
375 }
376 return FALSE;
377 }
378
379 /*
380 * @unimplemented
381 */
382 HHOOK
383 WINAPI
384 SetWindowsHookExA(
385 int idHook,
386 HOOKPROC lpfn,
387 HINSTANCE hMod,
388 DWORD dwThreadId)
389 {
390 return IntSetWindowsHook(idHook, lpfn, hMod, dwThreadId, TRUE);
391 }
392
393
394 /*
395 * @unimplemented
396 */
397 HHOOK
398 WINAPI
399 SetWindowsHookExW(
400 int idHook,
401 HOOKPROC lpfn,
402 HINSTANCE hMod,
403 DWORD dwThreadId)
404 {
405 return IntSetWindowsHook(idHook, lpfn, hMod, dwThreadId, FALSE);
406 }
407
408 NTSTATUS WINAPI
409 User32CallHookProcFromKernel(PVOID Arguments, ULONG ArgumentLength)
410 {
411 PHOOKPROC_CALLBACK_ARGUMENTS Common;
412 LRESULT Result;
413 CREATESTRUCTW Csw;
414 CBT_CREATEWNDW CbtCreatewndw;
415 CREATESTRUCTA Csa;
416 CBT_CREATEWNDA CbtCreatewnda;
417 PHOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS CbtCreatewndExtra = NULL;
418 WPARAM wParam = 0;
419 LPARAM lParam = 0;
420 PKBDLLHOOKSTRUCT KeyboardLlData;
421 PMSLLHOOKSTRUCT MouseLlData;
422 PMSG Msg;
423 PMOUSEHOOKSTRUCT MHook;
424 PCWPSTRUCT CWP;
425 PCWPRETSTRUCT CWPR;
426 PRECTL prl;
427 LPCBTACTIVATESTRUCT pcbtas;
428
429 Common = (PHOOKPROC_CALLBACK_ARGUMENTS) Arguments;
430
431 switch(Common->HookId)
432 {
433 case WH_CBT:
434 {
435 switch(Common->Code)
436 {
437 case HCBT_CREATEWND:
438 CbtCreatewndExtra = (PHOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS)
439 ((PCHAR) Common + Common->lParam);
440 Csw = CbtCreatewndExtra->Cs;
441 if (NULL != CbtCreatewndExtra->Cs.lpszName)
442 {
443 Csw.lpszName = (LPCWSTR)((PCHAR) CbtCreatewndExtra
444 + (ULONG) CbtCreatewndExtra->Cs.lpszName);
445 }
446 if (0 != HIWORD(CbtCreatewndExtra->Cs.lpszClass))
447 {
448 Csw.lpszClass = (LPCWSTR)((PCHAR) CbtCreatewndExtra
449 + LOWORD((ULONG) CbtCreatewndExtra->Cs.lpszClass));
450 }
451 wParam = Common->wParam;
452 if (Common->Ansi)
453 {
454 memcpy(&Csa, &Csw, sizeof(CREATESTRUCTW));
455 CbtCreatewnda.lpcs = &Csa;
456 CbtCreatewnda.hwndInsertAfter = CbtCreatewndExtra->WndInsertAfter;
457 lParam = (LPARAM) &CbtCreatewnda;
458 }
459 else
460 {
461 CbtCreatewndw.lpcs = &Csw;
462 CbtCreatewndw.hwndInsertAfter = CbtCreatewndExtra->WndInsertAfter;
463 lParam = (LPARAM) &CbtCreatewndw;
464 }
465 break;
466 case HCBT_CLICKSKIPPED:
467 MHook = (PMOUSEHOOKSTRUCT)((PCHAR) Common + Common->lParam);
468 lParam = (LPARAM) MHook;
469 break;
470 case HCBT_MOVESIZE:
471 prl = (PRECTL)((PCHAR) Common + Common->lParam);
472 lParam = (LPARAM) prl;
473 break;
474 case HCBT_ACTIVATE:
475 pcbtas = (LPCBTACTIVATESTRUCT)((PCHAR) Common + Common->lParam);
476 lParam = (LPARAM) pcbtas;
477 break;
478 case HCBT_KEYSKIPPED:
479 case HCBT_MINMAX:
480 case HCBT_SETFOCUS:
481 case HCBT_SYSCOMMAND:
482 case HCBT_DESTROYWND:
483 case HCBT_QS:
484 wParam = Common->wParam;
485 lParam = Common->lParam;
486 break;
487 default:
488 ERR("HCBT_ not supported = %d\n", Common->Code);
489 return ZwCallbackReturn(NULL, 0, STATUS_NOT_SUPPORTED);
490 }
491
492 if (Common->Proc)
493 Result = Common->Proc(Common->Code, wParam, lParam);
494 else
495 {
496 ERR("Common = 0x%x, Proc = 0x%x\n",Common,Common->Proc);
497 }
498 switch(Common->Code)
499 {
500 case HCBT_CREATEWND:
501 CbtCreatewndExtra->WndInsertAfter = CbtCreatewndw.hwndInsertAfter;
502 break;
503 }
504 break;
505 }
506 case WH_KEYBOARD_LL:
507 KeyboardLlData = (PKBDLLHOOKSTRUCT)((PCHAR) Common + Common->lParam);
508 Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) KeyboardLlData);
509 break;
510 case WH_MOUSE_LL:
511 MouseLlData = (PMSLLHOOKSTRUCT)((PCHAR) Common + Common->lParam);
512 Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) MouseLlData);
513 break;
514 case WH_MOUSE:
515 MHook = (PMOUSEHOOKSTRUCT)((PCHAR) Common + Common->lParam);
516 Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) MHook);
517 break;
518 case WH_CALLWNDPROC:
519 CWP = (PCWPSTRUCT)((PCHAR) Common + Common->lParam);
520 Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) CWP);
521 break;
522 case WH_CALLWNDPROCRET:
523 CWPR = (PCWPRETSTRUCT)((PCHAR) Common + Common->lParam);
524 Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) CWPR);
525 break;
526 case WH_MSGFILTER:
527 case WH_SYSMSGFILTER:
528 case WH_GETMESSAGE:
529 Msg = (PMSG)((PCHAR) Common + Common->lParam);
530 // FIXME("UHOOK Memory: %x: %x\n",Common, Msg);
531 Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) Msg);
532 break;
533 case WH_FOREGROUNDIDLE:
534 case WH_KEYBOARD:
535 case WH_SHELL:
536 Result = Common->Proc(Common->Code, Common->wParam, Common->lParam);
537 break;
538 default:
539 return ZwCallbackReturn(NULL, 0, STATUS_NOT_SUPPORTED);
540 }
541
542 return ZwCallbackReturn(&Result, sizeof(LRESULT), STATUS_SUCCESS);
543 }
544
545 NTSTATUS WINAPI
546 User32CallEventProcFromKernel(PVOID Arguments, ULONG ArgumentLength)
547 {
548 PEVENTPROC_CALLBACK_ARGUMENTS Common;
549
550 Common = (PEVENTPROC_CALLBACK_ARGUMENTS) Arguments;
551
552 Common->Proc(Common->hook,
553 Common->event,
554 Common->hwnd,
555 Common->idObject,
556 Common->idChild,
557 Common->dwEventThread,
558 Common->dwmsEventTime);
559
560 return ZwCallbackReturn(NULL, 0, STATUS_SUCCESS);
561 }
562
563
564