C++/VB - RPC_E_CANTCALLOUT_ININPUTSYNCCALL

Asked By domehead100
05-Nov-09 07:40 PM
I am getting this error (RPC_E_CANTCALLOUT_ININPUTSYNCCALL) when trying
to use an IDispatch pointer from another process.

Here is the situation:
1) I have an app ("my app") and a DLL injected into a target process.
As the user interacts with the target process, the DLL will
periodically put some data into shared memory and use
SendMessageTimeout to notify the my app that it needs to take a look
at the data.  Part of that data potentially includes an IDispatch
pointer to an object in the target app that the my app might need to
manipulate.
2)  My app inspects the data, and under certain conditions, it will
unmarshal an IDispatch pointer from shared memory and attempt to make
some Invoke calls on the IDispatch.  Before any of this occurs, the
main app has already done a ReplyMessage to the message sent from the
DLL.

This is when I get the RPC_E_CANTCALLOUT_ININPUTSYNCCALL error.  My
understanding is that this is because COM thinks my app is still
processing the SendMessage call from the DLL and will not allow it to
make any cross-thread/cross-process COM calls while this is so to
prevent any possible deadlocks.

Just before my first Invoke, where the error occurs, ::InSendMessageEx
returns ISMEX_SEND | ISMEX_REPLIED, indicating that my app HAS replied
to the message.  The MSDN documentation indicates that in this case
the calling thread (that did the SendMessage) is not blocked.  So, COM
should realize this and not return the error; but, perhaps COM is just
using ::InSendMessage, which returns TRUE?

I do not think I can use the technique of doing a PostMessage the way
things are coded, because the processing needs to be completely
synchronous between the DLL and the my app; e.g. the
SendMessageTimeout is used to suspend the target app briefly while my
app has a chance to do some quick processing.

Currently the code that processes the message from the DLL is in the
GUI thread in my app (though the GUI is usually hidden when the user
is working in the target app).

I thought that perhaps I could put the code that handles the message
from the DLL into a separate thread, and then use events rather than
SendMessage to fire off processing in that thread in my app.  Instead
of doing a SendMessageTimeout call, the DLL would do a
WaitForMultipleObjects and my app would set one of two events
indicating that it does or does not need to process the data.

Any ideas if this would work or if there is an easier way?  it will be a
fair amount of effort to move the processing code into another thread.

Thanks much for any help!

~Mike
WaitForMultipleObjects
(1)
InSendMessageEx
(1)
SendMessageTimeout
(1)
UserDefinedMessage
(1)
OnPostedMessage
(1)
OnSentMessage
(1)
InSendMessage
(1)
ReplyMessage
(1)
  Igor Tandetnik replied to domehead100
03-Nov-09 11:53 AM
You are trying to make an out-of-apartment COM call inside a message =
handler invoked in response to a sent message (as opposed to a posted =
one; see SendMessage, PostMessage). You cannot do that. Post yourself a =
message, then make the call from that message's handler.


You have already violated this principle when you called ReplyMessage. =
The moment you did, SendMessageTimeout returned on the DLL's side, and =
the DLL proceeded on its merry way. The two processes are now running in =
parallel, not synchronized in any way.


But you finished your quick processing when you called ReplyMessage, =
right? So there ishould be no harm in PostMessage after that.
--=20
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not =
necessarily a good idea. It is hard to be sure where they are going to =
land, and it could be dangerous sitting under them as they fly overhead. =
-- RFC 1925
  Remy Lebeau replied to domehead100
03-Nov-09 01:48 PM
That error occurs when you call a COM method from inside a window message
handler that is triggered by one of the SendMessage...() functions.  COM
uses window messages internally, and thus would deadlock if the call were
allowed to be performed while SendMessage...() is busy.  Thus, you cannot
call COM methods while handling SendMessage...() requests.


