Solved

GetBuffer() on win CE

Posted on 2002-04-17
35
480 Views
Last Modified: 2008-02-01
I want to copy some data from a char buffer into a CString. The following works great on VC++6 but does not work on windows CE.

char* dataBuff[1024];
loadDataIntoBuffer(dataBuff); //dataBuff has data

DWORD Pos = 10;

CString tmpStr = "";
LPTSTR pstr = tmpStr.GetBuffer(Pos); //addr of pstr is 0x0004bad4
memcpy( pstr,dataBuff,Pos); //value of pstr is "??????..."
tmpStr.ReleaseBuffer();

Why this doesn't work under winCE? is there a better way to copy retrieve data from a char buffer into a CString?

thanks in advance
0
Comment
Question by:el_rooky
  • 17
  • 8
  • 7
  • +1
35 Comments
 
LVL 32

Expert Comment

by:jhance
ID: 6948159
Have you tried:

CString tmpStr = CString(dataBuff);

There is no need to use GetBuffer() and memcpy() since the CString contructor is perfectly able to make a CString from a char *.
0
 

Author Comment

by:el_rooky
ID: 6948185
I don't want to convert the entire dataBuff into a CString since dataBuff could be very large. How can I retreive only the first 10 characters or characters from location 10 to 20 of dataBuff ?
0
 
LVL 32

Expert Comment

by:jhance
ID: 6948314
Well, one approach would be to stuff a NULL terminator into the end of where you want the string copied from and pass CString's contructor the address of the beginning of the area you want to use.
0
 

Author Comment

by:el_rooky
ID: 6948360
jhance,
could you give me an example please? Let say that I have the following:
char* dataBuff[1024];
CString str1 = "";
CString str2 = "";
I want to copy characters from location 0 to 10 into str1 and from 11 to 20 into str2.
How can I acomplish that using your sugested method?
0
 
LVL 86

Expert Comment

by:jkr
ID: 6948386
What about

CString strData;
CString str1;
CString str2;

str1 = strData.Mid ( 0, 10);
str2 = strData.Mid ( 11, 20);

That's what the CString extraction methods are made for...
0
 
LVL 30

Expert Comment

by:Axter
ID: 6948447
You could try the following minor modification:

char* dataBuff[1024];
loadDataIntoBuffer(dataBuff); //dataBuff has data

DWORD Pos = 10;

CString tmpStr = "xxxx";//Add some data here ****
LPTSTR pstr = tmpStr.GetBuffer(Pos); //addr of pstr is 0x0004bad4
memcpy( pstr,dataBuff,Pos); //value of pstr is "??????..."
tmpStr.ReleaseBuffer();

Instead of having tmpStr equal to "", make it equal to a small string less then Pos length.

By doing this, you force the CString object to actually assign a buffer.
0
 
LVL 32

Expert Comment

by:jhance
ID: 6948448
I think he indicated that the problem was that strData might be quite large.  On a "real" Windows machine that is probably not much of an issue but on CE it might kill the thing...
0
 
LVL 30

Expert Comment

by:Axter
ID: 6948471
>>I think he indicated that the problem was that strData
>>might be quite large.

I'm not suggesting to add the target data.  I'm suggesting to put dummy data for the initialize field.
CString tmpStr = "blabla";//Add some dummy data here

The reason I'm suggesting this is that it could be posible that CString refferncing code is causing the problem.  If you assign data to CString from a string literal with (not-empty), then you'll fource CString to create it's own buffer when it initiates.

If you just assign "", CString will reference a built-in EmptyCString object, which is pointed to by every CString object that gets initiated with no data.
0
 
LVL 30

Expert Comment

by:Axter
ID: 6948480
I just realized your code is not assigning enough space for the target data.
Try this:
char* dataBuff[1024];
loadDataIntoBuffer(dataBuff); //dataBuff has data

DWORD Pos = 10;

CString tmpStr = "";
LPTSTR pstr = tmpStr.GetBuffer(Pos+1); //addr of pstr is 0x0004bad4
memcpy( pstr,dataBuff,Pos); //value of pstr is "??????..."
tmpStr.ReleaseBuffer();
0
 
LVL 86

Expert Comment

by:jkr
ID: 6948482
I usually don't repeat myself, but CString DOES have means to extract data without usind any temporary storage - 'Left()','Mid()' and 'Right()'. So,

CString strData;
CString str1;
CString str2;

str1 = strData.Mid ( 0, 10);
str2 = strData.Mid ( 11, 20);

should definitely work, even on CE...
0
 
LVL 30

Expert Comment

by:Axter
ID: 6948484
Correction:
char* dataBuff[1024];
loadDataIntoBuffer(dataBuff); //dataBuff has data

DWORD Pos = 10;

CString tmpStr = "";
LPTSTR pstr = tmpStr.GetBuffer(Pos+1);
memcpy(pstr,dataBuff,Pos);
pstr[Pos]=0;
tmpStr.ReleaseBuffer();
0
 
LVL 86

Expert Comment

by:jkr
ID: 6948501
Again: There is no need to use any temproary storage...

BTW:

>>char* dataBuff[1024];

Why would we need 1024 'char*'? :o)

0
 
LVL 30

Expert Comment

by:Axter
ID: 6948502
Actually, in reading the documentation for CString::GetBuffer, the Length argument doesn't include the NULL terminator.

I would still try adding an extra byte to GetBuffer, just to make sure the CE version is not incorrectly implemented.
0
 
LVL 30

Expert Comment

by:Axter
ID: 6948510
el_rooky,
Is the data you're adding to your CString object, of wide charactor type?

CString is a wide charactor type in Windows CE.
This could be what's causing your problem.
0
 
LVL 30

Expert Comment

by:Axter
ID: 6948525
>>Why would we need 1024 'char*'? :o)
Very good point.

el_rooky,
How is loadDataIntoBuffer putting data into dataBuff?

Can you post the type for loadDataIntoBuffer?

I think your real problem is the declaration of dataBuff.

It should one of the following, and not both:
char dataBuff[1024];

or

char* dataBuff;

Depending on what loadDataIntoBuffer receives for an argument.

I suspected it should be char dataBuff[1024];
0
 
LVL 86

Expert Comment

by:jkr
ID: 6948527
Well, as it seems to be en vogue now not to care what others post, I'll also follow that scheme:

CString has methods to extract data without usind any temporary storage - 'Left()','Mid()' and 'Right()'. So, just use

CString strData;
CString str1;
CString str2;

str1 = strData.Mid ( 0, 10);
str2 = strData.Mid ( 11, 20);
0
 
LVL 30

Expert Comment

by:Axter
ID: 6948552
jkr,
The method you're posting only works if you first get the data into strData.
IMHO, The questioner seems to be having problems getting to that point.
0
Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

 

Author Comment

by:el_rooky
ID: 6948592
I just came back from lunch and found all these comments, it's great! I've tried most of your suggestions and here are my findings:

1) jkr - my data buffer is actually of size 49152 wich in windows CE is consider a large buffer. And I don't want to convert it to a CString, otherwise your suggestion makes all the sence.

2) Axter - I've tried all modifications suggested to the current code and nothing works. Except when I use TCHAR instead of char. So you are right. Windows CE is a unicode enviroment.

3) The question still is, since I can not chance the dataBuff to a wide character type (dont ask me why, there are a lot of reasons. DataBuff must remain as an array of chars) how do I copy string of characters from an array of chars into a CString?
0
 
LVL 30

Expert Comment

by:Axter
ID: 6948612
You need to first convert the data to wide charactor, and then put it into the CString buffer.
0
 
LVL 30

Expert Comment

by:Axter
ID: 6948625
If your source data is of char* type, you have no choice but to first convert the data, before memcpy to the CString buffer.

As I stated previously, Windows CE uses Wide charactor type for CString, so any data you put into the CString buffer, has to be of Wide charactor type, in order for it to be readable.
0
 
