reactos/dll/win32/user32/windows/hook.c
Amine Khaldi c424146e2c Create a branch for cmake bringup.
svn path=/branches/cmake-bringup/; revision=48236
2010-07-24 18:52:44 +00:00

564 lines
14 KiB
C

/*
* ReactOS kernel
* Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
*
* PROJECT: ReactOS user32.dll
* FILE: lib/user32/windows/input.c
* PURPOSE: Input
* PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
* UPDATE HISTORY:
* 09-05-2001 CSH Created
*/
/* INCLUDES ******************************************************************/
#include <user32.h>
#include <wine/debug.h>
WINE_DEFAULT_DEBUG_CHANNEL(user32);
/* PRIVATE FUNCTIONS *********************************************************/
static
DWORD
FASTCALL
GetMaskFromEvent(DWORD Event)
{
DWORD Ret = 0;
if ( Event > EVENT_OBJECT_STATECHANGE )
{
if ( Event == EVENT_OBJECT_LOCATIONCHANGE ) return SRV_EVENT_LOCATIONCHANGE;
if ( Event == EVENT_OBJECT_NAMECHANGE ) return SRV_EVENT_NAMECHANGE;
if ( Event == EVENT_OBJECT_VALUECHANGE ) return SRV_EVENT_VALUECHANGE;
return SRV_EVENT_CREATE;
}
if ( Event == EVENT_OBJECT_STATECHANGE ) return SRV_EVENT_STATECHANGE;
Ret = SRV_EVENT_RUNNING;
if ( Event < EVENT_SYSTEM_MENUSTART ) return SRV_EVENT_CREATE;
if ( Event <= EVENT_SYSTEM_MENUPOPUPEND )
{
Ret = SRV_EVENT_MENU;
}
else
{
if ( Event <= EVENT_CONSOLE_CARET-1 ) return SRV_EVENT_CREATE;
if ( Event <= EVENT_CONSOLE_END_APPLICATION ) return SRV_EVENT_END_APPLICATION;
if ( Event != EVENT_OBJECT_FOCUS ) return SRV_EVENT_CREATE;
}
return Ret;
}
static
HHOOK
FASTCALL
IntSetWindowsHook(
int idHook,
HOOKPROC lpfn,
HINSTANCE hMod,
DWORD dwThreadId,
BOOL bAnsi)
{
WCHAR ModuleName[MAX_PATH];
UNICODE_STRING USModuleName;
if (NULL != hMod)
{
if (0 == GetModuleFileNameW(hMod, ModuleName, MAX_PATH))
{
return NULL;
}
RtlInitUnicodeString(&USModuleName, ModuleName);
}
else
{
RtlInitUnicodeString(&USModuleName, NULL);
}
return NtUserSetWindowsHookEx(hMod, &USModuleName, dwThreadId, idHook, lpfn, bAnsi);
}
/* FUNCTIONS *****************************************************************/
#if 0
BOOL
WINAPI
CallMsgFilter(
LPMSG lpMsg,
int nCode)
{
UNIMPLEMENTED;
return FALSE;
}
#endif
/*
* @implemented
*/
BOOL
WINAPI
CallMsgFilterA(
LPMSG lpMsg,
int nCode)
{
BOOL ret = FALSE;
if (nCode != HCBT_CREATEWND) ret = NtUserCallMsgFilter((LPMSG) lpMsg, nCode);
else
{
UNICODE_STRING usBuffer;
CBT_CREATEWNDA *cbtcwA = (CBT_CREATEWNDA *)lpMsg->lParam;
CBT_CREATEWNDW cbtcwW;
CREATESTRUCTW csW;
MSG Msg;
Msg.hwnd = lpMsg->hwnd;
Msg.message = lpMsg->message;
Msg.time = lpMsg->time;
Msg.pt = lpMsg->pt;
Msg.wParam = lpMsg->wParam;
cbtcwW.lpcs = &csW;
cbtcwW.hwndInsertAfter = cbtcwA->hwndInsertAfter;
csW = *(CREATESTRUCTW *)cbtcwA->lpcs;
if (HIWORD(cbtcwA->lpcs->lpszName))
{
RtlCreateUnicodeStringFromAsciiz(&usBuffer,cbtcwA->lpcs->lpszName);
csW.lpszName = usBuffer.Buffer;
}
if (HIWORD(cbtcwA->lpcs->lpszClass))
{
RtlCreateUnicodeStringFromAsciiz(&usBuffer,cbtcwA->lpcs->lpszClass);
csW.lpszClass = usBuffer.Buffer;
}
Msg.lParam =(LPARAM) &cbtcwW;
ret = NtUserCallMsgFilter((LPMSG)&Msg, nCode);
lpMsg->time = Msg.time;
lpMsg->pt = Msg.pt;
cbtcwA->hwndInsertAfter = cbtcwW.hwndInsertAfter;
if (HIWORD(csW.lpszName)) HeapFree( GetProcessHeap(), 0, (LPWSTR)csW.lpszName );
if (HIWORD(csW.lpszClass)) HeapFree( GetProcessHeap(), 0, (LPWSTR)csW.lpszClass );
}
return ret;
}
/*
* @implemented
*/
BOOL
WINAPI
CallMsgFilterW(
LPMSG lpMsg,
int nCode)
{
return NtUserCallMsgFilter((LPMSG) lpMsg, nCode);
}
/*
* @implemented
*/
LRESULT
WINAPI
CallNextHookEx(
HHOOK Hook, // Windows NT/XP/2003: Ignored.
int Code,
WPARAM wParam,
LPARAM lParam)
{
PCLIENTINFO ClientInfo;
DWORD Flags, Save;
PHOOK pHook;
LRESULT lResult = 0;
GetConnected();
ClientInfo = GetWin32ClientInfo();
if (!ClientInfo->phkCurrent) return 0;
pHook = SharedPtrToUser(ClientInfo->phkCurrent);
if (pHook->HookId == WH_CALLWNDPROC || pHook->HookId == WH_CALLWNDPROCRET)
{
Save = ClientInfo->dwHookData;
Flags = ClientInfo->CI_flags & CI_CURTHPRHOOK;
// wParam: If the message was sent by the current thread/process, it is
// nonzero; otherwise, it is zero.
if (wParam) ClientInfo->CI_flags |= CI_CURTHPRHOOK;
else ClientInfo->CI_flags &= ~CI_CURTHPRHOOK;
if (pHook->HookId == WH_CALLWNDPROC)
{
PCWPSTRUCT pCWP = (PCWPSTRUCT)lParam;
NtUserMessageCall( pCWP->hwnd,
pCWP->message,
pCWP->wParam,
pCWP->lParam,
(ULONG_PTR)&lResult,
FNID_CALLWNDPROC,
pHook->Ansi);
}
else
{
PCWPRETSTRUCT pCWPR = (PCWPRETSTRUCT)lParam;
ClientInfo->dwHookData = pCWPR->lResult;
NtUserMessageCall( pCWPR->hwnd,
pCWPR->message,
pCWPR->wParam,
pCWPR->lParam,
(ULONG_PTR)&lResult,
FNID_CALLWNDPROCRET,
pHook->Ansi);
}
ClientInfo->CI_flags ^= ((ClientInfo->CI_flags ^ Flags) & CI_CURTHPRHOOK);
ClientInfo->dwHookData = Save;
}
else
lResult = NtUserCallNextHookEx(Code, wParam, lParam, pHook->Ansi);
return lResult;
}
/*
* @unimplemented
*/
HHOOK
WINAPI
SetWindowsHookW(int idHook, HOOKPROC lpfn)
{
return IntSetWindowsHook(idHook, lpfn, NULL, 0, FALSE);
}
/*
* @unimplemented
*/
HHOOK
WINAPI
SetWindowsHookA(int idHook, HOOKPROC lpfn)
{
return IntSetWindowsHook(idHook, lpfn, NULL, 0, TRUE);
}
/*
* @unimplemented
*/
BOOL
WINAPI
DeregisterShellHookWindow(HWND hWnd)
{
return NtUserCallHwnd(hWnd, HWND_ROUTINE_DEREGISTERSHELLHOOKWINDOW);
}
/*
* @unimplemented
*/
BOOL
WINAPI
RegisterShellHookWindow(HWND hWnd)
{
return NtUserCallHwnd(hWnd, HWND_ROUTINE_REGISTERSHELLHOOKWINDOW);
}
/*
* @implemented
*/
BOOL
WINAPI
UnhookWindowsHook ( int nCode, HOOKPROC pfnFilterProc )
{
return NtUserCallTwoParam(nCode, (DWORD_PTR)pfnFilterProc, TWOPARAM_ROUTINE_UNHOOKWINDOWSHOOK);
}
/*
* @implemented
*/
VOID
WINAPI
NotifyWinEvent(
DWORD event,
HWND hwnd,
LONG idObject,
LONG idChild
)
{
// "Servers call NotifyWinEvent to announce the event to the system after the
// event has occurred; they must never notify the system of an event before
// the event has occurred." msdn on NotifyWinEvent.
if (gpsi->dwInstalledEventHooks & GetMaskFromEvent(event)) // Check to see.
NtUserNotifyWinEvent(event, hwnd, idObject, idChild);
}
/*
* @implemented
*/
HWINEVENTHOOK
WINAPI
SetWinEventHook(
UINT eventMin,
UINT eventMax,
HMODULE hmodWinEventProc,
WINEVENTPROC pfnWinEventProc,
DWORD idProcess,
DWORD idThread,
UINT dwFlags
)
{
WCHAR ModuleName[MAX_PATH];
UNICODE_STRING USModuleName;
if ((hmodWinEventProc != NULL) && (dwFlags & WINEVENT_INCONTEXT))
{
if (0 == GetModuleFileNameW(hmodWinEventProc, ModuleName, MAX_PATH))
{
return NULL;
}
RtlInitUnicodeString(&USModuleName, ModuleName);
}
else
{
RtlInitUnicodeString(&USModuleName, NULL);
}
return NtUserSetWinEventHook(eventMin,
eventMax,
hmodWinEventProc,
&USModuleName,
pfnWinEventProc,
idProcess,
idThread,
dwFlags);
}
/*
* @implemented
*/
BOOL
WINAPI
IsWinEventHookInstalled(
DWORD event)
{
if ((PTHREADINFO)NtCurrentTeb()->Win32ThreadInfo)
{
return (gpsi->dwInstalledEventHooks & GetMaskFromEvent(event)) != 0;
}
return FALSE;
}
/*
* @unimplemented
*/
HHOOK
WINAPI
SetWindowsHookExA(
int idHook,
HOOKPROC lpfn,
HINSTANCE hMod,
DWORD dwThreadId)
{
return IntSetWindowsHook(idHook, lpfn, hMod, dwThreadId, TRUE);
}
/*
* @unimplemented
*/
HHOOK
WINAPI
SetWindowsHookExW(
int idHook,
HOOKPROC lpfn,
HINSTANCE hMod,
DWORD dwThreadId)
{
return IntSetWindowsHook(idHook, lpfn, hMod, dwThreadId, FALSE);
}
NTSTATUS WINAPI
User32CallHookProcFromKernel(PVOID Arguments, ULONG ArgumentLength)
{
PHOOKPROC_CALLBACK_ARGUMENTS Common;
LRESULT Result;
CREATESTRUCTW Csw;
CBT_CREATEWNDW CbtCreatewndw;
CREATESTRUCTA Csa;
CBT_CREATEWNDA CbtCreatewnda;
PHOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS CbtCreatewndExtra = NULL;
WPARAM wParam = 0;
LPARAM lParam = 0;
PKBDLLHOOKSTRUCT KeyboardLlData;
PMSLLHOOKSTRUCT MouseLlData;
PMSG Msg;
PMOUSEHOOKSTRUCT MHook;
PCWPSTRUCT CWP;
PCWPRETSTRUCT CWPR;
PRECTL prl;
LPCBTACTIVATESTRUCT pcbtas;
Common = (PHOOKPROC_CALLBACK_ARGUMENTS) Arguments;
switch(Common->HookId)
{
case WH_CBT:
{
switch(Common->Code)
{
case HCBT_CREATEWND:
CbtCreatewndExtra = (PHOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS)
((PCHAR) Common + Common->lParam);
Csw = CbtCreatewndExtra->Cs;
if (NULL != CbtCreatewndExtra->Cs.lpszName)
{
Csw.lpszName = (LPCWSTR)((PCHAR) CbtCreatewndExtra
+ (ULONG_PTR) CbtCreatewndExtra->Cs.lpszName);
}
if (0 != HIWORD(CbtCreatewndExtra->Cs.lpszClass))
{
Csw.lpszClass = (LPCWSTR)((PCHAR) CbtCreatewndExtra
+ LOWORD((ULONG_PTR) CbtCreatewndExtra->Cs.lpszClass));
}
wParam = Common->wParam;
if (Common->Ansi)
{
memcpy(&Csa, &Csw, sizeof(CREATESTRUCTW));
CbtCreatewnda.lpcs = &Csa;
CbtCreatewnda.hwndInsertAfter = CbtCreatewndExtra->WndInsertAfter;
lParam = (LPARAM) &CbtCreatewnda;
}
else
{
CbtCreatewndw.lpcs = &Csw;
CbtCreatewndw.hwndInsertAfter = CbtCreatewndExtra->WndInsertAfter;
lParam = (LPARAM) &CbtCreatewndw;
}
break;
case HCBT_CLICKSKIPPED:
MHook = (PMOUSEHOOKSTRUCT)((PCHAR) Common + Common->lParam);
lParam = (LPARAM) MHook;
break;
case HCBT_MOVESIZE:
prl = (PRECTL)((PCHAR) Common + Common->lParam);
lParam = (LPARAM) prl;
break;
case HCBT_ACTIVATE:
pcbtas = (LPCBTACTIVATESTRUCT)((PCHAR) Common + Common->lParam);
lParam = (LPARAM) pcbtas;
break;
case HCBT_KEYSKIPPED:
case HCBT_MINMAX:
case HCBT_SETFOCUS:
case HCBT_SYSCOMMAND:
case HCBT_DESTROYWND:
case HCBT_QS:
wParam = Common->wParam;
lParam = Common->lParam;
break;
default:
ERR("HCBT_ not supported = %d\n", Common->Code);
return ZwCallbackReturn(NULL, 0, STATUS_NOT_SUPPORTED);
}
if (Common->Proc)
Result = Common->Proc(Common->Code, wParam, lParam);
else
{
ERR("Common = 0x%x, Proc = 0x%x\n",Common,Common->Proc);
}
switch(Common->Code)
{
case HCBT_CREATEWND:
CbtCreatewndExtra->WndInsertAfter = CbtCreatewndw.hwndInsertAfter;
break;
}
break;
}
case WH_KEYBOARD_LL:
KeyboardLlData = (PKBDLLHOOKSTRUCT)((PCHAR) Common + Common->lParam);
Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) KeyboardLlData);
break;
case WH_MOUSE_LL:
MouseLlData = (PMSLLHOOKSTRUCT)((PCHAR) Common + Common->lParam);
Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) MouseLlData);
break;
case WH_MOUSE:
MHook = (PMOUSEHOOKSTRUCT)((PCHAR) Common + Common->lParam);
Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) MHook);
break;
case WH_CALLWNDPROC:
CWP = (PCWPSTRUCT)((PCHAR) Common + Common->lParam);
Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) CWP);
break;
case WH_CALLWNDPROCRET:
CWPR = (PCWPRETSTRUCT)((PCHAR) Common + Common->lParam);
Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) CWPR);
break;
case WH_MSGFILTER:
case WH_SYSMSGFILTER:
case WH_GETMESSAGE:
Msg = (PMSG)((PCHAR) Common + Common->lParam);
// FIXME("UHOOK Memory: %x: %x\n",Common, Msg);
Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) Msg);
break;
case WH_FOREGROUNDIDLE:
case WH_KEYBOARD:
case WH_SHELL:
Result = Common->Proc(Common->Code, Common->wParam, Common->lParam);
break;
default:
return ZwCallbackReturn(NULL, 0, STATUS_NOT_SUPPORTED);
}
return ZwCallbackReturn(&Result, sizeof(LRESULT), STATUS_SUCCESS);
}
NTSTATUS WINAPI
User32CallEventProcFromKernel(PVOID Arguments, ULONG ArgumentLength)
{
PEVENTPROC_CALLBACK_ARGUMENTS Common;
Common = (PEVENTPROC_CALLBACK_ARGUMENTS) Arguments;
Common->Proc(Common->hook,
Common->event,
Common->hwnd,
Common->idObject,
Common->idChild,
Common->dwEventThread,
Common->dwmsEventTime);
return ZwCallbackReturn(NULL, 0, STATUS_SUCCESS);
}