mirror of
https://github.com/reactos/reactos.git
synced 2025-08-06 00:23:10 +00:00

add stubs to user32 and add partial non-working implementation of Message Pump Hooks svn path=/trunk/; revision=6711
1075 lines
21 KiB
C
1075 lines
21 KiB
C
/* $Id: message.c,v 1.28 2003/11/19 13:19:39 weiden Exp $
|
|
*
|
|
* 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
|
|
*/
|
|
#include <windows.h>
|
|
#include <user32.h>
|
|
#include <string.h>
|
|
#include <debug.h>
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
LPARAM
|
|
STDCALL
|
|
GetMessageExtraInfo(VOID)
|
|
{
|
|
UNIMPLEMENTED;
|
|
return (LPARAM)0;
|
|
}
|
|
|
|
|
|
/*
|
|
* @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
|
|
*/
|
|
WINBOOL
|
|
STDCALL
|
|
InSendMessage(VOID)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
/*
|
|
* @unimplemented
|
|
*/
|
|
DWORD
|
|
STDCALL
|
|
InSendMessageEx(
|
|
LPVOID lpReserved)
|
|
{
|
|
UNIMPLEMENTED;
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
* @unimplemented
|
|
*/
|
|
WINBOOL
|
|
STDCALL
|
|
ReplyMessage(
|
|
LRESULT lResult)
|
|
{
|
|
UNIMPLEMENTED;
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
/*
|
|
* @unimplemented
|
|
*/
|
|
LPARAM
|
|
STDCALL
|
|
SetMessageExtraInfo(
|
|
LPARAM lParam)
|
|
{
|
|
UNIMPLEMENTED;
|
|
return (LPARAM)0;
|
|
}
|
|
|
|
|
|
BOOL
|
|
MsgiAnsiToUnicodeMessage(LPMSG UnicodeMsg, LPMSG AnsiMsg)
|
|
{
|
|
*UnicodeMsg = *AnsiMsg;
|
|
switch (AnsiMsg->message)
|
|
{
|
|
case WM_GETTEXT:
|
|
case WM_ASKCBFORMATNAME:
|
|
{
|
|
LPWSTR Buffer = HeapAlloc(GetProcessHeap(), 0,
|
|
AnsiMsg->wParam * sizeof(WCHAR));
|
|
if (!Buffer)
|
|
{
|
|
return FALSE;
|
|
}
|
|
UnicodeMsg->lParam = (LPARAM)Buffer;
|
|
break;
|
|
}
|
|
|
|
/* AnsiMsg->lParam is string (0-terminated) */
|
|
case WM_SETTEXT:
|
|
case WM_WININICHANGE:
|
|
case WM_DEVMODECHANGE:
|
|
case CB_DIR:
|
|
case LB_DIR:
|
|
case LB_ADDFILE:
|
|
case EM_REPLACESEL:
|
|
{
|
|
UNICODE_STRING UnicodeString;
|
|
RtlCreateUnicodeStringFromAsciiz(&UnicodeString, (LPSTR)AnsiMsg->lParam);
|
|
UnicodeMsg->lParam = (LPARAM)UnicodeString.Buffer;
|
|
break;
|
|
}
|
|
|
|
case WM_NCCREATE:
|
|
case WM_CREATE:
|
|
{
|
|
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;
|
|
if (HIWORD(xs->cs.lpszName))
|
|
{
|
|
RtlCreateUnicodeStringFromAsciiz(&UnicodeBuffer, (LPSTR)xs->cs.lpszName);
|
|
xs->lpszName = xs->cs.lpszName = UnicodeBuffer.Buffer;
|
|
}
|
|
if (HIWORD(xs->cs.lpszClass))
|
|
{
|
|
RtlCreateUnicodeStringFromAsciiz(&UnicodeBuffer, (LPSTR)xs->cs.lpszClass);
|
|
xs->lpszClass = xs->cs.lpszClass = UnicodeBuffer.Buffer;
|
|
}
|
|
UnicodeMsg->lParam = (LPARAM)xs;
|
|
break;
|
|
}
|
|
|
|
case WM_MDICREATE:
|
|
{
|
|
UNICODE_STRING UnicodeBuffer;
|
|
MDICREATESTRUCTW *cs =
|
|
(MDICREATESTRUCTW *)HeapAlloc(GetProcessHeap(), 0, sizeof(*cs));
|
|
|
|
if (!cs)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
*cs = *(MDICREATESTRUCTW *)AnsiMsg->lParam;
|
|
|
|
if (HIWORD(cs->szClass))
|
|
{
|
|
RtlCreateUnicodeStringFromAsciiz(&UnicodeBuffer, (LPSTR)cs->szClass);
|
|
cs->szClass = UnicodeBuffer.Buffer;
|
|
}
|
|
|
|
RtlCreateUnicodeStringFromAsciiz(&UnicodeBuffer, (LPSTR)cs->szTitle);
|
|
cs->szTitle = UnicodeBuffer.Buffer;
|
|
|
|
UnicodeMsg->lParam = (LPARAM)cs;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
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;
|
|
}
|
|
HeapFree(GetProcessHeap(), 0, Buffer);
|
|
break;
|
|
}
|
|
|
|
case WM_GETTEXTLENGTH:
|
|
case CB_GETLBTEXTLEN:
|
|
case LB_GETTEXTLEN:
|
|
{
|
|
/* FIXME: There may be one DBCS char for each Unicode char */
|
|
*Result *= 2;
|
|
break;
|
|
}
|
|
|
|
case WM_SETTEXT:
|
|
case WM_WININICHANGE:
|
|
case WM_DEVMODECHANGE:
|
|
case CB_DIR:
|
|
case LB_DIR:
|
|
case LB_ADDFILE:
|
|
case EM_REPLACESEL:
|
|
{
|
|
UNICODE_STRING UnicodeString;
|
|
RtlInitUnicodeString(&UnicodeString, (PCWSTR)UnicodeMsg->lParam);
|
|
RtlFreeUnicodeString(&UnicodeString);
|
|
break;
|
|
}
|
|
|
|
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;
|
|
if (HIWORD(cs->szTitle))
|
|
{
|
|
RtlInitUnicodeString(&UnicodeString, (PCWSTR)cs->szTitle);
|
|
RtlFreeUnicodeString(&UnicodeString);
|
|
}
|
|
if (HIWORD(cs->szClass))
|
|
{
|
|
RtlInitUnicodeString(&UnicodeString, (PCWSTR)cs->szClass);
|
|
RtlFreeUnicodeString(&UnicodeString);
|
|
}
|
|
HeapFree(GetProcessHeap(), 0, cs);
|
|
}
|
|
break;
|
|
}
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
VOID STATIC
|
|
User32ConvertToAsciiMessage(UINT* Msg, WPARAM* wParam, LPARAM* lParam)
|
|
{
|
|
switch((*Msg))
|
|
{
|
|
case WM_CREATE:
|
|
case WM_NCCREATE:
|
|
{
|
|
CREATESTRUCTA* CsA;
|
|
CREATESTRUCTW* CsW;
|
|
UNICODE_STRING UString;
|
|
ANSI_STRING AString;
|
|
|
|
CsW = (CREATESTRUCTW*)(*lParam);
|
|
CsA = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(CREATESTRUCTA));
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
VOID STATIC
|
|
User32FreeAsciiConvertedMessage(UINT Msg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
switch(Msg)
|
|
{
|
|
case WM_GETTEXT:
|
|
{
|
|
ANSI_STRING AnsiString;
|
|
UNICODE_STRING UnicodeString;
|
|
LPSTR TempString;
|
|
LPSTR InString;
|
|
InString = (LPSTR)lParam;
|
|
TempString = RtlAllocateHeap(RtlGetProcessHeap(), 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(RtlGetProcessHeap(), 0, TempString);
|
|
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(RtlGetProcessHeap(), 0, (LPSTR)Cs->lpszName);
|
|
if (HIWORD((ULONG)Cs->lpszClass) != 0)
|
|
{
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, (LPSTR)Cs->lpszClass);
|
|
}
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, Cs);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
LRESULT STDCALL
|
|
CallWindowProcA(WNDPROC lpPrevWndFunc,
|
|
HWND hWnd,
|
|
UINT Msg,
|
|
WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
MSG AnsiMsg;
|
|
MSG UnicodeMsg;
|
|
LRESULT Result;
|
|
BOOL IsHandle;
|
|
WndProcHandle wphData;
|
|
|
|
IsHandle = NtUserDereferenceWndProcHandle(lpPrevWndFunc,&wphData);
|
|
AnsiMsg.hwnd = hWnd;
|
|
AnsiMsg.message = Msg;
|
|
AnsiMsg.wParam = wParam;
|
|
AnsiMsg.lParam = lParam;
|
|
if (!IsHandle)
|
|
{
|
|
return(lpPrevWndFunc(hWnd, Msg, wParam, lParam));
|
|
} else {
|
|
if (wphData.IsUnicode)
|
|
{
|
|
if (!MsgiAnsiToUnicodeMessage(&UnicodeMsg, &AnsiMsg))
|
|
{
|
|
return(FALSE);
|
|
}
|
|
Result = wphData.WindowProc(UnicodeMsg.hwnd, UnicodeMsg.message,
|
|
UnicodeMsg.wParam, UnicodeMsg.lParam);
|
|
if (!MsgiAnsiToUnicodeReply(&UnicodeMsg, &AnsiMsg, &Result))
|
|
{
|
|
return(FALSE);
|
|
}
|
|
return(Result);
|
|
}
|
|
else
|
|
{
|
|
return(wphData.WindowProc(hWnd, Msg, wParam, lParam));
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
LRESULT STDCALL
|
|
CallWindowProcW(WNDPROC lpPrevWndFunc,
|
|
HWND hWnd,
|
|
UINT Msg,
|
|
WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
BOOL IsHandle;
|
|
WndProcHandle wphData;
|
|
|
|
IsHandle = NtUserDereferenceWndProcHandle(lpPrevWndFunc,&wphData);
|
|
if (!IsHandle)
|
|
{
|
|
return(lpPrevWndFunc(hWnd, Msg, wParam, lParam));
|
|
} else {
|
|
if (!wphData.IsUnicode)
|
|
{
|
|
LRESULT Result;
|
|
User32ConvertToAsciiMessage(&Msg, &wParam, &lParam);
|
|
Result = wphData.WindowProc(hWnd, Msg, wParam, lParam);
|
|
User32FreeAsciiConvertedMessage(Msg, wParam, lParam);
|
|
return(Result);
|
|
}
|
|
else
|
|
{
|
|
return(wphData.WindowProc(hWnd, Msg, wParam, lParam));
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
LRESULT STDCALL
|
|
DispatchMessageA(CONST MSG *lpmsg)
|
|
{
|
|
return(NtUserDispatchMessage(lpmsg));
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
LRESULT STDCALL
|
|
DispatchMessageW(CONST MSG *lpmsg)
|
|
{
|
|
return(NtUserDispatchMessage((LPMSG)lpmsg));
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
WINBOOL STDCALL
|
|
GetMessageA(LPMSG lpMsg,
|
|
HWND hWnd,
|
|
UINT wMsgFilterMin,
|
|
UINT wMsgFilterMax)
|
|
{
|
|
BOOL Res;
|
|
PUSER32_THREAD_DATA ThreadData = User32GetThreadData();
|
|
|
|
Res = NtUserGetMessage(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax);
|
|
if (Res && lpMsg->message != WM_PAINT && lpMsg->message != WM_QUIT)
|
|
{
|
|
ThreadData->LastMessage = *lpMsg;
|
|
}
|
|
return(Res);
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
WINBOOL STDCALL
|
|
GetMessageW(LPMSG lpMsg,
|
|
HWND hWnd,
|
|
UINT wMsgFilterMin,
|
|
UINT wMsgFilterMax)
|
|
{
|
|
BOOL Res;
|
|
PUSER32_THREAD_DATA ThreadData = User32GetThreadData();
|
|
|
|
Res = NtUserGetMessage(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax);
|
|
if (Res && lpMsg->message != WM_PAINT && lpMsg->message != WM_QUIT)
|
|
{
|
|
ThreadData->LastMessage = *lpMsg;
|
|
}
|
|
return(Res);
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
WINBOOL STDCALL
|
|
PeekMessageA(LPMSG lpMsg,
|
|
HWND hWnd,
|
|
UINT wMsgFilterMin,
|
|
UINT wMsgFilterMax,
|
|
UINT wRemoveMsg)
|
|
{
|
|
BOOL Res;
|
|
PUSER32_THREAD_DATA ThreadData = User32GetThreadData();
|
|
|
|
Res = NtUserPeekMessage(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg);
|
|
if (Res && lpMsg->message != WM_PAINT && lpMsg->message != WM_QUIT)
|
|
{
|
|
ThreadData->LastMessage = *lpMsg;
|
|
}
|
|
return(Res);
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
WINBOOL
|
|
STDCALL
|
|
PeekMessageW(
|
|
LPMSG lpMsg,
|
|
HWND hWnd,
|
|
UINT wMsgFilterMin,
|
|
UINT wMsgFilterMax,
|
|
UINT wRemoveMsg)
|
|
{
|
|
BOOL Res;
|
|
PUSER32_THREAD_DATA ThreadData = User32GetThreadData();
|
|
|
|
Res = NtUserPeekMessage(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg);
|
|
if (Res && lpMsg->message != WM_PAINT && lpMsg->message != WM_QUIT)
|
|
{
|
|
ThreadData->LastMessage = *lpMsg;
|
|
}
|
|
return(Res);
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
WINBOOL
|
|
STDCALL
|
|
PostMessageA(
|
|
HWND hWnd,
|
|
UINT Msg,
|
|
WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
return NtUserPostMessage(hWnd, Msg, wParam, lParam);
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
WINBOOL
|
|
STDCALL
|
|
PostMessageW(
|
|
HWND hWnd,
|
|
UINT Msg,
|
|
WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
return NtUserPostMessage(hWnd, Msg, wParam, lParam);
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
VOID
|
|
STDCALL
|
|
PostQuitMessage(
|
|
int nExitCode)
|
|
{
|
|
(void) NtUserPostMessage(NULL, WM_QUIT, nExitCode, 0);
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
WINBOOL
|
|
STDCALL
|
|
PostThreadMessageA(
|
|
DWORD idThread,
|
|
UINT Msg,
|
|
WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
return NtUserPostThreadMessage(idThread, Msg, wParam, lParam);
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
WINBOOL
|
|
STDCALL
|
|
PostThreadMessageW(
|
|
DWORD idThread,
|
|
UINT Msg,
|
|
WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
return NtUserPostThreadMessage(idThread, Msg, wParam, lParam);
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
LRESULT STDCALL
|
|
SendMessageW(HWND hWnd,
|
|
UINT Msg,
|
|
WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
return(NtUserSendMessage(hWnd, Msg, wParam, lParam));
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
LRESULT STDCALL
|
|
SendMessageA(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
MSG AnsiMsg;
|
|
MSG UcMsg;
|
|
LRESULT Result;
|
|
|
|
AnsiMsg.hwnd = hWnd;
|
|
AnsiMsg.message = Msg;
|
|
AnsiMsg.wParam = wParam;
|
|
AnsiMsg.lParam = lParam;
|
|
|
|
if (!MsgiAnsiToUnicodeMessage(&UcMsg, &AnsiMsg))
|
|
{
|
|
return(FALSE);
|
|
}
|
|
Result = SendMessageW(UcMsg.hwnd, UcMsg.message, UcMsg.wParam, UcMsg.lParam);
|
|
if (!MsgiAnsiToUnicodeReply(&UcMsg, &AnsiMsg, &Result))
|
|
{
|
|
return(FALSE);
|
|
}
|
|
return(Result);
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
WINBOOL
|
|
STDCALL
|
|
SendMessageCallbackA(
|
|
HWND hWnd,
|
|
UINT Msg,
|
|
WPARAM wParam,
|
|
LPARAM lParam,
|
|
SENDASYNCPROC lpCallBack,
|
|
ULONG_PTR dwData)
|
|
{
|
|
return NtUserSendMessageCallback(
|
|
hWnd,
|
|
Msg,
|
|
wParam,
|
|
lParam,
|
|
lpCallBack,
|
|
dwData);
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
WINBOOL
|
|
STDCALL
|
|
SendMessageCallbackW(
|
|
HWND hWnd,
|
|
UINT Msg,
|
|
WPARAM wParam,
|
|
LPARAM lParam,
|
|
SENDASYNCPROC lpCallBack,
|
|
ULONG_PTR dwData)
|
|
{
|
|
return NtUserSendMessageCallback(
|
|
hWnd,
|
|
Msg,
|
|
wParam,
|
|
lParam,
|
|
lpCallBack,
|
|
dwData);
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
LRESULT
|
|
STDCALL
|
|
SendMessageTimeoutA(
|
|
HWND hWnd,
|
|
UINT Msg,
|
|
WPARAM wParam,
|
|
LPARAM lParam,
|
|
UINT fuFlags,
|
|
UINT uTimeout,
|
|
PDWORD_PTR lpdwResult)
|
|
{
|
|
UNIMPLEMENTED;
|
|
return (LRESULT)0;
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
LRESULT
|
|
STDCALL
|
|
SendMessageTimeoutW(
|
|
HWND hWnd,
|
|
UINT Msg,
|
|
WPARAM wParam,
|
|
LPARAM lParam,
|
|
UINT fuFlags,
|
|
UINT uTimeout,
|
|
PDWORD_PTR lpdwResult)
|
|
{
|
|
UNIMPLEMENTED;
|
|
return (LRESULT)0;
|
|
}
|
|
|
|
|
|
/*
|
|
* @unimplemented
|
|
*/
|
|
WINBOOL
|
|
STDCALL
|
|
SendNotifyMessageA(
|
|
HWND hWnd,
|
|
UINT Msg,
|
|
WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
UNIMPLEMENTED;
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
/*
|
|
* @unimplemented
|
|
*/
|
|
WINBOOL
|
|
STDCALL
|
|
SendNotifyMessageW(
|
|
HWND hWnd,
|
|
UINT Msg,
|
|
WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
UNIMPLEMENTED;
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
WINBOOL STDCALL
|
|
TranslateMessage(CONST MSG *lpMsg)
|
|
{
|
|
return(TranslateMessageEx((LPMSG)lpMsg, 0));
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
WINBOOL STDCALL
|
|
TranslateMessageEx(CONST MSG *lpMsg, DWORD unk)
|
|
{
|
|
return(NtUserTranslateMessage((LPMSG)lpMsg, (HKL)unk));
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
WINBOOL
|
|
STDCALL
|
|
WaitMessage(VOID)
|
|
{
|
|
return NtUserWaitMessage();
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
UINT STDCALL
|
|
RegisterWindowMessageA(LPCSTR lpString)
|
|
{
|
|
UNICODE_STRING String;
|
|
BOOLEAN Result;
|
|
UINT Atom;
|
|
|
|
Result = RtlCreateUnicodeStringFromAsciiz(&String, (PCSZ)lpString);
|
|
if (!Result)
|
|
{
|
|
return(0);
|
|
}
|
|
Atom = NtUserRegisterWindowMessage(&String);
|
|
RtlFreeUnicodeString(&String);
|
|
return(Atom);
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
UINT STDCALL
|
|
RegisterWindowMessageW(LPCWSTR lpString)
|
|
{
|
|
UNICODE_STRING String;
|
|
|
|
RtlInitUnicodeString(&String, lpString);
|
|
return(NtUserRegisterWindowMessage(&String));
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
HWND STDCALL
|
|
SetCapture(HWND hWnd)
|
|
{
|
|
return(NtUserSetCapture(hWnd));
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
HWND STDCALL
|
|
GetCapture(VOID)
|
|
{
|
|
return(NtUserGetCapture());
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
WINBOOL STDCALL
|
|
ReleaseCapture(VOID)
|
|
{
|
|
NtUserSetCapture(NULL);
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
/*
|
|
* @unimplemented
|
|
*/
|
|
DWORD
|
|
STDCALL
|
|
RealGetQueueStatus(UINT flags)
|
|
{
|
|
DWORD ret;
|
|
WORD changed_bits, wake_bits;
|
|
|
|
#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
|
|
*/
|
|
WINBOOL STDCALL GetInputState(VOID)
|
|
{
|
|
DWORD ret;
|
|
WORD wake_bits;
|
|
|
|
#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(FALSE /*ClearChanges*/);
|
|
|
|
wake_bits = HIWORD(ret);
|
|
|
|
return wake_bits & (QS_KEY | QS_MOUSEBUTTON);
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
WINBOOL STDCALL SetMessageQueue(int cMessagesMax)
|
|
{
|
|
/* Function does nothing on 32 bit windows */
|
|
return TRUE;
|
|
}
|
|
typedef DWORD (WINAPI * RealGetQueueStatusProc)(UINT flags);
|
|
typedef DWORD (WINAPI * RealMsgWaitForMultipleObjectsExProc)(DWORD nCount, LPHANDLE lpHandles, DWORD dwMilliseconds, DWORD dwWakeMask, DWORD dwFlags);
|
|
|
|
typedef struct _USER_MESSAGE_PUMP_ADDRESSES {
|
|
DWORD cbSize;
|
|
//NtUserRealInternalGetMessageProc NtUserRealInternalGetMessage;
|
|
//NtUserRealWaitMessageExProc NtUserRealWaitMessageEx;
|
|
RealGetQueueStatusProc RealGetQueueStatus;
|
|
RealMsgWaitForMultipleObjectsExProc RealMsgWaitForMultipleObjectsEx;
|
|
} USER_MESSAGE_PUMP_ADDRESSES, * PUSER_MESSAGE_PUMP_ADDRESSES;
|
|
|
|
DWORD
|
|
STDCALL
|
|
RealMsgWaitForMultipleObjectsEx(
|
|
DWORD nCount,
|
|
LPHANDLE pHandles,
|
|
DWORD dwMilliseconds,
|
|
DWORD dwWakeMask,
|
|
DWORD dwFlags);
|
|
|
|
typedef BOOL (WINAPI * MESSAGEPUMPHOOKPROC)(BOOL Unregistering,PUSER_MESSAGE_PUMP_ADDRESSES MessagePumpAddresses);
|
|
|
|
RTL_CRITICAL_SECTION gcsMPH;
|
|
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;
|
|
|
|
/* 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;*/
|
|
|
|
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)
|
|
{
|
|
RtlEnterCriticalSection(&gcsMPH);
|
|
if(!Hook) {
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
RtlLeaveCriticalSection(&gcsMPH);
|
|
return FALSE;
|
|
}
|
|
if(!gcLoadMPH) {
|
|
USER_MESSAGE_PUMP_ADDRESSES Addresses;
|
|
gpfnInitMPH = Hook;
|
|
ResetMessagePumpHook(&Addresses);
|
|
if(!Hook(FALSE, &Addresses) || !Addresses.cbSize) {
|
|
RtlLeaveCriticalSection(&gcsMPH);
|
|
return FALSE;
|
|
}
|
|
memcpy(&gmph, &Addresses, Addresses.cbSize);
|
|
} else {
|
|
if(gpfnInitMPH != Hook) {
|
|
RtlLeaveCriticalSection(&gcsMPH);
|
|
return FALSE;
|
|
}
|
|
}
|
|
if(NtUserCallNoParam(NOPARAM_ROUTINE_INIT_MESSAGE_PUMP)) {
|
|
RtlLeaveCriticalSection(&gcsMPH);
|
|
return FALSE;
|
|
}
|
|
if (!gcLoadMPH++) {
|
|
InterlockedExchange(&gfMessagePumpHook, 1);
|
|
}
|
|
RtlLeaveCriticalSection(&gcsMPH);
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL WINAPI UnregisterMessagePumpHook(VOID)
|
|
{
|
|
RtlEnterCriticalSection(&gcsMPH);
|
|
if(gcLoadMPH > 0) {
|
|
if(NtUserCallNoParam(NOPARAM_ROUTINE_UNINIT_MESSAGE_PUMP)) {
|
|
gcLoadMPH--;
|
|
if(!gcLoadMPH) {
|
|
InterlockedExchange(&gfMessagePumpHook, 0);
|
|
gpfnInitMPH(TRUE, NULL);
|
|
ResetMessagePumpHook(&gmph);
|
|
gpfnInitMPH = 0;
|
|
}
|
|
RtlLeaveCriticalSection(&gcsMPH);
|
|
return TRUE;
|
|
}
|
|
}
|
|
RtlLeaveCriticalSection(&gcsMPH);
|
|
return FALSE;
|
|
}
|
|
|
|
DWORD WINAPI GetQueueStatus(UINT flags)
|
|
{
|
|
return IsInsideMessagePumpHook() ? gmph.RealGetQueueStatus(flags) : RealGetQueueStatus(flags);
|
|
}
|
|
|
|
DWORD WINAPI MsgWaitForMultipleObjectsEx(DWORD nCount, LPHANDLE lpHandles, DWORD dwMilliseconds, DWORD dwWakeMask, DWORD dwFlags)
|
|
{
|
|
return IsInsideMessagePumpHook() ? gmph.RealMsgWaitForMultipleObjectsEx(nCount, lpHandles,dwMilliseconds, dwWakeMask, dwFlags) : RealMsgWaitForMultipleObjectsEx(nCount, lpHandles,dwMilliseconds, dwWakeMask, dwFlags);
|
|
}
|