Reputation: 15301
I'm trying to get Pointer Win32 messages of a specific window, by a hook on WH_CALLWNDPROC
, WH_CALLWNDPROCRET
and WH_GETMESSAGE
.
I use SetWindowsHookEx
in a c++ dll to hook and receive messages.
unsigned long processID = 0;
unsigned long threadID = GetWindowThreadProcessId(hWnd, &processID);
g_hhkGetMsg = SetWindowsHookEx(WH_GETMESSAGE,
GetMsgProc,
g_hinstDLL,
threadID);
This works for many windows, but not for CoreWindow
of UWP windows.
Each UWP app window has a structure like this:
Hooking to ApplicationFrameWindow works correctly, but hooking to Windows.UI.Core.CoreWindow
does not work. (SetWindowsHookEx
shows success, but I don't get any messages in the callback)
However, Spy++ is able to capture the messages from the CoreWindow
. (The CoreWindow
receives WM_POINTER messages, so I need to subscribe to that window)
Thinking the issue might be on my code, I also tried the open source tool MyLiteSpy to see if that can capture messages from the CoreWindow. It can't capture anything, just like my sample code. (But MyLiteSpy is able to get messages from ApplicationFrameWindow of the same UWP app, and so can my code and Spy++)
Interestingly, this (old) blog post about Spy++ says that they use the same three hooks as me and MyLiteSpy, but it's getting messages that my code can't receive.
What is the difference here? Any idea why this is happening?
(Is Spy++ using hooks other than the three mentioned? The blog post is written in 2007, so things might have changed)
Upvotes: 3
Views: 2575
Reputation: 33706
windows of class Windows.UI.Core.CoreWindow is usually immersive windows. for be able enumerate such, top level, windows, we need have disableWindowFiltering in manifest. it disables window filtering so you can enumerate (via EnumWindows
) immersive windows from the desktop. but say direct call to FindWindowW(L"Windows.UI.Core.CoreWindow", L"Start");
- not fail even without disableWindowFiltering in manifest. however this part is only related to visibility immersive windows, via EnumWindows
, for your application.
another task set WH_GETMESSAGE
hook for such windows. problem here that this windows usually belong to Windows Store app (AppContainer ) process.
Windows Store app development: If dwThreadId is zero, then window hook DLLs are not loaded in-process for the Windows Store app processes and the Windows Runtime broker process unless they are installed by either UIAccess processes (accessibility tools).
so we need have or uiAccess
set to true in manifest (say <requestedExecutionLevel level="requireAdministrator" uiAccess="true" />
) or not 0 for dwThreadId
in call SetWindowsHookEx
. the dwThreadId
we can got via GetWindowThreadProcessId
the WH_GETMESSAGE
hook is always in process hook. so if we call it for another process - hook procedure must be located in dll, which will be loaded to target process. and here is main problem - how load dll to Windows Store app (AppContainer ) process.
i check this with self simply dll - try set hook for Windows.UI.Core.CoreWindow::Calculator
window. the call for SetWindowsHookEx(WH_GETMESSAGE, ..)
is ok, and in Calculator.exe called LoadLibraryExW
for my dll, but this call fail inside NtQueryAttributesFile
with error STATUS_ACCESS_DENIED
. ok, Appcontainer is very restricted process, so i try change security descriptor on my dll. set it to "D:P(A;;FA;;;BA)(A;;FXFR;;;WD)(A;;FXFR;;;AC)S:P(ML;;NW;;;LW)"
(give full access to Builtin (local ) administrators and read-execute access to all applications running in an app package context (SDDL_ALL_APP_PACKAGES
- "AC"
) and Everyone ("WD"
). with this LoadLibraryExW
go forward, but anyway fail in call ZwCreateSection
for my DLL with code STATUS_SYSTEM_NEEDS_REMEDIATION
(C000047EL
- An error in a system binary was detected) after which is LdrAppxHandleIntegrityFailure
called (exported function from ntdll.dll)
so for load DLL to Windows Store app (Appcontainer) it must be signed. from kernel side call-stack is next
CI!KappxpNotifyNonPackagedFile
CI!KappxNotifyIntegrityFailureInPackagedProcess
CI!CipReportAndReprieveUMCIFailure
CI!CiValidateImageHeader
nt!SeValidateImageHeader
nt!MiValidateSectionCreate
nt!MiCreateNewSection
nt!MiCreateImageOrDataSection
nt!MiCreateSection
interesting that if check fail CI.DLL inside KappxpNotifyNonPackagedFile
write file name and hash to registry under HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\AppModel\StateChange
- BinaryName
(REG_SZ
) and BinaryHash
(REG_BINARY
)
in case Spyxx - it use signed dll - spyxxhk[_amd64].dll - this dll (if allow all app packages access to it) is loaded to process ok. so potentially Spy++ can collect messages from Appcontainer apps too. but in my research Spy++ call SetWindowsHookExW
at begin with dwThreadId
set to zero. as result spyxxhk[_amd64].dll will be not injected to Windows Store apps. need every time use not 0 dwThreadId and have special security descriptor on dll.
Upvotes: 6