mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 10:04:49 +00:00
Present for GreatLord:
Implement WH_KEYBOARD_LL hook svn path=/trunk/; revision=15281
This commit is contained in:
parent
f326ceb70f
commit
c1557a2be1
9 changed files with 206 additions and 43 deletions
|
@ -281,6 +281,7 @@ User32CallHookProcFromKernel(PVOID Arguments, ULONG ArgumentLength)
|
|||
PHOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS CbtCreatewndExtra;
|
||||
WPARAM wParam;
|
||||
LPARAM lParam;
|
||||
KBDLLHOOKSTRUCT *KeyboardLlData;
|
||||
|
||||
Common = (PHOOKPROC_CALLBACK_ARGUMENTS) Arguments;
|
||||
|
||||
|
@ -353,6 +354,10 @@ User32CallHookProcFromKernel(PVOID Arguments, ULONG ArgumentLength)
|
|||
break;
|
||||
}
|
||||
break;
|
||||
case WH_KEYBOARD_LL:
|
||||
KeyboardLlData = (KBDLLHOOKSTRUCT *)((PCHAR) Common + Common->lParam);
|
||||
Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) KeyboardLlData);
|
||||
break;
|
||||
default:
|
||||
return ZwCallbackReturn(NULL, 0, STATUS_NOT_SUPPORTED);
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ typedef struct _USER_SENT_MESSAGE
|
|||
ULONG_PTR CompletionCallbackContext;
|
||||
/* entry in the dispatching list of the sender's message queue */
|
||||
LIST_ENTRY DispatchingListEntry;
|
||||
BOOL HookMessage;
|
||||
} USER_SENT_MESSAGE, *PUSER_SENT_MESSAGE;
|
||||
|
||||
typedef struct _USER_SENT_MESSAGE_NOTIFY
|
||||
|
@ -127,7 +128,8 @@ MsqIsHung(PUSER_MESSAGE_QUEUE MessageQueue);
|
|||
NTSTATUS FASTCALL
|
||||
MsqSendMessage(PUSER_MESSAGE_QUEUE MessageQueue,
|
||||
HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam,
|
||||
UINT uTimeout, BOOL Block, ULONG_PTR *uResult);
|
||||
UINT uTimeout, BOOL Block, BOOL HookMessage,
|
||||
ULONG_PTR *uResult);
|
||||
PUSER_MESSAGE FASTCALL
|
||||
MsqCreateMessage(LPMSG Msg, BOOLEAN FreeLParam);
|
||||
VOID FASTCALL
|
||||
|
|
|
@ -240,6 +240,43 @@ Win32kThreadCallback (struct _ETHREAD *Thread,
|
|||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* Only used in ntuser/input.c KeyboardThreadMain(). If it's
|
||||
not called there anymore, please delete */
|
||||
NTSTATUS
|
||||
Win32kInitWin32Thread(PETHREAD Thread)
|
||||
{
|
||||
PEPROCESS Process;
|
||||
|
||||
Process = Thread->ThreadsProcess;
|
||||
|
||||
if (Process->Win32Process == NULL)
|
||||
{
|
||||
/* FIXME - lock the process */
|
||||
Process->Win32Process = ExAllocatePool(NonPagedPool, sizeof(W32PROCESS));
|
||||
|
||||
if (Process->Win32Process == NULL)
|
||||
return STATUS_NO_MEMORY;
|
||||
|
||||
RtlZeroMemory(Process->Win32Process, sizeof(W32PROCESS));
|
||||
/* FIXME - unlock the process */
|
||||
|
||||
Win32kProcessCallback(Process, TRUE);
|
||||
}
|
||||
|
||||
if (Thread->Tcb.Win32Thread == NULL)
|
||||
{
|
||||
Thread->Tcb.Win32Thread = ExAllocatePool (NonPagedPool, sizeof(W32THREAD));
|
||||
if (Thread->Tcb.Win32Thread == NULL)
|
||||
return STATUS_NO_MEMORY;
|
||||
|
||||
RtlZeroMemory(Thread->Tcb.Win32Thread, sizeof(W32THREAD));
|
||||
|
||||
Win32kThreadCallback(Thread, TRUE);
|
||||
}
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This definition doesn't work
|
||||
|
|
|
@ -293,6 +293,9 @@ IntCallHookProc(INT HookId,
|
|||
return 0;
|
||||
}
|
||||
break;
|
||||
case WH_KEYBOARD_LL:
|
||||
ArgumentLength += sizeof(KBDLLHOOKSTRUCT);
|
||||
break;
|
||||
default:
|
||||
DPRINT1("Trying to call unsupported window hook %d\n", HookId);
|
||||
return 0;
|
||||
|
@ -343,6 +346,10 @@ IntCallHookProc(INT HookId,
|
|||
break;
|
||||
}
|
||||
break;
|
||||
case WH_KEYBOARD_LL:
|
||||
RtlCopyMemory(Extra, (PVOID) lParam, sizeof(KBDLLHOOKSTRUCT));
|
||||
Common->lParam = (LPARAM) (Extra - (PCHAR) Common);
|
||||
break;
|
||||
}
|
||||
|
||||
ResultPointer = &Result;
|
||||
|
|
|
@ -182,8 +182,10 @@ IntFreeHook(PHOOKTABLE Table, PHOOK Hook, PWINSTATION_OBJECT WinStaObj)
|
|||
RtlFreeUnicodeString(&Hook->ModuleName);
|
||||
|
||||
/* Dereference thread if required */
|
||||
if(Hook->Flags & HOOK_THREAD_REFERENCED)
|
||||
if (Hook->Flags & HOOK_THREAD_REFERENCED)
|
||||
{
|
||||
ObDereferenceObject(Hook->Thread);
|
||||
}
|
||||
|
||||
/* Close handle */
|
||||
ObmCloseHandle(WinStaObj->HandleTable, Hook->Self);
|
||||
|
@ -191,7 +193,7 @@ IntFreeHook(PHOOKTABLE Table, PHOOK Hook, PWINSTATION_OBJECT WinStaObj)
|
|||
|
||||
/* remove a hook, freeing it if the chain is not in use */
|
||||
STATIC FASTCALL VOID
|
||||
IntRemoveHook(PHOOK Hook, PWINSTATION_OBJECT WinStaObj)
|
||||
IntRemoveHook(PHOOK Hook, PWINSTATION_OBJECT WinStaObj, BOOL TableAlreadyLocked)
|
||||
{
|
||||
PHOOKTABLE Table = IntGetTable(Hook);
|
||||
|
||||
|
@ -201,7 +203,10 @@ IntRemoveHook(PHOOK Hook, PWINSTATION_OBJECT WinStaObj)
|
|||
return;
|
||||
}
|
||||
|
||||
if (! TableAlreadyLocked)
|
||||
{
|
||||
IntLockHookTable(Table);
|
||||
}
|
||||
if (0 != Table->Counts[HOOKID_TO_INDEX(Hook->HookId)])
|
||||
{
|
||||
Hook->Proc = NULL; /* chain is in use, just mark it and return */
|
||||
|
@ -210,7 +215,10 @@ IntRemoveHook(PHOOK Hook, PWINSTATION_OBJECT WinStaObj)
|
|||
{
|
||||
IntFreeHook(Table, Hook, WinStaObj);
|
||||
}
|
||||
if (! TableAlreadyLocked)
|
||||
{
|
||||
IntUnLockHookTable(Table);
|
||||
}
|
||||
}
|
||||
|
||||
/* release a hook chain, removing deleted hooks if the use count drops to 0 */
|
||||
|
@ -249,17 +257,42 @@ IntReleaseHookChain(PHOOKTABLE Table, int HookId, PWINSTATION_OBJECT WinStaObj)
|
|||
IntUnLockHookTable(Table);
|
||||
}
|
||||
|
||||
static LRESULT FASTCALL
|
||||
IntCallLowLevelHook(INT HookId, INT Code, WPARAM wParam, LPARAM lParam, PHOOK Hook)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
ULONG_PTR uResult;
|
||||
|
||||
/* FIXME should get timeout from
|
||||
* HKEY_CURRENT_USER\Control Panel\Desktop\LowLevelHooksTimeout */
|
||||
Status = MsqSendMessage(Hook->Thread->Tcb.Win32Thread->MessageQueue, (HWND) Code, HookId,
|
||||
wParam, lParam, /*500*/0, TRUE, TRUE, &uResult);
|
||||
|
||||
return NT_SUCCESS(Status) ? uResult : 0;
|
||||
}
|
||||
|
||||
LRESULT FASTCALL
|
||||
HOOK_CallHooks(INT HookId, INT Code, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
PHOOK Hook;
|
||||
PHOOKTABLE Table = MsqGetHooks(PsGetWin32Thread()->MessageQueue);
|
||||
PW32THREAD Win32Thread;
|
||||
PHOOKTABLE Table;
|
||||
LRESULT Result;
|
||||
PWINSTATION_OBJECT WinStaObj;
|
||||
NTSTATUS Status;
|
||||
|
||||
ASSERT(WH_MINHOOK <= HookId && HookId <= WH_MAXHOOK);
|
||||
|
||||
Win32Thread = PsGetWin32Thread();
|
||||
if (NULL == Win32Thread)
|
||||
{
|
||||
Table = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
Table = MsqGetHooks(Win32Thread->MessageQueue);
|
||||
}
|
||||
|
||||
if (NULL == Table || ! (Hook = IntGetFirstValidHook(Table, HookId)))
|
||||
{
|
||||
/* try global table */
|
||||
|
@ -270,6 +303,13 @@ HOOK_CallHooks(INT HookId, INT Code, WPARAM wParam, LPARAM lParam)
|
|||
}
|
||||
}
|
||||
|
||||
if (Hook->Thread != PsGetCurrentThread()
|
||||
&& (WH_KEYBOARD_LL == HookId || WH_MOUSE_LL == HookId))
|
||||
{
|
||||
DPRINT("Calling hook in owning thread\n");
|
||||
return IntCallLowLevelHook(HookId, Code, wParam, lParam, Hook);
|
||||
}
|
||||
|
||||
if (Hook->Thread != PsGetCurrentThread())
|
||||
{
|
||||
DPRINT1("Calling hooks in other threads not implemented yet");
|
||||
|
@ -294,7 +334,7 @@ HOOK_CallHooks(INT HookId, INT Code, WPARAM wParam, LPARAM lParam)
|
|||
0,
|
||||
&WinStaObj);
|
||||
|
||||
if(! NT_SUCCESS(Status))
|
||||
if (! NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Invalid window station????\n");
|
||||
}
|
||||
|
@ -324,7 +364,7 @@ HOOK_DestroyThreadHooks(PETHREAD Thread)
|
|||
0,
|
||||
&WinStaObj);
|
||||
|
||||
if(! NT_SUCCESS(Status))
|
||||
if (! NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Invalid window station????\n");
|
||||
return;
|
||||
|
@ -344,7 +384,7 @@ HOOK_DestroyThreadHooks(PETHREAD Thread)
|
|||
Elem = Elem->Flink;
|
||||
if (HookObj->Thread == Thread)
|
||||
{
|
||||
IntRemoveHook(HookObj, WinStaObj);
|
||||
IntRemoveHook(HookObj, WinStaObj, TRUE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -372,7 +412,7 @@ NtUserCallNextHookEx(
|
|||
0,
|
||||
&WinStaObj);
|
||||
|
||||
if(! NT_SUCCESS(Status))
|
||||
if (! NT_SUCCESS(Status))
|
||||
{
|
||||
SetLastNtError(Status);
|
||||
return FALSE;
|
||||
|
@ -433,7 +473,7 @@ NtUserSetWindowsHookEx(
|
|||
BOOL Ansi)
|
||||
{
|
||||
PWINSTATION_OBJECT WinStaObj;
|
||||
BOOLEAN Global, ReleaseThread;
|
||||
BOOLEAN Global;
|
||||
PETHREAD Thread;
|
||||
PHOOK Hook;
|
||||
UNICODE_STRING ModuleName;
|
||||
|
@ -473,15 +513,23 @@ NtUserSetWindowsHookEx(
|
|||
SetLastWin32Error(ERROR_INVALID_PARAMETER);
|
||||
return NULL;
|
||||
}
|
||||
ReleaseThread = TRUE;
|
||||
}
|
||||
else /* system-global hook */
|
||||
{
|
||||
ReleaseThread = FALSE;
|
||||
if (HookId == WH_KEYBOARD_LL || HookId == WH_MOUSE_LL)
|
||||
{
|
||||
Mod = NULL;
|
||||
Thread = PsGetCurrentThread();
|
||||
Status = ObReferenceObjectByPointer(Thread,
|
||||
THREAD_ALL_ACCESS,
|
||||
PsThreadType,
|
||||
KernelMode);
|
||||
|
||||
if (! NT_SUCCESS(Status))
|
||||
{
|
||||
SetLastNtError(Status);
|
||||
return (HANDLE) NULL;
|
||||
}
|
||||
}
|
||||
else if (NULL == Mod)
|
||||
{
|
||||
|
@ -495,16 +543,20 @@ NtUserSetWindowsHookEx(
|
|||
Global = TRUE;
|
||||
}
|
||||
|
||||
/* We only (partially) support local WH_CBT hooks for now */
|
||||
if (WH_CBT != HookId || Global)
|
||||
/* We only (partially) support local WH_CBT hooks and
|
||||
* WH_KEYBOARD_LL/WH_MOUSE_LL hooks for now */
|
||||
if ((WH_CBT != HookId || Global)
|
||||
&& WH_KEYBOARD_LL != HookId && WH_MOUSE_LL != HookId)
|
||||
{
|
||||
#if 0 /* Removed to get winEmbed working again */
|
||||
UNIMPLEMENTED
|
||||
#else
|
||||
DPRINT1("Not implemented: HookId %d Global %s\n", HookId, Global ? "TRUE" : "FALSE");
|
||||
#endif
|
||||
if(ReleaseThread)
|
||||
if (NULL != Thread)
|
||||
{
|
||||
ObDereferenceObject(Thread);
|
||||
}
|
||||
SetLastWin32Error(ERROR_NOT_SUPPORTED);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -514,10 +566,12 @@ NtUserSetWindowsHookEx(
|
|||
0,
|
||||
&WinStaObj);
|
||||
|
||||
if(! NT_SUCCESS(Status))
|
||||
if (! NT_SUCCESS(Status))
|
||||
{
|
||||
if (NULL != Thread)
|
||||
{
|
||||
if(ReleaseThread && Thread)
|
||||
ObDereferenceObject(Thread);
|
||||
}
|
||||
SetLastNtError(Status);
|
||||
return (HANDLE) NULL;
|
||||
}
|
||||
|
@ -525,14 +579,18 @@ NtUserSetWindowsHookEx(
|
|||
Hook = IntAddHook(Thread, HookId, Global, WinStaObj);
|
||||
if (NULL == Hook)
|
||||
{
|
||||
if(ReleaseThread)
|
||||
if (NULL != Thread)
|
||||
{
|
||||
ObDereferenceObject(Thread);
|
||||
}
|
||||
ObDereferenceObject(WinStaObj);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(ReleaseThread)
|
||||
if (NULL != Thread)
|
||||
{
|
||||
Hook->Flags |= HOOK_THREAD_REFERENCED;
|
||||
}
|
||||
|
||||
if (NULL != Mod)
|
||||
{
|
||||
|
@ -540,9 +598,11 @@ NtUserSetWindowsHookEx(
|
|||
if (! NT_SUCCESS(Status))
|
||||
{
|
||||
ObmDereferenceObject(Hook);
|
||||
IntRemoveHook(Hook, WinStaObj);
|
||||
if(ReleaseThread)
|
||||
IntRemoveHook(Hook, WinStaObj, FALSE);
|
||||
if (NULL != Thread)
|
||||
{
|
||||
ObDereferenceObject(Thread);
|
||||
}
|
||||
ObDereferenceObject(WinStaObj);
|
||||
SetLastNtError(Status);
|
||||
return NULL;
|
||||
|
@ -553,9 +613,11 @@ NtUserSetWindowsHookEx(
|
|||
if (NULL == Hook->ModuleName.Buffer)
|
||||
{
|
||||
ObmDereferenceObject(Hook);
|
||||
IntRemoveHook(Hook, WinStaObj);
|
||||
if(ReleaseThread)
|
||||
IntRemoveHook(Hook, WinStaObj, FALSE);
|
||||
if (NULL != Thread)
|
||||
{
|
||||
ObDereferenceObject(Thread);
|
||||
}
|
||||
ObDereferenceObject(WinStaObj);
|
||||
SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
|
||||
return NULL;
|
||||
|
@ -567,9 +629,11 @@ NtUserSetWindowsHookEx(
|
|||
if (! NT_SUCCESS(Status))
|
||||
{
|
||||
ObmDereferenceObject(Hook);
|
||||
IntRemoveHook(Hook, WinStaObj);
|
||||
if(ReleaseThread)
|
||||
IntRemoveHook(Hook, WinStaObj, FALSE);
|
||||
if (NULL != Thread)
|
||||
{
|
||||
ObDereferenceObject(Thread);
|
||||
}
|
||||
ObDereferenceObject(WinStaObj);
|
||||
SetLastNtError(Status);
|
||||
return NULL;
|
||||
|
@ -618,7 +682,7 @@ NtUserUnhookWindowsHookEx(
|
|||
0,
|
||||
&WinStaObj);
|
||||
|
||||
if(! NT_SUCCESS(Status))
|
||||
if (! NT_SUCCESS(Status))
|
||||
{
|
||||
SetLastNtError(Status);
|
||||
return FALSE;
|
||||
|
@ -635,7 +699,7 @@ NtUserUnhookWindowsHookEx(
|
|||
}
|
||||
ASSERT(Hook == HookObj->Self);
|
||||
|
||||
IntRemoveHook(HookObj, WinStaObj);
|
||||
IntRemoveHook(HookObj, WinStaObj, FALSE);
|
||||
|
||||
ObmDereferenceObject(HookObj);
|
||||
ObDereferenceObject(WinStaObj);
|
||||
|
|
|
@ -184,7 +184,7 @@ MouseThreadMain(PVOID StartContext)
|
|||
DPRINT("Mouse Input Thread Starting...\n");
|
||||
|
||||
/*
|
||||
* Receive and process keyboard input.
|
||||
* Receive and process mouse input.
|
||||
*/
|
||||
while(InputThreadsRunning)
|
||||
{
|
||||
|
@ -409,6 +409,8 @@ KeyboardThreadMain(PVOID StartContext)
|
|||
MSG msg;
|
||||
PUSER_MESSAGE_QUEUE FocusQueue;
|
||||
struct _ETHREAD *FocusThread;
|
||||
extern NTSTATUS Win32kInitWin32Thread(PETHREAD Thread);
|
||||
|
||||
|
||||
PKEYBOARD_INDICATOR_TRANSLATION IndicatorTrans = NULL;
|
||||
UINT ModifierState = 0;
|
||||
|
@ -434,6 +436,22 @@ KeyboardThreadMain(PVOID StartContext)
|
|||
return; //(Status);
|
||||
}
|
||||
|
||||
/* Not sure if converting this thread to a win32 thread is such
|
||||
a great idea. Since we're posting keyboard messages to the focus
|
||||
window message queue, we'll be (indirectly) doing sendmessage
|
||||
stuff from this thread (for WH_KEYBOARD_LL processing), which
|
||||
means we need our own message queue. If keyboard messages were
|
||||
instead queued to the system message queue, the thread removing
|
||||
the message from the system message queue would be responsible
|
||||
for WH_KEYBOARD_LL processing and we wouldn't need this thread
|
||||
to be a win32 thread. */
|
||||
Status = Win32kInitWin32Thread(PsGetCurrentThread());
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Win32K: Failed making keyboard thread a win32 thread.\n");
|
||||
return; //(Status);
|
||||
}
|
||||
|
||||
IntKeyboardGetIndicatorTrans(KeyboardDeviceHandle,
|
||||
&IndicatorTrans);
|
||||
|
||||
|
|
|
@ -1332,7 +1332,7 @@ IntSendMessageTimeoutSingle(HWND hWnd,
|
|||
}
|
||||
|
||||
Status = MsqSendMessage(Window->MessageQueue, hWnd, Msg, wParam, lParam,
|
||||
uTimeout, (uFlags & SMTO_BLOCK), uResult);
|
||||
uTimeout, (uFlags & SMTO_BLOCK), FALSE, uResult);
|
||||
IntReleaseWindowObject(Window);
|
||||
if (STATUS_TIMEOUT == Status)
|
||||
{
|
||||
|
|
|
@ -618,6 +618,7 @@ MsqPostKeyboardMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|||
PUSER_MESSAGE_QUEUE FocusMessageQueue;
|
||||
MSG Msg;
|
||||
LARGE_INTEGER LargeTickCount;
|
||||
KBDLLHOOKSTRUCT KbdHookData;
|
||||
|
||||
DPRINT("MsqPostKeyboardMessage(uMsg 0x%x, wParam 0x%x, lParam 0x%x)\n",
|
||||
uMsg, wParam, lParam);
|
||||
|
@ -632,6 +633,20 @@ MsqPostKeyboardMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|||
/* We can't get the Msg.pt point here since we don't know thread
|
||||
(and thus the window station) the message will end up in yet. */
|
||||
|
||||
KbdHookData.vkCode = Msg.wParam;
|
||||
KbdHookData.scanCode = (Msg.lParam >> 16) & 0xff;
|
||||
KbdHookData.flags = (0 == (Msg.lParam & 0x01000000) ? 0 : LLKHF_EXTENDED) |
|
||||
(0 == (Msg.lParam & 0x20000000) ? 0 : LLKHF_ALTDOWN) |
|
||||
(0 == (Msg.lParam & 0x80000000) ? 0 : LLKHF_UP);
|
||||
KbdHookData.time = Msg.time;
|
||||
KbdHookData.dwExtraInfo = 0;
|
||||
if (HOOK_CallHooks(WH_KEYBOARD_LL, HC_ACTION, Msg.message, (LPARAM) &KbdHookData))
|
||||
{
|
||||
DPRINT("Kbd msg %d wParam %d lParam 0x%08x dropped by WH_KEYBOARD_LL hook\n",
|
||||
Msg.message, Msg.wParam, Msg.lParam);
|
||||
return;
|
||||
}
|
||||
|
||||
FocusMessageQueue = IntGetFocusMessageQueue();
|
||||
if( !IntGetScreenDC() ) {
|
||||
/* FIXME: What to do about Msg.pt here? */
|
||||
|
@ -793,11 +808,21 @@ MsqDispatchOneSentMessage(PUSER_MESSAGE_QUEUE MessageQueue)
|
|||
|
||||
IntUnLockMessageQueue(MessageQueue);
|
||||
|
||||
if (Message->HookMessage)
|
||||
{
|
||||
Result = HOOK_CallHooks(Message->Msg.message,
|
||||
(INT) Message->Msg.hwnd,
|
||||
Message->Msg.wParam,
|
||||
Message->Msg.lParam);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Call the window procedure. */
|
||||
Result = IntSendMessage(Message->Msg.hwnd,
|
||||
Message->Msg.message,
|
||||
Message->Msg.wParam,
|
||||
Message->Msg.lParam);
|
||||
}
|
||||
|
||||
/* remove the message from the local dispatching list, because it doesn't need
|
||||
to be cleaned up on thread termination anymore */
|
||||
|
@ -957,7 +982,8 @@ MsqSendNotifyMessage(PUSER_MESSAGE_QUEUE MessageQueue,
|
|||
NTSTATUS FASTCALL
|
||||
MsqSendMessage(PUSER_MESSAGE_QUEUE MessageQueue,
|
||||
HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam,
|
||||
UINT uTimeout, BOOL Block, ULONG_PTR *uResult)
|
||||
UINT uTimeout, BOOL Block, BOOL HookMessage,
|
||||
ULONG_PTR *uResult)
|
||||
{
|
||||
PUSER_SENT_MESSAGE Message;
|
||||
KEVENT CompletionEvent;
|
||||
|
@ -992,6 +1018,7 @@ MsqSendMessage(PUSER_MESSAGE_QUEUE MessageQueue,
|
|||
Message->SenderQueue = ThreadQueue;
|
||||
IntReferenceMessageQueue(ThreadQueue);
|
||||
Message->CompletionCallback = NULL;
|
||||
Message->HookMessage = HookMessage;
|
||||
|
||||
IntReferenceMessageQueue(MessageQueue);
|
||||
|
||||
|
|
|
@ -2147,7 +2147,10 @@ extern "C" {
|
|||
#define MOD_ON_KEYUP 2048
|
||||
#define MOD_RIGHT 16384
|
||||
#define MOD_LEFT 32768
|
||||
#define LLKHF_EXTENDED 0x00000001
|
||||
#define LLKHF_INJECTED 0x00000010
|
||||
#define LLKHF_ALTDOWN 0x00000020
|
||||
#define LLKHF_UP 0x00000080
|
||||
#if (WINVER >= 0x0500)
|
||||
#define FLASHW_STOP 0
|
||||
#define FLASHW_CAPTION 1
|
||||
|
|
Loading…
Reference in a new issue