Board index » cppbuilder » AV - Stack getting trashed - HELP!

AV - Stack getting trashed - HELP!


2006-04-22 06:57:03 AM
cppbuilder39
I need to use the following code to get the MAC address on Win XP and 2k3.
It should work fine....
However, when execution gets to the lines (marked below) the stack gets
completely trashed. I have isolated the problem into a test app. You can
reproduce it by creating a new BCB project, drop a button on the form and
add this code.
Does it work on your system? Please help!
BCB6 Patched.
TIA
----------------
#include <winsock2.h>
#include "Iptypes.h"
#include "Iphlpapi.h"
typedef ULONG (*TGetAdaptersAddresses)(ULONG Family, ULONG Flags, PVOID
Reserved, PIP_ADAPTER_ADDRESSES pAdapterAddresses, PULONG pOutBufLen);
void __fastcall TForm10::Button1Click(TObject *Sender)
{
HINSTANCE hinst = LoadLibrary("Iphlpapi.dll");
AnsiString AMacAddress = EmptyStr;
if(NULL != hinst)
{
try
{
try
{
TGetAdaptersAddresses pGetAdaptersAddresses =
(TGetAdaptersAddresses)GetProcAddress(hinst, "GetAdaptersAddresses");
if(NULL != pGetAdaptersAddresses)
{
IP_ADAPTER_ADDRESSES * pAddresses = NULL;
try
{
ULONG outBufLen = 0;
// Make an initial call to GetAdaptersAddresses to
get the
// size needed into the outBufLen variable
if (pGetAdaptersAddresses(AF_INET, 0, NULL,
pAddresses, &outBufLen) == ERROR_BUFFER_OVERFLOW)
{
if (pAddresses)
GlobalFree(pAddresses);
pAddresses = (IP_ADAPTER_ADDRESSES*)new unsigned
char[outBufLen];
}
// Make a second call to GetAdapters Addresses to
get the actual data we want
if (pGetAdaptersAddresses(AF_INET, 0, NULL,
pAddresses, &outBufLen) == NO_ERROR)
{
// successful,
unsigned char * MACData =
pAddresses->PhysicalAddress;
////////<<---------------- As this next loop
executes - the stack gets trashed !!! WHY???
DWORD i;
for (i = 0; i <
pAddresses->PhysicalAddressLength; i++)
AMacAddress = AMacAddress + Format("%.2X:",
ARRAYOFCONST(( MACData[i] )));
AMacAddress =
AMacAddress.Delete(AMacAddress.Length(), 1); // take off the last colon
}
}
__finally
{
if (pAddresses)
delete [] pAddresses;
}
}
}
catch(...)
{
AMacAddress = "UNKNOWN MAC ADDR";
}
}
__finally
{
FreeLibrary(hinst);
}
}
MessageDlg(AMacAddress, mtWarning, TMsgDlgButtons() << mbOK, 0);
}
 
 

Re:AV - Stack getting trashed - HELP!

