How does PeekMessage really work? |
AliR \(VC++ MVP\) posted on Monday, September 08, 2008 11:38 AM
|
See Below.....
PeekMessage retrieves a message from the calling thread's message queue, it
doesn't care if was sent view SendMessage or PostMessage. PeekMessage does
not process the message, that's job of the winproc to process messages (this
happens during the call to DispatchMessage), PeekMessage simply returns the
message that is at the top of the queue.
PeekMessage returns one message at a time. Again it does not process message
simply returns a message. Not that wRemoveMsg parameter let you tell it to
either remove the message if you are calling PeekMessage to process the
message after you receive it, or to leave it in the queue, if you are
calling PeekMessage just out of curiousity and won't really be processing
the message. See GetMessage if you always want to remove the message from
the queue.
wMsgFilterMin and wMsgFilterMax is used to only receive back message in the
specified range. And simply won't return any messages outside of that
range.
I have never used these before, but the docs say that they filter message by
type. Kind of like FilterMin and FilterMax
I don't understand questions 5, and 6
PM_NOYIELD will make user that no other threads are released during the call
to PeekMessage. Explaining this one will take a couple of pages. each
thread in your application gets a time slice of the processer. So a thread
will run for a while and when it becomes idle the processor is given to
another thread in your app, and so far and so forth. Callling PeekMessage
might cause another thread to take over momentarily, PM_NOYIELD will pervent
that from happening.
AliR. |
 |
|
My bad, I keep forgetting that. |
AliR \(VC++ MVP\) posted on Monday, September 08, 2008 2:48 PM
|
My bad, I keep forgetting that.
BTW, here is a link that explains all of this in more detail. Also some
difference between PeekMessage and GetMessage:
http://msdn.microsoft.com/en-us/library/ms644928(VS.85).aspx
AliR.
See in-line, below ...
This incorrectly infers that a message sent by SendMessage somehow
ends up in the message queue. It doesn't. A message sent by
SendMessage is a non-queued message that does not end up in the
message queue, and is not retrievable by a call to PeekMessage (or a
call to GetMessage).
A message sent by SendMessage calls the target window's WinProc
directly, without going through the message queue. If the thread
calling SendMessage is the same thread as the target window, then a
call to SendMessage is very much like a simple function call, that
calls the WinProc for the target window. If the are in different
threads, then the process is more complicated, but the end result is
the same in that sent messages are non-queued messages that bypass the
message queue and do not somehow end up in the message queue.
On the other hand, messages posted by PostMessage end up in the
message queue, together with other messages that get routed through
the message queue (like timer messages, paint messages, system
messages, keyboard messages, etc.) It's only if the message resides
in the message queue that the message can be retrived by calls to
PeekMessage or GetMessages.
As one explanation, see Paul DiLascia's C++ Q&A column from December
2000, "Sending Messages in Windows" at
http://msdn.microsoft.com/en-us/magazine/cc301431.aspx
PeekMessage will not process *any* sent messages, for the reason that
messages sent by using SendMessage will not go into the message queue. |
 |
|
How does PeekMessage really work? |
DenisAdamchu posted on Monday, September 08, 2008 4:53 PM
|
Guys, I'm totally confused now.
At http://msdn.microsoft.com/en-us/library/ms644943(VS.85).aspx
I see the following in the Remarks section:
messages sent to windows owned by the calling thread using the SendMessage,
SendMessageCallback, SendMessageTimeout, or SendNotifyMessage function. Then
the first queued message that matches the specified filter is retrieved. The
system may also process internal events."
Doesn't it mean that PeekMessage DO process sent messages?
Malachy, you insist that PeekMessage() does not process sent messages and
retrieves only posted messages from the message queue (I understand that sent
messages go to "another place" anyway). Could you please tell me what is the
purpose of the PM_QS_SENDMESSAGE flag?
Concerning PM_NOYIELD. AliR, do you mean that this flag prevents the context
switching? I thought its impossible.
Thanks. |
 |
|
How does PeekMessage really work? |
AliR \(VC++ MVP\) posted on Monday, September 08, 2008 5:02 PM
|
Thats what the doc says:
PM_REMOVE. This flag prevents the system from releasing any thread that is
waiting for the caller to go idle (see WaitForInputIdle)." |
 |
