From ea9e7b631832d892eeff1919c22f48f1c312620d Mon Sep 17 00:00:00 2001 From: Nikolay Sivov Date: Tue, 18 Mar 2014 02:24:26 +0400 Subject: [PATCH] widl: Fix default value types. --- tools/widl/write_msft.c | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/tools/widl/write_msft.c b/tools/widl/write_msft.c index 724be27e19d..adffe8571e8 100644 --- a/tools/widl/write_msft.c +++ b/tools/widl/write_msft.c @@ -1191,6 +1191,8 @@ static void write_value(msft_typelib_t* typelib, int *out, int vt, const void *v case VT_UINT: case VT_HRESULT: case VT_PTR: + case VT_UNKNOWN: + case VT_DISPATCH: { const unsigned int lv = get_ulong_val(*(const unsigned int *)value, vt); if((lv & 0x3ffffff) == lv) { @@ -1257,6 +1259,33 @@ static HRESULT set_custdata(msft_typelib_t *typelib, REFGUID guid, return S_OK; } +/* It's possible to have a default value for pointer arguments too. + In this case default value has a referenced type, e.g. + 'LONG*' argument gets VT_I4, 'DOUBLE*' - VT_R8. IUnknown* and IDispatch* + are recognised too and stored as VT_UNKNOWN and VT_DISPATCH. + But IUnknown/IDispatch arguments can only have default value of 0 + (or expression that resolves to zero) while other pointers can have + any default value. */ +static int get_defaultvalue_vt(type_t *type) +{ + int vt = get_type_vt(type); + if (type_get_type(type) == TYPE_ENUM) + vt = VT_I4; + else + { + vt = get_type_vt(type); + if (vt == VT_PTR && is_ptr(type)) { + vt = get_type_vt(type_pointer_get_ref(type)); + /* The only acceptable value for pointers to non-basic types + is NULL, it's stored as VT_I4 for both 32 and 64 bit typelibs. */ + if (vt == VT_USERDEFINED) + vt = VT_I4; + } + } + + return vt; +} + static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, var_t *func, int index) { int offset, name_offset; @@ -1481,10 +1510,7 @@ static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, var_t *func, int index) { int vt; expr_t *expr = (expr_t *)attr->u.pval; - if (type_get_type(arg->type) == TYPE_ENUM) - vt = VT_INT; - else - vt = get_type_vt(arg->type); + vt = get_defaultvalue_vt(arg->type); paramflags |= 0x30; /* PARAMFLAG_FHASDEFAULT | PARAMFLAG_FOPT */ if (expr->type == EXPR_STRLIT || expr->type == EXPR_WSTRLIT) {