Converting unicode interface name to character string


I am writing some software that deals with internet interfaces. I have written a class that calls GetInterfaceInfo followed by GetIfEntry to get information on each of the interfaces:

std::list<Interface> sysList;
sysList = Interface::Discover();

The Interface class contains the name, index, broadcast address etc. of each interface. I have tested my class and it is correctly returning all the interfaces on the system. For compatibility with other classes it is necessary that I have a method in my interface class that returns the name of the interface as a string. However, in the microsoft documentation: (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/rras/rras/mib_ifrow.asp) it says that the name of the interface is returned as an array of wide characters: WCHAR wszName[MAX_INTERFACE_NAME_LEN].

My questions:
Is there any way to print the interface name so that I can verify that it has been returned correctly? (I have tried printf, wprintf, wcout etc with a variety of options however they always either return nothing or a string of about 500 identical characters).

Having verified that the interface name is being returned correctly, is there any way to convert from wide characters to characters so that my method can return a string of charaters??
jeordstaAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

GrahamRoweCommented:
The Microsoft macro W2A will convert a wide string to a single byte string. Bear in mind that you must provide the USES_CONVERSION macro in tandem with this one as it allocates a temporary variable used in the conversion.

Code Sample:

wchar_t* pwsName = L"Hello World.";

USES_CONVERSION;

char* pszName = W2A (pwsName);

printf ("%s\n", pszName);
0
jkrCommented:
>>The Microsoft macro W2A will convert a wide string to a single byte string.

... if you are using ATL. It is actually easier to

#include <stdlib.h>

WCHAR wszName[MAX_INTERFACE_NAME_LEN];
char szName[MAX_INTERFACE_NAME_LEN];

wcstombs ( szName, wszName, sizeof ( szName));


0
GrahamRoweCommented:
jkr - I think that you may have got things slightly wrong there.

A multibyte string is not the same as the single byte string asked for by jeordsta. Multibyte strings are (as I recall) a bit of a hack by MS from the early days before Unicode was standardised on. A multibyte string contains characters encoded into either one or two bytes and have a distinct API to allow you to traverse the strng.

G
0
Cloud Class® Course: Python 3 Fundamentals

This course will teach participants about installing and configuring Python, syntax, importing, statements, types, strings, booleans, files, lists, tuples, comprehensions, functions, and classes.

jkrCommented:
>>I think that you may have got things slightly wrong there

No :o)

Check atlconv.h where that 'W2A()' macro is declared and you will find out that they're using 'WideCharToMultiByte()' for the conversion ('wcstombs()' is just the CRT wrapper for that API). Not into a in-depth discussion of charsets now, though)
0
GrahamRoweCommented:
Ta for that. Think I owe you points now ;-)

G.
0
jeordstaAuthor Commented:
Hey guys,

Thanks for the quick response however this still doesn't seem to be working. GrahamRowe: I tried your method first but the USESCONVERSION macro was undefined. What is ATL? I didn't know what I had to include to use the macro. jkr: I tried your method and it compiled without error. However it still isn't producing meaningful output. I have written a very simple program below which illustrates what I am trying to do:

int main(int argc,char* argv[]) {
  MIB_IFROW IfRow;
  char error_message[1024];

  IfRow.dwIndex=1;
  if (GetIfEntry(&IfRow)!=NO_ERROR) {
    strcpy(error_message, GetErrorMsg());
    printf ("Error in GetIfEntry: %s\n", error_message);
  }

  char szName[MAX_INTERFACE_NAME_LEN];

  wcstombs ( szName, IfRow.wszName, sizeof ( szName));    
  printf ("Interface name: %s\n", szName);
};

Here is the output:

Interface name: ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦

I have tried running this program on a variety of versions of windows (XP, 2000 and 98) but every version produces this same output. Is it possible to get meaningful output to thhe console??

TIA, jeordsta.
0
jeordstaAuthor Commented:
Oh, I forgot to mention that the above code will complain about GetErrorMsg() being undefined. It is just a little function that calls GetLastError() and then FormatMessage().
0
DanRollinsCommented:
>> jkr - I think that you may have got things slightly wrong there...

Hehehe ... I thought everybody knew that "Multibyte" really means "single byte"  Isn't it obvious?
=-=-=-=-=-=-=-=-=-=-=-

