BSTR to char*

Posted on 2001-07-16
Last Modified: 2007-11-27
I am looking for an example for a convesion funcion from BSTR to char*.
Question by:gshriki
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 7
  • 3
  • 3
  • +5

Expert Comment

ID: 6285865
here you are:

// BSTR input;
char strtmp[200];
// Here we convert the BSTR to a char *
                    input,              // actual Message
                    lstrlenW(input),    // sizeof bstrMsg
                    strtmp,             // recieving variable
                    lstrlenW(input),    // sizeof(strMsg),


Expert Comment

ID: 6285873
msdn page for reference:

Platform SDK

The WideCharToMultiByte function maps a wide-character string to a new character string. The new character string is not necessarily from a multibyte character set.

int WideCharToMultiByte(
  UINT CodePage,            // code page
  DWORD dwFlags,            // performance and mapping flags
  LPCWSTR lpWideCharStr,    // wide-character string
  int cchWideChar,          // number of chars in string
  LPSTR lpMultiByteStr,     // buffer for new string
  int cbMultiByte,          // size of buffer
  LPCSTR lpDefaultChar,     // default for unmappable chars
  LPBOOL lpUsedDefaultChar  // set when default char used
[in] Specifies the code page used to perform the conversion. This parameter can be given the value of any code page that is installed or available in the system. You can also specify one of the following values. Value Meaning
CP_ACP ANSI code page
CP_MACCP Macintosh code page
CP_OEMCP OEM code page
CP_SYMBOL Windows 2000 or later: Symbol code page (42)
CP_THREAD_ACP Windows 2000 or later: Current thread's ANSI code page
CP_UTF7 Windows 98, Windows Me, Windows NT 4.0 and Windows 2000 or later: Translate using UTF-7. When this is set, lpDefaultChar and lpUsedDefaultChar must be NULL
CP_UTF8 Windows 98, Windows Me, Windows NT 4.0 and Windows 2000 or later: Translate using UTF-8. When this is set, dwFlags must be zero and both lpDefaultChar and lpUsedDefaultChar must be NULL.

[in] Specifies the handling of unmapped characters. The function performs more quickly when none of these flags is set. The following flag constants are defined. Value Meaning
WC_NO_BEST_FIT_CHARS Windows 2000 or later: Any Unicode characters that do not translate directly to multibyte equivalents will be translated to the default character (see lpDefaultChar parameter). In other words, if translating from Unicode to multibyte and back to Unicode again does not yield the exact same Unicode character, the default character is used.
This flag may be used by itself or in combination with the other dwFlag options.
WC_COMPOSITECHECK Convert composite characters to precomposed characters.
WC_DISCARDNS Discard nonspacing characters during conversion.
WC_SEPCHARS Generate separate characters during conversion. This is the default conversion behavior.
WC_DEFAULTCHAR Replace exceptions with the default character during conversion.

When WC_COMPOSITECHECK is specified, the function converts composite characters to precomposed characters. A composite character consists of a base character and a nonspacing character, each having different character values. A precomposed character has a single character value for a base/nonspacing character combination. In the character ?, the e is the base character, and the accent grave mark is the nonspacing character.

When an application specifies WC_COMPOSITECHECK, it can use the last three flags in this list (WC_DISCARDNS, WC_SEPCHARS, and WC_DEFAULTCHAR) to customize the conversion to precomposed characters. These flags determine the function's behavior when there is no precomposed mapping for a base/nonspace character combination in a wide-character string. These last three flags can only be used if the WC_COMPOSITECHECK flag is set.

The function's default behavior is to generate separate characters (WC_SEPCHARS) for unmapped composite characters.

[in] Points to the wide-character string to be converted.
[in] Specifies the number of wide characters in the string pointed to by the lpWideCharStr parameter. If this value is ?1, the string is assumed to be null-terminated and the length is calculated automatically. The length will include the null-terminator.
[out] Points to the buffer to receive the translated string.
[in] Specifies the size, in bytes, of the buffer pointed to by the lpMultiByteStr parameter. If this value is zero, the function returns the number of bytes required for the buffer. (In this case, the lpMultiByteStr buffer is not used.)
[in] Points to the character used if a wide character cannot be represented in the specified code page. If this parameter is NULL, a system default value is used. The function is faster when both lpDefaultChar and lpUsedDefaultChar are NULL.
If CodePage is either CP_UTF7 or CP_UTF8, this parameter must be NULL.

[in] Points to a flag that indicates whether a default character was used. The flag is set to TRUE if one or more wide characters in the source string cannot be represented in the specified code page. Otherwise, the flag is set to FALSE. This parameter may be NULL. The function is faster when both lpDefaultChar and lpUsedDefaultChar are NULL.
If CodePage is either CP_UTF7 or CP_UTF8, this parameter must be NULL.

Return Values
If the function succeeds, and cbMultiByte is nonzero, the return value is the number of bytes written to the buffer pointed to by lpMultiByteStr. The number includes the byte for the null terminator.

If the function succeeds, and cbMultiByte is zero, the return value is the required size, in bytes, for a buffer that can receive the translated string.

If the function fails, the return value is zero. To get extended error information, call . GetLastError may return one of the following error codes:


The lpMultiByteStr and lpWideCharStr pointers must not be the same. If they are the same, the function fails, and GetLastError returns ERROR_INVALID_PARAMETER.

If CodePage is CP_SYMBOL and cbMultiByte is less than cchWideChar, no characters are written to lpMultiByte. Otherwise, if cbMultiByte is less than cchWideChar, cbMultiByte characters are copied to the buffer pointed to by lpMultiByte.

An application can use the lpDefaultChar parameter to change the default character used for the conversion.

As noted earlier, the WideCharToMultiByte function operates most efficiently when both lpDefaultChar and lpUsedDefaultChar are NULL. The following table shows the behavior of WideCharToMultiByte for the four combinations of lpDefaultChar and lpUsedDefaultChar.

lpDefaultChar lpUsedDefaultChar Result
NULL NULL No default checking. This is the most efficient way to use this function.
non-NULL NULL Uses the specified default character, but does not set lpUsedDefaultChar.
NULL non-NULL Uses the system default character and sets lpUsedDefaultChar if necessary.
non-NULL non-NULL Uses the specified default character and sets lpUsedDefaultChar if necessary.

MAPI: For more information, see Syntax and Limitations for Win32 Functions Useful in MAPI Development.

For an example, see Looking Up a User's Full Name.

  Windows NT/2000 or later: Requires Windows NT 3.1 or later.
  Windows 95/98/Me: Requires Windows 95 or later.
  Header: Declared in Winnls.h; include Windows.h.
  Library: Use Kernel32.lib.

LVL 32

Accepted Solution

jhance earned 50 total points
ID: 6285886
Alternatively, you could use the _bstr_t template:

char *lpszConverted;

_bstr_t myBstr(myBSTR, FALSE);
lpszConverted = (char *)myBstr;

Note that the _bstr_t template class implements the (char *) operatator to convert.
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!


Expert Comment

ID: 6286069
char* CopyBSTRToCStr (const BSTR bstr)
     if (bstr == NULL)
          return NULL;
     int len = wcstombs(NULL, bstr, 0);
     char *p_result = new char[len+1];
     int bytes = wcstombs(p_result, bstr, len);
     if (bytes < 0)
          delete []p_result;
          return NULL;
     p_result[bytes] = '\0';
     return p_result;

BSTR CopyCStrToBSTR (const char* cstr)
     if (cstr == NULL)
          return NULL;

     int len = mbstowcs(NULL, cstr, 0);
     wchar_t *p_wide = new wchar_t[len+1];
     int bytes = mbstowcs(p_wide, cstr, len);
     if (bytes <= 0)
          delete []p_wide;
          return NULL;
     p_wide[bytes] = _mbbtombc('\0');
     BSTR p_result = SysAllocString(p_wide);
     delete [] p_wide;
     return p_result;
LVL 32

Expert Comment

ID: 6286196
Dear C++ Moderator,

Please review this question's history.  I fail to see how wiseguyncorner's "answer" is significantly differentiated from the earlier comments.  It's my opinion that he is out of line in posting an answer like this in light of the eariler comments.

Expert Comment

ID: 6286244
Rejected proposed answer on request.


I can only post my personal opinion on this, so don't take this as an official line of any description.

If you can provide an answer that fully, and comprehensively addresses an asker's question, I don't see why you shouldn't lock it with the answer.

It depends very much what the question is though. A complex programming question typically doesn't have a single correct solution. In that case, most experts agree that the "netiquette" for this site is to post your suggestions as a comment - after all, there's nothing stopping an asker from accepting your comment as the answer if it's good enough.

In this particular case, a few alternative solutions were already suggested, in which circumstance it is pretty much generally accepted that any new suggestions should be posted as comments only, just like jhance says.

So, use your judgement, but if there's a chance that there may be alternative solutions, and even ones that are more elegant or better than yours, I suggest you only post comments. And it is generally considered polite, on *any* site, to adopt the local "netiquette".

Anyway, gshriki,

Of course, if you feel that wiseguyncomer's suggestion is the best of the lot, you're quite free to accept his comment. Me rejecting it on your behalf doesn't mean you can't accept it if you wish. If you feel it addresses your problem, accept it, or any of the other comments made by other people here. Whichever addresses your need best.

Community Support Moderator@Experts-Exchange

Expert Comment

ID: 6286296
wiseguyncorner's answer completely solved the problem of qshriki, and indeed contributed to this question as noone had yet found a 'reasy to use' solution for the asker (jhance will disagree).

qshriki, if you feel that wiseguyncorner's answer helped you, you should award the points to wisenguycorner.
LVL 32

Expert Comment

ID: 6286315
I will disagree and point out that there were already TWO different and relevant proposals in this thread.  If this were my question, I'd have already accepted SEves comment as being both first and workable.

I only pointed out an alternative that could also be useful but in no way feel entitled to the points here.

My gripe is with posting an answer when in fact an answer is unwarranted due to the circumctance.  Had wiseguy been first in the thread, I'd have have NO PROBLEM with him locking this when an answer since his solution also appears workable.  The problem here is that viable solutions are ALREADY POSTED AS COMMENTS and wiseguy therefore was out of line to lock the Q.

Thank you Mr. Moderator for helping out.

Expert Comment

ID: 6286333
Dear C++ Moderator,

I would like to believe that these postings are in an academic sense, heuristic.  It is my belief that answers are given in not only a helpful and beneficial way, but also to give the recipient the idea that there are many ways to solve his or her problem.

In light of the question,
"I am looking for an example for a convesion funcion from BSTR to char*."
I answered just that.  Matter of fact, I answered both of gshriki's questions (refer to "Question: covert char * to BSTR *")

I also believe that this question does diferentiate from the rest by using POSIX as opposed to the API (minus SysAllocString).

If one looks up the definition of both comments and Answers, I believe that you will understand that my answer was not a comment, it was an answer.  If you think that I am wrong, please email me.  I also don't believe that this is the time, nor place to argue about the topics of a site and the business logic that runs it.  In my opinion, I or anyone else should be able to "Answer a question." - not just post a comment.  I likewise believe comments are for discussion of previous "Answers."

I should not stand at fault for idiosyncrasies that this site uses.

Thus, I stand by my answer.
LVL 30

Expert Comment

ID: 6286336
Just helping should not be a determinating factor.
Help could be use to determine if the points should be split.
If the points are to go only to one expert, then it should go to the expert who the questioner feels answer his/her question.
LVL 32

Expert Comment

ID: 6286372
>>Thus, I stand by my answer.

Please, you should stand by your answer.  But you should have posted it here as a comment!  If you were first in the question, then it's fair game.  But you disregarded other experts who posted viable comments as well.

That's where you went wrong.

Expert Comment

ID: 6286423
~52 minutes
4 phone calls, 1 cup of coffee, and 35 lines of stl that would make your mother cry.  Who is to say that I wasn't the first to look at this question.  
LVL 32

Expert Comment

ID: 6286471
>> Who is to say that I wasn't the first to look at this question.  

It doesn't matter when you looked at it.  It's the time you posted your comment that counts.  In this case we have:

SEve at:  07/16/2001 06:27AM PST and 07/16/2001 06:29AM PST
jhance: 07/16/2001 06:33AM PST

You come along almost an hour later at: 07/16/2001 07:21AM PST

LVL 30

Expert Comment

ID: 6286562
Hi wiseguyncorner, welcome to EE.

All of the experts here, for the most part have learn from other experts as to the proper etiquette for posting answer.

An answer should not be posted as an answer, if other experts have previously posted possible answers as comments, and/or have already made contributions to the question.

There are many experts who never post answers as answer.  Instead, they post their answers as comments.

If you read the following link, you'll see why this is the preferred method for many of our valued experts, including myself.

Expert Comment

ID: 6287569
If you want to use ATL macros in Visual C++ I think you can use the following simple code to convert BSTR named "text" to char *str:

char *str = W2A(text);


Expert Comment

ID: 6287596
oops I think that macro would be W2CA

LVL 32

Expert Comment

ID: 6287661
The ATL macros are often quite useful.  If you are going to use them be sure to:

#include "afxpriv.h"

to get the macro definitions.  And don't forget the:


line in every function body that uses any of these macros.

Expert Comment

ID: 6287667
... But it aren't ATL macros, it are MFC macros.
LVL 32

Expert Comment

ID: 6287683
>>But it aren't ATL macros, it are MFC macros.

Then why does Microsoft describe them in the section of the SDK titled:

"ATL Macros and Global Functions"

Since these are indeed macros and not global functions, Microsoft is saying they are ATL macros....;-)

Expert Comment

ID: 6288303
aha, now i see your "Rated #1 arrogant, obnoxious, bully on Experts Exchange" jhance ;). kidding!

Expert Comment

ID: 6288800
>> Since these are indeed macros and not global functions, Microsoft is saying they are ATL macros....;-)

? Anyway: Those macros existed before ATL, and they reside in the MFC\include directory. I don't know why Microsoft tells it should be ATL macros. Maybe a typo :)

Featured Post

Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Article by: SunnyDark
This article's goal is to present you with an easy to use XML wrapper for C++ and also present some interesting techniques that you might use with MS C++. The reason I built this class is to ease the pain of using XML files with C++, since there is…
C++ Properties One feature missing from standard C++ that you will find in many other Object Oriented Programming languages is something called a Property (…
The viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.
The viewer will be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.

696 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question