-/* $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
* FILE: lib/user32/windows/message.c
* UPDATE HISTORY:
* 06-06-2001 CSH Created
*/
-#include <windows.h>
+
#include <user32.h>
-#include <string.h>
+#define NDEBUG
#include <debug.h>
-#include <user32/callback.h>
-#include <message.h>
-#define NTOS_MODE_USER
-#include <ntos.h>
/* 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.
}
else
{
- New = HeapAlloc(GetProcessHeap(), 0,
+ New = HeapAlloc(GetProcessHeap(), 0,
(DdeNumAlloc + GROWBY) * sizeof(DDEPAIR));
}
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)
GlobalUnlock((HGLOBAL) UMMsg->lParam);
}
break;
+
+ 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;
+
+ RtlCopyMemory(pKMCopyData + 1, pUMCopyData->lpData,
+ pUMCopyData->cbData);
+
+ KMMsg->lParam = (LPARAM)pKMCopyData;
+ }
+ break;
+
default:
break;
}
{
case WM_DDE_ACK:
case WM_DDE_EXECUTE:
+ case WM_COPYDATA:
HeapFree(GetProcessHeap(), 0, (LPVOID) KMMsg->lParam);
break;
default:
switch (UMMsg->message)
{
+ 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;
+
case WM_DDE_ACK:
{
PKMDDELPARAM DdeLparam = (PKMDDELPARAM) KMMsg->lParam;
{
UMMsg->lParam = DdeLparam->Value.Unpacked;
}
- break;
}
+ break;
+
case WM_DDE_EXECUTE:
{
PKMDDEEXECUTEDATA KMDdeExecuteData;
UMMsg->lParam = (LPARAM) GlobalData;
}
break;
+
+ case WM_COPYDATA:
+ {
+ PCOPYDATASTRUCT pKMCopyData = (PCOPYDATASTRUCT)KMMsg->lParam;
+ pKMCopyData->lpData = pKMCopyData + 1;
+ }
+ break;
+
default:
break;
}
}
break;
}
-
- case WM_GETTEXTLENGTH:
- case CB_GETLBTEXTLEN:
- case LB_GETTEXTLEN:
- {
- /* FIXME: There may be one DBCS char for each Unicode char */
- *Result *= 2;
- break;
- }
}
MsgiAnsiToUnicodeCleanup(UnicodeMsg, AnsiMsg);
}
CsA->lpszClass = AString.Buffer;
}
- UnicodeMsg->lParam = (LPARAM)CsA;
+ AnsiMsg->lParam = (LPARAM)CsA;
+ break;
+ }
+ 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;
}
case WM_SETTEXT:
switch(UnicodeMsg->message)
{
case WM_GETTEXT:
+ {
+ RtlFreeHeap(GetProcessHeap(), 0, (PVOID) AnsiMsg->lParam);
+ break;
+ }
case WM_SETTEXT:
{
ANSI_STRING AString;
if (0 < AnsiMsg->wParam &&
! MultiByteToWideChar(CP_ACP, 0, Buffer, -1, UBuffer, UnicodeMsg->wParam))
{
- UBuffer[AnsiMsg->wParam - 1] = L'\0';
+ UBuffer[UnicodeMsg->wParam - 1] = L'\0';
}
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);
+ MsgiUnicodeToAnsiCleanup(AnsiMsg, UnicodeMsg);
return TRUE;
}
}
else
{
- New = HeapAlloc(GetProcessHeap(), 0,
+ New = HeapAlloc(GetProcessHeap(), 0,
(MsgConversionNumAlloc + GROWBY) * sizeof(MSGCONVERSION));
}
STDCALL
InSendMessage(VOID)
{
+ static DWORD ShowNotImplemented = TRUE;
+ if (ShowNotImplemented)
+ {
+ DbgPrint("InSendMessage is unimplemented\n");
+ ShowNotImplemented = FALSE;
+ }
/* return(NtUserGetThreadState(THREADSTATE_INSENDMESSAGE) != ISMEX_NOSEND); */
- UNIMPLEMENTED;
return FALSE;
}
}
}
-STATIC LRESULT FASTCALL
+static LRESULT FASTCALL
IntCallWindowProcA(BOOL IsAnsiProc,
WNDPROC WndProc,
HWND hWnd,
LRESULT Result;
Info.Ansi = FALSE;
- Result = NtUserSendMessageTimeout(hWnd, Msg, wParam, lParam, fuFlags, uTimeout,
+ Result = NtUserSendMessageTimeout(hWnd, Msg, wParam, lParam, fuFlags, uTimeout,
lpdwResult, &Info);
if (! Info.HandledByKernel)
{
RealGetQueueStatus(UINT flags)
{
DWORD ret;
- WORD changed_bits, wake_bits;
+ WORD changed_bits, wake_bits;
#if 0 /* wine stuff. don't know what it does... */
DWORD ret;
WORD wake_bits;
-#if 0 /* wine stuff. don't know what it does... */
+#if 0 /* wine stuff. don't know what it does... */
/* check for pending X events */
if (USER_Driver.pMsgWaitForMultipleObjectsEx)
#endif
ret = NtUserGetQueueStatus(FALSE /*ClearChanges*/);
-
+
wake_bits = HIWORD(ret);
return wake_bits & (QS_KEY | QS_MOUSEBUTTON);
{
if(!gfMessagePumpHook)
return FALSE;
-
+
+ /* This code checks if we're inside SendMessage. */
+#if 0
/* 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] <= 0)
return FALSE;*/
+#endif
return TRUE;
}
return FALSE;
}
if (!gcLoadMPH++) {
- InterlockedExchange(&gfMessagePumpHook, 1);
+ InterlockedExchange((PLONG)&gfMessagePumpHook, 1);
}
LeaveCriticalSection(&gcsMPH);
return TRUE;
if(NtUserCallNoParam(NOPARAM_ROUTINE_UNINIT_MESSAGE_PUMP)) {
gcLoadMPH--;
if(!gcLoadMPH) {
- InterlockedExchange(&gfMessagePumpHook, 0);
+ InterlockedExchange((PLONG)&gfMessagePumpHook, 0);
gpfnInitMPH(TRUE, NULL);
ResetMessagePumpHook(&gmph);
gpfnInitMPH = 0;
return IsInsideMessagePumpHook() ? gmph.RealGetQueueStatus(flags) : RealGetQueueStatus(flags);
}
-DWORD WINAPI MsgWaitForMultipleObjectsEx(DWORD nCount, CONST HANDLE *lpHandles, DWORD dwMilliseconds, DWORD dwWakeMask, DWORD dwFlags)
+/**
+ * @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;
+
+ 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;
+ }
+
+ RtlCopyMemory(RealHandles, pHandles, nCount * sizeof(HANDLE));
+ RealHandles[nCount] = MessageQueueHandle;
+
+ Result = WaitForMultipleObjectsEx(nCount + 1, RealHandles,
+ dwFlags & MWMO_WAITALL,
+ dwMilliseconds, dwFlags & MWMO_ALERTABLE);
+
+ HeapFree(GetProcessHeap(), 0, RealHandles);
+ NtUserMsqClearWakeMask();
+
+ return Result;
+}
+
+/*
+ * @implemented
+ */
+DWORD WINAPI
+MsgWaitForMultipleObjectsEx(
+ DWORD nCount,
+ CONST HANDLE *lpHandles,
+ DWORD dwMilliseconds,
+ DWORD dwWakeMask,
+ DWORD dwFlags)
+{
+ return IsInsideMessagePumpHook() ? gmph.RealMsgWaitForMultipleObjectsEx(nCount, lpHandles, dwMilliseconds, dwWakeMask, dwFlags) : RealMsgWaitForMultipleObjectsEx(nCount, lpHandles,dwMilliseconds, dwWakeMask, dwFlags);
+}
+
+/*
+ * @implemented
+ */
+DWORD STDCALL
+MsgWaitForMultipleObjects(
+ DWORD nCount,
+ CONST HANDLE *lpHandles,
+ BOOL fWaitAll,
+ DWORD dwMilliseconds,
+ DWORD dwWakeMask)
{
- return IsInsideMessagePumpHook() ? gmph.RealMsgWaitForMultipleObjectsEx(nCount, lpHandles, dwMilliseconds, dwWakeMask, dwFlags) : RealMsgWaitForMultipleObjectsEx(nCount, lpHandles,dwMilliseconds, dwWakeMask, dwFlags);
+ return MsgWaitForMultipleObjectsEx(nCount, lpHandles, dwMilliseconds,
+ dwWakeMask, fWaitAll ? MWMO_WAITALL : 0);
}
-BOOL FASTCALL MessageInit()
+
+BOOL FASTCALL MessageInit(VOID)
{
InitializeCriticalSection(&DdeCrst);
InitializeCriticalSection(&MsgConversionCrst);
+ InitializeCriticalSection(&gcsMPH);
return TRUE;
}
+
+VOID FASTCALL MessageCleanup(VOID)
+{
+ DeleteCriticalSection(&DdeCrst);
+ DeleteCriticalSection(&MsgConversionCrst);
+ DeleteCriticalSection(&gcsMPH);
+}
+
+/***********************************************************************
+ * 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 );
+}