diff --git a/tools/widl/parser.y b/tools/widl/parser.y index 0d03b03ef53..b757c5c83a9 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -90,7 +90,7 @@ static var_t *make_var(char *name); static func_list_t *append_func(func_list_t *list, func_t *func); static func_t *make_func(var_t *def, var_list_t *args); static type_t *make_class(char *name); -static type_t *make_safearray(void); +static type_t *make_safearray(typeref_t *tref); static type_t *make_builtin(char *name); static type_t *make_int(int sign); @@ -833,7 +833,7 @@ type: tVOID { $$ = make_tref(NULL, duptype(find_type("void", 0), 1)); } | tSTRUCT aIDENTIFIER { $$ = make_tref(NULL, get_type(RPC_FC_STRUCT, $2, tsSTRUCT)); } | uniondef { $$ = make_tref(NULL, $1); } | tUNION aIDENTIFIER { $$ = make_tref(NULL, find_type2($2, tsUNION)); } - | tSAFEARRAY '(' type ')' { $$ = make_tref(NULL, make_safearray()); } + | tSAFEARRAY '(' type ')' { $$ = make_tref(NULL, make_safearray($3)); } ; typedef: tTYPEDEF m_attributes type pident_list { reg_typedefs(type_ref($3), $4, $2); @@ -1321,9 +1321,19 @@ static type_t *make_class(char *name) return c; } -static type_t *make_safearray(void) +static type_t *make_safearray(typeref_t *tref) { - return make_type(RPC_FC_FP, find_type("SAFEARRAY", 0)); + const type_t *sa_orig = find_type("SAFEARRAY", 0); + type_t *sa = make_type(sa_orig->type, sa_orig->ref); + type_t *ptr; + + if (sa_orig->name) + sa->name = strdup(sa_orig->name); + sa->ref = type_ref(tref); + ptr = make_type(RPC_FC_FP, sa); + ptr->name = strdup("SAFEARRAY"); + + return ptr; } #define HASHMAX 64 diff --git a/tools/widl/typelib.c b/tools/widl/typelib.c index 4e66c7b0634..2f8708b973b 100644 --- a/tools/widl/typelib.c +++ b/tools/widl/typelib.c @@ -181,7 +181,11 @@ unsigned short get_type_vt(type_t *t) case RPC_FC_OP: case RPC_FC_FP: if(t->ref) + { + if (match(t->ref->name, "SAFEARRAY")) + return VT_SAFEARRAY; return VT_PTR; + } error("get_type_vt: unknown-deref-type: %d\n", t->ref->type); break; diff --git a/tools/widl/write_msft.c b/tools/widl/write_msft.c index 0017bd91d40..d3a5bf4a14c 100644 --- a/tools/widl/write_msft.c +++ b/tools/widl/write_msft.c @@ -903,14 +903,22 @@ static int encode_type( *decoded_size = 8 /*sizeof(TYPEDESC)*/ + child_size; break; } -#if 0 case VT_SAFEARRAY: - /* FIXME: Make with the error checking. */ - FIXME("SAFEARRAY vartype, may not work correctly.\n"); + { + int next_vt; - ctl2_encode_typedesc(typelib, tdesc->u.lptdesc, &target_type, NULL, NULL, &child_size); + /* skip over SAFEARRAY type straight to element type */ + type = type->ref; + + for(next_vt = 0; type->ref; type = type->ref) { + next_vt = get_type_vt(type->ref); + if (next_vt != 0) + break; + } + + encode_type(typelib, next_vt, type->ref, &target_type, NULL, NULL, &child_size); for (typeoffset = 0; typeoffset < typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length; typeoffset += 8) { typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset]; @@ -934,16 +942,15 @@ static int encode_type( typedata[1] = target_type; } - *encoded_tdesc = typeoffset; + *encoded_type = typeoffset; *width = 4; *alignment = 4; - *decoded_size = sizeof(TYPEDESC) + child_size; + *decoded_size = 8 /*sizeof(TYPEDESC)*/ + child_size; break; + } -#endif - case VT_USERDEFINED: { int typeinfo_offset;