- Use the new version of NtUserGetMessage and NtUserPeekMessage written by Jim. It is possible to use them now because GetMessage and PeekMessage don't return messages that contain pointers. As a result they don't need to do any extra work to copy the message to user mode. All messages that contain pointers are sent messages and this means that they don't get into the message loop. Instead they are passed directly to the window proc.
- DispatchMessage works only if the target window belongs to the current thread. This lets us remove uneeded copies of lparam to user mode. 

[user32]
- Remove a bunch of uneeded code in GetMessage and PeekMessage that copyied the lparam in a new buffer and did unicode to ansi convertions. It is not needed because they don't receive messages with pointers any more

svn path=/trunk/; revision=50030
This commit is contained in:
Giannis Adamopoulos 2010-12-15 19:21:48 +00:00
parent 2138d6d794
commit ca9039c50e
3 changed files with 40 additions and 453 deletions

View file

@ -931,121 +931,6 @@ MsgiUnicodeToAnsiReply(LPMSG AnsiMsg, LPMSG UnicodeMsg, LRESULT *Result)
return TRUE;
}
typedef struct tagMSGCONVERSION
{
BOOL InUse;
BOOL Ansi;
MSG KMMsg;
MSG UnicodeMsg;
MSG AnsiMsg;
PMSG FinalMsg;
SIZE_T LParamSize;
} MSGCONVERSION, *PMSGCONVERSION;
static PMSGCONVERSION MsgConversions = NULL;
static unsigned MsgConversionNumAlloc = 0;
static unsigned MsgConversionNumUsed = 0;
static CRITICAL_SECTION MsgConversionCrst;
static BOOL FASTCALL
MsgConversionAdd(PMSGCONVERSION Conversion)
{
unsigned i;
EnterCriticalSection(&MsgConversionCrst);
if (MsgConversionNumUsed == MsgConversionNumAlloc)
{
#define GROWBY 4
PMSGCONVERSION New;
if (NULL != MsgConversions)
{
New = HeapReAlloc(GetProcessHeap(), 0, MsgConversions,
(MsgConversionNumAlloc + GROWBY) * sizeof(MSGCONVERSION));
}
else
{
New = HeapAlloc(GetProcessHeap(), 0,
(MsgConversionNumAlloc + GROWBY) * sizeof(MSGCONVERSION));
}
if (NULL == New)
{
LeaveCriticalSection(&MsgConversionCrst);
return FALSE;
}
MsgConversions = New;
/* zero out newly allocated part */
memset(MsgConversions + MsgConversionNumAlloc, 0, GROWBY * sizeof(MSGCONVERSION));
MsgConversionNumAlloc += GROWBY;
#undef GROWBY
}
for (i = 0; i < MsgConversionNumAlloc; i++)
{
if (! MsgConversions[i].InUse)
{
MsgConversions[i] = *Conversion;
MsgConversions[i].InUse = TRUE;
MsgConversionNumUsed++;
break;
}
}
LeaveCriticalSection(&MsgConversionCrst);
return TRUE;
}
static void FASTCALL
MsgConversionCleanup(CONST MSG *Msg, BOOL Ansi, BOOL CheckMsgContents, LRESULT *Result)
{
BOOL Found;
PMSGCONVERSION Conversion;
LRESULT Dummy;
EnterCriticalSection(&MsgConversionCrst);
for (Conversion = MsgConversions;
Conversion < MsgConversions + MsgConversionNumAlloc;
Conversion++)
{
if (Conversion->InUse &&
((Ansi && Conversion->Ansi) ||
(! Ansi && ! Conversion->Ansi)))
{
Found = (Conversion->FinalMsg == Msg);
if (! Found && CheckMsgContents)
{
if (Ansi)
{
Found = (0 == memcmp(Msg, &Conversion->AnsiMsg, sizeof(MSG)));
}
else
{
Found = (0 == memcmp(Msg, &Conversion->UnicodeMsg, sizeof(MSG)));
}
}
if (Found)
{
if (Ansi)
{
MsgiUnicodeToAnsiReply(&Conversion->AnsiMsg, &Conversion->UnicodeMsg,
NULL == Result ? &Dummy : Result);
}
MsgiKMToUMReply(&Conversion->KMMsg, &Conversion->UnicodeMsg,
NULL == Result ? &Dummy : Result);
if (0 != Conversion->LParamSize)
{
NtFreeVirtualMemory(NtCurrentProcess(), (PVOID *) &Conversion->KMMsg.lParam,
&Conversion->LParamSize, MEM_DECOMMIT);
}
Conversion->InUse = FALSE;
MsgConversionNumUsed--;
}
}
}
LeaveCriticalSection(&MsgConversionCrst);
}
/*
* @implemented
*/
@ -1717,46 +1602,22 @@ GetMessageA(LPMSG lpMsg,
UINT wMsgFilterMax)
{
BOOL Res;
MSGCONVERSION Conversion;
NTUSERGETMESSAGEINFO Info;
PUSER32_THREAD_DATA ThreadData = User32GetThreadData();
MsgConversionCleanup(lpMsg, TRUE, FALSE, NULL);
Res = NtUserGetMessage(&Info, hWnd, wMsgFilterMin, wMsgFilterMax);
Res = NtUserGetMessage(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax);
if (-1 == (int) Res)
{
return Res;
}
Conversion.LParamSize = Info.LParamSize;
Conversion.KMMsg = Info.Msg;
if (! MsgiKMToUMMessage(&Conversion.KMMsg, &Conversion.UnicodeMsg))
{
return (BOOL) -1;
}
if (! MsgiUnicodeToAnsiMessage(&Conversion.AnsiMsg, &Conversion.UnicodeMsg))
{
MsgiKMToUMCleanup(&Info.Msg, &Conversion.UnicodeMsg);
return (BOOL) -1;
}
if (!lpMsg)
{
SetLastError( ERROR_NOACCESS );
return FALSE;
}
*lpMsg = Conversion.AnsiMsg;
Conversion.Ansi = TRUE;
Conversion.FinalMsg = lpMsg;
MsgConversionAdd(&Conversion);
if (Res && lpMsg->message != WM_PAINT && lpMsg->message != WM_QUIT)
{
ThreadData->LastMessage = Info.Msg;
ThreadData->LastMessage = *lpMsg;
}
return Res;
}
/*
* @implemented
*/
@ -1767,42 +1628,24 @@ GetMessageW(LPMSG lpMsg,
UINT wMsgFilterMax)
{
BOOL Res;
MSGCONVERSION Conversion;
NTUSERGETMESSAGEINFO Info;
PUSER32_THREAD_DATA ThreadData = User32GetThreadData();
MsgConversionCleanup(lpMsg, FALSE, FALSE, NULL);
Res = NtUserGetMessage(&Info, hWnd, wMsgFilterMin, wMsgFilterMax);
Res = NtUserGetMessage(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax);
if (-1 == (int) Res)
{
return Res;
}
Conversion.LParamSize = Info.LParamSize;
Conversion.KMMsg = Info.Msg;
if (! MsgiKMToUMMessage(&Conversion.KMMsg, &Conversion.UnicodeMsg))
{
return (BOOL) -1;
}
if (!lpMsg)
{
SetLastError( ERROR_NOACCESS );
return FALSE;
}
*lpMsg = Conversion.UnicodeMsg;
Conversion.Ansi = FALSE;
Conversion.FinalMsg = lpMsg;
MsgConversionAdd(&Conversion);
if (Res && lpMsg->message != WM_PAINT && lpMsg->message != WM_QUIT)
{
ThreadData->LastMessage = Info.Msg;
ThreadData->LastMessage = *lpMsg;
}
return Res;
}
BOOL WINAPI
PeekMessageWorker(PNTUSERGETMESSAGEINFO pInfo,
PeekMessageWorker(PMSG pMsg,
HWND hWnd,
UINT wMsgFilterMin,
UINT wMsgFilterMax,
@ -1835,7 +1678,7 @@ PeekMessageWorker(PNTUSERGETMESSAGEINFO pInfo,
}
}
}
return NtUserPeekMessage(pInfo, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg);
return NtUserPeekMessage(pMsg, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg);
}
/*
@ -1849,40 +1692,17 @@ PeekMessageA(LPMSG lpMsg,
UINT wRemoveMsg)
{
BOOL Res;
MSGCONVERSION Conversion;
NTUSERGETMESSAGEINFO Info;
PUSER32_THREAD_DATA ThreadData = User32GetThreadData();
MsgConversionCleanup(lpMsg, TRUE, FALSE, NULL);
Res = PeekMessageWorker(&Info, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg);
Res = PeekMessageWorker(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg);
if (-1 == (int) Res || !Res)
{
return FALSE;
}
Conversion.LParamSize = Info.LParamSize;
Conversion.KMMsg = Info.Msg;
if (! MsgiKMToUMMessage(&Conversion.KMMsg, &Conversion.UnicodeMsg))
{
return FALSE;
}
if (! MsgiUnicodeToAnsiMessage(&Conversion.AnsiMsg, &Conversion.UnicodeMsg))
{
MsgiKMToUMCleanup(&Info.Msg, &Conversion.UnicodeMsg);
return FALSE;
}
if (!lpMsg)
{
SetLastError( ERROR_NOACCESS );
return FALSE;
}
*lpMsg = Conversion.AnsiMsg;
Conversion.Ansi = TRUE;
Conversion.FinalMsg = lpMsg;
MsgConversionAdd(&Conversion);
if (Res && lpMsg->message != WM_PAINT && lpMsg->message != WM_QUIT)
{
ThreadData->LastMessage = Info.Msg;
ThreadData->LastMessage = *lpMsg;
}
return Res;
@ -1902,35 +1722,17 @@ PeekMessageW(
UINT wRemoveMsg)
{
BOOL Res;
MSGCONVERSION Conversion;
NTUSERGETMESSAGEINFO Info;
PUSER32_THREAD_DATA ThreadData = User32GetThreadData();
MsgConversionCleanup(lpMsg, FALSE, FALSE, NULL);
Res = PeekMessageWorker(&Info, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg);
Res = PeekMessageWorker(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg);
if (-1 == (int) Res || !Res)
{
return FALSE;
}
Conversion.LParamSize = Info.LParamSize;
Conversion.KMMsg = Info.Msg;
if (! MsgiKMToUMMessage(&Conversion.KMMsg, &Conversion.UnicodeMsg))
{
return FALSE;
}
if (!lpMsg)
{
SetLastError( ERROR_NOACCESS );
return FALSE;
}
*lpMsg = Conversion.UnicodeMsg;
Conversion.Ansi = FALSE;
Conversion.FinalMsg = lpMsg;
MsgConversionAdd(&Conversion);
if (Res && lpMsg->message != WM_PAINT && lpMsg->message != WM_QUIT)
{
ThreadData->LastMessage = Info.Msg;
ThreadData->LastMessage = *lpMsg;
}
return Res;
@ -2878,7 +2680,6 @@ MsgWaitForMultipleObjects(
BOOL FASTCALL MessageInit(VOID)
{
InitializeCriticalSection(&DdeCrst);
InitializeCriticalSection(&MsgConversionCrst);
InitializeCriticalSection(&gcsMPH);
return TRUE;
@ -2887,7 +2688,6 @@ BOOL FASTCALL MessageInit(VOID)
VOID FASTCALL MessageCleanup(VOID)
{
DeleteCriticalSection(&DdeCrst);
DeleteCriticalSection(&MsgConversionCrst);
DeleteCriticalSection(&gcsMPH);
}

View file

@ -1996,19 +1996,11 @@ NTAPI
NtUserGetListBoxInfo(
HWND hWnd);
typedef struct tagNTUSERGETMESSAGEINFO
{
MSG Msg;
ULONG LParamSize;
} NTUSERGETMESSAGEINFO, *PNTUSERGETMESSAGEINFO;
BOOL
NTAPI
NtUserGetMessage(
PNTUSERGETMESSAGEINFO MsgInfo,
BOOL APIENTRY
NtUserGetMessage(PMSG pMsg,
HWND hWnd,
UINT wMsgFilterMin,
UINT wMsgFilterMax);
UINT MsgFilterMin,
UINT MsgFilterMax);
DWORD
NTAPI
@ -2373,14 +2365,12 @@ NtUserPaintMenuBar(
DWORD dwUnknown5,
DWORD dwUnknown6);
BOOL
NTAPI
NtUserPeekMessage(
PNTUSERGETMESSAGEINFO MsgInfo,
BOOL APIENTRY
NtUserPeekMessage( PMSG pMsg,
HWND hWnd,
UINT wMsgFilterMin,
UINT wMsgFilterMax,
UINT wRemoveMsg);
UINT MsgFilterMin,
UINT MsgFilterMax,
UINT RemoveMsg);
BOOL
NTAPI

View file

@ -426,10 +426,7 @@ IntDispatchMessage(PMSG pMsg)
LARGE_INTEGER TickCount;
LONG Time;
LRESULT retval = 0;
PMSGMEMORY MsgMemoryEntry;
INT lParamBufferSize;
PTHREADINFO pti;
LPARAM lParamPacked;
PWND Window = NULL;
if (pMsg->hwnd)
@ -452,7 +449,6 @@ IntDispatchMessage(PMSG pMsg)
{
if (pMsg->message == WM_TIMER)
{
ObReferenceObject(pti->pEThread);
if (ValidateTimerCallback(pti,pMsg->lParam))
{
KeQueryTickCount(&TickCount);
@ -463,9 +459,8 @@ IntDispatchMessage(PMSG pMsg)
WM_TIMER,
pMsg->wParam,
(LPARAM)Time,
sizeof(LPARAM));
0);
}
ObDereferenceObject(pti->pEThread);
return retval;
}
else
@ -483,35 +478,17 @@ IntDispatchMessage(PMSG pMsg)
// Need a window!
if ( !Window ) return 0;
/* See if this message type is present in the table */
MsgMemoryEntry = FindMsgMemory(pMsg->message);
if ( !MsgMemoryEntry )
{
lParamBufferSize = -1;
}
else
{
lParamBufferSize = MsgMemorySize(MsgMemoryEntry, pMsg->wParam, pMsg->lParam);
}
/* Since we are doing a callback on the same thread right away, there is
no need to copy the lparam to kernel mode and then back to usermode.
We just pretend it isn't a pointer */
if (! NT_SUCCESS(PackParam(&lParamPacked, pMsg->message, pMsg->wParam, pMsg->lParam, FALSE)))
{
DPRINT1("Failed to pack message parameters\n");
return 0;
}
ObReferenceObject(pti->pEThread);
retval = co_IntCallWindowProc( Window->lpfnWndProc,
!Window->Unicode,
pMsg->hwnd,
pMsg->message,
pMsg->wParam,
lParamPacked,
lParamBufferSize);
if (! NT_SUCCESS(UnpackParam(lParamPacked, pMsg->message, pMsg->wParam, pMsg->lParam, FALSE)))
{
DPRINT1("Failed to unpack message parameters\n");
}
pMsg->lParam,
0);
if (pMsg->message == WM_PAINT)
{
@ -520,7 +497,7 @@ IntDispatchMessage(PMSG pMsg)
co_UserGetUpdateRgn( Window, hrgn, TRUE );
REGION_FreeRgnByHandle( hrgn );
}
ObDereferenceObject(pti->pEThread);
return retval;
}
@ -868,6 +845,9 @@ co_IntGetPeekMessage( PMSG pMsg,
bGMSG );
if (Present)
{
/* GetMessage or PostMessage must never get messages that contain pointers */
ASSERT(FindMsgMemory(pMsg->message) == NULL);
pti->timeLast = pMsg->time;
pti->ptLast = pMsg->pt;
@ -1698,104 +1678,8 @@ NtUserWaitMessage(VOID)
return ret;
}
BOOL APIENTRY
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.
*/
{
NTUSERGETMESSAGEINFO Info;
NTSTATUS Status;
PMSGMEMORY MsgMemoryEntry;
PVOID UserMem;
ULONG Size;
MSG Msg;
BOOL GotMessage;
if ( (MsgFilterMin|MsgFilterMax) & ~WM_MAXIMUM )
{
SetLastWin32Error(ERROR_INVALID_PARAMETER);
return FALSE;
}
UserEnterExclusive();
RtlZeroMemory(&Msg, sizeof(MSG));
GotMessage = co_IntGetPeekMessage(&Msg, hWnd, MsgFilterMin, MsgFilterMax, PM_REMOVE, TRUE);
UserLeave();
Info.Msg = Msg;
/* See if this message type is present in the table */
MsgMemoryEntry = FindMsgMemory(Info.Msg.message);
_SEH2_TRY
{
ProbeForWrite(UnsafeInfo, sizeof(NTUSERGETMESSAGEINFO), 1);
RtlCopyMemory(UnsafeInfo, &Info, sizeof(NTUSERGETMESSAGEINFO));
if (NULL == MsgMemoryEntry)
{
/* Not present, no copying needed */
UnsafeInfo->LParamSize = 0;
}
else
{
/* Determine required size */
Size = MsgMemorySize(MsgMemoryEntry, Info.Msg.wParam, Info.Msg.lParam);
/* Allocate required amount of user-mode memory */
Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
&UserMem,
0,
&Size,
MEM_COMMIT,
PAGE_READWRITE);
if (! NT_SUCCESS(Status))
{
SetLastNtError(Status);
_SEH2_YIELD(return (BOOL) -1);
}
/* Transfer lParam data to user-mode mem */
ProbeForWrite(UserMem, Size, 1);
RtlCopyMemory(UserMem, (PVOID)Info.Msg.lParam, Size);
UnsafeInfo->LParamSize = Size;
UnsafeInfo->Msg.lParam = (LPARAM) UserMem;
}
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
SetLastNtError(_SEH2_GetExceptionCode());
if(UserMem != NULL)
{
ZwFreeVirtualMemory(NtCurrentProcess(), &UserMem, &Size, MEM_RELEASE);
}
_SEH2_YIELD(return (BOOL) -1);
}
_SEH2_END;
return GotMessage;
}
BOOL APIENTRY
NtUserGetMessageX(PMSG pMsg,
NtUserGetMessage(PMSG pMsg,
HWND hWnd,
UINT MsgFilterMin,
UINT MsgFilterMax )
@ -1836,94 +1720,7 @@ NtUserGetMessageX(PMSG pMsg,
}
BOOL APIENTRY
NtUserPeekMessage(PNTUSERGETMESSAGEINFO UnsafeInfo,
HWND hWnd,
UINT MsgFilterMin,
UINT MsgFilterMax,
UINT RemoveMsg)
{
NTSTATUS Status;
NTUSERGETMESSAGEINFO Info;
PMSGMEMORY MsgMemoryEntry;
PVOID UserMem = NULL;
ULONG Size;
MSG Msg;
BOOL Ret;
if ( RemoveMsg & PM_BADMSGFLAGS )
{
SetLastWin32Error(ERROR_INVALID_FLAGS);
return FALSE;
}
UserEnterExclusive();
RtlZeroMemory(&Msg, sizeof(MSG));
Ret = co_IntGetPeekMessage(&Msg, hWnd, MsgFilterMin, MsgFilterMax, RemoveMsg, FALSE);
UserLeave();
if (Ret)
{
Info.Msg = Msg;
/* See if this message type is present in the table */
MsgMemoryEntry = FindMsgMemory(Info.Msg.message);
_SEH2_TRY
{
ProbeForWrite(UnsafeInfo, sizeof(NTUSERGETMESSAGEINFO), 1);
RtlCopyMemory(UnsafeInfo, &Info, sizeof(NTUSERGETMESSAGEINFO));
if (NULL == MsgMemoryEntry)
{
/* Not present, no copying needed */
UnsafeInfo->LParamSize = 0;
}
else
{
/* Determine required size */
Size = MsgMemorySize(MsgMemoryEntry, Info.Msg.wParam, Info.Msg.lParam);
/* Allocate required amount of user-mode memory */
Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
&UserMem,
0,
&Size,
MEM_COMMIT,
PAGE_READWRITE);
if (! NT_SUCCESS(Status))
{
SetLastNtError(Status);
_SEH2_YIELD(return (BOOL) -1);
}
/* Transfer lParam data to user-mode mem */
ProbeForWrite(UserMem, Size, 1);
RtlCopyMemory(UserMem, (PVOID)Info.Msg.lParam, Size);
UnsafeInfo->LParamSize = Size;
UnsafeInfo->Msg.lParam = (LPARAM) UserMem;
}
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
SetLastNtError(_SEH2_GetExceptionCode());
Ret = (BOOL) -1;
if(UserMem != NULL)
{
ZwFreeVirtualMemory(NtCurrentProcess(), &UserMem, &Size, MEM_RELEASE);
}
}
_SEH2_END;
}
return Ret;
}
BOOL APIENTRY
NtUserPeekMessageX( PMSG pMsg,
NtUserPeekMessage( PMSG pMsg,
HWND hWnd,
UINT MsgFilterMin,
UINT MsgFilterMax,