I have a sample of code taken from Registering for Device Notification to detect if a USB device is removed. This code uses the Win32 API and I have built and test it with success.
When I try to integrate this functionality into a QObject
-derived class, I'm getting a crash in the MessagePump()
method:
void QObjectDerivedClass::MessagePump() {
MSG message;
int retVal;
if (!m_hWnd) {
return;
}
qDebug() << Q_FUNC_INFO;
// Get all messages for any window that belongs to this thread,
// without any filtering. Potential optimization could be
// obtained via use of filter values if desired.
while ((retVal = GetMessage(&message, m_hWnd,
MSG_FILTER_MIN, MSG_FILTER_MAX)) != 0) {
if (retVal == -1) {
break;
} else {
TranslateMessage(&message);
DispatchMessage(&message);
}
}
}
As you can imagine, I have to modify the WndProc()
callback in the example to use a static member for this class and satisfy WNDCLASS
object as follow:
BOOL QObjectDerivedClass::InitWindowClass() {
WNDCLASSEX wndClass;/* = {0};*/
wndClass.cbSize = sizeof(WNDCLASSEX);
wndClass.style = 0;
wndClass.hInstance = reinterpret_cast<HINSTANCE>(GetModuleHandle(0));
// WndProcThunk is an static member of QObjectDerivedClass
wndClass.lpfnWndProc = reinterpret_cast<WNDPROC>(WndProcThunk);
wndClass.cbClsExtra = 0;
wndClass.cbWndExtra = 0;
wndClass.hIcon = NULL;
wndClass.hIconSm = NULL;
wndClass.hbrBackground = NULL;
wndClass.hCursor = NULL;
wndClass.lpszClassName = WND_CLASS_NAME;
wndClass.lpszMenuName = NULL;
if (!RegisterClassEx(&wndClass)) {
qDebug() << Q_FUNC_INFO << "Unable to register window class. Error:"
<< QString::number(GetLastError());
return FALSE;
}
m_instance = wndClass.hInstance;
return TRUE;
}
The call stack when the application crashes is:
1 0xd26128 2 SetManipulationInputTarget USER32 0x7709d2b3 3 DispatchMessageW USER32 0x7707e88a 4 DispatchMessageW USER32 0x7707e4c0 5 RealGetWindowClassW USER32 0x7708a64f 6 KiUserCallbackDispatcher ntdll 0x772e08c6 7 QObjectDerivedClass::MessagePump qobjectderived.cpp 165 0xa52e88 8 QObjectDerivedClass::Start qobjectderived.cpp 346 0xa52bc2 9 wWinMain main.cpp 259 0xa525ff 10 invoke_main exe_common.inl 118 0xa5516e 11 __scrt_common_main_seh exe_common.inl 253 0xa54fd0 12 __scrt_common_main exe_common.inl 296 0xa54e6d 13 wWinMainCRTStartup exe_wwinmain.cpp 17 0xa55188 14 BaseThreadInitThunk KERNEL32 0x73d862c4 15 RtlSubscribeWnfStateChangeNotification ntdll 0x772d0fd9 16 RtlSubscribeWnfStateChangeNotification ntdll 0x772d0fa4
Any idea how to solve this crash?
EDIT: Posted standard output:
int __stdcall wWinMain(struct HINSTANCE__ *,struct HINSTANCE__ *,wchar_t *,int) int __stdcall QObjectDerivedClass::WndProcThunk(struct HWND__ *,unsigned int,unsigned int,long) int __stdcall QObjectDerivedClass::WndProcThunk(struct HWND__ *,unsigned int,unsigned int,long) int __stdcall QObjectDerivedClass::WndProcThunk(struct HWND__ *,unsigned int,unsigned int,long) int __stdcall QObjectDerivedClass::WndProcThunk(struct HWND__ *,unsigned int,unsigned int,long) void __thiscall QObjectDerivedClass::MessagePump(void)
QObjectDerivedClass
instance being destroyed by some other event that it itself pumped, and crashing when returning fromMessagePump
the first time that it happens to try to access any of its fields. It's a classic problem that arises all the time when mixing code-modal logic with non-UI-modal dialogs, I expect this to be some variation over this theme. – Matteo Italia