reactos/reactos/subsystems/win32/win32k/ntuser/callback.c

433 lines
12 KiB
C
Raw Normal View History

/*
* ReactOS W32 Subsystem
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id$
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* PURPOSE: Window classes
* FILE: subsys/win32k/ntuser/wndproc.c
* PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
* Thomas Weidenmueller (w3seek@users.sourceforge.net)
* REVISION HISTORY:
* 06-06-2001 CSH Created
* NOTES: Please use the Callback Memory Management functions for
* callbacks to make sure, the memory is freed on thread
* termination!
*/
/* INCLUDES ******************************************************************/
#include <w32k.h>
#define NDEBUG
#include <debug.h>
/* CALLBACK MEMORY MANAGEMENT ************************************************/
typedef struct _INT_CALLBACK_HEADER
{
/* list entry in the W32THREAD structure */
LIST_ENTRY ListEntry;
}
INT_CALLBACK_HEADER, *PINT_CALLBACK_HEADER;
PVOID FASTCALL
IntCbAllocateMemory(ULONG Size)
{
PINT_CALLBACK_HEADER Mem;
PW32THREAD W32Thread;
if(!(Mem = ExAllocatePoolWithTag(PagedPool, Size + sizeof(INT_CALLBACK_HEADER),
TAG_CALLBACK)))
{
return NULL;
}
W32Thread = PsGetCurrentThreadWin32Thread();
ASSERT(W32Thread);
/* insert the callback memory into the thread's callback list */
InsertTailList(&W32Thread->W32CallbackListHead, &Mem->ListEntry);
return (Mem + 1);
}
VOID FASTCALL
IntCbFreeMemory(PVOID Data)
{
PINT_CALLBACK_HEADER Mem;
PW32THREAD W32Thread;
ASSERT(Data);
Mem = ((PINT_CALLBACK_HEADER)Data - 1);
W32Thread = PsGetCurrentThreadWin32Thread();
ASSERT(W32Thread);
/* remove the memory block from the thread's callback list */
RemoveEntryList(&Mem->ListEntry);
/* free memory */
ExFreePool(Mem);
}
VOID FASTCALL
IntCleanupThreadCallbacks(PW32THREAD W32Thread)
{
PLIST_ENTRY CurrentEntry;
PINT_CALLBACK_HEADER Mem;
while (!IsListEmpty(&W32Thread->W32CallbackListHead))
{
CurrentEntry = RemoveHeadList(&W32Thread->W32CallbackListHead);
Mem = CONTAINING_RECORD(CurrentEntry, INT_CALLBACK_HEADER,
ListEntry);
/* free memory */
ExFreePool(Mem);
}
}
/* FUNCTIONS *****************************************************************/
VOID STDCALL
co_IntCallSentMessageCallback(SENDASYNCPROC CompletionCallback,
HWND hWnd,
UINT Msg,
ULONG_PTR CompletionCallbackContext,
LRESULT Result)
{
SENDASYNCPROC_CALLBACK_ARGUMENTS Arguments;
PVOID ResultPointer;
ULONG ResultLength;
NTSTATUS Status;
Arguments.Callback = CompletionCallback;
Arguments.Wnd = hWnd;
Arguments.Msg = Msg;
Arguments.Context = CompletionCallbackContext;
Arguments.Result = Result;
UserLeaveCo();
Status = KeUserModeCallback(USER32_CALLBACK_SENDASYNCPROC,
&Arguments,
sizeof(SENDASYNCPROC_CALLBACK_ARGUMENTS),
&ResultPointer,
&ResultLength);
UserEnterCo();
if (!NT_SUCCESS(Status))
{
2002-07-04 David Welch <welch@computer2.darkstar.org> * subsys/win32k/include/callback.h: Fixed callback argument definitions. * subsys/win32k/ntuser/winpos.c: Implemented some more of the windows sizing/moving code. * subsys/win32k/ntuser/painting.c: Implemented some more of the window painting code. * subsys/win32k/objects/coord.c: Implemented LPtoDP and DPtoLP. * subsys/win32k/objects/region.c: Added stubs for some more region functions. 2002-07-04 David Welch <welch@computer2.darkstar.org> * ntoskrnl/ps/process.c (NtCreateProcess): Duplicate the process desktop handle as well. 2002-07-04 David Welch <welch@computer2.darkstar.org> * ntoskrnl/se/token.c: Don't call the ZwXXX variant of system calls when in system context. 2002-07-04 David Welch <welch@computer2.darkstar.org> * ntoskrnl/Makefile: Added file with MDA output code. * ntoskrnl/kd/kdebug.c: Recognize MDA as a destination for debug output. 2002-07-04 David Welch <welch@computer2.darkstar.org> * lib/user32/windows/defwnd.c: Implemented some more of the default window handler. 2002-07-04 David Welch <welch@computer2.darkstar.org> * lib/user32/misc/stubs.c: Removed some stubs to seperate files. 2002-07-04 David Welch <welch@computer2.darkstar.org> * lib/user32/user32.def: Export ScreenToClient otherwise we get problems when code in user32 tries to call it. 2002-07-04 David Welch <welch@computer2.darkstar.org> * include/win32k/region.h: Added prototypes for some missing region functions. 2002-07-04 David Welch <welch@computer2.darkstar.org> * include/win32k/ntuser.h: Added prototypes for some missing NtUserXXX functions. 2002-07-04 David Welch <welch@computer2.darkstar.org> * include/user32/wininternal.h: Added some constants for private GetDCEx styles that WINE needs. 2002-07-04 David Welch <welch@computer2.darkstar.org> * include/user32/callback.h: Fixed callbacks for messages with parameters. 2002-07-04 David Welch <welch@computer2.darkstar.org> * include/napi/win32.h (W32THREAD): Added pointer to the thread's desktop. * include/napi/win32.h (W32PROCESS): Removed handle table, added a pointer to the process's window station. * subsys/win32k/ntuser/guicheck.c (W32kGuiCheck): Reference a process's window station on the first win32k system call. Reference a thread's desktop on the first win32k system call. 2002-07-04 David Welch <welch@computer2.darkstar.org> * include/messages.h: Added some missing WM_XXX constants. 2002-07-04 David Welch <welch@computer2.darkstar.org> * drivers/dd/ide/makefile: Compiling with debugging messages needs libgcc to be linked in. 2002-07-04 David Welch <welch@computer2.darkstar.org> * iface/addsys/genw32k.c: Generate a variable with the number of system calls. * iface/native/genntdll.c: Generate a proper stack frame for the user system call stubs. * ntoskrnl/ke/i386/syscall.S: Generate a proper stack frame for the handler for system calls. 2002-07-04 David Welch <welch@computer2.darkstar.org> * Makefile: Build the GUI startup application. * subsys/system/gstart/gstart.c: Application to start up the GUI. svn path=/trunk/; revision=3179
2002-07-04 19:56:38 +00:00
return;
}
return;
}
LRESULT STDCALL
co_IntCallWindowProc(WNDPROC Proc,
BOOLEAN IsAnsiProc,
HWND Wnd,
UINT Message,
WPARAM wParam,
LPARAM lParam,
INT lParamBufferSize)
{
WINDOWPROC_CALLBACK_ARGUMENTS StackArguments;
PWINDOWPROC_CALLBACK_ARGUMENTS Arguments;
NTSTATUS Status;
PVOID ResultPointer;
ULONG ResultLength;
ULONG ArgumentLength;
LRESULT Result;
if (0 < lParamBufferSize)
{
ArgumentLength = sizeof(WINDOWPROC_CALLBACK_ARGUMENTS) + lParamBufferSize;
Arguments = IntCbAllocateMemory(ArgumentLength);
if (NULL == Arguments)
{
DPRINT1("Unable to allocate buffer for window proc callback\n");
return -1;
}
RtlMoveMemory((PVOID) ((char *) Arguments + sizeof(WINDOWPROC_CALLBACK_ARGUMENTS)),
(PVOID) lParam, lParamBufferSize);
}
else
{
Arguments = &StackArguments;
ArgumentLength = sizeof(WINDOWPROC_CALLBACK_ARGUMENTS);
}
Arguments->Proc = Proc;
Arguments->IsAnsiProc = IsAnsiProc;
Arguments->Wnd = Wnd;
Arguments->Msg = Message;
Arguments->wParam = wParam;
Arguments->lParam = lParam;
Arguments->lParamBufferSize = lParamBufferSize;
ResultPointer = NULL;
ResultLength = ArgumentLength;
UserLeaveCo();
Status = KeUserModeCallback(USER32_CALLBACK_WINDOWPROC,
Arguments,
ArgumentLength,
&ResultPointer,
&ResultLength);
_SEH_TRY
{
/* Simulate old behaviour: copy into our local buffer */
RtlMoveMemory(Arguments, ResultPointer, ArgumentLength);
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
UserEnterCo();
if (!NT_SUCCESS(Status))
{
if (0 < lParamBufferSize)
{
IntCbFreeMemory(Arguments);
}
return -1;
}
Result = Arguments->Result;
if (0 < lParamBufferSize)
{
RtlMoveMemory((PVOID) lParam,
(PVOID) ((char *) Arguments + sizeof(WINDOWPROC_CALLBACK_ARGUMENTS)),
lParamBufferSize);
IntCbFreeMemory(Arguments);
}
return Result;
}
HMENU STDCALL
co_IntLoadSysMenuTemplate()
{
LRESULT Result;
NTSTATUS Status;
PVOID ResultPointer;
ULONG ResultLength;
ResultPointer = NULL;
ResultLength = sizeof(LRESULT);
UserLeaveCo();
Status = KeUserModeCallback(USER32_CALLBACK_LOADSYSMENUTEMPLATE,
NULL,
0,
&ResultPointer,
&ResultLength);
/* Simulate old behaviour: copy into our local buffer */
Result = *(LRESULT*)ResultPointer;
UserEnterCo();
if (!NT_SUCCESS(Status))
{
return(0);
}
return (HMENU)Result;
}
BOOL STDCALL
co_IntLoadDefaultCursors(VOID)
{
LRESULT Result;
NTSTATUS Status;
PVOID ResultPointer;
ULONG ResultLength;
BOOL DefaultCursor = TRUE;
ResultPointer = NULL;
ResultLength = sizeof(LRESULT);
UserLeaveCo();
Status = KeUserModeCallback(USER32_CALLBACK_LOADDEFAULTCURSORS,
&DefaultCursor,
sizeof(BOOL),
&ResultPointer,
&ResultLength);
/* Simulate old behaviour: copy into our local buffer */
Result = *(LRESULT*)ResultPointer;
UserEnterCo();
if (!NT_SUCCESS(Status))
{
return FALSE;
}
return TRUE;
}
LRESULT STDCALL
co_IntCallHookProc(INT HookId,
INT Code,
WPARAM wParam,
LPARAM lParam,
HOOKPROC Proc,
BOOLEAN Ansi,
PUNICODE_STRING ModuleName)
{
ULONG ArgumentLength;
PVOID Argument;
LRESULT Result;
NTSTATUS Status;
PVOID ResultPointer;
ULONG ResultLength;
PHOOKPROC_CALLBACK_ARGUMENTS Common;
CBT_CREATEWNDW *CbtCreateWnd =NULL;
PCHAR Extra;
PHOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS CbtCreatewndExtra ;
PUNICODE_STRING WindowName = NULL;
PUNICODE_STRING ClassName = NULL;
ArgumentLength = sizeof(HOOKPROC_CALLBACK_ARGUMENTS) - sizeof(WCHAR)
+ ModuleName->Length;
switch(HookId)
{
case WH_CBT:
switch(Code)
{
case HCBT_CREATEWND:
CbtCreateWnd = (CBT_CREATEWNDW *) lParam;
ArgumentLength += sizeof(HOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS);
WindowName = (PUNICODE_STRING) (CbtCreateWnd->lpcs->lpszName);
ArgumentLength += WindowName->Length + sizeof(WCHAR);
ClassName = (PUNICODE_STRING) (CbtCreateWnd->lpcs->lpszClass);
if (! IS_ATOM(ClassName->Buffer))
{
ArgumentLength += ClassName->Length + sizeof(WCHAR);
}
break;
default:
DPRINT1("Trying to call unsupported CBT hook %d\n", Code);
return 0;
}
break;
case WH_KEYBOARD_LL:
ArgumentLength += sizeof(KBDLLHOOKSTRUCT);
break;
case WH_MOUSE_LL:
ArgumentLength += sizeof(MSLLHOOKSTRUCT);
break;
default:
DPRINT1("Trying to call unsupported window hook %d\n", HookId);
return 0;
}
Argument = IntCbAllocateMemory(ArgumentLength);
if (NULL == Argument)
{
DPRINT1("HookProc callback failed: out of memory\n");
return 0;
}
Common = (PHOOKPROC_CALLBACK_ARGUMENTS) Argument;
Common->HookId = HookId;
Common->Code = Code;
Common->wParam = wParam;
Common->lParam = lParam;
Common->Proc = Proc;
Common->Ansi = Ansi;
Common->ModuleNameLength = ModuleName->Length;
memcpy(Common->ModuleName, ModuleName->Buffer, ModuleName->Length);
Extra = (PCHAR) Common->ModuleName + Common->ModuleNameLength;
switch(HookId)
{
case WH_CBT:
switch(Code)
{
case HCBT_CREATEWND:
Common->lParam = (LPARAM) (Extra - (PCHAR) Common);
CbtCreatewndExtra = (PHOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS) Extra;
CbtCreatewndExtra->Cs = *(CbtCreateWnd->lpcs);
CbtCreatewndExtra->WndInsertAfter = CbtCreateWnd->hwndInsertAfter;
Extra = (PCHAR) (CbtCreatewndExtra + 1);
RtlCopyMemory(Extra, WindowName->Buffer, WindowName->Length);
CbtCreatewndExtra->Cs.lpszName = (LPCWSTR) (Extra - (PCHAR) CbtCreatewndExtra);
CbtCreatewndExtra->Cs.lpszClass = ClassName->Buffer;
Extra += WindowName->Length;
*((WCHAR *) Extra) = L'\0';
Extra += sizeof(WCHAR);
if (! IS_ATOM(ClassName->Buffer))
{
RtlCopyMemory(Extra, ClassName->Buffer, ClassName->Length);
CbtCreatewndExtra->Cs.lpszClass =
(LPCWSTR) MAKELONG(Extra - (PCHAR) CbtCreatewndExtra, 1);
Extra += ClassName->Length;
*((WCHAR *) Extra) = L'\0';
}
break;
}
break;
case WH_KEYBOARD_LL:
RtlCopyMemory(Extra, (PVOID) lParam, sizeof(KBDLLHOOKSTRUCT));
Common->lParam = (LPARAM) (Extra - (PCHAR) Common);
break;
case WH_MOUSE_LL:
RtlCopyMemory(Extra, (PVOID) lParam, sizeof(MSLLHOOKSTRUCT));
Common->lParam = (LPARAM) (Extra - (PCHAR) Common);
break;
}
ResultPointer = NULL;
ResultLength = sizeof(LRESULT);
UserLeaveCo();
Status = KeUserModeCallback(USER32_CALLBACK_HOOKPROC,
Argument,
ArgumentLength,
&ResultPointer,
&ResultLength);
/* Simulate old behaviour: copy into our local buffer */
Result = *(LRESULT*)ResultPointer;
UserEnterCo();
IntCbFreeMemory(Argument);
if (!NT_SUCCESS(Status))
{
return 0;
}
return Result;
}
/* EOF */