📄 message.c
字号:
if(uResult)
{
*uResult = Result;
}
if (! NT_SUCCESS(UnpackParam(lParamPacked, Msg, wParam, lParam)))
{
DPRINT1("Failed to unpack message parameters\n");
RETURN( TRUE);
}
RETURN( TRUE);
}
if(uFlags & SMTO_ABORTIFHUNG && MsqIsHung(Window->MessageQueue))
{
/* FIXME - Set a LastError? */
RETURN( FALSE);
}
if(Window->Status & WINDOWSTATUS_DESTROYING)
{
/* FIXME - last error? */
DPRINT1("Attempted to send message to window 0x%x that is being destroyed!\n", hWnd);
RETURN( FALSE);
}
Status = co_MsqSendMessage(Window->MessageQueue, hWnd, Msg, wParam, lParam,
uTimeout, (uFlags & SMTO_BLOCK), FALSE, uResult);
if (STATUS_TIMEOUT == Status)
{
/* MSDN says GetLastError() should return 0 after timeout */
SetLastWin32Error(0);
RETURN( FALSE);
}
else if (! NT_SUCCESS(Status))
{
SetLastNtError(Status);
RETURN( FALSE);
}
RETURN( TRUE);
CLEANUP:
if (Window) UserDerefObjectCo(Window);
END_CLEANUP;
}
LRESULT FASTCALL
co_IntSendMessageTimeout(HWND hWnd,
UINT Msg,
WPARAM wParam,
LPARAM lParam,
UINT uFlags,
UINT uTimeout,
ULONG_PTR *uResult)
{
PWINDOW_OBJECT DesktopWindow;
HWND *Children;
HWND *Child;
if (HWND_BROADCAST != hWnd)
{
return co_IntSendMessageTimeoutSingle(hWnd, Msg, wParam, lParam, uFlags, uTimeout, uResult);
}
DesktopWindow = UserGetWindowObject(IntGetDesktopWindow());
if (NULL == DesktopWindow)
{
SetLastWin32Error(ERROR_INTERNAL_ERROR);
return 0;
}
Children = IntWinListChildren(DesktopWindow);
if (NULL == Children)
{
return 0;
}
for (Child = Children; NULL != *Child; Child++)
{
co_IntSendMessageTimeoutSingle(*Child, Msg, wParam, lParam, uFlags, uTimeout, uResult);
}
ExFreePool(Children);
return (LRESULT) TRUE;
}
/* This function posts a message if the destination's message queue belongs to
another thread, otherwise it sends the message. It does not support broadcast
messages! */
LRESULT FASTCALL
co_IntPostOrSendMessage(HWND hWnd,
UINT Msg,
WPARAM wParam,
LPARAM lParam)
{
ULONG_PTR Result;
PWINDOW_OBJECT Window;
if(hWnd == HWND_BROADCAST)
{
return 0;
}
if(!(Window = UserGetWindowObject(hWnd)))
{
return 0;
}
if(Window->MessageQueue != PsGetCurrentThreadWin32Thread()->MessageQueue)
{
Result = UserPostMessage(hWnd, Msg, wParam, lParam);
}
else
{
if(!co_IntSendMessageTimeoutSingle(hWnd, Msg, wParam, lParam, SMTO_NORMAL, 0, &Result))
{
Result = 0;
}
}
return (LRESULT)Result;
}
LRESULT FASTCALL
co_IntDoSendMessage(HWND hWnd,
UINT Msg,
WPARAM wParam,
LPARAM lParam,
PDOSENDMESSAGE dsm,
PNTUSERSENDMESSAGEINFO UnsafeInfo)
{
LRESULT Result = TRUE;
NTSTATUS Status;
PWINDOW_OBJECT Window;
NTUSERSENDMESSAGEINFO Info;
MSG UserModeMsg;
MSG KernelModeMsg;
PMSGMEMORY MsgMemoryEntry;
RtlZeroMemory(&Info, sizeof(NTUSERSENDMESSAGEINFO));
/* FIXME: Call hooks. */
if (HWND_BROADCAST != hWnd)
{
Window = UserGetWindowObject(hWnd);
if (NULL == Window)
{
/* Tell usermode to not touch this one */
Info.HandledByKernel = TRUE;
MmCopyToCaller(UnsafeInfo, &Info, sizeof(NTUSERSENDMESSAGEINFO));
return 0;
}
}
/* FIXME: Check for an exiting window. */
/* See if the current thread can handle the message */
if (HWND_BROADCAST != hWnd && NULL != PsGetCurrentThreadWin32Thread() &&
Window->MessageQueue == PsGetCurrentThreadWin32Thread()->MessageQueue)
{
/* Gather the information usermode needs to call the window proc directly */
Info.HandledByKernel = FALSE;
Status = MmCopyFromCaller(&(Info.Ansi), &(UnsafeInfo->Ansi),
sizeof(BOOL));
if (! NT_SUCCESS(Status))
{
Info.Ansi = ! Window->Unicode;
}
if (Window->IsSystem)
{
Info.Proc = (!Info.Ansi ? Window->WndProc : Window->WndProcExtra);
}
else
{
Info.Ansi = !Window->Unicode;
Info.Proc = Window->WndProc;
}
}
else
{
/* Must be handled by other thread */
// if (HWND_BROADCAST != hWnd)
// {
// UserDerefObject(Window);
// }
Info.HandledByKernel = TRUE;
UserModeMsg.hwnd = hWnd;
UserModeMsg.message = Msg;
UserModeMsg.wParam = wParam;
UserModeMsg.lParam = lParam;
MsgMemoryEntry = FindMsgMemory(UserModeMsg.message);
Status = CopyMsgToKernelMem(&KernelModeMsg, &UserModeMsg, MsgMemoryEntry);
if (! NT_SUCCESS(Status))
{
MmCopyToCaller(UnsafeInfo, &Info, sizeof(NTUSERSENDMESSAGEINFO));
SetLastWin32Error(ERROR_INVALID_PARAMETER);
return (dsm ? 0 : -1);
}
if(!dsm)
{
Result = co_IntSendMessage(KernelModeMsg.hwnd, KernelModeMsg.message,
KernelModeMsg.wParam, KernelModeMsg.lParam);
}
else
{
Result = co_IntSendMessageTimeout(KernelModeMsg.hwnd, KernelModeMsg.message,
KernelModeMsg.wParam, KernelModeMsg.lParam,
dsm->uFlags, dsm->uTimeout, &dsm->Result);
}
Status = CopyMsgToUserMem(&UserModeMsg, &KernelModeMsg);
if (! NT_SUCCESS(Status))
{
MmCopyToCaller(UnsafeInfo, &Info, sizeof(NTUSERSENDMESSAGEINFO));
SetLastWin32Error(ERROR_INVALID_PARAMETER);
return(dsm ? 0 : -1);
}
}
Status = MmCopyToCaller(UnsafeInfo, &Info, sizeof(NTUSERSENDMESSAGEINFO));
if (! NT_SUCCESS(Status))
{
SetLastWin32Error(ERROR_INVALID_PARAMETER);
}
return (LRESULT)Result;
}
LRESULT STDCALL
NtUserSendMessageTimeout(HWND hWnd,
UINT Msg,
WPARAM wParam,
LPARAM lParam,
UINT uFlags,
UINT uTimeout,
ULONG_PTR *uResult,
PNTUSERSENDMESSAGEINFO UnsafeInfo)
{
DOSENDMESSAGE dsm;
LRESULT Result;
DECLARE_RETURN(BOOL);
DPRINT("Enter NtUserSendMessageTimeout\n");
UserEnterExclusive();
dsm.uFlags = uFlags;
dsm.uTimeout = uTimeout;
Result = co_IntDoSendMessage(hWnd, Msg, wParam, lParam, &dsm, UnsafeInfo);
if(uResult != NULL && Result != 0)
{
NTSTATUS Status;
Status = MmCopyToCaller(uResult, &dsm.Result, sizeof(ULONG_PTR));
if(!NT_SUCCESS(Status))
{
SetLastWin32Error(ERROR_INVALID_PARAMETER);
RETURN( FALSE);
}
}
RETURN( Result);
CLEANUP:
DPRINT("Leave NtUserSendMessageTimeout, ret=%i\n",_ret_);
UserLeave();
END_CLEANUP;
}
LRESULT STDCALL
NtUserSendMessage(HWND Wnd,
UINT Msg,
WPARAM wParam,
LPARAM lParam,
PNTUSERSENDMESSAGEINFO UnsafeInfo)
{
DECLARE_RETURN(BOOL);
DPRINT("Enter NtUserSendMessage\n");
UserEnterExclusive();
RETURN(co_IntDoSendMessage(Wnd, Msg, wParam, lParam, NULL, UnsafeInfo));
CLEANUP:
DPRINT("Leave NtUserSendMessage, ret=%i\n",_ret_);
UserLeave();
END_CLEANUP;
}
BOOL STDCALL
NtUserSendMessageCallback(HWND hWnd,
UINT Msg,
WPARAM wParam,
LPARAM lParam,
SENDASYNCPROC lpCallBack,
ULONG_PTR dwData)
{
UNIMPLEMENTED;
return 0;
}
BOOL FASTCALL
UserSendNotifyMessage(HWND hWnd,
UINT Msg,
WPARAM wParam,
LPARAM lParam)
{
BOOL Result = TRUE;
// Basicly the same as IntPostOrSendMessage
if (hWnd == HWND_BROADCAST) //Handle Broadcast
{
HWND *List;
PWINDOW_OBJECT DesktopWindow;
ULONG i;
DesktopWindow = UserGetWindowObject(IntGetDesktopWindow());
List = IntWinListChildren(DesktopWindow);
if (List != NULL)
{
for (i = 0; List[i]; i++)
{
UserSendNotifyMessage(List[i], Msg, wParam, lParam);
}
ExFreePool(List);
}
}
else
{
ULONG_PTR PResult;
PWINDOW_OBJECT Window;
NTSTATUS Status;
MSG UserModeMsg;
MSG KernelModeMsg;
PMSGMEMORY MsgMemoryEntry;
if(!(Window = UserGetWindowObject(hWnd))) return FALSE;
if(Window->MessageQueue != PsGetCurrentThreadWin32Thread()->MessageQueue)
{ // Send message w/o waiting for it.
Result = UserPostMessage(hWnd, Msg, wParam, lParam);
}
else
{ // Handle message and callback.
UserModeMsg.hwnd = hWnd;
UserModeMsg.message = Msg;
UserModeMsg.wParam = wParam;
UserModeMsg.lParam = lParam;
MsgMemoryEntry = FindMsgMemory(UserModeMsg.message);
Status = CopyMsgToKernelMem(&KernelModeMsg, &UserModeMsg, MsgMemoryEntry);
if (! NT_SUCCESS(Status))
{
SetLastWin32Error(ERROR_INVALID_PARAMETER);
return FALSE;
}
Result = co_IntSendMessageTimeoutSingle(
KernelModeMsg.hwnd, KernelModeMsg.message,
KernelModeMsg.wParam, KernelModeMsg.lParam,
SMTO_NORMAL, 0, &PResult);
Status = CopyMsgToUserMem(&UserModeMsg, &KernelModeMsg);
if (! NT_SUCCESS(Status))
{
SetLastWin32Error(ERROR_INVALID_PARAMETER);
return FALSE;
}
}
}
return Result;
}
BOOL STDCALL
NtUserSendNotifyMessage(HWND hWnd,
UINT Msg,
WPARAM wParam,
LPARAM lParam)
{
DECLARE_RETURN(BOOL);
DPRINT("EnterNtUserSendNotifyMessage\n");
UserEnterExclusive();
RETURN(UserSendNotifyMessage(hWnd, Msg, wParam, lParam));
CLEANUP:
DPRINT("Leave NtUserSendNotifyMessage, ret=%i\n",_ret_);
UserLeave();
END_CLEANUP;
}
BOOL STDCALL
NtUserWaitMessage(VOID)
{
DECLARE_RETURN(BOOL);
DPRINT("EnterNtUserWaitMessage\n");
UserEnterExclusive();
RETURN(co_IntWaitMessage(NULL, 0, 0));
CLEANUP:
DPRINT("Leave NtUserWaitMessage, ret=%i\n",_ret_);
UserLeave();
END_CLEANUP;
}
DWORD STDCALL
NtUserGetQueueStatus(BOOL ClearChanges)
{
PUSER_MESSAGE_QUEUE Queue;
DWORD Result;
DECLARE_RETURN(DWORD);
DPRINT("Enter NtUserGetQueueStatus\n");
UserEnterExclusive();
Queue = PsGetCurrentThreadWin32Thread()->MessageQueue;
Result = MAKELONG(Queue->QueueBits, Queue->ChangedBits);
if (ClearChanges)
{
Queue->ChangedBits = 0;
}
RETURN( Result);
CLEANUP:
DPRINT("Leave NtUserGetQueueStatus, ret=%i\n",_ret_);
UserLeave();
END_CLEANUP;
}
BOOL STDCALL
IntInitMessagePumpHook()
{
((PW32THREAD)PsGetCurrentThread()->Tcb.Win32Thread)->MessagePumpHookValue++;
return TRUE;
}
BOOL STDCALL
IntUninitMessagePumpHook()
{
if (((PW32THREAD)PsGetCurrentThread()->Tcb.Win32Thread)->MessagePumpHookValue <= 0)
{
return FALSE;
}
((PW32THREAD)PsGetCurrentThread()->Tcb.Win32Thread)->MessagePumpHookValue--;
return TRUE;
}
/* EOF */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -