Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

CString to LPCSTR

62 views
Skip to first unread message

Al

unread,
Dec 28, 2007, 10:48:01 PM12/28/07
to
I am getting an error
<error>
C2440: 'type cast' : cannot covert from 'CString' to 'LPCSTR'
<error>

I am using VS2005 and I am taking code out of CodeGuru and I am getting this
error message. I have read something about the CString length has change
using VS2005. How can I convert CString to LPCSTR? To be a little more
specific I am trying to StreamIn & StreamOut with a CRichEditCtrl.
--
Just Al

Joseph M. Newcomer

unread,
Dec 28, 2007, 11:05:31 PM12/28/07
to
Do you really want an LPCSTR? Wouldn't you rather have an LPCTSTR?

The code is probably incorrectly written, and probably should have said LPCTSTR. Reason
is that CString used to default to 8-bit characters in a standard build, but in VS2005,
they sensibly changed builds to default to Unicode. So code that was improperly written
would work in 8-bit builds, but correctly produces error messages when built in Unicode.

Note that when giving error messages like this, it is considered sensible to actually show
the source line that produced the error, and ideally the declarations of all variables
involved in the statement.
joe

Joseph M. Newcomer [MVP]
email: newc...@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm

Al

unread,
Dec 28, 2007, 11:43:01 PM12/28/07
to
This is one version that I have been trying to use but the same problem
arises with other versions of similar code. I have showed below where the
errors occur.


<code>
static DWORD CALLBACK EditStreamCallBack(DWORD dwCookie, LPBYTE pbBuff, LONG
cb,
LONG *pcb)
{
CString *pstr = (CString *)dwCookie;

if( pstr->GetLength() < cb )
{
*pcb = pstr->GetLength();
<error>
memcpy(pbBuff, (LPCSTR)*pstr, *pcb );
<error>
pstr->Empty();
}
else
{
*pcb = cb;
<error>
memcpy(pbBuff, (LPCSTR)*pstr, *pcb );
<error>
*pstr = pstr->Right( pstr->GetLength() - cb );
}
return 0;
}
<code>

--
Just Al

David Webber

unread,
Dec 29, 2007, 7:32:11 AM12/29/07
to

"Al" <A...@discussions.microsoft.com> wrote in message
news:29FCF33E-3B59-400D...@microsoft.com...

> This is one version that I have been trying to use but the same problem
> arises with other versions of similar code. I have showed below where the
> errors occur.

Then act on Joe's advice.

> CString *pstr = (CString *)dwCookie;

// I assume that you are sure that dwCookie is the address of a CString
// (and not for example a char *, wchar_t * or anything else)?