|
How does PeekMessage really work? |
Malachy Moses posted on Monday, September 08, 2008 8:33 PM
|
See in-line, below ...
it
does
his
he
This incorrectly infers that a message sent by SendMessage somehow
ends up in the message queue. It doesn't. A message sent by
SendMessage is a non-queued message that does not end up in the
message queue, and is not retrievable by a call to PeekMessage (or a
call to GetMessage).
A message sent by SendMessage calls the target window's WinProc
directly, without going through the message queue. If the thread
calling SendMessage is the same thread as the target window, then a
call to SendMessage is very much like a simple function call, that
calls the WinProc for the target window. If the are in different
threads, then the process is more complicated, but the end result is
the same in that sent messages are non-queued messages that bypass the
message queue and do not somehow end up in the message queue.
On the other hand, messages posted by PostMessage end up in the
message queue, together with other messages that get routed through
the message queue (like timer messages, paint messages, system
messages, keyboard messages, etc.) It's only if the message resides
in the message queue that the message can be retrived by calls to
PeekMessage or GetMessages.
As one explanation, see Paul DiLascia's C++ Q&A column from December
2000, "Sending Messages in Windows" at http://msdn.microsoft.com/en-us/maga=
zine/cc301431.aspx
age
t to
rom
PeekMessage will not process *any* sent messages, for the reason that
messages sent by using SendMessage will not go into the message queue. |
 |
|
How does PeekMessage really work? |
Malachy Moses posted on Monday, September 08, 2008 8:33 PM
|
See in-line below ....
On Sep 8, 1:53=A0pm, Denis Adamchuk
is,
e,
hen
The
No it doesn't mean that. Read the documentation again carefully. The
system *delivers* these messages *during* the call to PeekMessage.
Thus, before PeekMessage returns, all sent messages are dispatched
automatically. You don't get these messages back as a result from the
call to PeekMessage. In fact, the documentation explicitly states
that such messages are "nonqueued".
This is the "more complicated" part that I mentioned above, and refers
to a situation where SendMessage has been called from a thread
different from the thread that manages the window's message queue.
Such messages are accumulated in a "separate place" (using the words
of Raymond Chen) that is different from the message queue. Since they
are not queued messages, they must be processed separately from the
message queue. The timing at which they are processed is a priority
timing, ahead of messages in the queue. Thus, when the thread that
manages the window's queue is re-awakened, as soon as it calls a
function like PeekMessage or GetMessage, any messages that are in the
which queued messages are returned for manual dispatching by your
program (i.e., in your program's call to DispatchMessage).
For more information, read this thread from Raymond Chen's blog Old
New Thing: "The various ways of sending a message" at
http://blogs.msdn.com/oldnewthing/archive/2004/11/19/266664.aspx .
The comments are where the meat of the information resides. For
example, selected and re-ordered comments tell us the following:
thread, the window procedure is called immediately by SendMessage().
are posting from *this* thread or another thread, the messages go into
don't technically go into "the message queue" but rather a "separate
place".
directly or indirectly looks at this "separate place" (such as
PeekMessage or GetMessage), the system first checks if there are any
messages in the "separate place" and dispatches them all automatically
(i.e., automatically calls the window procedure). The system then
checks "the message queue" and returns the first matching message."
sent
the
I have never used PM_QS_SENDMESSAGE, and can't talk definitively.
That was one of the questions in the blog I linked to, and the
question remained unanswered. However, according to the documentation
that you linked to, it apparently "Process[es] all sent messages",
which fits into the explanation quoted above. |
 |
|
[... |
Bogdan posted on Tuesday, September 09, 2008 9:39 AM
|
[...]
Another thing worth noting in this case is that, in some cases, message
queue might be flushed (e.g. when you destroy COM objects) so in practice
you have posted messages delivered to your window as if they were sent.
Bogdan |
 |
|
Malachy, thanks for your explanation. |
DenisAdamchu posted on Tuesday, September 09, 2008 12:39 PM
|
Malachy, thanks for your explanation.
I've carefully read the article by Raymond.
In the OldNewThing discussion I found a similar question about inter-thread
sent messages which are kept in a "separate place". This one is very
important for me now but it is still unanswered:
dispatch them? I would like to be able to filter out, for example, Shatter
attacks. "
In other words I would like to disable sent messages to be processed
(dispatched) within PeekMessage or allow it only for group of messages
(filter by ID).
I suppose the root cause of my confusion is the PM_QS_SENDMESSAGE.
I still don't understand how this flag affect the PeekMessage() execution.
In my application PeekMessage() delivers sent messages to the WndProc in the
both cases:
Moreover, when I set all PM_QS_* flags except PM_QS_SENDMESSAGE
PeekMessage() does the same.
Don't you know any newsgroup where could I address my question?
May be microsoft.public.vc.mfc is not the appropriate one but my post to the
microsoft.public.win32.programmer.ui didn't recieve any replies at all.
Thanks a lot! |
 |
|
How does PeekMessage really work? |
Doug Harrison [MVP] posted on Tuesday, September 09, 2008 4:59 PM
|
On Tue, 9 Sep 2008 09:39:01 -0700, Denis Adamchuk
I think those are two different questions. I don't know how to accomplish
the former (maybe a message hook?), but you're supposed to be able to
accomplish the latter with PeekMessage. Note that it won't help with MFC's
or Windows' internal GetMessage loops, use of WaitMessage, etc.
Yeah, the documentation is confusing, because the default is to process
sent messages! It may be that specifying nothing processes everything,
while if you specify PM_QS_POSTMESSAGE, you will suppress the processing of
sent messages. Are you sure that:
::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE | PM_QS_POSTMESSAGE);
processes pending interthread sent messages?
--
Doug Harrison
Visual C++ MVP |
 |
|
This is different thing. |
Alexander Grigoriev posted on Tuesday, September 09, 2008 11:28 PM
|
This is different thing. WaitForInputIdle waits for a special event
associated with a process, which is set on any GetMessage-type call. THis
flag makes sure the event will not be set at PeekMessage, |
 |
|
HiI'm going to describe briefly my situation and to show you a stack. |
DenisAdamchu posted on Wednesday, September 10, 2008 5:17 AM
|
Hi
I'm going to describe briefly my situation and to show you a stack.
I have two threads and in the second thread I create a dialog. Parent window
for the dialog belongs to the first thread.
Collaboration between threads is based on a custom message queue which is
handled insided WM_TIMER message handler. It doesn't matter essentially.
The first thread performs a kind of "synchronous call":
- It places a request to the message queue of the 2nd thread;
- and waits for an event to be signaled when a dialog is created.
While it's waiting I have to pump the first thread message queue to avoid
hang up. I'm trying to do it by means of ::PeekMessage(&msg, NULL, 0, 0,
PM_NOREMOVE | PM_QS_POSTMESSAGE) and get the following stack:
Second thread:
ntdll.dll!_KiFastSystemCallRet@0()
user32.dll!_NtUserCreateWindowEx@60()
user32.dll!_InternalCreateDialog@28()
user32.dll!_CreateDialogIndirectParamAorW@24()
user32.dll!_CreateDialogIndirectParamA@20()
First thread:
Primary.exe!CWnd::OnParentNotify( <cut arguments> )
Primary.exe!CWnd::OnWndMsg( <cut arguments> )
Primary.exe!CWnd::WindowProc( <cut arguments> )
Primary.exe!AfxCallWndProc( <cut arguments> )
Primary.exe!AfxWndProc( <cut arguments> )
user32.dll!_InternalCallWinProc@20()
user32.dll!_UserCallWinProcCheckWow@32()
user32.dll!_DispatchClientMessage@20()
user32.dll!___fnDWORD@4()
ntdll.dll!_KiUserCallbackDispatcher@12()
user32.dll!_NtUserPeekMessage@20()
user32.dll!_PeekMessageA@20()
Support.dll!CTransportManager::pumpWindowsMessages()
So WM_PARENTNOTIFY is sent by CreateDialogIndirect and is dispatched by
PeekMessage... |
 |
