How to convert LPTSTR to BSTR?
-
In my project i am using FormatMessage API which is returning the LPTSTR buffer pointer lpMsgBuf, if i use CComBstr Message(lpMsgBuf); to copy the lpMsgBuf to BSTR. But this conversion shows memory leak. I am using LocalFree(lpMsgBuf); to release the lpMsgBuf. I am using USES_CONVERSION macro also. Is there anyway to resolve this? or what is the correct way to convert LPTSTR to BSTR? Thanks in advance.
Regards, Bala
Probably posting your code will help. :)
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler. -- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong. -- Iain Clarke -
Probably posting your code will help. :)
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler. -- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong. -- Iain ClarkeHere is my code: //Functions used to report the Error STDMETHODIMP CVBErrAgent::ReportError(IErrMsg *pErrMsg, SAFEARRAY** args) { //CCOmBstr variables for unformatted and formatted message CComBSTR formatstring, message; pErrMsg->get_ErrMsg(&formatstring); //Function to format the message. This function uses FormatMessage API to get formatted string. FormatMessageFromString(formatstring, args, &message); pErrMsg->put_ErrMsg(message); tlErrorBehavior behav; pErrMsg->get_Behavior(&behav); if(behav != tlErrorIgnore) return CErrSvcClientImpl::tl_Error(pErrMsg); return S_FALSE; } HRESULT CVBErrAgent::FormatMessageFromString(BSTR formatstring, SAFEARRAY **args, BSTR *outputstring) { std::vector vecargs; VARIANT HUGEP * pvar; long lbound, ubound, elcount; //Codes to read SAFEARRAY and creates the argsarray vector, this will be passed to FormatMessage API. if (FAILED (SafeArrayGetLBound(*args, 1, &lbound)) || FAILED (SafeArrayGetUBound(*args, 1, &ubound))) return E_INVALIDARG; elcount = ubound - lbound + 1; if(elcount == 1) { SafeArrayAccessData(*args, (void HUGEP **)&pvar); //If the SAFEARRAY consists of a single VARIANT that is of type VT_ARRAY then //We want to call SafeArrayToVector using the embedded array. if(pvar[0].vt & VT_ARRAY) { SafeArrayToVector(pvar->parray, vecargs); } else SafeArrayToVector(*args, vecargs); SafeArrayUnaccessData(*args); } else SafeArrayToVector(*args, vecargs); std::vector::iterator it; int count = vecargs.size(); vector argsarray(count); USES_CONVERSION; for(it = vecargs.begin(), count = 0; it != vecargs.end(); it++, count++) { if((*it).vt & VT_BSTR) { if((*it).vt & VT_BYREF) argsarray[count] = reinterpret_cast(OLE2T(*(*it).pbstrVal)); else argsarray[count] = reinterpret_cast(OLE2T((*it).bstrVal)); } else if((*it).vt & VT_I4 || (*it).vt & VT_I2) { if((*it).vt & VT_BYREF) argsarray[count] = reinterpret_cast(*(*it).plVal); else argsarray[count] = reinterpret_cast((*it).lVal); } } LPTSTR lpMsgBuf; DWORD messageflags = FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_ARGUMENT_ARRAY ; DWORD retval; //Format the message from the format string. retval = FormatMessage( messageflags, OLE2T(formatstring), NULL, LANG_SYSTEM_DEFAULT, (LPTSTR) &lpMsgBuf, 0, (va_list*)&argsarray[0] ); i
-
Here is my code: //Functions used to report the Error STDMETHODIMP CVBErrAgent::ReportError(IErrMsg *pErrMsg, SAFEARRAY** args) { //CCOmBstr variables for unformatted and formatted message CComBSTR formatstring, message; pErrMsg->get_ErrMsg(&formatstring); //Function to format the message. This function uses FormatMessage API to get formatted string. FormatMessageFromString(formatstring, args, &message); pErrMsg->put_ErrMsg(message); tlErrorBehavior behav; pErrMsg->get_Behavior(&behav); if(behav != tlErrorIgnore) return CErrSvcClientImpl::tl_Error(pErrMsg); return S_FALSE; } HRESULT CVBErrAgent::FormatMessageFromString(BSTR formatstring, SAFEARRAY **args, BSTR *outputstring) { std::vector vecargs; VARIANT HUGEP * pvar; long lbound, ubound, elcount; //Codes to read SAFEARRAY and creates the argsarray vector, this will be passed to FormatMessage API. if (FAILED (SafeArrayGetLBound(*args, 1, &lbound)) || FAILED (SafeArrayGetUBound(*args, 1, &ubound))) return E_INVALIDARG; elcount = ubound - lbound + 1; if(elcount == 1) { SafeArrayAccessData(*args, (void HUGEP **)&pvar); //If the SAFEARRAY consists of a single VARIANT that is of type VT_ARRAY then //We want to call SafeArrayToVector using the embedded array. if(pvar[0].vt & VT_ARRAY) { SafeArrayToVector(pvar->parray, vecargs); } else SafeArrayToVector(*args, vecargs); SafeArrayUnaccessData(*args); } else SafeArrayToVector(*args, vecargs); std::vector::iterator it; int count = vecargs.size(); vector argsarray(count); USES_CONVERSION; for(it = vecargs.begin(), count = 0; it != vecargs.end(); it++, count++) { if((*it).vt & VT_BSTR) { if((*it).vt & VT_BYREF) argsarray[count] = reinterpret_cast(OLE2T(*(*it).pbstrVal)); else argsarray[count] = reinterpret_cast(OLE2T((*it).bstrVal)); } else if((*it).vt & VT_I4 || (*it).vt & VT_I2) { if((*it).vt & VT_BYREF) argsarray[count] = reinterpret_cast(*(*it).plVal); else argsarray[count] = reinterpret_cast((*it).lVal); } } LPTSTR lpMsgBuf; DWORD messageflags = FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_ARGUMENT_ARRAY ; DWORD retval; //Format the message from the format string. retval = FormatMessage( messageflags, OLE2T(formatstring), NULL, LANG_SYSTEM_DEFAULT, (LPTSTR) &lpMsgBuf, 0, (va_list*)&argsarray[0] ); i
In your
FormatMessage
callbalakrishnan vinchu wrote:
retval = FormatMessage( messageflags, OLE2T(formatstring), NULL, LANG_SYSTEM_DEFAULT, (LPTSTR) &lpMsgBuf, 0, (va_list*)&argsarray[0] );
The line
(LPTSTR) &lpMsgBuf,
is wrong. It should be simply
lpMsgBuf,
Forget it. :)If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler. -- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong. -- Iain Clarkemodified on Wednesday, May 7, 2008 5:40 AM
-
In your
FormatMessage
callbalakrishnan vinchu wrote:
retval = FormatMessage( messageflags, OLE2T(formatstring), NULL, LANG_SYSTEM_DEFAULT, (LPTSTR) &lpMsgBuf, 0, (va_list*)&argsarray[0] );
The line
(LPTSTR) &lpMsgBuf,
is wrong. It should be simply
lpMsgBuf,
Forget it. :)If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler. -- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong. -- Iain Clarkemodified on Wednesday, May 7, 2008 5:40 AM
I changed my code as you explained in previous mail. LPTSTR lpMsgBuf = NULL; DWORD messageflags = FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_ARGUMENT_ARRAY ; DWORD retval; //Format the message from the format string. retval = FormatMessage( messageflags, OLE2T(formatstring), NULL, LANG_SYSTEM_DEFAULT, lpMsgBuf, // Suggested to pass simply lpMsgBug 0, (va_list*)&argsarray[0] ); if (!retval) return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, GetLastError()); CComBSTR message(lpMsgBuf); *outputstring = message.Detach(); LocalFree(lpMsgBuf); Now i am not getting the Formatted message, since retval returned from FormatMessgae API is zero (i.e 0), Because of this CComBSTR message didn't created. Also if i wont initialize lpMsgBuf = NULL, then functions just gives exception. Give me some suggestion. Thanks
Regards, Bala
-
I changed my code as you explained in previous mail. LPTSTR lpMsgBuf = NULL; DWORD messageflags = FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_ARGUMENT_ARRAY ; DWORD retval; //Format the message from the format string. retval = FormatMessage( messageflags, OLE2T(formatstring), NULL, LANG_SYSTEM_DEFAULT, lpMsgBuf, // Suggested to pass simply lpMsgBug 0, (va_list*)&argsarray[0] ); if (!retval) return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, GetLastError()); CComBSTR message(lpMsgBuf); *outputstring = message.Detach(); LocalFree(lpMsgBuf); Now i am not getting the Formatted message, since retval returned from FormatMessgae API is zero (i.e 0), Because of this CComBSTR message didn't created. Also if i wont initialize lpMsgBuf = NULL, then functions just gives exception. Give me some suggestion. Thanks
Regards, Bala
Once try this initialize lpMsgBuf as:
LPVOID lpMsgBuf;
and inside FormatMessage write lpMsgBuf as:(LPTSTR) &lpMsgBuf,
Mukesh Kumar Software Engineer
-
Here is my code: //Functions used to report the Error STDMETHODIMP CVBErrAgent::ReportError(IErrMsg *pErrMsg, SAFEARRAY** args) { //CCOmBstr variables for unformatted and formatted message CComBSTR formatstring, message; pErrMsg->get_ErrMsg(&formatstring); //Function to format the message. This function uses FormatMessage API to get formatted string. FormatMessageFromString(formatstring, args, &message); pErrMsg->put_ErrMsg(message); tlErrorBehavior behav; pErrMsg->get_Behavior(&behav); if(behav != tlErrorIgnore) return CErrSvcClientImpl::tl_Error(pErrMsg); return S_FALSE; } HRESULT CVBErrAgent::FormatMessageFromString(BSTR formatstring, SAFEARRAY **args, BSTR *outputstring) { std::vector vecargs; VARIANT HUGEP * pvar; long lbound, ubound, elcount; //Codes to read SAFEARRAY and creates the argsarray vector, this will be passed to FormatMessage API. if (FAILED (SafeArrayGetLBound(*args, 1, &lbound)) || FAILED (SafeArrayGetUBound(*args, 1, &ubound))) return E_INVALIDARG; elcount = ubound - lbound + 1; if(elcount == 1) { SafeArrayAccessData(*args, (void HUGEP **)&pvar); //If the SAFEARRAY consists of a single VARIANT that is of type VT_ARRAY then //We want to call SafeArrayToVector using the embedded array. if(pvar[0].vt & VT_ARRAY) { SafeArrayToVector(pvar->parray, vecargs); } else SafeArrayToVector(*args, vecargs); SafeArrayUnaccessData(*args); } else SafeArrayToVector(*args, vecargs); std::vector::iterator it; int count = vecargs.size(); vector argsarray(count); USES_CONVERSION; for(it = vecargs.begin(), count = 0; it != vecargs.end(); it++, count++) { if((*it).vt & VT_BSTR) { if((*it).vt & VT_BYREF) argsarray[count] = reinterpret_cast(OLE2T(*(*it).pbstrVal)); else argsarray[count] = reinterpret_cast(OLE2T((*it).bstrVal)); } else if((*it).vt & VT_I4 || (*it).vt & VT_I2) { if((*it).vt & VT_BYREF) argsarray[count] = reinterpret_cast(*(*it).plVal); else argsarray[count] = reinterpret_cast((*it).lVal); } } LPTSTR lpMsgBuf; DWORD messageflags = FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_ARGUMENT_ARRAY ; DWORD retval; //Format the message from the format string. retval = FormatMessage( messageflags, OLE2T(formatstring), NULL, LANG_SYSTEM_DEFAULT, (LPTSTR) &lpMsgBuf, 0, (va_list*)&argsarray[0] ); i
balakrishnan vinchu wrote:
*outputstring = message.Detach();
you already taken the ownership of the BSTR, created and associated with the CComBSTR, by Detach method; hence CComBSTR is not expected to release the BSTR. If you are expecting so then you are not supposed to return that buffer as out parameter (outputstring). this outputstring is not released and i think, so the tool you used to detect memory leak points to the creator of it, CComBSTR message(lpMsgBuf);.
-
I changed my code as you explained in previous mail. LPTSTR lpMsgBuf = NULL; DWORD messageflags = FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_ARGUMENT_ARRAY ; DWORD retval; //Format the message from the format string. retval = FormatMessage( messageflags, OLE2T(formatstring), NULL, LANG_SYSTEM_DEFAULT, lpMsgBuf, // Suggested to pass simply lpMsgBug 0, (va_list*)&argsarray[0] ); if (!retval) return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, GetLastError()); CComBSTR message(lpMsgBuf); *outputstring = message.Detach(); LocalFree(lpMsgBuf); Now i am not getting the Formatted message, since retval returned from FormatMessgae API is zero (i.e 0), Because of this CComBSTR message didn't created. Also if i wont initialize lpMsgBuf = NULL, then functions just gives exception. Give me some suggestion. Thanks
Regards, Bala
Is this the right way? LPVOID lpMsgBuf; DWORD messageflags = FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_ARGUMENT_ARRAY ; DWORD retval; //Format the message from the format string. retval = FormatMessage( messageflags, OLE2T(formatstring), NULL, LANG_SYSTEM_DEFAULT, (LPTSTR) &lpMsgBuf, 0, (va_list*)&argsarray[0] ); if (!retval) return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, GetLastError()); CComBSTR message; message = T2OLE(LPTSTR(lpMsgBuf)); message.CopyTo(outputstring); I modified LPTSTR lpMsgBuf; to LPVOID lpMsgBuf; And converted LPTSTR to LPOLESTR. Am i doing correct here? :-)
Regards, Bala
-
I changed my code as you explained in previous mail. LPTSTR lpMsgBuf = NULL; DWORD messageflags = FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_ARGUMENT_ARRAY ; DWORD retval; //Format the message from the format string. retval = FormatMessage( messageflags, OLE2T(formatstring), NULL, LANG_SYSTEM_DEFAULT, lpMsgBuf, // Suggested to pass simply lpMsgBug 0, (va_list*)&argsarray[0] ); if (!retval) return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, GetLastError()); CComBSTR message(lpMsgBuf); *outputstring = message.Detach(); LocalFree(lpMsgBuf); Now i am not getting the Formatted message, since retval returned from FormatMessgae API is zero (i.e 0), Because of this CComBSTR message didn't created. Also if i wont initialize lpMsgBuf = NULL, then functions just gives exception. Give me some suggestion. Thanks
Regards, Bala
You're right (and I was wrong...). Whenever you use
FORMAT_MESSAGE_ALLOCATE_BUFFER
you have to pass the address of the variable, hence your code was correct. :)If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler. -- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong. -- Iain Clarke -
balakrishnan vinchu wrote:
*outputstring = message.Detach();
you already taken the ownership of the BSTR, created and associated with the CComBSTR, by Detach method; hence CComBSTR is not expected to release the BSTR. If you are expecting so then you are not supposed to return that buffer as out parameter (outputstring). this outputstring is not released and i think, so the tool you used to detect memory leak points to the creator of it, CComBSTR message(lpMsgBuf);.
Is this the right way? LPVOID lpMsgBuf; DWORD messageflags = FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_ARGUMENT_ARRAY ; DWORD retval; //Format the message from the format string. retval = FormatMessage( messageflags, OLE2T(formatstring), NULL, LANG_SYSTEM_DEFAULT, (LPTSTR) &lpMsgBuf, 0, (va_list*)&argsarray[0] ); if (!retval) return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, GetLastError()); CComBSTR message; message = T2OLE(LPTSTR(lpMsgBuf)); message.CopyTo(outputstring); I modified LPTSTR lpMsgBuf; to LPVOID lpMsgBuf; And converted LPTSTR to LPOLESTR. Am i doing correct here? [Smile]
Regards, Bala
-
Is this the right way? LPVOID lpMsgBuf; DWORD messageflags = FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_ARGUMENT_ARRAY ; DWORD retval; //Format the message from the format string. retval = FormatMessage( messageflags, OLE2T(formatstring), NULL, LANG_SYSTEM_DEFAULT, (LPTSTR) &lpMsgBuf, 0, (va_list*)&argsarray[0] ); if (!retval) return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, GetLastError()); CComBSTR message; message = T2OLE(LPTSTR(lpMsgBuf)); message.CopyTo(outputstring); I modified LPTSTR lpMsgBuf; to LPVOID lpMsgBuf; And converted LPTSTR to LPOLESTR. Am i doing correct here? :-)
Regards, Bala
Is this working correctly now? :)
Mukesh Kumar Software Engineer
-
Is this the right way? LPVOID lpMsgBuf; DWORD messageflags = FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_ARGUMENT_ARRAY ; DWORD retval; //Format the message from the format string. retval = FormatMessage( messageflags, OLE2T(formatstring), NULL, LANG_SYSTEM_DEFAULT, (LPTSTR) &lpMsgBuf, 0, (va_list*)&argsarray[0] ); if (!retval) return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, GetLastError()); CComBSTR message; message = T2OLE(LPTSTR(lpMsgBuf)); message.CopyTo(outputstring); I modified LPTSTR lpMsgBuf; to LPVOID lpMsgBuf; And converted LPTSTR to LPOLESTR. Am i doing correct here? [Smile]
Regards, Bala
the question is not about "message" variable how you clean up "outputstring" variable.