You will have to re-design your code a little bit.  If you do not want to
change the DLL code, then the app's message handler will have to make a copy
of the data and cache it somewhere, and then PostMessage() a second message
back to itself, or otherwise signal itself in any other way of your
choosing, so the app knows that data is still pending.  That will allow the
SendMessage() to fully complete, unblocking the DLL and the app's message
queue.  The second message/signal can then safely make the IDispatch call,
using the copied data as needed.  Or, perform the COM call in a different
thread than the one that is receiving the message.



Even though you have replied to the DLL, thus unblocking the DLL so it can
continue on its way, your app's message queue is still blocked while your
message handler is still running.  You have to exit your mssage handler to
unblock the message queue.  Thus the need to perform the COM call
asynchronously.


Yes.


The ISMEX_SEND flag indicates that the calling thread is still processing a
received message.


True, but the receiving thread is still blocked.


That was true in old OS versions, but in Windows 2000 COM was changed to use
InSendMessageEx() instead.  Even then, that still does not solve the root
problem.  The calling thread is still blocked and cannot make an outbound
COM call yet.


You can use PostMessage(), but on the app side privately, not in the DLL.
The DLL can continue using SendMessageTimeout().  Since you are calling
ReplyMessage() on the app side before making the COM call, that means the
DLL does not have to wait for the app to fully process the data before
continuing on its way, so a private PostMessage() on the app side to delay
the COM call a few extra milliseconds should work just fine.


Since you are using SendMessage...() to send the message, it does not matter
which thread receives the message, if you perform the COM call in the same
thread.  As long as the original message handler is still running, that
thread is blocked from making outbound COM calls.  So either exit the
message handler and do the COM call from a secondary posted message, or else
have the original message handler delegate the COM call to another thread so
it is not blocked by the receiving thread's message handler.
  domehead100 replied to Igor Tandetnik
05-Nov-09 07:40 PM
Thanks for the help Igor (again :o)).  But, I am still a bit stuck...

My main question is:  Do you think that if I used events instead of
SendMessageTimeout/ReplyMessage, that would appease the COM subsystem?

You're right, once I do the ReplyMessage, that part is not truly
synchronous.  The reason for SendMessageTimeout/ReplyMessage is to be
PostMessage, but I think it would be unreliable since then I am waiting
for a system-defined context switch rather than a direct process that
I have some control of.  After the ReplyMessage, there is further
processing and manipulation of the target app that is truly
synchronous, as you have helped me see more clearly, that is not my
problem.

My quandry with the ReplyMessage is that, as you point out, "The
moment you did [ReplyMessage], SendMessageTimeout returned on the
DLL's side, and the DLL proceeded on its merry way. The two processes
are now running in parallel, not synchronized in any way."  BUT, COM
is apparently not smart enough to figure this out (apparently it uses
InSendMessage instead of InSendMessageEx).

If my app has nothing to do, it simply returns early to the
SendMessageTimeout.  It only does the ReplyMessage if it has some
manipulation/automation of the target app to perform.  That's the
reason for the ReplyMessage, to prevent a deadlock in this case.

~Mike
  domehead100 replied to Remy Lebeau
05-Nov-09 07:40 PM
....

Remy, thanks very, very much.  What you said makes a lot of sense.  I
interpreted the RPC_E_CANNOTCALLOUT error to mean only that COM would
not let me call out because it though the thread that sent the message
was blocking waiting on me, which would cause a deadlock.  I never
considered COM's use of the message loop in my app.  (vaguely
wondering if a MTA help in any way here, but do not even want to go
there even if it was)

I am going to experiment with some combination of PostMessage and
events and see what happens.

Thanks again,

~Mike

M
ot
y
that
et
o
opy
ge
the
ll,
nt
n
to
a
  Igor Tandetnik replied to domehead100
03-Nov-09 03:28 PM
Yes. Though I do not quite see what you expect to gain from the added =
complexity, over simply posting yourself a message.


I do not understand. If you believe your code would have race conditions =
with PostMessage, then it already has race conditions without =
PostMessage. You seem to be arguing that without PostMessage, your =
application will crash and burn less often. I am not sure this is a =
strong argument to make.

