From ae68da49b62609036e32f3e447f9c61daa9490d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9=20van=20Geldorp?= Date: Fri, 12 Dec 2003 14:22:37 +0000 Subject: [PATCH] Incomplete implementation of hooks svn path=/trunk/; revision=6965 --- reactos/include/defines.h | 5 + reactos/include/user32/callback.h | 25 +- reactos/include/win32k/ntuser.h | 28 +- reactos/include/wine/debug.h | 2 +- reactos/lib/gdi32/misc/stubs.c | 24 +- reactos/lib/gdi32/objects/fillshap.c | 20 + reactos/lib/shlwapi/istream.c | 6 +- reactos/lib/shlwapi/reg.c | 5 + reactos/lib/user32/misc/dllmain.c | 2 + reactos/lib/user32/windows/hook.c | 147 +++++- reactos/subsys/win32k/include/callback.h | 9 + reactos/subsys/win32k/include/hook.h | 32 ++ reactos/subsys/win32k/include/msgqueue.h | 6 + reactos/subsys/win32k/include/object.h | 3 +- reactos/subsys/win32k/main/dllmain.c | 4 +- reactos/subsys/win32k/misc/object.c | 18 +- reactos/subsys/win32k/ntuser/callback.c | 111 ++++- reactos/subsys/win32k/ntuser/hook.c | 570 ++++++++++++++++++++++- reactos/subsys/win32k/ntuser/msgqueue.c | 14 +- reactos/subsys/win32k/ntuser/windc.c | 4 +- reactos/subsys/win32k/ntuser/window.c | 44 +- reactos/subsys/win32k/objects/fillshap.c | 417 ++++++++++++++++- 22 files changed, 1376 insertions(+), 120 deletions(-) create mode 100644 reactos/subsys/win32k/include/hook.h diff --git a/reactos/include/defines.h b/reactos/include/defines.h index 2bd011e0b1d..4753564949f 100644 --- a/reactos/include/defines.h +++ b/reactos/include/defines.h @@ -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) diff --git a/reactos/include/user32/callback.h b/reactos/include/user32/callback.h index 4c1fb28b773..9bc1eca7784 100644 --- a/reactos/include/user32/callback.h +++ b/reactos/include/user32/callback.h @@ -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 */ diff --git a/reactos/include/win32k/ntuser.h b/reactos/include/win32k/ntuser.h index cb9ccc92bc2..bd30b8e3109 100644 --- a/reactos/include/win32k/ntuser.h +++ b/reactos/include/win32k/ntuser.h @@ -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 diff --git a/reactos/include/wine/debug.h b/reactos/include/wine/debug.h index 785eab11d7d..afe27cff824 100644 --- a/reactos/include/wine/debug.h +++ b/reactos/include/wine/debug.h @@ -2,7 +2,7 @@ #define __WINE_DEBUG_H #include "../roscfg.h" -#ifndef DBG +#if ! defined(DBG) || ! defined(YDEBUG) #define NDEBUG #endif #include "../debug.h" diff --git a/reactos/lib/gdi32/misc/stubs.c b/reactos/lib/gdi32/misc/stubs.c index 11a491ec800..0dde5376501 100644 --- a/reactos/lib/gdi32/misc/stubs.c +++ b/reactos/lib/gdi32/misc/stubs.c @@ -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 */ diff --git a/reactos/lib/gdi32/objects/fillshap.c b/reactos/lib/gdi32/objects/fillshap.c index 4256ec8163e..a2a33f0a245 100644 --- a/reactos/lib/gdi32/objects/fillshap.c +++ b/reactos/lib/gdi32/objects/fillshap.c @@ -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); +} diff --git a/reactos/lib/shlwapi/istream.c b/reactos/lib/shlwapi/istream.c index cea294e30b0..e81e666bbda 100644 --- a/reactos/lib/shlwapi/istream.c +++ b/reactos/lib/shlwapi/istream.c @@ -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; } diff --git a/reactos/lib/shlwapi/reg.c b/reactos/lib/shlwapi/reg.c index 1d4cfe1632f..0d65ee850db 100644 --- a/reactos/lib/shlwapi/reg.c +++ b/reactos/lib/shlwapi/reg.c @@ -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 #include #ifdef __REACTOS__ diff --git a/reactos/lib/user32/misc/dllmain.c b/reactos/lib/user32/misc/dllmain.c index 095e6869c98..328d87cfb8e 100644 --- a/reactos/lib/user32/misc/dllmain.c +++ b/reactos/lib/user32/misc/dllmain.c @@ -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(); diff --git a/reactos/lib/user32/windows/hook.c b/reactos/lib/user32/windows/hook.c index 729e4774370..79b0695f821 100644 --- a/reactos/lib/user32/windows/hook.c +++ b/reactos/lib/user32/windows/hook.c @@ -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 #include +#include + +#define NDEBUG #include /* 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); +} diff --git a/reactos/subsys/win32k/include/callback.h b/reactos/subsys/win32k/include/callback.h index a6ae3fcbdcd..f0da1e46199 100644 --- a/reactos/subsys/win32k/include/callback.h +++ b/reactos/subsys/win32k/include/callback.h @@ -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 */ diff --git a/reactos/subsys/win32k/include/hook.h b/reactos/subsys/win32k/include/hook.h new file mode 100644 index 00000000000..921cf25c17a --- /dev/null +++ b/reactos/subsys/win32k/include/hook.h @@ -0,0 +1,32 @@ +#ifndef _WIN32K_HOOK_H +#define _WIN32K_HOOK_H + +#include +#include + +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 */ diff --git a/reactos/subsys/win32k/include/msgqueue.h b/reactos/subsys/win32k/include/msgqueue.h index ce5ef117a7d..f45300cde23 100644 --- a/reactos/subsys/win32k/include/msgqueue.h +++ b/reactos/subsys/win32k/include/msgqueue.h @@ -3,6 +3,7 @@ #include #include +#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 */ diff --git a/reactos/subsys/win32k/include/object.h b/reactos/subsys/win32k/include/object.h index 6f46df07a37..1cd0dc59221 100644 --- a/reactos/subsys/win32k/include/object.h +++ b/reactos/subsys/win32k/include/object.h @@ -12,7 +12,8 @@ typedef enum { otWindow, otMenu, otAcceleratorTable, - otCursorIcon + otCursorIcon, + otHookProc } USER_OBJECT_TYPE; typedef struct _USER_OBJECT_HEADER diff --git a/reactos/subsys/win32k/main/dllmain.c b/reactos/subsys/win32k/main/dllmain.c index d8e1893749f..0ef0e4ef26b 100644 --- a/reactos/subsys/win32k/main/dllmain.c +++ b/reactos/subsys/win32k/main/dllmain.c @@ -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 #include +#include #define NDEBUG #include @@ -161,6 +162,7 @@ Win32kThreadCallback (struct _ETHREAD *Thread, DbgPrint (" Destroy thread\n"); #endif + HOOK_DestroyThreadHooks(Thread); RemoveTimersThread(Thread->Cid.UniqueThread); UnregisterThreadHotKeys(Thread); DestroyThreadWindows(Thread); diff --git a/reactos/subsys/win32k/misc/object.c b/reactos/subsys/win32k/misc/object.c index 2a44a430966..cf67e37dc6b 100644 --- a/reactos/subsys/win32k/misc/object.c +++ b/reactos/subsys/win32k/misc/object.c @@ -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; } diff --git a/reactos/subsys/win32k/ntuser/callback.c b/reactos/subsys/win32k/ntuser/callback.c index 391c46fe065..78311aa94e6 100644 --- a/reactos/subsys/win32k/ntuser/callback.c +++ b/reactos/subsys/win32k/ntuser/callback.c @@ -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 +#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 */ diff --git a/reactos/subsys/win32k/ntuser/hook.c b/reactos/subsys/win32k/ntuser/hook.c index 8a68b3a6bae..9c7b949ab24 100644 --- a/reactos/subsys/win32k/ntuser/hook.c +++ b/reactos/subsys/win32k/ntuser/hook.c @@ -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 #include +#include +#include +#include +#include +#include +#include +#include +#include #define NDEBUG -#include +#include -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 diff --git a/reactos/subsys/win32k/ntuser/msgqueue.c b/reactos/subsys/win32k/ntuser/msgqueue.c index 760807f35af..71cb76ba4e4 100644 --- a/reactos/subsys/win32k/ntuser/msgqueue.c +++ b/reactos/subsys/win32k/ntuser/msgqueue.c @@ -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 */ diff --git a/reactos/subsys/win32k/ntuser/windc.c b/reactos/subsys/win32k/ntuser/windc.c index 2c667659fd6..11ef67dc2c6 100644 --- a/reactos/subsys/win32k/ntuser/windc.c +++ b/reactos/subsys/win32k/ntuser/windc.c @@ -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) diff --git a/reactos/subsys/win32k/ntuser/window.c b/reactos/subsys/win32k/ntuser/window.c index 988118dbc03..9b1d2af5d30 100644 --- a/reactos/subsys/win32k/ntuser/window.c +++ b/reactos/subsys/win32k/ntuser/window.c @@ -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 #include +#include #define NDEBUG #include @@ -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) diff --git a/reactos/subsys/win32k/objects/fillshap.c b/reactos/subsys/win32k/objects/fillshap.c index 27adad60788..ab051771463 100644 --- a/reactos/subsys/win32k/objects/fillshap.c +++ b/reactos/subsys/win32k/objects/fillshap.c @@ -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 @@ -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