Incomplete implementation of hooks

svn path=/trunk/; revision=6965
This commit is contained in:
Gé van Geldorp 2003-12-12 14:22:37 +00:00
parent dc8bfd1046
commit ae68da49b6
22 changed files with 1376 additions and 120 deletions

View file

@ -815,13 +815,18 @@ extern "C" {
#define WH_JOURNALPLAYBACK (1)
#define WH_JOURNALRECORD (0)
#define WH_KEYBOARD (2)
#define WH_KEYBOARD_LL (13)
#define WH_MOUSE (7)
#define WH_MOUSE_LL (14)
#define WH_MSGFILTER (-1)
#define WH_SHELL (10)
#define WH_SYSMSGFILTER (6)
#define WH_MSGFILTER (-1)
#define WH_FOREGROUNDIDLE (11)
#define WH_MINHOOK (-1)
#define WH_MAXHOOK (14)
/* DefineDosDevice */
#define DDD_RAW_TARGET_PATH (1)
#define DDD_REMOVE_DEFINITION (2)

View file

@ -13,7 +13,8 @@
#define USER32_CALLBACK_SENDSTYLECHANGED (9)
#define USER32_CALLBACK_LOADSYSMENUTEMPLATE (10)
#define USER32_CALLBACK_LOADDEFAULTCURSORS (11)
#define USER32_CALLBACK_MAXIMUM (11)
#define USER32_CALLBACK_HOOKPROC (12)
#define USER32_CALLBACK_MAXIMUM (12)
typedef struct _WINDOWPROC_CALLBACK_ARGUMENTS
{
@ -101,6 +102,26 @@ typedef struct _SENDSTYLECHANGED_CALLBACK_ARGUMENTS
DWORD WhichStyle;
} SENDSTYLECHANGED_CALLBACK_ARGUMENTS, *PSENDSTYLECHANGED_CALLBACK_ARGUMENTS;
typedef struct _HOOKPROC_CALLBACK_ARGUMENTS
{
INT HookId;
INT Code;
WPARAM wParam;
LPARAM lParam;
HOOKPROC Proc;
BOOLEAN Ansi;
UINT ModuleNameLength;
WCHAR ModuleName[1];
} HOOKPROC_CALLBACK_ARGUMENTS, *PHOOKPROC_CALLBACK_ARGUMENTS;
typedef struct _HOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS
{
CREATESTRUCTW Cs; /* lpszName and lpszClass replaced by offsets */
HWND WndInsertAfter;
/* WCHAR szName[] */
/* WCHAR szClass[] */
} HOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS, *PHOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS;
NTSTATUS STDCALL
User32CallWindowProcFromKernel(PVOID Arguments, ULONG ArgumentLength);
NTSTATUS STDCALL
@ -125,5 +146,7 @@ NTSTATUS STDCALL
User32LoadSysMenuTemplateForKernel(PVOID Arguments, ULONG ArgumentLength);
NTSTATUS STDCALL
User32SetupDefaultCursors(PVOID Arguments, ULONG ArgumentLength);
NTSTATUS STDCALL
User32CallHookProcFromKernel(PVOID Arguments, ULONG ArgumentLength);
#endif /* __INCLUDE_USER32_CALLBACK_H */

View file

@ -152,13 +152,13 @@ NtUserCallMsgFilter(
DWORD Unknown0,
DWORD Unknown1);
DWORD
LRESULT
STDCALL
NtUserCallNextHookEx(
DWORD Unknown0,
DWORD Unknown1,
DWORD Unknown2,
DWORD Unknown3);
HHOOK Hook,
int Code,
WPARAM wParam,
LPARAM lParam);
#define NOPARAM_ROUTINE_REGISTER_PRIMITIVE 0xffff0001 /* Private ROS */
#define NOPARAM_ROUTINE_DESTROY_CARET 0xffff0002
@ -1566,15 +1566,15 @@ NtUserSetWindowsHookAW(
DWORD Unknown1,
DWORD Unknown2);
DWORD
HHOOK
STDCALL
NtUserSetWindowsHookEx(
DWORD Unknown0,
DWORD Unknown1,
DWORD Unknown2,
DWORD Unknown3,
DWORD Unknown4,
DWORD Unknown5);
HINSTANCE Mod,
PUNICODE_STRING ModuleName,
DWORD ThreadId,
int HookId,
HOOKPROC HookProc,
BOOL Ansi);
DWORD
STDCALL
@ -1688,10 +1688,10 @@ NtUserTranslateMessage(
LPMSG lpMsg,
HKL dwhkl );
DWORD
BOOL
STDCALL
NtUserUnhookWindowsHookEx(
DWORD Unknown0);
HHOOK Hook);
DWORD
STDCALL

View file

@ -2,7 +2,7 @@
#define __WINE_DEBUG_H
#include "../roscfg.h"
#ifndef DBG
#if ! defined(DBG) || ! defined(YDEBUG)
#define NDEBUG
#endif
#include "../debug.h"

View file

@ -1,4 +1,4 @@
/* $Id: stubs.c,v 1.40 2003/11/16 22:44:39 sedwards Exp $
/* $Id: stubs.c,v 1.41 2003/12/12 14:22:36 gvg Exp $
*
* reactos/lib/gdi32/misc/stubs.c
*
@ -513,28 +513,6 @@ InvertRgn(
return FALSE;
}
/*
* @unimplemented
*/
BOOL
STDCALL
Pie(
HDC a0,
int a1,
int a2,
int a3,
int a4,
int a5,
int a6,
int a7,
int a8
)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
/*
* @unimplemented
*/

View file