Are the other fields in the MIB_IFROW populated with valid data?  Possibly some types of these puppies don't have any kind of hyman-readable name associated.

You should prefill the structure with 0s before calling GetIfEntry.

-- Dan
0
DanRollinsCommented:
Also, the GetInterfaceInfo function provides a means to get the name. -- Dan
0
jeordstaAuthor Commented:
Dan,

I tried setting the memory to zero which produced:
Interface Name:
So it seems reasonable to assume that GetIfEntry() isn't returning anything for wszName.

I tried GetInterfaceInfo() but my first call, to work out how much memory is needed for IP_INTERFACE_INFO resulted in an error. When I used FormatMessage to retrieve the system error it complained that "this function is only available in Win32 mode." What on earth is Win32 mode??! And how do I get into that mode??
0
DanRollinsCommented:
It worked right away for me:

#include <windows.h>
#include <Iphlpapi.h>
#include <stdio.h>
#pragma comment(lib, "D:\\VisualStudio.NET\\Vc7\\PlatformSDK\\lib\\Iphlpapi.lib" )

void ShowErr( DWORD nErr )
{
     LPVOID lpMsgBuf;
     FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
          NULL, nErr,
          MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
          (LPTSTR) &lpMsgBuf, 0, NULL
     );
     printf( "GetLastError (0x0%x) %s\r\n", nErr, (LPCSTR)lpMsgBuf );
     LocalFree( lpMsgBuf );
}
void ShowLastErr()  { ShowErr( GetLastError() ); }

int main()
{
     IP_INTERFACE_INFO rIPII;
     DWORD nSize= sizeof(rIPII);

     byte buf[5000];
     IP_INTERFACE_INFO* parIPII= (IP_INTERFACE_INFO*)buf;

     DWORD nRet= GetInterfaceInfo( &rIPII, &nSize ); // error code is 0x0007a
     ShowErr( nRet );

     nRet= GetInterfaceInfo( parIPII, &nSize ); // nSize is 0x0c30
     ShowLastErr();

     WCHAR* pwsName= parIPII->Adapter[0].Name;
     char   szName[MAX_ADAPTER_NAME];
     wcstombs ( szName, pwsName, sizeof ( szName));

     printf( "%s\r\n", szName );
     return(0);
}

output from this program is:

GetLastError (0x07a) The data area passed to a system call is too small.

GetLastError (0x00) The operation completed successfully.

\DEVICE\TCPIP_{1552B244-28CA-4492-980E-182BA89DCC06}

0
DanRollinsCommented:
I added this code...

     MIB_IFROW rMIRow;
     DWORD nEntryCnt;

     nRet= GetNumberOfInterfaces( &nEntryCnt );

     for (DWORD j=1; j< nEntryCnt+1; j++ ) {
          memset( &rMIRow, 0 , sizeof(rMIRow));
          rMIRow.dwIndex=j;

          nRet= GetIfEntry( &rMIRow );
          if (nRet !=NO_ERROR ) {
               ShowErr( nRet );
               break;
          }
          printf("entry# %d: Name= '%S', description= '%s'\r\n", j,rMIRow.wszName, rMIRow.bDescr );
     }

and got this additional output....

entry# 1: Name= '', description= 'MS TCP Loopback interface'
entry# 2: Name= '', description= 'VIA PCI 10/100Mb Fast Ethernet Adapter'

-- Dan
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
jeordstaAuthor Commented:
Dear Dan,

Here is the output from your fist program:

GetLastError (0x07a) The data area passed to a system call is too
small.

GetLastError (0x00) The operation completed successfully.

¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦l_e
Press any key to continue

And your second program:

GetLastError (0x07a) The data area passed to a system call is too
small.

GetLastError (0x00) The operation completed successfully.

¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦l_e
entry# 1: Name= '', description= 'MS TCP Loopback interface'
GetLastError (0x0d) The data is invalid.

entry# 16777218: Name= '', description= 'Intel(R) PRO Adapter'
Press any key to continue

Note that I had to add a bit that manually told GetIfEntry to look for an index of 16777218 because it abandons the for loop before it finds it. Although this still doesn't allow me to see the name of the interface (ie display wszName) it does allow a description of the interface which I was after anyway! Thanks, Geordie.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Microsoft Development

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.