"Borland Lover" < XXXX@XXXXX.COM >wrote in message
Quote
However, when execution gets to the lines (marked below) the stack
gets completely trashed.
That is because you are not managing the stack correctly in the first place.
See below.
Quote
typedef ULONG (*TGetAdaptersAddresses)(ULONG Family, ULONG Flags, PVOID
Reserved, PIP_ADAPTER_ADDRESSES pAdapterAddresses, PULONG pOutBufLen);
You are not specifying any calling convention in that declaration, so the
compiler's default conention is used. Under C++, the default is __cdecl,
which is NOT the convention that GetAdaptersAddresses() actually uses. If
you look at the documentation for GetAdatersAddresses(), it uses WINAPI for
the calling convention, which in turn usually resolves to __stdcall. Win32
API functions always use the __stdcall convention (wsprintf() is about the
only API function that uses __cdecl instead). __cdecl and _stdcall
manipulate the stack very differently.
Use this code instead:
typedef ULONG (WINAPI *TGetAdaptersAddresses)(ULONG Family, ULONG Flags,
PVOID Reserved, PIP_ADAPTER_ADDRESSES pAdapterAddresses, PULONG pOutBufLen);
void __fastcall TForm10::Button1Click(TObject *Sender)
{
HINSTANCE hinst = LoadLibrary("Iphlpapi.dll");
AnsiString AMacAddress;
if( NULL != hinst )
{
try
{
TGetAdaptersAddresses pGetAdaptersAddresses =
(TGetAdaptersAddresses) GetProcAddress(hinst, TEXT("GetAdaptersAddresses"));
if( NULL != pGetAdaptersAddresses )
{
IP_ADAPTER_ADDRESSES * pAddresses = NULL;
try
{
ULONG outBufLen = 0;
ULONG ulErr = pGetAdaptersAddresses(AF_INET, 0,
NULL, NULL, &outBufLen);
if( ERROR_BUFFER_OVERFLOW == ulErr )
{
pAddresses = (IP_ADAPTER_ADDRESSES*) new
BYTE[outBufLen];
ulErr = pGetAdaptersAddresses(AF_INET, 0, NULL,
pAddresses, &outBufLen);
}
if( (NO_ERROR == ulErr) && (0 !=
pAddresses->PhysicalAddressLength) )
{
AMacAddress.SetLength((pAddresses->PhysicalAddressLength * 3) - 1);
char *ptr = AMacAddress.c_str();
LPBYTE MACData = pAddresses->PhysicalAddress;
sprintf(ptr, "%02X", MACData[0]);
ptr += 2;
for(DWORD i = 1; i <
pAddresses->PhysicalAddressLength; ++i)
{
sprintf(ptr, ":%02X", MACData[i]);
ptr += 3;
}
}
}
__finally
{
delete [] pAddresses;
}
}
}
catch(...)
{
AMacAddress = "UNKNOWN MAC ADDR";
}
FreeLibrary(hinst);
}
MessageDlg(AMacAddress, mtWarning, TMsgDlgButtons() << mbOK, 0);
}
Gambit
 

Re:AV - Stack getting trashed - HELP!

"Remy Lebeau (TeamB)" < XXXX@XXXXX.COM >wrote in message
Quote

"Borland Lover" < XXXX@XXXXX.COM >wrote in message
news:4449633f$ XXXX@XXXXX.COM ...

>However, when execution gets to the lines (marked below) the stack
>gets completely trashed.

That is because you are not managing the stack correctly in the first
place.
See below.

>typedef ULONG (*TGetAdaptersAddresses)(ULONG Family, ULONG Flags, PVOID
>Reserved, PIP_ADAPTER_ADDRESSES pAdapterAddresses, PULONG pOutBufLen);
Of course! Makes total sense. Works like a charm. Thank you very much.
 

{smallsort}

Re:AV - Stack getting trashed - HELP!

What about these two functions :
GetAdaptersInfo - it does not specify a calling convention in the MSDN.
What do I use in BCB?
UuidCreateSequential - it specifies RPC_ENTRY. What do I use in BCB?
I am loading and calling both right now without specifying the calling
convention - and they seem to be working fine. Is this a fluke?
TIA
 

Re:AV - Stack getting trashed - HELP!

"Borland Lover" < XXXX@XXXXX.COM >wrote in message
Quote
GetAdaptersInfo - it does not specify a calling convention
in the MSDN.
As I told you earlier, *all* Win32 API functions use WINAPI (aka __stdcall),
except for wsprintf() which uses __cdecl instead. If you look in
iphlpapi.h, where GetAdaptersInfo() is actually declared, you can see that:
DWORD
WINAPI // <-- here
GetAdaptersInfo(
PIP_ADAPTER_INFO pAdapterInfo, PULONG pOutBufLen
);
Quote
UuidCreateSequential - it specifies RPC_ENTRY. What do I use in BCB?
You use RPC_ENTRY, which transparently maps to __stdcall. Always use what
is actually in the declaration.
Quote
I am loading and calling both right now without specifying the calling
convention - and they seem to be working fine. Is this a fluke?
Yes. You must always specify a calling convention, or else the compiler is
free to choose its own. As you have already seen earlier, the compiler can
chose the wrong convention and mess up the runtime behavior as a result.
Gambit
 

Re:AV - Stack getting trashed - HELP!

Thank you Remy.
"Remy Lebeau (TeamB)" < XXXX@XXXXX.COM >wrote
[...]