LVL 86

Expert Comment

by:jkr
ID: 6948631
OK, sorry, it seems that I misread the Q (blushing :o)

So, let's see:

char dataBuff[1024];
CString str1;
CString str2;

wchar_t* pwsz = str1.GetBufferSetLength ( 11);

ZeroMemory ( pwsz, 11 * sizeof ( wchar_t));

wcscpyn ( pwsz, ( wchar_t*) dataBuff);

wchar_t* pwsz = str1.GetBufferSetLength ( 11);

ZeroMemory ( pwsz, 11 * sizeof ( wchar_t), 10);

wcscpyn ( pwsz, ( wchar_t*) dataBuff + 11, 10);
0
 

Author Comment

by:el_rooky
ID: 6948774
jkr,
following your example the following piece of code does not work either:

char dataBuff[18] = "abcdefghijklmnopq";
CString tmpStr = "";

wchar_t* pwsz = tmpStr.GetBufferSetLength (5);
ZeroMemory ( pwsz, 5 * sizeof ( wchar_t));
wcscpy ( pwsz, ( wchar_t*) dataBuff);

pwsz gets a bunch of '?'

notice that I've changed wcspyn to wcspy since wcspyn was undefined.

0
 

Author Comment

by:el_rooky
ID: 6948808
jkr,
following your example the following piece of code does not work either:

char dataBuff[18] = "abcdefghijklmnopq";
CString tmpStr = "";

wchar_t* pwsz = tmpStr.GetBufferSetLength (5);
ZeroMemory ( pwsz, 5 * sizeof ( wchar_t));
wcscpy ( pwsz, ( wchar_t*) dataBuff);

pwsz gets a bunch of '?'

notice that I've changed wcspyn to wcspy since wcspyn was undefined.

0
 
LVL 30

Accepted Solution

by:
Axter earned 200 total points
ID: 6948822
Try this:

void SimpleCharToWide(const char* Src, int Len, wchar_t* Target)
{
     for(int i = 0;i < Len;++i)
     {
          Target[i] = Src[0];
          Target[i+1] = 0;
     }
}

void Functionx(void)
{
     char dataBuff[] = "abcdefghijklmnopq";

     DWORD Pos = 10;

     CString tmpStr = "";
     wchar_t* pwsz = tmpStr.GetBufferSetLength ((Pos+1)*sizeof(wchar_t));
     SimpleCharToWide(dataBuff, strlen(dataBuff), pwsz);
     tmpStr.ReleaseBuffer();
}
0
 
LVL 30

Expert Comment

by:Axter
ID: 6948826
There is an API function that you should use in place of the SimpleCharToWide function I posted, but I don't remember what it's called.
0
 
LVL 30

Expert Comment

by:Axter
ID: 6948837
You should use MultiByteToWideChar function to convert your char data to widechar data.
0
 
LVL 86

Expert Comment

by:jkr
ID: 6948849
>>pwsz gets a bunch of '?'

Yes, it should have read

wchar_t* pwsz = tmpStr.GetBufferSetLength (6); // 6, as we need a trailing zero!
ZeroMemory ( pwsz, 6 * sizeof ( wchar_t));
memcpy ( pwsz, ( wchar_t*) dataBuff, 5 * sizeof ( wchar_t));
0
 
LVL 30

Expert Comment

by:Axter
ID: 6948901
Here's an example using MultiByteToWideChar

void Function(void)
{
     char dataBuff[] = "abcdefghijklmnopq";

     DWORD Pos = 10;

     CString tmpStr = "";
     wchar_t* pwsz = tmpStr.GetBufferSetLength ((Pos+1)*sizeof(wchar_t));
     MultiByteToWideChar(CP_ACP, 0, dataBuff, strlen(dataBuff), pwsz, strlen(dataBuff));
     tmpStr.ReleaseBuffer();
}

0
 
LVL 30

Expert Comment

