[Win32k|User32]

- Finish 50030 (work by Giannis), Now PostMessage passes all the correct data based on Get/PeekMessage. Example: Post A, Get/Peek A, Translate A, Dispatch A, should be that simple. FYI: DDE memory handling should be in win32k not user32 and why,,,,, ~see next point~
- Patch up problems (at a minimum) going into the SendMessage/Timeout A2U U2A support in win32k and fixed SMTO callback if local.

svn path=/trunk/; revision=50047
This commit is contained in:
James Tabor 2010-12-17 01:09:42 +00:00
parent f21a470fe6
commit e8264b6759
4 changed files with 216 additions and 205 deletions

View file

@ -116,7 +116,6 @@ typedef struct _USER32_TRACKINGLIST {
typedef struct _USER32_THREAD_DATA
{
MSG LastMessage;
USER32_TRACKINGLIST tracking_info; /* TrackMouseEvent stuff */
} USER32_THREAD_DATA, *PUSER32_THREAD_DATA;

View file

@ -145,7 +145,8 @@ DdeGetPair(HGLOBAL ServerMem)
return Ret;
}
static BOOL FASTCALL
static
BOOL FASTCALL
MsgiUMToKMMessage(PMSG UMMsg, PMSG KMMsg, BOOL Posted)
{
*KMMsg = *UMMsg;
@ -249,7 +250,8 @@ MsgiUMToKMMessage(PMSG UMMsg, PMSG KMMsg, BOOL Posted)
return TRUE;
}
static VOID FASTCALL
static
VOID FASTCALL
MsgiUMToKMCleanup(PMSG UMMsg, PMSG KMMsg)
{
switch (KMMsg->message)
@ -949,9 +951,7 @@ DWORD
WINAPI
GetMessagePos(VOID)
{
PUSER32_THREAD_DATA ThreadData = User32GetThreadData();
return(MAKELONG(ThreadData->LastMessage.pt.x, ThreadData->LastMessage.pt.y));
//return NtUserCallNoParam(NOPARAM_ROUTINE_GETMSESSAGEPOS);
return NtUserCallNoParam(NOPARAM_ROUTINE_GETMSESSAGEPOS);
}
@ -961,9 +961,7 @@ GetMessagePos(VOID)
LONG WINAPI
GetMessageTime(VOID)
{
PUSER32_THREAD_DATA ThreadData = User32GetThreadData();
return(ThreadData->LastMessage.time);
// return NtUserGetThreadState(THREADSTATE_GETMESSAGETIME);
return NtUserGetThreadState(THREADSTATE_GETMESSAGETIME);
}
@ -1602,7 +1600,12 @@ GetMessageA(LPMSG lpMsg,
UINT wMsgFilterMax)
{
BOOL Res;
PUSER32_THREAD_DATA ThreadData = User32GetThreadData();
if ( (wMsgFilterMin|wMsgFilterMax) & ~WM_MAXIMUM )
{
SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
}
Res = NtUserGetMessage(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax);
if (-1 == (int) Res)
@ -1610,11 +1613,6 @@ GetMessageA(LPMSG lpMsg,
return Res;
}
if (Res && lpMsg->message != WM_PAINT && lpMsg->message != WM_QUIT)
{
ThreadData->LastMessage = *lpMsg;
}
return Res;
}
@ -1628,7 +1626,12 @@ GetMessageW(LPMSG lpMsg,
UINT wMsgFilterMax)
{
BOOL Res;
PUSER32_THREAD_DATA ThreadData = User32GetThreadData();
if ( (wMsgFilterMin|wMsgFilterMax) & ~WM_MAXIMUM )
{
SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
}
Res = NtUserGetMessage(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax);
if (-1 == (int) Res)
@ -1636,20 +1639,15 @@ GetMessageW(LPMSG lpMsg,
return Res;
}
if (Res && lpMsg->message != WM_PAINT && lpMsg->message != WM_QUIT)
{
ThreadData->LastMessage = *lpMsg;
}
return Res;
}
BOOL WINAPI
PeekMessageWorker(PMSG pMsg,
HWND hWnd,
UINT wMsgFilterMin,
UINT wMsgFilterMax,
UINT wRemoveMsg)
PeekMessageWorker( PMSG pMsg,
HWND hWnd,
UINT wMsgFilterMin,
UINT wMsgFilterMax,
UINT wRemoveMsg)
{
PCLIENTINFO pci;
PCLIENTTHREADINFO pcti;
@ -1692,7 +1690,6 @@ PeekMessageA(LPMSG lpMsg,
UINT wRemoveMsg)
{
BOOL Res;
PUSER32_THREAD_DATA ThreadData = User32GetThreadData();
Res = PeekMessageWorker(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg);
if (-1 == (int) Res || !Res)
@ -1700,11 +1697,6 @@ PeekMessageA(LPMSG lpMsg,
return FALSE;
}
if (Res && lpMsg->message != WM_PAINT && lpMsg->message != WM_QUIT)
{
ThreadData->LastMessage = *lpMsg;
}
return Res;
}
@ -1722,7 +1714,6 @@ PeekMessageW(
UINT wRemoveMsg)
{
BOOL Res;
PUSER32_THREAD_DATA ThreadData = User32GetThreadData();
Res = PeekMessageWorker(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg);
if (-1 == (int) Res || !Res)
@ -1730,46 +1721,9 @@ PeekMessageW(
return FALSE;
}
if (Res && lpMsg->message != WM_PAINT && lpMsg->message != WM_QUIT)
{
ThreadData->LastMessage = *lpMsg;
}
return Res;
}
//
// Worker function for post message.
//
BOOL
FASTCALL
PostMessageWorker(
HWND Wnd,
UINT Msg,
WPARAM wParam,
LPARAM lParam)
{
MSG UMMsg, KMMsg;
LRESULT Result;
UMMsg.hwnd = Wnd;
UMMsg.message = Msg;
UMMsg.wParam = wParam;
UMMsg.lParam = lParam;
if (! MsgiUMToKMMessage(&UMMsg, &KMMsg, TRUE))
{
return FALSE;
}
Result = NtUserPostMessage( Wnd,
KMMsg.message,
KMMsg.wParam,
KMMsg.lParam);
MsgiUMToKMCleanup(&UMMsg, &KMMsg);
return Result;
}
/*
* @implemented
*/
@ -1781,24 +1735,38 @@ PostMessageA(
WPARAM wParam,
LPARAM lParam)
{
MSG AnsiMsg, UcMsg;
BOOL Ret;
LRESULT Ret;
AnsiMsg.hwnd = hWnd;
AnsiMsg.message = Msg;
AnsiMsg.wParam = wParam;
AnsiMsg.lParam = lParam;
if (!MsgiAnsiToUnicodeMessage(&UcMsg, &AnsiMsg))
/* Check for combo box or a list box to send names. */
if (Msg == CB_DIR || Msg == LB_DIR)
{
return FALSE;
/*
Set DDL_POSTMSGS, so use the PostMessage function to send messages to the
combo/list box. Forces a call like DlgDirListComboBox.
*/
//wParam |= DDL_POSTMSGS;
return NtUserPostMessage(hWnd, Msg, wParam, lParam);
}
Ret = PostMessageW( hWnd, UcMsg.message, UcMsg.wParam, UcMsg.lParam);
/* No drop files or current Process, just post message. */
if ( (Msg != WM_DROPFILES) ||
( NtUserQueryWindow( hWnd, QUERY_WINDOW_UNIQUE_PROCESS_ID) ==
PtrToUint(NtCurrentTeb()->ClientId.UniqueProcess) ) )
{
return NtUserPostMessage(hWnd, Msg, wParam, lParam);
}
MsgiAnsiToUnicodeCleanup(&UcMsg, &AnsiMsg);
/* We have drop files and this is not the same process for this window. */
return Ret;
/* Just incase, check wParam for Global memory handle and send size. */
Ret = SendMessageA( hWnd,
WM_COPYGLOBALDATA,
(WPARAM)GlobalSize((HGLOBAL)wParam), // Zero if not a handle.
(LPARAM)wParam); // Send wParam as lParam.
if ( Ret ) return NtUserPostMessage(hWnd, Msg, (WPARAM)Ret, lParam);
return FALSE;
}
/*
@ -1821,8 +1789,8 @@ PostMessageW(
Set DDL_POSTMSGS, so use the PostMessage function to send messages to the
combo/list box. Forces a call like DlgDirListComboBox.
*/
wParam |= DDL_POSTMSGS;
return PostMessageWorker(hWnd, Msg, wParam, lParam);
//wParam |= DDL_POSTMSGS;
return NtUserPostMessage(hWnd, Msg, wParam, lParam);
}
/* No drop files or current Process, just post message. */
@ -1830,7 +1798,7 @@ PostMessageW(
( NtUserQueryWindow( hWnd, QUERY_WINDOW_UNIQUE_PROCESS_ID) ==
PtrToUint(NtCurrentTeb()->ClientId.UniqueProcess) ) )
{
return PostMessageWorker(hWnd, Msg, wParam, lParam);
return NtUserPostMessage(hWnd, Msg, wParam, lParam);
}
/* We have drop files and this is not the same process for this window. */
@ -1841,7 +1809,7 @@ PostMessageW(
(WPARAM)GlobalSize((HGLOBAL)wParam), // Zero if not a handle.
(LPARAM)wParam); // Send wParam as lParam.
if ( Ret ) return PostMessageWorker(hWnd, Msg, (WPARAM)Ret, lParam);
if ( Ret ) return NtUserPostMessage(hWnd, Msg, (WPARAM)Ret, lParam);
return FALSE;
}
@ -1902,11 +1870,16 @@ SendMessageW(HWND Wnd,
PWND Window;
PTHREADINFO ti = GetW32ThreadInfo();
Window = ValidateHwnd(Wnd);
if (!Window) return FALSE;
if ( Msg & ~WM_MAXIMUM )
{
SetLastError( ERROR_INVALID_PARAMETER );
return 0;
}
if (Wnd != HWND_BROADCAST && (Msg < WM_DDE_FIRST || Msg > WM_DDE_LAST))
{
Window = ValidateHwnd(Wnd);
if ( Window != NULL &&
Window->head.pti == ti &&
// !IsThreadHooked(GetWin32ClientInfo()) && // Enable to test message system bug.
@ -1937,7 +1910,7 @@ SendMessageW(HWND Wnd,
return FALSE;
}
Result = NtUserMessageCall( KMMsg.hwnd,
Result = NtUserMessageCall( Wnd,
KMMsg.message,
KMMsg.wParam,
KMMsg.lParam,
@ -1962,11 +1935,16 @@ SendMessageA(HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam)
PWND Window;
PTHREADINFO ti = GetW32ThreadInfo();
Window = ValidateHwnd(Wnd);
if (!Window) return FALSE;
if ( Msg & ~WM_MAXIMUM )
{
SetLastError( ERROR_INVALID_PARAMETER );
return 0;
}
if (Wnd != HWND_BROADCAST && (Msg < WM_DDE_FIRST || Msg > WM_DDE_LAST))
{
Window = ValidateHwnd(Wnd);
if ( Window != NULL &&
Window->head.pti == ti &&
// !IsThreadHooked(GetWin32ClientInfo()) && // Enable to test message system bug.
@ -2003,7 +1981,7 @@ SendMessageA(HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam)
return FALSE;
}
Result = NtUserMessageCall( KMMsg.hwnd,
Result = NtUserMessageCall( Wnd,
KMMsg.message,
KMMsg.wParam,
KMMsg.lParam,
@ -2047,7 +2025,7 @@ SendMessageCallbackA(
return FALSE;
}
Result = NtUserMessageCall( UcMsg.hwnd,
Result = NtUserMessageCall( hWnd,
UcMsg.message,
UcMsg.wParam,
UcMsg.lParam,
@ -2104,8 +2082,8 @@ SendMessageTimeoutA(
MSG AnsiMsg, UcMsg;
LRESULT Result;
DOSENDMESSAGE dsm;
SPY_EnterMessage(SPY_SENDMESSAGE, hWnd, Msg, wParam, lParam);
PWND Window;
PTHREADINFO ti = GetW32ThreadInfo();
if ( Msg & ~WM_MAXIMUM || fuFlags & ~(SMTO_NOTIMEOUTIFNOTHUNG|SMTO_ABORTIFHUNG|SMTO_BLOCK))
{
@ -2115,6 +2093,23 @@ SendMessageTimeoutA(
if (lpdwResult) *lpdwResult = 0;
if (hWnd != HWND_BROADCAST && (Msg < WM_DDE_FIRST || Msg > WM_DDE_LAST))
{
Window = ValidateHwnd(hWnd);
if ( Window != NULL &&
Window->head.pti == ti &&
!ISITHOOKED(WH_CALLWNDPROC) &&
!ISITHOOKED(WH_CALLWNDPROCRET) &&
!(Window->state & WNDS_SERVERSIDEWINDOWPROC) )
{
Result = IntCallMessageProc(Window, hWnd, Msg, wParam, lParam, TRUE);
if (lpdwResult) *lpdwResult = Result;
return TRUE;
}
}
SPY_EnterMessage(SPY_SENDMESSAGE, hWnd, Msg, wParam, lParam);
dsm.uFlags = fuFlags;
dsm.uTimeout = uTimeout;
@ -2128,7 +2123,7 @@ SendMessageTimeoutA(
return FALSE;
}
Result = NtUserMessageCall( UcMsg.hwnd,
Result = NtUserMessageCall( hWnd,
UcMsg.message,
UcMsg.wParam,
UcMsg.lParam,
@ -2162,8 +2157,8 @@ SendMessageTimeoutW(
{
LRESULT Result;
DOSENDMESSAGE dsm;
SPY_EnterMessage(SPY_SENDMESSAGE, hWnd, Msg, wParam, lParam);
PWND Window;
PTHREADINFO ti = GetW32ThreadInfo();
if ( Msg & ~WM_MAXIMUM || fuFlags & ~(SMTO_NOTIMEOUTIFNOTHUNG|SMTO_ABORTIFHUNG|SMTO_BLOCK))
{
@ -2173,6 +2168,23 @@ SendMessageTimeoutW(
if (lpdwResult) *lpdwResult = 0;
if (hWnd != HWND_BROADCAST && (Msg < WM_DDE_FIRST || Msg > WM_DDE_LAST))
{
Window = ValidateHwnd(hWnd);
if ( Window != NULL &&
Window->head.pti == ti &&
!ISITHOOKED(WH_CALLWNDPROC) &&
!ISITHOOKED(WH_CALLWNDPROCRET) &&
!(Window->state & WNDS_SERVERSIDEWINDOWPROC) )
{
Result = IntCallMessageProc(Window, hWnd, Msg, wParam, lParam, FALSE);
if (lpdwResult) *lpdwResult = Result;
return TRUE;
}
}
SPY_EnterMessage(SPY_SENDMESSAGE, hWnd, Msg, wParam, lParam);
dsm.uFlags = fuFlags;
dsm.uTimeout = uTimeout;

View file

@ -61,6 +61,7 @@ static MSGMEMORY MsgMemory[] =
{ WM_STYLECHANGED, sizeof(STYLESTRUCT), MMS_FLAG_READ },
{ WM_STYLECHANGING, sizeof(STYLESTRUCT), MMS_FLAG_READWRITE },
{ WM_COPYDATA, MMS_SIZE_SPECIAL, MMS_FLAG_READ },
{ WM_COPYGLOBALDATA, MMS_SIZE_WPARAM, MMS_FLAG_READ },
{ WM_WINDOWPOSCHANGED, sizeof(WINDOWPOS), MMS_FLAG_READ },
{ WM_WINDOWPOSCHANGING, sizeof(WINDOWPOS), MMS_FLAG_READWRITE },
};
@ -134,10 +135,6 @@ MsgMemorySize(PMSGMEMORY MsgMemoryEntry, WPARAM wParam, LPARAM lParam)
Size = sizeof(COPYDATASTRUCT) + ((PCOPYDATASTRUCT)lParam)->cbData;
break;
case WM_COPYGLOBALDATA:
Size = wParam;
break;
default:
ASSERT(FALSE);
Size = 0;
@ -243,7 +240,6 @@ PackParam(LPARAM *lParamPacked, UINT Msg, WPARAM wParam, LPARAM lParam, BOOL Non
ASSERT(CsData == (PCHAR) PackedCs + Size);
*lParamPacked = (LPARAM) PackedCs;
}
else if (PoolType == NonPagedPool)
{
PMSGMEMORY MsgMemoryEntry;
@ -317,6 +313,100 @@ UnpackParam(LPARAM lParamPacked, UINT Msg, WPARAM wParam, LPARAM lParam, BOOL No
return STATUS_INVALID_PARAMETER;
}
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");
ExFreePoolWithTag(KernelMem, TAG_MSG);
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;
}
//
// Wakeup any thread/process waiting on idle input.
//
@ -654,100 +744,6 @@ co_IntPeekMessage( PMSG Msg,
return TRUE;
}
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");
ExFreePoolWithTag(KernelMem, TAG_MSG);
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;
}
static BOOL FASTCALL
co_IntWaitMessage( PWND Window,
UINT MsgFilterMin,
@ -775,9 +771,9 @@ co_IntWaitMessage( PWND Window,
/* Nothing found. Wait for new messages. */
Status = co_MsqWaitForNewMessages( ThreadQueue,
Window,
MsgFilterMin,
MsgFilterMax);
Window,
MsgFilterMin,
MsgFilterMax);
}
while ( (STATUS_WAIT_0 <= Status && Status <= STATUS_WAIT_63) ||
STATUS_TIMEOUT == Status );
@ -834,6 +830,7 @@ co_IntGetPeekMessage( PMSG pMsg,
}
pti = PsGetCurrentThreadWin32Thread();
pti->pClientInfo->cSpins++; // Bump up the spin count.
do
{
@ -848,8 +845,11 @@ co_IntGetPeekMessage( PMSG pMsg,
/* GetMessage or PostMessage must never get messages that contain pointers */
ASSERT(FindMsgMemory(pMsg->message) == NULL);
pti->timeLast = pMsg->time;
pti->ptLast = pMsg->pt;
if (pMsg->message != WM_PAINT && pMsg->message != WM_QUIT)
{
pti->timeLast = pMsg->time;
pti->ptLast = pMsg->pt;
}
// The WH_GETMESSAGE hook enables an application to monitor messages about to
// be returned by the GetMessage or PeekMessage function.
@ -984,7 +984,7 @@ UserPostMessage( HWND Wnd,
KernelModeMsg.wParam,
KernelModeMsg.lParam);
if(MsgMemoryEntry)
if (MsgMemoryEntry && KernelModeMsg.lParam)
ExFreePool((PVOID) KernelModeMsg.lParam);
return TRUE;
@ -1019,7 +1019,7 @@ UserPostMessage( HWND Wnd,
{
UserPostMessage(List[i], Msg, wParam, lParam);
}
ExFreePool(List);
ExFreePoolWithTag(List,TAG_WINLIST);//ExFreePool(List);
}
}
else

View file

@ -1624,7 +1624,7 @@ co_MsqReplyMessage( LRESULT lResult )
pti = PsGetCurrentThreadWin32Thread();
Message = pti->pusmCurrent;
if(!Message) return FALSE;
if (!Message) return FALSE;
if (Message->QS_Flags & QS_SMRESULT) return FALSE;