Hi,
There is a problem with explorer managing the desktop and the sending of PAINT messages. I've narrowed it down to the following area. In dlls/user/message.c wait_message_reply(), if QS_PAINT are the bits we get, and we call MsgWaitForMultipleObjectsEx, it seems to block the process indefinitely. Should another process be replying here? I decided to make the function return if we get QS_PAINT. Now my app doesn't hang and paints properly. Any ideas what I should be looking for or know?
Note the call MsgWaitForMultipleObjectsEx waits for sent messages. Changing it makes no difference.
Thanks, Jesse
--- wine-current/dlls/user/message.c 2006-03-30 19:37:06.000000000 -0700 +++ wine/dlls/user/message.c 2006-04-09 18:47:14.000000000 -0700 @@ -2136,7 +2136,7 @@ static void wait_message_reply( UINT fla } SERVER_END_REQ;
- if (wake_bits & QS_SMRESULT) return; /* got a result */ + if (wake_bits & (QS_SMRESULT | QS_PAINT)) return; /* got a result */ if (wake_bits & QS_SENDMESSAGE) { /* Process the sent message immediately */
Jesse Allen the3dfxdude@gmail.com writes:
There is a problem with explorer managing the desktop and the sending of PAINT messages. I've narrowed it down to the following area. In dlls/user/message.c wait_message_reply(), if QS_PAINT are the bits we get, and we call MsgWaitForMultipleObjectsEx, it seems to block the process indefinitely. Should another process be replying here? I decided to make the function return if we get QS_PAINT. Now my app doesn't hang and paints properly. Any ideas what I should be looking for or know?
If we are in wait_message_reply the other process is supposed to reply. You should check what message this is, and why it doesn't get replied to.
On 4/10/06, Alexandre Julliard julliard@winehq.org wrote:
Jesse Allen the3dfxdude@gmail.com writes:
There is a problem with explorer managing the desktop and the sending of PAINT messages. I've narrowed it down to the following area. In dlls/user/message.c wait_message_reply(), if QS_PAINT are the bits we get, and we call MsgWaitForMultipleObjectsEx, it seems to block the process indefinitely. Should another process be replying here? I decided to make the function return if we get QS_PAINT. Now my app doesn't hang and paints properly. Any ideas what I should be looking for or know?
If we are in wait_message_reply the other process is supposed to reply. You should check what message this is, and why it doesn't get replied to.
This is what the app, Warcraft III.exe is doing ----- Start of process 0x8:
Creates 16x16 window, WS_POPUP style in thread 0x9, 10024 (Root Window) ShowWindow 10024 In ShowWindow .... set_active_window Creates a new thread 0xc Starts process 0xe CreateEvent "WARCRAFT_III_OK" and waits on read pipe for event
In thread 0xc: Creates 500x400 window, WS_EX_TOOLWINDOW, 10026 (Splash Screen) ShowWindow, 10026 In ShowWindow....hits set_active_window. Previous active window is 10024, SendMessage WM_NCACTIVATE to 10024 (thread 0x9). Waits for reply.
In process 0xe using war3.exe: Executes some copy protection code Creates a window 10028 (Game Window -- Not visible) Waits for process 0x8 to close ----
Both thread 0x9 and thread 0xc are waiting for receiving something different from each other at the same time. This will never work. Before explorer managed the desktop, thread 0xc would not send WM_NCACTIVATE, and when it proceeded, it would cause the "WARCRAFT_III_OK" event and thread 0x9 would continue normally... painting etc. The purpose of 0x9 waiting for the event is to see whether the copy protection threads succeeds normally. If they do not, it will show a messagebox. But the copy protection threads do succeed, we are just not passing messages properly at this point.
I tried doing something in set_active_window when getting a window that is WS_POPUP. Like returning early with TRUE or FALSE, or just avoiding the server call or SendMessage WM_NCACTIVATE. For the most part the app would no longer hang, but one of three things would happen, the splash screen would not paint, or the game window would not paint, or both will paint but the game window would not get input focus.
The backtrace of thread 0xc at SendMessage is still at ftp://resnet.dnip.net/ShowWindowProblem.txt
Jesse
"Jesse Allen" the3dfxdude@gmail.com writes:
Start of process 0x8:
Creates 16x16 window, WS_POPUP style in thread 0x9, 10024 (Root Window) ShowWindow 10024 In ShowWindow .... set_active_window Creates a new thread 0xc Starts process 0xe CreateEvent "WARCRAFT_III_OK" and waits on read pipe for event
Is that a WaitForxxx or a MsgWaitForxxx?
On 4/11/06, Alexandre Julliard julliard@winehq.org wrote:
"Jesse Allen" the3dfxdude@gmail.com writes:
Start of process 0x8:
Creates 16x16 window, WS_POPUP style in thread 0x9, 10024 (Root Window) ShowWindow 10024 In ShowWindow .... set_active_window Creates a new thread 0xc Starts process 0xe CreateEvent "WARCRAFT_III_OK" and waits on read pipe for event
Is that a WaitForxxx or a MsgWaitForxxx?
WaitForSingleObject in kernel32. The read call is in wait_reply of dlls/ntdll/thread.c and that is where that thread gets stuck.
"Jesse Allen" the3dfxdude@gmail.com writes:
WaitForSingleObject in kernel32. The read call is in wait_reply of dlls/ntdll/thread.c and that is where that thread gets stuck.
Does this help?
diff --git a/server/window.c b/server/window.c index 8254793..5ceab49 100644 --- a/server/window.c +++ b/server/window.c @@ -426,7 +426,7 @@ static struct window *create_window( str }
/* if parent belongs to a different thread, attach the two threads */ - if (parent && parent->thread && parent->thread != current) + if (parent && parent->thread && parent->thread != current && !is_desktop_window(parent)) { if (!attach_thread_input( current, parent->thread )) goto failed; }
On 4/12/06, Alexandre Julliard julliard@winehq.org wrote:
"Jesse Allen" the3dfxdude@gmail.com writes:
WaitForSingleObject in kernel32. The read call is in wait_reply of dlls/ntdll/thread.c and that is where that thread gets stuck.
Does this help?
diff --git a/server/window.c b/server/window.c index 8254793..5ceab49 100644 --- a/server/window.c +++ b/server/window.c @@ -426,7 +426,7 @@ static struct window *create_window( str }
/* if parent belongs to a different thread, attach the two threads */
- if (parent && parent->thread && parent->thread != current)
- if (parent && parent->thread && parent->thread != current && !is_desktop_window(parent)) { if (!attach_thread_input( current, parent->thread )) goto failed; }
-- Alexandre Julliard julliard@winehq.org
Yes. Both app and test app ok. That explains it too. =)
On 4/11/06, Alexandre Julliard julliard@winehq.org wrote:
"Jesse Allen" the3dfxdude@gmail.com writes:
Start of process 0x8:
Creates 16x16 window, WS_POPUP style in thread 0x9, 10024 (Root Window) ShowWindow 10024 In ShowWindow .... set_active_window Creates a new thread 0xc Starts process 0xe CreateEvent "WARCRAFT_III_OK" and waits on read pipe for event
Is that a WaitForxxx or a MsgWaitForxxx?
-- Alexandre Julliard julliard@winehq.org
Ok, I'm not sure about it waiting for that event. The call is 0009:Call kernel32.WaitForSingleObject(00000048,ffffffff) ret=00401c00
Anyway I wrote a test app, showwindow.c. It is available on ftp://resnet.dnip.net . The relay log is there too. The test app tries to mimic the calls I see. I tested under wine and it does hang. I will see about windows.
BTW, I replaced the SendMessage in set_active_window with SendMessageTimeout where ever thread 0xc would hang sending to 0x9 and doing that would make it work normally, but I don't know if that is what you want and I want to see what windows does first.