What control do you believe you have over a context switch? Recall that =
Windows features preemptive multitasking, and there are systems with =
multiple CPUs that can run two processes truly simultaneously.


So help it, by posting a message to yourself.


So instead of ReplyMessage, call PostMessage and prevent a deadlock this =
way.
--=20
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not =
necessarily a good idea. It is hard to be sure where they are going to =
land, and it could be dangerous sitting under them as they fly overhead. =
-- RFC 1925
  domehead100 replied to Igor Tandetnik
05-Nov-09 07:40 PM
ith PostMessage, then it already has race
essage, your application will crash and

I think there is an inevitable race condition.  I am trying to get in
and manipulate the target app while the user is potentially typing
keystrokes.  When they type a key that requires my app to take action,
which may involve inserting keystrokes into the input queue, it needs
to begin manipulating the target app before the user presses the next
key or at least before the target app processes that next keystroke
message.  I am trying to always win the race.

indows features preemptive multitasking,
simultaneously.

I have no control over a context switch; however, as soon as the DLL
calls SendMessageTimeout, the target app is blocked until I return or
reply to it (or the timeout occurs).  So, the target will not get a
time slice or if it does it will not do anything because it is
blocking.  With PostMessage, as soon as the DLL calls PostMessage, the
target app is free to do whatever immediately.  The difference is that
with SendMessage, I can take a few milliseconds to:  a) determine if I
need to take action, and b) do some additional processing if needed,
before returning or replying to the message.  By the time ReplyMessage
is called, my app has already determined what it needs to do (often
just SendInput), has queued up whatever data it needs, and is ready
virtually in the next line of code after ReplyMessage to take action
(e.g., SendInput).  The race is between the time I ReplyMessage and
the time I take action.  With PostMessage, the race begins as soon as
PostMessage is called.  I am trying to get a head start to make sure I
always win the race, if that makes sense.  This has all worked
superbly, only now I am trying to add functionality of scripting or
manipulating the target app through automation, and now I have run into
this COM safety feature.  I am not complaining about it, it makes
sense, I was just confused by the documentation.

Thanks again for taking the time to help me with this.  I realize that
perhaps I am being stupid or stubborn or whatever; hope I have not
been irritating though :o).

I will try PostMessage and see how that works, and probably some
combination of events as well (I do not think events will be all that
complex if I do not have to add another thread).

~Mike
  Igor Tandetnik replied to domehead100
03-Nov-09 09:35 PM
I think you misunderstand. I do not suggest that the DLL use PostMessage =
instead of SendMessageTimeout. I suggest that your controlling =
application call PostMessage on _itself_ in the same place where now it =
calls ReplyMessage, then return immediately. Any processing that you =
currently perform after ReplyMessage should be moved to the posted =
message's handler. Like this:

// Before
OnSentMessage() {
DoQuickProcessing();
ReplyMessage();
DoSlowProcessing();
}

// After

OnSentMessage() {
DoQuickProcessing();
PostMessage(UserDefinedMessage);
}

OnPostedMessage() {
DoSlowProcessing();
}

