2005-01-06 10:16:18 +00:00
|
|
|
/*
|
2001-06-12 17:51:51 +00:00
|
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
|
|
* PROJECT: ReactOS user32.dll
|
|
|
|
* FILE: lib/user32/windows/message.c
|
|
|
|
* PURPOSE: Messages
|
|
|
|
* PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
|
|
|
|
* UPDATE HISTORY:
|
|
|
|
* 06-06-2001 CSH Created
|
|
|
|
*/
|
2004-08-15 21:36:30 +00:00
|
|
|
|
2005-06-19 18:06:53 +00:00
|
|
|
#include <user32.h>
|
2006-06-26 13:16:43 +00:00
|
|
|
|
|
|
|
#include <wine/debug.h>
|
2001-06-12 17:51:51 +00:00
|
|
|
|
2004-04-29 21:13:16 +00:00
|
|
|
/* DDE message exchange
|
2005-05-09 01:42:07 +00:00
|
|
|
*
|
2004-04-29 21:13:16 +00:00
|
|
|
* - 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.
|
2003-07-10 21:04:32 +00:00
|
|
|
*/
|
|
|
|
|
2004-04-29 21:13:16 +00:00
|
|
|
/* 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.
|
2003-07-10 21:04:32 +00:00
|
|
|
*/
|
2004-04-29 21:13:16 +00:00
|
|
|
typedef struct tagDDEPAIR
|
2002-06-13 20:36:40 +00:00
|
|
|
{
|
2004-04-29 21:13:16 +00:00
|
|
|
HGLOBAL ClientMem;
|
|
|
|
HGLOBAL ServerMem;
|
|
|
|
} DDEPAIR, *PDDEPAIR;
|
2002-06-13 20:36:40 +00:00
|
|
|
|
2004-04-29 21:13:16 +00:00
|
|
|
static PDDEPAIR DdePairs = NULL;
|
|
|
|
static unsigned DdeNumAlloc = 0;
|
|
|
|
static unsigned DdeNumUsed = 0;
|
|
|
|
static CRITICAL_SECTION DdeCrst;
|
2003-07-10 21:04:32 +00:00
|
|
|
|
2004-04-29 21:13:16 +00:00
|
|
|
static BOOL FASTCALL
|
|
|
|
DdeAddPair(HGLOBAL ClientMem, HGLOBAL ServerMem)
|
2002-06-13 20:36:40 +00:00
|
|
|
{
|
2004-04-29 21:13:16 +00:00
|
|
|
unsigned i;
|
2003-05-12 19:30:00 +00:00
|
|
|
|
2004-04-29 21:13:16 +00:00
|
|
|
EnterCriticalSection(&DdeCrst);
|
2003-07-10 21:04:32 +00:00
|
|
|
|
2004-04-29 21:13:16 +00:00
|
|
|
/* 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
|
|
|
|
{
|
2005-05-09 01:42:07 +00:00
|
|
|
New = HeapAlloc(GetProcessHeap(), 0,
|
2004-04-29 21:13:16 +00:00
|
|
|
(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;
|
2002-06-13 20:36:40 +00:00
|
|
|
}
|
|
|
|
|
2004-04-29 21:13:16 +00:00
|
|
|
static HGLOBAL FASTCALL
|
|
|
|
DdeGetPair(HGLOBAL ServerMem)
|
|
|
|
{
|
|
|
|
unsigned i;
|
|
|
|
HGLOBAL Ret = NULL;
|
2003-07-10 21:04:32 +00:00
|
|
|
|
2004-04-29 21:13:16 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
static BOOL FASTCALL
|
|
|
|
MsgiUMToKMMessage(PMSG UMMsg, PMSG KMMsg, BOOL Posted)
|
2002-06-13 20:36:40 +00:00
|
|
|
{
|
2004-04-29 21:13:16 +00:00
|
|
|
*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;
|
2004-12-25 20:30:50 +00:00
|
|
|
|
2004-04-29 21:13:16 +00:00
|
|
|
case WM_DDE_EXECUTE:
|
|
|
|
{
|
|
|
|
SIZE_T Size;
|
|
|
|
PKMDDEEXECUTEDATA KMDdeExecuteData;
|
|
|
|
PVOID Data;
|
2005-05-09 01:42:07 +00:00
|
|
|
|
2004-04-29 21:13:16 +00:00
|
|
|
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;
|
2004-12-25 20:30:50 +00:00
|
|
|
|
|
|
|
case WM_COPYDATA:
|
|
|
|
{
|
|
|
|
PCOPYDATASTRUCT pUMCopyData = (PCOPYDATASTRUCT)UMMsg->lParam;
|
|
|
|
PCOPYDATASTRUCT pKMCopyData;
|
|
|
|
|
|
|
|
pKMCopyData = HeapAlloc(GetProcessHeap(), 0,
|
|
|
|
sizeof(COPYDATASTRUCT) + pUMCopyData->cbData);
|
|
|
|
if (pKMCopyData == NULL)
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_OUTOFMEMORY);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
pKMCopyData->dwData = pUMCopyData->dwData;
|
|
|
|
pKMCopyData->cbData = pUMCopyData->cbData;
|
|
|
|
pKMCopyData->lpData = pKMCopyData + 1;
|
|
|
|
|
2005-05-09 01:42:07 +00:00
|
|
|
RtlCopyMemory(pKMCopyData + 1, pUMCopyData->lpData,
|
2004-12-25 20:30:50 +00:00
|
|
|
pUMCopyData->cbData);
|
|
|
|
|
|
|
|
KMMsg->lParam = (LPARAM)pKMCopyData;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2004-04-29 21:13:16 +00:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
2002-06-13 20:36:40 +00:00
|
|
|
}
|
2003-05-12 19:30:00 +00:00
|
|
|
|
2004-04-29 21:13:16 +00:00
|
|
|
static VOID FASTCALL
|
|
|
|
MsgiUMToKMCleanup(PMSG UMMsg, PMSG KMMsg)
|
|
|
|
{
|
|
|
|
switch (KMMsg->message)
|
|
|
|
{
|
|
|
|
case WM_DDE_ACK:
|
|
|
|
case WM_DDE_EXECUTE:
|
2004-12-25 20:30:50 +00:00
|
|
|
case WM_COPYDATA:
|
2004-04-29 21:13:16 +00:00
|
|
|
HeapFree(GetProcessHeap(), 0, (LPVOID) KMMsg->lParam);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2003-07-10 21:04:32 +00:00
|
|
|
|
2004-04-29 21:13:16 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
static BOOL FASTCALL
|
|
|
|
MsgiUMToKMReply(PMSG UMMsg, PMSG KMMsg, LRESULT *Result)
|
2002-06-13 20:36:40 +00:00
|
|
|
{
|
2004-04-29 21:13:16 +00:00
|
|
|
MsgiUMToKMCleanup(UMMsg, KMMsg);
|
|
|
|
|
|
|
|
return TRUE;
|
2002-06-13 20:36:40 +00:00
|
|
|
}
|
2003-05-12 19:30:00 +00:00
|
|
|
|
2004-04-29 21:13:16 +00:00
|
|
|
static BOOL FASTCALL
|
|
|
|
MsgiKMToUMMessage(PMSG KMMsg, PMSG UMMsg)
|
|
|
|
{
|
|
|
|
*UMMsg = *KMMsg;
|
2003-07-10 21:04:32 +00:00
|
|
|
|
2004-04-29 21:13:16 +00:00
|
|
|
switch (UMMsg->message)
|
|
|
|
{
|
2004-06-16 06:09:40 +00:00
|
|
|
case WM_CREATE:
|
|
|
|
case WM_NCCREATE:
|
|
|
|
{
|
|
|
|
CREATESTRUCTW *Cs = (CREATESTRUCTW *) KMMsg->lParam;
|
|
|
|
PCHAR Class;
|
|
|
|
Cs->lpszName = (LPCWSTR) ((PCHAR) Cs + (DWORD_PTR) Cs->lpszName);
|
|
|
|
Class = (PCHAR) Cs + (DWORD_PTR) Cs->lpszClass;
|
|
|
|
if (L'A' == *((WCHAR *) Class))
|
|
|
|
{
|
|
|
|
Class += sizeof(WCHAR);
|
|
|
|
Cs->lpszClass = (LPCWSTR)(DWORD_PTR) (*((ATOM *) Class));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ASSERT(L'S' == *((WCHAR *) Class));
|
|
|
|
Class += sizeof(WCHAR);
|
|
|
|
Cs->lpszClass = (LPCWSTR) Class;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2004-04-29 21:13:16 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
2004-06-16 06:09:40 +00:00
|
|
|
break;
|
|
|
|
|
2004-04-29 21:13:16 +00:00
|
|
|
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;
|
2004-06-16 06:09:40 +00:00
|
|
|
|
2004-12-25 20:30:50 +00:00
|
|
|
case WM_COPYDATA:
|
|
|
|
{
|
|
|
|
PCOPYDATASTRUCT pKMCopyData = (PCOPYDATASTRUCT)KMMsg->lParam;
|
|
|
|
pKMCopyData->lpData = pKMCopyData + 1;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2004-04-29 21:13:16 +00:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static VOID FASTCALL
|
|
|
|
MsgiKMToUMCleanup(PMSG KMMsg, PMSG UMMsg)
|
2002-06-13 20:36:40 +00:00
|
|
|
{
|
2004-04-29 21:13:16 +00:00
|
|
|
switch (KMMsg->message)
|
|
|
|
{
|
|
|
|
case WM_DDE_EXECUTE:
|
|
|
|
#ifdef TODO
|
|
|
|
HeapFree(GetProcessHeap(), 0, (LPVOID) KMMsg->lParam);
|
|
|
|
GlobalUnlock((HGLOBAL) UMMsg->lParam);
|
|
|
|
#endif
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
2002-06-13 20:36:40 +00:00
|
|
|
}
|
2002-06-18 21:51:11 +00:00
|
|
|
|
2004-04-29 21:13:16 +00:00
|
|
|
static BOOL FASTCALL
|
|
|
|
MsgiKMToUMReply(PMSG KMMsg, PMSG UMMsg, LRESULT *Result)
|
|
|
|
{
|
|
|
|
MsgiKMToUMCleanup(KMMsg, UMMsg);
|
2003-07-10 21:04:32 +00:00
|
|
|
|
2004-04-29 21:13:16 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static BOOL FASTCALL
|
2003-11-08 09:33:14 +00:00
|
|
|
MsgiAnsiToUnicodeMessage(LPMSG UnicodeMsg, LPMSG AnsiMsg)
|
2002-06-13 20:36:40 +00:00
|
|
|
{
|
2003-11-08 09:33:14 +00:00
|
|
|
*UnicodeMsg = *AnsiMsg;
|
|
|
|
switch (AnsiMsg->message)
|
2002-06-18 21:51:11 +00:00
|
|
|
{
|
2002-09-03 22:44:21 +00:00
|
|
|
case WM_GETTEXT:
|
2003-11-08 09:33:14 +00:00
|
|
|
case WM_ASKCBFORMATNAME:
|
2002-09-03 22:44:21 +00:00
|
|
|
{
|
2003-11-08 09:33:14 +00:00
|
|
|
LPWSTR Buffer = HeapAlloc(GetProcessHeap(), 0,
|
|
|
|
AnsiMsg->wParam * sizeof(WCHAR));
|
|
|
|
if (!Buffer)
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
UnicodeMsg->lParam = (LPARAM)Buffer;
|
|
|
|
break;
|
2002-09-03 22:44:21 +00:00
|
|
|
}
|
2003-11-08 09:33:14 +00:00
|
|
|
|
|
|
|
/* AnsiMsg->lParam is string (0-terminated) */
|
2003-05-19 20:11:17 +00:00
|
|
|
case WM_SETTEXT:
|
2003-11-08 09:33:14 +00:00
|
|
|
case WM_WININICHANGE:
|
|
|
|
case WM_DEVMODECHANGE:
|
|
|
|
case CB_DIR:
|
|
|
|
case LB_DIR:
|
|
|
|
case LB_ADDFILE:
|
|
|
|
case EM_REPLACESEL:
|
2003-05-19 20:11:17 +00:00
|
|
|
{
|
2006-05-03 10:35:11 +00:00
|
|
|
goto ConvertLParamString;
|
|
|
|
}
|
|
|
|
|
|
|
|
case LB_ADDSTRING:
|
|
|
|
case LB_ADDSTRING_LOWER:
|
|
|
|
case LB_ADDSTRING_UPPER:
|
|
|
|
case LB_INSERTSTRING:
|
|
|
|
case LB_INSERTSTRING_UPPER:
|
|
|
|
case LB_INSERTSTRING_LOWER:
|
|
|
|
case LB_FINDSTRING:
|
|
|
|
case LB_FINDSTRINGEXACT:
|
|
|
|
case LB_SELECTSTRING:
|
|
|
|
{
|
|
|
|
DWORD dwStyle = GetWindowLongW(AnsiMsg->hwnd, GWL_STYLE);
|
|
|
|
if (!(dwStyle & (LBS_OWNERDRAWFIXED | LBS_OWNERDRAWVARIABLE)) &&
|
|
|
|
(dwStyle & LBS_HASSTRINGS))
|
|
|
|
{
|
|
|
|
goto ConvertLParamString;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case CB_ADDSTRING:
|
|
|
|
case CB_INSERTSTRING:
|
|
|
|
case CB_FINDSTRING:
|
|
|
|
case CB_FINDSTRINGEXACT:
|
|
|
|
case CB_SELECTSTRING:
|
|
|
|
{
|
|
|
|
DWORD dwStyle = GetWindowLongW(AnsiMsg->hwnd, GWL_STYLE);
|
|
|
|
if (!(dwStyle & (CBS_OWNERDRAWFIXED | CBS_OWNERDRAWVARIABLE)) &&
|
|
|
|
(dwStyle & CBS_HASSTRINGS))
|
|
|
|
{
|
|
|
|
UNICODE_STRING UnicodeString;
|
|
|
|
|
|
|
|
ConvertLParamString:
|
|
|
|
RtlCreateUnicodeStringFromAsciiz(&UnicodeString, (LPSTR)AnsiMsg->lParam);
|
|
|
|
UnicodeMsg->lParam = (LPARAM)UnicodeString.Buffer;
|
|
|
|
}
|
2003-11-08 09:33:14 +00:00
|
|
|
break;
|
2003-05-19 20:11:17 +00:00
|
|
|
}
|
2003-11-08 09:33:14 +00:00
|
|
|
|
2002-06-18 21:51:11 +00:00
|
|
|
case WM_NCCREATE:
|
2003-11-08 09:33:14 +00:00
|
|
|
case WM_CREATE:
|
2002-06-18 21:51:11 +00:00
|
|
|
{
|
2003-11-08 09:33:14 +00:00
|
|
|
UNICODE_STRING UnicodeBuffer;
|
|
|
|
struct s
|
|
|
|
{
|
|
|
|
CREATESTRUCTW cs; /* new structure */
|
|
|
|
LPCWSTR lpszName; /* allocated Name */
|
|
|
|
LPCWSTR lpszClass; /* allocated Class */
|
|
|
|
};
|
|
|
|
struct s *xs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct s));
|
|
|
|
if (!xs)
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
xs->cs = *(CREATESTRUCTW *)AnsiMsg->lParam;
|
2006-05-14 21:26:24 +00:00
|
|
|
if (!IS_INTRESOURCE(xs->cs.lpszName))
|
2003-11-08 09:33:14 +00:00
|
|
|
{
|
|
|
|
RtlCreateUnicodeStringFromAsciiz(&UnicodeBuffer, (LPSTR)xs->cs.lpszName);
|
|
|
|
xs->lpszName = xs->cs.lpszName = UnicodeBuffer.Buffer;
|
|
|
|
}
|
2006-05-14 21:26:24 +00:00
|
|
|
if (!IS_ATOM(xs->cs.lpszClass))
|
2003-11-08 09:33:14 +00:00
|
|
|
{
|
|
|
|
RtlCreateUnicodeStringFromAsciiz(&UnicodeBuffer, (LPSTR)xs->cs.lpszClass);
|
|
|
|
xs->lpszClass = xs->cs.lpszClass = UnicodeBuffer.Buffer;
|
|
|
|
}
|
|
|
|
UnicodeMsg->lParam = (LPARAM)xs;
|
|
|
|
break;
|
|
|
|
}
|
2002-06-18 21:51:11 +00:00
|
|
|
|
2003-11-08 09:33:14 +00:00
|
|
|
case WM_MDICREATE:
|
|
|
|
{
|
|
|
|
UNICODE_STRING UnicodeBuffer;
|
|
|
|
MDICREATESTRUCTW *cs =
|
|
|
|
(MDICREATESTRUCTW *)HeapAlloc(GetProcessHeap(), 0, sizeof(*cs));
|
|
|
|
|
|
|
|
if (!cs)
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
*cs = *(MDICREATESTRUCTW *)AnsiMsg->lParam;
|
|
|
|
|
2006-05-14 21:26:24 +00:00
|
|
|
if (!IS_ATOM(cs->szClass))
|
2003-11-08 09:33:14 +00:00
|
|
|
{
|
|
|
|
RtlCreateUnicodeStringFromAsciiz(&UnicodeBuffer, (LPSTR)cs->szClass);
|
|
|
|
cs->szClass = UnicodeBuffer.Buffer;
|
|
|
|
}
|
|
|
|
|
|
|
|
RtlCreateUnicodeStringFromAsciiz(&UnicodeBuffer, (LPSTR)cs->szTitle);
|
|
|
|
cs->szTitle = UnicodeBuffer.Buffer;
|
|
|
|
|
|
|
|
UnicodeMsg->lParam = (LPARAM)cs;
|
|
|
|
break;
|
2002-06-18 21:51:11 +00:00
|
|
|
}
|
|
|
|
}
|
2003-11-08 09:33:14 +00:00
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-04-29 21:13:16 +00:00
|
|
|
static BOOL FASTCALL
|
2003-12-14 11:36:43 +00:00
|
|
|
MsgiAnsiToUnicodeCleanup(LPMSG UnicodeMsg, LPMSG AnsiMsg)
|
2003-11-08 09:33:14 +00:00
|
|
|
{
|
|
|
|
switch (AnsiMsg->message)
|
|
|
|
{
|
|
|
|
case WM_GETTEXT:
|
|
|
|
case WM_ASKCBFORMATNAME:
|
|
|
|
{
|
2003-12-14 11:36:43 +00:00
|
|
|
HeapFree(GetProcessHeap(), 0, (PVOID) UnicodeMsg->lParam);
|
2003-11-08 09:33:14 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case WM_SETTEXT:
|
|
|
|
case WM_WININICHANGE:
|
|
|
|
case WM_DEVMODECHANGE:
|
|
|
|
case CB_DIR:
|
|
|
|
case LB_DIR:
|
|
|
|
case LB_ADDFILE:
|
|
|
|
case EM_REPLACESEL:
|
|
|
|
{
|
2006-05-03 10:35:11 +00:00
|
|
|
goto FreeLParamString;
|
|
|
|
}
|
|
|
|
|
|
|
|
case LB_ADDSTRING:
|
|
|
|
case LB_ADDSTRING_LOWER:
|
|
|
|
case LB_ADDSTRING_UPPER:
|
|
|
|
case LB_INSERTSTRING:
|
|
|
|
case LB_INSERTSTRING_UPPER:
|
|
|
|
case LB_INSERTSTRING_LOWER:
|
|
|
|
case LB_FINDSTRING:
|
|
|
|
case LB_FINDSTRINGEXACT:
|
|
|
|
case LB_SELECTSTRING:
|
|
|
|
{
|
|
|
|
DWORD dwStyle = GetWindowLongW(AnsiMsg->hwnd, GWL_STYLE);
|
|
|
|
if (!(dwStyle & (LBS_OWNERDRAWFIXED | LBS_OWNERDRAWVARIABLE)) &&
|
|
|
|
(dwStyle & LBS_HASSTRINGS))
|
|
|
|
{
|
|
|
|
goto FreeLParamString;
|
|
|
|
}
|
2003-11-08 09:33:14 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2006-05-03 10:35:11 +00:00
|
|
|
case CB_ADDSTRING:
|
|
|
|
case CB_INSERTSTRING:
|
|
|
|
case CB_FINDSTRING:
|
|
|
|
case CB_FINDSTRINGEXACT:
|
|
|
|
case CB_SELECTSTRING:
|
|
|
|
{
|
|
|
|
DWORD dwStyle = GetWindowLongW(AnsiMsg->hwnd, GWL_STYLE);
|
|
|
|
if (!(dwStyle & (CBS_OWNERDRAWFIXED | CBS_OWNERDRAWVARIABLE)) &&
|
|
|
|
(dwStyle & CBS_HASSTRINGS))
|
|
|
|
{
|
|
|
|
UNICODE_STRING UnicodeString;
|
|
|
|
|
|
|
|
FreeLParamString:
|
|
|
|
RtlInitUnicodeString(&UnicodeString, (PCWSTR)UnicodeMsg->lParam);
|
|
|
|
RtlFreeUnicodeString(&UnicodeString);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-11-08 09:33:14 +00:00
|
|
|
case WM_NCCREATE:
|
|
|
|
case WM_CREATE:
|
|
|
|
{
|
|
|
|
UNICODE_STRING UnicodeString;
|
|
|
|
struct s
|
|
|
|
{
|
|
|
|
CREATESTRUCTW cs; /* new structure */
|
|
|
|
LPWSTR lpszName; /* allocated Name */
|
|
|
|
LPWSTR lpszClass; /* allocated Class */
|
|
|
|
};
|
|
|
|
struct s *xs = (struct s *)UnicodeMsg->lParam;
|
|
|
|
if (xs->lpszName)
|
|
|
|
{
|
|
|
|
RtlInitUnicodeString(&UnicodeString, (PCWSTR)xs->lpszName);
|
|
|
|
RtlFreeUnicodeString(&UnicodeString);
|
|
|
|
}
|
|
|
|
if (xs->lpszClass)
|
|
|
|
{
|
|
|
|
RtlInitUnicodeString(&UnicodeString, (PCWSTR)xs->lpszClass);
|
|
|
|
RtlFreeUnicodeString(&UnicodeString);
|
|
|
|
}
|
|
|
|
HeapFree(GetProcessHeap(), 0, xs);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_MDICREATE:
|
|
|
|
{
|
|
|
|
UNICODE_STRING UnicodeString;
|
|
|
|
MDICREATESTRUCTW *cs = (MDICREATESTRUCTW *)UnicodeMsg->lParam;
|
2006-05-14 21:26:24 +00:00
|
|
|
RtlInitUnicodeString(&UnicodeString, (PCWSTR)cs->szTitle);
|
|
|
|
RtlFreeUnicodeString(&UnicodeString);
|
|
|
|
if (!IS_ATOM(cs->szClass))
|
2003-11-08 09:33:14 +00:00
|
|
|
{
|
|
|
|
RtlInitUnicodeString(&UnicodeString, (PCWSTR)cs->szClass);
|
|
|
|
RtlFreeUnicodeString(&UnicodeString);
|
|
|
|
}
|
|
|
|
HeapFree(GetProcessHeap(), 0, cs);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return(TRUE);
|
2002-06-13 20:36:40 +00:00
|
|
|
}
|
|
|
|
|
2003-07-10 21:04:32 +00:00
|
|
|
|
2004-04-29 21:13:16 +00:00
|
|
|
static BOOL FASTCALL
|
2003-12-14 11:36:43 +00:00
|
|
|
MsgiAnsiToUnicodeReply(LPMSG UnicodeMsg, LPMSG AnsiMsg, LRESULT *Result)
|
|
|
|
{
|
|
|
|
switch (AnsiMsg->message)
|
|
|
|
{
|
|
|
|
case WM_GETTEXT:
|
|
|
|
case WM_ASKCBFORMATNAME:
|
|
|
|
{
|
|
|
|
LPWSTR Buffer = (LPWSTR)UnicodeMsg->lParam;
|
|
|
|
LPSTR AnsiBuffer = (LPSTR)AnsiMsg->lParam;
|
|
|
|
if (UnicodeMsg->wParam > 0 &&
|
|
|
|
!WideCharToMultiByte(CP_ACP, 0, Buffer, -1,
|
|
|
|
AnsiBuffer, UnicodeMsg->wParam, NULL, NULL))
|
|
|
|
{
|
|
|
|
AnsiBuffer[UnicodeMsg->wParam - 1] = 0;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
MsgiAnsiToUnicodeCleanup(UnicodeMsg, AnsiMsg);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-04-29 21:13:16 +00:00
|
|
|
static BOOL FASTCALL
|
|
|
|
MsgiUnicodeToAnsiMessage(LPMSG AnsiMsg, LPMSG UnicodeMsg)
|
2002-06-13 20:36:40 +00:00
|
|
|
{
|
2004-04-29 21:13:16 +00:00
|
|
|
*AnsiMsg = *UnicodeMsg;
|
|
|
|
|
|
|
|
switch(UnicodeMsg->message)
|
2002-06-18 21:51:11 +00:00
|
|
|
{
|
2004-04-29 21:13:16 +00:00
|
|
|
case WM_CREATE:
|
|
|
|
case WM_NCCREATE:
|
|
|
|
{
|
|
|
|
CREATESTRUCTA* CsA;
|
|
|
|
CREATESTRUCTW* CsW;
|
|
|
|
UNICODE_STRING UString;
|
|
|
|
ANSI_STRING AString;
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
|
|
|
CsW = (CREATESTRUCTW*)(UnicodeMsg->lParam);
|
|
|
|
CsA = RtlAllocateHeap(GetProcessHeap(), 0, sizeof(CREATESTRUCTA));
|
|
|
|
if (NULL == CsA)
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
memcpy(CsA, CsW, sizeof(CREATESTRUCTW));
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
2004-12-05 03:50:33 +00:00
|
|
|
AnsiMsg->lParam = (LPARAM)CsA;
|
2004-04-29 21:13:16 +00:00
|
|
|
break;
|
|
|
|
}
|
2004-08-31 23:32:01 +00:00
|
|
|
case WM_GETTEXT:
|
|
|
|
{
|
|
|
|
/* Ansi string might contain MBCS chars so we need 2 * the number of chars */
|
|
|
|
AnsiMsg->wParam = UnicodeMsg->wParam * 2;
|
|
|
|
AnsiMsg->lParam = (LPARAM) RtlAllocateHeap(GetProcessHeap(), 0, AnsiMsg->wParam);
|
|
|
|
if (NULL == (PVOID) AnsiMsg->lParam)
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2004-04-29 21:13:16 +00:00
|
|
|
case WM_SETTEXT:
|
2006-05-03 10:35:11 +00:00
|
|
|
case CB_DIR:
|
|
|
|
case LB_DIR:
|
|
|
|
case LB_ADDFILE:
|
2004-04-29 21:13:16 +00:00
|
|
|
{
|
2006-05-03 10:35:11 +00:00
|
|
|
goto ConvertLParamString;
|
|
|
|
}
|
|
|
|
|
|
|
|
case LB_ADDSTRING:
|
|
|
|
case LB_ADDSTRING_LOWER:
|
|
|
|
case LB_ADDSTRING_UPPER:
|
|
|
|
case LB_INSERTSTRING:
|
|
|
|
case LB_INSERTSTRING_UPPER:
|
|
|
|
case LB_INSERTSTRING_LOWER:
|
|
|
|
case LB_FINDSTRING:
|
|
|
|
case LB_FINDSTRINGEXACT:
|
|
|
|
case LB_SELECTSTRING:
|
|
|
|
{
|
|
|
|
DWORD dwStyle = GetWindowLongW(AnsiMsg->hwnd, GWL_STYLE);
|
|
|
|
if (!(dwStyle & (LBS_OWNERDRAWFIXED | LBS_OWNERDRAWVARIABLE)) &&
|
|
|
|
(dwStyle & LBS_HASSTRINGS))
|
2004-04-29 21:13:16 +00:00
|
|
|
{
|
2006-05-03 10:35:11 +00:00
|
|
|
goto ConvertLParamString;
|
2004-04-29 21:13:16 +00:00
|
|
|
}
|
|
|
|
break;
|
2006-05-03 10:35:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
case CB_ADDSTRING:
|
|
|
|
case CB_INSERTSTRING:
|
|
|
|
case CB_FINDSTRING:
|
|
|
|
case CB_FINDSTRINGEXACT:
|
|
|
|
case CB_SELECTSTRING:
|
|
|
|
{
|
|
|
|
DWORD dwStyle = GetWindowLongW(AnsiMsg->hwnd, GWL_STYLE);
|
|
|
|
if (!(dwStyle & (CBS_OWNERDRAWFIXED | CBS_OWNERDRAWVARIABLE)) &&
|
|
|
|
(dwStyle & CBS_HASSTRINGS))
|
|
|
|
{
|
|
|
|
ANSI_STRING AnsiString;
|
|
|
|
UNICODE_STRING UnicodeString;
|
|
|
|
|
|
|
|
ConvertLParamString:
|
|
|
|
RtlInitUnicodeString(&UnicodeString, (PWSTR) UnicodeMsg->lParam);
|
|
|
|
if (! NT_SUCCESS(RtlUnicodeStringToAnsiString(&AnsiString,
|
|
|
|
&UnicodeString,
|
|
|
|
TRUE)))
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
AnsiMsg->lParam = (LPARAM) AnsiString.Buffer;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2006-05-14 21:26:24 +00:00
|
|
|
|
|
|
|
case WM_MDICREATE:
|
|
|
|
{
|
|
|
|
ANSI_STRING AnsiBuffer;
|
|
|
|
UNICODE_STRING UnicodeString;
|
|
|
|
MDICREATESTRUCTA *cs =
|
|
|
|
(MDICREATESTRUCTA *)HeapAlloc(GetProcessHeap(), 0, sizeof(*cs));
|
|
|
|
|
|
|
|
if (!cs)
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
*cs = *(MDICREATESTRUCTA *)UnicodeMsg->lParam;
|
|
|
|
|
|
|
|
if (!IS_ATOM(cs->szClass))
|
|
|
|
{
|
|
|
|
RtlInitUnicodeString(&UnicodeString, (LPCWSTR)cs->szClass);
|
|
|
|
if (! NT_SUCCESS(RtlUnicodeStringToAnsiString(&AnsiBuffer,
|
|
|
|
&UnicodeString,
|
|
|
|
TRUE)))
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
cs->szClass = AnsiBuffer.Buffer;
|
|
|
|
}
|
|
|
|
|
|
|
|
RtlInitUnicodeString(&UnicodeString, (LPCWSTR)cs->szTitle);
|
|
|
|
if (! NT_SUCCESS(RtlUnicodeStringToAnsiString(&AnsiBuffer,
|
|
|
|
&UnicodeString,
|
|
|
|
TRUE)))
|
|
|
|
{
|
|
|
|
if (!IS_ATOM(cs->szClass))
|
|
|
|
{
|
|
|
|
RtlInitAnsiString(&AnsiBuffer, cs->szClass);
|
|
|
|
RtlFreeAnsiString(&AnsiBuffer);
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
cs->szTitle = AnsiBuffer.Buffer;
|
|
|
|
|
|
|
|
AnsiMsg->lParam = (LPARAM)cs;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2004-04-29 21:13:16 +00:00
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static BOOL FASTCALL
|
|
|
|
MsgiUnicodeToAnsiCleanup(LPMSG AnsiMsg, LPMSG UnicodeMsg)
|
|
|
|
{
|
|
|
|
switch(UnicodeMsg->message)
|
|
|
|
{
|
|
|
|
case WM_GETTEXT:
|
2004-08-31 23:32:01 +00:00
|
|
|
{
|
|
|
|
RtlFreeHeap(GetProcessHeap(), 0, (PVOID) AnsiMsg->lParam);
|
|
|
|
break;
|
|
|
|
}
|
2004-04-29 21:13:16 +00:00
|
|
|
case WM_SETTEXT:
|
|
|
|
{
|
2006-05-03 10:35:11 +00:00
|
|
|
goto FreeLParamString;
|
2004-04-29 21:13:16 +00:00
|
|
|
}
|
|
|
|
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;
|
|
|
|
}
|
2006-05-03 10:35:11 +00:00
|
|
|
|
|
|
|
case LB_ADDSTRING:
|
|
|
|
case LB_ADDSTRING_LOWER:
|
|
|
|
case LB_ADDSTRING_UPPER:
|
|
|
|
case LB_INSERTSTRING:
|
|
|
|
case LB_INSERTSTRING_UPPER:
|
|
|
|
case LB_INSERTSTRING_LOWER:
|
|
|
|
case LB_FINDSTRING:
|
|
|
|
case LB_FINDSTRINGEXACT:
|
|
|
|
case LB_SELECTSTRING:
|
|
|
|
{
|
|
|
|
DWORD dwStyle = GetWindowLongW(AnsiMsg->hwnd, GWL_STYLE);
|
|
|
|
if (!(dwStyle & (LBS_OWNERDRAWFIXED | LBS_OWNERDRAWVARIABLE)) &&
|
|
|
|
(dwStyle & LBS_HASSTRINGS))
|
|
|
|
{
|
|
|
|
goto FreeLParamString;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case CB_ADDSTRING:
|
|
|
|
case CB_INSERTSTRING:
|
|
|
|
case CB_FINDSTRING:
|
|
|
|
case CB_FINDSTRINGEXACT:
|
|
|
|
case CB_SELECTSTRING:
|
|
|
|
{
|
|
|
|
DWORD dwStyle = GetWindowLongW(AnsiMsg->hwnd, GWL_STYLE);
|
|
|
|
if (!(dwStyle & (CBS_OWNERDRAWFIXED | CBS_OWNERDRAWVARIABLE)) &&
|
|
|
|
(dwStyle & CBS_HASSTRINGS))
|
|
|
|
{
|
|
|
|
ANSI_STRING AString;
|
|
|
|
|
|
|
|
FreeLParamString:
|
|
|
|
RtlInitAnsiString(&AString, (PSTR) AnsiMsg->lParam);
|
|
|
|
RtlFreeAnsiString(&AString);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2006-05-14 21:26:24 +00:00
|
|
|
case WM_MDICREATE:
|
|
|
|
{
|
|
|
|
ANSI_STRING AnsiString;
|
|
|
|
MDICREATESTRUCTA *cs = (MDICREATESTRUCTA *)AnsiMsg->lParam;
|
|
|
|
RtlInitAnsiString(&AnsiString, (PCSTR)cs->szTitle);
|
|
|
|
RtlFreeAnsiString(&AnsiString);
|
|
|
|
if (!IS_ATOM(cs->szClass))
|
|
|
|
{
|
|
|
|
RtlInitAnsiString(&AnsiString, (PCSTR)cs->szClass);
|
|
|
|
RtlFreeAnsiString(&AnsiString);
|
|
|
|
}
|
|
|
|
HeapFree(GetProcessHeap(), 0, cs);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2002-06-18 21:51:11 +00:00
|
|
|
}
|
2004-04-29 21:13:16 +00:00
|
|
|
|
|
|
|
return TRUE;
|
2002-06-18 21:51:11 +00:00
|
|
|
}
|
|
|
|
|
2003-07-10 21:04:32 +00:00
|
|
|
|
2004-04-29 21:13:16 +00:00
|
|
|
static BOOL FASTCALL
|
|
|
|
MsgiUnicodeToAnsiReply(LPMSG AnsiMsg, LPMSG UnicodeMsg, LRESULT *Result)
|
2002-06-18 21:51:11 +00:00
|
|
|
{
|
2004-04-29 21:13:16 +00:00
|
|
|
switch (UnicodeMsg->message)
|
2003-11-08 09:33:14 +00:00
|
|
|
{
|
|
|
|
case WM_GETTEXT:
|
2004-04-29 21:13:16 +00:00
|
|
|
case WM_ASKCBFORMATNAME:
|
2003-11-08 09:33:14 +00:00
|
|
|
{
|
2004-04-29 21:13:16 +00:00
|
|
|
LPSTR Buffer = (LPSTR) AnsiMsg->lParam;
|
|
|
|
LPWSTR UBuffer = (LPWSTR) UnicodeMsg->lParam;
|
|
|
|
if (0 < AnsiMsg->wParam &&
|
|
|
|
! MultiByteToWideChar(CP_ACP, 0, Buffer, -1, UBuffer, UnicodeMsg->wParam))
|
|
|
|
{
|
2004-12-05 03:50:33 +00:00
|
|
|
UBuffer[UnicodeMsg->wParam - 1] = L'\0';
|
2004-04-29 21:13:16 +00:00
|
|
|
}
|
|
|
|
break;
|
2003-11-08 09:33:14 +00:00
|
|
|
}
|
|
|
|
}
|
2004-04-29 21:13:16 +00:00
|
|
|
|
2004-12-05 03:50:33 +00:00
|
|
|
MsgiUnicodeToAnsiCleanup(AnsiMsg, UnicodeMsg);
|
2004-04-29 21:13:16 +00:00
|
|
|
|
|
|
|
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
|
|
|
|
{
|
2005-05-09 01:42:07 +00:00
|
|
|
New = HeapAlloc(GetProcessHeap(), 0,
|
2004-04-29 21:13:16 +00:00
|
|
|
(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)
|
|
|
|
{
|
2004-12-30 02:32:26 +00:00
|
|
|
static DWORD ShowNotImplemented = TRUE;
|
|
|
|
if (ShowNotImplemented)
|
|
|
|
{
|
|
|
|
DbgPrint("InSendMessage is unimplemented\n");
|
|
|
|
ShowNotImplemented = FALSE;
|
|
|
|
}
|
2004-04-29 21:13:16 +00:00
|
|
|
/* return(NtUserGetThreadState(THREADSTATE_INSENDMESSAGE) != ISMEX_NOSEND); */
|
|
|
|
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);
|
2002-06-18 21:51:11 +00:00
|
|
|
}
|
|
|
|
|
2003-12-26 22:52:12 +00:00
|
|
|
LRESULT FASTCALL
|
2003-12-14 11:36:43 +00:00
|
|
|
IntCallWindowProcW(BOOL IsAnsiProc,
|
|
|
|
WNDPROC WndProc,
|
|
|
|
HWND hWnd,
|
|
|
|
UINT Msg,
|
|
|
|
WPARAM wParam,
|
|
|
|
LPARAM lParam)
|
|
|
|
{
|
2004-04-29 21:13:16 +00:00
|
|
|
MSG AnsiMsg;
|
|
|
|
MSG UnicodeMsg;
|
2003-12-14 11:36:43 +00:00
|
|
|
LRESULT Result;
|
|
|
|
|
2006-07-13 20:47:59 +00:00
|
|
|
if (WndProc == NULL)
|
|
|
|
{
|
|
|
|
DPRINT1("IntCallWindowsProcW() called with WndProc = NULL!\n");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2003-12-14 11:36:43 +00:00
|
|
|
if (IsAnsiProc)
|
|
|
|
{
|
2004-04-29 21:13:16 +00:00
|
|
|
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);
|
2006-04-05 08:05:55 +00:00
|
|
|
|
2004-04-29 21:13:16 +00:00
|
|
|
if (! MsgiUnicodeToAnsiReply(&AnsiMsg, &UnicodeMsg, &Result))
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
2003-12-14 11:36:43 +00:00
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return WndProc(hWnd, Msg, wParam, lParam);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-11-22 00:05:23 +00:00
|
|
|
static LRESULT FASTCALL
|
2003-12-14 11:36:43 +00:00
|
|
|
IntCallWindowProcA(BOOL IsAnsiProc,
|
|
|
|
WNDPROC WndProc,
|
|
|
|
HWND hWnd,
|
|
|
|
UINT Msg,
|
|
|
|
WPARAM wParam,
|
|
|
|
LPARAM lParam)
|
|
|
|
{
|
|
|
|
MSG AnsiMsg;
|
|
|
|
MSG UnicodeMsg;
|
|
|
|
LRESULT Result;
|
|
|
|
|
2006-07-13 20:47:59 +00:00
|
|
|
if (WndProc == NULL)
|
|
|
|
{
|
|
|
|
DPRINT1("IntCallWindowsProcA() called with WndProc = NULL!\n");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2003-12-14 11:36:43 +00:00
|
|
|
if (IsAnsiProc)
|
|
|
|
{
|
|
|
|
return WndProc(hWnd, Msg, wParam, lParam);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
AnsiMsg.hwnd = hWnd;
|
|
|
|
AnsiMsg.message = Msg;
|
|
|
|
AnsiMsg.wParam = wParam;
|
|
|
|
AnsiMsg.lParam = lParam;
|
|
|
|
if (! MsgiAnsiToUnicodeMessage(&UnicodeMsg, &AnsiMsg))
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
Result = WndProc(UnicodeMsg.hwnd, UnicodeMsg.message,
|
|
|
|
UnicodeMsg.wParam, UnicodeMsg.lParam);
|
2006-04-05 08:05:55 +00:00
|
|
|
|
2003-12-14 11:36:43 +00:00
|
|
|
if (! MsgiAnsiToUnicodeReply(&UnicodeMsg, &AnsiMsg, &Result))
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-05-03 04:17:50 +00:00
|
|
|
static BOOL __inline
|
|
|
|
IsCallProcHandle(IN WNDPROC lpWndProc)
|
|
|
|
{
|
|
|
|
/* FIXME - check for 64 bit architectures... */
|
|
|
|
return ((ULONG_PTR)lpWndProc & 0xFFFF0000) == 0xFFFF0000;
|
|
|
|
}
|
|
|
|
|
2003-07-10 21:04:32 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2002-06-18 21:51:11 +00:00
|
|
|
LRESULT STDCALL
|
|
|
|
CallWindowProcA(WNDPROC lpPrevWndFunc,
|
|
|
|
HWND hWnd,
|
|
|
|
UINT Msg,
|
|
|
|
WPARAM wParam,
|
|
|
|
LPARAM lParam)
|
|
|
|
{
|
2006-04-05 08:05:55 +00:00
|
|
|
WNDPROC_INFO wpInfo;
|
2003-11-08 09:33:14 +00:00
|
|
|
|
2006-04-14 18:23:11 +00:00
|
|
|
/* FIXME - can the first parameter be NULL? */
|
2004-04-09 20:03:21 +00:00
|
|
|
if (lpPrevWndFunc == NULL)
|
2006-04-14 18:23:11 +00:00
|
|
|
lpPrevWndFunc = (WNDPROC)NtUserGetWindowLong(hWnd, GWLP_WNDPROC, TRUE);
|
2004-04-09 20:03:21 +00:00
|
|
|
|
2006-05-03 04:17:50 +00:00
|
|
|
if (!IsCallProcHandle(lpPrevWndFunc) ||
|
|
|
|
!NtUserDereferenceWndProcHandle((HANDLE)lpPrevWndFunc,
|
2006-04-05 08:05:55 +00:00
|
|
|
&wpInfo))
|
2002-06-18 21:51:11 +00:00
|
|
|
{
|
2003-12-14 11:36:43 +00:00
|
|
|
return IntCallWindowProcA(TRUE, lpPrevWndFunc, hWnd, Msg, wParam, lParam);
|
2002-06-18 21:51:11 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2006-04-05 08:05:55 +00:00
|
|
|
return IntCallWindowProcA(!wpInfo.IsUnicode, wpInfo.WindowProc,
|
2003-12-14 11:36:43 +00:00
|
|
|
hWnd, Msg, wParam, lParam);
|
2002-06-18 21:51:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-07-10 21:04:32 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2002-06-18 21:51:11 +00:00
|
|
|
LRESULT STDCALL
|
|
|
|
CallWindowProcW(WNDPROC lpPrevWndFunc,
|
|
|
|
HWND hWnd,
|
|
|
|
UINT Msg,
|
|
|
|
WPARAM wParam,
|
|
|
|
LPARAM lParam)
|
|
|
|
{
|
2006-04-05 08:05:55 +00:00
|
|
|
WNDPROC_INFO wpInfo;
|
2003-11-11 20:28:21 +00:00
|
|
|
|
2006-04-14 18:23:11 +00:00
|
|
|
/* FIXME - can the first parameter be NULL? */
|
|
|
|
if (lpPrevWndFunc == NULL)
|
|
|
|
lpPrevWndFunc = (WNDPROC)NtUserGetWindowLong(hWnd, GWLP_WNDPROC, FALSE);
|
|
|
|
|
2006-05-03 04:17:50 +00:00
|
|
|
if (!IsCallProcHandle(lpPrevWndFunc) ||
|
|
|
|
!NtUserDereferenceWndProcHandle((HANDLE)lpPrevWndFunc,
|
2006-04-05 08:05:55 +00:00
|
|
|
&wpInfo))
|
2002-06-18 21:51:11 +00:00
|
|
|
{
|
2003-12-14 11:36:43 +00:00
|
|
|
return IntCallWindowProcW(FALSE, lpPrevWndFunc, hWnd, Msg, wParam, lParam);
|
2002-06-18 21:51:11 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2006-04-05 08:05:55 +00:00
|
|
|
return IntCallWindowProcW(!wpInfo.IsUnicode, wpInfo.WindowProc,
|
2003-12-14 11:36:43 +00:00
|
|
|
hWnd, Msg, wParam, lParam);
|
2002-06-18 21:51:11 +00:00
|
|
|
}
|
2002-06-13 20:36:40 +00:00
|
|
|
}
|
|
|
|
|
2001-06-12 17:51:51 +00:00
|
|
|
|
2003-07-10 21:04:32 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2002-09-03 22:44:21 +00:00
|
|
|
LRESULT STDCALL
|
|
|
|
DispatchMessageA(CONST MSG *lpmsg)
|
2001-06-12 17:51:51 +00:00
|
|
|
{
|
2004-04-29 21:13:16 +00:00
|
|
|
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;
|
2001-06-12 17:51:51 +00:00
|
|
|
}
|
|
|
|
|
2003-07-10 21:04:32 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2002-09-03 22:44:21 +00:00
|
|
|
LRESULT STDCALL
|
|
|
|
DispatchMessageW(CONST MSG *lpmsg)
|
2001-06-12 17:51:51 +00:00
|
|
|
{
|
2004-04-29 21:13:16 +00:00
|
|
|
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;
|
2001-06-12 17:51:51 +00:00
|
|
|
}
|
|
|
|
|
2003-07-10 21:04:32 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2004-01-23 23:38:26 +00:00
|
|
|
BOOL STDCALL
|
2003-08-01 18:45:35 +00:00
|
|
|
GetMessageA(LPMSG lpMsg,
|
|
|
|
HWND hWnd,
|
|
|
|
UINT wMsgFilterMin,
|
|
|
|
UINT wMsgFilterMax)
|
2001-06-12 17:51:51 +00:00
|
|
|
{
|
2003-08-01 18:45:35 +00:00
|
|
|
BOOL Res;
|
2004-04-29 21:13:16 +00:00
|
|
|
MSGCONVERSION Conversion;
|
|
|
|
NTUSERGETMESSAGEINFO Info;
|
2003-08-01 18:45:35 +00:00
|
|
|
PUSER32_THREAD_DATA ThreadData = User32GetThreadData();
|
|
|
|
|
2004-04-29 21:13:16 +00:00
|
|
|
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);
|
2003-08-01 18:45:35 +00:00
|
|
|
if (Res && lpMsg->message != WM_PAINT && lpMsg->message != WM_QUIT)
|
|
|
|
{
|
2004-04-29 21:13:16 +00:00
|
|
|
ThreadData->LastMessage = Info.Msg;
|
2003-08-01 18:45:35 +00:00
|
|
|
}
|
2004-04-29 21:13:16 +00:00
|
|
|
|
|
|
|
return Res;
|
2001-06-12 17:51:51 +00:00
|
|
|
}
|
|
|
|
|
2003-07-10 21:04:32 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2004-01-23 23:38:26 +00:00
|
|
|
BOOL STDCALL
|
2003-08-01 18:45:35 +00:00
|
|
|
GetMessageW(LPMSG lpMsg,
|
|
|
|
HWND hWnd,
|
|
|
|
UINT wMsgFilterMin,
|
|
|
|
UINT wMsgFilterMax)
|
2001-06-12 17:51:51 +00:00
|
|
|
{
|
2003-08-01 18:45:35 +00:00
|
|
|
BOOL Res;
|
2004-04-29 21:13:16 +00:00
|
|
|
MSGCONVERSION Conversion;
|
|
|
|
NTUSERGETMESSAGEINFO Info;
|
2003-08-01 18:45:35 +00:00
|
|
|
PUSER32_THREAD_DATA ThreadData = User32GetThreadData();
|
|
|
|
|
2004-04-29 21:13:16 +00:00
|
|
|
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);
|
2003-08-01 18:45:35 +00:00
|
|
|
if (Res && lpMsg->message != WM_PAINT && lpMsg->message != WM_QUIT)
|
|
|
|
{
|
2004-04-29 21:13:16 +00:00
|
|
|
ThreadData->LastMessage = Info.Msg;
|
2003-08-01 18:45:35 +00:00
|
|
|
}
|
2004-04-29 21:13:16 +00:00
|
|
|
|
|
|
|
return Res;
|
2001-06-12 17:51:51 +00:00
|
|
|
}
|
|
|
|
|
2003-07-10 21:04:32 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2004-01-23 23:38:26 +00:00
|
|
|
BOOL STDCALL
|
2003-08-01 18:45:35 +00:00
|
|
|
PeekMessageA(LPMSG lpMsg,
|
|
|
|
HWND hWnd,
|
|
|
|
UINT wMsgFilterMin,
|
|
|
|
UINT wMsgFilterMax,
|
|
|
|
UINT wRemoveMsg)
|
2001-06-12 17:51:51 +00:00
|
|
|
{
|
2003-08-01 18:45:35 +00:00
|
|
|
BOOL Res;
|
2004-04-29 21:13:16 +00:00
|
|
|
MSGCONVERSION Conversion;
|
|
|
|
NTUSERGETMESSAGEINFO Info;
|
2003-08-01 18:45:35 +00:00
|
|
|
PUSER32_THREAD_DATA ThreadData = User32GetThreadData();
|
|
|
|
|
2004-04-29 21:13:16 +00:00
|
|
|
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);
|
2003-08-01 18:45:35 +00:00
|
|
|
if (Res && lpMsg->message != WM_PAINT && lpMsg->message != WM_QUIT)
|
|
|
|
{
|
2004-04-29 21:13:16 +00:00
|
|
|
ThreadData->LastMessage = Info.Msg;
|
2003-08-01 18:45:35 +00:00
|
|
|
}
|
2004-04-29 21:13:16 +00:00
|
|
|
|
|
|
|
return Res;
|
2001-06-12 17:51:51 +00:00
|
|
|
}
|
|
|
|
|
2003-07-10 21:04:32 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2004-01-23 23:38:26 +00:00
|
|
|
BOOL
|
2001-06-12 17:51:51 +00:00
|
|
|
STDCALL
|
|
|
|
PeekMessageW(
|
|
|
|
LPMSG lpMsg,
|
|
|
|
HWND hWnd,
|
|
|
|
UINT wMsgFilterMin,
|
|
|
|
UINT wMsgFilterMax,
|
|
|
|
UINT wRemoveMsg)
|
|
|
|
{
|
2003-08-01 18:45:35 +00:00
|
|
|
BOOL Res;
|
2004-04-29 21:13:16 +00:00
|
|
|
MSGCONVERSION Conversion;
|
|
|
|
NTUSERGETMESSAGEINFO Info;
|
2003-08-01 18:45:35 +00:00
|
|
|
PUSER32_THREAD_DATA ThreadData = User32GetThreadData();
|
2004-04-29 21:13:16 +00:00
|
|
|
|
|
|
|
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);
|
2003-08-01 18:45:35 +00:00
|
|
|
if (Res && lpMsg->message != WM_PAINT && lpMsg->message != WM_QUIT)
|
|
|
|
{
|
2004-04-29 21:13:16 +00:00
|
|
|
ThreadData->LastMessage = Info.Msg;
|
2003-08-01 18:45:35 +00:00
|
|
|
}
|
2004-04-29 21:13:16 +00:00
|
|
|
|
|
|
|
return Res;
|
2001-06-12 17:51:51 +00:00
|
|
|
}
|
|
|
|
|
2003-07-10 21:04:32 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2004-01-23 23:38:26 +00:00
|
|
|
BOOL
|
2001-06-12 17:51:51 +00:00
|
|
|
STDCALL
|
|
|
|
PostMessageA(
|
2004-04-29 21:13:16 +00:00
|
|
|
HWND Wnd,
|
2001-06-12 17:51:51 +00:00
|
|
|
UINT Msg,
|
|
|
|
WPARAM wParam,
|
|
|
|
LPARAM lParam)
|
|
|
|
{
|
2004-04-29 21:13:16 +00:00
|
|
|
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;
|
2001-06-12 17:51:51 +00:00
|
|
|
}
|
|
|
|
|
2003-07-10 21:04:32 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2004-01-23 23:38:26 +00:00
|
|
|
BOOL
|
2001-06-12 17:51:51 +00:00
|
|
|
STDCALL
|
|
|
|
PostMessageW(
|
2004-04-29 21:13:16 +00:00
|
|
|
HWND Wnd,
|
2001-06-12 17:51:51 +00:00
|
|
|
UINT Msg,
|
|
|
|
WPARAM wParam,
|
|
|
|
LPARAM lParam)
|
|
|
|
{
|
2004-04-29 21:13:16 +00:00
|
|
|
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;
|
2001-06-12 17:51:51 +00:00
|
|
|
}
|
|
|
|
|
2003-07-10 21:04:32 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2001-06-12 17:51:51 +00:00
|
|
|
VOID
|
|
|
|
STDCALL
|
|
|
|
PostQuitMessage(
|
|
|
|
int nExitCode)
|
|
|
|
{
|
2003-03-06 23:57:03 +00:00
|
|
|
(void) NtUserPostMessage(NULL, WM_QUIT, nExitCode, 0);
|
2001-06-12 17:51:51 +00:00
|
|
|
}
|
|
|
|
|
2003-07-10 21:04:32 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2004-01-23 23:38:26 +00:00
|
|
|
BOOL
|
2001-06-12 17:51:51 +00:00
|
|
|
STDCALL
|
|
|
|
PostThreadMessageA(
|
|
|
|
DWORD idThread,
|
|
|
|
UINT Msg,
|
|
|
|
WPARAM wParam,
|
|
|
|
LPARAM lParam)
|
|
|
|
{
|
|
|
|
return NtUserPostThreadMessage(idThread, Msg, wParam, lParam);
|
|
|
|
}
|
|
|
|
|
2003-07-10 21:04:32 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2004-01-23 23:38:26 +00:00
|
|
|
BOOL
|
2001-06-12 17:51:51 +00:00
|
|
|
STDCALL
|
|
|
|
PostThreadMessageW(
|
|
|
|
DWORD idThread,
|
|
|
|
UINT Msg,
|
|
|
|
WPARAM wParam,
|
|
|
|
LPARAM lParam)
|
|
|
|
{
|
|
|
|
return NtUserPostThreadMessage(idThread, Msg, wParam, lParam);
|
|
|
|
}
|
|
|
|
|
2003-07-10 21:04:32 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2002-09-03 22:44:21 +00:00
|
|
|
LRESULT STDCALL
|
2003-12-14 11:36:43 +00:00
|
|
|
SendMessageW(HWND Wnd,
|
2002-09-03 22:44:21 +00:00
|
|
|
UINT Msg,
|
|
|
|
WPARAM wParam,
|
|
|
|
LPARAM lParam)
|
2001-06-12 17:51:51 +00:00
|
|
|
{
|
2004-04-29 21:13:16 +00:00
|
|
|
MSG UMMsg, KMMsg;
|
2003-12-14 11:36:43 +00:00
|
|
|
NTUSERSENDMESSAGEINFO Info;
|
|
|
|
LRESULT Result;
|
|
|
|
|
2004-04-29 21:13:16 +00:00
|
|
|
UMMsg.hwnd = Wnd;
|
|
|
|
UMMsg.message = Msg;
|
|
|
|
UMMsg.wParam = wParam;
|
|
|
|
UMMsg.lParam = lParam;
|
|
|
|
if (! MsgiUMToKMMessage(&UMMsg, &KMMsg, FALSE))
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
2004-01-28 20:54:30 +00:00
|
|
|
Info.Ansi = FALSE;
|
2004-04-29 21:13:16 +00:00
|
|
|
Result = NtUserSendMessage(KMMsg.hwnd, KMMsg.message,
|
|
|
|
KMMsg.wParam, KMMsg.lParam, &Info);
|
2003-12-14 11:36:43 +00:00
|
|
|
if (! Info.HandledByKernel)
|
|
|
|
{
|
2004-04-29 21:13:16 +00:00
|
|
|
MsgiUMToKMCleanup(&UMMsg, &KMMsg);
|
2003-12-14 11:36:43 +00:00
|
|
|
/* We need to send the message ourselves */
|
2004-04-29 21:13:16 +00:00
|
|
|
Result = IntCallWindowProcW(Info.Ansi, Info.Proc, UMMsg.hwnd, UMMsg.message,
|
|
|
|
UMMsg.wParam, UMMsg.lParam);
|
|
|
|
}
|
|
|
|
else if (! MsgiUMToKMReply(&UMMsg, &KMMsg, &Result))
|
|
|
|
{
|
|
|
|
return FALSE;
|
2003-12-14 11:36:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return Result;
|
2002-09-03 22:44:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-07-10 21:04:32 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2002-09-03 22:44:21 +00:00
|
|
|
LRESULT STDCALL
|
2003-12-14 11:36:43 +00:00
|
|
|
SendMessageA(HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam)
|
2002-09-03 22:44:21 +00:00
|
|
|
{
|
2004-04-29 21:13:16 +00:00
|
|
|
MSG AnsiMsg, UcMsg;
|
|
|
|
MSG KMMsg;
|
2002-09-03 22:44:21 +00:00
|
|
|
LRESULT Result;
|
2003-12-14 11:36:43 +00:00
|
|
|
NTUSERSENDMESSAGEINFO Info;
|
2002-09-03 22:44:21 +00:00
|
|
|
|
2003-12-14 11:36:43 +00:00
|
|
|
AnsiMsg.hwnd = Wnd;
|
2002-09-03 22:44:21 +00:00
|
|
|
AnsiMsg.message = Msg;
|
|
|
|
AnsiMsg.wParam = wParam;
|
|
|
|
AnsiMsg.lParam = lParam;
|
2003-12-14 11:36:43 +00:00
|
|
|
if (! MsgiAnsiToUnicodeMessage(&UcMsg, &AnsiMsg))
|
2002-09-03 22:44:21 +00:00
|
|
|
{
|
2003-12-14 11:36:43 +00:00
|
|
|
return FALSE;
|
2002-09-03 22:44:21 +00:00
|
|
|
}
|
2003-12-14 11:36:43 +00:00
|
|
|
|
2004-04-29 21:13:16 +00:00
|
|
|
if (! MsgiUMToKMMessage(&UcMsg, &KMMsg, FALSE))
|
|
|
|
{
|
|
|
|
MsgiAnsiToUnicodeCleanup(&UcMsg, &AnsiMsg);
|
|
|
|
return FALSE;
|
|
|
|
}
|
2004-01-28 20:54:30 +00:00
|
|
|
Info.Ansi = TRUE;
|
2004-04-29 21:13:16 +00:00
|
|
|
Result = NtUserSendMessage(KMMsg.hwnd, KMMsg.message,
|
|
|
|
KMMsg.wParam, KMMsg.lParam, &Info);
|
2003-12-14 11:36:43 +00:00
|
|
|
if (! Info.HandledByKernel)
|
2002-09-03 22:44:21 +00:00
|
|
|
{
|
2003-12-14 11:36:43 +00:00
|
|
|
/* We need to send the message ourselves */
|
|
|
|
if (Info.Ansi)
|
|
|
|
{
|
|
|
|
/* Ansi message and Ansi window proc, that's easy. Clean up
|
|
|
|
the Unicode message though */
|
2004-04-29 21:13:16 +00:00
|
|
|
MsgiUMToKMCleanup(&UcMsg, &KMMsg);
|
2003-12-14 11:36:43 +00:00
|
|
|
MsgiAnsiToUnicodeCleanup(&UcMsg, &AnsiMsg);
|
|
|
|
Result = IntCallWindowProcA(Info.Ansi, Info.Proc, Wnd, Msg, wParam, lParam);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Unicode winproc. Although we started out with an Ansi message we
|
|
|
|
already converted it to Unicode for the kernel call. Reuse that
|
|
|
|
message to avoid another conversion */
|
|
|
|
Result = IntCallWindowProcW(Info.Ansi, Info.Proc, UcMsg.hwnd,
|
|
|
|
UcMsg.message, UcMsg.wParam, UcMsg.lParam);
|
|
|
|
if (! MsgiAnsiToUnicodeReply(&UcMsg, &AnsiMsg, &Result))
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
2002-09-03 22:44:21 +00:00
|
|
|
}
|
2004-04-29 21:13:16 +00:00
|
|
|
/* Message sent by kernel. Convert back to Ansi */
|
|
|
|
else if (! MsgiUMToKMReply(&UcMsg, &KMMsg, &Result) ||
|
|
|
|
! MsgiAnsiToUnicodeReply(&UcMsg, &AnsiMsg, &Result))
|
2003-12-14 14:01:38 +00:00
|
|
|
{
|
2004-04-29 21:13:16 +00:00
|
|
|
return FALSE;
|
2003-12-14 14:01:38 +00:00
|
|
|
}
|
2003-12-14 11:36:43 +00:00
|
|
|
|
|
|
|
return Result;
|
2001-06-12 17:51:51 +00:00
|
|
|
}
|
|
|
|
|
2003-07-10 21:04:32 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2004-01-23 23:38:26 +00:00
|
|
|
BOOL
|
2001-06-12 17:51:51 +00:00
|
|
|
STDCALL
|
|
|
|
SendMessageCallbackA(
|
|
|
|
HWND hWnd,
|
|
|
|
UINT Msg,
|
|
|
|
WPARAM wParam,
|
|
|
|
LPARAM lParam,
|
|
|
|
SENDASYNCPROC lpCallBack,
|
|
|
|
ULONG_PTR dwData)
|
|
|
|
{
|
|
|
|
return NtUserSendMessageCallback(
|
|
|
|
hWnd,
|
|
|
|
Msg,
|
|
|
|
wParam,
|
|
|
|
lParam,
|
|
|
|
lpCallBack,
|
|
|
|
dwData);
|
|
|
|
}
|
|
|
|
|
2003-07-10 21:04:32 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2004-01-23 23:38:26 +00:00
|
|
|
BOOL
|
2001-06-12 17:51:51 +00:00
|
|
|
STDCALL
|
|
|
|
SendMessageCallbackW(
|
|
|
|
HWND hWnd,
|
|
|
|
UINT Msg,
|
|
|
|
WPARAM wParam,
|
|
|
|
LPARAM lParam,
|
|
|
|
SENDASYNCPROC lpCallBack,
|
|
|
|
ULONG_PTR dwData)
|
|
|
|
{
|
|
|
|
return NtUserSendMessageCallback(
|
|
|
|
hWnd,
|
|
|
|
Msg,
|
|
|
|
wParam,
|
|
|
|
lParam,
|
|
|
|
lpCallBack,
|
|
|
|
dwData);
|
|
|
|
}
|
|
|
|
|
2003-07-10 21:04:32 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2001-06-12 17:51:51 +00:00
|
|
|
LRESULT
|
|
|
|
STDCALL
|
|
|
|
SendMessageTimeoutA(
|
|
|
|
HWND hWnd,
|
|
|
|
UINT Msg,
|
|
|
|
WPARAM wParam,
|
|
|
|
LPARAM lParam,
|
|
|
|
UINT fuFlags,
|
|
|
|
UINT uTimeout,
|
|
|
|
PDWORD_PTR lpdwResult)
|
|
|
|
{
|
2004-03-11 14:47:44 +00:00
|
|
|
MSG AnsiMsg;
|
|
|
|
MSG UcMsg;
|
|
|
|
LRESULT Result;
|
|
|
|
NTUSERSENDMESSAGEINFO Info;
|
|
|
|
|
|
|
|
AnsiMsg.hwnd = hWnd;
|
|
|
|
AnsiMsg.message = Msg;
|
|
|
|
AnsiMsg.wParam = wParam;
|
|
|
|
AnsiMsg.lParam = lParam;
|
|
|
|
if (! MsgiAnsiToUnicodeMessage(&UcMsg, &AnsiMsg))
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
Info.Ansi = TRUE;
|
|
|
|
Result = NtUserSendMessageTimeout(UcMsg.hwnd, UcMsg.message,
|
|
|
|
UcMsg.wParam, UcMsg.lParam,
|
|
|
|
fuFlags, uTimeout, (ULONG_PTR*)lpdwResult, &Info);
|
|
|
|
if(!Result)
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
if (! Info.HandledByKernel)
|
|
|
|
{
|
|
|
|
/* We need to send the message ourselves */
|
|
|
|
if (Info.Ansi)
|
|
|
|
{
|
|
|
|
/* Ansi message and Ansi window proc, that's easy. Clean up
|
|
|
|
the Unicode message though */
|
|
|
|
MsgiAnsiToUnicodeCleanup(&UcMsg, &AnsiMsg);
|
|
|
|
Result = IntCallWindowProcA(Info.Ansi, Info.Proc, hWnd, Msg, wParam, lParam);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Unicode winproc. Although we started out with an Ansi message we
|
|
|
|
already converted it to Unicode for the kernel call. Reuse that
|
|
|
|
message to avoid another conversion */
|
|
|
|
Result = IntCallWindowProcW(Info.Ansi, Info.Proc, UcMsg.hwnd,
|
|
|
|
UcMsg.message, UcMsg.wParam, UcMsg.lParam);
|
|
|
|
if (! MsgiAnsiToUnicodeReply(&UcMsg, &AnsiMsg, &Result))
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(lpdwResult)
|
|
|
|
*lpdwResult = Result;
|
|
|
|
Result = TRUE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Message sent by kernel. Convert back to Ansi */
|
|
|
|
if (! MsgiAnsiToUnicodeReply(&UcMsg, &AnsiMsg, &Result))
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return Result;
|
2001-06-12 17:51:51 +00:00
|
|
|
}
|
|
|
|
|
2003-07-10 21:04:32 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2001-06-12 17:51:51 +00:00
|
|
|
LRESULT
|
|
|
|
STDCALL
|
|
|
|
SendMessageTimeoutW(
|
|
|
|
HWND hWnd,
|
|
|
|
UINT Msg,
|
|
|
|
WPARAM wParam,
|
|
|
|
LPARAM lParam,
|
|
|
|
UINT fuFlags,
|
|
|
|
UINT uTimeout,
|
|
|
|
PDWORD_PTR lpdwResult)
|
|
|
|
{
|
2004-03-11 14:47:44 +00:00
|
|
|
NTUSERSENDMESSAGEINFO Info;
|
|
|
|
LRESULT Result;
|
|
|
|
|
|
|
|
Info.Ansi = FALSE;
|
2005-05-09 01:42:07 +00:00
|
|
|
Result = NtUserSendMessageTimeout(hWnd, Msg, wParam, lParam, fuFlags, uTimeout,
|
2004-03-11 14:47:44 +00:00
|
|
|
lpdwResult, &Info);
|
|
|
|
if (! Info.HandledByKernel)
|
|
|
|
{
|
|
|
|
/* We need to send the message ourselves */
|
|
|
|
Result = IntCallWindowProcW(Info.Ansi, Info.Proc, hWnd, Msg, wParam, lParam);
|
|
|
|
if(lpdwResult)
|
|
|
|
*lpdwResult = Result;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return Result;
|
2001-06-12 17:51:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-07-10 21:04:32 +00:00
|
|
|
/*
|
|
|
|
* @unimplemented
|
|
|
|
*/
|
2004-01-23 23:38:26 +00:00
|
|
|
BOOL
|
2001-06-12 17:51:51 +00:00
|
|
|
STDCALL
|
|
|
|
SendNotifyMessageA(
|
|
|
|
HWND hWnd,
|
|
|
|
UINT Msg,
|
|
|
|
WPARAM wParam,
|
|
|
|
LPARAM lParam)
|
|
|
|
{
|
2003-05-12 19:30:00 +00:00
|
|
|
UNIMPLEMENTED;
|
2001-06-12 17:51:51 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2003-07-10 21:04:32 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* @unimplemented
|
|
|
|
*/
|
2004-01-23 23:38:26 +00:00
|
|
|
BOOL
|
2001-06-12 17:51:51 +00:00
|
|
|
STDCALL
|
|
|
|
SendNotifyMessageW(
|
|
|
|
HWND hWnd,
|
|
|
|
UINT Msg,
|
|
|
|
WPARAM wParam,
|
|
|
|
LPARAM lParam)
|
|
|
|
{
|
2003-05-12 19:30:00 +00:00
|
|
|
UNIMPLEMENTED;
|
2001-06-12 17:51:51 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2003-07-10 21:04:32 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2004-01-23 23:38:26 +00:00
|
|
|
BOOL STDCALL
|
2004-04-09 20:03:21 +00:00
|
|
|
TranslateMessageEx(CONST MSG *lpMsg, DWORD unk)
|
2001-06-12 17:51:51 +00:00
|
|
|
{
|
2004-04-09 20:03:21 +00:00
|
|
|
return(NtUserTranslateMessage((LPMSG)lpMsg, (HKL)unk));
|
2003-08-14 20:25:52 +00:00
|
|
|
}
|
|
|
|
|
2004-04-09 20:03:21 +00:00
|
|
|
|
2003-08-14 20:25:52 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2004-01-23 23:38:26 +00:00
|
|
|
BOOL STDCALL
|
2004-04-09 20:03:21 +00:00
|
|
|
TranslateMessage(CONST MSG *lpMsg)
|
2003-08-14 20:25:52 +00:00
|
|
|
{
|
2004-04-09 20:03:21 +00:00
|
|
|
return(TranslateMessageEx((LPMSG)lpMsg, 0));
|
2001-06-12 17:51:51 +00:00
|
|
|
}
|
|
|
|
|
2003-07-10 21:04:32 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2004-01-23 23:38:26 +00:00
|
|
|
BOOL
|
2001-06-12 17:51:51 +00:00
|
|
|
STDCALL
|
|
|
|
WaitMessage(VOID)
|
|
|
|
{
|
2003-05-21 22:58:43 +00:00
|
|
|
return NtUserWaitMessage();
|
2001-06-12 17:51:51 +00:00
|
|
|
}
|
|
|
|
|
2003-07-10 21:04:32 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2002-05-06 22:20:32 +00:00
|
|
|
UINT STDCALL
|
|
|
|
RegisterWindowMessageA(LPCSTR lpString)
|
|
|
|
{
|
|
|
|
UNICODE_STRING String;
|
|
|
|
BOOLEAN Result;
|
|
|
|
UINT Atom;
|
|
|
|
|
2002-09-17 23:46:23 +00:00
|
|
|
Result = RtlCreateUnicodeStringFromAsciiz(&String, (PCSZ)lpString);
|
2002-05-06 22:20:32 +00:00
|
|
|
if (!Result)
|
|
|
|
{
|
|
|
|
return(0);
|
|
|
|
}
|
2003-05-02 07:52:33 +00:00
|
|
|
Atom = NtUserRegisterWindowMessage(&String);
|
2002-05-06 22:20:32 +00:00
|
|
|
RtlFreeUnicodeString(&String);
|
|
|
|
return(Atom);
|
|
|
|
}
|
|
|
|
|
2003-07-10 21:04:32 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2002-05-06 22:20:32 +00:00
|
|
|
UINT STDCALL
|
|
|
|
RegisterWindowMessageW(LPCWSTR lpString)
|
|
|
|
{
|
2003-05-02 07:52:33 +00:00
|
|
|
UNICODE_STRING String;
|
|
|
|
|
|
|
|
RtlInitUnicodeString(&String, lpString);
|
|
|
|
return(NtUserRegisterWindowMessage(&String));
|
2002-05-06 22:20:32 +00:00
|
|
|
}
|
|
|
|
|
2003-07-27 11:54:42 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
HWND STDCALL
|
|
|
|
SetCapture(HWND hWnd)
|
|
|
|
{
|
|
|
|
return(NtUserSetCapture(hWnd));
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
HWND STDCALL
|
|
|
|
GetCapture(VOID)
|
|
|
|
{
|
|
|
|
return(NtUserGetCapture());
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2004-01-23 23:38:26 +00:00
|
|
|
BOOL STDCALL
|
2003-07-27 11:54:42 +00:00
|
|
|
ReleaseCapture(VOID)
|
|
|
|
{
|
|
|
|
NtUserSetCapture(NULL);
|
|
|
|
return(TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-08-02 16:56:13 +00:00
|
|
|
/*
|
|
|
|
* @unimplemented
|
|
|
|
*/
|
|
|
|
DWORD
|
|
|
|
STDCALL
|
2003-11-19 13:19:40 +00:00
|
|
|
RealGetQueueStatus(UINT flags)
|
2003-08-02 16:56:13 +00:00
|
|
|
{
|
|
|
|
DWORD ret;
|
2005-05-09 01:42:07 +00:00
|
|
|
WORD changed_bits, wake_bits;
|
2003-08-02 16:56:13 +00:00
|
|
|
|
|
|
|
#if 0 /* wine stuff. don't know what it does... */
|
|
|
|
|
|
|
|
/* check for pending X events */
|
|
|
|
if (USER_Driver.pMsgWaitForMultipleObjectsEx)
|
|
|
|
USER_Driver.pMsgWaitForMultipleObjectsEx( 0, NULL, 0, 0, 0 );
|
|
|
|
#endif
|
|
|
|
|
|
|
|
ret = NtUserGetQueueStatus(TRUE /*ClearChanges*/);
|
|
|
|
|
|
|
|
changed_bits = LOWORD(ret);
|
|
|
|
wake_bits = HIWORD(ret);
|
|
|
|
|
|
|
|
return MAKELONG(changed_bits & flags, wake_bits & flags);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @unimplemented
|
|
|
|
*/
|
2004-01-23 23:38:26 +00:00
|
|
|
BOOL STDCALL GetInputState(VOID)
|
2003-08-02 16:56:13 +00:00
|
|
|
{
|
|
|
|
DWORD ret;
|
|
|
|
WORD wake_bits;
|
|
|
|
|
2005-05-09 01:42:07 +00:00
|
|
|
#if 0 /* wine stuff. don't know what it does... */
|
2003-08-02 16:56:13 +00:00
|
|
|
|
|
|
|
/* check for pending X events */
|
|
|
|
if (USER_Driver.pMsgWaitForMultipleObjectsEx)
|
|
|
|
USER_Driver.pMsgWaitForMultipleObjectsEx( 0, NULL, 0, 0, 0 );
|
|
|
|
#endif
|
|
|
|
|
|
|
|
ret = NtUserGetQueueStatus(FALSE /*ClearChanges*/);
|
2005-05-09 01:42:07 +00:00
|
|
|
|
2003-08-02 16:56:13 +00:00
|
|
|
wake_bits = HIWORD(ret);
|
|
|
|
|
|
|
|
return wake_bits & (QS_KEY | QS_MOUSEBUTTON);
|
|
|
|
}
|
|
|
|
|
2004-04-29 21:13:16 +00:00
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2003-08-14 20:25:52 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2004-01-23 23:38:26 +00:00
|
|
|
BOOL STDCALL SetMessageQueue(int cMessagesMax)
|
2003-08-14 20:25:52 +00:00
|
|
|
{
|
|
|
|
/* Function does nothing on 32 bit windows */
|
|
|
|
return TRUE;
|
|
|
|
}
|
2003-11-19 13:19:40 +00:00
|
|
|
typedef DWORD (WINAPI * RealGetQueueStatusProc)(UINT flags);
|
2004-04-09 20:03:21 +00:00
|
|
|
typedef DWORD (WINAPI * RealMsgWaitForMultipleObjectsExProc)(DWORD nCount, CONST HANDLE *lpHandles, DWORD dwMilliseconds, DWORD dwWakeMask, DWORD dwFlags);
|
2003-08-14 20:25:52 +00:00
|
|
|
|
2003-11-19 13:19:40 +00:00
|
|
|
typedef struct _USER_MESSAGE_PUMP_ADDRESSES {
|
|
|
|
DWORD cbSize;
|
|
|
|
//NtUserRealInternalGetMessageProc NtUserRealInternalGetMessage;
|
|
|
|
//NtUserRealWaitMessageExProc NtUserRealWaitMessageEx;
|
|
|
|
RealGetQueueStatusProc RealGetQueueStatus;
|
|
|
|
RealMsgWaitForMultipleObjectsExProc RealMsgWaitForMultipleObjectsEx;
|
|
|
|
} USER_MESSAGE_PUMP_ADDRESSES, * PUSER_MESSAGE_PUMP_ADDRESSES;
|
2003-07-27 11:54:42 +00:00
|
|
|
|
2003-11-19 13:19:40 +00:00
|
|
|
DWORD
|
|
|
|
STDCALL
|
|
|
|
RealMsgWaitForMultipleObjectsEx(
|
|
|
|
DWORD nCount,
|
2004-04-09 20:03:21 +00:00
|
|
|
CONST HANDLE *pHandles,
|
2003-11-19 13:19:40 +00:00
|
|
|
DWORD dwMilliseconds,
|
|
|
|
DWORD dwWakeMask,
|
|
|
|
DWORD dwFlags);
|
|
|
|
|
|
|
|
typedef BOOL (WINAPI * MESSAGEPUMPHOOKPROC)(BOOL Unregistering,PUSER_MESSAGE_PUMP_ADDRESSES MessagePumpAddresses);
|
|
|
|
|
2004-04-09 20:03:21 +00:00
|
|
|
CRITICAL_SECTION gcsMPH;
|
2003-11-19 13:19:40 +00:00
|
|
|
MESSAGEPUMPHOOKPROC gpfnInitMPH;
|
|
|
|
DWORD gcLoadMPH = 0;
|
|
|
|
USER_MESSAGE_PUMP_ADDRESSES gmph = {sizeof(USER_MESSAGE_PUMP_ADDRESSES),
|
|
|
|
//NtUserRealInternalGetMessage,
|
|
|
|
//NtUserRealInternalWaitMessageEx,
|
|
|
|
RealGetQueueStatus,
|
|
|
|
RealMsgWaitForMultipleObjectsEx
|
|
|
|
};
|
|
|
|
|
|
|
|
DWORD gfMessagePumpHook = 0;
|
|
|
|
|
|
|
|
BOOL WINAPI IsInsideMessagePumpHook()
|
|
|
|
{
|
|
|
|
if(!gfMessagePumpHook)
|
|
|
|
return FALSE;
|
2005-05-09 01:42:07 +00:00
|
|
|
|
2004-12-30 02:32:26 +00:00
|
|
|
/* This code checks if we're inside SendMessage. */
|
2004-12-25 22:59:10 +00:00
|
|
|
#if 0
|
2003-11-19 13:19:40 +00:00
|
|
|
/* Since our TEB doesnt match that of real windows, testing this value is useless until we know what it does
|
|
|
|
PUCHAR NtTeb = (PUCHAR)NtCurrentTeb();
|
|
|
|
|
|
|
|
if(!*(PLONG*)&NtTeb[0x708])
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if(**(PLONG*)&NtTeb[0x708] <= 0)
|
|
|
|
return FALSE;*/
|
2004-12-25 22:59:10 +00:00
|
|
|
#endif
|
2003-11-19 13:19:40 +00:00
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void WINAPI ResetMessagePumpHook(PUSER_MESSAGE_PUMP_ADDRESSES Addresses)
|
|
|
|
{
|
|
|
|
Addresses->cbSize = sizeof(USER_MESSAGE_PUMP_ADDRESSES);
|
|
|
|
//Addresses->NtUserRealInternalGetMessage = (NtUserRealInternalGetMessageProc)NtUserRealInternalGetMessage;
|
|
|
|
//Addresses->NtUserRealWaitMessageEx = (NtUserRealWaitMessageExProc)NtUserRealInternalWaitMessageEx;
|
|
|
|
Addresses->RealGetQueueStatus = RealGetQueueStatus;
|
|
|
|
Addresses->RealMsgWaitForMultipleObjectsEx = RealMsgWaitForMultipleObjectsEx;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL WINAPI RegisterMessagePumpHook(MESSAGEPUMPHOOKPROC Hook)
|
|
|
|
{
|
2004-04-09 20:03:21 +00:00
|
|
|
EnterCriticalSection(&gcsMPH);
|
2003-11-19 13:19:40 +00:00
|
|
|
if(!Hook) {
|
|
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
2004-04-09 20:03:21 +00:00
|
|
|
LeaveCriticalSection(&gcsMPH);
|
2003-11-19 13:19:40 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
if(!gcLoadMPH) {
|
|
|
|
USER_MESSAGE_PUMP_ADDRESSES Addresses;
|
|
|
|
gpfnInitMPH = Hook;
|
|
|
|
ResetMessagePumpHook(&Addresses);
|
|
|
|
if(!Hook(FALSE, &Addresses) || !Addresses.cbSize) {
|
2004-04-09 20:03:21 +00:00
|
|
|
LeaveCriticalSection(&gcsMPH);
|
2003-11-19 13:19:40 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
memcpy(&gmph, &Addresses, Addresses.cbSize);
|
|
|
|
} else {
|
|
|
|
if(gpfnInitMPH != Hook) {
|
2004-04-09 20:03:21 +00:00
|
|
|
LeaveCriticalSection(&gcsMPH);
|
2003-11-19 13:19:40 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(NtUserCallNoParam(NOPARAM_ROUTINE_INIT_MESSAGE_PUMP)) {
|
2004-04-09 20:03:21 +00:00
|
|
|
LeaveCriticalSection(&gcsMPH);
|
2003-11-19 13:19:40 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
if (!gcLoadMPH++) {
|
2004-12-13 15:39:52 +00:00
|
|
|
InterlockedExchange((PLONG)&gfMessagePumpHook, 1);
|
2003-11-19 13:19:40 +00:00
|
|
|
}
|
2004-04-09 20:03:21 +00:00
|
|
|
LeaveCriticalSection(&gcsMPH);
|
2003-11-19 13:19:40 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
2003-07-27 11:54:42 +00:00
|
|
|
|
2003-11-19 13:19:40 +00:00
|
|
|
BOOL WINAPI UnregisterMessagePumpHook(VOID)
|
|
|
|
{
|
2004-04-09 20:03:21 +00:00
|
|
|
EnterCriticalSection(&gcsMPH);
|
2003-11-19 13:19:40 +00:00
|
|
|
if(gcLoadMPH > 0) {
|
|
|
|
if(NtUserCallNoParam(NOPARAM_ROUTINE_UNINIT_MESSAGE_PUMP)) {
|
|
|
|
gcLoadMPH--;
|
|
|
|
if(!gcLoadMPH) {
|
2004-12-13 15:39:52 +00:00
|
|
|
InterlockedExchange((PLONG)&gfMessagePumpHook, 0);
|
2003-11-19 13:19:40 +00:00
|
|
|
gpfnInitMPH(TRUE, NULL);
|
|
|
|
ResetMessagePumpHook(&gmph);
|
|
|
|
gpfnInitMPH = 0;
|
|
|
|
}
|
2004-04-09 20:03:21 +00:00
|
|
|
LeaveCriticalSection(&gcsMPH);
|
2003-11-19 13:19:40 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
2004-04-09 20:03:21 +00:00
|
|
|
LeaveCriticalSection(&gcsMPH);
|
2003-11-19 13:19:40 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
DWORD WINAPI GetQueueStatus(UINT flags)
|
|
|
|
{
|
|
|
|
return IsInsideMessagePumpHook() ? gmph.RealGetQueueStatus(flags) : RealGetQueueStatus(flags);
|
|
|
|
}
|
|
|
|
|
2004-12-25 22:59:10 +00:00
|
|
|
/**
|
|
|
|
* @name RealMsgWaitForMultipleObjectsEx
|
|
|
|
*
|
|
|
|
* Wait either for either message arrival or for one of the passed events
|
|
|
|
* to be signalled.
|
|
|
|
*
|
|
|
|
* @param nCount
|
|
|
|
* Number of handles in the pHandles array.
|
|
|
|
* @param pHandles
|
|
|
|
* Handles of events to wait for.
|
|
|
|
* @param dwMilliseconds
|
|
|
|
* Timeout interval.
|
|
|
|
* @param dwWakeMask
|
|
|
|
* Mask specifying on which message events we should wakeup.
|
|
|
|
* @param dwFlags
|
|
|
|
* Wait type (see MWMO_* constants).
|
|
|
|
*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
|
|
|
|
DWORD STDCALL
|
|
|
|
RealMsgWaitForMultipleObjectsEx(
|
|
|
|
DWORD nCount,
|
|
|
|
const HANDLE *pHandles,
|
|
|
|
DWORD dwMilliseconds,
|
|
|
|
DWORD dwWakeMask,
|
|
|
|
DWORD dwFlags)
|
|
|
|
{
|
|
|
|
LPHANDLE RealHandles;
|
|
|
|
HANDLE MessageQueueHandle;
|
|
|
|
DWORD Result;
|
2005-01-06 10:16:18 +00:00
|
|
|
|
2004-12-25 22:59:10 +00:00
|
|
|
if (dwFlags & ~(MWMO_WAITALL | MWMO_ALERTABLE | MWMO_INPUTAVAILABLE))
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
|
|
return WAIT_FAILED;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
if (dwFlags & MWMO_INPUTAVAILABLE)
|
|
|
|
{
|
|
|
|
RealGetQueueStatus(dwWakeMask);
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
|
|
|
MessageQueueHandle = NtUserMsqSetWakeMask(dwWakeMask);
|
|
|
|
if (MessageQueueHandle == NULL)
|
|
|
|
{
|
|
|
|
SetLastError(0); /* ? */
|
|
|
|
return WAIT_FAILED;
|
|
|
|
}
|
|
|
|
|
|
|
|
RealHandles = HeapAlloc(GetProcessHeap(), 0, (nCount + 1) * sizeof(HANDLE));
|
|
|
|
if (RealHandles == NULL)
|
|
|
|
{
|
|
|
|
NtUserMsqClearWakeMask();
|
|
|
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
|
|
return WAIT_FAILED;
|
|
|
|
}
|
|
|
|
|
2005-01-06 10:16:18 +00:00
|
|
|
RtlCopyMemory(RealHandles, pHandles, nCount * sizeof(HANDLE));
|
2004-12-25 22:59:10 +00:00
|
|
|
RealHandles[nCount] = MessageQueueHandle;
|
|
|
|
|
|
|
|
Result = WaitForMultipleObjectsEx(nCount + 1, RealHandles,
|
|
|
|
dwFlags & MWMO_WAITALL,
|
|
|
|
dwMilliseconds, dwFlags & MWMO_ALERTABLE);
|
|
|
|
|
|
|
|
HeapFree(GetProcessHeap(), 0, RealHandles);
|
|
|
|
NtUserMsqClearWakeMask();
|
|
|
|
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
2004-12-27 16:48:29 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
DWORD WINAPI
|
|
|
|
MsgWaitForMultipleObjectsEx(
|
|
|
|
DWORD nCount,
|
|
|
|
CONST HANDLE *lpHandles,
|
|
|
|
DWORD dwMilliseconds,
|
|
|
|
DWORD dwWakeMask,
|
|
|
|
DWORD dwFlags)
|
2003-11-19 13:19:40 +00:00
|
|
|
{
|
2004-12-27 16:48:29 +00:00
|
|
|
return IsInsideMessagePumpHook() ? gmph.RealMsgWaitForMultipleObjectsEx(nCount, lpHandles, dwMilliseconds, dwWakeMask, dwFlags) : RealMsgWaitForMultipleObjectsEx(nCount, lpHandles,dwMilliseconds, dwWakeMask, dwFlags);
|
2003-11-19 13:19:40 +00:00
|
|
|
}
|
2004-04-29 21:13:16 +00:00
|
|
|
|
2004-12-27 16:48:29 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
DWORD STDCALL
|
|
|
|
MsgWaitForMultipleObjects(
|
|
|
|
DWORD nCount,
|
|
|
|
CONST HANDLE *lpHandles,
|
|
|
|
BOOL fWaitAll,
|
|
|
|
DWORD dwMilliseconds,
|
|
|
|
DWORD dwWakeMask)
|
|
|
|
{
|
|
|
|
return MsgWaitForMultipleObjectsEx(nCount, lpHandles, dwMilliseconds,
|
|
|
|
dwWakeMask, fWaitAll ? MWMO_WAITALL : 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-12-12 20:15:23 +00:00
|
|
|
BOOL FASTCALL MessageInit(VOID)
|
2004-04-29 21:13:16 +00:00
|
|
|
{
|
|
|
|
InitializeCriticalSection(&DdeCrst);
|
|
|
|
InitializeCriticalSection(&MsgConversionCrst);
|
2005-12-12 20:15:23 +00:00
|
|
|
InitializeCriticalSection(&gcsMPH);
|
2004-04-29 21:13:16 +00:00
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
2005-12-03 17:21:37 +00:00
|
|
|
|
2005-12-12 20:15:23 +00:00
|
|
|
VOID FASTCALL MessageCleanup(VOID)
|
|
|
|
{
|
|
|
|
DeleteCriticalSection(&DdeCrst);
|
|
|
|
DeleteCriticalSection(&MsgConversionCrst);
|
|
|
|
DeleteCriticalSection(&gcsMPH);
|
|
|
|
}
|
|
|
|
|
2005-12-03 17:21:37 +00:00
|
|
|
/***********************************************************************
|
|
|
|
* map_wparam_AtoW
|
|
|
|
*
|
|
|
|
* Convert the wparam of an ASCII message to Unicode.
|
|
|
|
*/
|
|
|
|
static WPARAM
|
|
|
|
map_wparam_AtoW( UINT message, WPARAM wparam )
|
|
|
|
{
|
|
|
|
switch(message)
|
|
|
|
{
|
|
|
|
case WM_CHARTOITEM:
|
|
|
|
case EM_SETPASSWORDCHAR:
|
|
|
|
case WM_CHAR:
|
|
|
|
case WM_DEADCHAR:
|
|
|
|
case WM_SYSCHAR:
|
|
|
|
case WM_SYSDEADCHAR:
|
|
|
|
case WM_MENUCHAR:
|
|
|
|
{
|
|
|
|
char ch[2];
|
|
|
|
WCHAR wch[2];
|
|
|
|
ch[0] = (wparam & 0xff);
|
|
|
|
ch[1] = (wparam >> 8);
|
|
|
|
MultiByteToWideChar(CP_ACP, 0, ch, 2, wch, 2);
|
|
|
|
wparam = MAKEWPARAM(wch[0], wch[1]);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case WM_IME_CHAR:
|
|
|
|
{
|
|
|
|
char ch[2];
|
|
|
|
WCHAR wch;
|
|
|
|
ch[0] = (wparam >> 8);
|
|
|
|
ch[1] = (wparam & 0xff);
|
|
|
|
if (ch[0]) MultiByteToWideChar(CP_ACP, 0, ch, 2, &wch, 1);
|
|
|
|
else MultiByteToWideChar(CP_ACP, 0, &ch[1], 1, &wch, 1);
|
|
|
|
wparam = MAKEWPARAM( wch, HIWORD(wparam) );
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return wparam;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
BOOL WINAPI
|
|
|
|
IsDialogMessageA( HWND hwndDlg, LPMSG pmsg )
|
|
|
|
{
|
|
|
|
MSG msg = *pmsg;
|
|
|
|
msg.wParam = map_wparam_AtoW( msg.message, msg.wParam );
|
|
|
|
return IsDialogMessageW( hwndDlg, &msg );
|
|
|
|
}
|