I have CComBSTR in my code and have to pass it to function with argument type LPCSTR.
How to convert CComBSTR to LPCSTR?
There are many ways to do this, but the ATL way would be using Using MFC MBCS/Unicode Conversion Macros:
void SomeCode()
{
USES_CONVERSION;
CComBSTR bstr(L"hello world");
LPCSTR lp = W2CA(bstr); // bstr is a LPWSTR
}
Related
I need to use WinAPI function to restart a windows service, I am not familiar with strings in C++.
My function receive as parameter: const CStringA& serviceName:
bool MyClassName::RestartServer(const CStringA& serviceName)
When I obtain SC Handle via OpenService(..) I need to provide type LPCWSTR :
SC_HANDLE SHandle = OpenService(hSCManager, LPCWSTR serviceNameAsWideString, SC_MANAGER_ALL_ACCESS);
How do I convert CStringA to LPCWSTR?
I tried to following:
CA2W(serviceName, CP_UTF8);
CString str("MyServiceName"); CStringW strw(str); LPCWSTR ptr = strw;
Both did not work properly, they compiled, but when I tried to execute the code.
It failed to OpenService().
What worked:
LPCWSTR newString = serviceName.AllocSysString();
What am I missing here? Why 1 and 2 did not work? Why 3 worked?
How do I properly deallocate newString?
Your code requires a conversion because you are calling the TCHAR-based OpenService() macro, which maps to either OpenServiceW() or OpenServiceA() depending on whether UNICODE is defined:
__checkReturn
WINADVAPI
SC_HANDLE
WINAPI
OpenServiceA(
__in SC_HANDLE hSCManager,
__in LPCSTR lpServiceName,
__in DWORD dwDesiredAccess
);
__checkReturn
WINADVAPI
SC_HANDLE
WINAPI
OpenServiceW(
__in SC_HANDLE hSCManager,
__in LPCWSTR lpServiceName,
__in DWORD dwDesiredAccess
);
#ifdef UNICODE
#define OpenService OpenServiceW
#else
#define OpenService OpenServiceA
#endif // !UNICODE
In your case, UNICODE is clearly being defined in your project, so your code is really calling OpenServiceW(), which is why it expects an LPCWSTR as input.
Your RestartServer() method takes a CStringA (char-based ANSI) string as input, so you should use OpenServiceA() explicitly to match the same character type, no conversion needed:
bool MyClassName::RestartServer(const CStringA& serviceName)
{
...
SC_HANDLE SHandle = OpenServiceA(hSCManager, serviceName, SC_MANAGER_ALL_ACCESS);
...
}
Otherwise, if you are going to continue using TCHAR-based functionality in your code 1, then you should change your RestartServer() method to take a CString instead of a CStringA so it adopts the same ANSI/Unicode mapping that OpenService() does (and other TCHAR-based functions do), again avoiding a conversion:
1: which you should not do, since there is rarely a need to ever write code for Win9x/ME nowadays. Windows has been a Unicode-based OS since NT4.
bool MyClassName::RestartServer(const CString& serviceName)
If that is not an option for you, then CA2W() will work just fine:
bool MyClassName::RestartServer(const CStringA& serviceName)
{
USES_CONVERSION;
...
SC_HANDLE SHandle = OpenService(hSCManager, ATL::CA2W(serviceName), SC_MANAGER_ALL_ACCESS);
...
}
Though, you might consider just using CString internally and let it handle a conversion if needed:
bool MyClassName::RestartServer(const CStringA& serviceName)
{
...
SC_HANDLE SHandle = OpenService(hSCManager, CString(serviceName), SC_MANAGER_ALL_ACCESS);
...
}
Or, make the code conditional:
bool MyClassName::RestartServer(const CStringA& serviceName)
{
...
SC_HANDLE SHandle = OpenService(hSCManager,
#ifdef UNICODE
CStringW(serviceName)
#else
serviceName
#endif
, SC_MANAGER_ALL_ACCESS);
...
}
CStringA and CStringW have constructors taking both const char* and const wchar_t* C strings.
Write following:
CStringW serviceNameW( serviceName );
About AllocSysString, it creates a copy in BSTR, they’re more complex than C strings, they’re null-terminated too but they also have length at negative offset. If you want to do manual memory management, call SysFreeString on the pointer. Or if you want BSTR but don’t want manual memory management, use CComBSTR class.
I have a method in C# DLL having one input and two output parameters. All the three are String.
I want to call that function from firebreath C++. How do I have to pass the BSTR* value from C++?. And how do I get that out values from C#?
I have already tried to get using
BSTR* userKey =NULL;
*userKey = ::SysAllocString(L"Hello Managed World");
But its not working.
C# function:
public void GetPublicKeyforEncryption(String ToUserEmailAddress, out String userKey , out String mySharedKey)
C++ Calling function:
std::wstring& ToUserEmailaddress;
BYTE **bEncryptData = NULL;
BSTR bsData = SysAllocStringLen(ToUserEmailaddress.data(), ToUserEmailaddress.size());
BSTR* userKey =NULL;
BSTR* mySharedKey =NULL;
CSharpInterface->GetPublicKeyforEncryption(bsData,userKey ,mySharedKey );
In the above c++ GetPublicKeyforEncryption bsData value is passed correctly,How will i allocate memory and Pass
userKey ,mySharedKey in the BSTR* type
Anyone can solve this issue?
Help me.
Thanks
Sanju
That's not correct code, BSTR is already a pointer type. You need to pass a pointer to your BSTR variable so the called method can assign it. Generic code that assumes just one out string argument:
BSTR retval = NULL;
HRESULT hr = CSharpInterface->SomeMethod(&retval);
if (SUCCEEDED(hr)) {
// Use retval
//...
SysFreeString(retval);
}
Here is my need
BSTR l_strArgs;
LPCWSTR sth;
//----
//---
OutputDebugStringW(sth);
How to convert BSTR to LPCWSTR ?
Is there any header only library that coverts any string type(microsoft) to LPCWSTR type ?
Just cover NULL scenario and you're good to go
BSTR l_strArgs;
LPCWSTR sth = strArgs ? strArgs : L"";
As you mentioned ATL in the tag, here is ATL-style one-liner:
OutputDebugString(CString(l_strArgs));
or, to make sure you are staying in Unicode domain:
OutputDebugStringW(CStringW(l_strArgs));
I just found this one
BSTR l_strArgs;
LPCWSTR sth;
CString cs(_com_util::ConvertBSTRToString(l_strArg));
sth = cs;
OutputDebugStringW(sth);
BSTRs become easier to handle when you use a wrapper like _bstr_t instead. Here's the microsoft documentation on them
http://msdn.microsoft.com/en-us/library/zthfhkd6%28v=VS.100%29.aspx
As you would expect, one of the _bstr_t constructors takes a BSTR parameter. There is also an operator to return a const wchar_t* which you should be able to cast to LPCWSTR.
Hope this helps
From book ATL Internals, I knew BSTR is different from OLECHAR*, and there are CComBSTR and CString for BSTR.
According MSDN Allocating and Releasing Memory for a BSTR, I knew memory management responsibility for caller/callee.
Take this line from MSDN,
HRESULT CMyWebBrowser::put_StatusText(BSTR bstr)
I still do not know how to handle bstr properly in my implementation. Since I still have a basic question for BSTR -- should we treat bstr as a value (like int) or as a reference (like int*), at least on COM interface boundary.
I want to convert BSTR as soon as possible to CString/CComBSTR in my implementation. Value or Reference semantic will be totally different case for the conversion. I've digged into CComBSTR.Attach, CComBSTR.AssignBSTR, etc. But the code cannot solve my doubts.
MSDN CComBSTR.Attach has some code snip, I feel it is wrong since it is not obey Allocating and Releasing Memory for a BSTR. ATL Internals said SetSysString will 'free the original BSTR passed in', if I used it, it will violate BSTR argument convention, just like CComBSTR.Attach.
All in all, I want to using CString to handle raw BSTR in implementation, but do not know the correct way...I've written some just work code in my projects, but I always feel nervous since I don't know whether I am correct.
Let me talk coding language
HRESULT CMyWebBrowser::put_StatusText(BSTR bstr)
{
// What I do NOT know
CString str1; // 1. copy bstr (with embeded NUL)
CString str2; // 2. ref bstr
// What I know
CComBSTR cbstr1;
cbstr1.AssignBSTR(bstr); // 3. copy bstr
CComBSTR cbstr2;
cbstr2.Attach(bstr); // 4. ref bstr, do not copy
// What I do NOT know
// Should we copy or ref bstr ???
}
CComBSTR is just a RAII wrapper around raw BSTR. So feel free to use CComBSTR instead of raw BSTR to help writing code that is exception-safe, that makes it harder to leak resources (i.e. the raw BSTR), etc.
If the BSTR is an input parameter, it's just like a const wchar_t* (with length prefixed, and potentially some NULs L'\0' characters inside). If the BSTR doesn't have NULs embedded inside, you can simply pass it to a CString constructor, that will make a deep-copy of it, and you can locally work with your CString. Modifications to that CString won't be visible on the original BSTR. You can use std::wstring as well (and note that std::wstring can handle embedded NULs as well).
void DoSomething(BSTR bstrInput)
{
std::wstring myString(bstrInput);
// ... work with std::wstring (or CString...) inside here
}
Instead, if the BSTR is an output parameter, then it is passed using another level of indirection, i.e. BSTR*. In this case, you can use CComBSTR::Detach() inside your method to release the BSTR safely wrapped into the CComBSTR, and transfer its ownership to the caller:
HRESULT DoSomething( BSTR* pbstrOut )
{
// Check parameter pointer
if (pbstrOut == nullptr)
return E_POINTER;
// Guard code with try-catch, since exceptions can't cross COM module boundaries.
try
{
std::wstring someString;
// ... work with std::wstring (or CString...) inside here
// Build a BSTR from the ordinary string
CComBSTR bstr(someString.c_str());
// Return to caller ("move semantics", i.e. transfer ownership
// from current CComBSTR to the caller)
*pbstrOut = bstr.Detach();
// All right
return S_OK;
}
catch(const std::exception& e)
{
// Log exception message...
return E_FAIL;
}
catch(const CAtlException& e)
{
return e; // implicit cast to HRESULT
}
}
Basically, the idea is to use BSTR (wrapped in a RAII class like CComBSTR) only at the boundary, and do the local work using std::wstring or CString.
As a "bouns reading", consider Eric Lippert's guide to BSTR semantics.
Having BSTR on input, you are not responsible to release it. Converting to CString is easy:
CString sValue(bstr);
or, if you prefer to keep Unicode characters on MBCS build:
CStringW sValue(bstr);
If you need to convert back when you have [out] parameter, you do (simple version):
VOID Foo(/*[out]*/ BSTR* psValue)
{
CString sValue;
*psValue = CComBSTR(sValue).Detach();
}
Full version is:
STDMETHODIMP Foo(/*[out]*/ BSTR* psValue)
{
_ATLTRY
{
ATLENSURE_THROW(psValue, E_POINTER); // Parameter validation
*psValue = NULL; // We're responsible to initialize this no matter what
CString sValue;
// Doing our stuff to get the string value into variable
*psValue = CComBSTR(sValue).Detach();
}
_ATLCATCH(Exception)
{
return Exception;
}
return S_OK;
}
It's been years since I have done C++ let alone ATL code
I have this method that needs surgical help :(
This is for a mobile app so I don't want to use CString and MFC
I need to convert the BSTR* str to the correct type LPCTSTR for use in the registry Set.Value method
STDMETHODIMP CAXSampleCtl::SendMSG(BSTR* str)
{
CRegKey key;
key.Create(HKEY_LOCAL_MACHINE, _T("MyKeyName"));
key.SetValue( str <<<--- nope, _T("MyValueName"));
key.Flush();
key.Close();
return S_OK;
}
COLE2T macro is just for you, see String Conversion Classes and Macros
To convert to a BSTR, pass the existing string to the constructor of
CComBSTR. To convert from a BSTR, use COLE2[C]DestinationType[EX],
such as COLE2T.