Module: wine Branch: master Commit: ff8930f2bfdfd5a16924422fcd9e2730593952fa URL: http://source.winehq.org/git/wine.git/?a=commit;h=ff8930f2bfdfd5a16924422fcd...
Author: Dan Hipschman dsh@linux.ucla.edu Date: Fri Oct 19 15:30:12 2007 -0700
widl: Fix problems with variable-size user types.
---
dlls/rpcrt4/tests/server.c | 48 ++++++++++++++++++++++++++++++++++++++++++ dlls/rpcrt4/tests/server.idl | 9 +++++++ tools/widl/typegen.c | 22 +++++++++++++++++- 3 files changed, 77 insertions(+), 2 deletions(-)
diff --git a/dlls/rpcrt4/tests/server.c b/dlls/rpcrt4/tests/server.c index 97f2e23..d0f4eef 100644 --- a/dlls/rpcrt4/tests/server.c +++ b/dlls/rpcrt4/tests/server.c @@ -459,6 +459,18 @@ s_make_pyramid_doub_carr(unsigned char n, doub_carr_t **dc) *dc = t; }
+unsigned +s_hash_bstr(bstr_t b) +{ + short n = b[-1]; + short *s = b; + unsigned hash = 0; + short i; + for (i = 0; i < n; ++i) + hash = 5 * hash + (unsigned) s[i]; + return hash; +} + void s_stop(void) { @@ -744,6 +756,38 @@ us_t_UserFree(ULONG *flags, us_t *pus) HeapFree(GetProcessHeap(), 0, pus->x); }
+ULONG __RPC_USER +bstr_t_UserSize(ULONG *flags, ULONG start, bstr_t *b) +{ + return start + FIELD_OFFSET(wire_bstr_t, data[(*b)[-1]]); +} + +unsigned char * __RPC_USER +bstr_t_UserMarshal(ULONG *flags, unsigned char *buffer, bstr_t *b) +{ + wire_bstr_t *wb = (wire_bstr_t *) buffer; + wb->n = (*b)[-1]; + memcpy(&wb->data, *b, wb->n * sizeof wb->data[0]); + return buffer + FIELD_OFFSET(wire_bstr_t, data[wb->n]); +} + +unsigned char * __RPC_USER +bstr_t_UserUnmarshal(ULONG *flags, unsigned char *buffer, bstr_t *b) +{ + wire_bstr_t *wb = (wire_bstr_t *) buffer; + short *data = HeapAlloc(GetProcessHeap(), 0, (wb->n + 1) * sizeof *data); + data[0] = wb->n; + memcpy(&data[1], wb->data, wb->n * sizeof data[1]); + *b = &data[1]; + return buffer + FIELD_OFFSET(wire_bstr_t, data[wb->n]); +} + +void __RPC_USER +bstr_t_UserFree(ULONG *flags, bstr_t *b) +{ + HeapFree(GetProcessHeap(), 0, &((*b)[-1])); +} + static void pointer_tests(void) { @@ -754,6 +798,8 @@ pointer_tests(void) int *pa[4]; puints_t pus; cpuints_t cpus; + short bstr_data[] = { 5, 'H', 'e', 'l', 'l', 'o' }; + bstr_t bstr = &bstr_data[1];
ok(test_list_length(list) == 3, "RPC test_list_length\n"); ok(square_puint(p1) == 121, "RPC square_puint\n"); @@ -794,6 +840,8 @@ pointer_tests(void) pa[3] = &a[3]; ok(sum_pcarr(pa, 4) == 10, "RPC sum_pcarr\n");
+ ok(hash_bstr(bstr) == s_hash_bstr(bstr), "RPC hash_bstr_data\n"); + free_list(list); }
diff --git a/dlls/rpcrt4/tests/server.idl b/dlls/rpcrt4/tests/server.idl index 807bf44..fa1ea15 100644 --- a/dlls/rpcrt4/tests/server.idl +++ b/dlls/rpcrt4/tests/server.idl @@ -281,5 +281,14 @@ cpp_quote("#endif") int sum_doub_carr(doub_carr_t *dc); void make_pyramid_doub_carr(unsigned char n, [out] doub_carr_t **dc);
+ typedef struct + { + short n; + [size_is(n)] short data[]; + } wire_bstr_t; + + typedef [wire_marshal(wire_bstr_t)] short *bstr_t; + unsigned hash_bstr(bstr_t s); + void stop(void); } diff --git a/tools/widl/typegen.c b/tools/widl/typegen.c index 6f194b7..dd21fe4 100644 --- a/tools/widl/typegen.c +++ b/tools/widl/typegen.c @@ -907,13 +907,31 @@ static int processed(const type_t *type) return type->typestring_offset && !type->tfswrite; }
+static int user_type_has_variable_size(const type_t *t) +{ + if (is_ptr(t)) + return TRUE; + else + switch (t->type) + { + case RPC_FC_PSTRUCT: + case RPC_FC_CSTRUCT: + case RPC_FC_CPSTRUCT: + case RPC_FC_CVSTRUCT: + return TRUE; + } + /* Note: Since this only applies to user types, we can't have a conformant + array here, and strings should get filed under pointer in this case. */ + return FALSE; +} + static void write_user_tfs(FILE *file, type_t *type, unsigned int *tfsoff) { unsigned int start, absoff, flags; unsigned int align = 0, ualign = 0; const char *name; type_t *utype = get_user_type(type, &name); - size_t usize = type_memsize(utype, &ualign); + size_t usize = user_type_has_variable_size(utype) ? 0 : type_memsize(utype, &ualign); size_t size = type_memsize(type, &align); unsigned short funoff = user_type_offset(name); short reloff; @@ -949,8 +967,8 @@ static void write_user_tfs(FILE *file, type_t *type, unsigned int *tfsoff) print_file(file, 2, "0x%x,\t/* Alignment= %d, Flags= %02x */\n", flags | (align - 1), align - 1, flags); print_file(file, 2, "NdrFcShort(0x%hx),\t/* Function offset= %hu */\n", funoff, funoff); - print_file(file, 2, "NdrFcShort(0x%lx),\t/* %lu */\n", usize, usize); print_file(file, 2, "NdrFcShort(0x%lx),\t/* %lu */\n", size, size); + print_file(file, 2, "NdrFcShort(0x%lx),\t/* %lu */\n", usize, usize); *tfsoff += 8; reloff = absoff - *tfsoff; print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%lu) */\n", reloff, reloff, absoff);