--=20
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not =
necessarily a good idea. It is hard to be sure where they are going to =
land, and it could be dangerous sitting under them as they fly overhead. =
-- RFC 1925
Create New Account
help
How do I get SendMessageTimeout from the command line? C++ / VB I have a C program that calls SendMessageTimeout as thus: lResult = SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0L, (LPARAM)"Policy", SMTO_ABORTIFHUNG, 5000, &dwRetVal); I know that I can use rundll32 dll, LockWorkStation to lock the screen. I figured that I can do the same for SendMessageTimeout but I can't get it to work. This is what I am trying: rundll32 user32.dll, SendMessageTimeout 65535 26 0 "Policy" 2 5000 0 Is this even possible? Thanks, Mike Win32 UI Discussions SendMessageTimeout (1) DwRetVal (1) LResult (1) Drat (1) Mike (1) SETTINGCHANGE (1) ABORTIFHUNG (1) Rundll32 (1) No, it is not because RunLL32 passes the arguments as a text string while SendMessageTimeout wants four (the first and last are pointers) DWORDS Regards, Will Drat! OK. Thanks. Mike keywords: How, do, I, get, SendMessageTimeout, from, the, command, line? description: I have a C program that calls SendMessageTimeout as thus
WaitForMultipleObjects C++ / VB WaitForMultipleObjects event firing order question while bWaitAll is set to FALSE. . Scenario: Event 1 is fired t been called by the first. Event 1 is now complete, ResetEvent(1), and hits WaitForMultipleObjects call Two questions. . Will Event 1 every get triggered based on the second SetEvent(1)? Will WaitForMultipleObjects process the next event in the same order it was triggered? I ask because after the first handle in the array whose object was signaled. VC ATL Discussions VB (1) WaitForMultipleObjects (1) JavaScript (1) ResetEvent (1) BWaitAll (1) SetEvent (1) Windows (1) Pigs (1) Event is s already signalled has no effect. Just like assigning true to a boolean variable twice. WaitForMultipleObjects with bWaitAll = FALSE waits until at least one of the handles is signalled, and returns items to be processed in the order they were received, implement a producer-consumer queue. WaitForMultipleObjects with multiple event handles (presumably one per work item) is not a suitable mechanism for for some knowledge transfer to myself. . I use WaitForSingleObject for thread handling, but never used WaitForMultipleObjects, but after reading some information, it sparked some questions. . I can see some possible uses
WaitForMultipleObjects returning ERROR_INVALID_HANDLE C++ / VB I have a problem with WaitForMultipleObjects sometimes (not allways) returning ERROR_INVALID_HANDLE. Printing the array of handles in question did not show if the handle is valid or not? many thanks, Felix VC Language Discussions WaiteForMultipleObjects (1) WaitForMultipleObjects (1) IsHandleValid (1) GetLastError (1) CWinThread (1) CloseHandle (1) WriteFile (1) ReadFile (1) What did point however is quite strange: calling 'GetHandleInformation' for each handle in the array passed to 'WaitForMultipleObjects' (which failed) does work fine and returns with success. Why does 'GetHandleInformation' not fail for at least one handle passed to 'WaitForMultipleObjects'? Looking at these facts I am not sure anymore if WaitForMultipleObjects' tells me the truth: does the error code 'ERROR_INVALID_HANDLE' really mean that a handle from the array I passed to 'WaitForMultipleObjects' was invalid or might this error refer to some other (which?) handle? Felix I can handle is not supposed to be waited on. See waitable object list in documentation for `WaitForMultipleObjects'. 2. There is a race condition and some handle is closed during a call to
WaitForMultipleObjects: How to asynchronously wait? C++ / VB Hello! I'm using WaitForMultipleObjects to wait for three threads to finish. CWinThread* thread1 = AfxBeginThread(foo, NULL, THREAD_PRIORITY_NORMAL, 0, 0 the threads finishes in order to update the GUI: for (i = 0; i < 3; i++) { WaitForMultipleObjects(3, h, FALSE, INFINITE); / / do something UpdateData(FALSE); } The problem is that as soon as one of the threads is finished, the for loop executes all three times without WaitForMultipleObjects waiting for the remaining 2 threads. What am I doing wrong? Do I have to remove the handle for the thread which is finished from the HANDLE array before calling WaitForMultipleObjects again? How can I do that? Many thanks, MIchael VC Language Discussions WaitForMultipleObjects (1) DwEvent (1) THREAD_PRIORITY_NORMAL (1) MIchaelRe (1) MsgWaitForMultipleObjects (1) CWinThread (1) AfxBeginThread (1) INFINITE (1 signalled (the thread has terminated) it remains signalled until it's closed. That's why WaitForMultipleObjects returns immediately when you pass this hande to it again. Wait is not edge-triggered fact that a handle is signalled, no matter how it got there). Return value of WaitForMultipleObjects tells you which handle caused it to return. You now need to prepare a new