|
Thanks for your links! |
DenisAdamchu posted on Wednesday, September 10, 2008 5:26 AM
|
Thanks for your links!
It's a good idea to analyze messages in WndProc or have a hook, say
WH_CALLWNDPROC for this purpose. But unfortunately it's too late to analyze a
message when it's already retrieved from the send-message queue because if I
don't want to handle it NOW - I cannot just return it to the queue, its
impossible. |
 |
|
How does PeekMessage really work? |
Malachy Moses posted on Friday, September 12, 2008 1:38 AM
|
On Sep 9, 9:39=A0am, Denis Adamchuk
ad
r
I don't have an answer for you, but I have some more information.
First, there might be a real name for the "separate place" mentioned
in Raymond Chen's blog. The name might be "send-message queue", and
the thread that sent the message might have a correspondingly-named
from the so-called "message queue" that is serviced by GetMessage and
PeekMessage. Here are two links that talk about these topics, and
about the algorithm that the Windows system uses to service these
three queues.
HTML/ch26d.htm
http://ymei.freeshell.org/gopher/Book/Programming%20Applications%20for%20MS=
%20Windows%204thed/ch26e.htm
Second, with respect to protection against shatter attacks, I think
the right place to do this is inside the WinProc itself. The WinProc
will get all messages, regardless of how they are sent/posted. Inside
the WinProc, you sill need to determine the origin of the message
(thread ID, maybe). Windows must somehow know of the origin, since
Windows needs to know where to send the LRESULT of your WinProc. I
don't know how to get the originating thread ID, however. It would be
nice if the API had a GetOriginOfMSg function, or if the MSG structure
included this information, but it doesn't. You probably will need to
look to undocumented Windows internals. Probably, the internal
structure for MSG must have some sort of identifier on where to send
the LRESULT, so that it ends up in the correct thread's reply-message
queue (per new terminology above).
Third, when I am trying to figure out how Windows works internally, I
often look at the source code for the WINE windows emulator. This
often provides good hints to me on what Windows is probably doing. In
your case, the files you might want to start with are windows/queue.c
and windows/message.c . See the explanation of the WINE messaging sub-
system, at the bottom of this link:
uide/c3764
Good luck. If you find an answer, please let us know. |
 |
|