by:Axter
ID: 6948904
Correction:
void Function(void)
{
    char dataBuff[] = "abcdefghijklmnopq";

    DWORD Pos = 10;

    CString tmpStr = "";
    wchar_t* pwsz = tmpStr.GetBufferSetLength ((Pos+1)*sizeof(wchar_t));
    MultiByteToWideChar(CP_ACP, 0, dataBuff, strlen(dataBuff), pwsz, (Pos+1)*sizeof(wchar_t));
    tmpStr.ReleaseBuffer();
}
0
 
LVL 86

Expert Comment

by:jkr
ID: 6948907
Hum, I am confused now - I thought we were dealing with the UNICODE version of CString?
0
 
LVL 30

Expert Comment

by:Axter
ID: 6948915
>>Hum, I am confused now - I thought we were dealing with
>>the UNICODE version of CString?

Yes, but the source data is char type.
So he's trying to put char type data into a UNICODE CString object.
0
 
LVL 30

Expert Comment

by:Axter
ID: 6948921
FYI:
MultiByteToWideChar is used to convert ANSI char type data to wide char.
It can also convert MultiByte to wide char, as the name suggest.
0
 
LVL 86

Expert Comment

by:jkr
ID: 6948930
>>Yes, but the source data is char type.

Argl, I though it was UNICODE "disguised" in a char buffer...
0
 

Author Comment

by:el_rooky
ID: 6949053
sorry for the confusion jkr. Thanks for your help anyways. I've posted the same question in the Windows CE group. IF you go there I'll give you those points.

Axter,
your function SimpleCharToWide works better than the MultiByteToWideChar function, which does not always gives me the correct string lenght. Your piece of code works great for me with a fix to a couple of bugs.

void SimpleCharToWide(const char* Src, int Len, wchar_t* Target)
{
    for(int i = 0;i < Len;++i)
    {
         Target[i] = Src[i]; //bug1 Src[0];
         Target[i+1] = 0;
    }
}

void Functionx(void)
{
    char dataBuff[] = "abcdefghijklmnopq";

    DWORD Pos = 10;

    CString tmpStr = "";
    wchar_t* pwsz = tmpStr.GetBufferSetLength ((Pos+1)*sizeof(wchar_t));
//    SimpleCharToWide(dataBuff, strlen(dataBuff), pwsz);
    SimpleCharToWide(dataBuff, pos, pwsz);
    tmpStr.ReleaseBuffer();
}
0
 

Author Comment

by:el_rooky
ID: 6949070
sorry for the confusion jkr. Thanks for your help anyways. I've posted the same question in the Windows CE group. IF you go there I'll give you those points.

Axter,
your function SimpleCharToWide works better than the MultiByteToWideChar function, which does not always gives me the correct string lenght. Your piece of code works great for me with a fix to a couple of bugs.

void SimpleCharToWide(const char* Src, int Len, wchar_t* Target)
{
    for(int i = 0;i < Len;++i)
    {
         Target[i] = Src[i]; //bug1 Src[0];
         Target[i+1] = 0;
    }
}

void Functionx(void)
{
    char dataBuff[] = "abcdefghijklmnopq";

    DWORD Pos = 10;

    CString tmpStr = "";
    wchar_t* pwsz = tmpStr.GetBufferSetLength ((Pos+1)*sizeof(wchar_t));
//    SimpleCharToWide(dataBuff, strlen(dataBuff), pwsz);
    SimpleCharToWide(dataBuff, pos, pwsz);
    tmpStr.ReleaseBuffer();
}
0

Featured Post

Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

Join & Write a Comment

Introduction This article is the first in a series of articles about the C/C++ Visual Studio Express debugger.  It provides a quick start guide in using the debugger. Part 2 focuses on additional topics in breakpoints.  Lastly, Part 3 focuses on th…
This article will show you some of the more useful Standard Template Library (STL) algorithms through the use of working examples.  You will learn about how these algorithms fit into the STL architecture, how they work with STL containers, and why t…
The viewer will learn how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.

758 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now