oleaut32: Fix BSTR marshaling to be wire compatible with Windows.
This commit is contained in:
parent
3671263108
commit
2e8a74d520
|
@ -30,6 +30,7 @@
|
||||||
/* doesn't work on Windows due to needing more of the
|
/* doesn't work on Windows due to needing more of the
|
||||||
* MIDL_STUB_MESSAGE structure to be filled out */
|
* MIDL_STUB_MESSAGE structure to be filled out */
|
||||||
#define LPSAFEARRAY_UNMARSHAL_WORKS 0
|
#define LPSAFEARRAY_UNMARSHAL_WORKS 0
|
||||||
|
#define BSTR_UNMARSHAL_WORKS 0
|
||||||
|
|
||||||
static void test_marshal_LPSAFEARRAY(void)
|
static void test_marshal_LPSAFEARRAY(void)
|
||||||
{
|
{
|
||||||
|
@ -115,11 +116,78 @@ static void test_marshal_LPSAFEARRAY(void)
|
||||||
HeapFree(GetProcessHeap(), 0, buffer);
|
HeapFree(GetProcessHeap(), 0, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_marshal_BSTR(void)
|
||||||
|
{
|
||||||
|
unsigned long size;
|
||||||
|
MIDL_STUB_MESSAGE stubMsg = { 0 };
|
||||||
|
USER_MARSHAL_CB umcb = { 0 };
|
||||||
|
unsigned char *buffer;
|
||||||
|
BSTR b, b2;
|
||||||
|
WCHAR str[] = {'m','a','r','s','h','a','l',' ','t','e','s','t','1',0};
|
||||||
|
DWORD *wireb, len;
|
||||||
|
|
||||||
|
umcb.Flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION);
|
||||||
|
umcb.pReserve = NULL;
|
||||||
|
umcb.pStubMsg = &stubMsg;
|
||||||
|
|
||||||
|
b = SysAllocString(str);
|
||||||
|
len = SysStringLen(b);
|
||||||
|
ok(len == 13, "get %ld\n", len);
|
||||||
|
|
||||||
|
/* BSTRs are DWORD aligned */
|
||||||
|
size = BSTR_UserSize(&umcb.Flags, 1, &b);
|
||||||
|
ok(size == 42, "size %ld\n", size);
|
||||||
|
|
||||||
|
size = BSTR_UserSize(&umcb.Flags, 0, &b);
|
||||||
|
ok(size == 38, "size %ld\n", size);
|
||||||
|
|
||||||
|
buffer = HeapAlloc(GetProcessHeap(), 0, size);
|
||||||
|
BSTR_UserMarshal(&umcb.Flags, buffer, &b);
|
||||||
|
wireb = (DWORD*)buffer;
|
||||||
|
|
||||||
|
ok(*wireb == len, "wv[0] %08lx\n", *wireb);
|
||||||
|
wireb++;
|
||||||
|
ok(*wireb == len * 2, "wv[1] %08lx\n", *wireb);
|
||||||
|
wireb++;
|
||||||
|
ok(*wireb == len, "wv[2] %08lx\n", *wireb);
|
||||||
|
wireb++;
|
||||||
|
ok(!memcmp(wireb, str, len * 2), "strings differ\n");
|
||||||
|
|
||||||
|
if (BSTR_UNMARSHAL_WORKS)
|
||||||
|
{
|
||||||
|
b2 = NULL;
|
||||||
|
BSTR_UserUnmarshal(&umcb.Flags, buffer, &b2);
|
||||||
|
ok(b2 != NULL, "NULL LPSAFEARRAY didn't unmarshal\n");
|
||||||
|
ok(!memcmp(b, b2, (len + 1) * 2), "strings differ\n");
|
||||||
|
BSTR_UserFree(&umcb.Flags, &b2);
|
||||||
|
}
|
||||||
|
|
||||||
|
HeapFree(GetProcessHeap(), 0, buffer);
|
||||||
|
SysFreeString(b);
|
||||||
|
|
||||||
|
b = NULL;
|
||||||
|
size = BSTR_UserSize(&umcb.Flags, 0, &b);
|
||||||
|
ok(size == 12, "size %ld\n", size);
|
||||||
|
|
||||||
|
buffer = HeapAlloc(GetProcessHeap(), 0, size);
|
||||||
|
BSTR_UserMarshal(&umcb.Flags, buffer, &b);
|
||||||
|
wireb = (DWORD*)buffer;
|
||||||
|
ok(*wireb == 0, "wv[0] %08lx\n", *wireb);
|
||||||
|
wireb++;
|
||||||
|
ok(*wireb == 0xffffffff, "wv[1] %08lx\n", *wireb);
|
||||||
|
wireb++;
|
||||||
|
ok(*wireb == 0, "wv[2] %08lx\n", *wireb);
|
||||||
|
|
||||||
|
HeapFree(GetProcessHeap(), 0, buffer);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
START_TEST(usrmarshal)
|
START_TEST(usrmarshal)
|
||||||
{
|
{
|
||||||
CoInitialize(NULL);
|
CoInitialize(NULL);
|
||||||
|
|
||||||
test_marshal_LPSAFEARRAY();
|
test_marshal_LPSAFEARRAY();
|
||||||
|
test_marshal_BSTR();
|
||||||
|
|
||||||
CoUninitialize();
|
CoUninitialize();
|
||||||
}
|
}
|
||||||
|
|
|
@ -140,50 +140,73 @@ void WINAPI CLEANLOCALSTORAGE_UserFree(unsigned long *pFlags, CLEANLOCALSTORAGE
|
||||||
|
|
||||||
/* BSTR */
|
/* BSTR */
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
DWORD len; /* No. of chars not including trailing '\0' */
|
||||||
|
DWORD byte_len; /* len * 2 or 0xffffffff if len == 0 */
|
||||||
|
DWORD len2; /* == len */
|
||||||
|
} bstr_wire_t;
|
||||||
|
|
||||||
unsigned long WINAPI BSTR_UserSize(unsigned long *pFlags, unsigned long Start, BSTR *pstr)
|
unsigned long WINAPI BSTR_UserSize(unsigned long *pFlags, unsigned long Start, BSTR *pstr)
|
||||||
{
|
{
|
||||||
TRACE("(%lx,%ld,%p) => %p\n", *pFlags, Start, pstr, *pstr);
|
TRACE("(%lx,%ld,%p) => %p\n", *pFlags, Start, pstr, *pstr);
|
||||||
if (*pstr) TRACE("string=%s\n", debugstr_w(*pstr));
|
if (*pstr) TRACE("string=%s\n", debugstr_w(*pstr));
|
||||||
Start += sizeof(FLAGGED_WORD_BLOB) + sizeof(OLECHAR) * (SysStringLen(*pstr) - 1);
|
ALIGN_LENGTH(Start, 3);
|
||||||
TRACE("returning %ld\n", Start);
|
Start += sizeof(bstr_wire_t) + sizeof(OLECHAR) * (SysStringLen(*pstr));
|
||||||
return Start;
|
TRACE("returning %ld\n", Start);
|
||||||
|
return Start;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char * WINAPI BSTR_UserMarshal(unsigned long *pFlags, unsigned char *Buffer, BSTR *pstr)
|
unsigned char * WINAPI BSTR_UserMarshal(unsigned long *pFlags, unsigned char *Buffer, BSTR *pstr)
|
||||||
{
|
{
|
||||||
wireBSTR str = (wireBSTR)Buffer;
|
bstr_wire_t *header;
|
||||||
|
TRACE("(%lx,%p,%p) => %p\n", *pFlags, Buffer, pstr, *pstr);
|
||||||
|
if (*pstr) TRACE("string=%s\n", debugstr_w(*pstr));
|
||||||
|
|
||||||
TRACE("(%lx,%p,%p) => %p\n", *pFlags, Buffer, pstr, *pstr);
|
ALIGN_POINTER(Buffer, 3);
|
||||||
if (*pstr) TRACE("string=%s\n", debugstr_w(*pstr));
|
header = (bstr_wire_t*)Buffer;
|
||||||
str->fFlags = 0;
|
header->len = header->len2 = SysStringLen(*pstr);
|
||||||
str->clSize = SysStringLen(*pstr);
|
if (header->len)
|
||||||
if (str->clSize)
|
{
|
||||||
memcpy(&str->asData, *pstr, sizeof(OLECHAR) * str->clSize);
|
header->byte_len = header->len * sizeof(OLECHAR);
|
||||||
return Buffer + sizeof(FLAGGED_WORD_BLOB) + sizeof(OLECHAR) * (str->clSize - 1);
|
memcpy(header + 1, *pstr, header->byte_len);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
header->byte_len = 0xffffffff; /* special case for an empty string */
|
||||||
|
|
||||||
|
return Buffer + sizeof(*header) + sizeof(OLECHAR) * header->len;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char * WINAPI BSTR_UserUnmarshal(unsigned long *pFlags, unsigned char *Buffer, BSTR *pstr)
|
unsigned char * WINAPI BSTR_UserUnmarshal(unsigned long *pFlags, unsigned char *Buffer, BSTR *pstr)
|
||||||
{
|
{
|
||||||
wireBSTR str = (wireBSTR)Buffer;
|
bstr_wire_t *header;
|
||||||
TRACE("(%lx,%p,%p) => %p\n", *pFlags, Buffer, pstr, *pstr);
|
TRACE("(%lx,%p,%p) => %p\n", *pFlags, Buffer, pstr, *pstr);
|
||||||
if (str->clSize) {
|
|
||||||
SysReAllocStringLen(pstr, (OLECHAR*)&str->asData, str->clSize);
|
ALIGN_POINTER(Buffer, 3);
|
||||||
}
|
header = (bstr_wire_t*)Buffer;
|
||||||
else if (*pstr) {
|
if(header->len != header->len2)
|
||||||
SysFreeString(*pstr);
|
FIXME("len %08lx != len2 %08lx\n", header->len, header->len2);
|
||||||
*pstr = NULL;
|
|
||||||
}
|
if(header->len)
|
||||||
if (*pstr) TRACE("string=%s\n", debugstr_w(*pstr));
|
SysReAllocStringLen(pstr, (OLECHAR*)(header + 1), header->len);
|
||||||
return Buffer + sizeof(FLAGGED_WORD_BLOB) + sizeof(OLECHAR) * (str->clSize - 1);
|
else if (*pstr)
|
||||||
|
{
|
||||||
|
SysFreeString(*pstr);
|
||||||
|
*pstr = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*pstr) TRACE("string=%s\n", debugstr_w(*pstr));
|
||||||
|
return Buffer + sizeof(*header) + sizeof(OLECHAR) * header->len;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WINAPI BSTR_UserFree(unsigned long *pFlags, BSTR *pstr)
|
void WINAPI BSTR_UserFree(unsigned long *pFlags, BSTR *pstr)
|
||||||
{
|
{
|
||||||
TRACE("(%lx,%p) => %p\n", *pFlags, pstr, *pstr);
|
TRACE("(%lx,%p) => %p\n", *pFlags, pstr, *pstr);
|
||||||
if (*pstr) {
|
if (*pstr)
|
||||||
SysFreeString(*pstr);
|
{
|
||||||
*pstr = NULL;
|
SysFreeString(*pstr);
|
||||||
}
|
*pstr = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* VARIANT */
|
/* VARIANT */
|
||||||
|
|
Loading…
Reference in New Issue