Huw Davies : oleaut32:
Correctly handle the case when the number of bytes in a BSTR is odd.
Alexandre Julliard
julliard at wine.codeweavers.com
Wed May 10 12:56:48 CDT 2006
Module: wine
Branch: refs/heads/master
Commit: 40986cd729afbbcffa4afca1c7815ff2f5492793
URL: http://source.winehq.org/git/?p=wine.git;a=commit;h=40986cd729afbbcffa4afca1c7815ff2f5492793
Author: Huw Davies <huw at codeweavers.com>
Date: Wed May 10 12:41:32 2006 +0100
oleaut32: Correctly handle the case when the number of bytes in a BSTR is odd.
---
dlls/oleaut32/tests/usrmarshal.c | 88 +++++++++++++++++++++++++++++++++-----
dlls/oleaut32/usrmarshal.c | 21 +++++----
2 files changed, 89 insertions(+), 20 deletions(-)
diff --git a/dlls/oleaut32/tests/usrmarshal.c b/dlls/oleaut32/tests/usrmarshal.c
index b0f3808..4433f50 100644
--- a/dlls/oleaut32/tests/usrmarshal.c
+++ b/dlls/oleaut32/tests/usrmarshal.c
@@ -227,20 +227,20 @@ static void test_marshal_LPSAFEARRAY(voi
static void check_bstr(void *buffer, BSTR b)
{
DWORD *wireb = buffer;
- DWORD len = SysStringLen(b);
+ DWORD len = SysStringByteLen(b);
- ok(*wireb == len, "wv[0] %08lx\n", *wireb);
+ ok(*wireb == (len + 1) / 2, "wv[0] %08lx\n", *wireb);
wireb++;
- if(len)
- ok(*wireb == len * 2, "wv[1] %08lx\n", *wireb);
+ if(b)
+ ok(*wireb == len, "wv[1] %08lx\n", *wireb);
else
ok(*wireb == 0xffffffff, "wv[1] %08lx\n", *wireb);
wireb++;
- ok(*wireb == len, "wv[2] %08lx\n", *wireb);
+ ok(*wireb == (len + 1) / 2, "wv[2] %08lx\n", *wireb);
if(len)
{
wireb++;
- ok(!memcmp(wireb, b, len * 2), "strings differ\n");
+ ok(!memcmp(wireb, b, (len + 1) & ~1), "strings differ\n");
}
return;
}
@@ -250,7 +250,7 @@ static void test_marshal_BSTR(void)
unsigned long size;
MIDL_STUB_MESSAGE stubMsg = { 0 };
USER_MARSHAL_CB umcb = { 0 };
- unsigned char *buffer;
+ unsigned char *buffer, *next;
BSTR b, b2;
WCHAR str[] = {'m','a','r','s','h','a','l',' ','t','e','s','t','1',0};
DWORD len;
@@ -271,14 +271,16 @@ static void test_marshal_BSTR(void)
ok(size == 38, "size %ld\n", size);
buffer = HeapAlloc(GetProcessHeap(), 0, size);
- BSTR_UserMarshal(&umcb.Flags, buffer, &b);
+ next = BSTR_UserMarshal(&umcb.Flags, buffer, &b);
+ ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
check_bstr(buffer, b);
if (BSTR_UNMARSHAL_WORKS)
{
b2 = NULL;
- BSTR_UserUnmarshal(&umcb.Flags, buffer, &b2);
- ok(b2 != NULL, "NULL LPSAFEARRAY didn't unmarshal\n");
+ next = BSTR_UserUnmarshal(&umcb.Flags, buffer, &b2);
+ ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
+ ok(b2 != NULL, "BSTR didn't unmarshal\n");
ok(!memcmp(b, b2, (len + 1) * 2), "strings differ\n");
BSTR_UserFree(&umcb.Flags, &b2);
}
@@ -291,11 +293,75 @@ static void test_marshal_BSTR(void)
ok(size == 12, "size %ld\n", size);
buffer = HeapAlloc(GetProcessHeap(), 0, size);
- BSTR_UserMarshal(&umcb.Flags, buffer, &b);
+ next = BSTR_UserMarshal(&umcb.Flags, buffer, &b);
+ ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
check_bstr(buffer, b);
+ if (BSTR_UNMARSHAL_WORKS)
+ {
+ b2 = NULL;
+ next = BSTR_UserUnmarshal(&umcb.Flags, buffer, &b2);
+ ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
+ ok(b2 == NULL, "NULL BSTR didn't unmarshal\n");
+ BSTR_UserFree(&umcb.Flags, &b2);
+ }
HeapFree(GetProcessHeap(), 0, buffer);
+ b = SysAllocStringByteLen("abc", 3);
+ *(((char*)b) + 3) = 'd';
+ len = SysStringLen(b);
+ ok(len == 1, "get %ld\n", len);
+ len = SysStringByteLen(b);
+ ok(len == 3, "get %ld\n", len);
+
+ size = BSTR_UserSize(&umcb.Flags, 0, &b);
+ ok(size == 16, "size %ld\n", size);
+
+ buffer = HeapAlloc(GetProcessHeap(), 0, size);
+ memset(buffer, 0xcc, size);
+ next = BSTR_UserMarshal(&umcb.Flags, buffer, &b);
+ ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
+ check_bstr(buffer, b);
+ ok(buffer[15] == 'd', "buffer[15] %02x\n", buffer[15]);
+
+ if (BSTR_UNMARSHAL_WORKS)
+ {
+ b2 = NULL;
+ next = BSTR_UserUnmarshal(&umcb.Flags, buffer, &b2);
+ ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
+ ok(b2 != NULL, "BSTR didn't unmarshal\n");
+ ok(!memcmp(b, b2, len), "strings differ\n");
+ BSTR_UserFree(&umcb.Flags, &b2);
+ }
+ HeapFree(GetProcessHeap(), 0, buffer);
+ SysFreeString(b);
+
+ b = SysAllocStringByteLen("", 0);
+ len = SysStringLen(b);
+ ok(len == 0, "get %ld\n", len);
+ len = SysStringByteLen(b);
+ ok(len == 0, "get %ld\n", len);
+
+ size = BSTR_UserSize(&umcb.Flags, 0, &b);
+ ok(size == 12, "size %ld\n", size);
+
+ buffer = HeapAlloc(GetProcessHeap(), 0, size);
+ next = BSTR_UserMarshal(&umcb.Flags, buffer, &b);
+ ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
+ check_bstr(buffer, b);
+
+ if (BSTR_UNMARSHAL_WORKS)
+ {
+ b2 = NULL;
+ next = BSTR_UserUnmarshal(&umcb.Flags, buffer, &b2);
+ ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
+ ok(b2 != NULL, "NULL LPSAFEARRAY didn't unmarshal\n");
+ len = SysStringByteLen(b2);
+ ok(len == 0, "byte len %ld\n", len);
+ BSTR_UserFree(&umcb.Flags, &b2);
+ }
+ HeapFree(GetProcessHeap(), 0, buffer);
+ SysFreeString(b);
}
static void check_variant_header(DWORD *wirev, VARIANT *v, unsigned long size)
diff --git a/dlls/oleaut32/usrmarshal.c b/dlls/oleaut32/usrmarshal.c
index 002df90..dd397c0 100644
--- a/dlls/oleaut32/usrmarshal.c
+++ b/dlls/oleaut32/usrmarshal.c
@@ -152,7 +152,7 @@ unsigned long WINAPI BSTR_UserSize(unsig
TRACE("(%lx,%ld,%p) => %p\n", *pFlags, Start, pstr, *pstr);
if (*pstr) TRACE("string=%s\n", debugstr_w(*pstr));
ALIGN_LENGTH(Start, 3);
- Start += sizeof(bstr_wire_t) + sizeof(OLECHAR) * (SysStringLen(*pstr));
+ Start += sizeof(bstr_wire_t) + ((SysStringByteLen(*pstr) + 1) & ~1);
TRACE("returning %ld\n", Start);
return Start;
}
@@ -160,19 +160,21 @@ unsigned long WINAPI BSTR_UserSize(unsig
unsigned char * WINAPI BSTR_UserMarshal(unsigned long *pFlags, unsigned char *Buffer, BSTR *pstr)
{
bstr_wire_t *header;
+ DWORD len = SysStringByteLen(*pstr);
+
TRACE("(%lx,%p,%p) => %p\n", *pFlags, Buffer, pstr, *pstr);
if (*pstr) TRACE("string=%s\n", debugstr_w(*pstr));
ALIGN_POINTER(Buffer, 3);
header = (bstr_wire_t*)Buffer;
- header->len = header->len2 = SysStringLen(*pstr);
- if (header->len)
+ header->len = header->len2 = (len + 1) / 2;
+ if (*pstr)
{
- header->byte_len = header->len * sizeof(OLECHAR);
- memcpy(header + 1, *pstr, header->byte_len);
+ header->byte_len = len;
+ memcpy(header + 1, *pstr, header->len * 2);
}
else
- header->byte_len = 0xffffffff; /* special case for an empty string */
+ header->byte_len = 0xffffffff; /* special case for a null bstr */
return Buffer + sizeof(*header) + sizeof(OLECHAR) * header->len;
}
@@ -187,14 +189,15 @@ unsigned char * WINAPI BSTR_UserUnmarsha
if(header->len != header->len2)
FIXME("len %08lx != len2 %08lx\n", header->len, header->len2);
- if(header->len)
- SysReAllocStringLen(pstr, (OLECHAR*)(header + 1), header->len);
- else if (*pstr)
+ if(*pstr)
{
SysFreeString(*pstr);
*pstr = NULL;
}
+ if(header->byte_len != 0xffffffff)
+ *pstr = SysAllocStringByteLen((char*)(header + 1), header->byte_len);
+
if (*pstr) TRACE("string=%s\n", debugstr_w(*pstr));
return Buffer + sizeof(*header) + sizeof(OLECHAR) * header->len;
}
More information about the wine-cvs
mailing list