@ -81,3 +81,23 @@ Ellipse(HDC hDc,
{
return NtGdiEllipse(hDc, Left, Top, Right, Bottom);
}
/*
* @implemented
*/
BOOL
STDCALL
Pie(HDC hDc,
int Left,
int Top,
int Right,
int Bottom,
int XRadialStart,
int YRadialStart,
int XRadialEnd,
int YRadialEnd)
{
return NtGdiPie(hDc, Left, Top, Right, Bottom, XRadialStart, YRadialStart,
XRadialEnd, YRadialEnd);
}

View file

@ -185,7 +185,7 @@ static HRESULT WINAPI IStream_fnSetSize(IStream *iface, ULARGE_INTEGER libNewSiz
ICOM_THIS(ISHFileStream, iface);
#endif
TRACE("(%p,%ld)\n", This, libNewSize.s.LowPart);
TRACE("(%p,%ld)\n", This, libNewSize.u.LowPart);
IStream_fnCommit(iface, 0); /* If ever buffered, this will be needed */
return E_NOTIMPL;
}
@ -203,7 +203,7 @@ static HRESULT WINAPI IStream_fnCopyTo(IStream *iface, IStream* pstm, ULARGE_INT
ULONGLONG ulSize;
HRESULT hRet = S_OK;
TRACE("(%p,%p,%ld,%p,%p)\n", This, pstm, cb.s.LowPart, pcbRead, pcbWritten);
TRACE("(%p,%p,%ld,%p,%p)\n", This, pstm, cb.u.LowPart, pcbRead, pcbWritten);
if (pcbRead)
pcbRead->QuadPart = 0;
@ -278,7 +278,7 @@ static HRESULT WINAPI IStream_fnLockUnlockRegion(IStream *iface, ULARGE_INTEGER
#ifndef NDEBUG
ICOM_THIS(ISHFileStream, iface);
#endif
TRACE("(%p,%ld,%ld,%ld)\n", This, libOffset.s.LowPart, cb.s.LowPart, dwLockType);
TRACE("(%p,%ld,%ld,%ld)\n", This, libOffset.u.LowPart, cb.u.LowPart, dwLockType);
return E_NOTIMPL;
}

View file

@ -19,6 +19,11 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef DBG
#undef DBG
#define DBG 1
#endif
#include <stdarg.h>
#include <string.h>
#ifdef __REACTOS__

View file

@ -78,6 +78,8 @@ Init(VOID)
(PVOID)User32LoadSysMenuTemplateForKernel;
NtCurrentPeb()->KernelCallbackTable[USER32_CALLBACK_LOADDEFAULTCURSORS] =
(PVOID)User32SetupDefaultCursors;
NtCurrentPeb()->KernelCallbackTable[USER32_CALLBACK_HOOKPROC] =
(PVOID)User32CallHookProcFromKernel;
/* Allocate an index for user32 thread local data. */
User32TlsIndex = TlsAlloc();

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: hook.c,v 1.11 2003/11/09 13:50:04 navaraf Exp $
/* $Id: hook.c,v 1.12 2003/12/12 14:22:37 gvg Exp $
*
* PROJECT: ReactOS user32.dll
* FILE: lib/user32/windows/input.c
@ -30,20 +30,22 @@
#include <windows.h>
#include <user32.h>
#include <user32/callback.h>
#define NDEBUG
#include <debug.h>
/* FUNCTIONS *****************************************************************/
/*
* @unimplemented
* @implemented
*/
WINBOOL
STDCALL
UnhookWindowsHookEx(
HHOOK hhk)
HHOOK Hook)
{
UNIMPLEMENTED;
return FALSE;
return NtUserUnhookWindowsHookEx(Hook);
}
#if 0
WINBOOL
@ -92,13 +94,41 @@ CallMsgFilterW(
LRESULT
STDCALL
CallNextHookEx(
HHOOK hhk,
int nCode,
HHOOK Hook,
int Code,
WPARAM wParam,
LPARAM lParam)
{
UNIMPLEMENTED;
return (LRESULT)0;
return NtUserCallNextHookEx(Hook, Code, wParam, lParam);
}
STATIC
HHOOK
FASTCALL
IntSetWindowsHook(
int idHook,
HOOKPROC lpfn,
HINSTANCE hMod,
DWORD dwThreadId,
BOOL bAnsi)
{
WCHAR ModuleName[MAX_PATH];
UNICODE_STRING USModuleName;
if (NULL != hMod)
{
if (0 == GetModuleFileNameW(hMod, ModuleName, MAX_PATH))
{
return NULL;
}
RtlInitUnicodeString(&USModuleName, ModuleName);
}
else
{
RtlInitUnicodeString(&USModuleName, NULL);
}
return NtUserSetWindowsHookEx(hMod, &USModuleName, dwThreadId, idHook, lpfn, bAnsi);
}
/*
@ -106,10 +136,9 @@ CallNextHookEx(
*/
HHOOK
STDCALL
SetWindowsHookW ( int idHook, HOOKPROC lpfn )
SetWindowsHookW(int idHook, HOOKPROC lpfn)
{
UNIMPLEMENTED;
return FALSE;
return IntSetWindowsHook(idHook, lpfn, NULL, 0, FALSE);
}
/*
@ -117,10 +146,9 @@ SetWindowsHookW ( int idHook, HOOKPROC lpfn )
*/
HHOOK
STDCALL
SetWindowsHookA ( int idHook, HOOKPROC lpfn )
SetWindowsHookA(int idHook, HOOKPROC lpfn)
{
UNIMPLEMENTED;
return FALSE;
return IntSetWindowsHook(idHook, lpfn, NULL, 0, TRUE);
}
/*
@ -225,8 +253,7 @@ SetWindowsHookExA(
HINSTANCE hMod,
DWORD dwThreadId)
{
UNIMPLEMENTED;
return 0;
return IntSetWindowsHook(idHook, lpfn, hMod, dwThreadId, TRUE);
}
@ -241,7 +268,89 @@ SetWindowsHookExW(
HINSTANCE hMod,
DWORD dwThreadId)
{
UNIMPLEMENTED;
return 0;
return IntSetWindowsHook(idHook, lpfn, hMod, dwThreadId, FALSE);
}
NTSTATUS STDCALL
User32CallHookProcFromKernel(PVOID Arguments, ULONG ArgumentLength)
{
PHOOKPROC_CALLBACK_ARGUMENTS Common;
LRESULT Result;
CREATESTRUCTW Csw;
CBT_CREATEWNDW CbtCreatewndw;
UNICODE_STRING UString;
CREATESTRUCTA Csa;
CBT_CREATEWNDA CbtCreatewnda;
ANSI_STRING AString;
PHOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS CbtCreatewndExtra;
WPARAM wParam;
LPARAM lParam;
Common = (PHOOKPROC_CALLBACK_ARGUMENTS) Arguments;
switch(Common->HookId)
{
case WH_CBT:
switch(Common->Code)
{
case HCBT_CREATEWND:
CbtCreatewndExtra = (PHOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS)
((PCHAR) Common + Common->lParam);
Csw = CbtCreatewndExtra->Cs;
Csw.lpszName = (LPCWSTR)((PCHAR) CbtCreatewndExtra
+ (ULONG) CbtCreatewndExtra->Cs.lpszName);
if (0 != HIWORD(CbtCreatewndExtra->Cs.lpszClass))
{
Csw.lpszClass = (LPCWSTR)((PCHAR) CbtCreatewndExtra
+ LOWORD((ULONG) CbtCreatewndExtra->Cs.lpszClass));
}
wParam = Common->wParam;
if (Common->Ansi)
{
memcpy(&Csa, &Csw, sizeof(CREATESTRUCTW));
RtlInitUnicodeString(&UString, Csw.lpszName);
RtlUnicodeStringToAnsiString(&AString, &UString, TRUE);
Csa.lpszName = AString.Buffer;
if (0 != HIWORD(Csw.lpszClass))
{
RtlInitUnicodeString(&UString, Csw.lpszClass);
RtlUnicodeStringToAnsiString(&AString, &UString, TRUE);
Csa.lpszClass = AString.Buffer;
}
CbtCreatewnda.lpcs = &Csa;
CbtCreatewnda.hwndInsertAfter = CbtCreatewndExtra->WndInsertAfter;
lParam = (LPARAM) &CbtCreatewnda;
}
else
{
CbtCreatewndw.lpcs = &Csw;
CbtCreatewndw.hwndInsertAfter = CbtCreatewndExtra->WndInsertAfter;
lParam = (LPARAM) &CbtCreatewndw;
}
break;
default:
return ZwCallbackReturn(NULL, 0, STATUS_NOT_SUPPORTED);
}
Result = Common->Proc(Common->Code, wParam, lParam);
switch(Common->Code)
{
case HCBT_CREATEWND:
if (Common->Ansi)
{
if (0 != HIWORD(Csa.lpszClass))
{
RtlFreeHeap(RtlGetProcessHeap(), 0, (LPSTR) Csa.lpszClass);
}
RtlFreeHeap(RtlGetProcessHeap(), 0, (LPSTR) Csa.lpszName);
}
break;
}
break;
default:
return ZwCallbackReturn(NULL, 0, STATUS_NOT_SUPPORTED);
}
return ZwCallbackReturn(&Result, sizeof(LRESULT), STATUS_SUCCESS);
}

View file

@ -49,4 +49,13 @@ IntLoadSysMenuTemplate();
BOOL STDCALL
IntLoadDefaultCursors(BOOL SetDefault);
LRESULT STDCALL
IntCallHookProc(INT HookId,
INT Code,
WPARAM wParam,
LPARAM lParam,
HOOKPROC Proc,
BOOLEAN Ansi,
PUNICODE_STRING ModuleName);
#endif /* _WIN32K_CALLBACK_H */

View file

@ -0,0 +1,32 @@
#ifndef _WIN32K_HOOK_H
#define _WIN32K_HOOK_H
#include <windows.h>
#include <internal/ps.h>
typedef struct tagHOOK
{
LIST_ENTRY Chain; /* Hook chain entry */
HHOOK Self; /* user handle for this hook */
PETHREAD Thread; /* Thread owning the hook */
int HookId; /* Hook table index */
HOOKPROC Proc; /* Hook function */
BOOLEAN Ansi; /* Is it an Ansi hook? */
UNICODE_STRING ModuleName; /* Module name for global hooks */
} HOOK, *PHOOK;
#define NB_HOOKS (WH_MAXHOOK-WH_MINHOOK+1)
typedef struct tagHOOKTABLE
{
FAST_MUTEX Lock;
LIST_ENTRY Hooks[NB_HOOKS]; /* array of hook chains */
UINT Counts[NB_HOOKS]; /* use counts for each hook chain */
} HOOKTABLE, *PHOOKTABLE;
LRESULT FASTCALL HOOK_CallHooks(INT HookId, INT Code, WPARAM wParam, LPARAM lParam);
VOID FASTCALL HOOK_DestroyThreadHooks(PETHREAD Thread);
#endif /* _WIN32K_HOOK_H */
/* EOF */

View file

@ -3,6 +3,7 @@
#include <internal/ex.h>
#include <windows.h>
#include "hook.h"
typedef struct _USER_MESSAGE
{
@ -73,6 +74,8 @@ typedef struct _USER_MESSAGE_QUEUE
HWND MenuOwner;
/* Identifes the menu state */
BYTE MenuState;
/* Window hooks */
PHOOKTABLE Hooks;
/* queue state tracking */
WORD WakeBits;
@ -150,6 +153,9 @@ BOOL IntInitMessagePumpHook();
BOOL IntUninitMessagePumpHook();
#define MAKE_LONG(x, y) ((((y) & 0xFFFF) << 16) | ((x) & 0xFFFF))
PHOOKTABLE FASTCALL MsqGetHooks(PUSER_MESSAGE_QUEUE Queue);
VOID FASTCALL MsqSetHooks(PUSER_MESSAGE_QUEUE Queue, PHOOKTABLE Hooks);
#endif /* _WIN32K_MSGQUEUE_H */
/* EOF */

View file

@ -12,7 +12,8 @@ typedef enum {
otWindow,
otMenu,
otAcceleratorTable,
otCursorIcon
otCursorIcon,
otHookProc
} USER_OBJECT_TYPE;
typedef struct _USER_OBJECT_HEADER

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: dllmain.c,v 1.59 2003/12/07 23:02:57 gvg Exp $
/* $Id: dllmain.c,v 1.60 2003/12/12 14:22:37 gvg Exp $
*
* Entry Point for win32k.sys
*/
@ -43,6 +43,7 @@
#include <include/hotkey.h>
#include <include/accelerator.h>
#include <include/guicheck.h>
#include <include/hook.h>
#define NDEBUG
#include <win32k/debug1.h>
@ -161,6 +162,7 @@ Win32kThreadCallback (struct _ETHREAD *Thread,
DbgPrint (" Destroy thread\n");
#endif
HOOK_DestroyThreadHooks(Thread);
RemoveTimersThread(Thread->Cid.UniqueThread);
UnregisterThreadHotKeys(Thread);
DestroyThreadWindows(Thread);

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: object.c,v 1.6 2003/05/18 17:16:17 ea Exp $
/* $Id: object.c,v 1.7 2003/12/12 14:22:37 gvg Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -66,13 +66,13 @@ ObmpPerformRetentionChecks(PUSER_OBJECT_HEADER ObjectHeader)
{
if (ObjectHeader->RefCount < 0)
{
DbgPrint("ObjectHeader 0x%X has invalid reference count (%d)\n",
DPRINT1("ObjectHeader 0x%X has invalid reference count (%d)\n",
ObjectHeader, ObjectHeader->RefCount);
}
if (ObjectHeader->HandleCount < 0)
{
DbgPrint("Object 0x%X has invalid handle count (%d)\n",
DPRINT1("Object 0x%X has invalid handle count (%d)\n",
ObjectHeader, ObjectHeader->HandleCount);
}
@ -101,6 +101,11 @@ ObmpGetObjectByHandle(PUSER_HANDLE_TABLE HandleTable,
PLIST_ENTRY Current;
ULONG i;
if (NULL == Handle)
{
return NULL;
}
Current = HandleTable->ListHead.Flink;
for (i = 0; i < Count; i++)
@ -108,6 +113,7 @@ ObmpGetObjectByHandle(PUSER_HANDLE_TABLE HandleTable,
Current = Current->Flink;
if (Current == &(HandleTable->ListHead))
{
DPRINT1("Invalid handle\n");
return NULL;
}
}
@ -195,6 +201,7 @@ ObmpDeleteHandle(PUSER_HANDLE_TABLE HandleTable,
Entry = ObmpGetObjectByHandle(HandleTable, Handle);
if (Entry == NULL)
{
DPRINT1("Invalid handle\n");
ObmpUnlockHandleTable(HandleTable);
return NULL;
}
@ -404,7 +411,7 @@ ObmCreateHandle(PUSER_HANDLE_TABLE HandleTable,
Block->Handles[i].ObjectBody = ObjectBody;
ObmpUnlockHandleTable(HandleTable);
*HandleReturn = (HANDLE)((Handle + i) << 2);
return ERROR_SUCCESS;
return STATUS_SUCCESS;
}
}
@ -419,6 +426,7 @@ ObmCreateHandle(PUSER_HANDLE_TABLE HandleTable,
sizeof(USER_HANDLE_BLOCK));
if (!NewBlock)
{
DPRINT1("Unable to allocate new handle block\n");
*HandleReturn = (PHANDLE)NULL;
return STATUS_INSUFFICIENT_RESOURCES;
}
@ -471,6 +479,7 @@ ObmReferenceObjectByHandle(PUSER_HANDLE_TABLE HandleTable,
if ((ObjectType != otUnknown) && (ObjectHeader->Type != ObjectType))
{
DPRINT1("Object type mismatch\n");
return STATUS_UNSUCCESSFUL;
}
@ -518,6 +527,7 @@ ObmCreateHandleTable(VOID)
sizeof(USER_HANDLE_TABLE));
if (!HandleTable)
{
DPRINT1("Unable to create handle table\n");
return NULL;
}

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: callback.c,v 1.18 2003/12/07 23:02:57 gvg Exp $
/* $Id: callback.c,v 1.19 2003/12/12 14:22:37 gvg Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -43,6 +43,8 @@
#define NDEBUG
#include <debug.h>
#define TAG_CALLBACK TAG('C', 'B', 'C', 'K')
/* FUNCTIONS *****************************************************************/
VOID STDCALL
@ -417,4 +419,111 @@ IntLoadDefaultCursors(BOOL SetDefault)
return (BOOL)Result;
}
LRESULT STDCALL
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;
PCHAR Extra;
PHOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS CbtCreatewndExtra;
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)
+ (wcslen(CbtCreateWnd->lpcs->lpszName)
+ 1) * sizeof(WCHAR);
if (0 != HIWORD(CbtCreateWnd->lpcs->lpszClass))
{
ArgumentLength += (wcslen(CbtCreateWnd->lpcs->lpszClass)
+ 1) * sizeof(WCHAR);
}
break;
default:
DPRINT1("Trying to call unsupported CBT hook %d\n", Code);
return 0;
}
break;
default:
DPRINT1("Trying to call unsupported window hook %d\n", HookId);
return 0;
}
Argument = ExAllocatePoolWithTag(PagedPool, ArgumentLength, TAG_CALLBACK);
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);
memcpy(Extra, CbtCreateWnd->lpcs->lpszName,
(wcslen(CbtCreateWnd->lpcs->lpszName) + 1) * sizeof(WCHAR));
CbtCreatewndExtra->Cs.lpszName = (LPCWSTR) (Extra - (PCHAR) CbtCreatewndExtra);
Extra += (wcslen(CbtCreateWnd->lpcs->lpszName) + 1) * sizeof(WCHAR);
if (0 != HIWORD(CbtCreateWnd->lpcs->lpszClass))
{
memcpy(Extra, CbtCreateWnd->lpcs->lpszClass,
(wcslen(CbtCreateWnd->lpcs->lpszClass) + 1) * sizeof(WCHAR));
CbtCreatewndExtra->Cs.lpszClass =
(LPCWSTR) MAKELONG(Extra - (PCHAR) CbtCreatewndExtra, 1);
}
break;
}
break;
}
ResultPointer = &Result;
ResultLength = sizeof(LRESULT);
Status = NtW32Call(USER32_CALLBACK_HOOKPROC,
Argument,
ArgumentLength,
&ResultPointer,
&ResultLength);
if (!NT_SUCCESS(Status))
{
return 0;
}
return Result;
}
/* EOF */

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: hook.c,v 1.2 2003/05/18 17:16:17 ea Exp $
/* $Id: hook.c,v 1.3 2003/12/12 14:22:37 gvg Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -25,22 +25,393 @@
* PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
* REVISION HISTORY:
* 06-06-2001 CSH Created
* NOTE: Most of this code was adapted from Wine,
* Copyright (C) 2002 Alexandre Julliard
*/
#include <ddk/ntddk.h>
#include <win32k/win32k.h>
#include <include/callback.h>
#include <include/error.h>
#include <include/hook.h>
#include <include/object.h>
#include <include/msgqueue.h>
#include <include/winsta.h>
#include <internal/ps.h>
#include <internal/safe.h>
#define NDEBUG
#include <debug.h>
#include <win32k/debug1.h>
DWORD
#define TAG_HOOK TAG('W', 'N', 'H', 'K')
#define HOOKID_TO_INDEX(HookId) (HookId - WH_MINHOOK)
STATIC PHOOKTABLE GlobalHooks;
/* create a new hook table */
STATIC FASTCALL PHOOKTABLE
IntAllocHookTable(void)
{
PHOOKTABLE Table;
UINT i;
Table = ExAllocatePoolWithTag(PagedPool, sizeof(HOOKTABLE), TAG_HOOK);
if (NULL != Table)
{
ExInitializeFastMutex(&Table->Lock);
for (i = 0; i < NB_HOOKS; i++)
{
InitializeListHead(&Table->Hooks[i]);
Table->Counts[i] = 0;
}
}
return Table;
}
/* create a new hook and add it to the specified table */
STATIC FASTCALL PHOOK
IntAddHook(PETHREAD Thread, int HookId, BOOLEAN Global, PWINSTATION_OBJECT WinStaObj)
{
PHOOK Hook;
PHOOKTABLE Table = Global ? GlobalHooks : MsqGetHooks(Thread->Win32Thread->MessageQueue);
HANDLE Handle;
if (NULL == Table)
{
Table = IntAllocHookTable();
if (NULL == Table)
{
return NULL;
}
if (Global)
{
GlobalHooks = Table;
}
else
{
MsqSetHooks(Thread->Win32Thread->MessageQueue, Table);
}
}
Hook = ObmCreateObject(WinStaObj->HandleTable, &Handle,
otHookProc, sizeof(HOOK));
if (NULL == Hook)
{
return NULL;
}
Hook->Self = Handle;
Hook->Thread = Thread;
Hook->HookId = HookId;
RtlInitUnicodeString(&Hook->ModuleName, NULL);
ExAcquireFastMutex(&Table->Lock);
InsertHeadList(&Table->Hooks[HOOKID_TO_INDEX(HookId)], &Hook->Chain);
ExReleaseFastMutex(&Table->Lock);
return Hook;
}
/* get the hook table that a given hook belongs to */
STATIC PHOOKTABLE FASTCALL
IntGetTable(PHOOK Hook)
{
if (NULL == Hook->Thread || WH_KEYBOARD_LL == Hook->HookId ||
WH_MOUSE_LL == Hook->HookId)
{
return GlobalHooks;
}
return MsqGetHooks(Hook->Thread->Win32Thread->MessageQueue);
}
/* get the first hook in the chain */
STATIC PHOOK FASTCALL
IntGetFirstHook(PHOOKTABLE Table, int HookId)
{
PLIST_ENTRY Elem = Table->Hooks[HOOKID_TO_INDEX(HookId)].Flink;
return Elem == &Table->Hooks[HOOKID_TO_INDEX(HookId)]
? NULL : CONTAINING_RECORD(Elem, HOOK, Chain);
}
/* find the first non-deleted hook in the chain */
STATIC PHOOK FASTCALL
IntGetFirstValidHook(PHOOKTABLE Table, int HookId)
{
PHOOK Hook;
PLIST_ENTRY Elem;
ExAcquireFastMutex(&Table->Lock);
Hook = IntGetFirstHook(Table, HookId);
while (NULL != Hook && NULL == Hook->Proc)
{
Elem = Hook->Chain.Flink;
Hook = (Elem == &Table->Hooks[HOOKID_TO_INDEX(HookId)]
? NULL : CONTAINING_RECORD(Elem, HOOK, Chain));
}
ExReleaseFastMutex(&Table->Lock);
return Hook;
}
/* find the next hook in the chain, skipping the deleted ones */
STATIC PHOOK FASTCALL
IntGetNextHook(PHOOK Hook)
{
PHOOKTABLE Table = IntGetTable(Hook);
int HookId = Hook->HookId;
PLIST_ENTRY Elem;
ExAcquireFastMutex(&Table->Lock);
Elem = Hook->Chain.Flink;
while (Elem != &Table->Hooks[HOOKID_TO_INDEX(HookId)])
{
Hook = CONTAINING_RECORD(Elem, HOOK, Chain);
if (NULL != Hook->Proc)
{
ExReleaseFastMutex(&Table->Lock);
return Hook;
}
}
ExReleaseFastMutex(&Table->Lock);
if (NULL != GlobalHooks && Table != GlobalHooks) /* now search through the global table */
{
return IntGetFirstValidHook(GlobalHooks, HookId);
}
return NULL;
}
/* free a hook, removing it from its chain */
STATIC VOID FASTCALL
IntFreeHook(PHOOKTABLE Table, PHOOK Hook, PWINSTATION_OBJECT WinStaObj)
{
RemoveEntryList(&Hook->Chain);
RtlFreeUnicodeString(&Hook->ModuleName);
ObmCloseHandle(WinStaObj->HandleTable, Hook->Self);
}
/* remove a hook, freeing it if the chain is not in use */
STATIC FASTCALL VOID
IntRemoveHook(PHOOK Hook, PWINSTATION_OBJECT WinStaObj)
{
PHOOKTABLE Table = IntGetTable(Hook);
ASSERT(NULL != Table);
if (NULL == Table)
{
return;
}
ExAcquireFastMutex(&Table->Lock);
if (0 != Table->Counts[HOOKID_TO_INDEX(Hook->HookId)])
{
Hook->Proc = NULL; /* chain is in use, just mark it and return */
}
else
{
IntFreeHook(Table, Hook, WinStaObj);
}
ExReleaseFastMutex(&Table->Lock);
}
/* release a hook chain, removing deleted hooks if the use count drops to 0 */
STATIC VOID FASTCALL
IntReleaseHookChain(PHOOKTABLE Table, int HookId, PWINSTATION_OBJECT WinStaObj)
{
PLIST_ENTRY Elem;
PHOOK HookObj;
if (NULL == Table)
{
return;
}
ExAcquireFastMutex(&Table->Lock);
/* use count shouldn't already be 0 */
ASSERT(0 != Table->Counts[HOOKID_TO_INDEX(HookId)]);
if (0 == Table->Counts[HOOKID_TO_INDEX(HookId)])
{
ExReleaseFastMutex(&Table->Lock);
return;
}
if (0 == --Table->Counts[HOOKID_TO_INDEX(HookId)])
{
Elem = Table->Hooks[HOOKID_TO_INDEX(HookId)].Flink;
while (Elem != &Table->Hooks[HOOKID_TO_INDEX(HookId)])
{
HookObj = CONTAINING_RECORD(Elem, HOOK, Chain);
Elem = Elem->Flink;
if (NULL == HookObj->Proc)
{
IntFreeHook(Table, HookObj, WinStaObj);
}
}
}
ExReleaseFastMutex(&Table->Lock);
}
LRESULT FASTCALL
HOOK_CallHooks(INT HookId, INT Code, WPARAM wParam, LPARAM lParam)
{
PHOOK Hook;
PHOOKTABLE Table = MsqGetHooks(PsGetWin32Thread()->MessageQueue);
LRESULT Result;
PWINSTATION_OBJECT WinStaObj;
NTSTATUS Status;
ASSERT(WH_MINHOOK <= HookId && HookId <= WH_MAXHOOK);
if (NULL == Table || ! (Hook = IntGetFirstValidHook(Table, HookId)))
{
/* try global table */
Table = GlobalHooks;
if (NULL == Table || ! (Hook = IntGetFirstValidHook(Table, HookId)))
{
return 0; /* no hook set */
}
}
if (Hook->Thread != PsGetCurrentThread())
{
DPRINT1("Calling hooks in other threads not implemented yet");
return 0;
}
ExAcquireFastMutex(&Table->Lock);
Table->Counts[HOOKID_TO_INDEX(HookId)]++;
ExReleaseFastMutex(&Table->Lock);
if (Table != GlobalHooks && GlobalHooks != NULL)
{
ExAcquireFastMutex(&GlobalHooks->Lock);
GlobalHooks->Counts[HOOKID_TO_INDEX(HookId)]++;
ExReleaseFastMutex(&GlobalHooks->Lock);
}
Result = IntCallHookProc(HookId, Code, wParam, lParam, Hook->Proc,
Hook->Ansi, &Hook->ModuleName);
Status = IntValidateWindowStationHandle(PROCESS_WINDOW_STATION(),
KernelMode,
0,
&WinStaObj);
if(! NT_SUCCESS(Status))
{
DPRINT1("Invalid window station????\n");
}
else
{
IntReleaseHookChain(MsqGetHooks(PsGetWin32Thread()->MessageQueue), HookId, WinStaObj);
IntReleaseHookChain(GlobalHooks, HookId, WinStaObj);
ObDereferenceObject(WinStaObj);
}
return Result;
}
VOID FASTCALL
HOOK_DestroyThreadHooks(PETHREAD Thread)
{
int HookId;
PLIST_ENTRY Elem;
PHOOK HookObj;
PWINSTATION_OBJECT WinStaObj;
NTSTATUS Status;
if (NULL != GlobalHooks)
{
Status = IntValidateWindowStationHandle(PROCESS_WINDOW_STATION(),
KernelMode,
0,
&WinStaObj);
if(! NT_SUCCESS(Status))
{
DPRINT1("Invalid window station????\n");
return;
}
ExAcquireFastMutex(&GlobalHooks->Lock);
for (HookId = WH_MINHOOK; HookId <= WH_MAXHOOK; HookId++)
{
/* only low-level keyboard/mouse global hooks can be owned by a thread */
switch(HookId)
{
case WH_KEYBOARD_LL:
case WH_MOUSE_LL:
Elem = GlobalHooks->Hooks[HOOKID_TO_INDEX(HookId)].Flink;
while (Elem != &GlobalHooks->Hooks[HOOKID_TO_INDEX(HookId)])
{
HookObj = CONTAINING_RECORD(Elem, HOOK, Chain);
Elem = Elem->Flink;
if (HookObj->Thread == Thread)
{
IntRemoveHook(HookObj, WinStaObj);
}
}
break;
}
}
ExReleaseFastMutex(&GlobalHooks->Lock);
ObDereferenceObject(WinStaObj);
}
}
LRESULT
STDCALL
NtUserCallNextHookEx(
DWORD Unknown0,
DWORD Unknown1,
DWORD Unknown2,
DWORD Unknown3)
HHOOK Hook,
int Code,
WPARAM wParam,
LPARAM lParam)
{
UNIMPLEMENTED
PHOOK HookObj, NextObj;
PWINSTATION_OBJECT WinStaObj;
NTSTATUS Status;
Status = IntValidateWindowStationHandle(PROCESS_WINDOW_STATION(),
KernelMode,
0,
&WinStaObj);
if(! NT_SUCCESS(Status))
{
SetLastNtError(Status);
return FALSE;
}
Status = ObmReferenceObjectByHandle(WinStaObj->HandleTable, Hook,
otHookProc, (PVOID *) &HookObj);
ObDereferenceObject(WinStaObj);
if (! NT_SUCCESS(Status))
{
DPRINT1("Invalid handle passed to NtUserCallNextHookEx\n");
SetLastNtError(Status);
return 0;
}
ASSERT(Hook == HookObj->Self);
if (NULL != HookObj->Thread && (HookObj->Thread != PsGetCurrentThread()))
{
DPRINT1("Thread mismatch\n");
ObmDereferenceObject(HookObj);
SetLastWin32Error(ERROR_INVALID_HANDLE);
return 0;
}
NextObj = IntGetNextHook(HookObj);
ObmDereferenceObject(HookObj);
if (NULL != NextObj)
{
DPRINT1("Calling next hook not implemented\n");
UNIMPLEMENTED
SetLastWin32Error(ERROR_NOT_SUPPORTED);
return 0;
}
return 0;
}
@ -57,19 +428,147 @@ NtUserSetWindowsHookAW(
return 0;
}
DWORD
HHOOK
STDCALL
NtUserSetWindowsHookEx(
DWORD Unknown0,
DWORD Unknown1,
DWORD Unknown2,
DWORD Unknown3,
DWORD Unknown4,
DWORD Unknown5)
HINSTANCE Mod,
PUNICODE_STRING UnsafeModuleName,
DWORD ThreadId,
int HookId,
HOOKPROC HookProc,
BOOL Ansi)
{
UNIMPLEMENTED
PWINSTATION_OBJECT WinStaObj;
BOOLEAN Global;
PETHREAD Thread;
PHOOK Hook;
UNICODE_STRING ModuleName;
NTSTATUS Status;
HHOOK Handle;
return 0;
if (HookId < WH_MINHOOK || WH_MAXHOOK < HookId || NULL == HookProc)
{
SetLastWin32Error(ERROR_INVALID_PARAMETER);
return NULL;
}
if (ThreadId) /* thread-local hook */
{
if (HookId == WH_JOURNALRECORD ||
HookId == WH_JOURNALPLAYBACK ||
HookId == WH_KEYBOARD_LL ||
HookId == WH_MOUSE_LL ||
HookId == WH_SYSMSGFILTER)
{
/* these can only be global */
SetLastWin32Error(ERROR_INVALID_PARAMETER);
return NULL;
}
Mod = NULL;
Global = FALSE;
if (! NT_SUCCESS(PsLookupThreadByThreadId((PVOID) ThreadId, &Thread)))
{
DPRINT1("Invalid thread id 0x%x\n", ThreadId);
SetLastWin32Error(ERROR_INVALID_PARAMETER);
return NULL;
}
if (Thread->ThreadsProcess != PsGetCurrentProcess())
{
DPRINT1("Can't specify thread belonging to another process\n");
SetLastWin32Error(ERROR_INVALID_PARAMETER);
return NULL;
}
}
else /* system-global hook */
{
if (HookId == WH_KEYBOARD_LL || HookId == WH_MOUSE_LL)
{
Mod = NULL;
Thread = PsGetCurrentThread();
}
else if (NULL == Mod)
{
SetLastWin32Error(ERROR_INVALID_PARAMETER);
return NULL;
}
else
{
Thread = NULL;
}
Global = TRUE;
}
/* We only (partially) support local WH_CBT hooks for now */
if (WH_CBT != HookId || Global)
{
UNIMPLEMENTED
SetLastWin32Error(ERROR_NOT_SUPPORTED);
return NULL;
}
Status = IntValidateWindowStationHandle(PROCESS_WINDOW_STATION(),
KernelMode,
0,
&WinStaObj);
if(! NT_SUCCESS(Status))
{
SetLastNtError(Status);
return (HANDLE) NULL;
}
Hook = IntAddHook(Thread, HookId, Global, WinStaObj);
if (NULL == Hook)
{
ObDereferenceObject(WinStaObj);
return NULL;
}
if (NULL != Mod)
{
Status = MmCopyFromCaller(&ModuleName, UnsafeModuleName, sizeof(UNICODE_STRING));
if (! NT_SUCCESS(Status))
{
ObmDereferenceObject(Hook);
IntRemoveHook(Hook, WinStaObj);
ObDereferenceObject(WinStaObj);
SetLastNtError(Status);
return NULL;
}
Hook->ModuleName.Buffer = ExAllocatePoolWithTag(PagedPool,
ModuleName.MaximumLength,
TAG_HOOK);
if (NULL == Hook->ModuleName.Buffer)
{
ObmDereferenceObject(Hook);
IntRemoveHook(Hook, WinStaObj);
ObDereferenceObject(WinStaObj);
SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
return NULL;
}
Hook->ModuleName.MaximumLength = ModuleName.MaximumLength;
Status = MmCopyFromCaller(Hook->ModuleName.Buffer,
ModuleName.Buffer,
ModuleName.MaximumLength);
if (! NT_SUCCESS(Status))
{
ObmDereferenceObject(Hook);
IntRemoveHook(Hook, WinStaObj);
ObDereferenceObject(WinStaObj);
SetLastNtError(Status);
return NULL;
}
Hook->ModuleName.Length = ModuleName.Length;
}
Hook->Proc = HookProc;
Hook->Ansi = Ansi;
Handle = Hook->Self;
ObmDereferenceObject(Hook);
ObDereferenceObject(WinStaObj);
return Handle;
}
DWORD
@ -89,14 +588,43 @@ NtUserSetWinEventHook(
return 0;
}
DWORD
BOOL
STDCALL
NtUserUnhookWindowsHookEx(
DWORD Unknown0)
HHOOK Hook)
{
UNIMPLEMENTED
PWINSTATION_OBJECT WinStaObj;
PHOOK HookObj;
NTSTATUS Status;
return 0;
Status = IntValidateWindowStationHandle(PROCESS_WINDOW_STATION(),
KernelMode,
0,
&WinStaObj);
if(! NT_SUCCESS(Status))
{
SetLastNtError(Status);
return FALSE;
}
Status = ObmReferenceObjectByHandle(WinStaObj->HandleTable, Hook,
otHookProc, (PVOID *) &HookObj);
if (! NT_SUCCESS(Status))
{
DPRINT1("Invalid handle passed to NtUserUnhookWindowsHookEx\n");
ObDereferenceObject(WinStaObj);
SetLastNtError(Status);
return FALSE;
}
ASSERT(Hook == HookObj->Self);
IntRemoveHook(HookObj, WinStaObj);
ObmDereferenceObject(HookObj);
ObDereferenceObject(WinStaObj);
return TRUE;
}
DWORD

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: msgqueue.c,v 1.41 2003/12/08 20:40:41 gvg Exp $
/* $Id: msgqueue.c,v 1.42 2003/12/12 14:22:37 gvg Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -861,4 +861,16 @@ MsqDestroyMessageQueue(PUSER_MESSAGE_QUEUE MessageQueue)
ExFreePool(MessageQueue);
}
PHOOKTABLE FASTCALL
MsqGetHooks(PUSER_MESSAGE_QUEUE Queue)
{
return Queue->Hooks;
}
VOID FASTCALL
MsqSetHooks(PUSER_MESSAGE_QUEUE Queue, PHOOKTABLE Hooks)
{
Queue->Hooks = Hooks;
}
/* EOF */

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: windc.c,v 1.41 2003/12/03 08:19:03 gvg Exp $
/* $Id: windc.c,v 1.42 2003/12/12 14:22:37 gvg Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -390,7 +390,9 @@ NtUserGetDCEx(HWND hWnd, HANDLE ClipRegion, ULONG Flags)
{
Dce = Window->Dce;
/* FIXME: Implement this. */
#ifdef TODO
DbgBreakPoint();
#endif
}
if (NULL == Dce)

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: window.c,v 1.156 2003/12/10 22:09:56 weiden Exp $
/* $Id: window.c,v 1.157 2003/12/12 14:22:37 gvg Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -50,6 +50,7 @@
#include <include/menu.h>
#include <include/hotkey.h>
#include <include/focus.h>
#include <include/hook.h>
#define NDEBUG
#include <win32k/debug1.h>
@ -1033,8 +1034,8 @@ NtUserCreateWindowEx(DWORD dwExStyle,
POINT MaxPos;
#endif
CREATESTRUCTW Cs;
CBT_CREATEWNDW CbtCreate;
LRESULT Result;
DPRINT("NtUserCreateWindowEx\n");
DPRINT("NtUserCreateWindowEx(): (%d,%d-%d,%d)\n", x, y, nWidth, nHeight);
@ -1240,6 +1241,30 @@ NtUserCreateWindowEx(DWORD dwExStyle,
}
WindowObject->ClientRect = WindowObject->WindowRect;
Cs.lpCreateParams = lpParam;
Cs.hInstance = hInstance;
Cs.hMenu = hMenu;
Cs.hwndParent = ParentWindowHandle;
Cs.cx = nWidth;
Cs.cy = nHeight;
Cs.x = x;
Cs.y = y;
Cs.style = dwStyle;
Cs.lpszName = lpWindowName->Buffer;
Cs.lpszClass = lpClassName->Buffer;
Cs.dwExStyle = dwExStyle;
CbtCreate.lpcs = &Cs;
CbtCreate.hwndInsertAfter = HWND_TOP;
if (HOOK_CallHooks(WH_CBT, HCBT_CREATEWND, (WPARAM) Handle, (LPARAM) &CbtCreate))
{
if (NULL != ParentWindow)
{
IntReleaseWindowObject(ParentWindow);
}
DPRINT1("CBT-hook returned !0\n");
return (HWND) NULL;
}
/*
* Get the size and position of the window.
*/
@ -1276,28 +1301,13 @@ NtUserCreateWindowEx(DWORD dwExStyle,
IntCreateScrollBar(WindowObject, SB_HORZ);
/* Send a NCCREATE message. */
Cs.lpCreateParams = lpParam;
Cs.hInstance = hInstance;
Cs.hMenu = hMenu;
Cs.hwndParent = ParentWindowHandle;
Cs.cx = nWidth;
Cs.cy = nHeight;
Cs.x = x;
Cs.y = y;
Cs.style = dwStyle;
Cs.lpszName = lpWindowName->Buffer;
Cs.lpszClass = lpClassName->Buffer;
Cs.dwExStyle = dwExStyle;
// AG: For some reason these don't get set already. This might need moving
// elsewhere... What is actually done with WindowObject anyway, to retain
// its data?
DPRINT("[win32k.window] NtUserCreateWindowEx style %d, exstyle %d, parent %d\n", Cs.style, Cs.dwExStyle, Cs.hwndParent);
// NtUserSetWindowLong(Handle, GWL_STYLE, WindowObject->Style, TRUE);
// NtUserSetWindowLong(Handle, GWL_EXSTYLE, WindowObject->ExStyle, TRUE);
DPRINT("NtUserCreateWindowEx(): (%d,%d-%d,%d)\n", x, y, nWidth, nHeight);
// Any more?
DPRINT("NtUserCreateWindowEx(): About to send NCCREATE message.\n");
Result = IntSendNCCREATEMessage(WindowObject->Self, &Cs);
if (!Result)

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: fillshap.c,v 1.35 2003/10/04 20:04:10 gvg Exp $ */
/* $Id: fillshap.c,v 1.36 2003/12/12 14:22:37 gvg Exp $ */
#undef WIN32_LEAN_AND_MEAN
#include <windows.h>
@ -136,7 +136,7 @@ NtGdiEllipse(HDC hDC,
BRUSHOBJ_UnlockBrush(dc->w.hBrush);
DC_UnlockDc(hDC);
return TRUE;
return ret;
}
Radius = (Right - Left) / 2;
@ -231,22 +231,415 @@ NtGdiEllipse(HDC hDC,
BRUSHOBJ_UnlockBrush(dc->w.hBrush);
DC_UnlockDc(hDC);
return TRUE;
return ret;
}
typedef struct tagSHAPEPOINT
{
int X;
int Y;
int Type;
} SHAPEPOINT, *PSHAPEPOINT;
#define SHAPEPOINT_TYPE_CIRCLE 'C'
#define SHAPEPOINT_TYPE_LINE_RIGHT 'R' /* Fill at right side of line */
#define SHAPEPOINT_TYPE_LINE_LEFT 'L' /* Fill at left side of line */
#define SETPOINT(x, y, type) \
ShapePoints[*PointCount].X = (x); \
ShapePoints[*PointCount].Y = (y); \
ShapePoints[*PointCount].Type = (type); \
(*PointCount)++
#define SETCIRCLEPOINT(x, y) \
SETPOINT(x, y, SHAPEPOINT_TYPE_CIRCLE)
#ifdef TODO
STATIC VOID
FASTCALL
CirclePoints(UINT *PointCount, PSHAPEPOINT ShapePoints, int Left, int Top,
int Right, int Bottom)
{
int X, X18, X27, X36, X45;
int Y, Y14, Y23, Y58, Y67;
int d, Radius;
BOOL Even;
Even = (0 == (Right - Left) % 2);
Right--;
Bottom--;
Radius = (Right - Left) / 2;
if (Even)
{
X = 0;
Y = Radius;
d = 2 - Radius;
X18 = Right;
X27 = (Left + Right) / 2 + 1;
X36 = (Left + Right) / 2;
X45 = Left;
Y14 = Top + Radius;
Y23 = Top;
Y58 = Top + Radius + 1;
Y67 = Top + (Right - Left);
ShapePoints[*PointCount].X = X27;
SETCIRCLEPOINT(X27, Y23);
SETCIRCLEPOINT(X36, Y23);
SETCIRCLEPOINT(X18, Y14);
SETCIRCLEPOINT(X45, Y14);
SETCIRCLEPOINT(X18, Y58);
SETCIRCLEPOINT(X45, Y58);
SETCIRCLEPOINT(X27, Y67);
SETCIRCLEPOINT(X36, Y67);
}
else
{
X = 0;
Y = Radius;
d = 1 - Radius;
X18 = Right;
X27 = (Left + Right) / 2;
X36 = (Left + Right) / 2;
X45 = Left;
Y14 = Top + Radius;
Y23 = Top;
Y58 = Top + Radius;
Y67 = Top + (Right - Left);
SETCIRCLEPOINT(X27, Y23);
SETCIRCLEPOINT(X45, Y14);
SETCIRCLEPOINT(X18, Y58);
SETCIRCLEPOINT(X27, Y67);
}
while (X < Y)
{
if (d < 0)
{
d += 2 * X + (Even ? 4 : 3);
X27++;
X36--;
Y14--;
Y58++;
}
else
{
d += 2 * (X - Y) + 5;
Y--;
Y23++;
Y67--;
X18--;
X45++;
X27++;
X36--;
Y14--;
Y58++;
}
X++;
SETCIRCLEPOINT(X27, Y23);
SETCIRCLEPOINT(X36, Y23);
SETCIRCLEPOINT(X18, Y14);
SETCIRCLEPOINT(X45, Y14);
SETCIRCLEPOINT(X18, Y58);
SETCIRCLEPOINT(X45, Y58);
SETCIRCLEPOINT(X27, Y67);
SETCIRCLEPOINT(X36, Y67);
}
}
STATIC VOID
LinePoints(UINT *PointCount, PSHAPEPOINT ShapePoints, int Left, int Top,
int Right, int Bottom, int XTo, int YTo, BOOL Start)
{
LONG x, y, deltax, deltay, i, xchange, ychange, error;
int Type;
x = (Right + Left) / 2;
y = (Bottom + Top) / 2;
deltax = XTo - x;
deltay = YTo - y;
if (deltax < 0)
{
xchange = -1;
deltax = - deltax;
x--;
}
else
{
xchange = 1;
}
if (deltay < 0)
{
ychange = -1;
deltay = - deltay;
y--;
Type = (Start ? SHAPEPOINT_TYPE_LINE_LEFT : SHAPEPOINT_TYPE_LINE_RIGHT);
}
else
{
ychange = 1;
Type = (Start ? SHAPEPOINT_TYPE_LINE_RIGHT : SHAPEPOINT_TYPE_LINE_LEFT);
}
if (y == YTo)
{
for (i = x; i <= XTo; i++)
{
SETPOINT(i, y, Type);
}
}
else if (x == XTo)
{
for (i = y; i <= YTo; i++)
{
SETPOINT(x, i, Type);
}
}
else
{
error = 0;
if (deltax < deltay)
{
for (i = 0; i < deltay; i++)
{
SETPOINT(x, y, Type);
y = y + ychange;
error = error + deltax;
if (deltay <= error)
{
x = x + xchange;
error = error - deltay;
}
}
}
else
{
for (i = 0; i < deltax; i++)
{
SETPOINT(x, y, Type);
x = x + xchange;
error = error + deltay;
if (deltax <= error)
{
y = y + ychange;
error = error - deltax;
}
}
}
}
}
STATIC int
CDECL
CompareShapePoints(const void *pv1, const void *pv2)
{
if (((const PSHAPEPOINT) pv1)->Y < ((const PSHAPEPOINT) pv2)->Y)
{
return -1;
}
else if (((const PSHAPEPOINT) pv2)->Y < ((const PSHAPEPOINT) pv1)->Y)
{
return +1;
}
else if (((const PSHAPEPOINT) pv1)->X < ((const PSHAPEPOINT) pv2)->X)
{
return -1;
}
else if (((const PSHAPEPOINT) pv2)->X < ((const PSHAPEPOINT) pv1)->X)
{
return +1;
}
else
{
return 0;
}
}
#endif
BOOL
STDCALL
NtGdiPie(HDC hDC,
int LeftRect,
int TopRect,
int RightRect,
int BottomRect,
int XRadial1,
int YRadial1,
int XRadial2,
int YRadial2)
int Left,
int Top,
int Right,
int Bottom,
int XRadialStart,
int YRadialStart,
int XRadialEnd,
int YRadialEnd)
{
UNIMPLEMENTED;
#ifdef TODO
PDC dc;
RECTL RectBounds;
PSURFOBJ SurfObj;
BRUSHOBJ PenBrushObj;
PBRUSHOBJ FillBrushObj;
PSHAPEPOINT ShapePoints;
UINT Point, PointCount;
BOOL ret = TRUE;
int Y, CircleStart, CircleEnd, LineStart, LineEnd;
BOOL FullFill;
if (Right <= Left || Bottom <= Top)
{
SetLastWin32Error(ERROR_INVALID_PARAMETER);
return FALSE;
}
if (Right - Left != Bottom - Top)
{
UNIMPLEMENTED;
}
dc = DC_LockDc ( hDC );
if (NULL == dc)
{
SetLastWin32Error(ERROR_INVALID_HANDLE);
return FALSE;
}
FillBrushObj = BRUSHOBJ_LockBrush(dc->w.hBrush);
if (NULL == FillBrushObj)
{
DC_UnlockDc(hDC);
SetLastWin32Error(ERROR_INTERNAL_ERROR);
return FALSE;
}
Left += dc->w.DCOrgX;
Right += dc->w.DCOrgX;
Top += dc->w.DCOrgY;
Bottom += dc->w.DCOrgY;
XRadialStart += dc->w.DCOrgX;
YRadialStart += dc->w.DCOrgY;
XRadialEnd += dc->w.DCOrgX;
YRadialEnd += dc->w.DCOrgY;
RectBounds.left = Left;
RectBounds.right = Right;
RectBounds.top = Top;
RectBounds.bottom = Bottom;
SurfObj = (PSURFOBJ) AccessUserObject((ULONG)dc->Surface);
HPenToBrushObj(&PenBrushObj, dc->w.hPen);
/* Number of points for the circle is 4 * sqrt(2) * Radius, start
and end line have at most Radius points, so allocate at least
that much */
ShapePoints = ExAllocatePool(PagedPool, 8 * (Right - Left + 1) / 2 * sizeof(SHAPEPOINT));
if (NULL == ShapePoints)
{
BRUSHOBJ_UnlockBrush(dc->w.hBrush);
DC_UnlockDc(hDC);
SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
}
if (Left == Right)
{
PUTPIXEL(Left, Top, &PenBrushObj);
BRUSHOBJ_UnlockBrush(dc->w.hBrush);
DC_UnlockDc(hDC);
return ret;
}
PointCount = 0;
CirclePoints(&PointCount, ShapePoints, Left, Top, Right, Bottom);
LinePoints(&PointCount, ShapePoints, Left, Top, Right, Bottom,
XRadialStart, YRadialStart, TRUE);
LinePoints(&PointCount, ShapePoints, Left, Top, Right, Bottom,
XRadialEnd, YRadialEnd, FALSE);
ASSERT(PointCount <= 8 * (Right - Left + 1) / 2);
EngSort((PBYTE) ShapePoints, sizeof(SHAPEPOINT), PointCount, CompareShapePoints);
FullFill = TRUE;
Point = 0;
while (Point < PointCount)
{
Y = ShapePoints[Point].Y;
/* Skip any line pixels before circle */
while (Point < PointCount && ShapePoints[Point].Y == Y
&& SHAPEPOINT_TYPE_CIRCLE != ShapePoints[Point].Type)
{
Point++;
}
/* Handle left side of circle */
if (Point < PointCount && ShapePoints[Point].Y == Y)
{
CircleStart = ShapePoints[Point].X;
Point++;
while (Point < PointCount && ShapePoints[Point].Y == Y
&& ShapePoints[Point].X == ShapePoints[Point - 1].X + 1
&& SHAPEPOINT_TYPE_CIRCLE == ShapePoints[Point].Type)
{
Point++;
}
CircleEnd = ShapePoints[Point - 1].X;
PUTLINE(CircleStart, Y, CircleEnd + 1, Y, &PenBrushObj);
}
/* Handle line(s) (max 2) inside the circle */
while (Point < PointCount && ShapePoints[Point].Y == Y
&& SHAPEPOINT_TYPE_CIRCLE != ShapePoints[Point].Type)
{
LineStart = ShapePoints[Point].X;
Point++;
while (Point < PointCount && ShapePoints[Point].Y == Y
&& ShapePoints[Point].X == ShapePoints[Point - 1].X + 1
&& ShapePoints[Point].Type == ShapePoints[Point - 1].Type)
{
Point++;
}
LineEnd = ShapePoints[Point - 1].X;
PUTLINE(LineStart, Y, LineEnd + 1, Y, &PenBrushObj);
}
/* Handle right side of circle */
while (Point < PointCount && ShapePoints[Point].Y == Y
&& SHAPEPOINT_TYPE_CIRCLE == ShapePoints[Point].Type)
{
CircleStart = ShapePoints[Point].X;
Point++;
while (Point < PointCount && ShapePoints[Point].Y == Y
&& ShapePoints[Point].X == ShapePoints[Point - 1].X + 1
&& SHAPEPOINT_TYPE_CIRCLE == ShapePoints[Point].Type)
{
Point++;
}
CircleEnd = ShapePoints[Point - 1].X;
PUTLINE(CircleStart, Y, CircleEnd + 1, Y, &PenBrushObj);
}
/* Skip any line pixels after circle */
while (Point < PointCount && ShapePoints[Point].Y == Y)
{
Point++;
}
}
ExFreePool(ShapePoints);
BRUSHOBJ_UnlockBrush(dc->w.hBrush);
DC_UnlockDc(hDC);
return ret;
#else
return TRUE;
#endif
}
#if 0