diff --git a/reactos/include/win32k/ntuser.h b/reactos/include/win32k/ntuser.h index 9db51015fd3..ece27718a4c 100644 --- a/reactos/include/win32k/ntuser.h +++ b/reactos/include/win32k/ntuser.h @@ -384,9 +384,17 @@ NtUserDestroyCursorIcon( BOOLEAN STDCALL NtUserDestroyWindow(HWND Wnd); +typedef struct tagNTUSERDISPATCHMESSAGEINFO +{ + BOOL HandledByKernel; + BOOL Ansi; + WNDPROC Proc; + MSG Msg; +} NTUSERDISPATCHMESSAGEINFO, *PNTUSERDISPATCHMESSAGEINFO; + LRESULT STDCALL -NtUserDispatchMessage(CONST MSG* lpmsg); +NtUserDispatchMessage(PNTUSERDISPATCHMESSAGEINFO MsgInfo); BOOL STDCALL @@ -734,10 +742,16 @@ STDCALL NtUserGetListBoxInfo( DWORD Unknown0); +typedef struct tagNTUSERGETMESSAGEINFO +{ + MSG Msg; + ULONG LParamSize; +} NTUSERGETMESSAGEINFO, *PNTUSERGETMESSAGEINFO; + BOOL STDCALL NtUserGetMessage( - LPMSG lpMsg, + PNTUSERGETMESSAGEINFO MsgInfo, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax); @@ -1036,7 +1050,7 @@ NtUserPaintDesktop( BOOL STDCALL NtUserPeekMessage( - LPMSG lpMsg, + PNTUSERGETMESSAGEINFO MsgInfo, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax, @@ -1717,6 +1731,28 @@ NtUserSetScrollBarInfo( LONG idObject, SETSCROLLBARINFO *info); +/* lParam of DDE messages */ +typedef struct tagKMDDEEXECUTEDATA +{ + HWND Sender; + HGLOBAL ClientMem; + /* BYTE Data[DataSize] */ +} KMDDEEXECUTEDATA, *PKMDDEEXECUTEDATA; + +typedef struct tagKMDDELPARAM +{ + BOOL Packed; + union + { + struct + { + UINT uiLo; + UINT uiHi; + } Packed; + LPARAM Unpacked; + } Value; +} KMDDELPARAM, *PKMDDELPARAM; + #endif /* __WIN32K_NTUSER_H */ /* EOF */ diff --git a/reactos/lib/user32/include/message.h b/reactos/lib/user32/include/message.h new file mode 100644 index 00000000000..7f1d9399bb0 --- /dev/null +++ b/reactos/lib/user32/include/message.h @@ -0,0 +1,14 @@ +/* $Id: message.h,v 1.1 2004/04/29 21:13:16 gvg Exp $ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS user32.dll + * FILE: include/message.h + * PURPOSE: Message management definitions + */ + +#ifndef LIB_USER32_INCLUDE_MESSAGE_H +#define LIB_USER32_INCLUDE_MESSAGE_H + +BOOL FASTCALL MessageInit(VOID); + +#endif /* LIB_USER32_INCLUDE_MESSAGE_H */ diff --git a/reactos/lib/user32/misc/ddeclient.c b/reactos/lib/user32/misc/ddeclient.c index 54af3c074ff..24b67237cd4 100644 --- a/reactos/lib/user32/misc/ddeclient.c +++ b/reactos/lib/user32/misc/ddeclient.c @@ -1340,7 +1340,7 @@ static LRESULT CALLBACK WDML_ClientProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPA } return (IsWindowUnicode(hwnd)) ? - DefWindowProcA(hwnd, iMsg, wParam, lParam) : DefWindowProcW(hwnd, iMsg, wParam, lParam); + DefWindowProcW(hwnd, iMsg, wParam, lParam) : DefWindowProcA(hwnd, iMsg, wParam, lParam); } /***************************************************************** diff --git a/reactos/lib/user32/misc/ddeserver.c b/reactos/lib/user32/misc/ddeserver.c index 29210b88121..8e3a28a9bbd 100644 --- a/reactos/lib/user32/misc/ddeserver.c +++ b/reactos/lib/user32/misc/ddeserver.c @@ -994,7 +994,8 @@ static LRESULT CALLBACK WDML_ServerConvProc(HWND hwndServer, UINT iMsg, WPARAM w } if (iMsg < WM_DDE_FIRST || iMsg > WM_DDE_LAST) { - return DefWindowProcA(hwndServer, iMsg, wParam, lParam); + return IsWindowUnicode(hwndServer) ? DefWindowProcW(hwndServer, iMsg, wParam, lParam) : + DefWindowProcA(hwndServer, iMsg, wParam, lParam); } EnterCriticalSection(&WDML_CritSect); diff --git a/reactos/lib/user32/misc/dllmain.c b/reactos/lib/user32/misc/dllmain.c index b636958f70a..15fbf11bc32 100644 --- a/reactos/lib/user32/misc/dllmain.c +++ b/reactos/lib/user32/misc/dllmain.c @@ -6,6 +6,7 @@ #include #include #include +#include #define _WIN32K_KAPI_H #include #include @@ -73,6 +74,7 @@ Init(VOID) User32TlsIndex = TlsAlloc(); MenuInit(); + MessageInit(); InitializeCriticalSection(&U32AccelCacheLock); InitializeCriticalSection(&gcsMPH); diff --git a/reactos/lib/user32/windows/message.c b/reactos/lib/user32/windows/message.c index 200c01a5740..b46f5af9604 100644 --- a/reactos/lib/user32/windows/message.c +++ b/reactos/lib/user32/windows/message.c @@ -1,4 +1,4 @@ -/* $Id: message.c,v 1.38 2004/04/10 00:54:35 navaraf Exp $ +/* $Id: message.c,v 1.39 2004/04/29 21:13:16 gvg Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS user32.dll @@ -12,96 +12,329 @@ #include #include #include +#include +#include #define NTOS_MODE_USER #include -/* - * @implemented +/* DDE message exchange + * + * - Session initialization + * Client sends a WM_DDE_INITIATE message, usually a broadcast message. lParam of + * this message contains a pair of global atoms, the Application and Topic atoms. + * The client must destroy the atoms. + * Server window proc handles the WM_DDE_INITIATE message and if the Application + * and Topic atoms are recognized sends a WM_DDE_ACK message to the client. lParam + * of the reply message contains another pair of global atoms (Application and + * Topic again), which must be destroyed by the server. + * + * - Execute + * Client posts a WM_DDE_EXECUTE message to the server window. lParam of that message + * is a global memory handle containing the string to execute. After the command has + * been executed the server posts a WM_DDE_ACK message to the client, which contains + * a packed lParam which in turn contains that global memory handle. The client takes + * ownership of both the packed lParam (meaning it needs to call FreeDDElParam() on + * it and the global memory handle. + * This might work nice and easy in Win3.1, but things are more complicated for NT. + * Global memory handles in NT are not really global, they're still local to the + * process. So, what happens under the hood is that PostMessage must handle the + * WM_DDE_EXECUTE message specially. It will obtain the contents of the global memory + * area, repack that into a new structure together with the original memory handle + * and pass that off to the win32k. Win32k will marshall that data over to the target + * (server) process where it will be unpacked and stored in a newly allocated global + * memory area. The handle of that area will then be sent to the window proc, after + * storing it together with the "original" (client) handle in a table. + * The server will eventually post the WM_DDE_ACK response, containing the global + * memory handle it received. PostMessage must then lookup that memory handle (only + * valid in the server process) and replace it with the corresponding client memory + * handle. To avoid memory leaks, the server-side global memory block must be freed. + * Also, the WM_DDE_ACK lParam (a PackDDElParam() result) is unpacked and the + * individual components are handed to win32k.sys to post to the client side. Since + * the server side app hands over ownership of the packed lParam when it calls + * PostMessage(), the packed lParam needs to be freed on the server side too. + * When the WM_DDE_ACK message (containing the client-side global memory handle) + * arrives at the client side a new lParam is PackDDElParam()'ed and this is handed + * to the client side window proc which is expected to free/reuse it. */ -LPARAM -STDCALL -GetMessageExtraInfo(VOID) + +/* since the WM_DDE_ACK response to a WM_DDE_EXECUTE message should contain the handle + * to the memory handle, we keep track (in the server side) of all pairs of handle + * used (the client passes its value and the content of the memory handle), and + * the server stored both values (the client, and the local one, created after the + * content). When a ACK message is generated, the list of pair is searched for a + * matching pair, so that the client memory handle can be returned. + */ +typedef struct tagDDEPAIR { - return (LPARAM)NtUserCallNoParam(NOPARAM_ROUTINE_GETMESSAGEEXTRAINFO); + HGLOBAL ClientMem; + HGLOBAL ServerMem; +} DDEPAIR, *PDDEPAIR; + +static PDDEPAIR DdePairs = NULL; +static unsigned DdeNumAlloc = 0; +static unsigned DdeNumUsed = 0; +static CRITICAL_SECTION DdeCrst; + +static BOOL FASTCALL +DdeAddPair(HGLOBAL ClientMem, HGLOBAL ServerMem) +{ + unsigned i; + + EnterCriticalSection(&DdeCrst); + + /* now remember the pair of hMem on both sides */ + if (DdeNumUsed == DdeNumAlloc) + { +#define GROWBY 4 + PDDEPAIR New; + if (NULL != DdePairs) + { + New = HeapReAlloc(GetProcessHeap(), 0, DdePairs, + (DdeNumAlloc + GROWBY) * sizeof(DDEPAIR)); + } + else + { + New = HeapAlloc(GetProcessHeap(), 0, + (DdeNumAlloc + GROWBY) * sizeof(DDEPAIR)); + } + + if (NULL == New) + { + LeaveCriticalSection(&DdeCrst); + return FALSE; + } + DdePairs = New; + /* zero out newly allocated part */ + memset(&DdePairs[DdeNumAlloc], 0, GROWBY * sizeof(DDEPAIR)); + DdeNumAlloc += GROWBY; +#undef GROWBY + } + + for (i = 0; i < DdeNumAlloc; i++) + { + if (NULL == DdePairs[i].ServerMem) + { + DdePairs[i].ClientMem = ClientMem; + DdePairs[i].ServerMem = ServerMem; + DdeNumUsed++; + break; + } + } + LeaveCriticalSection(&DdeCrst); + + return TRUE; } - -/* - * @implemented - */ -DWORD -STDCALL -GetMessagePos(VOID) +static HGLOBAL FASTCALL +DdeGetPair(HGLOBAL ServerMem) { - PUSER32_THREAD_DATA ThreadData = User32GetThreadData(); - return(MAKELONG(ThreadData->LastMessage.pt.x, ThreadData->LastMessage.pt.y)); + unsigned i; + HGLOBAL Ret = NULL; + + EnterCriticalSection(&DdeCrst); + for (i = 0; i < DdeNumAlloc; i++) + { + if (DdePairs[i].ServerMem == ServerMem) + { + /* free this pair */ + DdePairs[i].ServerMem = 0; + DdeNumUsed--; + Ret = DdePairs[i].ClientMem; + break; + } + } + LeaveCriticalSection(&DdeCrst); + + return Ret; } - -/* - * @implemented - */ -LONG STDCALL -GetMessageTime(VOID) +static BOOL FASTCALL +MsgiUMToKMMessage(PMSG UMMsg, PMSG KMMsg, BOOL Posted) { - PUSER32_THREAD_DATA ThreadData = User32GetThreadData(); - return(ThreadData->LastMessage.time); + *KMMsg = *UMMsg; + + switch (UMMsg->message) + { + case WM_DDE_ACK: + { + PKMDDELPARAM DdeLparam; + DdeLparam = HeapAlloc(GetProcessHeap(), 0, sizeof(KMDDELPARAM)); + if (NULL == DdeLparam) + { + return FALSE; + } + if (Posted) + { + DdeLparam->Packed = TRUE; + if (! UnpackDDElParam(UMMsg->message, UMMsg->lParam, + &DdeLparam->Value.Packed.uiLo, + &DdeLparam->Value.Packed.uiHi)) + { + return FALSE; + } + if (0 != HIWORD(DdeLparam->Value.Packed.uiHi)) + { + /* uiHi should contain a hMem from WM_DDE_EXECUTE */ + HGLOBAL h = DdeGetPair((HGLOBAL) DdeLparam->Value.Packed.uiHi); + if (NULL != h) + { + GlobalFree((HGLOBAL) DdeLparam->Value.Packed.uiHi); + DdeLparam->Value.Packed.uiHi = (UINT) h; + } + } + FreeDDElParam(UMMsg->message, UMMsg->lParam); + } + else + { + DdeLparam->Packed = FALSE; + DdeLparam->Value.Unpacked = UMMsg->lParam; + } + KMMsg->lParam = (LPARAM) DdeLparam; + } + break; + case WM_DDE_EXECUTE: + { + SIZE_T Size; + PKMDDEEXECUTEDATA KMDdeExecuteData; + PVOID Data; + + Size = GlobalSize((HGLOBAL) UMMsg->lParam); + Data = GlobalLock((HGLOBAL) UMMsg->lParam); + if (NULL == Data) + { + SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } + KMDdeExecuteData = HeapAlloc(GetProcessHeap(), 0, sizeof(KMDDEEXECUTEDATA) + Size); + if (NULL == KMDdeExecuteData) + { + SetLastError(ERROR_OUTOFMEMORY); + return FALSE; + } + KMDdeExecuteData->Sender = (HWND) UMMsg->wParam; + KMDdeExecuteData->ClientMem = (HGLOBAL) UMMsg->lParam; + memcpy((PVOID) (KMDdeExecuteData + 1), Data, Size); + KMMsg->wParam = sizeof(KMDDEEXECUTEDATA) + Size; + KMMsg->lParam = (LPARAM) KMDdeExecuteData; + GlobalUnlock((HGLOBAL) UMMsg->lParam); + } + break; + default: + break; + } + + return TRUE; } - -/* - * @unimplemented - */ -BOOL -STDCALL -InSendMessage(VOID) +static VOID FASTCALL +MsgiUMToKMCleanup(PMSG UMMsg, PMSG KMMsg) { - /* return(NtUserGetThreadState(THREADSTATE_INSENDMESSAGE) != ISMEX_NOSEND); */ - UNIMPLEMENTED; - return FALSE; + switch (KMMsg->message) + { + case WM_DDE_ACK: + case WM_DDE_EXECUTE: + HeapFree(GetProcessHeap(), 0, (LPVOID) KMMsg->lParam); + break; + default: + break; + } + + return; } - -/* - * @unimplemented - */ -DWORD -STDCALL -InSendMessageEx( - LPVOID lpReserved) +static BOOL FASTCALL +MsgiUMToKMReply(PMSG UMMsg, PMSG KMMsg, LRESULT *Result) { - /* return NtUserGetThreadState(THREADSTATE_INSENDMESSAGE); */ - UNIMPLEMENTED; - return 0; + MsgiUMToKMCleanup(UMMsg, KMMsg); + + return TRUE; } - -/* - * @unimplemented - */ -BOOL -STDCALL -ReplyMessage( - LRESULT lResult) +static BOOL FASTCALL +MsgiKMToUMMessage(PMSG KMMsg, PMSG UMMsg) { - UNIMPLEMENTED; - return FALSE; + *UMMsg = *KMMsg; + + switch (UMMsg->message) + { + case WM_DDE_ACK: + { + PKMDDELPARAM DdeLparam = (PKMDDELPARAM) KMMsg->lParam; + if (DdeLparam->Packed) + { + UMMsg->lParam = PackDDElParam(KMMsg->message, + DdeLparam->Value.Packed.uiLo, + DdeLparam->Value.Packed.uiHi); + } + else + { + UMMsg->lParam = DdeLparam->Value.Unpacked; + } + break; + } + case WM_DDE_EXECUTE: + { + PKMDDEEXECUTEDATA KMDdeExecuteData; + HGLOBAL GlobalData; + PVOID Data; + + KMDdeExecuteData = (PKMDDEEXECUTEDATA) KMMsg->lParam; + GlobalData = GlobalAlloc(GMEM_MOVEABLE, KMMsg->wParam - sizeof(KMDDEEXECUTEDATA)); + if (NULL == GlobalData) + { + return FALSE; + } + Data = GlobalLock(GlobalData); + if (NULL == Data) + { + GlobalFree(GlobalData); + return FALSE; + } + memcpy(Data, (PVOID) (KMDdeExecuteData + 1), KMMsg->wParam - sizeof(KMDDEEXECUTEDATA)); + GlobalUnlock(GlobalData); + if (! DdeAddPair(KMDdeExecuteData->ClientMem, GlobalData)) + { + GlobalFree(GlobalData); + return FALSE; + } + UMMsg->wParam = (WPARAM) KMDdeExecuteData->Sender; + UMMsg->lParam = (LPARAM) GlobalData; + } + break; + default: + break; + } + + return TRUE; } - -/* - * @implemented - */ -LPARAM -STDCALL -SetMessageExtraInfo( - LPARAM lParam) +static VOID FASTCALL +MsgiKMToUMCleanup(PMSG KMMsg, PMSG UMMsg) { - return NtUserSetMessageExtraInfo(lParam); + switch (KMMsg->message) + { + case WM_DDE_EXECUTE: +#ifdef TODO + HeapFree(GetProcessHeap(), 0, (LPVOID) KMMsg->lParam); + GlobalUnlock((HGLOBAL) UMMsg->lParam); +#endif + break; + default: + break; + } + + return; } +static BOOL FASTCALL +MsgiKMToUMReply(PMSG KMMsg, PMSG UMMsg, LRESULT *Result) +{ + MsgiKMToUMCleanup(KMMsg, UMMsg); -BOOL + return TRUE; +} + +static BOOL FASTCALL MsgiAnsiToUnicodeMessage(LPMSG UnicodeMsg, LPMSG AnsiMsg) { *UnicodeMsg = *AnsiMsg; @@ -196,7 +429,7 @@ MsgiAnsiToUnicodeMessage(LPMSG UnicodeMsg, LPMSG AnsiMsg) } -BOOL +static BOOL FASTCALL MsgiAnsiToUnicodeCleanup(LPMSG UnicodeMsg, LPMSG AnsiMsg) { switch (AnsiMsg->message) @@ -269,7 +502,7 @@ MsgiAnsiToUnicodeCleanup(LPMSG UnicodeMsg, LPMSG AnsiMsg) } -BOOL +static BOOL FASTCALL MsgiAnsiToUnicodeReply(LPMSG UnicodeMsg, LPMSG AnsiMsg, LRESULT *Result) { switch (AnsiMsg->message) @@ -304,104 +537,341 @@ MsgiAnsiToUnicodeReply(LPMSG UnicodeMsg, LPMSG AnsiMsg, LRESULT *Result) } -VOID STATIC -User32ConvertToAsciiMessage(UINT* Msg, WPARAM* wParam, LPARAM* lParam) +static BOOL FASTCALL +MsgiUnicodeToAnsiMessage(LPMSG AnsiMsg, LPMSG UnicodeMsg) { - switch((*Msg)) + *AnsiMsg = *UnicodeMsg; + + switch(UnicodeMsg->message) { - case WM_CREATE: - case WM_NCCREATE: - { - CREATESTRUCTA* CsA; - CREATESTRUCTW* CsW; - UNICODE_STRING UString; - ANSI_STRING AString; + case WM_CREATE: + case WM_NCCREATE: + { + CREATESTRUCTA* CsA; + CREATESTRUCTW* CsW; + UNICODE_STRING UString; + ANSI_STRING AString; + NTSTATUS Status; - CsW = (CREATESTRUCTW*)(*lParam); - CsA = RtlAllocateHeap(GetProcessHeap(), 0, sizeof(CREATESTRUCTA)); - memcpy(CsA, CsW, sizeof(CREATESTRUCTW)); + CsW = (CREATESTRUCTW*)(UnicodeMsg->lParam); + CsA = RtlAllocateHeap(GetProcessHeap(), 0, sizeof(CREATESTRUCTA)); + if (NULL == CsA) + { + return FALSE; + } + memcpy(CsA, CsW, sizeof(CREATESTRUCTW)); - RtlInitUnicodeString(&UString, CsW->lpszName); - RtlUnicodeStringToAnsiString(&AString, &UString, TRUE); - CsA->lpszName = AString.Buffer; - if (HIWORD((ULONG)CsW->lpszClass) != 0) - { - RtlInitUnicodeString(&UString, CsW->lpszClass); - RtlUnicodeStringToAnsiString(&AString, &UString, TRUE); - CsA->lpszClass = AString.Buffer; - } - (*lParam) = (LPARAM)CsA; - break; - } - case WM_SETTEXT: - { - ANSI_STRING AnsiString; - UNICODE_STRING UnicodeString; - RtlInitUnicodeString(&UnicodeString, (PWSTR) *lParam); - if (NT_SUCCESS(RtlUnicodeStringToAnsiString(&AnsiString, - &UnicodeString, - TRUE))) - { - *lParam = (LPARAM) AnsiString.Buffer; - } - break; - } + RtlInitUnicodeString(&UString, CsW->lpszName); + Status = RtlUnicodeStringToAnsiString(&AString, &UString, TRUE); + if (! NT_SUCCESS(Status)) + { + RtlFreeHeap(GetProcessHeap(), 0, CsA); + return FALSE; + } + CsA->lpszName = AString.Buffer; + if (HIWORD((ULONG)CsW->lpszClass) != 0) + { + RtlInitUnicodeString(&UString, CsW->lpszClass); + Status = RtlUnicodeStringToAnsiString(&AString, &UString, TRUE); + if (! NT_SUCCESS(Status)) + { + RtlInitAnsiString(&AString, CsA->lpszName); + RtlFreeAnsiString(&AString); + RtlFreeHeap(GetProcessHeap(), 0, CsA); + return FALSE; + } + CsA->lpszClass = AString.Buffer; + } + UnicodeMsg->lParam = (LPARAM)CsA; + break; + } + case WM_SETTEXT: + { + ANSI_STRING AnsiString; + UNICODE_STRING UnicodeString; + RtlInitUnicodeString(&UnicodeString, (PWSTR) UnicodeMsg->lParam); + if (! NT_SUCCESS(RtlUnicodeStringToAnsiString(&AnsiString, + &UnicodeString, + TRUE))) + { + return FALSE; + } + AnsiMsg->lParam = (LPARAM) AnsiString.Buffer; + break; + } } + + return TRUE; } -VOID STATIC -User32FreeAsciiConvertedMessage(UINT Msg, WPARAM wParam, LPARAM lParam) +static BOOL FASTCALL +MsgiUnicodeToAnsiCleanup(LPMSG AnsiMsg, LPMSG UnicodeMsg) { - switch(Msg) + switch(UnicodeMsg->message) + { + case WM_GETTEXT: + case WM_SETTEXT: + { + ANSI_STRING AString; + RtlInitAnsiString(&AString, (PSTR) AnsiMsg->lParam); + RtlFreeAnsiString(&AString); + break; + } + case WM_CREATE: + case WM_NCCREATE: + { + CREATESTRUCTA* Cs; + ANSI_STRING AString; + + Cs = (CREATESTRUCTA*) AnsiMsg->lParam; + RtlInitAnsiString(&AString, Cs->lpszName); + RtlFreeAnsiString(&AString); + if (HIWORD((ULONG)Cs->lpszClass) != 0) + { + RtlInitAnsiString(&AString, Cs->lpszClass); + RtlFreeAnsiString(&AString); + } + RtlFreeHeap(GetProcessHeap(), 0, Cs); + break; + } + } + + return TRUE; +} + + +static BOOL FASTCALL +MsgiUnicodeToAnsiReply(LPMSG AnsiMsg, LPMSG UnicodeMsg, LRESULT *Result) +{ + switch (UnicodeMsg->message) { case WM_GETTEXT: + case WM_ASKCBFORMATNAME: { - ANSI_STRING AnsiString; - UNICODE_STRING UnicodeString; - LPSTR TempString; - LPSTR InString; - InString = (LPSTR)lParam; - TempString = RtlAllocateHeap(GetProcessHeap(), 0, strlen(InString) + 1); - strcpy(TempString, InString); - RtlInitAnsiString(&AnsiString, TempString); - UnicodeString.Length = wParam * sizeof(WCHAR); - UnicodeString.MaximumLength = wParam * sizeof(WCHAR); - UnicodeString.Buffer = (PWSTR)lParam; - if (! NT_SUCCESS(RtlAnsiStringToUnicodeString(&UnicodeString, - &AnsiString, - FALSE))) - { - if (1 <= wParam) - { - UnicodeString.Buffer[0] = L'\0'; - } - } - RtlFreeHeap(GetProcessHeap(), 0, TempString); - break; + LPSTR Buffer = (LPSTR) AnsiMsg->lParam; + LPWSTR UBuffer = (LPWSTR) UnicodeMsg->lParam; + if (0 < AnsiMsg->wParam && + ! MultiByteToWideChar(CP_ACP, 0, Buffer, -1, UBuffer, UnicodeMsg->wParam)) + { + UBuffer[AnsiMsg->wParam - 1] = L'\0'; + } + break; } - case WM_SETTEXT: - { - ANSI_STRING AnsiString; - RtlInitAnsiString(&AnsiString, (PSTR) lParam); - RtlFreeAnsiString(&AnsiString); - break; - } - case WM_CREATE: - case WM_NCCREATE: - { - CREATESTRUCTA* Cs; - Cs = (CREATESTRUCTA*)lParam; - RtlFreeHeap(GetProcessHeap(), 0, (LPSTR)Cs->lpszName); - if (HIWORD((ULONG)Cs->lpszClass) != 0) - { - RtlFreeHeap(GetProcessHeap(), 0, (LPSTR)Cs->lpszClass); - } - RtlFreeHeap(GetProcessHeap(), 0, Cs); - break; + case WM_GETTEXTLENGTH: + case CB_GETLBTEXTLEN: + case LB_GETTEXTLEN: + { + /* FIXME: There may be one DBCS char for each Unicode char */ + *Result /= sizeof(WCHAR); + break; } } + + MsgiUnicodeToAnsiCleanup(UnicodeMsg, AnsiMsg); + + return TRUE; +} + +typedef struct tagMSGCONVERSION +{ + BOOL InUse; + BOOL Ansi; + MSG KMMsg; + MSG UnicodeMsg; + MSG AnsiMsg; + PMSG FinalMsg; + ULONG 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 + */ +LPARAM +STDCALL +GetMessageExtraInfo(VOID) +{ + return (LPARAM)NtUserCallNoParam(NOPARAM_ROUTINE_GETMESSAGEEXTRAINFO); +} + + +/* + * @implemented + */ +DWORD +STDCALL +GetMessagePos(VOID) +{ + PUSER32_THREAD_DATA ThreadData = User32GetThreadData(); + return(MAKELONG(ThreadData->LastMessage.pt.x, ThreadData->LastMessage.pt.y)); +} + + +/* + * @implemented + */ +LONG STDCALL +GetMessageTime(VOID) +{ + PUSER32_THREAD_DATA ThreadData = User32GetThreadData(); + return(ThreadData->LastMessage.time); +} + + +/* + * @unimplemented + */ +BOOL +STDCALL +InSendMessage(VOID) +{ + /* return(NtUserGetThreadState(THREADSTATE_INSENDMESSAGE) != ISMEX_NOSEND); */ + UNIMPLEMENTED; + return FALSE; +} + + +/* + * @unimplemented + */ +DWORD +STDCALL +InSendMessageEx( + LPVOID lpReserved) +{ + /* return NtUserGetThreadState(THREADSTATE_INSENDMESSAGE); */ + UNIMPLEMENTED; + return 0; +} + + +/* + * @unimplemented + */ +BOOL +STDCALL +ReplyMessage( + LRESULT lResult) +{ + UNIMPLEMENTED; + return FALSE; +} + + +/* + * @implemented + */ +LPARAM +STDCALL +SetMessageExtraInfo( + LPARAM lParam) +{ + return NtUserSetMessageExtraInfo(lParam); } LRESULT FASTCALL @@ -412,13 +882,25 @@ IntCallWindowProcW(BOOL IsAnsiProc, WPARAM wParam, LPARAM lParam) { + MSG AnsiMsg; + MSG UnicodeMsg; LRESULT Result; if (IsAnsiProc) { - User32ConvertToAsciiMessage(&Msg, &wParam, &lParam); - Result = WndProc(hWnd, Msg, wParam, lParam); - User32FreeAsciiConvertedMessage(Msg, wParam, lParam); + UnicodeMsg.hwnd = hWnd; + UnicodeMsg.message = Msg; + UnicodeMsg.wParam = wParam; + UnicodeMsg.lParam = lParam; + if (! MsgiUnicodeToAnsiMessage(&AnsiMsg, &UnicodeMsg)) + { + return FALSE; + } + Result = WndProc(AnsiMsg.hwnd, AnsiMsg.message, AnsiMsg.wParam, AnsiMsg.lParam); + if (! MsgiUnicodeToAnsiReply(&AnsiMsg, &UnicodeMsg, &Result)) + { + return FALSE; + } return Result; } else @@ -525,7 +1007,21 @@ CallWindowProcW(WNDPROC lpPrevWndFunc, LRESULT STDCALL DispatchMessageA(CONST MSG *lpmsg) { - return(NtUserDispatchMessage(lpmsg)); + NTUSERDISPATCHMESSAGEINFO Info; + LRESULT Result; + + Info.Ansi = TRUE; + Info.Msg = *lpmsg; + Result = NtUserDispatchMessage(&Info); + if (! Info.HandledByKernel) + { + /* We need to send the message ourselves */ + Result = IntCallWindowProcA(Info.Ansi, Info.Proc, Info.Msg.hwnd, + Info.Msg.message, Info.Msg.wParam, Info.Msg.lParam); + } + MsgConversionCleanup(lpmsg, TRUE, TRUE, &Result); + + return Result; } @@ -535,7 +1031,21 @@ DispatchMessageA(CONST MSG *lpmsg) LRESULT STDCALL DispatchMessageW(CONST MSG *lpmsg) { - return(NtUserDispatchMessage((LPMSG)lpmsg)); + NTUSERDISPATCHMESSAGEINFO Info; + LRESULT Result; + + Info.Ansi = FALSE; + Info.Msg = *lpmsg; + Result = NtUserDispatchMessage(&Info); + if (! Info.HandledByKernel) + { + /* We need to send the message ourselves */ + Result = IntCallWindowProcW(Info.Ansi, Info.Proc, Info.Msg.hwnd, + Info.Msg.message, Info.Msg.wParam, Info.Msg.lParam); + } + MsgConversionCleanup(lpmsg, FALSE, TRUE, &Result); + + return Result; } @@ -549,14 +1059,38 @@ GetMessageA(LPMSG lpMsg, UINT wMsgFilterMax) { BOOL Res; + MSGCONVERSION Conversion; + NTUSERGETMESSAGEINFO Info; PUSER32_THREAD_DATA ThreadData = User32GetThreadData(); - Res = NtUserGetMessage(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax); + MsgConversionCleanup(lpMsg, TRUE, FALSE, NULL); + Res = NtUserGetMessage(&Info, 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; + } + *lpMsg = Conversion.AnsiMsg; + Conversion.Ansi = TRUE; + Conversion.FinalMsg = lpMsg; + MsgConversionAdd(&Conversion); if (Res && lpMsg->message != WM_PAINT && lpMsg->message != WM_QUIT) { - ThreadData->LastMessage = *lpMsg; + ThreadData->LastMessage = Info.Msg; } - return(Res); + + return Res; } @@ -570,14 +1104,33 @@ GetMessageW(LPMSG lpMsg, UINT wMsgFilterMax) { BOOL Res; + MSGCONVERSION Conversion; + NTUSERGETMESSAGEINFO Info; PUSER32_THREAD_DATA ThreadData = User32GetThreadData(); - Res = NtUserGetMessage(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax); + MsgConversionCleanup(lpMsg, FALSE, FALSE, NULL); + Res = NtUserGetMessage(&Info, 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; + } + *lpMsg = Conversion.UnicodeMsg; + Conversion.Ansi = FALSE; + Conversion.FinalMsg = lpMsg; + MsgConversionAdd(&Conversion); if (Res && lpMsg->message != WM_PAINT && lpMsg->message != WM_QUIT) { - ThreadData->LastMessage = *lpMsg; + ThreadData->LastMessage = Info.Msg; } - return(Res); + + return Res; } @@ -592,14 +1145,38 @@ PeekMessageA(LPMSG lpMsg, UINT wRemoveMsg) { BOOL Res; + MSGCONVERSION Conversion; + NTUSERGETMESSAGEINFO Info; PUSER32_THREAD_DATA ThreadData = User32GetThreadData(); - Res = NtUserPeekMessage(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg); + MsgConversionCleanup(lpMsg, TRUE, FALSE, NULL); + Res = NtUserPeekMessage(&Info, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg); + if (-1 == (int) Res || ! 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; + } + *lpMsg = Conversion.AnsiMsg; + Conversion.Ansi = TRUE; + Conversion.FinalMsg = lpMsg; + MsgConversionAdd(&Conversion); if (Res && lpMsg->message != WM_PAINT && lpMsg->message != WM_QUIT) { - ThreadData->LastMessage = *lpMsg; + ThreadData->LastMessage = Info.Msg; } - return(Res); + + return Res; } @@ -616,14 +1193,33 @@ PeekMessageW( UINT wRemoveMsg) { BOOL Res; + MSGCONVERSION Conversion; + NTUSERGETMESSAGEINFO Info; PUSER32_THREAD_DATA ThreadData = User32GetThreadData(); - - Res = NtUserPeekMessage(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg); + + MsgConversionCleanup(lpMsg, FALSE, FALSE, NULL); + Res = NtUserPeekMessage(&Info, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg); + if (-1 == (int) Res || ! Res) + { + return Res; + } + Conversion.LParamSize = Info.LParamSize; + Conversion.KMMsg = Info.Msg; + + if (! MsgiKMToUMMessage(&Conversion.KMMsg, &Conversion.UnicodeMsg)) + { + return (BOOL) -1; + } + *lpMsg = Conversion.UnicodeMsg; + Conversion.Ansi = FALSE; + Conversion.FinalMsg = lpMsg; + MsgConversionAdd(&Conversion); if (Res && lpMsg->message != WM_PAINT && lpMsg->message != WM_QUIT) { - ThreadData->LastMessage = *lpMsg; + ThreadData->LastMessage = Info.Msg; } - return(Res); + + return Res; } @@ -633,12 +1229,35 @@ PeekMessageW( BOOL STDCALL PostMessageA( - HWND hWnd, + HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam) { - return NtUserPostMessage(hWnd, Msg, wParam, lParam); + MSG AnsiMsg, UcMsg; + MSG KMMsg; + LRESULT Result; + + AnsiMsg.hwnd = Wnd; + AnsiMsg.message = Msg; + AnsiMsg.wParam = wParam; + AnsiMsg.lParam = lParam; + if (! MsgiAnsiToUnicodeMessage(&UcMsg, &AnsiMsg)) + { + return FALSE; + } + + if (! MsgiUMToKMMessage(&UcMsg, &KMMsg, TRUE)) + { + MsgiAnsiToUnicodeCleanup(&UcMsg, &AnsiMsg); + return FALSE; + } + Result = NtUserPostMessage(KMMsg.hwnd, KMMsg.message, + KMMsg.wParam, KMMsg.lParam); + MsgiUMToKMCleanup(&UcMsg, &KMMsg); + MsgiAnsiToUnicodeCleanup(&UcMsg, &AnsiMsg); + + return Result; } @@ -648,12 +1267,27 @@ PostMessageA( BOOL STDCALL PostMessageW( - HWND hWnd, + HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam) { - return NtUserPostMessage(hWnd, Msg, wParam, 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(KMMsg.hwnd, KMMsg.message, + KMMsg.wParam, KMMsg.lParam); + MsgiUMToKMCleanup(&UMMsg, &KMMsg); + + return Result; } @@ -708,15 +1342,31 @@ SendMessageW(HWND Wnd, WPARAM wParam, LPARAM lParam) { + MSG UMMsg, KMMsg; NTUSERSENDMESSAGEINFO Info; LRESULT Result; + UMMsg.hwnd = Wnd; + UMMsg.message = Msg; + UMMsg.wParam = wParam; + UMMsg.lParam = lParam; + if (! MsgiUMToKMMessage(&UMMsg, &KMMsg, FALSE)) + { + return FALSE; + } Info.Ansi = FALSE; - Result = NtUserSendMessage(Wnd, Msg, wParam, lParam, &Info); + Result = NtUserSendMessage(KMMsg.hwnd, KMMsg.message, + KMMsg.wParam, KMMsg.lParam, &Info); if (! Info.HandledByKernel) { + MsgiUMToKMCleanup(&UMMsg, &KMMsg); /* We need to send the message ourselves */ - Result = IntCallWindowProcW(Info.Ansi, Info.Proc, Wnd, Msg, wParam, lParam); + Result = IntCallWindowProcW(Info.Ansi, Info.Proc, UMMsg.hwnd, UMMsg.message, + UMMsg.wParam, UMMsg.lParam); + } + else if (! MsgiUMToKMReply(&UMMsg, &KMMsg, &Result)) + { + return FALSE; } return Result; @@ -729,8 +1379,8 @@ SendMessageW(HWND Wnd, LRESULT STDCALL SendMessageA(HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam) { - MSG AnsiMsg; - MSG UcMsg; + MSG AnsiMsg, UcMsg; + MSG KMMsg; LRESULT Result; NTUSERSENDMESSAGEINFO Info; @@ -743,9 +1393,14 @@ SendMessageA(HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam) return FALSE; } + if (! MsgiUMToKMMessage(&UcMsg, &KMMsg, FALSE)) + { + MsgiAnsiToUnicodeCleanup(&UcMsg, &AnsiMsg); + return FALSE; + } Info.Ansi = TRUE; - Result = NtUserSendMessage(UcMsg.hwnd, UcMsg.message, - UcMsg.wParam, UcMsg.lParam, &Info); + Result = NtUserSendMessage(KMMsg.hwnd, KMMsg.message, + KMMsg.wParam, KMMsg.lParam, &Info); if (! Info.HandledByKernel) { /* We need to send the message ourselves */ @@ -753,6 +1408,7 @@ SendMessageA(HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam) { /* Ansi message and Ansi window proc, that's easy. Clean up the Unicode message though */ + MsgiUMToKMCleanup(&UcMsg, &KMMsg); MsgiAnsiToUnicodeCleanup(&UcMsg, &AnsiMsg); Result = IntCallWindowProcA(Info.Ansi, Info.Proc, Wnd, Msg, wParam, lParam); } @@ -769,13 +1425,11 @@ SendMessageA(HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam) } } } - else + /* Message sent by kernel. Convert back to Ansi */ + else if (! MsgiUMToKMReply(&UcMsg, &KMMsg, &Result) || + ! MsgiAnsiToUnicodeReply(&UcMsg, &AnsiMsg, &Result)) { - /* Message sent by kernel. Convert back to Ansi */ - if (! MsgiAnsiToUnicodeReply(&UcMsg, &AnsiMsg, &Result)) - { - return FALSE; - } + return FALSE; } return Result; @@ -1109,6 +1763,63 @@ BOOL STDCALL GetInputState(VOID) return wake_bits & (QS_KEY | QS_MOUSEBUTTON); } + +NTSTATUS STDCALL +User32CallWindowProcFromKernel(PVOID Arguments, ULONG ArgumentLength) +{ + PWINDOWPROC_CALLBACK_ARGUMENTS CallbackArgs; + MSG KMMsg, UMMsg; + + /* Make sure we don't try to access mem beyond what we were given */ + if (ArgumentLength < sizeof(WINDOWPROC_CALLBACK_ARGUMENTS)) + { + return STATUS_INFO_LENGTH_MISMATCH; + } + + CallbackArgs = (PWINDOWPROC_CALLBACK_ARGUMENTS) Arguments; + KMMsg.hwnd = CallbackArgs->Wnd; + KMMsg.message = CallbackArgs->Msg; + KMMsg.wParam = CallbackArgs->wParam; + /* Check if lParam is really a pointer and adjust it if it is */ + if (0 <= CallbackArgs->lParamBufferSize) + { + if (ArgumentLength != sizeof(WINDOWPROC_CALLBACK_ARGUMENTS) + + CallbackArgs->lParamBufferSize) + { + return STATUS_INFO_LENGTH_MISMATCH; + } + KMMsg.lParam = (LPARAM) ((char *) CallbackArgs + sizeof(WINDOWPROC_CALLBACK_ARGUMENTS)); + } + else + { + if (ArgumentLength != sizeof(WINDOWPROC_CALLBACK_ARGUMENTS)) + { + return STATUS_INFO_LENGTH_MISMATCH; + } + KMMsg.lParam = CallbackArgs->lParam; + } + + if (WM_NCCALCSIZE == CallbackArgs->Msg && CallbackArgs->wParam) + { + NCCALCSIZE_PARAMS *Params = (NCCALCSIZE_PARAMS *) KMMsg.lParam; + Params->lppos = (PWINDOWPOS) (Params + 1); + } + + if (! MsgiKMToUMMessage(&KMMsg, &UMMsg)) + { + } + + CallbackArgs->Result = IntCallWindowProcW(CallbackArgs->IsAnsiProc, CallbackArgs->Proc, + UMMsg.hwnd, UMMsg.message, + UMMsg.wParam, UMMsg.lParam); + + if (! MsgiKMToUMReply(&KMMsg, &UMMsg, &CallbackArgs->Result)) + { + } + + return ZwCallbackReturn(CallbackArgs, ArgumentLength, STATUS_SUCCESS); +} + /* * @implemented */ @@ -1240,3 +1951,11 @@ DWORD WINAPI MsgWaitForMultipleObjectsEx(DWORD nCount, CONST HANDLE *lpHandles, { return IsInsideMessagePumpHook() ? gmph.RealMsgWaitForMultipleObjectsEx(nCount, lpHandles, dwMilliseconds, dwWakeMask, dwFlags) : RealMsgWaitForMultipleObjectsEx(nCount, lpHandles,dwMilliseconds, dwWakeMask, dwFlags); } + +BOOL FASTCALL MessageInit() +{ + InitializeCriticalSection(&DdeCrst); + InitializeCriticalSection(&MsgConversionCrst); + + return TRUE; +} diff --git a/reactos/lib/user32/windows/window.c b/reactos/lib/user32/windows/window.c index 4a6a091189f..b7960e125cc 100644 --- a/reactos/lib/user32/windows/window.c +++ b/reactos/lib/user32/windows/window.c @@ -1,4 +1,4 @@ -/* $Id: window.c,v 1.112 2004/04/15 23:36:02 weiden Exp $ +/* $Id: window.c,v 1.113 2004/04/29 21:13:16 gvg Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS user32.dll @@ -48,53 +48,6 @@ User32CallSendAsyncProcForKernel(PVOID Arguments, ULONG ArgumentLength) } -NTSTATUS STDCALL -User32CallWindowProcFromKernel(PVOID Arguments, ULONG ArgumentLength) -{ - PWINDOWPROC_CALLBACK_ARGUMENTS CallbackArgs; - LPARAM lParam; - - /* Make sure we don't try to access mem beyond what we were given */ - if (ArgumentLength < sizeof(WINDOWPROC_CALLBACK_ARGUMENTS)) - { - return STATUS_INFO_LENGTH_MISMATCH; - } - - CallbackArgs = (PWINDOWPROC_CALLBACK_ARGUMENTS) Arguments; - /* Check if lParam is really a pointer and adjust it if it is */ - if (0 <= CallbackArgs->lParamBufferSize) - { - if (ArgumentLength != sizeof(WINDOWPROC_CALLBACK_ARGUMENTS) - + CallbackArgs->lParamBufferSize) - { - return STATUS_INFO_LENGTH_MISMATCH; - } - lParam = (LPARAM) ((char *) CallbackArgs + sizeof(WINDOWPROC_CALLBACK_ARGUMENTS)); - } - else - { - if (ArgumentLength != sizeof(WINDOWPROC_CALLBACK_ARGUMENTS)) - { - return STATUS_INFO_LENGTH_MISMATCH; - } - lParam = CallbackArgs->lParam; - } - - if (WM_NCCALCSIZE == CallbackArgs->Msg && CallbackArgs->wParam) - { - NCCALCSIZE_PARAMS *Params = (NCCALCSIZE_PARAMS *) lParam; - Params->lppos = (PWINDOWPOS) (Params + 1); - } - - - CallbackArgs->Result = IntCallWindowProcW(CallbackArgs->IsAnsiProc, CallbackArgs->Proc, - CallbackArgs->Wnd, CallbackArgs->Msg, - CallbackArgs->wParam, lParam); - - return ZwCallbackReturn(CallbackArgs, ArgumentLength, STATUS_SUCCESS); -} - - /* * @unimplemented */ diff --git a/reactos/subsys/win32k/include/msgqueue.h b/reactos/subsys/win32k/include/msgqueue.h index bc9f77a43d7..7c0bbc833bb 100644 --- a/reactos/subsys/win32k/include/msgqueue.h +++ b/reactos/subsys/win32k/include/msgqueue.h @@ -11,6 +11,7 @@ typedef struct _USER_MESSAGE { LIST_ENTRY ListEntry; + BOOLEAN FreeLParam; MSG Msg; } USER_MESSAGE, *PUSER_MESSAGE; @@ -103,12 +104,12 @@ MsqSendMessage(PUSER_MESSAGE_QUEUE MessageQueue, HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam, UINT uTimeout, BOOL Block, ULONG_PTR *uResult); PUSER_MESSAGE FASTCALL -MsqCreateMessage(LPMSG Msg); +MsqCreateMessage(LPMSG Msg, BOOLEAN FreeLParam); VOID FASTCALL MsqDestroyMessage(PUSER_MESSAGE Message); VOID FASTCALL MsqPostMessage(PUSER_MESSAGE_QUEUE MessageQueue, - MSG* Msg); + MSG* Msg, BOOLEAN FreeLParam); VOID FASTCALL MsqPostQuitMessage(PUSER_MESSAGE_QUEUE MessageQueue, ULONG ExitCode); BOOLEAN STDCALL diff --git a/reactos/subsys/win32k/include/painting.h b/reactos/subsys/win32k/include/painting.h index 1c01747c965..bba8478866b 100644 --- a/reactos/subsys/win32k/include/painting.h +++ b/reactos/subsys/win32k/include/painting.h @@ -12,7 +12,8 @@ IntValidateParent(PWINDOW_OBJECT Child, HRGN ValidRegion); BOOL FASTCALL IntRedrawWindow(PWINDOW_OBJECT Wnd, const RECT* UpdateRect, HRGN UpdateRgn, ULONG Flags); BOOL FASTCALL -IntGetPaintMessage(HWND hWnd, PW32THREAD Thread, MSG *Message, BOOL Remove); +IntGetPaintMessage(HWND hWnd, UINT MsgFilterMin, UINT MsgFilterMax, PW32THREAD Thread, + MSG *Message, BOOL Remove); BOOL STDCALL NtUserValidateRgn(HWND hWnd, HRGN hRgn); diff --git a/reactos/subsys/win32k/ntuser/keyboard.c b/reactos/subsys/win32k/ntuser/keyboard.c index b919e8a4f43..8c2fa92b50a 100644 --- a/reactos/subsys/win32k/ntuser/keyboard.c +++ b/reactos/subsys/win32k/ntuser/keyboard.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: keyboard.c,v 1.27 2004/03/15 19:06:35 dwelch Exp $ +/* $Id: keyboard.c,v 1.28 2004/04/29 21:13:16 gvg Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -659,14 +659,14 @@ IntTranslateKbdMessage(LPMSG lpMsg, NewMsg.wParam = dead_char; NewMsg.lParam = lpMsg->lParam; dead_char = 0; - MsqPostMessage(PsGetWin32Thread()->MessageQueue, &NewMsg); + MsqPostMessage(PsGetWin32Thread()->MessageQueue, &NewMsg, FALSE); } NewMsg.hwnd = lpMsg->hwnd; NewMsg.wParam = wp[0]; NewMsg.lParam = lpMsg->lParam; DPRINT( "CHAR='%c' %04x %08x\n", wp[0], wp[0], lpMsg->lParam ); - MsqPostMessage(PsGetWin32Thread()->MessageQueue, &NewMsg); + MsqPostMessage(PsGetWin32Thread()->MessageQueue, &NewMsg, FALSE); Result = TRUE; } else if (UState == -1) @@ -677,7 +677,7 @@ IntTranslateKbdMessage(LPMSG lpMsg, NewMsg.wParam = wp[0]; NewMsg.lParam = lpMsg->lParam; dead_char = wp[0]; - MsqPostMessage(PsGetWin32Thread()->MessageQueue, &NewMsg); + MsqPostMessage(PsGetWin32Thread()->MessageQueue, &NewMsg, FALSE); Result = TRUE; } diff --git a/reactos/subsys/win32k/ntuser/message.c b/reactos/subsys/win32k/ntuser/message.c index 0326fff7e56..1ba5935b310 100644 --- a/reactos/subsys/win32k/ntuser/message.c +++ b/reactos/subsys/win32k/ntuser/message.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: message.c,v 1.59 2004/04/15 23:36:03 weiden Exp $ +/* $Id: message.c,v 1.60 2004/04/29 21:13:16 gvg Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -70,91 +70,242 @@ IntCleanupMessageImpl(VOID) return STATUS_SUCCESS; } -LRESULT FASTCALL -IntDispatchMessage(MSG* Msg) -{ - LRESULT Result; - PWINDOW_OBJECT WindowObject; - /* Process timer messages. */ - if (Msg->message == WM_TIMER) - { - if (Msg->lParam) - { - LARGE_INTEGER LargeTickCount; - /* FIXME: Call hooks. */ - - /* FIXME: Check for continuing validity of timer. */ - - KeQueryTickCount(&LargeTickCount); - return IntCallWindowProc((WNDPROC)Msg->lParam, - FALSE, - Msg->hwnd, - Msg->message, - Msg->wParam, - (LPARAM)LargeTickCount.u.LowPart, - -1); - } - } - - if( Msg->hwnd == 0 ) return 0; - - /* Get the window object. */ - WindowObject = IntGetWindowObject(Msg->hwnd); - if(!WindowObject) - { - SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE); - return 0; - } - if(WindowObject->OwnerThread != PsGetCurrentThread()) +#define MMS_SIZE_WPARAM -1 +#define MMS_SIZE_WPARAMWCHAR -2 +#define MMS_SIZE_LPARAMSZ -3 +#define MMS_SIZE_SPECIAL -4 +#define MMS_FLAG_READ 0x01 +#define MMS_FLAG_WRITE 0x02 +#define MMS_FLAG_READWRITE (MMS_FLAG_READ | MMS_FLAG_WRITE) +typedef struct tagMSGMEMORY { - IntReleaseWindowObject(WindowObject); - DPRINT1("Window doesn't belong to the calling thread!\n"); - return 0; - } - /* FIXME: Call hook procedures. */ + UINT Message; + UINT Size; + INT Flags; + } MSGMEMORY, *PMSGMEMORY; - /* Call the window procedure. */ - if (0xFFFF0000 != ((DWORD) WindowObject->WndProcW & 0xFFFF0000)) +static MSGMEMORY MsgMemory[] = + { + { WM_CREATE, sizeof(CREATESTRUCTW), MMS_FLAG_READWRITE }, + { WM_DDE_ACK, sizeof(KMDDELPARAM), MMS_FLAG_READ }, + { WM_DDE_EXECUTE, MMS_SIZE_WPARAM, MMS_FLAG_READ }, + { WM_GETMINMAXINFO, sizeof(MINMAXINFO), MMS_FLAG_READWRITE }, + { WM_GETTEXT, MMS_SIZE_WPARAMWCHAR, MMS_FLAG_WRITE }, + { WM_NCCALCSIZE, MMS_SIZE_SPECIAL, MMS_FLAG_READWRITE }, + { WM_NCCREATE, sizeof(CREATESTRUCTW), MMS_FLAG_READWRITE }, + { WM_SETTEXT, MMS_SIZE_LPARAMSZ, MMS_FLAG_READ }, + { WM_STYLECHANGED, sizeof(STYLESTRUCT), MMS_FLAG_READ }, + { WM_STYLECHANGING, sizeof(STYLESTRUCT), MMS_FLAG_READWRITE }, + { WM_WINDOWPOSCHANGED, sizeof(WINDOWPOS), MMS_FLAG_READ }, + { WM_WINDOWPOSCHANGING, sizeof(WINDOWPOS), MMS_FLAG_READWRITE }, + }; + +static PMSGMEMORY FASTCALL +FindMsgMemory(UINT Msg) + { + PMSGMEMORY MsgMemoryEntry; + + /* See if this message type is present in the table */ + for (MsgMemoryEntry = MsgMemory; + MsgMemoryEntry < MsgMemory + sizeof(MsgMemory) / sizeof(MSGMEMORY); + MsgMemoryEntry++) { - Result = IntCallWindowProc(WindowObject->WndProcW, - FALSE, - Msg->hwnd, - Msg->message, - Msg->wParam, - Msg->lParam, - -1); + if (Msg == MsgMemoryEntry->Message) + { + return MsgMemoryEntry; + } + } + + return NULL; +} + +static UINT FASTCALL +MsgMemorySize(PMSGMEMORY MsgMemoryEntry, WPARAM wParam, LPARAM lParam) +{ + if (MMS_SIZE_WPARAM == MsgMemoryEntry->Size) + { + return (UINT) wParam; + } + else if (MMS_SIZE_WPARAMWCHAR == MsgMemoryEntry->Size) + { + return (UINT) (wParam * sizeof(WCHAR)); + } + else if (MMS_SIZE_LPARAMSZ == MsgMemoryEntry->Size) + { + return (UINT) ((wcslen((PWSTR) lParam) + 1) * sizeof(WCHAR)); + } + else if (MMS_SIZE_SPECIAL == MsgMemoryEntry->Size) + { + switch(MsgMemoryEntry->Message) + { + case WM_NCCALCSIZE: + return wParam ? sizeof(NCCALCSIZE_PARAMS) + sizeof(WINDOWPOS) : sizeof(RECT); + break; + default: + assert(FALSE); + return 0; + break; + } } else { - Result = IntCallWindowProc(WindowObject->WndProcA, - TRUE, - Msg->hwnd, - Msg->message, - Msg->wParam, - Msg->lParam, - -1); + return MsgMemoryEntry->Size; } - - IntReleaseWindowObject(WindowObject); - - return Result; +} + +static FASTCALL NTSTATUS +PackParam(LPARAM *lParamPacked, UINT Msg, WPARAM wParam, LPARAM lParam) +{ + NCCALCSIZE_PARAMS *UnpackedParams; + NCCALCSIZE_PARAMS *PackedParams; + + *lParamPacked = lParam; + if (WM_NCCALCSIZE == Msg && wParam) + { + UnpackedParams = (NCCALCSIZE_PARAMS *) lParam; + if (UnpackedParams->lppos != (PWINDOWPOS) (UnpackedParams + 1)) + { + PackedParams = ExAllocatePoolWithTag(PagedPool, + sizeof(NCCALCSIZE_PARAMS) + sizeof(WINDOWPOS), + TAG_MSG); + if (NULL == PackedParams) + { + DPRINT1("Not enough memory to pack lParam\n"); + return STATUS_NO_MEMORY; + } + RtlCopyMemory(PackedParams, UnpackedParams, sizeof(NCCALCSIZE_PARAMS)); + PackedParams->lppos = (PWINDOWPOS) (PackedParams + 1); + RtlCopyMemory(PackedParams->lppos, UnpackedParams->lppos, sizeof(WINDOWPOS)); + *lParamPacked = (LPARAM) PackedParams; + } + } + + return STATUS_SUCCESS; +} + +static FASTCALL NTSTATUS +UnpackParam(LPARAM lParamPacked, UINT Msg, WPARAM wParam, LPARAM lParam) +{ + NCCALCSIZE_PARAMS *UnpackedParams; + NCCALCSIZE_PARAMS *PackedParams; + PWINDOWPOS UnpackedWindowPos; + + if (lParamPacked == lParam) + { + return STATUS_SUCCESS; + } + + if (WM_NCCALCSIZE == Msg && wParam) + { + PackedParams = (NCCALCSIZE_PARAMS *) lParamPacked; + UnpackedParams = (NCCALCSIZE_PARAMS *) lParam; + UnpackedWindowPos = UnpackedParams->lppos; + RtlCopyMemory(UnpackedParams, PackedParams, sizeof(NCCALCSIZE_PARAMS)); + UnpackedParams->lppos = UnpackedWindowPos; + RtlCopyMemory(UnpackedWindowPos, PackedParams + 1, sizeof(WINDOWPOS)); + ExFreePool((PVOID) lParamPacked); + + return STATUS_SUCCESS; + } + + assert(FALSE); + + return STATUS_INVALID_PARAMETER; } LRESULT STDCALL -NtUserDispatchMessage(CONST MSG* UnsafeMsg) +NtUserDispatchMessage(PNTUSERDISPATCHMESSAGEINFO UnsafeMsgInfo) { NTSTATUS Status; - MSG Msg; + NTUSERDISPATCHMESSAGEINFO MsgInfo; + PWINDOW_OBJECT WindowObject; + LRESULT Result; - Status = MmCopyFromCaller(&Msg, (PVOID) UnsafeMsg, sizeof(MSG)); + Status = MmCopyFromCaller(&MsgInfo, UnsafeMsgInfo, sizeof(NTUSERDISPATCHMESSAGEINFO)); if (! NT_SUCCESS(Status)) { - SetLastNtError(Status); - return 0; + SetLastNtError(Status); + return 0; + } + + /* Process timer messages. */ + if (WM_TIMER == MsgInfo.Msg.message && 0 != MsgInfo.Msg.lParam) + { + LARGE_INTEGER LargeTickCount; + /* FIXME: Call hooks. */ + + /* FIXME: Check for continuing validity of timer. */ + + MsgInfo.HandledByKernel = FALSE; + KeQueryTickCount(&LargeTickCount); + MsgInfo.Proc = (WNDPROC) MsgInfo.Msg.lParam; + MsgInfo.Msg.lParam = (LPARAM)LargeTickCount.u.LowPart; + } + else if (NULL == MsgInfo.Msg.hwnd) + { + MsgInfo.HandledByKernel = TRUE; + Result = 0; + } + else + { + /* Get the window object. */ + WindowObject = IntGetWindowObject(MsgInfo.Msg.hwnd); + if (NULL == WindowObject) + { + SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE); + MsgInfo.HandledByKernel = TRUE; + Result = 0; + } + else + { + if (WindowObject->OwnerThread != PsGetCurrentThread()) + { + IntReleaseWindowObject(WindowObject); + DPRINT1("Window doesn't belong to the calling thread!\n"); + MsgInfo.HandledByKernel = TRUE; + Result = 0; + } + else + { + /* FIXME: Call hook procedures. */ + + MsgInfo.HandledByKernel = FALSE; + Result = 0; + if (0xFFFF0000 != ((DWORD) WindowObject->WndProcW & 0xFFFF0000)) + { + if (0xFFFF0000 != ((DWORD) WindowObject->WndProcA & 0xFFFF0000)) + { + /* Both Unicode and Ansi winprocs are real, use whatever + usermode prefers */ + MsgInfo.Proc = (MsgInfo.Ansi ? WindowObject->WndProcA + : WindowObject->WndProcW); + } + else + { + /* Real Unicode winproc */ + MsgInfo.Ansi = FALSE; + MsgInfo.Proc = WindowObject->WndProcW; + } + } + else + { + /* Must have real Ansi winproc */ + MsgInfo.Ansi = TRUE; + MsgInfo.Proc = WindowObject->WndProcA; + } + } + IntReleaseWindowObject(WindowObject); + } + } + Status = MmCopyToCaller(UnsafeMsgInfo, &MsgInfo, sizeof(NTUSERDISPATCHMESSAGEINFO)); + if (! NT_SUCCESS(Status)) + { + SetLastNtError(Status); + return 0; } - return IntDispatchMessage(&Msg); + return Result; } @@ -336,7 +487,7 @@ IntTranslateMouseMessage(PUSER_MESSAGE_QUEUE ThreadQueue, LPMSG Msg, USHORT *Hit * Internal version of PeekMessage() doing all the work */ BOOL FASTCALL -IntPeekMessage(LPMSG Msg, +IntPeekMessage(PUSER_MESSAGE Msg, HWND Wnd, UINT MsgFilterMin, UINT MsgFilterMax, @@ -372,10 +523,11 @@ IntPeekMessage(LPMSG Msg, { /* According to the PSDK, WM_QUIT messages are always returned, regardless of the filter specified */ - Msg->hwnd = NULL; - Msg->message = WM_QUIT; - Msg->wParam = ThreadQueue->QuitExitCode; - Msg->lParam = 0; + Msg->Msg.hwnd = NULL; + Msg->Msg.message = WM_QUIT; + Msg->Msg.wParam = ThreadQueue->QuitExitCode; + Msg->Msg.lParam = 0; + Msg->FreeLParam = FALSE; if (RemoveMessages) { ThreadQueue->QuitPosted = FALSE; @@ -393,7 +545,7 @@ IntPeekMessage(LPMSG Msg, &Message); if (Present) { - RtlCopyMemory(Msg, &Message->Msg, sizeof(MSG)); + RtlCopyMemory(Msg, Message, sizeof(USER_MESSAGE)); if (RemoveMessages) { MsqDestroyMessage(Message); @@ -411,7 +563,7 @@ IntPeekMessage(LPMSG Msg, &Message); if (Present) { - RtlCopyMemory(Msg, &Message->Msg, sizeof(MSG)); + RtlCopyMemory(Msg, Message, sizeof(USER_MESSAGE)); if (RemoveMessages) { MsqDestroyMessage(Message); @@ -423,8 +575,9 @@ IntPeekMessage(LPMSG Msg, while (MsqDispatchOneSentMessage(ThreadQueue)); /* Check for paint messages. */ - if (IntGetPaintMessage(Wnd, PsGetWin32Thread(), Msg, RemoveMessages)) + if (IntGetPaintMessage(Wnd, MsgFilterMin, MsgFilterMax, PsGetWin32Thread(), &Msg->Msg, RemoveMessages)) { + Msg->FreeLParam = FALSE; return TRUE; } @@ -438,12 +591,12 @@ IntPeekMessage(LPMSG Msg, { PWINDOW_OBJECT MsgWindow = NULL;; - if(Msg->hwnd && (MsgWindow = IntGetWindowObject(Msg->hwnd)) && - Msg->message >= WM_MOUSEFIRST && Msg->message <= WM_MOUSELAST) + if(Msg->Msg.hwnd && (MsgWindow = IntGetWindowObject(Msg->Msg.hwnd)) && + Msg->Msg.message >= WM_MOUSEFIRST && Msg->Msg.message <= WM_MOUSELAST) { USHORT HitTest; - if(IntTranslateMouseMessage(ThreadQueue, Msg, &HitTest, TRUE)) + if(IntTranslateMouseMessage(ThreadQueue, &Msg->Msg, &HitTest, TRUE)) /* FIXME - check message filter again, if the message doesn't match anymore, search again */ { @@ -453,10 +606,10 @@ IntPeekMessage(LPMSG Msg, } if(ThreadQueue->CaptureWindow == NULL) { - IntSendHitTestMessages(ThreadQueue, Msg); - if((Msg->message != WM_MOUSEMOVE && Msg->message != WM_NCMOUSEMOVE) && - IS_BTN_MESSAGE(Msg->message, DOWN) && - IntActivateWindowMouse(ThreadQueue, Msg, MsgWindow, &HitTest)) + IntSendHitTestMessages(ThreadQueue, &Msg->Msg); + if((Msg->Msg.message != WM_MOUSEMOVE && Msg->Msg.message != WM_NCMOUSEMOVE) && + IS_BTN_MESSAGE(Msg->Msg.message, DOWN) && + IntActivateWindowMouse(ThreadQueue, &Msg->Msg, MsgWindow, &HitTest)) { IntReleaseWindowObject(MsgWindow); /* eat the message, search again */ @@ -466,7 +619,7 @@ IntPeekMessage(LPMSG Msg, } else { - IntSendHitTestMessages(ThreadQueue, Msg); + IntSendHitTestMessages(ThreadQueue, &Msg->Msg); } if(MsgWindow) @@ -478,8 +631,8 @@ IntPeekMessage(LPMSG Msg, } USHORT HitTest; - if((Msg->hwnd && Msg->message >= WM_MOUSEFIRST && Msg->message <= WM_MOUSELAST) && - IntTranslateMouseMessage(ThreadQueue, Msg, &HitTest, FALSE)) + if((Msg->Msg.hwnd && Msg->Msg.message >= WM_MOUSEFIRST && Msg->Msg.message <= WM_MOUSELAST) && + IntTranslateMouseMessage(ThreadQueue, &Msg->Msg, &HitTest, FALSE)) /* FIXME - check message filter again, if the message doesn't match anymore, search again */ { @@ -494,43 +647,88 @@ IntPeekMessage(LPMSG Msg, } BOOL STDCALL -NtUserPeekMessage(LPMSG UnsafeMsg, +NtUserPeekMessage(PNTUSERGETMESSAGEINFO UnsafeInfo, HWND Wnd, UINT MsgFilterMin, UINT MsgFilterMax, UINT RemoveMsg) { - MSG SafeMsg; NTSTATUS Status; BOOL Present; + NTUSERGETMESSAGEINFO Info; PWINDOW_OBJECT Window; + PMSGMEMORY MsgMemoryEntry; + PVOID UserMem; + UINT Size; + USER_MESSAGE Msg; /* Validate input */ if (NULL != Wnd) { Window = IntGetWindowObject(Wnd); - if(!Window) - Wnd = NULL; + if (NULL == Window) + { + Wnd = NULL; + } else - IntReleaseWindowObject(Window); + { + IntReleaseWindowObject(Window); + } } + if (MsgFilterMax < MsgFilterMin) { MsgFilterMin = 0; MsgFilterMax = 0; } - Present = IntPeekMessage(&SafeMsg, Wnd, MsgFilterMin, MsgFilterMax, RemoveMsg); + Present = IntPeekMessage(&Msg, Wnd, MsgFilterMin, MsgFilterMax, RemoveMsg); if (Present) { - Status = MmCopyToCaller(UnsafeMsg, &SafeMsg, sizeof(MSG)); + 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)) - { - /* There is error return documented for PeekMessage(). - Do the best we can */ - SetLastNtError(Status); - return FALSE; - } + { + SetLastNtError(Status); + return (BOOL) -1; + } } return Present; @@ -543,7 +741,7 @@ IntWaitMessage(HWND Wnd, { PUSER_MESSAGE_QUEUE ThreadQueue; NTSTATUS Status; - MSG Msg; + USER_MESSAGE Msg; ThreadQueue = (PUSER_MESSAGE_QUEUE)PsGetWin32Thread()->MessageQueue; @@ -565,7 +763,7 @@ IntWaitMessage(HWND Wnd, } BOOL STDCALL -NtUserGetMessage(LPMSG UnsafeMsg, +NtUserGetMessage(PNTUSERGETMESSAGEINFO UnsafeInfo, HWND Wnd, UINT MsgFilterMin, UINT MsgFilterMax) @@ -581,9 +779,13 @@ NtUserGetMessage(LPMSG UnsafeMsg, */ { BOOL GotMessage; - MSG SafeMsg; + NTUSERGETMESSAGEINFO Info; NTSTATUS Status; PWINDOW_OBJECT Window; + PMSGMEMORY MsgMemoryEntry; + PVOID UserMem; + UINT Size; + USER_MESSAGE Msg; /* Validate input */ if (NULL != Wnd) @@ -602,10 +804,49 @@ NtUserGetMessage(LPMSG UnsafeMsg, do { - GotMessage = IntPeekMessage(&SafeMsg, Wnd, MsgFilterMin, MsgFilterMax, PM_REMOVE); + GotMessage = IntPeekMessage(&Msg, Wnd, MsgFilterMin, MsgFilterMax, PM_REMOVE); if (GotMessage) { - Status = MmCopyToCaller(UnsafeMsg, &SafeMsg, sizeof(MSG)); + 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); @@ -619,7 +860,7 @@ NtUserGetMessage(LPMSG UnsafeMsg, } while (! GotMessage); - return WM_QUIT != SafeMsg.message; + return WM_QUIT != Info.Msg.message; } DWORD @@ -638,21 +879,117 @@ NtUserMessageCall( 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 STDCALL -NtUserPostMessage(HWND hWnd, +NtUserPostMessage(HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam) { PWINDOW_OBJECT Window; - MSG Mesg; + MSG UserModeMsg, KernelModeMsg; LARGE_INTEGER LargeTickCount; + NTSTATUS Status; + PMSGMEMORY MsgMemoryEntry; if (WM_QUIT == Msg) { MsqPostQuitMessage(PsGetWin32Thread()->MessageQueue, wParam); } - else if (hWnd == HWND_BROADCAST) + else if (Wnd == HWND_BROADCAST) { HWND *List; PWINDOW_OBJECT DesktopWindow; @@ -670,21 +1007,30 @@ NtUserPostMessage(HWND hWnd, } else { - Window = IntGetWindowObject(hWnd); - if (!Window) + Window = IntGetWindowObject(Wnd); + if (NULL == Window) { - SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE); + SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE); return FALSE; } - Mesg.hwnd = hWnd; - Mesg.message = Msg; - Mesg.wParam = wParam; - Mesg.lParam = lParam; - Mesg.pt.x = PsGetWin32Process()->WindowStation->SystemCursor.x; - Mesg.pt.y = PsGetWin32Process()->WindowStation->SystemCursor.y; + + 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; + } + KernelModeMsg.pt.x = PsGetWin32Process()->WindowStation->SystemCursor.x; + KernelModeMsg.pt.y = PsGetWin32Process()->WindowStation->SystemCursor.y; KeQueryTickCount(&LargeTickCount); - Mesg.time = LargeTickCount.u.LowPart; - MsqPostMessage(Window->MessageQueue, &Mesg); + KernelModeMsg.time = LargeTickCount.u.LowPart; + MsqPostMessage(Window->MessageQueue, &KernelModeMsg, + NULL != MsgMemoryEntry && 0 != KernelModeMsg.lParam); IntReleaseWindowObject(Window); } @@ -697,11 +1043,11 @@ NtUserPostThreadMessage(DWORD idThread, WPARAM wParam, LPARAM lParam) { - MSG Mesg; - + MSG UserModeMsg, KernelModeMsg; PETHREAD peThread; PW32THREAD pThread; NTSTATUS Status; + PMSGMEMORY MsgMemoryEntry; Status = PsLookupThreadByThreadId((void *)idThread,&peThread); @@ -712,11 +1058,20 @@ NtUserPostThreadMessage(DWORD idThread, ObDereferenceObject( peThread ); return FALSE; } - Mesg.hwnd = 0; - Mesg.message = Msg; - Mesg.wParam = wParam; - Mesg.lParam = lParam; - MsqPostMessage(pThread->MessageQueue, &Mesg); + + 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)) + { + SetLastWin32Error(ERROR_INVALID_PARAMETER); + return FALSE; + } + MsqPostMessage(pThread->MessageQueue, &KernelModeMsg, + NULL != MsgMemoryEntry && 0 != KernelModeMsg.lParam); ObDereferenceObject( peThread ); return TRUE; } else { @@ -733,147 +1088,6 @@ NtUserQuerySendMessage(DWORD Unknown0) return 0; } -#define MMS_SIZE_WPARAM -1 -#define MMS_SIZE_WPARAMWCHAR -2 -#define MMS_SIZE_LPARAMSZ -3 -#define MMS_SIZE_SPECIAL -4 -#define MMS_FLAG_READ 0x01 -#define MMS_FLAG_WRITE 0x02 -#define MMS_FLAG_READWRITE (MMS_FLAG_READ | MMS_FLAG_WRITE) -typedef struct tagMSGMEMORY - { - UINT Message; - UINT Size; - INT Flags; - } MSGMEMORY, *PMSGMEMORY; - -static MSGMEMORY MsgMemory[] = - { - { WM_CREATE, sizeof(CREATESTRUCTW), MMS_FLAG_READWRITE }, - { WM_GETMINMAXINFO, sizeof(MINMAXINFO), MMS_FLAG_READWRITE }, - { WM_GETTEXT, MMS_SIZE_WPARAMWCHAR, MMS_FLAG_WRITE }, - { WM_NCCALCSIZE, MMS_SIZE_SPECIAL, MMS_FLAG_READWRITE }, - { WM_NCCREATE, sizeof(CREATESTRUCTW), MMS_FLAG_READWRITE }, - { WM_SETTEXT, MMS_SIZE_LPARAMSZ, MMS_FLAG_READ }, - { WM_STYLECHANGED, sizeof(STYLESTRUCT), MMS_FLAG_READ }, - { WM_STYLECHANGING, sizeof(STYLESTRUCT), MMS_FLAG_READWRITE }, - { WM_WINDOWPOSCHANGED, sizeof(WINDOWPOS), MMS_FLAG_READ }, - { WM_WINDOWPOSCHANGING, sizeof(WINDOWPOS), MMS_FLAG_READWRITE }, - }; - -static PMSGMEMORY FASTCALL -FindMsgMemory(UINT Msg) - { - PMSGMEMORY MsgMemoryEntry; - - /* See if this message type is present in the table */ - for (MsgMemoryEntry = MsgMemory; - MsgMemoryEntry < MsgMemory + sizeof(MsgMemory) / sizeof(MSGMEMORY); - MsgMemoryEntry++) - { - if (Msg == MsgMemoryEntry->Message) - { - return MsgMemoryEntry; - } - } - - return NULL; -} - -static UINT FASTCALL -MsgMemorySize(PMSGMEMORY MsgMemoryEntry, WPARAM wParam, LPARAM lParam) -{ - if (MMS_SIZE_WPARAM == MsgMemoryEntry->Size) - { - return (UINT) wParam; - } - else if (MMS_SIZE_WPARAMWCHAR == MsgMemoryEntry->Size) - { - return (UINT) (wParam * sizeof(WCHAR)); - } - else if (MMS_SIZE_LPARAMSZ == MsgMemoryEntry->Size) - { - return (UINT) ((wcslen((PWSTR) lParam) + 1) * sizeof(WCHAR)); - } - else if (MMS_SIZE_SPECIAL == MsgMemoryEntry->Size) - { - switch(MsgMemoryEntry->Message) - { - case WM_NCCALCSIZE: - return wParam ? sizeof(NCCALCSIZE_PARAMS) + sizeof(WINDOWPOS) : sizeof(RECT); - break; - default: - assert(FALSE); - return 0; - break; - } - } - else - { - return MsgMemoryEntry->Size; - } -} - -static NTSTATUS FASTCALL -PackParam(LPARAM *lParamPacked, UINT Msg, WPARAM wParam, LPARAM lParam) -{ - NCCALCSIZE_PARAMS *UnpackedParams; - NCCALCSIZE_PARAMS *PackedParams; - - *lParamPacked = lParam; - if (WM_NCCALCSIZE == Msg && wParam) - { - UnpackedParams = (NCCALCSIZE_PARAMS *) lParam; - if (UnpackedParams->lppos != (PWINDOWPOS) (UnpackedParams + 1)) - { - PackedParams = ExAllocatePoolWithTag(PagedPool, - sizeof(NCCALCSIZE_PARAMS) + sizeof(WINDOWPOS), - TAG_MSG); - if (NULL == PackedParams) - { - DPRINT1("Not enough memory to pack lParam\n"); - return STATUS_NO_MEMORY; - } - RtlCopyMemory(PackedParams, UnpackedParams, sizeof(NCCALCSIZE_PARAMS)); - PackedParams->lppos = (PWINDOWPOS) (PackedParams + 1); - RtlCopyMemory(PackedParams->lppos, UnpackedParams->lppos, sizeof(WINDOWPOS)); - *lParamPacked = (LPARAM) PackedParams; - } - } - - return STATUS_SUCCESS; -} - -static FASTCALL NTSTATUS -UnpackParam(LPARAM lParamPacked, UINT Msg, WPARAM wParam, LPARAM lParam) -{ - NCCALCSIZE_PARAMS *UnpackedParams; - NCCALCSIZE_PARAMS *PackedParams; - PWINDOWPOS UnpackedWindowPos; - - if (lParamPacked == lParam) - { - return STATUS_SUCCESS; - } - - if (WM_NCCALCSIZE == Msg && wParam) - { - PackedParams = (NCCALCSIZE_PARAMS *) lParamPacked; - UnpackedParams = (NCCALCSIZE_PARAMS *) lParam; - UnpackedWindowPos = UnpackedParams->lppos; - RtlCopyMemory(UnpackedParams, PackedParams, sizeof(NCCALCSIZE_PARAMS)); - UnpackedParams->lppos = UnpackedWindowPos; - RtlCopyMemory(UnpackedWindowPos, PackedParams + 1, sizeof(WINDOWPOS)); - ExFreePool((PVOID) lParamPacked); - - return STATUS_SUCCESS; - } - - assert(FALSE); - - return STATUS_INVALID_PARAMETER; -} - LRESULT FASTCALL IntSendMessage(HWND hWnd, UINT Msg, @@ -1030,62 +1244,6 @@ IntSendMessageTimeout(HWND hWnd, return (LRESULT) TRUE; } -static NTSTATUS FASTCALL -CopyMsgToKernelMem(MSG *KernelModeMsg, MSG *UserModeMsg) -{ - NTSTATUS Status; - PMSGMEMORY MsgMemoryEntry; - PVOID KernelMem; - UINT Size; - - *KernelModeMsg = *UserModeMsg; - - /* 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) - { - /* 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; -} /* 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 @@ -1128,44 +1286,6 @@ IntPostOrSendMessage(HWND hWnd, return Result; } -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; -} - LRESULT FASTCALL IntDoSendMessage(HWND Wnd, UINT Msg, @@ -1180,6 +1300,7 @@ IntDoSendMessage(HWND Wnd, NTUSERSENDMESSAGEINFO Info; MSG UserModeMsg; MSG KernelModeMsg; + PMSGMEMORY MsgMemoryEntry; RtlZeroMemory(&Info, sizeof(NTUSERSENDMESSAGEINFO)); @@ -1245,7 +1366,8 @@ IntDoSendMessage(HWND Wnd, UserModeMsg.message = Msg; UserModeMsg.wParam = wParam; UserModeMsg.lParam = lParam; - Status = CopyMsgToKernelMem(&KernelModeMsg, &UserModeMsg); + MsgMemoryEntry = FindMsgMemory(UserModeMsg.message); + Status = CopyMsgToKernelMem(&KernelModeMsg, &UserModeMsg, MsgMemoryEntry); if (! NT_SUCCESS(Status)) { MmCopyToCaller(UnsafeInfo, &Info, sizeof(NTUSERSENDMESSAGEINFO)); diff --git a/reactos/subsys/win32k/ntuser/msgqueue.c b/reactos/subsys/win32k/ntuser/msgqueue.c index 95e025ccb85..0b772992743 100644 --- a/reactos/subsys/win32k/ntuser/msgqueue.c +++ b/reactos/subsys/win32k/ntuser/msgqueue.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: msgqueue.c,v 1.90 2004/04/16 18:53:53 weiden Exp $ +/* $Id: msgqueue.c,v 1.91 2004/04/29 21:13:16 gvg Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -493,6 +493,7 @@ MsqPeekHardwareMessage(PUSER_MESSAGE_QUEUE MessageQueue, HWND hWnd, UserMsg = ExAllocateFromPagedLookasideList(&MessageLookasideList); /* What to do if out of memory? For now we just panic a bit in debug */ ASSERT(UserMsg); + UserMsg->FreeLParam = FALSE; UserMsg->Msg = Msg; InsertTailList(&HardwareMessageQueueHead, &UserMsg->ListEntry); IntLockSystemMessageQueue(OldIrql); @@ -597,7 +598,7 @@ MsqPostKeyboardMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) FocusMessageQueue = IntGetFocusMessageQueue(); if( !IntGetScreenDC() ) { if( W32kGetPrimitiveMessageQueue() ) { - MsqPostMessage(W32kGetPrimitiveMessageQueue(), &Msg); + MsqPostMessage(W32kGetPrimitiveMessageQueue(), &Msg, FALSE); } } else { if (FocusMessageQueue == NULL) @@ -610,7 +611,7 @@ MsqPostKeyboardMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) { Msg.hwnd = FocusMessageQueue->FocusWindow; DPRINT("Msg.hwnd = %x\n", Msg.hwnd); - MsqPostMessage(FocusMessageQueue, &Msg); + MsqPostMessage(FocusMessageQueue, &Msg, FALSE); } else { @@ -665,7 +666,7 @@ MsqPostHotKeyMessage(PVOID Thread, HWND hWnd, WPARAM wParam, LPARAM lParam) // Mesg.pt.y = PsGetWin32Process()->WindowStation->SystemCursor.y; // KeQueryTickCount(&LargeTickCount); // Mesg.time = LargeTickCount.u.LowPart; - MsqPostMessage(Window->MessageQueue, &Mesg); + MsqPostMessage(Window->MessageQueue, &Mesg, FALSE); ObmDereferenceObject(Window); ObDereferenceObject (Thread); @@ -678,7 +679,7 @@ MsqPostHotKeyMessage(PVOID Thread, HWND hWnd, WPARAM wParam, LPARAM lParam) } PUSER_MESSAGE FASTCALL -MsqCreateMessage(LPMSG Msg) +MsqCreateMessage(LPMSG Msg, BOOLEAN FreeLParam) { PUSER_MESSAGE Message; @@ -688,6 +689,7 @@ MsqCreateMessage(LPMSG Msg) return NULL; } + Message->FreeLParam = FreeLParam; RtlMoveMemory(&Message->Msg, Msg, sizeof(MSG)); return Message; @@ -875,11 +877,11 @@ MsqSendMessage(PUSER_MESSAGE_QUEUE MessageQueue, } VOID FASTCALL -MsqPostMessage(PUSER_MESSAGE_QUEUE MessageQueue, MSG* Msg) +MsqPostMessage(PUSER_MESSAGE_QUEUE MessageQueue, MSG* Msg, BOOLEAN FreeLParam) { PUSER_MESSAGE Message; - if(!(Message = MsqCreateMessage(Msg))) + if(!(Message = MsqCreateMessage(Msg, FreeLParam))) { return; } diff --git a/reactos/subsys/win32k/ntuser/painting.c b/reactos/subsys/win32k/ntuser/painting.c index 90f17a070df..13ce85c3180 100644 --- a/reactos/subsys/win32k/ntuser/painting.c +++ b/reactos/subsys/win32k/ntuser/painting.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * $Id: painting.c,v 1.80 2004/04/09 20:03:19 navaraf Exp $ + * $Id: painting.c,v 1.81 2004/04/29 21:13:16 gvg Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -609,8 +609,8 @@ IntFindWindowToRepaint(HWND hWnd, PW32THREAD Thread) } BOOL FASTCALL -IntGetPaintMessage(HWND hWnd, PW32THREAD Thread, MSG *Message, - BOOL Remove) +IntGetPaintMessage(HWND hWnd, UINT MsgFilterMin, UINT MsgFilterMax, + PW32THREAD Thread, MSG *Message, BOOL Remove) { PWINDOW_OBJECT Window; PUSER_MESSAGE_QUEUE MessageQueue = (PUSER_MESSAGE_QUEUE)Thread->MessageQueue; @@ -625,13 +625,14 @@ IntGetPaintMessage(HWND hWnd, PW32THREAD Thread, MSG *Message, if (Message->hwnd == NULL) { -#if 0 - DPRINT1("PAINTING BUG: Thread marked as containing dirty windows, but no dirty windows found!\n"); -#endif - IntLockMessageQueue(MessageQueue); - MessageQueue->PaintPosted = 0; - MessageQueue->PaintCount = 0; - IntUnLockMessageQueue(MessageQueue); + if (NULL == hWnd) + { + DPRINT1("PAINTING BUG: Thread marked as containing dirty windows, but no dirty windows found!\n"); + IntLockMessageQueue(MessageQueue); + MessageQueue->PaintPosted = 0; + MessageQueue->PaintCount = 0; + IntUnLockMessageQueue(MessageQueue); + } return FALSE; } @@ -639,7 +640,10 @@ IntGetPaintMessage(HWND hWnd, PW32THREAD Thread, MSG *Message, if (Window != NULL) { IntLockWindowUpdate(Window); - if (Window->Flags & WINDOWOBJECT_NEED_NCPAINT) + if (0 != (Window->Flags & WINDOWOBJECT_NEED_NCPAINT) + && ((0 == MsgFilterMin && 0 == MsgFilterMax) || + (MsgFilterMin <= WM_NCPAINT && + WM_NCPAINT <= MsgFilterMax))) { Message->message = WM_NCPAINT; Message->wParam = (WPARAM)Window->NCUpdateRegion; @@ -651,7 +655,9 @@ IntGetPaintMessage(HWND hWnd, PW32THREAD Thread, MSG *Message, Window->Flags &= ~WINDOWOBJECT_NEED_NCPAINT; MsqDecPaintCountQueue(Window->MessageQueue); } - } else + } else if ((0 == MsgFilterMin && 0 == MsgFilterMax) || + (MsgFilterMin <= WM_PAINT && + WM_PAINT <= MsgFilterMax)) { Message->message = WM_PAINT; Message->wParam = Message->lParam = 0; diff --git a/reactos/subsys/win32k/ntuser/timer.c b/reactos/subsys/win32k/ntuser/timer.c index cb2e5301bb0..8dcd7b88f48 100644 --- a/reactos/subsys/win32k/ntuser/timer.c +++ b/reactos/subsys/win32k/ntuser/timer.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: timer.c,v 1.30 2004/04/09 20:03:19 navaraf Exp $ +/* $Id: timer.c,v 1.31 2004/04/29 21:13:16 gvg Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -418,7 +418,7 @@ TimerThreadMain(PVOID StartContext) continue; } - MsqPostMessage(((PW32THREAD)Thread->Win32Thread)->MessageQueue, &MsgTimer->Msg); + MsqPostMessage(((PW32THREAD)Thread->Win32Thread)->MessageQueue, &MsgTimer->Msg, FALSE); ThreadsToDereference[ThreadsToDereferencePos] = Thread; ++ThreadsToDereferencePos;