diff --git a/tools/widl/parser.y b/tools/widl/parser.y index a991cad7a72..739b60c0fcf 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -1668,8 +1668,21 @@ static int get_struct_type(var_list_t *fields) { type_t *t = field->type; - if (is_ptr(field->type)) + if (is_ptr(t)) { + do + t = t->ref; + while (is_ptr(t)); + + switch (t->type) + { + case RPC_FC_IP: + case RPC_FC_ENCAPSULATED_UNION: + case RPC_FC_NON_ENCAPSULATED_UNION: + case RPC_FC_BOGUS_STRUCT: + return RPC_FC_BOGUS_STRUCT; + } + has_pointer = 1; continue; } diff --git a/tools/widl/typegen.c b/tools/widl/typegen.c index 6f12a22f3b3..9a5910a7ece 100644 --- a/tools/widl/typegen.c +++ b/tools/widl/typegen.c @@ -195,7 +195,8 @@ static int is_user_type(const type_t *t) static int is_embedded_complex(const type_t *type) { unsigned char tc = type->type; - return is_struct(tc) || is_union(tc) || is_array(type) || is_user_type(type); + return is_struct(tc) || is_union(tc) || is_array(type) || is_user_type(type) + || (is_ptr(type) && type->ref->type == RPC_FC_IP); } static int compare_expr(const expr_t *a, const expr_t *b) @@ -879,12 +880,7 @@ static void write_user_tfs(FILE *file, type_t *type, unsigned int *tfsoff) static void write_member_type(FILE *file, type_t *type, const var_t *field, unsigned int *corroff, unsigned int *tfsoff) { - if (is_ptr(type)) - { - print_file(file, 2, "0x8,\t/* FC_LONG */\n"); - *tfsoff += 1; - } - else if (is_embedded_complex(type)) + if (is_embedded_complex(type)) { size_t absoff; short reloff; @@ -907,6 +903,11 @@ static void write_member_type(FILE *file, type_t *type, const var_t *field, reloff, reloff, absoff); *tfsoff += 4; } + else if (is_ptr(type)) + { + print_file(file, 2, "0x8,\t/* FC_LONG */\n"); + *tfsoff += 1; + } else if (!write_base_type(file, type, tfsoff)) error("Unsupported member type 0x%x\n", type->type); } @@ -1415,12 +1416,12 @@ static size_t write_union_tfs(FILE *file, type_t *type, unsigned int *tfsoff) return start_offset; } -static size_t write_ip_tfs(FILE *file, const func_t *func, const type_t *type, const var_t *var, - unsigned int *typeformat_offset) +static size_t write_ip_tfs(FILE *file, const func_t *func, const attr_list_t *attrs, + type_t *type, unsigned int *typeformat_offset) { size_t i; size_t start_offset = *typeformat_offset; - const var_t *iid = get_attrp(var->attrs, ATTR_IIDIS); + const var_t *iid = get_attrp(attrs, ATTR_IIDIS); if (iid) { @@ -1442,6 +1443,8 @@ static size_t write_ip_tfs(FILE *file, const func_t *func, const type_t *type, c if (! uuid) error("%s: interface %s missing UUID\n", __FUNCTION__, base->name); + update_tfsoff(type, start_offset, file); + print_file(file, 0, "/* %d */\n", start_offset); print_file(file, 2, "0x2f,\t/* FC_IP */\n"); print_file(file, 2, "0x5a,\t/* FC_CONSTANT_IID */\n"); print_file(file, 2, "NdrFcLong(0x%08lx),\n", uuid->Data1); @@ -1539,7 +1542,7 @@ static size_t write_typeformatstring_var(FILE *file, int indent, const func_t *f if (base->type == RPC_FC_IP) { - return write_ip_tfs(file, func, type, var, typeformat_offset); + return write_ip_tfs(file, func, var->attrs, type, typeformat_offset); } /* special case for pointers to base types */ @@ -1609,14 +1612,20 @@ static int write_embedded_types(FILE *file, const attr_list_t *attrs, type_t *ty { type_t *ref = type->ref; - if (!processed(ref) && !is_base_type(ref->type)) - retmask |= write_embedded_types(file, NULL, ref, name, TRUE, tfsoff); + if (ref->type == RPC_FC_IP) + { + write_ip_tfs(file, NULL, attrs, type, tfsoff); + } + else + { + if (!processed(ref) && !is_base_type(ref->type)) + retmask |= write_embedded_types(file, NULL, ref, name, TRUE, tfsoff); - /* top-level pointers are handled inline for structures */ - if (write_ptr) - write_pointer_tfs(file, type, tfsoff); + if (write_ptr) + write_pointer_tfs(file, type, tfsoff); - retmask |= 1; + retmask |= 1; + } } else if (type->declarray && is_conformant_array(type)) ; /* conformant arrays and strings are handled specially */