Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to cast a wchar_t to a BYTE* in C

I want to cast a wchar_t variable to a BYTE * before sending it through a stream.

I Have

wchar_t val[] = L"abc";

and I try to cast using:

BYTE * bytes = (BYTE *)val;

I don't have all the characters when I read bytes; I only have the first character - "a"

I think, I do not convert well wchar_t.

What am I doing wrong?

EDIT :

static void DASH_process_receive(rdpSvcPlugin* plugin, wStream* data_in)
    int bytes;
    wStream* data_out;
    DASHPlugin* DASH = (DASHPlugin*) plugin;

    fprintf(stderr, "DASH_process_receive:\n");

    if (!DASH)
    {
        fprintf(stderr, "DASH_process_receive: DASH is nil\n");
        return;
    }

    /* process data in (from server) here */
    /* here we just send the same data back */

    bytes = Stream_Capacity(data_in);
    fprintf(stderr, "DASH_process_receive: got bytes %d\n", bytes);


       wchar_t val[] = L"abc";
       bytes = Stream_Capacity(data_in);

    if (bytes > 0)
    {

        fprintf(stderr, "size wcslen val  %zd\n", wcslen(val));

        fprintf(stderr, "size of val  %zd\n", sizeof(val)); //I Have 16

        data_out = Stream_New((BYTE*)val, sizeof(val));


        Stream_Copy(data_out, data_out,sizeof(val));

        /* svc_plugin_send takes ownership of data_out, that is why
           we do not free it */

        bytes = Stream_GetPosition(data_out);
        fprintf(stderr, "DASH_process_receive: sending bytes %d\n", bytes);

        svc_plugin_send(plugin, data_out);
}

    Stream_Free(data_in, TRUE);
}

EDIT : Reading data

WTSVirtualChannelRead(VirtChannelParamsStart, 20000, (PCHAR)Message, sizeof(Message), &ulBytesRead))

unsigned short Message[1024];
CString paramsPourStarter;
paramsPourStarter = Message;
SetDlgItemText(IDC_ED_DASH_RESU,paramsPourStarter);
like image 649
Pis Avatar asked Oct 12 '25 19:10

Pis


2 Answers

How are you reading the length of bytes?

If sizeof(wchar_t) == 2 (and assuming you're running on a little endian host) the data pointed to by byte will look like

{'a', '\0', 'b', '\0', 'c', '\0', '\0', '\0'}

so strlen would stop counting it's length after encountering the null character immediately after 'a'

When you convert the wchar_t array you should also calculate its length using wcslen

BYTE * bytes = (BYTE *)val;
size_t len = wcslen(val) * sizeof(val[0]);
// pass len to any functions which are passed bytes
like image 145
simonc Avatar answered Oct 14 '25 08:10

simonc


The casting is fine, and I'm going to assume that you send the correct number of bytes. Which can be found with sizeof(val) and equals 8 for the code in your question, assuming that wchar_t is a 2 byte UTF-16 character. Or if your wchar_t is a 4 byte UTF-32 character then sizeof(val) will be 16.

The problem would then be at the other end, in the code that reads the data. I can imagine three obvious failure modes:

  1. You fail to read the entire buffer. Perhaps you assume that the content is null terminated and read up to the first zero byte. That would be incorrect since a null wchar_t is actually two zero bytes.
  2. You read the entire buffer correctly, but you interpret the data as char* rather than wchar_t*.
  3. You read the data correctly and interpret it correctly as wchar_t*. But wchar_t is UTF-32 on the sender and UTF-16 for the receiver. Which means that you'd interpret the data as UTF-16 when it is in fact UTF-32.

Any of those explanations would explain why you only received the first character.

In any case I think you are going about the problem in the wrong way. You should probably not be passing UTF-16/UTF-32 down the wire. You'd be much better off with a byte oriented encoding for your text and the natural choice is UTF-8.

Update

Your update makes it a little clearer what is going on. You are sending UTF-32 data over the wire, but then interpreting that data as UTF-16 (assuming your Windows program is a Unicode program). This mis-match leads to the data being interpreted incorrectly and explains why you only receive the first character. That's item 3 above.

In order to solve this you need to be very clear about how your text is to be encoded. The fundamental problem you have can be observed by the fact that not anywhere in your question do you talk about text encoding. If you want to pass data between different programs you need to agree on a common text encoding. Again, I recommend that you put UTF-8 encoded text on the wire.

You also have a problem that you are assuming that the text is null-terminated. If you have a transmission error then your receiving program has a buffer overrun. The other issue you will need to get on top of is that of endianness. You need all parties to agree a common endianness for the data on the wire. Use network byte order.

like image 34
David Heffernan Avatar answered Oct 14 '25 07:10

David Heffernan