Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

AV - Stack getting trashed - HELP!

24 views
Skip to first unread message

Borland Lover

unread,
Apr 21, 2006, 6:57:03 PM4/21/06
to
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);

}


Remy Lebeau (TeamB)

unread,
Apr 24, 2006, 2:43:57 PM4/24/06
to

"Borland Lover" <kd...@kbdf.com> wrote in message
news:4449633f$1...@newsgroups.borland.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);

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


Borland Lover

unread,
Apr 25, 2006, 11:28:06 AM4/25/06
to

"Remy Lebeau (TeamB)" <no....@no.spam.com> wrote in message
news:444d1d06$1...@newsgroups.borland.com...

>
> "Borland Lover" <kd...@kbdf.com> wrote in message
> news:4449633f$1...@newsgroups.borland.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.

Borland Lover

unread,
Apr 25, 2006, 11:46:42 AM4/25/06
to
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


Remy Lebeau (TeamB)

unread,
Apr 25, 2006, 1:04:27 PM4/25/06
to

"Borland Lover" <kd...@kbdf.com> wrote in message
news:444e4463$1...@newsgroups.borland.com...

> 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
);

> 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.

> 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


Borland Lover

unread,
Apr 28, 2006, 11:36:42 AM4/28/06
to
Thank you Remy.

"Remy Lebeau (TeamB)" <no....@no.spam.com> wrote

[...]


0 new messages