> if( pstr->GetLength() < cb )
> {
> *pcb = pstr->GetLength();
> <error>
> memcpy(pbBuff, (LPCSTR)*pstr, *pcb );
> <error>

As Joe said

memcpy( pbBuff, (LPCTSTR)(*pstr), ((*pcb)+1)*(sizeof TCHAR) );

[I have added brackets which may or may not be necessary - my memory is a
seive on this so I play safe - and, with the "+1", I have copied the nul
TCHAR on the end. It's your job to make sure pbbuf is big enough.]

Dave
--
David Webber
Author of 'Mozart the Music Processor'
http://www.mozart.co.uk
For discussion/support see
http://www.mozart.co.uk/mozartists/mailinglist.htm

Al

unread,
Dec 29, 2007, 9:05:01 AM12/29/07
to
Thanks for the help and the extra help. I was thinking that I had to convert
the CString to a LPCSTR and I wasn't getting the fact that I could just
change the code to LPCTSTR. Thanks for clearing that up.
--
Just Al

Joseph M. Newcomer

unread,
Dec 29, 2007, 9:36:20 AM12/29/07
to
On Fri, 28 Dec 2007 20:43:01 -0800, Al <A...@discussions.microsoft.com> wrote:

>This is one version that I have been trying to use but the same problem
>arises with other versions of similar code. I have showed below where the
>errors occur.
>
>
><code>
>static DWORD CALLBACK EditStreamCallBack(DWORD dwCookie, LPBYTE pbBuff, LONG
>cb,
> LONG *pcb)
>{
> CString *pstr = (CString *)dwCookie;
>
> if( pstr->GetLength() < cb )

****
This should be <=, and it is comparing the wrong value. It MUST be
if(pstr->GetLength() * sizeof(TCHAR) <= cb)
or you will overwrite the buffer. This code was obviously written by someone who didn't
understand Unicode, and you should post a correction to the codeproject article when you
are done.
****


> {
> *pcb = pstr->GetLength();
><error>

****
WHAT <error>? It would have been useful to know what kind of error occurred here! When
asking questions like this, you have to show BOTH the source line (and all declarations)
AND the error message!

However, one thing is wrong with this: it is supposed to be a byte count of the number of
characters to transfer, but instead it is given as a *character* count, which is
erroneous. It should have said
*pcb = pstr->GetLength() * sizeof(TCHAR);
****

> memcpy(pbBuff, (LPCSTR)*pstr, *pcb );
><error>

****
This one is obvious: it is caused by the erroneous use of LPCSTR instead of LPCTSTR. In
addition, the length is wrong; it should have been written as
memcpy(pbBuff, (LPCTSTR)*ptr, *pcb);
but note above that *pcb is erroneously computed, and until you apply the first
correction, the code as written using *pcb as the length is erroneous
*****


> pstr->Empty();
> }
> else
> {
> *pcb = cb;

****
Note that this can be erroneous if cb is an odd number; to be absolutely correct, you
should make sure that this number is not an odd number in Unicode builds
****


><error>
> memcpy(pbBuff, (LPCSTR)*pstr, *pcb );
><error>

****
Same problem as above: the code is not Unicode-aware, and should have been LPCTSTR
****


> *pstr = pstr->Right( pstr->GetLength() - cb );

*****
For the same reasons given above, this non-Unicode-aware code is erroneous. It must be
rewritten as
*pstr = pstr->Right(pstr->GetLenght() - (cb / sizeof(TCHAR));
which is another reason you must make sure cb is an even value, and truncate downwards if
it is not.

One of the better features of VS2005 defaulting to Unicode builds is that it does not
allow the kind of sloppiness that created this code to continue. Consider the error
messages a Good Thing, they kept fundamentally incorrect code from compiling and doing
serious damage.
joe

****
> }
> return 0;
>}
><code>

David Ching

unread,
Dec 29, 2007, 9:40:14 AM12/29/07
to
"Al" <A...@discussions.microsoft.com> wrote in message
news:3E2D7296-DB98-4F4E...@microsoft.com...

> Thanks for the help and the extra help. I was thinking that I had to
> convert
> the CString to a LPCSTR and I wasn't getting the fact that I could just
> change the code to LPCTSTR. Thanks for clearing that up.
> --
> Just Al
>

The proper thing to do depends on what format of text the RichEdit control
is expecting. Since you're apparently building the project with UNICODE
(since CString doesn't cast to LPCSTR), I assume the RichEdit control is
expecting Unicode text. In that case, yes, you do can cast the CString to
LPCTSTR (which translates to LPCWSTR) and put that into the byte buffer of
the RichEdit control. But the memcpy() last parameter needs to be limited
by the minimum size of the byte buffer, or the length of the string. I like
to use StringCbCopy() to ensure the destination buffer does not get
overwritten.

Also, the RichEdit callback works such that if the entire contents can't fit
into the byte buffer, then you get called back again to put the next chunk
of contents into the byte buffer. Your callback needs to remember where it
left off the previous time so it can start at that point in the string. I
don't see the code to do that here.

-- David


Al

unread,
Dec 29, 2007, 10:16:00 AM12/29/07
to
Joseph

Thanks for all of the indepth explaination of the errors and with the
corrections on the code. I appreciate everyones help on this.

THANKS!

--
Just Al

Joseph M. Newcomer

unread,
Dec 29, 2007, 1:58:10 PM12/29/07
to
Actually, it does take that into account; the string = string.Right(...) handles lopping
off the first part. Of course, since it isn't Unicode-aware, it gets it wrong in a number
of ways, but once fixed for Unicode-awareness, it should handle that situation (I would
have done .Mid(cb/sizeof(TCHAR)) which seems easier, but Right(), done right, should work)
joe

0 new messages