From: James Tabor Date: Sat, 23 Oct 2010 05:36:12 +0000 (+0000) Subject: [Win32k|User32] X-Git-Tag: backups/reactos-yarotows@57446~9^2~2 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=e7c413731914c71ec2b50b836537c8b85f6a0bec [Win32k|User32] - Rewrite the Event and Hook procedures. See bug 5670 for more details. svn path=/trunk/; revision=49231 --- diff --git a/reactos/dll/win32/user32/include/user32.h b/reactos/dll/win32/user32/include/user32.h index ba2a8364656..c6dbbc7279c 100644 --- a/reactos/dll/win32/user32/include/user32.h +++ b/reactos/dll/win32/user32/include/user32.h @@ -43,7 +43,8 @@ #include #define HOOKID_TO_FLAG(HookId) (1 << ((HookId) + 1)) -#define ISITHOOKED(HookId) (GetWin32ClientInfo()->fsHooks & HOOKID_TO_FLAG(HookId)) +#define ISITHOOKED(HookId) (GetWin32ClientInfo()->fsHooks & HOOKID_TO_FLAG(HookId) ||\ + (GetWin32ClientInfo()->pDeskInfo && GetWin32ClientInfo()->pDeskInfo->fsHooks & HOOKID_TO_FLAG(HookId))) /* Temporarily in here for now. */ typedef struct _USERAPIHOOKINFO @@ -194,3 +195,4 @@ VOID FASTCALL GetConnected(VOID); BOOL FASTCALL DefSetText(HWND hWnd, PCWSTR String, BOOL Ansi); BOOL FASTCALL TestWindowProcess(PWND); VOID UserGetWindowBorders(DWORD, DWORD, SIZE *, BOOL); +VOID FASTCALL IntNotifyWinEvent(DWORD, HWND, LONG, LONG, DWORD); diff --git a/reactos/dll/win32/user32/include/user32p.h b/reactos/dll/win32/user32/include/user32p.h index 0227e8edce3..7bcf68cf777 100644 --- a/reactos/dll/win32/user32/include/user32p.h +++ b/reactos/dll/win32/user32/include/user32p.h @@ -83,9 +83,6 @@ #define NtUserGetCursorPos(lpPoint) \ (BOOL)NtUserCallOneParam((DWORD_PTR)lpPoint, ONEPARAM_ROUTINE_GETCURSORPOSITION) -#define NtUserIsWindowInDestroy(hWnd) \ - (BOOL)NtUserCallOneParam((DWORD_PTR)hWnd, ONEPARAM_ROUTINE_ISWINDOWINDESTROY) - #define NtUserEnableProcessWindowGhosting(bEnable) \ NtUserCallOneParam((DWORD_PTR)bEnable, ONEPARAM_ROUTINE_ENABLEPROCWNDGHSTING) diff --git a/reactos/dll/win32/user32/misc/misc.c b/reactos/dll/win32/user32/misc/misc.c index 76aaf462a31..e7b7672cfdc 100644 --- a/reactos/dll/win32/user32/misc/misc.c +++ b/reactos/dll/win32/user32/misc/misc.c @@ -304,13 +304,13 @@ GetUser32Handle(HANDLE handle) static const BOOL g_ObjectHeapTypeShared[VALIDATE_TYPE_EVENT + 1] = { FALSE, /* VALIDATE_TYPE_FREE (not used) */ - FALSE, /* VALIDATE_TYPE_WIN FALSE */ + FALSE, /* VALIDATE_TYPE_WIN */ TRUE, /* VALIDATE_TYPE_MENU FALSE */ TRUE, /* VALIDATE_TYPE_CURSOR */ TRUE, /* VALIDATE_TYPE_MWPOS */ - TRUE, /* VALIDATE_TYPE_HOOK FALSE */ + FALSE, /* VALIDATE_TYPE_HOOK */ FALSE, /* (not used) */ - TRUE, /* VALIDATE_TYPE_CALLPROC FALSE */ + FALSE, /* VALIDATE_TYPE_CALLPROC */ TRUE, /* VALIDATE_TYPE_ACCEL */ FALSE, /* (not used) */ FALSE, /* (not used) */ diff --git a/reactos/dll/win32/user32/windows/defwnd.c b/reactos/dll/win32/user32/windows/defwnd.c index 628940de1d6..76b34be0e9f 100644 --- a/reactos/dll/win32/user32/windows/defwnd.c +++ b/reactos/dll/win32/user32/windows/defwnd.c @@ -103,6 +103,7 @@ BOOL FASTCALL DefSetText(HWND hWnd, PCWSTR String, BOOL Ansi) { + BOOL Ret; LARGE_STRING lsString; if ( String ) @@ -112,7 +113,12 @@ DefSetText(HWND hWnd, PCWSTR String, BOOL Ansi) else RtlInitLargeUnicodeString((PLARGE_UNICODE_STRING)&lsString, String, 0); } - return NtUserDefSetText(hWnd, (String ? &lsString : NULL)); + Ret = NtUserDefSetText(hWnd, (String ? &lsString : NULL)); + + if (Ret) + IntNotifyWinEvent(EVENT_OBJECT_NAMECHANGE, hWnd, OBJID_WINDOW, CHILDID_SELF, 0); + + return Ret; } void @@ -1969,7 +1975,6 @@ RealDefWindowProcA(HWND hWnd, { DefWndNCPaint(hWnd, (HRGN)1, -1); } - Result = 1; break; } diff --git a/reactos/dll/win32/user32/windows/hook.c b/reactos/dll/win32/user32/windows/hook.c index 304f9320a96..f79bcbe7080 100644 --- a/reactos/dll/win32/user32/windows/hook.c +++ b/reactos/dll/win32/user32/windows/hook.c @@ -34,6 +34,14 @@ WINE_DEFAULT_DEBUG_CHANNEL(user32); +typedef struct _NOTIFYEVENT +{ + DWORD event; + LONG idObject; + LONG idChild; + DWORD flags; +} NOTIFYEVENT, *PNOTIFYEVENT; + /* PRIVATE FUNCTIONS *********************************************************/ static @@ -99,6 +107,29 @@ IntSetWindowsHook( return NtUserSetWindowsHookEx(hMod, &USModuleName, dwThreadId, idHook, lpfn, bAnsi); } +/* + Since ReactOS uses User32 as the main message source this was needed. + Base on the funny rules from the wine tests it left it with this option. + 8^( + */ +VOID +FASTCALL +IntNotifyWinEvent( + DWORD event, + HWND hwnd, + LONG idObject, + LONG idChild, + DWORD flags + ) +{ + NOTIFYEVENT ne; + ne.event = event; + ne.idObject = idObject; + ne.idChild = idChild; + ne.flags = flags; + if (gpsi->dwInstalledEventHooks & GetMaskFromEvent(event)) + NtUserCallHwndParam(hwnd, (DWORD)&ne, HWNDPARAM_ROUTINE_ROS_NOTIFYWINEVENT); +} /* FUNCTIONS *****************************************************************/ @@ -195,7 +226,7 @@ CallNextHookEx( { PCLIENTINFO ClientInfo; DWORD Flags, Save; - PHOOK pHook; + PHOOK pHook, phkNext; LRESULT lResult = 0; GetConnected(); @@ -204,9 +235,14 @@ CallNextHookEx( if (!ClientInfo->phkCurrent) return 0; - pHook = SharedPtrToUser(ClientInfo->phkCurrent); + pHook = DesktopPtrToUser(ClientInfo->phkCurrent); + + if (!pHook->phkNext) return 0; // Nothing to do.... - if (pHook->HookId == WH_CALLWNDPROC || pHook->HookId == WH_CALLWNDPROCRET) + phkNext = DesktopPtrToUser(pHook->phkNext); + + if ( phkNext->HookId == WH_CALLWNDPROC || + phkNext->HookId == WH_CALLWNDPROCRET) { Save = ClientInfo->dwHookData; Flags = ClientInfo->CI_flags & CI_CURTHPRHOOK; @@ -215,7 +251,7 @@ CallNextHookEx( if (wParam) ClientInfo->CI_flags |= CI_CURTHPRHOOK; else ClientInfo->CI_flags &= ~CI_CURTHPRHOOK; - if (pHook->HookId == WH_CALLWNDPROC) + if (phkNext->HookId == WH_CALLWNDPROC) { PCWPSTRUCT pCWP = (PCWPSTRUCT)lParam; @@ -225,7 +261,7 @@ CallNextHookEx( pCWP->lParam, (ULONG_PTR)&lResult, FNID_CALLWNDPROC, - pHook->Ansi); + phkNext->Ansi); } else { @@ -239,7 +275,7 @@ CallNextHookEx( pCWPR->lParam, (ULONG_PTR)&lResult, FNID_CALLWNDPROCRET, - pHook->Ansi); + phkNext->Ansi); } ClientInfo->CI_flags ^= ((ClientInfo->CI_flags ^ Flags) & CI_CURTHPRHOOK); ClientInfo->dwHookData = Save; @@ -252,23 +288,27 @@ CallNextHookEx( /* - * @unimplemented + * @implemented */ HHOOK WINAPI SetWindowsHookW(int idHook, HOOKPROC lpfn) { - return IntSetWindowsHook(idHook, lpfn, NULL, 0, FALSE); + DWORD ThreadId = PtrToUint(NtCurrentTeb()->ClientId.UniqueThread); + return IntSetWindowsHook(idHook, lpfn, NULL, ThreadId, FALSE); +// return NtUserSetWindowsHookAW(idHook, lpfn, FALSE); } /* - * @unimplemented + * @implemented */ HHOOK WINAPI SetWindowsHookA(int idHook, HOOKPROC lpfn) { - return IntSetWindowsHook(idHook, lpfn, NULL, 0, TRUE); + DWORD ThreadId = PtrToUint(NtCurrentTeb()->ClientId.UniqueThread); + return IntSetWindowsHook(idHook, lpfn, NULL, ThreadId, TRUE); +// return NtUserSetWindowsHookAW(idHook, lpfn, TRUE); } /* @@ -377,7 +417,7 @@ IsWinEventHookInstalled( } /* - * @unimplemented + * @implemented */ HHOOK WINAPI @@ -392,7 +432,7 @@ SetWindowsHookExA( /* - * @unimplemented + * @implemented */ HHOOK WINAPI @@ -417,14 +457,15 @@ User32CallHookProcFromKernel(PVOID Arguments, ULONG ArgumentLength) PHOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS CbtCreatewndExtra = NULL; WPARAM wParam = 0; LPARAM lParam = 0; - PKBDLLHOOKSTRUCT KeyboardLlData; - PMSLLHOOKSTRUCT MouseLlData; - PMSG Msg; - PMOUSEHOOKSTRUCT MHook; - PCWPSTRUCT CWP; - PCWPRETSTRUCT CWPR; + PKBDLLHOOKSTRUCT pKeyboardLlData; + PMSLLHOOKSTRUCT pMouseLlData; + PMSG pMsg; + PMOUSEHOOKSTRUCT pMHook; + PCWPSTRUCT pCWP; + PCWPRETSTRUCT pCWPR; PRECTL prl; LPCBTACTIVATESTRUCT pcbtas; + BOOL Hit = FALSE; Common = (PHOOKPROC_CALLBACK_ARGUMENTS) Arguments; @@ -464,8 +505,8 @@ User32CallHookProcFromKernel(PVOID Arguments, ULONG ArgumentLength) } break; case HCBT_CLICKSKIPPED: - MHook = (PMOUSEHOOKSTRUCT)((PCHAR) Common + Common->lParam); - lParam = (LPARAM) MHook; + pMHook = (PMOUSEHOOKSTRUCT)((PCHAR) Common + Common->lParam); + lParam = (LPARAM) pMHook; break; case HCBT_MOVESIZE: prl = (PRECTL)((PCHAR) Common + Common->lParam); @@ -475,7 +516,7 @@ User32CallHookProcFromKernel(PVOID Arguments, ULONG ArgumentLength) pcbtas = (LPCBTACTIVATESTRUCT)((PCHAR) Common + Common->lParam); lParam = (LPARAM) pcbtas; break; - case HCBT_KEYSKIPPED: + case HCBT_KEYSKIPPED: /* The rest SEH support */ case HCBT_MINMAX: case HCBT_SETFOCUS: case HCBT_SYSCOMMAND: @@ -490,7 +531,17 @@ User32CallHookProcFromKernel(PVOID Arguments, ULONG ArgumentLength) } if (Common->Proc) - Result = Common->Proc(Common->Code, wParam, lParam); + { + _SEH2_TRY + { + Result = Common->Proc(Common->Code, wParam, lParam); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + Hit = TRUE; + } + _SEH2_END; + } else { ERR("Common = 0x%x, Proc = 0x%x\n",Common,Common->Proc); @@ -504,41 +555,67 @@ User32CallHookProcFromKernel(PVOID Arguments, ULONG ArgumentLength) break; } case WH_KEYBOARD_LL: - KeyboardLlData = (PKBDLLHOOKSTRUCT)((PCHAR) Common + Common->lParam); - Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) KeyboardLlData); + pKeyboardLlData = (PKBDLLHOOKSTRUCT)((PCHAR) Common + Common->lParam); + Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) pKeyboardLlData); break; case WH_MOUSE_LL: - MouseLlData = (PMSLLHOOKSTRUCT)((PCHAR) Common + Common->lParam); - Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) MouseLlData); + pMouseLlData = (PMSLLHOOKSTRUCT)((PCHAR) Common + Common->lParam); + Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) pMouseLlData); break; - case WH_MOUSE: - MHook = (PMOUSEHOOKSTRUCT)((PCHAR) Common + Common->lParam); - Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) MHook); + case WH_MOUSE: /* SEH support */ + pMHook = (PMOUSEHOOKSTRUCT)((PCHAR) Common + Common->lParam); + _SEH2_TRY + { + Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) pMHook); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + Hit = TRUE; + } + _SEH2_END; break; case WH_CALLWNDPROC: - CWP = (PCWPSTRUCT)((PCHAR) Common + Common->lParam); - Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) CWP); + pCWP = (PCWPSTRUCT)((PCHAR) Common + Common->lParam); + Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) pCWP); break; case WH_CALLWNDPROCRET: - CWPR = (PCWPRETSTRUCT)((PCHAR) Common + Common->lParam); - Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) CWPR); + pCWPR = (PCWPRETSTRUCT)((PCHAR) Common + Common->lParam); + Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) pCWPR); break; - case WH_MSGFILTER: + case WH_MSGFILTER: /* All SEH support */ case WH_SYSMSGFILTER: case WH_GETMESSAGE: - Msg = (PMSG)((PCHAR) Common + Common->lParam); -// FIXME("UHOOK Memory: %x: %x\n",Common, Msg); - Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) Msg); + pMsg = (PMSG)((PCHAR) Common + Common->lParam); + _SEH2_TRY + { + Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) pMsg); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + Hit = TRUE; + } + _SEH2_END; break; - case WH_FOREGROUNDIDLE: + case WH_FOREGROUNDIDLE: /* <-- SEH support */ case WH_KEYBOARD: case WH_SHELL: - Result = Common->Proc(Common->Code, Common->wParam, Common->lParam); + _SEH2_TRY + { + Result = Common->Proc(Common->Code, Common->wParam, Common->lParam); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + Hit = TRUE; + } + _SEH2_END; break; default: return ZwCallbackReturn(NULL, 0, STATUS_NOT_SUPPORTED); } - + if (Hit) + { + ERR("Hook Exception! Id: %d, Code %d, Proc 0x%x\n",Common->HookId,Common->Code,Common->Proc); + } return ZwCallbackReturn(&Result, sizeof(LRESULT), STATUS_SUCCESS); } diff --git a/reactos/dll/win32/user32/windows/input.c b/reactos/dll/win32/user32/windows/input.c index aa9a997f070..08e457bf5a1 100644 --- a/reactos/dll/win32/user32/windows/input.c +++ b/reactos/dll/win32/user32/windows/input.c @@ -138,6 +138,7 @@ EnableWindow(HWND hWnd, if (Update) { + IntNotifyWinEvent(EVENT_OBJECT_STATECHANGE, hWnd, OBJID_WINDOW, CHILDID_SELF, 0); SendMessageW(hWnd, WM_ENABLE, (LPARAM)bEnable, 0); } // Return nonzero if it was disabled, or zero if it wasn't: diff --git a/reactos/dll/win32/user32/windows/menu.c b/reactos/dll/win32/user32/windows/menu.c index dd8f1ff1780..c9e87de47de 100644 --- a/reactos/dll/win32/user32/windows/menu.c +++ b/reactos/dll/win32/user32/windows/menu.c @@ -1636,6 +1636,8 @@ static BOOL FASTCALL MenuShowPopup(HWND hwndOwner, HMENU hmenu, UINT id, UINT fl top_popup_hmenu = hmenu; } + IntNotifyWinEvent(EVENT_SYSTEM_MENUPOPUPSTART, MenuInfo.Wnd, OBJID_CLIENT, CHILDID_SELF, 0); + /* Display the window */ SetWindowPos( MenuInfo.Wnd, HWND_TOPMOST, 0, 0, 0, 0, @@ -3445,6 +3447,7 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y, if (MenuInfo.Flags & MF_POPUP) { + IntNotifyWinEvent(EVENT_SYSTEM_MENUPOPUPEND, MenuInfo.Wnd, OBJID_CLIENT, CHILDID_SELF, 0); DestroyWindow(MenuInfo.Wnd); MenuInfo.Wnd = NULL; @@ -3518,7 +3521,11 @@ static BOOL FASTCALL MenuInitTracking(HWND hWnd, HMENU hMenu, BOOL bPopup, UINT MenuInfo.Wnd = hWnd; MenuSetRosMenuInfo(&MenuInfo); } - + + IntNotifyWinEvent( EVENT_SYSTEM_MENUSTART, + hWnd, + MenuInfo.Flags & MF_SYSMENU ? OBJID_SYSMENU : OBJID_MENU, + CHILDID_SELF, 0); return TRUE; } /*********************************************************************** @@ -3528,6 +3535,7 @@ static BOOL FASTCALL MenuExitTracking(HWND hWnd, BOOL bPopup) { TRACE("hwnd=%p\n", hWnd); + IntNotifyWinEvent( EVENT_SYSTEM_MENUEND, hWnd, OBJID_WINDOW, CHILDID_SELF, 0); SendMessageW( hWnd, WM_EXITMENULOOP, bPopup, 0 ); ShowCaret(0); top_popup = 0; @@ -3645,7 +3653,7 @@ BOOL WINAPI TrackPopupMenuEx( HMENU Menu, UINT Flags, int x, int y, { BOOL ret = FALSE; - if (!IsMenu(Menu)) + if (!IsMenu(Menu)) { SetLastError( ERROR_INVALID_MENU_HANDLE ); return FALSE; diff --git a/reactos/dll/win32/user32/windows/message.c b/reactos/dll/win32/user32/windows/message.c index 2c89b7863df..2645c87f234 100644 --- a/reactos/dll/win32/user32/windows/message.c +++ b/reactos/dll/win32/user32/windows/message.c @@ -2064,13 +2064,18 @@ SendMessageW(HWND Wnd, if (Wnd != HWND_BROADCAST && (Msg < WM_DDE_FIRST || Msg > WM_DDE_LAST)) { - if (Window != NULL && Window->head.pti == ti && !IsThreadHooked(GetWin32ClientInfo())) + if ( Window != NULL && + Window->head.pti == ti && + !IsThreadHooked(GetWin32ClientInfo()) && + !(Window->state & WNDS_SERVERSIDEWINDOWPROC) ) { /* NOTE: We can directly send messages to the window procedure if *all* the following conditions are met: * Window belongs to calling thread * The calling thread is not being hooked + * Not calling a server side proc: + Desktop, Switch, ScrollBar, Menu, IconTitle, or hWndMessage */ return IntCallMessageProc(Window, Wnd, Msg, wParam, lParam, FALSE); @@ -2130,13 +2135,18 @@ SendMessageA(HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam) if (Wnd != HWND_BROADCAST && (Msg < WM_DDE_FIRST || Msg > WM_DDE_LAST)) { - if (Window != NULL && Window->head.pti == ti && !IsThreadHooked(GetWin32ClientInfo())) + if ( Window != NULL && + Window->head.pti == ti && + !IsThreadHooked(GetWin32ClientInfo()) && + !(Window->state & WNDS_SERVERSIDEWINDOWPROC) ) { /* NOTE: We can directly send messages to the window procedure if *all* the following conditions are met: * Window belongs to calling thread * The calling thread is not being hooked + * Not calling a server side proc: + Desktop, Switch, ScrollBar, Menu, IconTitle, or hWndMessage */ return IntCallMessageProc(Window, Wnd, Msg, wParam, lParam, TRUE); diff --git a/reactos/dll/win32/user32/windows/window.c b/reactos/dll/win32/user32/windows/window.c index 468536ee290..1b1a0894e15 100644 --- a/reactos/dll/win32/user32/windows/window.c +++ b/reactos/dll/win32/user32/windows/window.c @@ -2060,7 +2060,11 @@ AnyPopup(VOID) BOOL WINAPI IsWindowInDestroy(HWND hWnd) { - return NtUserIsWindowInDestroy(hWnd); + PWND pwnd; + pwnd = ValidateHwnd(hWnd); + if (!pwnd) + return FALSE; + return ((pwnd->state2 & WNDS2_INDESTROY) == WNDS2_INDESTROY); } /* diff --git a/reactos/include/reactos/win32k/ntuser.h b/reactos/include/reactos/win32k/ntuser.h index 920e4e1abff..64071cb9066 100644 --- a/reactos/include/reactos/win32k/ntuser.h +++ b/reactos/include/reactos/win32k/ntuser.h @@ -51,13 +51,15 @@ VOID NTAPI RtlInitLargeAnsiString(IN OUT PLARGE_ANSI_STRING,IN PCSZ,IN INT); VOID NTAPI RtlInitLargeUnicodeString(IN OUT PLARGE_UNICODE_STRING,IN PCWSTR,IN INT); BOOL NTAPI RtlLargeStringToUnicodeString( PUNICODE_STRING, PLARGE_STRING); +#define NB_HOOKS (WH_MAXHOOK-WH_MINHOOK+1) + typedef struct _DESKTOPINFO { PVOID pvDesktopBase; PVOID pvDesktopLimit; struct _WND *spwnd; DWORD fsHooks; - struct tagHOOK * aphkStart[16]; + LIST_ENTRY aphkStart[NB_HOOKS]; HWND hTaskManWindow; HWND hProgmanWindow; @@ -127,15 +129,23 @@ typedef struct _PROCMARKHEAD /* Window Client Information structure */ struct _ETHREAD; +#define WEF_SETBYWNDPTI 0x0001 + typedef struct tagHOOK { THRDESKHEAD head; + struct tagHOOK *phkNext; /* This is for user space. */ + int HookId; /* Hook table index */ + ULONG_PTR offPfn; + ULONG flags; /* Some internal flags */ + INT ihmod; + PTHREADINFO ptiHooked; + struct _DESKTOP *rpdesk; + /* ReactOS */ LIST_ENTRY Chain; /* Hook chain entry */ struct _ETHREAD* Thread; /* Thread owning the hook */ - int HookId; /* Hook table index */ HOOKPROC Proc; /* Hook function */ BOOLEAN Ansi; /* Is it an Ansi hook? */ - ULONG Flags; /* Some internal flags */ UNICODE_STRING ModuleName; /* Module name for global hooks */ } HOOK, *PHOOK; @@ -3149,7 +3159,6 @@ typedef struct tagKMDDELPARAM #define NOPARAM_ROUTINE_ANYPOPUP 0xffff0006 #define ONEPARAM_ROUTINE_CSRSS_GUICHECK 0xffff0008 #define ONEPARAM_ROUTINE_SWITCHCARETSHOWING 0xfffe0008 -#define ONEPARAM_ROUTINE_ISWINDOWINDESTROY 0xfffe000c #define ONEPARAM_ROUTINE_ENABLEPROCWNDGHSTING 0xfffe000d #define ONEPARAM_ROUTINE_GETDESKTOPMAPPING 0xfffe000e #define ONEPARAM_ROUTINE_MSQSETWAKEMASK 0xfffe0027 @@ -3167,6 +3176,7 @@ typedef struct tagKMDDELPARAM #define TWOPARAM_ROUTINE_SETCARETPOS 0xfffd0060 #define TWOPARAM_ROUTINE_REGISTERLOGONPROC 0xfffd0062 #define TWOPARAM_ROUTINE_ROS_UPDATEUISTATE 0x1004 +#define HWNDPARAM_ROUTINE_ROS_NOTIFYWINEVENT 0x1005 DWORD NTAPI diff --git a/reactos/subsystems/win32/win32k/include/hook.h b/reactos/subsystems/win32/win32k/include/hook.h index d09304b4895..ce6d64e1b9f 100644 --- a/reactos/subsystems/win32/win32k/include/hook.h +++ b/reactos/subsystems/win32/win32k/include/hook.h @@ -1,17 +1,10 @@ #pragma once #define HOOK_THREAD_REFERENCED (0x1) -#define NB_HOOKS (WH_MAXHOOK-WH_MINHOOK+1) #define HOOKID_TO_INDEX(HookId) (HookId - WH_MINHOOK) #define HOOKID_TO_FLAG(HookId) (1 << ((HookId) + 1)) #define ISITHOOKED(HookId) (((PTHREADINFO)PsGetCurrentThreadWin32Thread())->fsHooks & HOOKID_TO_FLAG(HookId)) -typedef struct tagHOOKTABLE -{ - LIST_ENTRY Hooks[NB_HOOKS]; /* array of hook chains */ - UINT Counts[NB_HOOKS]; /* use counts for each hook chain */ -} HOOKTABLE, *PHOOKTABLE; - typedef struct tagEVENTHOOK { THROBJHEAD head; @@ -32,11 +25,22 @@ typedef struct tagEVENTTABLE UINT Counts; } EVENTTABLE, *PEVENTTABLE; +typedef struct _NOTIFYEVENT +{ + DWORD event; + LONG idObject; + LONG idChild; + DWORD flags; +} NOTIFYEVENT, *PNOTIFYEVENT; + +LRESULT FASTCALL co_CallHook(INT HookId, INT Code, WPARAM wParam, LPARAM lParam); LRESULT FASTCALL co_HOOK_CallHooks(INT HookId, INT Code, WPARAM wParam, LPARAM lParam); LRESULT FASTCALL co_EVENT_CallEvents(DWORD, HWND, UINT_PTR, LONG_PTR); VOID FASTCALL HOOK_DestroyThreadHooks(PETHREAD Thread); +VOID FASTCALL EVENT_DestroyThreadEvents(PETHREAD Thread); PHOOK FASTCALL IntGetHookObject(HHOOK); PHOOK FASTCALL IntGetNextHook(PHOOK Hook); LRESULT FASTCALL UserCallNextHookEx( PHOOK pHook, int Code, WPARAM wParam, LPARAM lParam, BOOL Ansi); +BOOL FASTCALL IntUnhookWindowsHook(int,HOOKPROC); /* EOF */ diff --git a/reactos/subsystems/win32/win32k/include/msgqueue.h b/reactos/subsystems/win32/win32k/include/msgqueue.h index e35ab0f5a15..569f1028d83 100644 --- a/reactos/subsystems/win32/win32k/include/msgqueue.h +++ b/reactos/subsystems/win32/win32k/include/msgqueue.h @@ -87,9 +87,6 @@ typedef struct _USER_MESSAGE_QUEUE /* Caret information for this queue */ PTHRDCARETINFO CaretInfo; - /* Window hooks */ - PHOOKTABLE Hooks; - /* queue state tracking */ WORD WakeMask; WORD QueueBits; @@ -212,9 +209,6 @@ BOOL APIENTRY IntInitMessagePumpHook(); BOOL APIENTRY 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); - LPARAM FASTCALL MsqSetMessageExtraInfo(LPARAM lParam); LPARAM FASTCALL MsqGetMessageExtraInfo(VOID); VOID APIENTRY MsqRemoveWindowMessagesFromQueue(PVOID pWindow); /* F*(&$ headers, will be gone in the rewrite! */ diff --git a/reactos/subsystems/win32/win32k/include/win32.h b/reactos/subsystems/win32/win32k/include/win32.h index 63dfba76fe2..ed1e645a0a6 100644 --- a/reactos/subsystems/win32/win32k/include/win32.h +++ b/reactos/subsystems/win32/win32k/include/win32.h @@ -96,6 +96,7 @@ typedef struct _THREADINFO LIST_ENTRY PtiLink; POINT ptLast; + LIST_ENTRY aphkStart[NB_HOOKS]; CLIENTTHREADINFO cti; // Used only when no Desktop or pcti NULL. /* ReactOS */ LIST_ENTRY WindowListHead; @@ -150,6 +151,8 @@ typedef struct _W32PROCESS LIST_ENTRY GDIBrushAttrFreeList; } W32PROCESS, *PW32PROCESS; +#define CLIBS 32 + typedef struct _PROCESSINFO { W32PROCESS; @@ -158,11 +161,15 @@ typedef struct _PROCESSINFO struct _DESKTOP* rpdeskStartup; PCLS pclsPrivateList; PCLS pclsPublicList; - + DWORD dwhmodLibLoadedMask; + HANDLE ahmodLibLoaded[CLIBS]; + struct _WINSTATION_OBJECT *prpwinsta; + HWINSTA hwinsta; + ACCESS_MASK amwinsta; + DWORD dwHotkey; HMONITOR hMonitor; - + LUID luidSession; USERSTARTUPINFO usi; - ULONG Flags; DWORD dwLayout; DWORD dwRegisteredClasses; /* ReactOS */ diff --git a/reactos/subsystems/win32/win32k/include/window.h b/reactos/subsystems/win32/win32k/include/window.h index a91183a0153..39a55b26e00 100644 --- a/reactos/subsystems/win32/win32k/include/window.h +++ b/reactos/subsystems/win32/win32k/include/window.h @@ -104,7 +104,7 @@ IntShowOwnedPopups( PWND owner, BOOL fShow ); LRESULT FASTCALL IntDefWindowProc( PWND Window, UINT Msg, WPARAM wParam, LPARAM lParam, BOOL Ansi); -VOID FASTCALL IntNotifyWinEvent(DWORD, PWND, LONG, LONG); +VOID FASTCALL IntNotifyWinEvent(DWORD, PWND, LONG, LONG, DWORD); PWND FASTCALL co_UserCreateWindowEx(CREATESTRUCTW*, PUNICODE_STRING, PLARGE_STRING); WNDPROC FASTCALL IntGetWindowProc(PWND,BOOL); diff --git a/reactos/subsystems/win32/win32k/main/dllmain.c b/reactos/subsystems/win32/win32k/main/dllmain.c index 0c992c0e72f..603dd9487d4 100644 --- a/reactos/subsystems/win32/win32k/main/dllmain.c +++ b/reactos/subsystems/win32/win32k/main/dllmain.c @@ -175,6 +175,7 @@ Win32kThreadCallback(struct _ETHREAD *Thread, { struct _EPROCESS *Process; PTHREADINFO Win32Thread; + int i; DECLARE_RETURN(NTSTATUS); DPRINT("Enter Win32kThreadCallback\n"); @@ -214,6 +215,10 @@ Win32kThreadCallback(struct _ETHREAD *Thread, InitializeListHead(&Win32Thread->WindowListHead); InitializeListHead(&Win32Thread->W32CallbackListHead); InitializeListHead(&Win32Thread->PtiLink); + for (i = 0; i < NB_HOOKS; i++) + { + InitializeListHead(&Win32Thread->aphkStart[i]); + } /* * inherit the thread desktop and process window station (if not yet inherited) from the process startup @@ -290,6 +295,7 @@ Win32kThreadCallback(struct _ETHREAD *Thread, Win32Thread->TIF_flags |= TIF_INCLEANUP; DceFreeThreadDCE(Win32Thread); HOOK_DestroyThreadHooks(Thread); + EVENT_DestroyThreadEvents(Thread); /* Cleanup timers */ DestroyTimersForThread(Win32Thread); KeSetEvent(Win32Thread->MessageQueue->NewMessages, IO_NO_INCREMENT, FALSE); diff --git a/reactos/subsystems/win32/win32k/ntuser/callback.c b/reactos/subsystems/win32/win32k/ntuser/callback.c index e536d4ca7e1..997cd4fb8b5 100644 --- a/reactos/subsystems/win32/win32k/ntuser/callback.c +++ b/reactos/subsystems/win32/win32k/ntuser/callback.c @@ -324,20 +324,20 @@ co_IntCallHookProc(INT HookId, PUNICODE_STRING ModuleName) { ULONG ArgumentLength; - PVOID Argument; + PVOID Argument = NULL; LRESULT Result = 0; NTSTATUS Status; PVOID ResultPointer; ULONG ResultLength; PHOOKPROC_CALLBACK_ARGUMENTS Common; - CBT_CREATEWNDW *CbtCreateWnd =NULL; + CBT_CREATEWNDW *CbtCreateWnd = NULL; PCHAR Extra; PHOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS CbtCreatewndExtra = NULL; - UNICODE_STRING WindowName; - UNICODE_STRING ClassName; - PANSI_STRING asWindowName; - PANSI_STRING asClassName; + UNICODE_STRING WindowName, ClassName; + ANSI_STRING asWindowName, asClassName; PTHREADINFO pti; + PWND pWnd; + BOOL Hit = FALSE; ASSERT(Proc); @@ -356,33 +356,67 @@ co_IntCallHookProc(INT HookId, switch(Code) { case HCBT_CREATEWND: + pWnd = UserGetWindowObject((HWND) wParam); + if (!pWnd) + { + DPRINT1("WH_CBT HCBT_CREATEWND wParam bad hWnd!\n"); + goto Fault_Exit; + } + CbtCreateWnd = (CBT_CREATEWNDW *) lParam; ArgumentLength += sizeof(HOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS); - asWindowName = (PANSI_STRING)&WindowName; - asClassName = (PANSI_STRING)&ClassName; - if (Ansi) { - RtlInitAnsiString(asWindowName, (PCSZ)CbtCreateWnd->lpcs->lpszName); - ArgumentLength += WindowName.Length + sizeof(CHAR); + RtlInitAnsiString(&asWindowName, NULL); + _SEH2_TRY + { + ProbeForRead(CbtCreateWnd->lpcs->lpszName, sizeof(CHAR), 1); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + Hit = TRUE; + } + _SEH2_END; + if (Hit) // Client is at deaths door. + goto Fault_Exit; + if (CbtCreateWnd->lpcs->lpszName) + RtlInitAnsiString(&asWindowName, (PCSZ)CbtCreateWnd->lpcs->lpszName); + ArgumentLength += asWindowName.Length + sizeof(CHAR); } else { - RtlInitUnicodeString(&WindowName, CbtCreateWnd->lpcs->lpszName); + RtlInitUnicodeString(&WindowName, NULL); + _SEH2_TRY + { + ProbeForRead(CbtCreateWnd->lpcs->lpszName, sizeof(WCHAR), 1); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + Hit = TRUE; + } + _SEH2_END; + if (Hit) + goto Fault_Exit; + if (CbtCreateWnd->lpcs->lpszName) + RtlInitUnicodeString(&WindowName, CbtCreateWnd->lpcs->lpszName); ArgumentLength += WindowName.Length + sizeof(WCHAR); } - if (! IS_ATOM(CbtCreateWnd->lpcs->lpszClass)) + if (!IS_ATOM(CbtCreateWnd->lpcs->lpszClass)) { if (Ansi) { - RtlInitAnsiString(asClassName, (PCSZ)CbtCreateWnd->lpcs->lpszClass); - ArgumentLength += ClassName.Length + sizeof(CHAR); + RtlInitAnsiString(&asClassName, NULL); + if (CbtCreateWnd->lpcs->lpszClass) + RtlInitAnsiString(&asClassName, (PCSZ)CbtCreateWnd->lpcs->lpszClass); + ArgumentLength += asClassName.Length + sizeof(CHAR); } else { - RtlInitUnicodeString(&ClassName, CbtCreateWnd->lpcs->lpszClass); + RtlInitUnicodeString(&ClassName, NULL); + if (CbtCreateWnd->lpcs->lpszClass) + RtlInitUnicodeString(&ClassName, CbtCreateWnd->lpcs->lpszClass); ArgumentLength += ClassName.Length + sizeof(WCHAR); } } @@ -408,7 +442,7 @@ co_IntCallHookProc(INT HookId, break; default: DPRINT1("Trying to call unsupported CBT hook %d\n", Code); - return 0; + goto Fault_Exit; } break; case WH_KEYBOARD_LL: @@ -437,14 +471,14 @@ co_IntCallHookProc(INT HookId, break; default: DPRINT1("Trying to call unsupported window hook %d\n", HookId); - return 0; + goto Fault_Exit; } Argument = IntCbAllocateMemory(ArgumentLength); if (NULL == Argument) { DPRINT1("HookProc callback failed: out of memory\n"); - return 0; + goto Fault_Exit; } Common = (PHOOKPROC_CALLBACK_ARGUMENTS) Argument; Common->HookId = HookId; @@ -454,7 +488,8 @@ co_IntCallHookProc(INT HookId, Common->Proc = Proc; Common->Ansi = Ansi; Common->ModuleNameLength = ModuleName->Length; - memcpy(Common->ModuleName, ModuleName->Buffer, ModuleName->Length); + if (ModuleName->Buffer) + RtlCopyMemory(Common->ModuleName, ModuleName->Buffer, ModuleName->Length); Extra = (PCHAR) Common->ModuleName + Common->ModuleNameLength; switch(HookId) @@ -468,32 +503,53 @@ co_IntCallHookProc(INT HookId, RtlCopyMemory( &CbtCreatewndExtra->Cs, CbtCreateWnd->lpcs, sizeof(CREATESTRUCTW) ); CbtCreatewndExtra->WndInsertAfter = CbtCreateWnd->hwndInsertAfter; Extra = (PCHAR) (CbtCreatewndExtra + 1); - RtlCopyMemory(Extra, WindowName.Buffer, WindowName.Length); - CbtCreatewndExtra->Cs.lpszName = (LPCWSTR) (Extra - (PCHAR) CbtCreatewndExtra); - CbtCreatewndExtra->Cs.lpszClass = ClassName.Buffer; - Extra += WindowName.Length; + CbtCreatewndExtra->Cs.lpszClass = ClassName.Buffer; // if Atom + if (Ansi) { + if (asWindowName.Buffer) + RtlCopyMemory(Extra, asWindowName.Buffer, asWindowName.Length); + CbtCreatewndExtra->Cs.lpszName = (LPCWSTR) (Extra - (PCHAR) CbtCreatewndExtra); + Extra += asWindowName.Length; + *((CHAR *) Extra) = '\0'; Extra += sizeof(CHAR); } else { + if (asWindowName.Buffer) + RtlCopyMemory(Extra, WindowName.Buffer, WindowName.Length); + CbtCreatewndExtra->Cs.lpszName = (LPCWSTR) (Extra - (PCHAR) CbtCreatewndExtra); + Extra += WindowName.Length; + *((WCHAR *) Extra) = L'\0'; Extra += sizeof(WCHAR); } - if (! IS_ATOM(ClassName.Buffer)) + if (!IS_ATOM(ClassName.Buffer)) { - RtlCopyMemory(Extra, ClassName.Buffer, ClassName.Length); - CbtCreatewndExtra->Cs.lpszClass = - (LPCWSTR)(ULONG_PTR) MAKELONG(Extra - (PCHAR) CbtCreatewndExtra, 1); - Extra += ClassName.Length; - if (Ansi) + { + if (asClassName.Buffer) + RtlCopyMemory(Extra, asClassName.Buffer, asClassName.Length); + CbtCreatewndExtra->Cs.lpszClass = + (LPCWSTR)(ULONG_PTR) MAKELONG(Extra - (PCHAR) CbtCreatewndExtra, 1); + Extra += asClassName.Length; + *((CHAR *) Extra) = '\0'; + Extra += sizeof(CHAR); + } else + { + if (ClassName.Buffer) + RtlCopyMemory(Extra, ClassName.Buffer, ClassName.Length); + CbtCreatewndExtra->Cs.lpszClass = + (LPCWSTR)(ULONG_PTR) MAKELONG(Extra - (PCHAR) CbtCreatewndExtra, 1); + Extra += ClassName.Length; + *((WCHAR *) Extra) = L'\0'; + Extra += sizeof(WCHAR); + } } break; case HCBT_CLICKSKIPPED: @@ -535,7 +591,6 @@ co_IntCallHookProc(INT HookId, case WH_GETMESSAGE: RtlCopyMemory(Extra, (PVOID) lParam, sizeof(MSG)); Common->lParam = (LPARAM) (Extra - (PCHAR) Common); -// DPRINT1("KHOOK Memory: %x\n",Common); break; case WH_FOREGROUNDIDLE: case WH_KEYBOARD: @@ -565,37 +620,47 @@ co_IntCallHookProc(INT HookId, _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { Result = 0; + Hit = TRUE; } _SEH2_END; if (!NT_SUCCESS(Status)) { - return 0; + goto Fault_Exit; } - - if (HookId == WH_CBT && Code == HCBT_CREATEWND) + /* Support write backs... SEH is in UserCallNextHookEx. */ + switch (HookId) { - if (CbtCreatewndExtra) - { - _SEH2_TRY - { /* - The parameters could have been changed, include the coordinates - and dimensions of the window. We copy it back. - */ - CbtCreateWnd->hwndInsertAfter = CbtCreatewndExtra->WndInsertAfter; - CbtCreateWnd->lpcs->x = CbtCreatewndExtra->Cs.x; - CbtCreateWnd->lpcs->y = CbtCreatewndExtra->Cs.y; - CbtCreateWnd->lpcs->cx = CbtCreatewndExtra->Cs.cx; - CbtCreateWnd->lpcs->cy = CbtCreatewndExtra->Cs.cy; + case WH_CBT: + if (Code == HCBT_CREATEWND) + { + if (CbtCreatewndExtra) + {/* + The parameters could have been changed, include the coordinates + and dimensions of the window. We copy it back. + */ + CbtCreateWnd->hwndInsertAfter = CbtCreatewndExtra->WndInsertAfter; + CbtCreateWnd->lpcs->x = CbtCreatewndExtra->Cs.x; + CbtCreateWnd->lpcs->y = CbtCreatewndExtra->Cs.y; + CbtCreateWnd->lpcs->cx = CbtCreatewndExtra->Cs.cx; + CbtCreateWnd->lpcs->cy = CbtCreatewndExtra->Cs.cy; + } } - _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + break; + // "The GetMsgProc hook procedure can examine or modify the message." + case WH_GETMESSAGE: + if (lParam) { - Result = 0; + RtlCopyMemory((PVOID) lParam, Extra, sizeof(MSG)); } - _SEH2_END; - } + break; } +Fault_Exit: + if (Hit) + { + DPRINT1("Exception CallHookProc HookId %d Code %d\n",HookId,Code); + } if (Argument) IntCbFreeMemory(Argument); return Result; diff --git a/reactos/subsystems/win32/win32k/ntuser/caret.c b/reactos/subsystems/win32/win32k/ntuser/caret.c index 3ebae7ae11b..76d58a7120b 100644 --- a/reactos/subsystems/win32/win32k/ntuser/caret.c +++ b/reactos/subsystems/win32/win32k/ntuser/caret.c @@ -30,10 +30,13 @@ static BOOL FASTCALL co_IntHideCaret(PTHRDCARETINFO CaretInfo) { + PWND pWnd; if(CaretInfo->hWnd && CaretInfo->Visible && CaretInfo->Showing) { + pWnd = UserGetWindowObject(CaretInfo->hWnd); co_IntSendMessage(CaretInfo->hWnd, WM_SYSTIMER, IDCARETTIMER, 0); CaretInfo->Showing = 0; + IntNotifyWinEvent(EVENT_OBJECT_HIDE, pWnd, OBJID_CARET, CHILDID_SELF, 0); return TRUE; } return FALSE; @@ -43,17 +46,20 @@ BOOL FASTCALL co_IntDestroyCaret(PTHREADINFO Win32Thread) { PUSER_MESSAGE_QUEUE ThreadQueue; + PWND pWnd; ThreadQueue = (PUSER_MESSAGE_QUEUE)Win32Thread->MessageQueue; if(!ThreadQueue || !ThreadQueue->CaretInfo) return FALSE; + pWnd = UserGetWindowObject(ThreadQueue->CaretInfo->hWnd); co_IntHideCaret(ThreadQueue->CaretInfo); ThreadQueue->CaretInfo->Bitmap = (HBITMAP)0; ThreadQueue->CaretInfo->hWnd = (HWND)0; ThreadQueue->CaretInfo->Size.cx = ThreadQueue->CaretInfo->Size.cy = 0; ThreadQueue->CaretInfo->Showing = 0; ThreadQueue->CaretInfo->Visible = 0; + IntNotifyWinEvent(EVENT_OBJECT_DESTROY, pWnd, OBJID_CARET, CHILDID_SELF, 0); return TRUE; } @@ -176,6 +182,7 @@ BOOL FASTCALL co_IntSetCaretPos(int X, int Y) { PTHREADINFO pti; + PWND pWnd; PUSER_MESSAGE_QUEUE ThreadQueue; pti = PsGetCurrentThreadWin32Thread(); @@ -183,6 +190,7 @@ co_IntSetCaretPos(int X, int Y) if(ThreadQueue->CaretInfo->hWnd) { + pWnd = UserGetWindowObject(ThreadQueue->CaretInfo->hWnd); if(ThreadQueue->CaretInfo->Pos.x != X || ThreadQueue->CaretInfo->Pos.y != Y) { co_IntHideCaret(ThreadQueue->CaretInfo); @@ -191,6 +199,7 @@ co_IntSetCaretPos(int X, int Y) ThreadQueue->CaretInfo->Pos.y = Y; co_IntSendMessage(ThreadQueue->CaretInfo->hWnd, WM_SYSTIMER, IDCARETTIMER, 0); IntSetTimer(UserGetWindowObject(ThreadQueue->CaretInfo->hWnd), IDCARETTIMER, IntGetCaretBlinkTime(), NULL, TMRF_SYSTEM); + IntNotifyWinEvent(EVENT_OBJECT_LOCATIONCHANGE, pWnd, OBJID_CARET, CHILDID_SELF, 0); } return TRUE; } @@ -277,6 +286,7 @@ BOOL FASTCALL co_UserHideCaret(PWND Window OPTIONAL) BOOL FASTCALL co_UserShowCaret(PWND Window OPTIONAL) { PTHREADINFO pti; + PWND pWnd; PUSER_MESSAGE_QUEUE ThreadQueue; if (Window) ASSERT_REFS_CO(Window); @@ -301,11 +311,12 @@ BOOL FASTCALL co_UserShowCaret(PWND Window OPTIONAL) ThreadQueue->CaretInfo->Visible = 1; if(!ThreadQueue->CaretInfo->Showing) { + pWnd = UserGetWindowObject(ThreadQueue->CaretInfo->hWnd); co_IntSendMessage(ThreadQueue->CaretInfo->hWnd, WM_SYSTIMER, IDCARETTIMER, 0); + IntNotifyWinEvent(EVENT_OBJECT_SHOW, pWnd, OBJID_CARET, OBJID_CARET, 0); } IntSetTimer(UserGetWindowObject(ThreadQueue->CaretInfo->hWnd), IDCARETTIMER, IntGetCaretBlinkTime(), NULL, TMRF_SYSTEM); } - return TRUE; } @@ -370,7 +381,7 @@ NtUserCreateCaret( } ThreadQueue->CaretInfo->Visible = 0; ThreadQueue->CaretInfo->Showing = 0; - + IntNotifyWinEvent(EVENT_OBJECT_CREATE, Window, OBJID_CARET, CHILDID_SELF, 0); RETURN(TRUE); CLEANUP: diff --git a/reactos/subsystems/win32/win32k/ntuser/desktop.c b/reactos/subsystems/win32/win32k/ntuser/desktop.c index 3a054f2f08d..59333113ad2 100644 --- a/reactos/subsystems/win32/win32k/ntuser/desktop.c +++ b/reactos/subsystems/win32/win32k/ntuser/desktop.c @@ -884,6 +884,7 @@ NtUserCreateDesktop( LARGE_STRING WindowName; PWND pWnd = NULL; CREATESTRUCTW Cs; + INT i; DECLARE_RETURN(HDESK); DPRINT("Enter NtUserCreateDesktop: %wZ\n", lpszDesktopName); @@ -1026,6 +1027,11 @@ NtUserCreateDesktop( /* Initialize some local (to win32k) desktop state. */ InitializeListHead(&DesktopObject->PtiList); DesktopObject->ActiveMessageQueue = NULL; + /* Setup Global Hooks. */ + for (i = 0; i < NB_HOOKS; i++) + { + InitializeListHead(&DesktopObject->pDeskInfo->aphkStart[i]); + } ExFreePoolWithTag(DesktopName.Buffer, TAG_STRING); if (! NT_SUCCESS(Status)) diff --git a/reactos/subsystems/win32/win32k/ntuser/event.c b/reactos/subsystems/win32/win32k/ntuser/event.c index 02d2ffeb2a2..2c5a91e53c1 100644 --- a/reactos/subsystems/win32/win32k/ntuser/event.c +++ b/reactos/subsystems/win32/win32k/ntuser/event.c @@ -2,7 +2,7 @@ * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * PURPOSE: Window event handlers - * FILE: subsystem/win32/win32k/ntuser/event.c + * FILE: subsystems/win32/win32k/ntuser/event.c * PROGRAMER: James Tabor (james.tabor@rectos.org) */ @@ -103,12 +103,15 @@ IntCallLowLevelEvent( PEVENTHOOK pEH, LONG idChild) { NTSTATUS Status; - ULONG_PTR uResult; - EVENTPACK EP; + PEVENTPACK pEP; + ULONG_PTR uResult = 0; - EP.pEH = pEH; - EP.idObject = idObject; - EP.idChild = idChild; + pEP = ExAllocatePoolWithTag(NonPagedPool, sizeof(EVENTPACK), TAG_HOOK); + if (!pEP) return 0; + + pEP->pEH = pEH; + pEP->idObject = idObject; + pEP->idChild = idChild; /* FIXME should get timeout from * HKEY_CURRENT_USER\Control Panel\Desktop\LowLevelHooksTimeout */ @@ -116,16 +119,18 @@ IntCallLowLevelEvent( PEVENTHOOK pEH, hwnd, event, 0, - (LPARAM)&EP, + (LPARAM)pEP, 5000, TRUE, MSQ_ISEVENT, &uResult); - + if (!NT_SUCCESS(Status)) + { + ExFreePoolWithTag(pEP, TAG_HOOK); + } return NT_SUCCESS(Status) ? uResult : 0; } - static BOOL FASTCALL @@ -145,14 +150,49 @@ IntRemoveEvent(PEVENTHOOK pEH) return FALSE; } +VOID +FASTCALL +EVENT_DestroyThreadEvents(PETHREAD Thread) +{ + PTHREADINFO pti; + PEVENTHOOK pEH; + PLIST_ENTRY pLE; + + pti = Thread->Tcb.Win32Thread; + if (!pti) return; + + if (!GlobalEvents || !GlobalEvents->Counts) return; + + pLE = GlobalEvents->Events.Flink; + if (IsListEmpty(pLE)) return; + + pEH = CONTAINING_RECORD(pLE, EVENTHOOK, Chain); + do + { + if (IsListEmpty(pLE)) break; + if (!pEH) break; + pLE = pEH->Chain.Flink; + if (pEH->head.pti == pti) + { + IntRemoveEvent(pEH); + } + pEH = CONTAINING_RECORD(pLE, EVENTHOOK, Chain); + } while (pLE != &GlobalEvents->Events); + + return; +} + /* FUNCTIONS *****************************************************************/ +// +// Dispatch MsgQueue Event Call processor! +// LRESULT FASTCALL co_EVENT_CallEvents( DWORD event, - HWND hwnd, - UINT_PTR idObject, - LONG_PTR idChild) + HWND hwnd, + UINT_PTR idObject, + LONG_PTR idChild) { PEVENTHOOK pEH; LRESULT Result; @@ -165,9 +205,11 @@ co_EVENT_CallEvents( DWORD event, hwnd, pEP->idObject, pEP->idChild, - (DWORD_PTR)(NtCurrentTeb()->ClientId).UniqueThread, + PtrToUint(NtCurrentTeb()->ClientId.UniqueThread), (DWORD)EngGetTickCount(), pEH->Proc); + + ExFreePoolWithTag(pEP, TAG_HOOK); return Result; } @@ -177,55 +219,66 @@ IntNotifyWinEvent( DWORD Event, PWND pWnd, LONG idObject, - LONG idChild) + LONG idChild, + DWORD flags) { PEVENTHOOK pEH; PLIST_ENTRY pLE; + PTHREADINFO pti, ptiCurrent; DPRINT("IntNotifyWinEvent GlobalEvents = 0x%x pWnd 0x%x\n",GlobalEvents, pWnd); - if (!pWnd) return; + if (!GlobalEvents || !GlobalEvents->Counts) return; if (pWnd && pWnd->state & WNDS_DESTROYED) return; - if (!GlobalEvents || !GlobalEvents->Counts) return; + ptiCurrent = PsGetCurrentThreadWin32Thread(); + + if (pWnd && flags & WEF_SETBYWNDPTI) + pti = pWnd->head.pti; + else + pti = ptiCurrent; pLE = GlobalEvents->Events.Flink; pEH = CONTAINING_RECORD(pLE, EVENTHOOK, Chain); do - { + { + if (!pEH) break; UserReferenceObject(pEH); // Must be inside the event window. if ( (pEH->eventMin <= Event) && (pEH->eventMax >= Event)) { - if (pEH->head.pti->pEThread != PsGetCurrentThread()) - { // if all process || all thread || other thread same process - if (!(pEH->idProcess) || !(pEH->idThread) || - (NtCurrentTeb()->ClientId.UniqueProcess == (PVOID)(DWORD_PTR)pEH->idProcess)) +// if all process || all thread || other thread same process +// if ^skip own thread && ((Pid && CPid == Pid && ^skip own process) || all process) + if ( (!pEH->idProcess || pEH->idProcess == PtrToUint(pti->pEThread->Cid.UniqueProcess)) && + (!(pEH->Flags & WINEVENT_SKIPOWNPROCESS) || pEH->head.pti->ppi != pti->ppi) && + (!pEH->idThread || pEH->idThread == PtrToUint(pti->pEThread->Cid.UniqueThread)) && + (!(pEH->Flags & WINEVENT_SKIPOWNTHREAD) || pEH->head.pti != pti) && + pEH->head.pti->rpdesk == ptiCurrent->rpdesk ) // Same as hooks. + { + // Send message to the thread if pEH is not current. + if (pEH->head.pti != ptiCurrent) { + DPRINT1("Global Event 0x%x, idObject %d\n", Event, idObject); IntCallLowLevelEvent( pEH, Event, UserHMGetHandle(pWnd), idObject, idChild); } - }// if ^skip own thread && ((Pid && CPid == Pid && ^skip own process) || all process) - else if ( !(pEH->Flags & WINEVENT_SKIPOWNTHREAD) && - ( ((pEH->idProcess && - NtCurrentTeb()->ClientId.UniqueProcess == (PVOID)(DWORD_PTR)pEH->idProcess) && - !(pEH->Flags & WINEVENT_SKIPOWNPROCESS)) || - !pEH->idProcess ) ) - { - // What in the deuce is this right-aligned formatting? - co_IntCallEventProc( UserHMGetHandle(pEH), - Event, - UserHMGetHandle(pWnd), - idObject, - idChild, - PtrToUint(NtCurrentTeb()->ClientId.UniqueThread), - (DWORD)EngGetTickCount(), - pEH->Proc); - } + else + { + DPRINT1("Local Event 0x%x, idObject %d\n", Event, idObject); + co_IntCallEventProc( UserHMGetHandle(pEH), + Event, + UserHMGetHandle(pWnd), + idObject, + idChild, + PtrToUint(NtCurrentTeb()->ClientId.UniqueThread), + (DWORD)EngGetTickCount(), + pEH->Proc); + } + } } UserDereferenceObject(pEH); pLE = pEH->Chain.Flink; @@ -255,7 +308,7 @@ NtUserNotifyWinEvent( if (gpsi->dwInstalledEventHooks & GetMaskFromEvent(Event)) { UserRefObjectCo(Window, &Ref); - IntNotifyWinEvent( Event, Window, idObject, idChild); + IntNotifyWinEvent( Event, Window, idObject, idChild, WEF_SETBYWNDPTI); UserDerefObjectCo(Window); } UserLeave(); @@ -322,7 +375,7 @@ NtUserSetWinEventHook( goto SetEventExit; } } - + // Creator, pti is set here. pEH = UserCreateObject(gHandleTable, NULL, &Handle, otEvent, sizeof(EVENTHOOK)); if (pEH) { @@ -330,16 +383,18 @@ NtUserSetWinEventHook( GlobalEvents->Counts++; UserHMGetHandle(pEH) = Handle; - if (Thread) - pEH->head.pti = Thread->Tcb.Win32Thread; - else - pEH->head.pti = GetW32ThreadInfo(); pEH->eventMin = eventMin; pEH->eventMax = eventMax; - pEH->idProcess = idProcess; - pEH->idThread = idThread; + pEH->idProcess = idProcess; // These are cmp'ed + pEH->idThread = idThread; // " pEH->Flags = dwflags; - + /* + If WINEVENT_INCONTEXT, set offset from hmod and proc. Save ihmod from + the atom index table where the hmod data is saved to be recalled later + if fSync set by WINEVENT_INCONTEXT. + If WINEVENT_OUTOFCONTEXT just use proc.. + Do this instead.... + */ if (NULL != hmodWinEventProc) { pEH->offPfn = (ULONG_PTR)((char *)lpfnWinEventProc - (char *)hmodWinEventProc); diff --git a/reactos/subsystems/win32/win32k/ntuser/focus.c b/reactos/subsystems/win32/win32k/ntuser/focus.c index 5832eaf41ad..414b1523bf7 100644 --- a/reactos/subsystems/win32/win32k/ntuser/focus.c +++ b/reactos/subsystems/win32/win32k/ntuser/focus.c @@ -165,6 +165,7 @@ co_IntSendKillFocusMessages(HWND hWndPrev, HWND hWnd) { if (hWndPrev) { + IntNotifyWinEvent(EVENT_OBJECT_FOCUS, NULL, OBJID_CLIENT, CHILDID_SELF, 0); co_IntPostOrSendMessage(hWndPrev, WM_KILLFOCUS, (WPARAM)hWnd, 0); } } @@ -174,6 +175,8 @@ co_IntSendSetFocusMessages(HWND hWndPrev, HWND hWnd) { if (hWnd) { + PWND pWnd = UserGetWindowObject(hWnd); + IntNotifyWinEvent(EVENT_OBJECT_FOCUS, pWnd, OBJID_CLIENT, CHILDID_SELF, 0); co_IntPostOrSendMessage(hWnd, WM_SETFOCUS, (WPARAM)hWndPrev, 0); } } @@ -356,8 +359,10 @@ co_IntSetActiveWindow(PWND Wnd OPTIONAL) cbt.fMouse = FALSE; cbt.hWndActive = hWndPrev; if (co_HOOK_CallHooks( WH_CBT, HCBT_ACTIVATE, (WPARAM)hWnd, (LPARAM)&cbt)) + { + DPRINT1("SetActiveWindow WH_CBT Call Hook return!\n"); return 0; - + } ThreadQueue->ActiveWindow = hWnd; co_IntSendDeactivateMessages(hWndPrev, hWnd); @@ -392,9 +397,11 @@ co_IntSetFocusWindow(PWND Window OPTIONAL) return hWndPrev; } - if (co_HOOK_CallHooks( WH_CBT, HCBT_SETFOCUS, (WPARAM)Window->head.h, (LPARAM)hWndPrev)) - return 0; - + if (co_HOOK_CallHooks( WH_CBT, HCBT_SETFOCUS, (WPARAM)Window->head.h, (LPARAM)hWndPrev)) + { + DPRINT1("SetFocusWindow 1 WH_CBT Call Hook return!\n"); + return 0; + } ThreadQueue->FocusWindow = Window->head.h; co_IntSendKillFocusMessages(hWndPrev, Window->head.h); @@ -403,9 +410,11 @@ co_IntSetFocusWindow(PWND Window OPTIONAL) else { ThreadQueue->FocusWindow = 0; - - if (co_HOOK_CallHooks( WH_CBT, HCBT_SETFOCUS, (WPARAM)0, (LPARAM)hWndPrev)) - return 0; + if (co_HOOK_CallHooks( WH_CBT, HCBT_SETFOCUS, (WPARAM)0, (LPARAM)hWndPrev)) + { + DPRINT1("SetFocusWindow 2 WH_CBT Call Hook return!\n"); + return 0; + } co_IntSendKillFocusMessages(hWndPrev, 0); } @@ -533,7 +542,7 @@ NtUserSetCapture(HWND hWnd) { PTHREADINFO pti; PUSER_MESSAGE_QUEUE ThreadQueue; - PWND Window; + PWND Window, pWnd; HWND hWndPrev; DECLARE_RETURN(HWND); @@ -553,13 +562,23 @@ NtUserSetCapture(HWND hWnd) hWndPrev = MsqSetStateWindow(ThreadQueue, MSQ_STATE_CAPTURE, hWnd); + if (hWndPrev) + { + pWnd = UserGetWindowObject(hWndPrev); + if (pWnd) + IntNotifyWinEvent(EVENT_SYSTEM_CAPTUREEND, pWnd, OBJID_WINDOW, CHILDID_SELF, WEF_SETBYWNDPTI); + } + /* also remove other windows if not capturing anymore */ - if(hWnd == NULL) + if (hWnd == NULL) { MsqSetStateWindow(ThreadQueue, MSQ_STATE_MENUOWNER, NULL); MsqSetStateWindow(ThreadQueue, MSQ_STATE_MOVESIZE, NULL); } + if (Window) + IntNotifyWinEvent(EVENT_SYSTEM_CAPTURESTART, Window, OBJID_WINDOW, CHILDID_SELF, WEF_SETBYWNDPTI); + co_IntPostOrSendMessage(hWndPrev, WM_CAPTURECHANGED, 0, (LPARAM)hWnd); ThreadQueue->CaptureWindow = hWnd; diff --git a/reactos/subsystems/win32/win32k/ntuser/hook.c b/reactos/subsystems/win32/win32k/ntuser/hook.c index 6b6df548973..d83c8c90c31 100644 --- a/reactos/subsystems/win32/win32k/ntuser/hook.c +++ b/reactos/subsystems/win32/win32k/ntuser/hook.c @@ -2,8 +2,10 @@ * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * PURPOSE: Window hooks - * FILE: subsystem/win32/win32k/ntuser/hook.c + * FILE: subsystems/win32/win32k/ntuser/hook.c * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * James Tabor (james.tabor@rectos.org) + * * REVISION HISTORY: * 06-06-2001 CSH Created * NOTE: Most of this code was adapted from Wine, @@ -15,474 +17,117 @@ #define NDEBUG #include -static PHOOKTABLE GlobalHooks; - - -/* PRIVATE FUNCTIONS *********************************************************/ - - -/* create a new hook table */ -static -PHOOKTABLE -IntAllocHookTable(void) -{ - PHOOKTABLE Table; - UINT i; - - Table = ExAllocatePoolWithTag(PagedPool, sizeof(HOOKTABLE), TAG_HOOK); - if (NULL != Table) - { - for (i = 0; i < NB_HOOKS; i++) - { - InitializeListHead(&Table->Hooks[i]); - Table->Counts[i] = 0; - } - } - - return Table; -} - - -PHOOK -FASTCALL -IntGetHookObject(HHOOK hHook) +typedef struct _HOOKPACK { - PHOOK Hook; - - if (!hHook) - { - SetLastWin32Error(ERROR_INVALID_HOOK_HANDLE); - return NULL; - } - - Hook = (PHOOK)UserGetObject(gHandleTable, hHook, otHook); - if (!Hook) - { - SetLastWin32Error(ERROR_INVALID_HOOK_HANDLE); - return NULL; - } - - ASSERT(Hook->head.cLockObj >= 0); - - Hook->head.cLockObj++; - - return Hook; -} - - - -/* create a new hook and add it to the specified table */ -static -PHOOK -IntAddHook(PETHREAD Thread, int HookId, BOOLEAN Global, PWINSTATION_OBJECT WinStaObj) -{ - PTHREADINFO W32Thread; - PHOOK Hook; - PHOOKTABLE Table = Global ? GlobalHooks : MsqGetHooks(((PTHREADINFO)Thread->Tcb.Win32Thread)->MessageQueue); - HANDLE Handle; - - if (NULL == Table) - { - Table = IntAllocHookTable(); - if (NULL == Table) - { - return NULL; - } - if (Global) - { - GlobalHooks = Table; - } - else - { - MsqSetHooks(((PTHREADINFO)Thread->Tcb.Win32Thread)->MessageQueue, Table); - } - } - - Hook = UserCreateObject(gHandleTable, NULL, &Handle, otHook, sizeof(HOOK)); - if (NULL == Hook) - { - return NULL; - } - - Hook->Thread = Thread; - Hook->HookId = HookId; - - if (Thread) - { - W32Thread = ((PTHREADINFO)Thread->Tcb.Win32Thread); - ASSERT(W32Thread != NULL); - W32Thread->fsHooks |= HOOKID_TO_FLAG(HookId); - - if (W32Thread->pClientInfo) - W32Thread->pClientInfo->fsHooks = W32Thread->fsHooks; - - if (W32Thread->pDeskInfo) // Do this for now. - W32Thread->pDeskInfo->fsHooks= W32Thread->fsHooks; + PHOOK pHk; + LPARAM lParam; +} HOOKPACK, *PHOOKPACK; - Hook->head.pti = W32Thread; - Hook->head.rpdesk = W32Thread->rpdesk; - } - - RtlInitUnicodeString(&Hook->ModuleName, NULL); - - InsertHeadList(&Table->Hooks[HOOKID_TO_INDEX(HookId)], &Hook->Chain); - - 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(((PTHREADINFO)Hook->Thread->Tcb.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; - - 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)); - } - - return Hook; -} - -/* find the next hook in the chain, skipping the deleted ones */ -PHOOK -FASTCALL -IntGetNextHook(PHOOK Hook) -{ - PHOOKTABLE Table = IntGetTable(Hook); - int HookId = Hook->HookId; - PLIST_ENTRY Elem; - - Elem = Hook->Chain.Flink; - while (Elem != &Table->Hooks[HOOKID_TO_INDEX(HookId)]) - { - Hook = CONTAINING_RECORD(Elem, HOOK, Chain); - if (NULL != Hook->Proc) - { - return Hook; - } - } - - if (NULL != GlobalHooks && Table != GlobalHooks) /* now search through the global table */ - { - return IntGetFirstValidHook(GlobalHooks, HookId); - } - - return NULL; -} +/* PRIVATE FUNCTIONS *********************************************************/ -/* free a hook, removing it from its chain */ static -VOID +LRESULT FASTCALL -IntFreeHook(PHOOKTABLE Table, PHOOK Hook, PWINSTATION_OBJECT WinStaObj) -{ - RemoveEntryList(&Hook->Chain); - RtlFreeUnicodeString(&Hook->ModuleName); - - /* Dereference thread if required */ - if (Hook->Flags & HOOK_THREAD_REFERENCED) - { - ObDereferenceObject(Hook->Thread); - } - - /* Close handle */ - UserDeleteObject(UserHMGetHandle(Hook), otHook); -} - -/* remove a hook, freeing it if the chain is not in use */ -static -VOID -IntRemoveHook(PHOOK Hook, PWINSTATION_OBJECT WinStaObj, BOOL TableAlreadyLocked) +IntCallLowLevelHook( PHOOK Hook, + INT Code, + WPARAM wParam, + LPARAM lParam) { - PTHREADINFO W32Thread; - PHOOKTABLE Table = IntGetTable(Hook); - - ASSERT(NULL != Table); // At this point this should not be null! - - W32Thread = ((PTHREADINFO)Hook->Thread->Tcb.Win32Thread); - ASSERT(W32Thread != NULL); - W32Thread->fsHooks &= ~HOOKID_TO_FLAG(Hook->HookId); - - GetWin32ClientInfo()->fsHooks = W32Thread->fsHooks; - - if (W32Thread->pDeskInfo) // Do this for now. - W32Thread->pDeskInfo->fsHooks= W32Thread->fsHooks; + NTSTATUS Status; + PTHREADINFO pti; + PHOOKPACK pHP; + ULONG_PTR uResult = 0; - if (0 != Table->Counts[HOOKID_TO_INDEX(Hook->HookId)]) - { - Hook->Proc = NULL; /* chain is in use, just mark it and return */ - } + if (Hook->Thread) + pti = Hook->Thread->Tcb.Win32Thread; else - { - IntFreeHook(Table, Hook, WinStaObj); - } -} + pti = Hook->head.pti; -/* 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; - } + pHP = ExAllocatePoolWithTag(NonPagedPool, sizeof(HOOKPACK), TAG_HOOK); + if (!pHP) return 0; - /* use count shouldn't already be 0 */ - ASSERT(0 != Table->Counts[HOOKID_TO_INDEX(HookId)]); - - if (0 == Table->Counts[HOOKID_TO_INDEX(HookId)]) - { - 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); - } - } - } -} - -static -LRESULT -FASTCALL -IntCallLowLevelHook(PHOOK Hook, INT Code, WPARAM wParam, LPARAM lParam) -{ - NTSTATUS Status; - ULONG_PTR uResult; + pHP->pHk = Hook; + pHP->lParam = lParam; /* FIXME should get timeout from * HKEY_CURRENT_USER\Control Panel\Desktop\LowLevelHooksTimeout */ - Status = co_MsqSendMessage(((PTHREADINFO)Hook->Thread->Tcb.Win32Thread)->MessageQueue, - IntToPtr(Code), - Hook->HookId, + Status = co_MsqSendMessage( pti->MessageQueue, + IntToPtr(Code), // hWnd + Hook->HookId, // Msg wParam, - lParam, + (LPARAM)pHP, 5000, TRUE, MSQ_ISHOOK, - &uResult); - - return NT_SUCCESS(Status) ? uResult : 0; -} - -/* - Called from inside kernel space. - */ -LRESULT -FASTCALL -co_HOOK_CallHooks(INT HookId, INT Code, WPARAM wParam, LPARAM lParam) -{ - PHOOK Hook, SaveHook; - PTHREADINFO pti; - PCLIENTINFO ClientInfo; - PHOOKTABLE Table; - LRESULT Result; - PWINSTATION_OBJECT WinStaObj; - NTSTATUS Status; - - ASSERT(WH_MINHOOK <= HookId && HookId <= WH_MAXHOOK); - -#if 0 - /* FIXME! Check pDeskInfo->fsHooks for global hooks! */ - if (!ISITHOOKED(HookId)) - { - return 0; - } -#endif - - pti = PsGetCurrentThreadWin32Thread(); - if (!pti) - { - Table = NULL; - } - else - { - Table = MsqGetHooks(pti->MessageQueue); - } - - 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()) && (Hook->Thread != NULL)) - { - DPRINT1("\nHook found by Id and posted to Thread! %d\n",HookId ); - /* Post it in message queue. */ - return IntCallLowLevelHook(Hook, Code, wParam, lParam); - } - - Table->Counts[HOOKID_TO_INDEX(HookId)]++; - if (Table != GlobalHooks && GlobalHooks != NULL) - { - GlobalHooks->Counts[HOOKID_TO_INDEX(HookId)]++; - } - - ClientInfo = GetWin32ClientInfo(); - SaveHook = ClientInfo->phkCurrent; - ClientInfo->phkCurrent = Hook; /* Load the call. */ - - Result = co_IntCallHookProc(HookId, - Code, - wParam, - lParam, - Hook->Proc, - Hook->Ansi, - &Hook->ModuleName); - - ClientInfo->phkCurrent = SaveHook; - - Status = IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation, - KernelMode, - 0, - &WinStaObj); - + &uResult); if (!NT_SUCCESS(Status)) { - DPRINT1("Invalid window station????\n"); - } - else - { - IntReleaseHookChain(MsqGetHooks(pti->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(PsGetCurrentProcess()->Win32WindowStation, - KernelMode, - 0, - &WinStaObj); - - if (!NT_SUCCESS(Status)) - { - DPRINT1("Invalid window station????\n"); - return; - } - - 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, TRUE); - } - } - break; - } - } + DPRINT1("Error Hook Call SendMsg. %d Status: 0x%x\n", Hook->HookId, Status); + ExFreePoolWithTag(pHP, TAG_HOOK); } + return NT_SUCCESS(Status) ? uResult : 0; } static LRESULT FASTCALL -co_HOOK_CallHookNext(PHOOK Hook, INT Code, WPARAM wParam, LPARAM lParam) +co_HOOK_CallHookNext( PHOOK Hook, + INT Code, + WPARAM wParam, + LPARAM lParam) { - if ((Hook->Thread != PsGetCurrentThread()) && (Hook->Thread != NULL)) + if ( (Hook->Thread != PsGetCurrentThread()) && (Hook->Thread != NULL) ) { - DPRINT1("CALLING HOOK from another Thread. %d\n", Hook->HookId); + DPRINT1("Calling Next HOOK from another Thread. %d\n", Hook->HookId); return IntCallLowLevelHook(Hook, Code, wParam, lParam); } - DPRINT("CALLING HOOK %d\n", Hook->HookId); + DPRINT("Calling Next HOOK %d\n", Hook->HookId); - return co_IntCallHookProc(Hook->HookId, - Code, - wParam, - lParam, - Hook->Proc, - Hook->Ansi, + return co_IntCallHookProc( Hook->HookId, + Code, + wParam, + lParam, + Hook->Proc, + Hook->Ansi, &Hook->ModuleName); } +// +// Dispatch MsgQueue Hook Call processor! +// +LRESULT +FASTCALL +co_CallHook( INT HookId, + INT Code, + WPARAM wParam, + LPARAM lParam) +{ + LRESULT Result; + PHOOK phk; + PHOOKPACK pHP = (PHOOKPACK)lParam; + + phk = pHP->pHk; + /* The odds are high for this to be a Global call. */ + Result = co_IntCallHookProc( HookId, + Code, + wParam, + pHP->lParam, + phk->Proc, + phk->Ansi, + &phk->ModuleName); + + ExFreePoolWithTag(pHP, TAG_HOOK); + return Result; +} LRESULT FASTCALL -IntCallDebugHook(PHOOK Hook, - int Code, - WPARAM wParam, - LPARAM lParam) +IntCallDebugHook( PHOOK Hook, + int Code, + WPARAM wParam, + LPARAM lParam, + BOOL Ansi) { LRESULT lResult = 0; ULONG Size; @@ -608,16 +253,13 @@ IntCallDebugHook(PHOOK Hook, return lResult; } -/* - Called from user space via CallNextHook. - */ LRESULT FASTCALL -UserCallNextHookEx(PHOOK Hook, - int Code, - WPARAM wParam, - LPARAM lParam, - BOOL Ansi) +UserCallNextHookEx( PHOOK Hook, + int Code, + WPARAM wParam, + LPARAM lParam, + BOOL Ansi) { LRESULT lResult = 0; BOOL BadChk = FALSE; @@ -1002,7 +644,7 @@ UserCallNextHookEx(PHOOK Hook, } case WH_DEBUG: - lResult = IntCallDebugHook(Hook, Code, wParam, lParam); + lResult = IntCallDebugHook(Hook, Code, wParam, lParam, Ansi); break; /* @@ -1018,70 +660,454 @@ UserCallNextHookEx(PHOOK Hook, DPRINT1("Unsupported HOOK Id -> %d\n",Hook->HookId); break; } - + if (Hook->HookId == WH_JOURNALPLAYBACK && lResult == 0) + lResult = -1; return lResult; } +PHOOK +FASTCALL +IntGetHookObject(HHOOK hHook) +{ + PHOOK Hook; + + if (!hHook) + { + SetLastWin32Error(ERROR_INVALID_HOOK_HANDLE); + return NULL; + } + + Hook = (PHOOK)UserGetObject(gHandleTable, hHook, otHook); + if (!Hook) + { + SetLastWin32Error(ERROR_INVALID_HOOK_HANDLE); + return NULL; + } + + UserReferenceObject(Hook); + + return Hook; +} + +/* get the first hook in the chain */ +static +PHOOK +FASTCALL +IntGetFirstHook(PLIST_ENTRY Table) +{ + PLIST_ENTRY Elem = Table->Flink; + + if (IsListEmpty(Table)) return NULL; + + return Elem == Table ? NULL : CONTAINING_RECORD(Elem, HOOK, Chain); +} + +/* find the next hook in the chain */ +PHOOK +FASTCALL +IntGetNextHook(PHOOK Hook) +{ + int HookId = Hook->HookId; + PLIST_ENTRY Elem; + PTHREADINFO pti; + + if (Hook->Thread) + { + pti = ((PTHREADINFO)Hook->Thread->Tcb.Win32Thread); + + Elem = Hook->Chain.Flink; + if (Elem != &pti->aphkStart[HOOKID_TO_INDEX(HookId)]) + return CONTAINING_RECORD(Elem, HOOK, Chain); + } + else + { + pti = PsGetCurrentThreadWin32Thread(); + + Elem = Hook->Chain.Flink; + if (Elem != &pti->pDeskInfo->aphkStart[HOOKID_TO_INDEX(HookId)]) + return CONTAINING_RECORD(Elem, HOOK, Chain); + } + return NULL; +} + +/* free a hook, removing it from its chain */ +static +VOID +FASTCALL +IntFreeHook(PHOOK Hook) +{ + RemoveEntryList(&Hook->Chain); + if (Hook->ModuleName.Buffer) + { + ExFreePoolWithTag(Hook->ModuleName.Buffer, TAG_HOOK); + Hook->ModuleName.Buffer = NULL; + } + /* Close handle */ + UserDeleteObject(UserHMGetHandle(Hook), otHook); +} + +/* remove a hook, freeing it from the chain */ +static +BOOL +FASTCALL +IntRemoveHook(PHOOK Hook) +{ + INT HookId; + PTHREADINFO pti; + + HookId = Hook->HookId; + + if (Hook->Thread) // Local + { + pti = ((PTHREADINFO)Hook->Thread->Tcb.Win32Thread); + + IntFreeHook( Hook); + + if ( IsListEmpty(&pti->aphkStart[HOOKID_TO_INDEX(HookId)]) ) + { + pti->fsHooks &= ~HOOKID_TO_FLAG(HookId); + _SEH2_TRY + { + GetWin32ClientInfo()->fsHooks = pti->fsHooks; + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + } + _SEH2_END; + return TRUE; + } + } + else // Global + { + IntFreeHook( Hook); + + pti = PsGetCurrentThreadWin32Thread(); + + if ( pti->pDeskInfo && + IsListEmpty(&pti->pDeskInfo->aphkStart[HOOKID_TO_INDEX(HookId)]) ) + { + pti->pDeskInfo->fsHooks &= ~HOOKID_TO_FLAG(HookId); + return TRUE; + } + } + return FALSE; +} + +VOID +FASTCALL +HOOK_DestroyThreadHooks(PETHREAD Thread) +{ + PTHREADINFO pti; + int HookId; + PHOOK HookObj; + PLIST_ENTRY pElem; + + pti = Thread->Tcb.Win32Thread; + if (!pti || !pti->pDeskInfo) return; + +// Local Thread cleanup. + if (pti->fsHooks) + { + for (HookId = WH_MINHOOK; HookId <= WH_MAXHOOK; HookId++) + { + PLIST_ENTRY pLLE = &pti->aphkStart[HOOKID_TO_INDEX(HookId)]; + + if (IsListEmpty(pLLE)) continue; + + pElem = pLLE->Flink; + HookObj = CONTAINING_RECORD(pElem, HOOK, Chain); + do + { + if (!HookObj) break; + if (IntRemoveHook(HookObj)) break; + pElem = HookObj->Chain.Flink; + HookObj = CONTAINING_RECORD(pElem, HOOK, Chain); + } + while (pElem != pLLE); + } + pti->fsHooks = 0; + } +// Global search based on Thread and cleanup. + if (pti->pDeskInfo->fsHooks) + { + for (HookId = WH_MINHOOK; HookId <= WH_MAXHOOK; HookId++) + { + PLIST_ENTRY pGLE = &pti->pDeskInfo->aphkStart[HOOKID_TO_INDEX(HookId)]; + + if (IsListEmpty(pGLE)) continue; + + pElem = pGLE->Flink; + HookObj = CONTAINING_RECORD(pElem, HOOK, Chain); + do + { + if (!HookObj) break; + if (HookObj->head.pti == pti) + { + if (IntRemoveHook(HookObj)) break; + } + pElem = HookObj->Chain.Flink; + HookObj = CONTAINING_RECORD(pElem, HOOK, Chain); + } + while (pElem != pGLE); + } + } + return; +} + +/* + Win32k Kernel Space Hook Caller. + */ LRESULT -APIENTRY -NtUserCallNextHookEx(int Code, - WPARAM wParam, - LPARAM lParam, - BOOL Ansi) +FASTCALL +co_HOOK_CallHooks( INT HookId, + INT Code, + WPARAM wParam, + LPARAM lParam) { - PHOOK HookObj, NextObj; + PHOOK Hook, SaveHook; + PTHREADINFO pti; PCLIENTINFO ClientInfo; - PWINSTATION_OBJECT WinStaObj; - NTSTATUS Status; - DECLARE_RETURN(LRESULT); + PLIST_ENTRY pLLE, pGLE; + BOOL Local = FALSE, Global = FALSE; + LRESULT Result = 0; - DPRINT("Enter NtUserCallNextHookEx\n"); - UserEnterExclusive(); + ASSERT(WH_MINHOOK <= HookId && HookId <= WH_MAXHOOK); - Status = IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation, - KernelMode, - 0, - &WinStaObj); - if (!NT_SUCCESS(Status)) + pti = GetW32ThreadInfo(); // Need to call this! + + if (!pti || !pti->pDeskInfo) + goto Exit; // Must have a desktop running for hooks. + + if ( pti->TIF_flags & TIF_INCLEANUP) + goto Exit; + + if ( ISITHOOKED(HookId) ) { - SetLastNtError(Status); - RETURN( 0); + DPRINT("Local Hooker %d\n", HookId); + Local = TRUE; } - ObDereferenceObject(WinStaObj); + if ( pti->pDeskInfo->fsHooks & HOOKID_TO_FLAG(HookId) ) + { + DPRINT("Global Hooker %d\n", HookId); + Global = TRUE; + } - ClientInfo = GetWin32ClientInfo(); + if ( !Local && !Global ) goto Exit; // No work! - if (!ClientInfo) RETURN( 0); + pLLE = &pti->aphkStart[HOOKID_TO_INDEX(HookId)]; + pGLE = &pti->pDeskInfo->aphkStart[HOOKID_TO_INDEX(HookId)]; + Hook = NULL; - HookObj = ClientInfo->phkCurrent; + /* SetWindowHookEx sorts out the Thread issue by placing the Hook to + the correct Thread if not NULL. + */ + if ( Local ) + { + Hook = IntGetFirstHook(pLLE); + if (!Hook) + { + DPRINT1("No Local Hook Found!\n"); + goto Exit; + } + ObReferenceObject(Hook->Thread); + + ClientInfo = pti->pClientInfo; + SaveHook = pti->sphkCurrent; + + /* Load it for the next call. */ + pti->sphkCurrent = Hook; + Hook->phkNext = IntGetNextHook(Hook); + if (ClientInfo) + { + _SEH2_TRY + { + ClientInfo->phkCurrent = Hook; + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + ClientInfo = NULL; // Don't bother next run. + } + _SEH2_END; + } + Result = co_IntCallHookProc( HookId, + Code, + wParam, + lParam, + Hook->Proc, + Hook->Ansi, + &Hook->ModuleName); + if (ClientInfo) + { + _SEH2_TRY + { + ClientInfo->phkCurrent = SaveHook; + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + } + _SEH2_END; + } + pti->sphkCurrent = SaveHook; + Hook->phkNext = NULL; + ObDereferenceObject(Hook->Thread); + } - if (!HookObj) RETURN( 0); + if ( Global ) + { + PTHREADINFO ptiHook; + + Hook = IntGetFirstHook(pGLE); + if (!Hook) + { + DPRINT1("No Global Hook Found!\n"); + goto Exit; + } + /* Performance goes down the drain. If more hooks are associated to this + * hook ID, this will have to post to each of the thread message queues + * or make a direct call. + */ + do + { + /* Hook->Thread is null, we hax around this with Hook->head.pti. */ + ptiHook = Hook->head.pti; + + /* "Global hook monitors messages for all threads in the same desktop + * as the calling thread." + */ + if ( ptiHook->TIF_flags & TIF_INCLEANUP || + ptiHook->rpdesk != pti->rpdesk) + { + Hook = IntGetNextHook(Hook); + if (!Hook) break; + continue; + } + // Lockup the thread while this links through user world. + ObReferenceObject(ptiHook->pEThread); + if (ptiHook != pti ) + { + DPRINT("\nGlobal Hook posting to another Thread! %d\n",HookId ); + Result = IntCallLowLevelHook(Hook, Code, wParam, lParam); + } + else + { /* Make the direct call. */ + Result = co_IntCallHookProc( HookId, + Code, + wParam, + lParam, + Hook->Proc, + Hook->Ansi, + &Hook->ModuleName); + } + ObDereferenceObject(ptiHook->pEThread); + Hook = IntGetNextHook(Hook); + } + while ( Hook ); + DPRINT("Ret: Global HookId %d Result 0x%x\n", HookId,Result); + } +Exit: + if (HookId == WH_JOURNALPLAYBACK && Result == 0) + Result = -1; + return Result; +} + +BOOL +FASTCALL +IntUnhookWindowsHook(int HookId, HOOKPROC pfnFilterProc) +{ + PHOOK Hook; + PLIST_ENTRY pLLE, pLE; + PTHREADINFO pti = PsGetCurrentThreadWin32Thread(); + + if (HookId < WH_MINHOOK || WH_MAXHOOK < HookId ) + { + SetLastWin32Error(ERROR_INVALID_HOOK_FILTER); + return FALSE; + } + + if (pti->fsHooks) + { + pLLE = &pti->aphkStart[HOOKID_TO_INDEX(HookId)]; + + if (IsListEmpty(pLLE)) return FALSE; + + pLE = pLLE->Flink; + Hook = CONTAINING_RECORD(pLE, HOOK, Chain); + do + { + if (!Hook) break; + if (Hook->Proc == pfnFilterProc) + { + if (Hook->head.pti == pti) + { + IntRemoveHook(Hook); + UserDereferenceObject(Hook); + return TRUE; + } + else + { + SetLastWin32Error(ERROR_ACCESS_DENIED); + return FALSE; + } + } + pLE = Hook->Chain.Flink; + Hook = CONTAINING_RECORD(pLE, HOOK, Chain); + } + while (pLE != pLLE); + } + return FALSE; +} - /* Check that the first hook in the chain is not this hook */ - NextObj = IntGetFirstHook(IntGetTable(HookObj), HookObj->HookId); +/* + * Support for compatibility only? Global hooks are processed in kernel space. + * This is very thread specific! Never seeing applications with more than one + * hook per thread installed. Most of the applications are Global hookers and + * associated with just one hook Id. Maybe it's for diagnostic testing or a + * throw back to 3.11? + */ +LRESULT +APIENTRY +NtUserCallNextHookEx( int Code, + WPARAM wParam, + LPARAM lParam, + BOOL Ansi) +{ + PTHREADINFO pti; + PHOOK HookObj, NextObj; + PCLIENTINFO ClientInfo; + LRESULT lResult = 0; + DECLARE_RETURN(LRESULT); - /* Its the same so it has already been called */ - if (HookObj == NextObj) RETURN(0); + DPRINT("Enter NtUserCallNextHookEx\n"); + UserEnterExclusive(); - UserReferenceObject(HookObj); + pti = GetW32ThreadInfo(); - Ansi = HookObj->Ansi; + HookObj = pti->sphkCurrent; - if (NULL != HookObj->Thread && (HookObj->Thread != PsGetCurrentThread())) + if (!HookObj) RETURN( 0); + + NextObj = HookObj->phkNext; + + pti->sphkCurrent = NextObj; + ClientInfo = pti->pClientInfo; + _SEH2_TRY { - DPRINT1("Thread mismatch\n"); - UserDereferenceObject(HookObj); - SetLastWin32Error(ERROR_INVALID_HANDLE); - RETURN( 0); + ClientInfo->phkCurrent = NextObj; } - - NextObj = IntGetNextHook(HookObj); - ClientInfo->phkCurrent = NextObj; /* Preset next hook from list. */ - UserCallNextHookEx( HookObj, Code, wParam, lParam, Ansi); - UserDereferenceObject(HookObj); + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + ClientInfo = NULL; + } + _SEH2_END; - RETURN( (LRESULT)NextObj); + /* Now in List run down. */ + if (ClientInfo && NextObj) + { + NextObj->phkNext = IntGetNextHook(NextObj); + lResult = UserCallNextHookEx( NextObj, Code, wParam, lParam, NextObj->Ansi); + } + RETURN( lResult); CLEANUP: DPRINT("Leave NtUserCallNextHookEx, ret=%i\n",_ret_); @@ -1091,43 +1117,51 @@ CLEANUP: HHOOK APIENTRY -NtUserSetWindowsHookAW(int idHook, - HOOKPROC lpfn, - BOOL Ansi) +NtUserSetWindowsHookAW( int idHook, + HOOKPROC lpfn, + BOOL Ansi) { + DWORD ThreadId; UNICODE_STRING USModuleName; RtlInitUnicodeString(&USModuleName, NULL); - - return NtUserSetWindowsHookEx(NULL, &USModuleName, 0, idHook, lpfn, Ansi); + ThreadId = PtrToUint(NtCurrentTeb()->ClientId.UniqueThread); + + return NtUserSetWindowsHookEx( NULL, + &USModuleName, + ThreadId, + idHook, + lpfn, + Ansi); } HHOOK APIENTRY -NtUserSetWindowsHookEx(HINSTANCE Mod, - PUNICODE_STRING UnsafeModuleName, - DWORD ThreadId, - int HookId, - HOOKPROC HookProc, - BOOL Ansi) +NtUserSetWindowsHookEx( HINSTANCE Mod, + PUNICODE_STRING UnsafeModuleName, + DWORD ThreadId, + int HookId, + HOOKPROC HookProc, + BOOL Ansi) { PWINSTATION_OBJECT WinStaObj; - PCLIENTINFO ClientInfo; - BOOLEAN Global; - PETHREAD Thread; PHOOK Hook; UNICODE_STRING ModuleName; NTSTATUS Status; HHOOK Handle; - BOOLEAN ThreadReferenced = FALSE; + PETHREAD Thread = NULL; + PTHREADINFO ptiCurrent, pti = NULL; + BOOL Hit = FALSE; DECLARE_RETURN(HHOOK); DPRINT("Enter NtUserSetWindowsHookEx\n"); UserEnterExclusive(); + ptiCurrent = GetW32ThreadInfo(); + if (HookId < WH_MINHOOK || WH_MAXHOOK < HookId ) { - SetLastWin32Error(ERROR_INVALID_PARAMETER); + SetLastWin32Error(ERROR_INVALID_HOOK_FILTER); RETURN( NULL); } @@ -1137,173 +1171,211 @@ NtUserSetWindowsHookEx(HINSTANCE Mod, RETURN( NULL); } - ClientInfo = GetWin32ClientInfo(); - if (ThreadId) /* thread-local hook */ { - if (HookId == WH_JOURNALRECORD || + 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((HANDLE)(DWORD_PTR) ThreadId, &Thread))) - { - DPRINT1("Invalid thread id 0x%x\n", ThreadId); - SetLastWin32Error(ERROR_INVALID_PARAMETER); - RETURN( NULL); - } - - /* Thread was referenced */ - ThreadReferenced = TRUE; - if (Thread->ThreadsProcess != PsGetCurrentProcess()) - { - ObDereferenceObject(Thread); - DPRINT1("Can't specify thread belonging to another process\n"); - SetLastWin32Error(ERROR_INVALID_PARAMETER); - RETURN( NULL); - } + { + /* these can only be global */ + SetLastWin32Error(ERROR_GLOBAL_ONLY_HOOK); + RETURN( NULL); + } + + if (!NT_SUCCESS(PsLookupThreadByThreadId((HANDLE)(DWORD_PTR) ThreadId, &Thread))) + { + DPRINT1("Invalid thread id 0x%x\n", ThreadId); + SetLastWin32Error(ERROR_INVALID_PARAMETER); + RETURN( NULL); + } + + pti = Thread->Tcb.Win32Thread; + + ObDereferenceObject(Thread); + + if ( pti->rpdesk != ptiCurrent->rpdesk) // gptiCurrent->rpdesk) + { + SetLastWin32Error(ERROR_ACCESS_DENIED); + RETURN( NULL); + } + + if (Thread->ThreadsProcess != PsGetCurrentProcess()) + { + if ( !Mod && + (HookId == WH_GETMESSAGE || + HookId == WH_CALLWNDPROC || + HookId == WH_CBT || + HookId == WH_HARDWARE || + HookId == WH_DEBUG || + HookId == WH_SHELL || + HookId == WH_FOREGROUNDIDLE || + HookId == WH_CALLWNDPROCRET) ) + { + SetLastWin32Error(ERROR_HOOK_NEEDS_HMOD); + RETURN( NULL); + } + + if ( (pti->TIF_flags & (TIF_CSRSSTHREAD|TIF_SYSTEMTHREAD)) && + (HookId == WH_GETMESSAGE || + HookId == WH_CALLWNDPROC || + HookId == WH_CBT || + HookId == WH_HARDWARE || + HookId == WH_DEBUG || + HookId == WH_SHELL || + HookId == WH_FOREGROUNDIDLE || + HookId == WH_CALLWNDPROCRET) ) + { + SetLastWin32Error(ERROR_HOOK_TYPE_NOT_ALLOWED); + RETURN( NULL); + } + } } else /* system-global hook */ { - if (HookId == WH_KEYBOARD_LL || HookId == WH_MOUSE_LL) - { - Mod = NULL; - Thread = PsGetCurrentThread(); - - Status = ObReferenceObjectByPointer(Thread, - THREAD_ALL_ACCESS, - PsThreadType, - KernelMode); - - if (!NT_SUCCESS(Status)) - { - SetLastNtError(Status); - RETURN( (HANDLE) NULL); - } - - /* Thread was referenced */ - ThreadReferenced = TRUE; - } - else if (NULL == Mod) - { - SetLastWin32Error(ERROR_HOOK_NEEDS_HMOD); - RETURN( NULL); - } - else - { - Thread = NULL; - } - Global = TRUE; + pti = ptiCurrent; // gptiCurrent; + if ( !Mod && + (HookId == WH_GETMESSAGE || + HookId == WH_CALLWNDPROC || + HookId == WH_CBT || + HookId == WH_SYSMSGFILTER || + HookId == WH_HARDWARE || + HookId == WH_DEBUG || + HookId == WH_SHELL || + HookId == WH_FOREGROUNDIDLE || + HookId == WH_CALLWNDPROCRET) ) + { + SetLastWin32Error(ERROR_HOOK_NEEDS_HMOD); + RETURN( NULL); + } } - if ((Global && (HookId != WH_KEYBOARD_LL && HookId != WH_MOUSE_LL)) || - WH_DEBUG == HookId || - WH_JOURNALPLAYBACK == HookId || - WH_JOURNALRECORD == HookId) - { -#if 0 /* Removed to get winEmbed working again */ - UNIMPLEMENTED -#else - DPRINT1("Not implemented: HookId %d Global %s\n", HookId, Global ? "TRUE" : "FALSE"); -#endif - - /* Dereference thread if needed */ - if (ThreadReferenced) ObDereferenceObject(Thread); - SetLastWin32Error(ERROR_NOT_SUPPORTED); - RETURN( NULL); - } - - Status = IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation, - KernelMode, - 0, + Status = IntValidateWindowStationHandle( PsGetCurrentProcess()->Win32WindowStation, + KernelMode, + 0, &WinStaObj); if (!NT_SUCCESS(Status)) { - /* Dereference thread if needed */ - if (ThreadReferenced) ObDereferenceObject(Thread); - SetLastNtError(Status); - RETURN( (HANDLE) NULL); + SetLastNtError(Status); + RETURN( NULL); } + ObDereferenceObject(WinStaObj); - Hook = IntAddHook(Thread, HookId, Global, WinStaObj); - if (NULL == Hook) + Hook = UserCreateObject(gHandleTable, NULL, &Handle, otHook, sizeof(HOOK)); + + if (!Hook) { - /* Dereference thread if needed */ - if (ThreadReferenced) ObDereferenceObject(Thread); - ObDereferenceObject(WinStaObj); - RETURN( NULL); + RETURN( NULL); } - /* Let IntFreeHook now that this thread needs a dereference */ - if (ThreadReferenced) + Hook->ihmod = (INT)Mod; // Module Index from atom table, Do this for now. + Hook->Thread = Thread; /* Set Thread, Null is Global. */ + Hook->HookId = HookId; + Hook->rpdesk = pti->rpdesk; + Hook->phkNext = NULL; /* Dont use as a chain! Use link lists for chaining. */ + Hook->Proc = HookProc; + Hook->Ansi = Ansi; + + if (ThreadId) /* thread-local hook */ { - Hook->Flags |= HOOK_THREAD_REFERENCED; + InsertHeadList(&pti->aphkStart[HOOKID_TO_INDEX(HookId)], &Hook->Chain); + pti->sphkCurrent = NULL; + Hook->ptiHooked = pti; + pti->fsHooks |= HOOKID_TO_FLAG(HookId); + + if (pti->pClientInfo) + { + if ( pti->ppi == ptiCurrent->ppi) /* gptiCurrent->ppi) */ + { + _SEH2_TRY + { + pti->pClientInfo->fsHooks = pti->fsHooks; + pti->pClientInfo->phkCurrent = 0; + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + Hit = TRUE; + } + _SEH2_END; + if (Hit) + { + DPRINT1("Problem writing to Local ClientInfo!\n"); + } + } + else + { + KeAttachProcess(&pti->ppi->peProcess->Pcb); + _SEH2_TRY + { + pti->pClientInfo->fsHooks = pti->fsHooks; + pti->pClientInfo->phkCurrent = 0; + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + Hit = TRUE; + } + _SEH2_END; + KeDetachProcess(); + if (Hit) + { + DPRINT1("Problem writing to Remote ClientInfo!\n"); + } + } + } } - - if (NULL != Mod) + else { - Status = MmCopyFromCaller(&ModuleName, UnsafeModuleName, sizeof(UNICODE_STRING)); - if (!NT_SUCCESS(Status)) - { - UserDereferenceObject(Hook); - IntRemoveHook(Hook, WinStaObj, FALSE); - ObDereferenceObject(WinStaObj); - SetLastNtError(Status); - RETURN( NULL); - } + InsertHeadList(&pti->pDeskInfo->aphkStart[HOOKID_TO_INDEX(HookId)], &Hook->Chain); + Hook->ptiHooked = NULL; + //gptiCurrent->pDeskInfo->fsHooks |= HOOKID_TO_FLAG(HookId); + pti->pDeskInfo->fsHooks |= HOOKID_TO_FLAG(HookId); + } - Hook->ModuleName.Buffer = ExAllocatePoolWithTag(PagedPool, + RtlInitUnicodeString(&Hook->ModuleName, NULL); + + if (Mod) + { + Status = MmCopyFromCaller(&ModuleName, + UnsafeModuleName, + sizeof(UNICODE_STRING)); + if (!NT_SUCCESS(Status)) + { + IntRemoveHook(Hook); + SetLastNtError(Status); + RETURN( NULL); + } + + Hook->ModuleName.Buffer = ExAllocatePoolWithTag( PagedPool, ModuleName.MaximumLength, TAG_HOOK); - if (NULL == Hook->ModuleName.Buffer) - { - UserDereferenceObject(Hook); - IntRemoveHook(Hook, WinStaObj, FALSE); - ObDereferenceObject(WinStaObj); - SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); - RETURN( NULL); - } - - Hook->ModuleName.MaximumLength = ModuleName.MaximumLength; - Status = MmCopyFromCaller(Hook->ModuleName.Buffer, + if (NULL == Hook->ModuleName.Buffer) + { + IntRemoveHook(Hook); + 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)) - { - ExFreePoolWithTag(Hook->ModuleName.Buffer, TAG_HOOK); - UserDereferenceObject(Hook); - IntRemoveHook(Hook, WinStaObj, FALSE); - ObDereferenceObject(WinStaObj); - SetLastNtError(Status); - RETURN( NULL); - } - - Hook->ModuleName.Length = ModuleName.Length; - /* make proc relative to the module base */ - Hook->Proc = (void *)((char *)HookProc - (char *)Mod); + if (!NT_SUCCESS(Status)) + { + ExFreePoolWithTag(Hook->ModuleName.Buffer, TAG_HOOK); + Hook->ModuleName.Buffer = NULL; + IntRemoveHook(Hook); + SetLastNtError(Status); + RETURN( NULL); + } + + Hook->ModuleName.Length = ModuleName.Length; + /* make proc relative to the module base */ + Hook->offPfn = (ULONG_PTR)((char *)HookProc - (char *)Mod); } else - Hook->Proc = HookProc; - - Hook->Ansi = Ansi; - Handle = UserHMGetHandle(Hook); - - /* Clear the client threads next hook. */ - ClientInfo->phkCurrent = 0; - - UserDereferenceObject(Hook); - - ObDereferenceObject(WinStaObj); + Hook->offPfn = 0; RETURN( Handle); @@ -1313,46 +1385,28 @@ CLEANUP: END_CLEANUP; } - BOOL APIENTRY NtUserUnhookWindowsHookEx(HHOOK Hook) { - PWINSTATION_OBJECT WinStaObj; PHOOK HookObj; - NTSTATUS Status; DECLARE_RETURN(BOOL); DPRINT("Enter NtUserUnhookWindowsHookEx\n"); UserEnterExclusive(); - Status = IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation, - KernelMode, - 0, - &WinStaObj); - - if (!NT_SUCCESS(Status)) - { - SetLastNtError(Status); - RETURN( FALSE); - } - - /* Status = UserReferenceObjectByHandle(gHandleTable, Hook, - otHookProc, (PVOID *) &HookObj); */ if (!(HookObj = IntGetHookObject(Hook))) { DPRINT1("Invalid handle passed to NtUserUnhookWindowsHookEx\n"); - ObDereferenceObject(WinStaObj); /* SetLastNtError(Status); */ RETURN( FALSE); } ASSERT(Hook == UserHMGetHandle(HookObj)); - IntRemoveHook(HookObj, WinStaObj, FALSE); + IntRemoveHook(HookObj); UserDereferenceObject(HookObj); - ObDereferenceObject(WinStaObj); RETURN( TRUE); diff --git a/reactos/subsystems/win32/win32k/ntuser/message.c b/reactos/subsystems/win32/win32k/ntuser/message.c index 403e02b84ce..4078d8a8b6c 100644 --- a/reactos/subsystems/win32/win32k/ntuser/message.c +++ b/reactos/subsystems/win32/win32k/ntuser/message.c @@ -368,9 +368,10 @@ IntDispatchMessage(PMSG pMsg) { LARGE_INTEGER TickCount; LONG Time; - LRESULT retval; + LRESULT retval = 0; PMSGMEMORY MsgMemoryEntry; INT lParamBufferSize; + PTHREADINFO pti; LPARAM lParamPacked; PWND Window = NULL; @@ -380,25 +381,29 @@ IntDispatchMessage(PMSG pMsg) if (!Window) return 0; } + pti = PsGetCurrentThreadWin32Thread(); + if (((pMsg->message == WM_SYSTIMER) || (pMsg->message == WM_TIMER)) && (pMsg->lParam) ) { if (pMsg->message == WM_TIMER) { - if (ValidateTimerCallback(PsGetCurrentThreadWin32Thread(),pMsg->lParam)) + ObReferenceObject(pti->pEThread); + if (ValidateTimerCallback(pti,pMsg->lParam)) { KeQueryTickCount(&TickCount); Time = MsqCalculateMessageTime(&TickCount); - return co_IntCallWindowProc((WNDPROC)pMsg->lParam, - TRUE, - pMsg->hwnd, - WM_TIMER, - pMsg->wParam, - (LPARAM)Time, - sizeof(LPARAM)); + retval = co_IntCallWindowProc((WNDPROC)pMsg->lParam, + TRUE, + pMsg->hwnd, + WM_TIMER, + pMsg->wParam, + (LPARAM)Time, + sizeof(LPARAM)); } - return 0; + ObDereferenceObject(pti->pEThread); + return retval; } else { @@ -431,7 +436,7 @@ IntDispatchMessage(PMSG pMsg) DPRINT1("Failed to pack message parameters\n"); return 0; } - + ObReferenceObject(pti->pEThread); retval = co_IntCallWindowProc( Window->lpfnWndProc, !Window->Unicode, pMsg->hwnd, @@ -452,6 +457,7 @@ IntDispatchMessage(PMSG pMsg) co_UserGetUpdateRgn( Window, hrgn, TRUE ); REGION_FreeRgnByHandle( hrgn ); } + ObDereferenceObject(pti->pEThread); return retval; } @@ -784,6 +790,7 @@ BOOL ProcessMouseMessage(MSG* Msg, BOOLEAN RemoveMessages) HCBT_CLICKSKIPPED, Msg->message, (LPARAM)&MHook); + DPRINT1("MouseMessage WH_CBT Call Hook return!\n"); return FALSE; } @@ -812,6 +819,7 @@ BOOL ProcessKeyboardMessage(MSG* Msg, BOOLEAN RemoveMessages) HCBT_KEYSKIPPED, LOWORD(Msg->wParam), Msg->lParam ); + DPRINT1("KeyboardMessage WH_CBT Call Hook return!\n"); return FALSE; } return TRUE; @@ -1322,13 +1330,13 @@ co_IntSendMessageTimeoutSingle( HWND hWnd, UINT uTimeout, ULONG_PTR *uResult ) { - ULONG_PTR Result; NTSTATUS Status; PWND Window = NULL; PMSGMEMORY MsgMemoryEntry; INT lParamBufferSize; LPARAM lParamPacked; PTHREADINFO Win32Thread; + ULONG_PTR Result = 0; DECLARE_RETURN(LRESULT); USER_REFERENCE_ENTRY Ref; @@ -1369,6 +1377,7 @@ co_IntSendMessageTimeoutSingle( HWND hWnd, RETURN( FALSE); } + ObReferenceObject(Win32Thread->pEThread); Result = (ULONG_PTR)co_IntCallWindowProc( Window->lpfnWndProc, !Window->Unicode, hWnd, @@ -1381,6 +1390,8 @@ co_IntSendMessageTimeoutSingle( HWND hWnd, *uResult = Result; } + ObDereferenceObject(Win32Thread->pEThread); + IntCallWndProcRet( Window, hWnd, Msg, wParam, lParam, (LRESULT *)uResult); if (! NT_SUCCESS(UnpackParam(lParamPacked, Msg, wParam, lParam, FALSE))) @@ -1408,14 +1419,14 @@ co_IntSendMessageTimeoutSingle( HWND hWnd, do { Status = co_MsqSendMessage( Window->head.pti->MessageQueue, - hWnd, - Msg, - wParam, - lParam, - uTimeout, - (uFlags & SMTO_BLOCK), - MSQ_NORMAL, - uResult ); + hWnd, + Msg, + wParam, + lParam, + uTimeout, + (uFlags & SMTO_BLOCK), + MSQ_NORMAL, + uResult ); } while ((STATUS_TIMEOUT == Status) && (uFlags & SMTO_NOTIMEOUTIFNOTHUNG) && @@ -1575,7 +1586,7 @@ co_IntSendMessageWithCallBack( HWND hWnd, /* If this is not a callback and it can be sent now, then send it. */ if ((Window->head.pti->MessageQueue == Win32Thread->MessageQueue) && (CompletionCallback == NULL)) { - + ObReferenceObject(Win32Thread->pEThread); Result = (ULONG_PTR)co_IntCallWindowProc( Window->lpfnWndProc, !Window->Unicode, hWnd, @@ -1587,6 +1598,7 @@ co_IntSendMessageWithCallBack( HWND hWnd, { *uResult = Result; } + ObDereferenceObject(Win32Thread->pEThread); } IntCallWndProcRet( Window, hWnd, Msg, wParam, lParam, (LRESULT *)uResult); @@ -2553,12 +2565,13 @@ NtUserMessageCall( 2000, &RetVal); } + Ret = RetVal; } else if (parm.flags & BSF_POSTMESSAGE) { Ret = UserPostMessage(HWND_BROADCAST, Msg, wParam, lParam); } - else if ( parm.flags & BSF_SENDNOTIFYMESSAGE) + else //Everything else,,,, if ( parm.flags & BSF_SENDNOTIFYMESSAGE) { Ret = UserSendNotifyMessage(HWND_BROADCAST, Msg, wParam, lParam); } @@ -2584,21 +2597,31 @@ NtUserMessageCall( case FNID_CALLWNDPROC: case FNID_CALLWNDPROCRET: { - PCLIENTINFO ClientInfo = GetWin32ClientInfo(); - PHOOK NextObj, Hook = ClientInfo->phkCurrent; + PTHREADINFO pti; + PCLIENTINFO ClientInfo; + PHOOK NextObj, Hook; + + pti = GetW32ThreadInfo(); - if (!ClientInfo || !Hook) break; + Hook = pti->sphkCurrent; - UserReferenceObject(Hook); + if (!Hook) break; - if (Hook->Thread && (Hook->Thread != PsGetCurrentThread())) + NextObj = Hook->phkNext; + ClientInfo = pti->pClientInfo; + _SEH2_TRY { - UserDereferenceObject(Hook); - break; + ClientInfo->phkCurrent = NextObj; } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + ClientInfo = NULL; + } + _SEH2_END; + + if (!ClientInfo || !NextObj) break; - NextObj = IntGetNextHook(Hook); - ClientInfo->phkCurrent = NextObj; + NextObj->phkNext = IntGetNextHook(NextObj); if ( Hook->HookId == WH_CALLWNDPROC) { @@ -2634,8 +2657,6 @@ NtUserMessageCall( Hook->Ansi, &Hook->ModuleName); } - UserDereferenceObject(Hook); - lResult = (LRESULT) NextObj; } break; } diff --git a/reactos/subsystems/win32/win32k/ntuser/msgqueue.c b/reactos/subsystems/win32/win32k/ntuser/msgqueue.c index 5d0bee88eba..04694b46286 100644 --- a/reactos/subsystems/win32/win32k/ntuser/msgqueue.c +++ b/reactos/subsystems/win32/win32k/ntuser/msgqueue.c @@ -948,26 +948,25 @@ co_MsqDispatchOneSentMessage(PUSER_MESSAGE_QUEUE MessageQueue) &Message->ListEntry); if (Message->HookMessage == MSQ_ISHOOK) - { - Result = co_HOOK_CallHooks(Message->Msg.message, - (INT)(INT_PTR)Message->Msg.hwnd, - Message->Msg.wParam, - Message->Msg.lParam); + { // Direct Hook Call processor + Result = co_CallHook( Message->Msg.message, // HookId + (INT)(INT_PTR)Message->Msg.hwnd, // Code + Message->Msg.wParam, + Message->Msg.lParam); } else if (Message->HookMessage == MSQ_ISEVENT) - { + { // Direct Event Call processor Result = co_EVENT_CallEvents( Message->Msg.message, Message->Msg.hwnd, Message->Msg.wParam, Message->Msg.lParam); } else - { - /* Call the window procedure. */ - Result = co_IntSendMessage(Message->Msg.hwnd, - Message->Msg.message, - Message->Msg.wParam, - Message->Msg.lParam); + { /* Call the window procedure. */ + Result = co_IntSendMessage( Message->Msg.hwnd, + Message->Msg.message, + Message->Msg.wParam, + Message->Msg.lParam); } /* remove the message from the local dispatching list, because it doesn't need @@ -1004,7 +1003,9 @@ co_MsqDispatchOneSentMessage(PUSER_MESSAGE_QUEUE MessageQueue) KeSetEvent(Message->CompletionEvent, IO_NO_INCREMENT, FALSE); } - /* Call the callback if the message was sent with SendMessageCallback */ + /* Call the callback if the message wa + + s sent with SendMessageCallback */ if (Message->CompletionCallback != NULL) { co_IntCallSentMessageCallback(Message->CompletionCallback, @@ -1133,10 +1134,10 @@ co_MsqSendMessage(PUSER_MESSAGE_QUEUE MessageQueue, PUSER_SENT_MESSAGE Message; KEVENT CompletionEvent; NTSTATUS WaitStatus; - LRESULT Result; PUSER_MESSAGE_QUEUE ThreadQueue; LARGE_INTEGER Timeout; PLIST_ENTRY Entry; + LRESULT Result = 0; //// Result could be trashed. //// if(!(Message = ExAllocatePoolWithTag(PagedPool, sizeof(USER_SENT_MESSAGE), TAG_USRMSG))) { @@ -1154,7 +1155,6 @@ co_MsqSendMessage(PUSER_MESSAGE_QUEUE MessageQueue, /* FIXME - increase reference counter of sender's message queue here */ - Result = 0; Message->Msg.hwnd = Wnd; Message->Msg.message = Msg; Message->Msg.wParam = wParam; @@ -1164,6 +1164,7 @@ co_MsqSendMessage(PUSER_MESSAGE_QUEUE MessageQueue, Message->SenderQueue = ThreadQueue; IntReferenceMessageQueue(ThreadQueue); Message->CompletionCallback = NULL; + Message->CompletionCallbackContext = 0; Message->HookMessage = HookMessage; Message->HasPackedLParam = FALSE; @@ -1632,18 +1633,6 @@ MsqDestroyMessageQueue(PUSER_MESSAGE_QUEUE MessageQueue) IntDereferenceMessageQueue(MessageQueue); } -PHOOKTABLE FASTCALL -MsqGetHooks(PUSER_MESSAGE_QUEUE Queue) -{ - return Queue->Hooks; -} - -VOID FASTCALL -MsqSetHooks(PUSER_MESSAGE_QUEUE Queue, PHOOKTABLE Hooks) -{ - Queue->Hooks = Hooks; -} - LPARAM FASTCALL MsqSetMessageExtraInfo(LPARAM lParam) { diff --git a/reactos/subsystems/win32/win32k/ntuser/object.c b/reactos/subsystems/win32/win32k/ntuser/object.c index 0c3fb075d7e..222b36cb6b8 100644 --- a/reactos/subsystems/win32/win32k/ntuser/object.c +++ b/reactos/subsystems/win32/win32k/ntuser/object.c @@ -330,8 +330,8 @@ UserCreateObject( PUSER_HANDLE_TABLE ht, { case otWindow: // case otMenu: -// case otHook: -// case otCallProc: + case otHook: + case otCallProc: case otInputContext: Object = DesktopHeapAlloc(rpdesk, size); dt = TRUE; @@ -420,8 +420,8 @@ UserDereferenceObject(PVOID object) { case otWindow: // case otMenu: -// case otHook: -// case otCallProc: + case otHook: + case otCallProc: case otInputContext: return DesktopHeapFree(((PTHRDESKHEAD)object)->rpdesk, object); diff --git a/reactos/subsystems/win32/win32k/ntuser/simplecall.c b/reactos/subsystems/win32/win32k/ntuser/simplecall.c index af977096c8a..29d35958e44 100644 --- a/reactos/subsystems/win32/win32k/ntuser/simplecall.c +++ b/reactos/subsystems/win32/win32k/ntuser/simplecall.c @@ -228,21 +228,6 @@ NtUserCallOneParam( RETURN (ret); } - case ONEPARAM_ROUTINE_ISWINDOWINDESTROY: - { - PWND Window; - DWORD_PTR Result; - - if(!(Window = UserGetWindowObject((HWND)Param))) - { - RETURN( FALSE); - } - - Result = (DWORD_PTR)IntIsWindowInDestroy(Window); - - RETURN( Result); - } - case ONEPARAM_ROUTINE_ENABLEPROCWNDGHSTING: { BOOL Enable; @@ -473,6 +458,8 @@ NtUserCallTwoParam( case TWOPARAM_ROUTINE_SETCURSORPOS: RETURN( (DWORD_PTR)UserSetCursorPos((int)Param1, (int)Param2, FALSE)); + case TWOPARAM_ROUTINE_UNHOOKWINDOWSHOOK: + RETURN( IntUnhookWindowsHook((int)Param1, (HOOKPROC)Param2)); } DPRINT1("Calling invalid routine number 0x%x in NtUserCallTwoParam(), Param1=0x%x Parm2=0x%x\n", Routine, Param1, Param2); @@ -713,6 +700,21 @@ NtUserCallHwndParam( UserLeave(); return 0; } + + case HWNDPARAM_ROUTINE_ROS_NOTIFYWINEVENT: + { + PWND pWnd; + PNOTIFYEVENT pne; + UserEnterExclusive(); + pne = (PNOTIFYEVENT)Param; + if (hWnd) + pWnd = UserGetWindowObject(hWnd); + else + pWnd = NULL; + IntNotifyWinEvent(pne->event, pWnd, pne->idObject, pne->idChild, pne->flags); + UserLeave(); + return 0; + } } UNIMPLEMENTED; diff --git a/reactos/subsystems/win32/win32k/ntuser/window.c b/reactos/subsystems/win32/win32k/ntuser/window.c index 0b270cf8c0b..f6e588fa1d8 100644 --- a/reactos/subsystems/win32/win32k/ntuser/window.c +++ b/reactos/subsystems/win32/win32k/ntuser/window.c @@ -163,7 +163,6 @@ IntIsWindow(HWND hWnd) } - PWND FASTCALL IntGetParent(PWND Wnd) { @@ -179,7 +178,6 @@ IntGetParent(PWND Wnd) return NULL; } - /* * IntWinListChildren * @@ -348,7 +346,7 @@ static LRESULT co_UserFreeWindow(PWND Window, Window->state2 |= WNDS2_INDESTROY; Window->style &= ~WS_VISIBLE; - IntNotifyWinEvent(EVENT_OBJECT_DESTROY, Window, OBJID_WINDOW, 0); + IntNotifyWinEvent(EVENT_OBJECT_DESTROY, Window, OBJID_WINDOW, CHILDID_SELF, 0); /* remove the window already at this point from the thread window list so we don't get into trouble when destroying the thread windows while we're still @@ -399,7 +397,9 @@ static LRESULT co_UserFreeWindow(PWND Window, if(BelongsToThreadData) co_IntSendMessage(Window->head.h, WM_NCDESTROY, 0, 0); } + DestroyTimersForWindow(ThreadData, Window); + HOOK_DestroyThreadHooks(ThreadData->pEThread); // This is needed here too! /* flush the message queue */ @@ -1168,6 +1168,7 @@ co_IntSetParent(PWND Wnd, PWND WndNewParent) } + IntNotifyWinEvent(EVENT_OBJECT_PARENTCHANGE, Wnd ,OBJID_WINDOW, CHILDID_SELF, WEF_SETBYWNDPTI); /* * SetParent additionally needs to make hwnd the top window * in the z-order and send the expected WM_WINDOWPOSCHANGING and @@ -1227,13 +1228,6 @@ IntUnlinkWindow(PWND Wnd) Wnd->spwndPrev = Wnd->spwndNext = NULL; } -BOOL FASTCALL -IntIsWindowInDestroy(PWND Window) -{ - return ((Window->state2 & WNDS2_INDESTROY) == WNDS2_INDESTROY); -} - - BOOL FASTCALL IntGetWindowPlacement(PWND Wnd, WINDOWPLACEMENT *lpwndpl) @@ -1635,6 +1629,33 @@ PWND FASTCALL IntCreateWindow(CREATESTRUCTW* Cs, pti = PsGetCurrentThreadWin32Thread(); + if (!(Cs->dwExStyle & WS_EX_LAYOUTRTL)) + { + if (ParentWindow) + { + if ( (Cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD && + ParentWindow->ExStyle & WS_EX_LAYOUTRTL && + !(ParentWindow->ExStyle & WS_EX_NOINHERITLAYOUT) ) + Cs->dwExStyle |= WS_EX_LAYOUTRTL; + } + else + {/* + Note from MSDN http://msdn.microsoft.com/en-us/library/aa913269.aspx : + + Dialog boxes and message boxes do not inherit layout, so you must + set the layout explicitly. + */ + if ( Class && Class->fnid != FNID_DIALOG) + { + PPROCESSINFO ppi = PsGetCurrentProcessWin32Process(); + if (ppi->dwLayout & LAYOUT_RTL) + { + Cs->dwExStyle |= WS_EX_LAYOUTRTL; + } + } + } + } + /* Automatically add WS_EX_WINDOWEDGE */ if ((Cs->dwExStyle & WS_EX_DLGMODALFRAME) || ((!(Cs->dwExStyle & WS_EX_STATICEDGE)) && @@ -1877,17 +1898,19 @@ co_UserCreateWindowEx(CREATESTRUCTW* Cs, PLARGE_STRING WindowName) { PWND Window = NULL, ParentWindow = NULL, OwnerWindow; - HWND hWnd, hWndParent, hWndOwner; + HWND hWnd, hWndParent, hWndOwner, hwndInsertAfter; DWORD dwStyle; PWINSTATION_OBJECT WinSta; PCLS Class = NULL; SIZE Size; POINT MaxPos; - CBT_CREATEWNDW CbtCreate; + CBT_CREATEWNDW * pCbtCreate; LRESULT Result; USER_REFERENCE_ENTRY ParentRef, Ref; PTHREADINFO pti; + ANSI_STRING asClassName; DWORD dwShowMode = SW_SHOW; + CREATESTRUCTW *pCsw; DECLARE_RETURN(PWND); /* Get the current window station and reference it */ @@ -1900,6 +1923,10 @@ co_UserCreateWindowEx(CREATESTRUCTW* Cs, WinSta = pti->rpdesk->rpwinstaParent; ObReferenceObjectByPointer(WinSta, KernelMode, ExWindowStationObjectType, 0); + pCsw = NULL; + pCbtCreate = NULL; + RtlInitAnsiString(&asClassName, NULL); + /* Get the class and reference it*/ Class = IntGetAndReferenceClass(ClassName, Cs->hInstance); if(!Class) @@ -1956,22 +1983,57 @@ co_UserCreateWindowEx(CREATESTRUCTW* Cs, RETURN(0); } - hWnd = Window->head.h; + hWnd = UserHMGetHandle(Window); UserRefObjectCo(Window, &Ref); ObDereferenceObject(WinSta); - /* Call the WH_CBT hook */ - dwStyle = Cs->style; - Cs->style = Window->style; /* HCBT_CREATEWND needs the real window style */ - CbtCreate.lpcs = Cs; - CbtCreate.hwndInsertAfter = HWND_TOP; + //// Call the WH_CBT hook //// + + // Allocate the calling structures Justin Case this goes Global. + pCsw = ExAllocatePoolWithTag(NonPagedPool, sizeof(CREATESTRUCTW), TAG_HOOK); + pCbtCreate = ExAllocatePoolWithTag(NonPagedPool, sizeof(CBT_CREATEWNDW), TAG_HOOK); + + /* Fill the new CREATESTRUCTW */ + pCsw->lpCreateParams = Cs->lpCreateParams; + pCsw->hInstance = Cs->hInstance; + pCsw->hMenu = Cs->hMenu; + pCsw->hwndParent = Cs->hwndParent; + pCsw->cx = Cs->cx; + pCsw->cy = Cs->cy; + pCsw->x = Cs->x; + pCsw->y = Cs->y; + pCsw->dwExStyle = Cs->dwExStyle; + dwStyle = Cs->style; // Save it anyway. + pCsw->style = Window->style; /* HCBT_CREATEWND needs the real window style */ + + pCsw->lpszName = (LPCWSTR) WindowName->Buffer; + pCsw->lpszClass = (LPCWSTR) ClassName->Buffer; + + if (Window->state & WNDS_ANSICREATOR) + { + if (!IS_ATOM(ClassName->Buffer)) + { + RtlUnicodeStringToAnsiString(&asClassName, ClassName, TRUE); + pCsw->lpszClass = (LPCWSTR) asClassName.Buffer; + } + } + + pCbtCreate->lpcs = pCsw; + pCbtCreate->hwndInsertAfter = HWND_TOP; - if (co_HOOK_CallHooks(WH_CBT, HCBT_CREATEWND, (WPARAM) hWnd, (LPARAM) &CbtCreate)) + Result = co_HOOK_CallHooks(WH_CBT, HCBT_CREATEWND, (WPARAM) hWnd, (LPARAM) pCbtCreate); + if (Result != 0) { - DPRINT1("HCBT_CREATEWND hook failed!\n"); + DPRINT1("WH_CBT HCBT_CREATEWND hook failed! 0x%x\n", Result); RETURN( (PWND) NULL); } + // Write back changes. + Cs->cx = pCsw->cx; + Cs->cy = pCsw->cy; + Cs->x = pCsw->x; + Cs->y = pCsw->y; + hwndInsertAfter = pCbtCreate->hwndInsertAfter; Cs->style = dwStyle; /* NCCREATE and WM_NCCALCSIZE need the original values*/ @@ -2014,7 +2076,7 @@ co_UserCreateWindowEx(CREATESTRUCTW* Cs, } /* Send the NCCREATE message */ - Result = co_IntSendMessage(Window->head.h, WM_NCCREATE, 0, (LPARAM) Cs); + Result = co_IntSendMessage(UserHMGetHandle(Window), WM_NCCREATE, 0, (LPARAM) Cs); if (!Result) { DPRINT1("co_UserCreateWindowEx(): NCCREATE message failed\n"); @@ -2032,7 +2094,7 @@ co_UserCreateWindowEx(CREATESTRUCTW* Cs, /* Send the WM_CREATE message. */ - Result = co_IntSendMessage(Window->head.h, WM_CREATE, 0, (LPARAM) Cs); + Result = co_IntSendMessage(UserHMGetHandle(Window), WM_CREATE, 0, (LPARAM) Cs); if (Result == (LRESULT)-1) { DPRINT1("co_UserCreateWindowEx(): WM_CREATE message failed\n"); @@ -2040,7 +2102,7 @@ co_UserCreateWindowEx(CREATESTRUCTW* Cs, } /* Send the EVENT_OBJECT_CREATE event*/ - IntNotifyWinEvent(EVENT_OBJECT_CREATE, Window, OBJID_WINDOW, 0); + IntNotifyWinEvent(EVENT_OBJECT_CREATE, Window, OBJID_WINDOW, CHILDID_SELF, 0); /* By setting the flag below it can be examined to determine if the window was created successfully and a valid pwnd was passed back to caller since @@ -2102,7 +2164,7 @@ co_UserCreateWindowEx(CREATESTRUCTW* Cs, if (Window->ExStyle & WS_EX_MDICHILD) { - co_IntSendMessage(ParentWindow->head.h, WM_MDIREFRESHMENU, 0, 0); + co_IntSendMessage(UserHMGetHandle(ParentWindow), WM_MDIREFRESHMENU, 0, 0); /* ShowWindow won't activate child windows */ co_WinPosSetWindowPos(Window, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE); } @@ -2121,6 +2183,10 @@ CLEANUP: IntDereferenceClass(Class, pti->pDeskInfo, pti->ppi); } + if (pCsw) ExFreePoolWithTag(pCsw, TAG_HOOK); + if (pCbtCreate) ExFreePoolWithTag(pCbtCreate, TAG_HOOK); + RtlFreeAnsiString(&asClassName); + if (Window) { UserDerefObjectCo(Window); @@ -2280,7 +2346,7 @@ NtUserCreateWindowEx( /* Call the internal function */ pwnd = co_UserCreateWindowEx(&Cs, &ustrClassName, plstrWindowName); - if(!pwnd) + if(!pwnd) { DPRINT1("co_UserCreateWindowEx failed!\n"); } @@ -2343,7 +2409,11 @@ BOOLEAN FASTCALL co_UserDestroyWindow(PWND Window) /* If window was created successfully and it is hooked */ if ((Window->state2 & WNDS2_WMCREATEMSGPROCESSED)) { - if (co_HOOK_CallHooks(WH_CBT, HCBT_DESTROYWND, (WPARAM) hWnd, 0)) return FALSE; + if (co_HOOK_CallHooks(WH_CBT, HCBT_DESTROYWND, (WPARAM) hWnd, 0)) + { + DPRINT1("Destroy Window WH_CBT Call Hook return!\n"); + return FALSE; + } } /* Inform the parent */ diff --git a/reactos/subsystems/win32/win32k/ntuser/winpos.c b/reactos/subsystems/win32/win32k/ntuser/winpos.c index 7a9562613c4..04c0fd7263f 100644 --- a/reactos/subsystems/win32/win32k/ntuser/winpos.c +++ b/reactos/subsystems/win32/win32k/ntuser/winpos.c @@ -299,8 +299,10 @@ co_WinPosMinMaximize(PWND Wnd, UINT ShowFlag, RECT* NewPos) WinPosInitInternalPos(Wnd, &Size, &Wnd->rcWindow); if (co_HOOK_CallHooks( WH_CBT, HCBT_MINMAX, (WPARAM)Wnd->head.h, ShowFlag)) + { + DPRINT1("WinPosMinMaximize WH_CBT Call Hook return!\n"); return SWP_NOSIZE | SWP_NOMOVE; - + } if (Wnd->style & WS_MINIMIZE) { if (!co_IntSendMessageNoWait(Wnd->head.h, WM_QUERYOPEN, 0, 0)) @@ -385,7 +387,6 @@ co_WinPosMinMaximize(PWND Wnd, UINT ShowFlag, RECT* NewPos) } } } - return(SwpFlags); } @@ -1358,6 +1359,14 @@ co_WinPosSetWindowPos( co_IntSendMessageNoWait(WinPos.hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM) &WinPos); } + if ( WinPos.flags & SWP_FRAMECHANGED || WinPos.flags & SWP_STATECHANGED || + !(WinPos.flags & SWP_NOCLIENTSIZE) || !(WinPos.flags & SWP_NOCLIENTMOVE) ) + { + PWND pWnd = UserGetWindowObject(WinPos.hwnd); + if (pWnd) + IntNotifyWinEvent(EVENT_OBJECT_LOCATIONCHANGE, pWnd, OBJID_WINDOW, CHILDID_SELF, WEF_SETBYWNDPTI); + } + return TRUE; }