String manipulation

I have a project, and I need to work with Strings (Append, Copy, and etc). I would be happy with CComBSTR, but I need a string address to pass to another function. CComBSTR has a length that is stored as an integer at the memory location preceding the data in the string, that is why I cannot pass it to that function that accepts LPCTSTR. I tried everything (Detach, pointers, conversions OLE2CT), and nothing helps. Can anybody suggest me anything else besides CComBSTR?!

Thank you.
[493 byte] By [tigrushke] at [2007-11-19 4:18:54]
# 1 Re: String manipulation
Why not use the STL string class?

Are you using CComBSTR purely to simplify concatenation etc.
tarantulaman at 2007-11-11 0:39:53 >
# 2 Re: String manipulation
Why not use the STL string class?

Are you using CComBSTR purely to simplify concatenation etc.

Yes, I am using CComBSTR to simplify concatenation. BSTR string type do not support
any string manipulation.

After string concatenation I need to converte some string back to BSTR to pass it to my other function.
tigrushke at 2007-11-11 0:40:53 >
# 3 Re: String manipulation
Hi Tigrushke ,

Please see if the following snippet helps,

USES_CONVERSION; //declare this macro
CComBSTR bstrTest = "String manipulation"; //a CComBSTR

CString str = W2A(bstrTest); //This will convert to character string

Thanks,
bugfighter
bugfighter at 2007-11-11 0:41:46 >
# 4 Re: String manipulation
Hi Tigrushke ,

Please see if the following snippet helps,

USES_CONVERSION; //declare this macro
CComBSTR bstrTest = "String manipulation"; //a CComBSTR

CString str = W2A(bstrTest); //This will convert to character string

Thanks,
bugfighter

Thank you, but it gives me a CString type. The problem with CComBSTR is that after I convert it to LPCTSTR, or BSTR string type, it doesn't show that it represent a string memory location address i.e. "0x0042407c 'string' ", it shows just "0x0042407c". CComBSTR stores an integer value (BSTR length) before the string address in the memory, that is why when I pass my newly converted BSTR from CComBSTR to shell structure (SHFILEOPSTRUCT), it doesn't recognize it, therefore I got an error 1026 that is not defiend in Errors.
tigrushke at 2007-11-11 0:42:54 >
# 5 Re: String manipulation
In my sample code I was just giving you an example of how you can convert a CComBSTR.
From your initial post I thought what you needed was to pass this string to a function that accepts LPCTSTR.

Can you please explain the problem in detail?
Is it about using CComBSTR strings with SHFileOperation ()?
bugfighter at 2007-11-11 0:43:52 >
# 6 Re: String manipulation
CString::AllocSysString() converts the CString to BSTR. You may later free the memory using ::SysFreeString().
Kheun at 2007-11-11 0:44:51 >
# 7 Re: String manipulation
I have tested the code below (Win2K). Please verify if this is what you need.

USES_CONVERSION;
CComBSTR bstrTestSrc = "D:\\TestFolder\\test.txt";
CComBSTR bstrTestDst = "D:\\TestFolder\\TestDest\\test.txt";

SHFILEOPSTRUCT FileOp;
FileOp.wFunc = FO_COPY;
FileOp.pFrom = W2A(bstrTestSrc);
FileOp.pTo = W2A(bstrTestDst);
FileOp.fFlags = FOF_ALLOWUNDO | FOF_FILESONLY | FOF_NOCONFIRMATION | FOF_NOERRORUI;

if(SHFileOperation(&FileOp) ==0) MessageBox("copied successfully!");

FileOp.wFunc = FO_DELETE;

if(SHFileOperation(&FileOp) ==0) MessageBox("deleted successfully!");
The code copies a test file to the destination folder first and deletes it from the source folder.

Thanks,
bugfighter
bugfighter at 2007-11-11 0:45:52 >
# 8 Re: String manipulation
I have tested the code below (Win2K). Please verify if this is what you need.

USES_CONVERSION;
CComBSTR bstrTestSrc = "D:\\TestFolder\\test.txt";
CComBSTR bstrTestDst = "D:\\TestFolder\\TestDest\\test.txt";

SHFILEOPSTRUCT FileOp;
FileOp.wFunc = FO_COPY;
FileOp.pFrom = W2A(bstrTestSrc);
FileOp.pTo = W2A(bstrTestDst);
FileOp.fFlags = FOF_ALLOWUNDO | FOF_FILESONLY | FOF_NOCONFIRMATION | FOF_NOERRORUI;

if(SHFileOperation(&FileOp) ==0) MessageBox("copied successfully!");

FileOp.wFunc = FO_DELETE;

if(SHFileOperation(&FileOp) ==0) MessageBox("deleted successfully!");
The code copies a test file to the destination folder first and deletes it from the source folder.

Thanks,
bugfighter

It is very strange, but I got an error trying to convert strings as:
error C2440: 'initializing' : cannot convert from 'char *' to 'const unsigned short *'
Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast.
Error executing cl.exe.
tigrushke at 2007-11-11 0:46:55 >
# 9 Re: String manipulation
OK,
Any luck after an explicit typecast?!

It continues to work fine on my m/c with this...

FileOp.pFrom = reinterpret_cast<LPCTSTR>W2A(bstrTestSrc);

Thanks,
bugfighter
bugfighter at 2007-11-11 0:47:58 >
# 10 Re: String manipulation
It is very strange, but I got an error trying to convert strings as:
error C2440: 'initializing' : cannot convert from 'char *' to 'const unsigned short *'
Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast.
Error executing cl.exe.

It's might be that you are compiling UNICODE.

Also some confusion about BSTR.

Like stated a BSTR has a length prefix but a BSTR is also zero-terminated (the best/worst of both worlds). Note that a BSTR pointer doesn't point to the prefix but points to the first character in the string i.e.

BSTR Pointer points here
------
|
________________v___________________________________________________
| Length Prefix | String ......... | Zero terminating character |
---------------------
Memory layout of BSTR (not to scale)


So you can safely cast a BSTR to LPOLESTR (but _not_ the other way around).

void f(BSTR b, LPOLESTR o)
{
LPOLESTR l_o = b; // ok
BSTR l_b = o; // very bad
}

But as BSTR and LPOLESTR are defined as:

typedef /* [wire_marshal] */ OLECHAR *BSTR;
typedef /* [string] */ OLECHAR *LPOLESTR;

The compiler don't see any difference between them and the code above compiles just fine even though one of the rows are _very_ wrong. Therefore when using BSTR and LPOLESTR you always have to be careful because the compiler can't help you.

A possible reason why the debugger doesn't show a string value might because if you're running VC6 it is set to default not to show UNICODE strings (and a BSTR is always an UNICODE string). Check Tools->Options->Editor Tab. Verify that the checkbox "Display unicode strings" is checked.

Since a BSTR is always unicode it means that initializing a CComBSTR like this:

CComBSTR l_bstr = "Test";

Will cause an unnecessary conversion from ansi string to unicode string. A better way to initialize a CComBSTR would be this:

CComBSTR l_bstr = L"Test";

The 'L' means that the string is a unicode string.

Hope this helps
marten_range at 2007-11-11 0:49:01 >