Watch, Follow, &
Connect with Us

For forums, blogs and more please visit our
Developer Tools Community.


Welcome, Guest
Guest Settings
Help

Thread: Call IcmpSendEcho2Ex Asynchronously


This question is not answered. Helpful answers available: 2. Correct answers available: 1.


Permlink Replies: 2 - Last Post: Dec 12, 2017 12:44 AM Last Post By: Shun Yi Tsai Threads: [ Previous | Next ]
Shun Yi Tsai

Posts: 9
Registered: 8/22/10
Call IcmpSendEcho2Ex Asynchronously  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Dec 10, 2017 2:08 AM
Hello,

I am utilizing RAD Studio Tokyo C++ Builder to build my program.
I called IcmpSendEcho2Ex API command synchronously, and it work well. However, when I called it asynchronously by specifying the third and fourth parameter --- ApcRoutine and ApcContext, program never run to ApcRoutine callback routine --- ICMPReplyCame. Is there anyone knowing where the mistake is?

Ben

Here is my code.
==========================================================================================================
void __fastcall TForm1::Button3Click(TObject *Sender)
{
char *pcSourceAddress,*pcDestinationAddress;
int iTTL=255,iSize_Date=64;
unsigned long ulSourceIPAddress = INADDR_NONE,ulDestinationIPAddress = INADDR_NONE;
DWORD DWReturnValue = 0;
HANDLE HIcmpFile;
AnsiString ASSAddress, ASDAddress;

ASSAddress = EditSourceIPAddress->Text;
ASDAddress = EditDestinationIPAddress->Text;

pcSourceAddress = ASSAddress.c_str();
pcDestinationAddress = ASDAddress.c_str();

void * SendData = malloc(iSize_Date);
LPVOID ReplyBuffer = NULL;
DWORD ReplySize = 0;
ulSourceIPAddress = inet_addr(pcSourceAddress);
ulDestinationIPAddress = inet_addr(pcDestinationAddress);
HIcmpFile = IcmpCreateFile();
if (HIcmpFile == INVALID_HANDLE_VALUE)
return;

ReplySize = 8* (sizeof(ICMP_ECHO_REPLY) +iSize_Date);

ReplyBuffer = (VOID*) malloc(ReplySize );

DWReturnValue = IcmpSendEcho2Ex(HIcmpFile, NULL, ICMPReplyCame, pcSourceAddress, ulSourceIPAddress,ulDestinationIPAddress, SendData, iSize_Date, NULL,
ReplyBuffer, ReplySize, iTTL);
// DWReturnValue = IcmpSendEcho2Ex(HIcmpFile, NULL, NULL, NULL, ulSourceIPAddress,ulDestinationIPAddress, SendData, iSize_Date, NULL,
// ReplyBuffer, ReplySize, iTTL);

PICMP_ECHO_REPLY pEchoReply = (PICMP_ECHO_REPLY)ReplyBuffer;

if( DWReturnValue )
DWReturnValue=pEchoReply->RoundTripTime;

free(ReplyBuffer);
free(SendData);
}
//---------------------------------------------------------------------------

int __stdcall ICMPReplyCame(void)
{
Form1->MemoICMPReply->Lines->Add("Get Reply");
}
//---------------------------------------------------------------------------
==========================================================================================================

PS : EditSourceIPAddress and EditDestinationIPAddress are VCL component TEdit.

Edited by: Shun Yi Tsai on Dec 10, 2017 2:09 AM
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: Call IcmpSendEcho2Ex Asynchronously [Edit]  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Dec 11, 2017 11:59 AM   in response to: Shun Yi Tsai in response to: Shun Yi Tsai
Shun Yi Tsai wrote:

I called IcmpSendEcho2Ex API command synchronously, and it work well.
However, when I called it asynchronously by specifying the third and
fourth parameter --- ApcRoutine and ApcContext, program never run to
ApcRoutine callback routine

That is because you are calling it in the main UI thread, which never
enters an **alertable wait state**, so the OS can't call your callback
procedure. Per the documentation:

https://msdn.microsoft.com/en-us/library/windows/desktop/bb309069.aspx

ApcRoutine [in, optional]
The routine that is called when **the calling thread is in an alertable
state** and an ICMP reply arrives.

Refer to MSDN documentation for more details about Alertable I/O:

https://msdn.microsoft.com/en-us/library/windows/desktop/aa363772.aspx

However, the VCL's main UI thread doesn't natively support Alertable
I/O, so you will have to use a worker thread instead (in which case,
using IcmpSendEcho2Ex() asynchronously is a bit redundant).

However, if you really want to use IcmpSendEcho2Ex() asynchronously in
the main UI thread, you don't need to use a callback procedure at all.
Use the 2nd parameter of IcmpSendEcho2Ex() instead (which you are
currently setting to NULL).

Use TEvent, or CreateEvent/Ex() directly, to create an event object
that you can then pass to IcmpSendEcho2Ex(). Then, you can use a
TTimer with TEvent::WaitFor()/WaitForSingleObject(), or
RegisterWaitForSingleObject(), to monitor the state of the event object.

When the event object is signaled, or the RegisterWaitForSingleObject()
callback is called, you can then process the ICMP reply data as needed.

--
Remy Lebeau (TeamB)
Shun Yi Tsai

Posts: 9
Registered: 8/22/10
Re: Call IcmpSendEcho2Ex Asynchronously [Edit]  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Dec 12, 2017 12:44 AM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
Remy Lebeau (TeamB) wrote:
Shun Yi Tsai wrote:

I called IcmpSendEcho2Ex API command synchronously, and it work well.
However, when I called it asynchronously by specifying the third and
fourth parameter --- ApcRoutine and ApcContext, program never run to
ApcRoutine callback routine

That is because you are calling it in the main UI thread, which never
enters an **alertable wait state**, so the OS can't call your callback
procedure. Per the documentation:

https://msdn.microsoft.com/en-us/library/windows/desktop/bb309069.aspx

ApcRoutine [in, optional]
The routine that is called when **the calling thread is in an alertable
state** and an ICMP reply arrives.

Refer to MSDN documentation for more details about Alertable I/O:

https://msdn.microsoft.com/en-us/library/windows/desktop/aa363772.aspx

However, the VCL's main UI thread doesn't natively support Alertable
I/O, so you will have to use a worker thread instead (in which case,
using IcmpSendEcho2Ex() asynchronously is a bit redundant).

However, if you really want to use IcmpSendEcho2Ex() asynchronously in
the main UI thread, you don't need to use a callback procedure at all.
Use the 2nd parameter of IcmpSendEcho2Ex() instead (which you are
currently setting to NULL).

Use TEvent, or CreateEvent/Ex() directly, to create an event object
that you can then pass to IcmpSendEcho2Ex(). Then, you can use a
TTimer with TEvent::WaitFor()/WaitForSingleObject(), or
RegisterWaitForSingleObject(), to monitor the state of the event object.

When the event object is signaled, or the RegisterWaitForSingleObject()
callback is called, you can then process the ICMP reply data as needed.

--
Remy Lebeau (TeamB)

Hi Remy,

Many thanks for your reply. I will try TEvent instead.

Ben
Legend
Helpful Answer (5 pts)
Correct Answer (10 pts)

Server Response from: ETNAJIVE02