Reputation: 2299
I am trying to call a C# library from C++. Here's the function that makes the first call:
CapsReport::CapsReport(const CCOMString& reportFileName, CCDatabase* pDatabase)
: m_pDatabase(pDatabase), m_pReportServer(__uuidof(ReportServer))
{
::CoInitialize(NULL);
SetReportName(reportFileName);
// public void Load(string DSNname, string userName, string password, string reportFileName)
BSTR dsnBstr = pDatabase->DataSource().GetManagedBstr();
BSTR userBstr = pDatabase->UserName().GetManagedBstr();
BSTR passwordBstr = pDatabase->Password().GetManagedBstr();
BSTR reportNameBstr = ::SysAllocString(reportFileName);
m_pReportServer->Load(dsnBstr, userBstr, passwordBstr, reportNameBstr);
::SysFreeString(reportNameBstr);
}
By the time the Load() method is called, all three BSTRs returned by GetManagedBstr() contain the password. I'm trying to figure out why.
DataSource(), UserName() and Password() all return objects of type CCOMString:
CCOMString UserName() { return m_User; };
CCOMString Password() { return m_Pwd; };
CCOMString DataSource() { return m_DSN; };
I didn't want to have to call ::SysAllocString() and ::SysFreeString() every time I wanted to pass a CCOMString into a C# library, so I added a private BSTR member to the CCOMString class initialized to NULL. In the destructor, I check to see if that member is null. If it is not, I call ::SysFreeString() and set it to NULL.
The GetManagedBstr() method uses an existing member function of CCOMString named AllocSysString(). First, here's GetManagedBstr():
BSTR CCOMString::GetManagedBstr()
{
m_bstr = AllocSysString();
return m_bstr;
}
Now, here's AllocSysString():
BSTR CCOMString::AllocSysString() const
{
#ifndef _UNICODE
int nLen = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)m_pszString, GetLength(), NULL, NULL);
BSTR bstr = ::SysAllocString(NULL, nLen+1);
MultiByteToWideChar(CP_ACP, 0, (LPCSTR)m_pszString, GetLength(), bstr, nLen);
#else
int nLen = _tcslen(m_pszString);
//BSTR bstr = ::SysAllocStringLen(NULL, nLen);
BSTR bstr = ::SysAllocString(m_pszString);
// _tcscpy_s(bstr, nLen, m_pszString);
#endif
return bstr;
}
m_pszString is merely the plain ordinary C++ string wrapped by CCOMString.
A BSTR object is a pointer. Somehow, all three BSTR objects are ending up pointing to the same memory location, even though they should have come from different CCOMString objects. How is this happening?
Upvotes: 1
Views: 610