http://bugs.winehq.org/show_bug.cgi?id=5402
--- Comment #13 from Anastasius Focht focht@gmx.net 2007-11-14 08:03:52 --- Created an attachment (id=9158) --> (http://bugs.winehq.org/attachment.cgi?id=9158) WINEDEBUG=+tid,+seh,+server to show active window problem
Hello,
upon request I investigated this bug .. seems indeed an oversight/bug in wine server ;-)
--- snip --- .. 0009:Call user32.GetClassInfoA(00400000,00130e90 "Afx:400000:b:10de:458:0",0034dfb4) ret=73d3b9c2 0009:Ret user32.GetClassInfoA() retval=00000000 ret=73d3b9c2 0009:Call user32.RegisterClassA(0034e004) ret=73d3b9cd 0009:Ret user32.RegisterClassA() retval=0000c044 ret=73d3b9cd .. 0009:Call user32.CreateWindowExA(00000000,001572b8 "Afx:400000:b:10de:458:0",00000000,50000000,00000000,00000000,00000000,00000000,00010032,000003ee,00400000,00000000) ret=73d3bba4 0009:Call winex11.drv.CreateWindow(00010034,0034de94,00000000) ret=604d80e7 .. 0009:Ret winex11.drv.ShowWindow() retval=00000000 ret=604db9ac 0009:Ret user32.CreateWindowExA() retval=00010034 ret=73d3bba4 .. 0009:Call user32.GetActiveWindow() ret=73d31314 0009:Ret user32.GetActiveWindow() retval=00000000 ret=73d31314 .. 0009:trace:seh:raise_exception code=c0000005 flags=0 addr=0x42e86e 0009:trace:seh:raise_exception info[0]=00000000 0009:trace:seh:raise_exception info[1]=00000138 0009:trace:seh:raise_exception eax=00000000 ebx=0034e098 ecx=0034e058 edx=00130f58 esi=0016a848 edi=0016a5b8 0009:trace:seh:raise_exception ebp=00000000 esp=0034e040 cs=0073 ds=007b es=007b fs=0033 gs=003b flags=00210246 --- snip ---
Estimated application call sequence (MFC based, dynamically linked), made up from debugging/disassembly:
--- snip app pseudo code --- .. AfxRegisterWndClass( ..) CWnd::CreateWindow( ..) .. CWinThread* pThread = AfxGetThread(); CWnd* pMainWnd = pThread->GetMainWnd(); .. pMainWnd->xxx *boom*
--- snip app pseudo code ---
MFC's CWinThread::GetMainWnd() tries to find associated main window for the thread object by looking at class member data first (in place active or main window members). If none is found (!= NULL) it calls user32.GetActiveWindow().
In windows, the newly created window handle is returned. Wine doesn't find an active window handle for the thread (user32.GetActiveWindow() retval=00000000) which leads to exception when MFC tries to dereference member data.
GetActiveWindow() -> get_thread_input (wine server)
--- snip --- server/queue.c:get_thread_input():
thread->queue -> thread->queue->input if (input) { reply->focus = input->focus; reply->capture = input->capture; reply->active = input->active; .. }
--- snip ---
The input->active member is NULL at this point - of course, no one made window active yet by explicit call.
I worked around by associating the newly created window handle to current thread queue -> input-> active in server window.c:create_window. Of course only if there was no previous active window.
E.g. something like this:
--- snip server/window.c:create_window() --- /* if parent belongs to a different thread and the window isn't */ /* top-level, attach the two threads */ if (parent && parent->thread && parent->thread != current && !is_desktop_window(parent)) { if (!attach_thread_input( current, parent->thread )) goto failed; } else /* otherwise just make sure that the thread has a message queue */ { if (!current->queue && !init_thread_queue( current)) goto failed; /* helper in queue.c which sets input->active member if none set yet) */ set_active_window( current, win->handle); } --- snip server/window.c:create_window() ---
Now MFC/app seems to be happy. I omitted a patch here because AJ probably comes up with cleaner solution - just to show the general problem/direction ;-)
I attached a server trace showing the thread queue input data members after window creation.
Regards