I was experimenting on a simple window to gain insights into the creation process. And I noticed some strange messages. Some was received by WinProc exclusively, others only appeared in message loop (GetMessage), DispatchMessage probably filtered them (0x60)? Some was passed to DefWindowProc by the loop (like 0x31F).
I suspect that Unique WMs you can see in the bottom might be from some random processes or Windows. And WM_TIMER is not passed to DefWindowProc because Dispatch calls it's callback, instead.
But what are this strange undocumented Windows-area messages? It's hightly unlikely that it can be from some random process, as I didn't disable UIPI for them via filters. I still get them in Admin mode, so it's either some rouge Admin program, or more likely OS itself.
I know that Registered WMs are from 4t Tray Minimiser program I use, but when I unload it, the undocumented ones still come in.
As you can see, 0x60 is very often repeated on window focus changes... Also, what could that WM_TIMER be?
Related
I’m trying to write some Rust code that uses Windows.Web.UI.Interop.WebViewControl (which is a Universal Windows Platform out-of-process wrapper expressly designed so Win32 apps can use EdgeHTML), and it’s all compiling, but not working properly at runtime.
The relevant code boils down to this, using the winit, winapi and winrt crates:
use winit::os::windows::WindowExt;
use winit::{EventsLoop, WindowBuilder};
use winapi::winrt::roapi::{RoInitialize, RO_INIT_SINGLETHREADED};
use winapi::shared::winerror::S_OK;
use winrt::{RtDefaultConstructible, RtAsyncOperation};
use winrt::windows::foundation::Rect;
use winrt::windows::web::ui::interop::WebViewControlProcess;
fn main() {
assert!(unsafe { RoInitialize(RO_INIT_SINGLETHREADED) } == S_OK);
let mut events_loop = EventsLoop::new();
let window = WindowBuilder::new()
.build(&events_loop)
.unwrap();
WebViewControlProcess::new()
.create_web_view_control_async(
window.get_hwnd() as usize as i64,
Rect {
X: 0.0,
Y: 0.0,
Width: 800.0,
Height: 600.0,
},
)
.expect("Creation call failed")
.blocking_get()
.expect("Creation async task failed")
.expect("Creation produced None");
}
The WebViewControlProcess instantiation works, and the CreateWebViewControlAsync function does seem to care about the value it received as host_window_handle (pass it 0, or one off from the actual HWND value, and it complains). Yet the IAsyncOperation stays determinedly at AsyncStatus.Started (0), and so the blocking_get() call hangs indefinitely.
A full, runnable demonstration of the issue (with a bit more instrumentation).
I get the feeling that the WebViewControlProcess is at fault: its ProcessId is stuck at 0, and it doesn’t look to have spawned any subprocess. The ProcessExited event does not seem to be being fired (I attached something to it immediately after instantiation, is there opportunity for it to be fired before that?). Calling Terminate() fails as one might expect in such a situation, E_FAIL.
Have I missed some sort of initialization for using Windows.Web.UI.Interop? Or is there some other reason why it’s not working?
It turned out that the problem was threading-related: the winit crate was doing its event loop in a different thread, and I did not realise this; I had erroneously assumed winit to be a harmless abstraction, which it turned out not quite to be.
I discovered this when I tried minimising and porting a known-functioning C++ example, this time doing all the Win32 API calls manually rather than using winit, so that the translation was correct. I got it to work, and discovered this:
The IAsyncOperation is fulfilled in the event loop, deep inside a DispatchMessageW call. That is when the Completion handler is called. Thus, for the operation to complete, you must run an event loop on the same thread. (An event loop on another thread doesn’t do anything.) Otherwise, it stays in the Started state.
Fortunately, winit is already moving to a new event loop which operates in the same thread, with the Windows implementation having landed a few days ago; when I migrated my code to use the eventloop-2.0 branch of winit, and to using the Completed handler instead of blocking_get(), it all started working.
I shall clarify about the winrt crate’s blocking_get() call which would normally be the obvious solution while prototyping: you can’t use it in this case because it causes deadlock, since it blocks until the IAsyncOperation completes, but the IAsyncOperation will not complete until you process messages in the event loop (DispatchMessageW), which will never happen because you’re blocking the thread.
Try to initialize WebViewProcessControl with winrt::init_apartment(); And it may needs a single-threaded apartment(according to the this answer).
More attention on Microsoft Edge Developer Guide:
Lastly, power users might notice the apppearance of the Desktop App
Web Viewer (previously named Win32WebViewHost), an internal system app
representing the Win32 WebView, in the following places:
● In the Windows 10 Action Center. The source of these notifications
should be understood as from a WebView hosted from a Win32 app.
● In the device access settings UI
(Settings->Privacy->Camera/Location/Microphone). Disabling any of
these settings denies access from all WebViews hosted in Win32 apps.
The documentation for WM_NOTIFY is easy enough to find, however I'm finding a fair amount of sample code and articles that refer to WM_REFLECT_NOTIFY, for which I can't find any documentation.
What is WM_REFLECT_NOTIFY, where can I find the documentation for it and how is this message different from WM_NOTIFY?
Example references:
Flickering in listview with ownerdraw and virtualmode
ListViewSubItem.Bounds almost works
WM_REFLECT_NOTIFY is referred to as having value of 0x204E, that is 0x2000 + WM_NOTIFY. Typical use of message reflection is to send back notification to its origin so that supposedly subclassed control could handle notification itself.
Hence the knowledge you are possibly missing and looking documentation for is that the control sends WM_NOTIFY to its parent in a regular way. And the parent does SendMessage with the same message parameters back to the control using message number 0x2000 + original Msg. The meaning of the parameters wParam, lParam is supposed to be the same of original message (WM_NOTIFY in your case).
The constant 0x2000 might possibly vary from framework to framework or be otherwise private agreement between controls and hosting windows.
MFC and ActiveX controls, for instance, reflect WM_NOTIFY messages making them OCM_NOTIFY messages, where (olectl.h):
#define OCM_NOTIFY (OCM__BASE + WM_NOTIFY)
#define OCM__BASE (WM_USER+0x1c00)
and finally (winuser.h):
#define WM_USER 0x0400
That is, the OCM_NOTIFY is 0x204E, just as your WM_REFLECT_NOTIFY. The MSDN docs on those from here: Reflected Window Message IDs.
I have a Windows WinMain() window in which I write simple graphics -- merely LineTo() and FillRect(). The rectangles move around. After about an hour, the output that used o go to the main window, all of a sudden goes to the upper left corner of my screen -- as if client coordinates were being interpreted as screen coordinates. My GetDC()'s and ReleaseDC()'s seem to be balanced, and I even checked the return value from ReleaseDC(), make sure it is not 0 (per MSDN). Sometimes the output moves back to my main window. When I got to the debugger (VS 2010), my coordinates do not seem amiss--but output is going to the wrong place. I handle WM_PAINT, WM_CREATE, WM_TIMER, and a few others. I do not know how to debug this. Any help would be appreciated.
This has 'not checking return values' written all over it. Pretty crucial in raw Win32 programming, most every API function returns a boolean or a handle where FALSE or NULL indicates failure. GetLastError() provides the error code.
A cheap way to check for this without modifying code is by using the debugger to look at the EAX register value after the API call. A 0 indicates failure. In Visual Studio you can do so by using the #eax and #err pseudo variables in the Watch window, respectively the function return value and the GetLastError value.
This goes bad once Windows starts failing API calls, probably because of a resource leak. You can see it with TaskMgr.exe, Processes tab. View + Select Columns and tick Handles, USER objects and GDI objects. It is usually the latter, restoring the device context and releasing drawing objects is very easy to fumble. You don't have to wait until it fails, a steadily climbing number in one of those columns is the giveaway. It goes belly-up when the value hits 10,000
You must be calling GetDC(NULL) somewhere by mistake, which would get the DC for the entire desktop.
You could make all your GetDC calls call a wrapper function which asserts if the argument is NULL to help track this down:
#include <assert.h>
HDC GetDCAssert(HWND hWnd)
{
assert(hWnd);
return ::GetDC(hWnd);
}
Two questions.
1) I understand this must be an expected outcome but maybe someone can tell me what I'm doing wrong; I'm trying to subclass all window classes in a global hook and it works except that I'm not able to close shop as I should and when the program initially registering the hook unregisters the hook and exits, subclassed applications start crashing.
Here's how I'm trying to do it..
// stores original wndprocs. In the hook dll, outside the shared memory.
map<HWND, WNDPROC> origWndProcs;
// in an EnumWindows callback, executed for all HWND's, also in the hook dll (UWM_REMOVE_HOOK is a registered unique message)
SendMessageTimeout(hWnd, UWM_REMOVE_HOOK, 0, 0, SMTO_ABORTIFHUNG | SMTO_NORMAL, 15000, res);
// Still in the same hook, in the subclassing wndproc..
if (msg == UWM_REMOVE_HOOK) {
if (origWndProcs.find(hwnd) != origWndProcs.end()) {
SetWindowLongPtr(hwnd, GWL_WNDPROC, (LONG_PTR)origWndProcs[hwnd]);
}
}
// clears the hook..
__declspec(dllexport) BOOL ClearHooks(HWND hWnd) {
BOOL unhooked = UnhookWindowsHookEx(hook) &&
UnhookWindowsHookEx(kb_hook) &&
UnhookWindowsHookEx(mouse_hook) &&
UnhookWindowsHookEx(cbt_hook);
if(unhooked)
hWndServer = NULL;
return unhooked;
}
In DllMain I don't do anything on DLL_PROCESS_DETACH. Instead, ClearHooks() is called from the program originally registering the hooks and there only after the hook has sent a message signalling that it has executed the EnumWindows operation (restores original wndprocs, see above).
I subclass windows in a WndProc hook; all visible windows that receive a message and whose current wndproc is not the one in the dll, are subclassed.
Basically all (as far as I can tell) applications crash on exit despite the fact that windows do seem to get the wndproc set back to what it was when it was replaced. Anyone have a clue what I might be doing wrong?
2) I need this to intercept WM_MINMAXINFO and modify window maxsize whenever a window is maximized. Unfortunately I can't do this in the dll but I have to talk with a program to get the size info. So, what's the best way to talk to that window; I need it to pass back some info so I can modify the structure that came with the original WM_MINMAXINFO message. Will a structure in WM_COPYDATA preserve it's data until the call to SendMessageTimeout returns?
Thanks
There are plenty of pain points here. You assume that no other code will subclass the window. And that such code will un-subclass it in the right order. There is no right order, your hooking is quite asynchronous from the program's execution.
But, the workaround is simple enough. You are already hooking with SetWindowsHookEx, might as well do one more. WH_CALLWNDPROC or WH_CALLWNDPROCRET, depending on what you want to do.
I'm dealing with an anti-debug application which disables EXCEPTION_DEBUG_EVENT from being passed to my debugger, instead it executes its SEH and UnhandledExceptionFilters.
I tried it with 3 different debuggers (even selfmade one)
My debugger receives other debug events like LOAD_DLL, CREATE_THREAD etc
Exceptions are not passed when first chance debugging aswell as last chance
Breakpoint events of my own created threads get passed to the debugger, so the anti-debug method must be thread specific and may be a modification of the ThreadInformationBlock
There's no kernel mode access
So how can it be possible in usermode to pass EXCEPTION_DEBUG_EVENT (for only one thread, not affecting the whole process) ?
Well.. the solution is rather simple:
call
NtSetInformationThread(
IN HANDLE ThreadHandle,
IN THREAD_INFORMATION_CLASS ThreadInformationClass,
IN PVOID ThreadInformation,
IN ULONG ThreadInformationLength );
with ThreadHideFromDebugger ( 0x11 ) as ThreadInformationClass.