mirror of
https://github.com/reactos/reactos.git
synced 2025-02-24 17:34:57 +00:00
[win32k]
- Merge changes from the themes branch. These changes will introduce test regressions for class functions and for TrackMouseEvent. The changes in the class functions are needed in order to let comctl32 register its own versions of built in controls. This is a hack and will be removed when we properly support class versions. The second change that causes test regressions is in TrackMouseEvent and it is needed in order to fix WM_MOUSELEAVE messages that were completely broken and not tested at all by wine's test suite. svn path=/trunk/; revision=53745
This commit is contained in:
parent
b880e23623
commit
06631cf0ea
14 changed files with 571 additions and 58 deletions
|
@ -54,3 +54,10 @@ IntCbFreeMemory(PVOID Data);
|
|||
HMENU APIENTRY co_IntCallLoadMenu(HINSTANCE,PUNICODE_STRING);
|
||||
|
||||
NTSTATUS APIENTRY co_IntClientThreadSetup(VOID);
|
||||
|
||||
HMODULE
|
||||
co_IntClientLoadLibrary(PUNICODE_STRING strLibName,
|
||||
PUNICODE_STRING strInitFunc,
|
||||
BOOL Unload,
|
||||
BOOL ApiHook);
|
||||
|
||||
|
|
|
@ -5,6 +5,13 @@
|
|||
#define HOOKID_TO_FLAG(HookId) (1 << ((HookId) + 1))
|
||||
#define ISITHOOKED(HookId) (((PTHREADINFO)PsGetCurrentThreadWin32Thread())->fsHooks & HOOKID_TO_FLAG(HookId))
|
||||
|
||||
/* NOTE: the following definition is not a real hook but
|
||||
a pseudo-id that will be used only for
|
||||
injecting user api hook module to all processes.
|
||||
It is used internally in win32k */
|
||||
#define WH_APIHOOK WH_MAX + 1
|
||||
|
||||
|
||||
typedef struct tagEVENTHOOK
|
||||
{
|
||||
THROBJHEAD head;
|
||||
|
@ -43,4 +50,10 @@ PHOOK FASTCALL IntGetNextHook(PHOOK Hook);
|
|||
LRESULT FASTCALL UserCallNextHookEx( PHOOK pHook, int Code, WPARAM wParam, LPARAM lParam, BOOL Ansi);
|
||||
BOOL FASTCALL IntUnhookWindowsHook(int,HOOKPROC);
|
||||
|
||||
BOOL FASTCALL UserLoadApiHook();
|
||||
BOOL IntLoadHookModule(int iHookID, HHOOK hHook, BOOL Unload);
|
||||
BOOL FASTCALL UserUnregisterUserApiHook();
|
||||
|
||||
extern PPROCESSINFO ppiUahServer;
|
||||
|
||||
/* EOF */
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#define MSQ_NORMAL 0
|
||||
#define MSQ_ISHOOK 1
|
||||
#define MSQ_ISEVENT 2
|
||||
#define MSQ_INJECTMODULE 3
|
||||
|
||||
#define QSIDCOUNTS 6
|
||||
|
||||
|
@ -206,6 +207,16 @@ co_IntSendMessageWithCallBack(HWND hWnd,
|
|||
SENDASYNCPROC CompletionCallback,
|
||||
ULONG_PTR CompletionCallbackContext,
|
||||
ULONG_PTR *uResult);
|
||||
BOOL FASTCALL
|
||||
co_MsqSendMessageAsync(PTHREADINFO ptiReceiver,
|
||||
HWND hwnd,
|
||||
UINT Msg,
|
||||
WPARAM wParam,
|
||||
LPARAM lParam,
|
||||
SENDASYNCPROC CompletionCallback,
|
||||
ULONG_PTR CompletionCallbackContext,
|
||||
BOOL HasPackedLParam,
|
||||
INT HookMessage);
|
||||
|
||||
LRESULT FASTCALL IntDispatchMessage(MSG* Msg);
|
||||
BOOL FASTCALL IntTranslateKbdMessage(LPMSG lpMsg, UINT flags);
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#define W32PF_NOWINDOWGHOSTING (0x01000000)
|
||||
#define W32PF_MANUALGUICHECK (0x02000000)
|
||||
#define W32PF_CREATEDWINORDC (0x04000000)
|
||||
#define W32PF_APIHOOKLOADED (0x08000000)
|
||||
|
||||
extern BOOL ClientPfnInit;
|
||||
extern HINSTANCE hModClient;
|
||||
|
|
|
@ -393,6 +393,22 @@ Win32kThreadCallback(struct _ETHREAD *Thread,
|
|||
/* Remove it from the list */
|
||||
*ppti = ptiCurrent->ptiSibling;
|
||||
|
||||
/* Decrement thread count and check if its 0 */
|
||||
ppiCurrent->cThreads--;
|
||||
|
||||
/* Do now some process cleanup that requires a valid win32 thread */
|
||||
if(ptiCurrent->ppi->cThreads == 0)
|
||||
{
|
||||
UserSetCursor(NULL, TRUE);
|
||||
|
||||
/* Check if we have registered the user api hook */
|
||||
if(ptiCurrent->ppi == ppiUahServer)
|
||||
{
|
||||
/* Unregister the api hook without blocking */
|
||||
UserUnregisterUserApiHook();
|
||||
}
|
||||
}
|
||||
|
||||
DceFreeThreadDCE(ptiCurrent);
|
||||
HOOK_DestroyThreadHooks(Thread);
|
||||
EVENT_DestroyThreadEvents(Thread);
|
||||
|
@ -421,14 +437,6 @@ Win32kThreadCallback(struct _ETHREAD *Thread,
|
|||
|
||||
IntSetThreadDesktop(NULL, TRUE);
|
||||
|
||||
/* Decrement thread count and check if its 0 */
|
||||
ppiCurrent->cThreads--;
|
||||
if (ppiCurrent->cThreads == 0)
|
||||
{
|
||||
/* UGLY: Prevent this function from being called later
|
||||
when we don't have a THREADINFO anymore. */
|
||||
UserSetCursor(NULL, TRUE);
|
||||
}
|
||||
|
||||
/* Free the THREADINFO */
|
||||
PsSetThreadWin32Thread(Thread, NULL);
|
||||
|
|
|
@ -116,6 +116,114 @@ IntRestoreTebWndCallback (HWND hWnd, PWND pWnd)
|
|||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
/* calls ClientLoadLibrary in user32 */
|
||||
HMODULE
|
||||
co_IntClientLoadLibrary(PUNICODE_STRING pstrLibName,
|
||||
PUNICODE_STRING pstrInitFunc,
|
||||
BOOL Unload,
|
||||
BOOL ApiHook)
|
||||
{
|
||||
PVOID ResultPointer;
|
||||
ULONG ResultLength;
|
||||
ULONG ArgumentLength;
|
||||
PCLIENT_LOAD_LIBRARY_ARGUMENTS pArguments;
|
||||
NTSTATUS Status;
|
||||
HMODULE Result;
|
||||
ULONG_PTR pLibNameBuffer = 0, pInitFuncBuffer = 0;
|
||||
|
||||
TRACE("co_IntClientLoadLibrary: %S, %S, %d, %d\n", pstrLibName->Buffer, pstrLibName->Buffer, Unload, ApiHook);
|
||||
|
||||
/* Calculate the size of the argument */
|
||||
ArgumentLength = sizeof(CLIENT_LOAD_LIBRARY_ARGUMENTS);
|
||||
if(pstrLibName)
|
||||
{
|
||||
pLibNameBuffer = ArgumentLength;
|
||||
ArgumentLength += pstrLibName->Length + sizeof(WCHAR);
|
||||
}
|
||||
if(pstrInitFunc)
|
||||
{
|
||||
pInitFuncBuffer = ArgumentLength;
|
||||
ArgumentLength += pstrInitFunc->Length + sizeof(WCHAR);
|
||||
}
|
||||
|
||||
/* Allocate the argument*/
|
||||
pArguments = IntCbAllocateMemory(ArgumentLength);
|
||||
if(pArguments == NULL)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Fill the argument */
|
||||
pArguments->Unload = Unload;
|
||||
pArguments->ApiHook = ApiHook;
|
||||
if(pstrLibName)
|
||||
{
|
||||
/* Copy the string to the callback memory */
|
||||
pLibNameBuffer += (ULONG_PTR)pArguments;
|
||||
pArguments->strLibraryName.Buffer = (PWCHAR)pLibNameBuffer;
|
||||
pArguments->strLibraryName.MaximumLength = pstrLibName->Length + sizeof(WCHAR);
|
||||
RtlCopyUnicodeString(&pArguments->strLibraryName, pstrLibName);
|
||||
|
||||
/* Fix argument pointer to be relative to the argument */
|
||||
pLibNameBuffer -= (ULONG_PTR)pArguments;
|
||||
pArguments->strLibraryName.Buffer = (PWCHAR)(pLibNameBuffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
RtlZeroMemory(&pArguments->strLibraryName, sizeof(UNICODE_STRING));
|
||||
}
|
||||
|
||||
if(pstrInitFunc)
|
||||
{
|
||||
/* Copy the strings to the callback memory */
|
||||
pInitFuncBuffer += (ULONG_PTR)pArguments;
|
||||
pArguments->strInitFuncName.Buffer = (PWCHAR)pInitFuncBuffer;
|
||||
pArguments->strInitFuncName.MaximumLength = pstrInitFunc->Length + sizeof(WCHAR);
|
||||
RtlCopyUnicodeString(&pArguments->strInitFuncName, pstrInitFunc);
|
||||
|
||||
/* Fix argument pointers to be relative to the argument */
|
||||
pInitFuncBuffer -= (ULONG_PTR)pArguments;
|
||||
pArguments->strInitFuncName.Buffer = (PWCHAR)(pInitFuncBuffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
RtlZeroMemory(&pArguments->strInitFuncName, sizeof(UNICODE_STRING));
|
||||
}
|
||||
|
||||
/* Do the callback */
|
||||
UserLeaveCo();
|
||||
|
||||
Status = KeUserModeCallback(USER32_CALLBACK_CLIENTLOADLIBRARY,
|
||||
pArguments,
|
||||
ArgumentLength,
|
||||
&ResultPointer,
|
||||
&ResultLength);
|
||||
|
||||
UserEnterCo();
|
||||
|
||||
/* Free the argument */
|
||||
IntCbFreeMemory(pArguments);
|
||||
|
||||
if(!NT_SUCCESS(Status))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
_SEH2_TRY
|
||||
{
|
||||
ProbeForRead(ResultPointer, sizeof(HMODULE), 1);
|
||||
/* Simulate old behaviour: copy into our local buffer */
|
||||
Result = *(HMODULE*)ResultPointer;
|
||||
}
|
||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
Result = 0;
|
||||
}
|
||||
_SEH2_END;
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
VOID APIENTRY
|
||||
co_IntCallSentMessageCallback(SENDASYNCPROC CompletionCallback,
|
||||
HWND hWnd,
|
||||
|
|
|
@ -1295,8 +1295,9 @@ UserRegisterClass(IN CONST WNDCLASSEXW* lpwcx,
|
|||
|
||||
if (lpwcx->style & CS_GLOBALCLASS)
|
||||
{
|
||||
/* HACK: allow global classes to be re-registered*/
|
||||
Class = IntFindClass( ClassAtom,
|
||||
NULL,
|
||||
lpwcx->hInstance,
|
||||
&pi->pclsPublicList,
|
||||
NULL);
|
||||
|
||||
|
|
|
@ -24,8 +24,222 @@ typedef struct _HOOKPACK
|
|||
PVOID pHookStructs;
|
||||
} HOOKPACK, *PHOOKPACK;
|
||||
|
||||
UNICODE_STRING strUahModule;
|
||||
UNICODE_STRING strUahInitFunc;
|
||||
PPROCESSINFO ppiUahServer;
|
||||
|
||||
/* PRIVATE FUNCTIONS *********************************************************/
|
||||
|
||||
/* Calls ClientLoadLibrary in user32 in order to load or unload a module */
|
||||
BOOL
|
||||
IntLoadHookModule(int iHookID, HHOOK hHook, BOOL Unload)
|
||||
{
|
||||
PPROCESSINFO ppi;
|
||||
HMODULE hmod;
|
||||
|
||||
ppi = PsGetCurrentProcessWin32Process();
|
||||
|
||||
ERR("IntLoadHookModule. Client PID: %d\n", PsGetProcessId(ppi->peProcess));
|
||||
|
||||
/* Check if this is the api hook */
|
||||
if(iHookID == WH_APIHOOK)
|
||||
{
|
||||
if(!Unload && !(ppi->W32PF_flags & W32PF_APIHOOKLOADED))
|
||||
{
|
||||
/* A callback in user mode can trigger UserLoadApiHook to be called and
|
||||
as a result IntLoadHookModule will be called recursively.
|
||||
To solve this we set the flag that means that the appliaction has
|
||||
loaded the api hook before the callback and in case of error we remove it */
|
||||
ppi->W32PF_flags |= W32PF_APIHOOKLOADED;
|
||||
|
||||
/* Call ClientLoadLibrary in user32 */
|
||||
hmod = co_IntClientLoadLibrary(&strUahModule, &strUahInitFunc, Unload, TRUE);
|
||||
TRACE("co_IntClientLoadLibrary returned %d\n", hmod );
|
||||
if(hmod == 0)
|
||||
{
|
||||
/* Remove the flag we set before */
|
||||
ppi->W32PF_flags &= ~W32PF_APIHOOKLOADED;
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
else if(Unload && (ppi->W32PF_flags & W32PF_APIHOOKLOADED))
|
||||
{
|
||||
/* Call ClientLoadLibrary in user32 */
|
||||
hmod = co_IntClientLoadLibrary(NULL, NULL, Unload, TRUE);
|
||||
if(hmod != 0)
|
||||
{
|
||||
ppi->W32PF_flags &= ~W32PF_APIHOOKLOADED;
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
STUB;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
IntHookModuleUnloaded:
|
||||
Sends a internal message to all threads of the requested desktop
|
||||
and notifies them that a global hook was destroyed
|
||||
and an injected module must be unloaded.
|
||||
As a result, IntLoadHookModule will be called for all the threads that
|
||||
will receive the special purpose internal message.
|
||||
*/
|
||||
BOOL
|
||||
IntHookModuleUnloaded(PDESKTOP pdesk, int iHookID, HHOOK hHook)
|
||||
{
|
||||
PTHREADINFO ptiCurrent;
|
||||
PLIST_ENTRY ListEntry;
|
||||
PPROCESSINFO ppiCsr;
|
||||
|
||||
ERR("IntHookModuleUnloaded: iHookID=%d\n", iHookID);
|
||||
|
||||
ppiCsr = PsGetProcessWin32Process(CsrProcess);
|
||||
|
||||
ListEntry = pdesk->PtiList.Flink;
|
||||
while(ListEntry != &pdesk->PtiList)
|
||||
{
|
||||
ptiCurrent = CONTAINING_RECORD(ListEntry, THREADINFO, PtiLink);
|
||||
|
||||
/* FIXME: do some more security checks here */
|
||||
|
||||
/* FIXME: the first check is a reactos specific hack for system threads */
|
||||
if(!PsIsSystemProcess(ptiCurrent->ppi->peProcess) &&
|
||||
ptiCurrent->ppi != ppiCsr)
|
||||
{
|
||||
if(ptiCurrent->ppi->W32PF_flags & W32PF_APIHOOKLOADED)
|
||||
{
|
||||
TRACE("IntHookModuleUnloaded: sending message to PID %d, ppi=0x%x\n", PsGetProcessId(ptiCurrent->ppi->peProcess), ptiCurrent->ppi);
|
||||
co_MsqSendMessageAsync( ptiCurrent,
|
||||
0,
|
||||
iHookID,
|
||||
TRUE,
|
||||
(LPARAM)hHook,
|
||||
NULL,
|
||||
0,
|
||||
FALSE,
|
||||
MSQ_INJECTMODULE);
|
||||
}
|
||||
}
|
||||
ListEntry = ListEntry->Flink;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL
|
||||
FASTCALL
|
||||
UserLoadApiHook()
|
||||
{
|
||||
return IntLoadHookModule(WH_APIHOOK, 0, FALSE);
|
||||
}
|
||||
|
||||
BOOL
|
||||
FASTCALL
|
||||
UserRegisterUserApiHook(
|
||||
PUNICODE_STRING pstrDllName,
|
||||
PUNICODE_STRING pstrFuncName)
|
||||
{
|
||||
PTHREADINFO pti, ptiCurrent;
|
||||
HWND *List;
|
||||
PWND DesktopWindow, pwndCurrent;
|
||||
ULONG i;
|
||||
PPROCESSINFO ppiCsr;
|
||||
|
||||
pti = PsGetCurrentThreadWin32Thread();
|
||||
ppiCsr = PsGetProcessWin32Process(CsrProcess);
|
||||
|
||||
/* Fail if the api hook is already registered */
|
||||
if(gpsi->dwSRVIFlags & SRVINFO_APIHOOK)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ERR("UserRegisterUserApiHook. Server PID: %d\n", PsGetProcessId(pti->ppi->peProcess));
|
||||
|
||||
/* Register the api hook */
|
||||
gpsi->dwSRVIFlags |= SRVINFO_APIHOOK;
|
||||
|
||||
strUahModule = *pstrDllName;
|
||||
strUahInitFunc = *pstrFuncName;
|
||||
ppiUahServer = pti->ppi;
|
||||
|
||||
/* Broadcast an internal message to every top level window */
|
||||
DesktopWindow = UserGetWindowObject(IntGetDesktopWindow());
|
||||
List = IntWinListChildren(DesktopWindow);
|
||||
|
||||
if (List != NULL)
|
||||
{
|
||||
for (i = 0; List[i]; i++)
|
||||
{
|
||||
pwndCurrent = UserGetWindowObject(List[i]);
|
||||
if(pwndCurrent == NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
ptiCurrent = pwndCurrent->head.pti;
|
||||
|
||||
/* FIXME: the first check is a reactos specific hack for system threads */
|
||||
if(PsIsSystemProcess(ptiCurrent->ppi->peProcess) ||
|
||||
ptiCurrent->ppi == ppiCsr)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
co_MsqSendMessageAsync( ptiCurrent,
|
||||
0,
|
||||
WH_APIHOOK,
|
||||
FALSE, /* load the module */
|
||||
0,
|
||||
NULL,
|
||||
0,
|
||||
FALSE,
|
||||
MSQ_INJECTMODULE);
|
||||
}
|
||||
ExFreePoolWithTag(List, USERTAG_WINDOWLIST);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL
|
||||
FASTCALL
|
||||
UserUnregisterUserApiHook()
|
||||
{
|
||||
PTHREADINFO pti;
|
||||
|
||||
pti = PsGetCurrentThreadWin32Thread();
|
||||
|
||||
/* Fail if the api hook is not registered */
|
||||
if(!(gpsi->dwSRVIFlags & SRVINFO_APIHOOK))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Only the process that registered the api hook can uregister it */
|
||||
if(ppiUahServer != PsGetCurrentProcessWin32Process())
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ERR("UserUnregisterUserApiHook. Server PID: %d\n", PsGetProcessId(pti->ppi->peProcess));
|
||||
|
||||
/* Unregister the api hook */
|
||||
gpsi->dwSRVIFlags &= ~SRVINFO_APIHOOK;
|
||||
ppiUahServer = NULL;
|
||||
ReleaseCapturedUnicodeString(&strUahModule, UserMode);
|
||||
ReleaseCapturedUnicodeString(&strUahInitFunc, UserMode);
|
||||
|
||||
/* Notify all applications that the api hook module must be unloaded */
|
||||
return IntHookModuleUnloaded(pti->rpdesk, WH_APIHOOK, 0);
|
||||
}
|
||||
|
||||
static
|
||||
LRESULT
|
||||
FASTCALL
|
||||
|
@ -1510,4 +1724,64 @@ CLEANUP:
|
|||
END_CLEANUP;
|
||||
}
|
||||
|
||||
BOOL
|
||||
APIENTRY
|
||||
NtUserRegisterUserApiHook(
|
||||
PUNICODE_STRING m_dllname1,
|
||||
PUNICODE_STRING m_funname1,
|
||||
DWORD dwUnknown3,
|
||||
DWORD dwUnknown4)
|
||||
{
|
||||
BOOL ret;
|
||||
UNICODE_STRING strDllNameSafe;
|
||||
UNICODE_STRING strFuncNameSafe;
|
||||
NTSTATUS Status;
|
||||
|
||||
/* Probe and capture parameters */
|
||||
Status = ProbeAndCaptureUnicodeString(&strDllNameSafe, UserMode, m_dllname1);
|
||||
if(!NT_SUCCESS(Status))
|
||||
{
|
||||
EngSetLastError(RtlNtStatusToDosError(Status));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Status = ProbeAndCaptureUnicodeString(&strFuncNameSafe, UserMode, m_funname1);
|
||||
if(!NT_SUCCESS(Status))
|
||||
{
|
||||
ReleaseCapturedUnicodeString(&strDllNameSafe, UserMode);
|
||||
EngSetLastError(RtlNtStatusToDosError(Status));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
UserEnterExclusive();
|
||||
|
||||
/* Call internal function */
|
||||
ret = UserRegisterUserApiHook(&strDllNameSafe, &strFuncNameSafe);
|
||||
|
||||
UserLeave();
|
||||
|
||||
/* Cleanup only in case of failure */
|
||||
if(ret == FALSE)
|
||||
{
|
||||
ReleaseCapturedUnicodeString(&strDllNameSafe, UserMode);
|
||||
ReleaseCapturedUnicodeString(&strFuncNameSafe, UserMode);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
BOOL
|
||||
APIENTRY
|
||||
NtUserUnregisterUserApiHook(VOID)
|
||||
{
|
||||
BOOL ret;
|
||||
|
||||
UserEnterExclusive();
|
||||
ret = UserUnregisterUserApiHook();
|
||||
UserLeave();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* EOF */
|
||||
|
|
|
@ -1611,19 +1611,6 @@ IntTrackMouseEvent(
|
|||
if (!(pWnd = UserGetWindowObject(lpEventTrack->hwndTrack)))
|
||||
return FALSE;
|
||||
|
||||
if ( pDesk->spwndTrack != pWnd ||
|
||||
(pDesk->htEx != HTCLIENT) ^ !!(lpEventTrack->dwFlags & TME_NONCLIENT) )
|
||||
{
|
||||
if ( lpEventTrack->dwFlags & TME_LEAVE && !(lpEventTrack->dwFlags & TME_CANCEL) )
|
||||
{
|
||||
UserPostMessage( lpEventTrack->hwndTrack,
|
||||
lpEventTrack->dwFlags & TME_NONCLIENT ? WM_NCMOUSELEAVE : WM_MOUSELEAVE,
|
||||
0, 0);
|
||||
}
|
||||
TRACE("IntTrackMouseEvent spwndTrack 0x%x pwnd 0x%x\n", pDesk->spwndTrack, pWnd);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Tracking spwndTrack same as pWnd */
|
||||
if ( lpEventTrack->dwFlags & TME_CANCEL ) // Canceled mode.
|
||||
{
|
||||
|
@ -1641,6 +1628,7 @@ IntTrackMouseEvent(
|
|||
}
|
||||
else // Not Canceled.
|
||||
{
|
||||
pDesk->spwndTrack = pWnd;
|
||||
if ( lpEventTrack->dwFlags & TME_LEAVE )
|
||||
pDesk->dwDTFlags |= DF_TME_LEAVE;
|
||||
|
||||
|
|
|
@ -539,22 +539,35 @@ co_MsqInsertMouseMessage(MSG* Msg, DWORD flags, ULONG_PTR dwExtraInfo, BOOL Hook
|
|||
|
||||
if (pwnd)
|
||||
{
|
||||
PWND pwndTrack = IntChildrenWindowFromPoint(pwnd, Msg->pt.x, Msg->pt.y);
|
||||
|
||||
if ( pDesk->spwndTrack != pwndTrack && pDesk->dwDTFlags & (DF_TME_LEAVE|DF_TME_HOVER) )
|
||||
/* If we a re tracking the mouse and it moves to another top level window */
|
||||
if(pDesk->spwndTrack &&
|
||||
UserGetAncestor(pDesk->spwndTrack, GA_ROOT) != pwnd)
|
||||
{
|
||||
if ( pDesk->dwDTFlags & DF_TME_LEAVE )
|
||||
UserPostMessage( UserHMGetHandle(pDesk->spwndTrack),
|
||||
(pDesk->htEx != HTCLIENT) ? WM_NCMOUSELEAVE : WM_MOUSELEAVE,
|
||||
0, 0);
|
||||
/* Generate a WM_MOUSELEAVE message */
|
||||
if ( pDesk->dwDTFlags & DF_TME_LEAVE )
|
||||
{
|
||||
MSG msgMouseLeave;
|
||||
|
||||
if ( pDesk->dwDTFlags & DF_TME_HOVER )
|
||||
IntKillTimer(UserHMGetHandle(pDesk->spwndTrack), ID_EVENT_SYSTIMER_MOUSEHOVER, TRUE);
|
||||
TRACE("co_MsqInsertMouseMessage: generating WM_MOUSELEAVE\n");
|
||||
|
||||
pDesk->dwDTFlags &= ~(DF_TME_LEAVE|DF_TME_HOVER);
|
||||
msgMouseLeave.hwnd = UserHMGetHandle(pDesk->spwndTrack);
|
||||
msgMouseLeave.message = WM_MOUSELEAVE;
|
||||
msgMouseLeave.pt = Msg->pt;
|
||||
msgMouseLeave.time = Msg->time;
|
||||
msgMouseLeave.lParam = msgMouseLeave.wParam = 0;
|
||||
|
||||
MsqPostMessage(pwnd->head.pti->MessageQueue, Msg, TRUE, QS_MOUSE);
|
||||
}
|
||||
|
||||
/* Stop tracking */
|
||||
if ( pDesk->dwDTFlags & DF_TME_HOVER )
|
||||
{
|
||||
IntKillTimer(pDesk->spwndTrack, ID_EVENT_SYSTIMER_MOUSEHOVER, TRUE);
|
||||
}
|
||||
|
||||
pDesk->spwndTrack = NULL;
|
||||
pDesk->htEx = 0;
|
||||
}
|
||||
pDesk->spwndTrack = pwndTrack;
|
||||
pDesk->htEx = GetNCHitEx(pDesk->spwndTrack, Msg->pt);
|
||||
}
|
||||
|
||||
hdcScreen = IntGetScreenDC();
|
||||
|
@ -811,6 +824,12 @@ co_MsqDispatchOneSentMessage(PUSER_MESSAGE_QUEUE MessageQueue)
|
|||
Message->Msg.wParam,
|
||||
Message->Msg.lParam);
|
||||
}
|
||||
else if(Message->HookMessage == MSQ_INJECTMODULE)
|
||||
{
|
||||
Result = IntLoadHookModule(Message->Msg.message,
|
||||
(HHOOK)Message->Msg.lParam,
|
||||
Message->Msg.wParam);
|
||||
}
|
||||
else if ((Message->CompletionCallback)
|
||||
&& (Message->CallBackSenderQueue == MessageQueue))
|
||||
{ /* Call the callback routine */
|
||||
|
@ -1006,6 +1025,58 @@ MsqRemoveWindowMessagesFromQueue(PVOID pWindow)
|
|||
}
|
||||
}
|
||||
|
||||
BOOL FASTCALL
|
||||
co_MsqSendMessageAsync(PTHREADINFO ptiReceiver,
|
||||
HWND hwnd,
|
||||
UINT Msg,
|
||||
WPARAM wParam,
|
||||
LPARAM lParam,
|
||||
SENDASYNCPROC CompletionCallback,
|
||||
ULONG_PTR CompletionCallbackContext,
|
||||
BOOL HasPackedLParam,
|
||||
INT HookMessage)
|
||||
{
|
||||
|
||||
PTHREADINFO ptiSender;
|
||||
PUSER_SENT_MESSAGE Message;
|
||||
|
||||
if(!(Message = ExAllocatePoolWithTag(NonPagedPool, sizeof(USER_SENT_MESSAGE), TAG_USRMSG)))
|
||||
{
|
||||
ERR("MsqSendMessage(): Not enough memory to allocate a message");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ptiSender = PsGetCurrentThreadWin32Thread();
|
||||
|
||||
IntReferenceMessageQueue(ptiReceiver->MessageQueue);
|
||||
/* Take reference on this MessageQueue if its a callback. It will be released
|
||||
when message is processed or removed from target hwnd MessageQueue */
|
||||
if (CompletionCallback)
|
||||
IntReferenceMessageQueue(ptiSender->MessageQueue);
|
||||
|
||||
Message->Msg.hwnd = hwnd;
|
||||
Message->Msg.message = Msg;
|
||||
Message->Msg.wParam = wParam;
|
||||
Message->Msg.lParam = lParam;
|
||||
Message->CompletionEvent = NULL;
|
||||
Message->Result = 0;
|
||||
Message->lResult = 0;
|
||||
Message->SenderQueue = NULL;
|
||||
Message->CallBackSenderQueue = ptiSender->MessageQueue;
|
||||
Message->DispatchingListEntry.Flink = NULL;
|
||||
Message->CompletionCallback = CompletionCallback;
|
||||
Message->CompletionCallbackContext = CompletionCallbackContext;
|
||||
Message->HookMessage = HookMessage;
|
||||
Message->HasPackedLParam = HasPackedLParam;
|
||||
Message->QS_Flags = QS_SENDMESSAGE;
|
||||
|
||||
InsertTailList(&ptiReceiver->MessageQueue->SentMessagesListHead, &Message->ListEntry);
|
||||
MsqWakeQueue(ptiReceiver->MessageQueue, QS_SENDMESSAGE, TRUE);
|
||||
IntDereferenceMessageQueue(ptiReceiver->MessageQueue);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
NTSTATUS FASTCALL
|
||||
co_MsqSendMessage(PUSER_MESSAGE_QUEUE MessageQueue,
|
||||
HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam,
|
||||
|
@ -1281,6 +1352,7 @@ BOOL co_IntProcessMouseMessage(MSG* msg, BOOL* RemoveMessages, UINT first, UINT
|
|||
PUSER_MESSAGE_QUEUE MessageQueue;
|
||||
PTHREADINFO pti;
|
||||
PSYSTEM_CURSORINFO CurInfo;
|
||||
PDESKTOP pDesk;
|
||||
DECLARE_RETURN(BOOL);
|
||||
|
||||
pti = PsGetCurrentThreadWin32Thread();
|
||||
|
@ -1289,6 +1361,7 @@ BOOL co_IntProcessMouseMessage(MSG* msg, BOOL* RemoveMessages, UINT first, UINT
|
|||
CurInfo = IntGetSysCursorInfo();
|
||||
pwndMsg = UserGetWindowObject(msg->hwnd);
|
||||
clk_msg = MessageQueue->msgDblClk;
|
||||
pDesk = pwndDesktop->head.rpdesk;
|
||||
|
||||
/* find the window to dispatch this mouse message to */
|
||||
if (MessageQueue->CaptureWindow)
|
||||
|
@ -1310,6 +1383,45 @@ BOOL co_IntProcessMouseMessage(MSG* msg, BOOL* RemoveMessages, UINT first, UINT
|
|||
RETURN(FALSE);
|
||||
}
|
||||
|
||||
/* If we a re tracking the mouse and it moves to another window */
|
||||
if(pDesk->spwndTrack &&
|
||||
pDesk->spwndTrack != pwndMsg &&
|
||||
msg->message != WM_MOUSELEAVE)
|
||||
{
|
||||
/* Generate a WM_MOUSELEAVE message */
|
||||
if ( pDesk->dwDTFlags & DF_TME_LEAVE )
|
||||
{
|
||||
MSG msgMouseLeave;
|
||||
|
||||
TRACE("co_IntProcessMouseMessage: generating WM_MOUSELEAVE\n");
|
||||
|
||||
msgMouseLeave.hwnd = UserHMGetHandle(pDesk->spwndTrack);
|
||||
msgMouseLeave.message = WM_MOUSELEAVE;
|
||||
msgMouseLeave.pt = msg->pt;
|
||||
msgMouseLeave.time = msg->time;
|
||||
msgMouseLeave.lParam = msgMouseLeave.wParam = 0;
|
||||
|
||||
MsqPostMessage(pwndMsg->head.pti->MessageQueue,
|
||||
&msgMouseLeave,
|
||||
TRUE,
|
||||
QS_MOUSE);
|
||||
}
|
||||
|
||||
/* Stop tracking */
|
||||
if ( pDesk->dwDTFlags & DF_TME_HOVER )
|
||||
{
|
||||
IntKillTimer(pDesk->spwndTrack, ID_EVENT_SYSTIMER_MOUSEHOVER, TRUE);
|
||||
}
|
||||
|
||||
pDesk->spwndTrack = NULL;
|
||||
pDesk->htEx = 0;
|
||||
}
|
||||
|
||||
if(pDesk->spwndTrack)
|
||||
{
|
||||
pDesk->htEx = hittest;
|
||||
}
|
||||
|
||||
msg->hwnd = UserHMGetHandle(pwndMsg);
|
||||
|
||||
#if 0
|
||||
|
|
|
@ -816,20 +816,6 @@ NtUserRealWaitMessageEx(
|
|||
return 0;
|
||||
}
|
||||
|
||||
BOOL
|
||||
APIENTRY
|
||||
NtUserRegisterUserApiHook(
|
||||
PUNICODE_STRING m_dllname1,
|
||||
PUNICODE_STRING m_funname1,
|
||||
DWORD dwUnknown3,
|
||||
DWORD dwUnknown4)
|
||||
{
|
||||
UserEnterExclusive();
|
||||
STUB;
|
||||
UserLeave();
|
||||
return 0;
|
||||
}
|
||||
|
||||
BOOL
|
||||
APIENTRY
|
||||
NtUserRegisterRawInputDevices(
|
||||
|
@ -963,14 +949,6 @@ NtUserPaintMenuBar(
|
|||
return 0;
|
||||
}
|
||||
|
||||
BOOL
|
||||
APIENTRY
|
||||
NtUserUnregisterUserApiHook(VOID)
|
||||
{
|
||||
STUB;
|
||||
return 0;
|
||||
}
|
||||
|
||||
BOOL
|
||||
APIENTRY
|
||||
NtUserGetLayeredWindowAttributes(
|
||||
|
|
|
@ -120,6 +120,9 @@ NtUserCallNoParam(DWORD Routine)
|
|||
case NOPARAM_ROUTINE_RELEASECAPTURE:
|
||||
RETURN( (DWORD_PTR)IntReleaseCapture());
|
||||
|
||||
case NOPARAM_ROUTINE_LOADUSERAPIHOOK:
|
||||
RETURN(UserLoadApiHook());
|
||||
|
||||
default:
|
||||
ERR("Calling invalid routine number 0x%x in NtUserCallNoParam\n", Routine);
|
||||
EngSetLastError(ERROR_INVALID_PARAMETER);
|
||||
|
|
|
@ -324,7 +324,7 @@ SystemTimerProc(HWND hwnd,
|
|||
if ( pDesk->dwDTFlags & DF_TME_HOVER &&
|
||||
pWnd == pDesk->spwndTrack )
|
||||
{
|
||||
Point = gpsi->ptCursor;
|
||||
Point = pWnd->head.pti->MessageQueue->MouseMoveMsg.pt;
|
||||
if ( RECTL_bPointInRect(&pDesk->rcMouseHover, Point.x, Point.y) )
|
||||
{
|
||||
if (pDesk->htEx == HTCLIENT) // In a client area.
|
||||
|
@ -345,10 +345,19 @@ SystemTimerProc(HWND hwnd,
|
|||
wParam = pDesk->htEx; // Need to support all HTXYZ hits.
|
||||
Msg = WM_NCMOUSEHOVER;
|
||||
}
|
||||
TRACE("Generating WM_NCMOUSEHOVER\n");
|
||||
UserPostMessage(hwnd, Msg, wParam, MAKELPARAM(Point.x, Point.y));
|
||||
pDesk->dwDTFlags &= ~DF_TME_HOVER;
|
||||
break; // Kill this timer.
|
||||
}
|
||||
else
|
||||
{
|
||||
RECTL_vSetRect(&pDesk->rcMouseHover,
|
||||
Point.x - gspv.iMouseHoverWidth / 2,
|
||||
Point.y - gspv.iMouseHoverHeight / 2,
|
||||
Point.x + gspv.iMouseHoverWidth / 2,
|
||||
Point.y + gspv.iMouseHoverHeight / 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
return; // Not this window so just return.
|
||||
|
|
|
@ -549,7 +549,7 @@ GreStretchBltMask(
|
|||
if (0 == WidthDest || 0 == HeightDest || 0 == WidthSrc || 0 == HeightSrc)
|
||||
{
|
||||
EngSetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (!hDCDest || (UsesSource && !hDCSrc) || (UsesMask && !hDCMask))
|
||||
|
|
Loading…
Reference in a new issue