📄 message.c
字号:
return TRUE;
}
/* Nothing found. Wait for new messages. */
Status = co_MsqWaitForNewMessages(ThreadQueue, Wnd, MsgFilterMin, MsgFilterMax);
}
while ((STATUS_WAIT_0 <= Status && Status <= STATUS_WAIT_63) || STATUS_TIMEOUT == Status);
SetLastNtError(Status);
return FALSE;
}
BOOL STDCALL
NtUserGetMessage(PNTUSERGETMESSAGEINFO UnsafeInfo,
HWND hWnd,
UINT MsgFilterMin,
UINT MsgFilterMax)
/*
* FUNCTION: Get a message from the calling thread's message queue.
* ARGUMENTS:
* UnsafeMsg - Pointer to the structure which receives the returned message.
* Wnd - Window whose messages are to be retrieved.
* MsgFilterMin - Integer value of the lowest message value to be
* retrieved.
* MsgFilterMax - Integer value of the highest message value to be
* retrieved.
*/
{
BOOL GotMessage;
NTUSERGETMESSAGEINFO Info;
NTSTATUS Status;
PWINDOW_OBJECT Window = NULL;
PMSGMEMORY MsgMemoryEntry;
PVOID UserMem;
UINT Size;
USER_MESSAGE Msg;
DECLARE_RETURN(BOOL);
// USER_REFERENCE_ENTRY Ref;
DPRINT("Enter NtUserGetMessage\n");
UserEnterExclusive();
/* Validate input */
if (hWnd && !(Window = UserGetWindowObject(hWnd)))
{
RETURN(-1);
}
// if (Window) UserRefObjectCo(Window, &Ref);
if (MsgFilterMax < MsgFilterMin)
{
MsgFilterMin = 0;
MsgFilterMax = 0;
}
do
{
GotMessage = co_IntPeekMessage(&Msg, hWnd, MsgFilterMin, MsgFilterMax, PM_REMOVE);
if (GotMessage)
{
Info.Msg = Msg.Msg;
/* See if this message type is present in the table */
MsgMemoryEntry = FindMsgMemory(Info.Msg.message);
if (NULL == MsgMemoryEntry)
{
/* Not present, no copying needed */
Info.LParamSize = 0;
}
else
{
/* Determine required size */
Size = MsgMemorySize(MsgMemoryEntry, Info.Msg.wParam,
Info.Msg.lParam);
/* Allocate required amount of user-mode memory */
Info.LParamSize = Size;
UserMem = NULL;
Status = ZwAllocateVirtualMemory(NtCurrentProcess(), &UserMem, 0,
&Info.LParamSize, MEM_COMMIT, PAGE_READWRITE);
if (! NT_SUCCESS(Status))
{
SetLastNtError(Status);
RETURN( (BOOL) -1);
}
/* Transfer lParam data to user-mode mem */
Status = MmCopyToCaller(UserMem, (PVOID) Info.Msg.lParam, Size);
if (! NT_SUCCESS(Status))
{
ZwFreeVirtualMemory(NtCurrentProcess(), (PVOID *) &UserMem,
&Info.LParamSize, MEM_DECOMMIT);
SetLastNtError(Status);
RETURN( (BOOL) -1);
}
Info.Msg.lParam = (LPARAM) UserMem;
}
if (Msg.FreeLParam && 0 != Msg.Msg.lParam)
{
ExFreePool((void *) Msg.Msg.lParam);
}
Status = MmCopyToCaller(UnsafeInfo, &Info, sizeof(NTUSERGETMESSAGEINFO));
if (! NT_SUCCESS(Status))
{
SetLastNtError(Status);
RETURN( (BOOL) -1);
}
}
else if (! co_IntWaitMessage(hWnd, MsgFilterMin, MsgFilterMax))
{
RETURN( (BOOL) -1);
}
}
while (! GotMessage);
RETURN( WM_QUIT != Info.Msg.message);
CLEANUP:
// if (Window) UserDerefObjectCo(Window);
DPRINT("Leave NtUserGetMessage\n");
UserLeave();
END_CLEANUP;
}
DWORD
STDCALL
NtUserMessageCall(
DWORD Unknown0,
DWORD Unknown1,
DWORD Unknown2,
DWORD Unknown3,
DWORD Unknown4,
DWORD Unknown5,
DWORD Unknown6)
{
UNIMPLEMENTED
return 0;
}
static NTSTATUS FASTCALL
CopyMsgToKernelMem(MSG *KernelModeMsg, MSG *UserModeMsg, PMSGMEMORY MsgMemoryEntry)
{
NTSTATUS Status;
PVOID KernelMem;
UINT Size;
*KernelModeMsg = *UserModeMsg;
/* See if this message type is present in the table */
if (NULL == MsgMemoryEntry)
{
/* Not present, no copying needed */
return STATUS_SUCCESS;
}
/* Determine required size */
Size = MsgMemorySize(MsgMemoryEntry, UserModeMsg->wParam, UserModeMsg->lParam);
if (0 != Size)
{
/* Allocate kernel mem */
KernelMem = ExAllocatePoolWithTag(PagedPool, Size, TAG_MSG);
if (NULL == KernelMem)
{
DPRINT1("Not enough memory to copy message to kernel mem\n");
return STATUS_NO_MEMORY;
}
KernelModeMsg->lParam = (LPARAM) KernelMem;
/* Copy data if required */
if (0 != (MsgMemoryEntry->Flags & MMS_FLAG_READ))
{
Status = MmCopyFromCaller(KernelMem, (PVOID) UserModeMsg->lParam, Size);
if (! NT_SUCCESS(Status))
{
DPRINT1("Failed to copy message to kernel: invalid usermode buffer\n");
ExFreePool(KernelMem);
return Status;
}
}
else
{
/* Make sure we don't pass any secrets to usermode */
RtlZeroMemory(KernelMem, Size);
}
}
else
{
KernelModeMsg->lParam = 0;
}
return STATUS_SUCCESS;
}
static NTSTATUS FASTCALL
CopyMsgToUserMem(MSG *UserModeMsg, MSG *KernelModeMsg)
{
NTSTATUS Status;
PMSGMEMORY MsgMemoryEntry;
UINT Size;
/* See if this message type is present in the table */
MsgMemoryEntry = FindMsgMemory(UserModeMsg->message);
if (NULL == MsgMemoryEntry)
{
/* Not present, no copying needed */
return STATUS_SUCCESS;
}
/* Determine required size */
Size = MsgMemorySize(MsgMemoryEntry, UserModeMsg->wParam, UserModeMsg->lParam);
if (0 != Size)
{
/* Copy data if required */
if (0 != (MsgMemoryEntry->Flags & MMS_FLAG_WRITE))
{
Status = MmCopyToCaller((PVOID) UserModeMsg->lParam, (PVOID) KernelModeMsg->lParam, Size);
if (! NT_SUCCESS(Status))
{
DPRINT1("Failed to copy message from kernel: invalid usermode buffer\n");
ExFreePool((PVOID) KernelModeMsg->lParam);
return Status;
}
}
ExFreePool((PVOID) KernelModeMsg->lParam);
}
return STATUS_SUCCESS;
}
BOOL FASTCALL
UserPostMessage(HWND Wnd,
UINT Msg,
WPARAM wParam,
LPARAM lParam)
{
MSG UserModeMsg, KernelModeMsg;
LARGE_INTEGER LargeTickCount;
NTSTATUS Status;
PMSGMEMORY MsgMemoryEntry;
if (WM_QUIT == Msg)
{
MsqPostQuitMessage(PsGetCurrentThreadWin32Thread()->MessageQueue, wParam);
}
else if (Wnd == HWND_BROADCAST)
{
HWND *List;
PWINDOW_OBJECT DesktopWindow;
ULONG i;
DesktopWindow = UserGetWindowObject(IntGetDesktopWindow());
List = IntWinListChildren(DesktopWindow);
if (List != NULL)
{
for (i = 0; List[i]; i++)
UserPostMessage(List[i], Msg, wParam, lParam);
ExFreePool(List);
}
}
else
{
PWINDOW_OBJECT Window;
Window = UserGetWindowObject(Wnd);
if (NULL == Window)
{
return FALSE;
}
if(Window->Status & WINDOWSTATUS_DESTROYING)
{
DPRINT1("Attempted to post message to window 0x%x that is being destroyed!\n", Wnd);
/* FIXME - last error code? */
return FALSE;
}
UserModeMsg.hwnd = Wnd;
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;
}
IntGetCursorLocation(PsGetCurrentThreadWin32Thread()->Desktop->WindowStation,
&KernelModeMsg.pt);
KeQueryTickCount(&LargeTickCount);
KernelModeMsg.time = MsqCalculateMessageTime(&LargeTickCount);
MsqPostMessage(Window->MessageQueue, &KernelModeMsg,
NULL != MsgMemoryEntry && 0 != KernelModeMsg.lParam,
QS_POSTMESSAGE);
}
return TRUE;
}
BOOL STDCALL
NtUserPostMessage(HWND hWnd,
UINT Msg,
WPARAM wParam,
LPARAM lParam)
{
DECLARE_RETURN(BOOL);
DPRINT("Enter NtUserPostMessage\n");
UserEnterExclusive();
RETURN(UserPostMessage(hWnd, Msg, wParam, lParam));
CLEANUP:
DPRINT("Leave NtUserPostMessage, ret=%i\n",_ret_);
UserLeave();
END_CLEANUP;
}
BOOL STDCALL
NtUserPostThreadMessage(DWORD idThread,
UINT Msg,
WPARAM wParam,
LPARAM lParam)
{
MSG UserModeMsg, KernelModeMsg;
PETHREAD peThread;
PW32THREAD pThread;
NTSTATUS Status;
PMSGMEMORY MsgMemoryEntry;
DECLARE_RETURN(BOOL);
DPRINT("Enter NtUserPostThreadMessage\n");
UserEnterExclusive();
Status = PsLookupThreadByThreadId((HANDLE)idThread,&peThread);
if( Status == STATUS_SUCCESS )
{
pThread = (PW32THREAD)peThread->Tcb.Win32Thread;
if( !pThread || !pThread->MessageQueue )
{
ObDereferenceObject( peThread );
RETURN( FALSE);
}
UserModeMsg.hwnd = NULL;
UserModeMsg.message = Msg;
UserModeMsg.wParam = wParam;
UserModeMsg.lParam = lParam;
MsgMemoryEntry = FindMsgMemory(UserModeMsg.message);
Status = CopyMsgToKernelMem(&KernelModeMsg, &UserModeMsg, MsgMemoryEntry);
if (! NT_SUCCESS(Status))
{
ObDereferenceObject( peThread );
SetLastWin32Error(ERROR_INVALID_PARAMETER);
RETURN( FALSE);
}
MsqPostMessage(pThread->MessageQueue, &KernelModeMsg,
NULL != MsgMemoryEntry && 0 != KernelModeMsg.lParam,
QS_POSTMESSAGE);
ObDereferenceObject( peThread );
RETURN( TRUE);
}
else
{
SetLastNtError( Status );
RETURN( FALSE);
}
CLEANUP:
DPRINT("Leave NtUserPostThreadMessage, ret=%i\n",_ret_);
UserLeave();
END_CLEANUP;
}
DWORD STDCALL
NtUserQuerySendMessage(DWORD Unknown0)
{
UNIMPLEMENTED;
return 0;
}
LRESULT FASTCALL
co_IntSendMessage(HWND hWnd,
UINT Msg,
WPARAM wParam,
LPARAM lParam)
{
ULONG_PTR Result = 0;
if(co_IntSendMessageTimeout(hWnd, Msg, wParam, lParam, SMTO_NORMAL, 0, &Result))
{
return (LRESULT)Result;
}
return 0;
}
static
LRESULT FASTCALL
co_IntSendMessageTimeoutSingle(HWND hWnd,
UINT Msg,
WPARAM wParam,
LPARAM lParam,
UINT uFlags,
UINT uTimeout,
ULONG_PTR *uResult)
{
ULONG_PTR Result;
NTSTATUS Status;
PWINDOW_OBJECT Window = NULL;
PMSGMEMORY MsgMemoryEntry;
INT lParamBufferSize;
LPARAM lParamPacked;
PW32THREAD Win32Thread;
DECLARE_RETURN(LRESULT);
USER_REFERENCE_ENTRY Ref;
/* FIXME: Call hooks. */
if (!(Window = UserGetWindowObject(hWnd)))
{
RETURN( FALSE);
}
UserRefObjectCo(Window, &Ref);
Win32Thread = PsGetCurrentThreadWin32Thread();
if (NULL != Win32Thread &&
Window->MessageQueue == Win32Thread->MessageQueue)
{
if (Win32Thread->IsExiting)
{
/* Never send messages to exiting threads */
RETURN( FALSE);
}
/* See if this message type is present in the table */
MsgMemoryEntry = FindMsgMemory(Msg);
if (NULL == MsgMemoryEntry)
{
lParamBufferSize = -1;
}
else
{
lParamBufferSize = MsgMemorySize(MsgMemoryEntry, wParam, lParam);
}
if (! NT_SUCCESS(PackParam(&lParamPacked, Msg, wParam, lParam)))
{
DPRINT1("Failed to pack message parameters\n");
RETURN( FALSE);
}
Result = (ULONG_PTR)co_IntCallWindowProc(Window->WndProc, !Window->Unicode, hWnd, Msg, wParam,
lParamPacked,lParamBufferSize);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -