Signed-off-by: Kevin Puetz PuetzKevinA@JohnDeere.com --- tools/widl/parser.l | 2 +- tools/widl/parser.y | 18 ++++++++++++++++++ tools/widl/widltypes.h | 7 +++++++ 3 files changed, 26 insertions(+), 1 deletion(-)
diff --git a/tools/widl/parser.l b/tools/widl/parser.l index 925265d00d..f50975bd67 100644 --- a/tools/widl/parser.l +++ b/tools/widl/parser.l @@ -337,6 +337,7 @@ static const struct keyword attr_keywords[] = {"context_handle_noserialize", tCONTEXTHANDLENOSERIALIZE}, {"context_handle_serialize", tCONTEXTHANDLENOSERIALIZE}, {"control", tCONTROL}, + {"custom", tCUSTOM}, {"decode", tDECODE}, {"defaultbind", tDEFAULTBIND}, {"defaultcollelem", tDEFAULTCOLLELEM}, @@ -427,7 +428,6 @@ static const struct keyword attr_keywords[] = };
/* attributes TODO: - custom first_is last_is max_is diff --git a/tools/widl/parser.y b/tools/widl/parser.y index 52eb96488a..1a300ddb33 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -58,6 +58,7 @@ static decl_spec_t *make_decl_spec(type_t *type, decl_spec_t *left, decl_spec_t static attr_t *make_attr(enum attr_type type); static attr_t *make_attrv(enum attr_type type, unsigned int val); static attr_t *make_attrp(enum attr_type type, void *val); +static attr_t *make_custom_attr(UUID *id, expr_t *pval); static expr_list_t *append_expr(expr_list_t *list, expr_t *expr); static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, declarator_t *decl, int top); static var_list_t *set_var_types(attr_list_t *attrs, decl_spec_t *decl_spec, declarator_list_t *decls); @@ -177,6 +178,7 @@ static typelib_t *current_typelib; %token tCALLAS tCALLBACK tCASE tCDECL tCHAR tCOCLASS tCODE tCOMMSTATUS %token tCONST tCONTEXTHANDLE tCONTEXTHANDLENOSERIALIZE %token tCONTEXTHANDLESERIALIZE tCONTROL tCPPQUOTE +%token tCUSTOM %token tDECODE tDEFAULT tDEFAULTBIND %token tDEFAULTCOLLELEM %token tDEFAULTVALUE @@ -505,6 +507,7 @@ attribute: { $$ = NULL; } | tCONTEXTHANDLENOSERIALIZE { $$ = make_attrv(ATTR_CONTEXTHANDLE, 0); /* RPC_CONTEXT_HANDLE_DONT_SERIALIZE */ } | tCONTEXTHANDLESERIALIZE { $$ = make_attrv(ATTR_CONTEXTHANDLE, 0); /* RPC_CONTEXT_HANDLE_SERIALIZE */ } | tCONTROL { $$ = make_attr(ATTR_CONTROL); } + | tCUSTOM '(' uuid_string ',' expr_const ')' { $$ = make_custom_attr($3, $5); } | tDECODE { $$ = make_attr(ATTR_DECODE); } | tDEFAULT { $$ = make_attr(ATTR_DEFAULT); } | tDEFAULTBIND { $$ = make_attr(ATTR_DEFAULTBIND); } @@ -1231,6 +1234,8 @@ static attr_list_t *append_attr(attr_list_t *list, attr_t *attr) list = xmalloc( sizeof(*list) ); list_init( list ); } + if(attr->type != ATTR_CUSTOM) + { LIST_FOR_EACH_ENTRY(attr_existing, list, attr_t, entry) if (attr_existing->type == attr->type) { @@ -1239,6 +1244,7 @@ static attr_list_t *append_attr(attr_list_t *list, attr_t *attr) list_remove(&attr_existing->entry); break; } + } list_add_tail( list, &attr->entry ); return list; } @@ -1363,6 +1369,17 @@ static attr_t *make_attrp(enum attr_type type, void *val) return a; }
+static attr_t *make_custom_attr(UUID *id, expr_t *pval) +{ + attr_t *a = xmalloc(sizeof(attr_t)); + attr_custdata_t *cstdata = xmalloc(sizeof(attr_custdata_t)); + a->type = ATTR_CUSTOM; + cstdata->id = *id; + cstdata->pval = pval; + a->u.pval = cstdata; + return a; +} + static expr_list_t *append_expr(expr_list_t *list, expr_t *expr) { if (!expr) return list; @@ -2136,6 +2153,7 @@ struct allowed_attr allowed_attr[] = /* ATTR_COMMSTATUS */ { 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "comm_status" }, /* ATTR_CONTEXTHANDLE */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "context_handle" }, /* ATTR_CONTROL */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, "control" }, + /* ATTR_CUSTOM */ { 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, "custom" }, /* ATTR_DECODE */ { 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "decode" }, /* ATTR_DEFAULT */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, "default" }, /* ATTR_DEFAULTBIND */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "defaultbind" }, diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h index 085a0ff55f..6b67538594 100644 --- a/tools/widl/widltypes.h +++ b/tools/widl/widltypes.h @@ -37,6 +37,7 @@ typedef GUID UUID;
typedef struct _loc_info_t loc_info_t; typedef struct _attr_t attr_t; +typedef struct _attr_custdata_t attr_custdata_t; typedef struct _expr_t expr_t; typedef struct _type_t type_t; typedef struct _var_t var_t; @@ -83,6 +84,7 @@ enum attr_type ATTR_COMMSTATUS, ATTR_CONTEXTHANDLE, ATTR_CONTROL, + ATTR_CUSTOM, ATTR_DECODE, ATTR_DEFAULT, ATTR_DEFAULTBIND, @@ -337,6 +339,11 @@ struct _expr_t { struct list entry; };
+struct _attr_custdata_t { + GUID id; + expr_t *pval; +}; + struct struct_details { var_list_t *fields;
Signed-off-by: Kevin Puetz PuetzKevinA@JohnDeere.com --- tools/widl/write_msft.c | 79 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 75 insertions(+), 4 deletions(-)
diff --git a/tools/widl/write_msft.c b/tools/widl/write_msft.c index aa05dcfe56..4fc5d46050 100644 --- a/tools/widl/write_msft.c +++ b/tools/widl/write_msft.c @@ -1276,6 +1276,7 @@ static HRESULT set_custdata(msft_typelib_t *typelib, REFGUID guid,
guidoffset = ctl2_alloc_guid(typelib, &guidentry); if(vt == VT_BSTR) + /* TODO midl appears to share a single reference if the same string is used as custdata in multiple places */ write_string_value(typelib, &data_out, value); else write_int_value(typelib, &data_out, vt, *(int*)value); @@ -1291,6 +1292,25 @@ static HRESULT set_custdata(msft_typelib_t *typelib, REFGUID guid, return S_OK; }
+static HRESULT set_custdata_attr(msft_typelib_t *typelib, attr_custdata_t *custdata, int *offset) +{ + switch(custdata->pval->type) { + case EXPR_STRLIT: + case EXPR_WSTRLIT: + set_custdata(typelib, &custdata->id, VT_BSTR, custdata->pval->u.sval, offset); + break; + case EXPR_HEXNUM: + case EXPR_NUM: + set_custdata(typelib, &custdata->id, VT_I4, &custdata->pval->u.lval, offset); + break; + default: + error("custom() attribute with unknown type\n"); + break; + } + + return S_OK; +} + static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, var_t *func, int index) { int offset, name_offset; @@ -1298,12 +1318,14 @@ static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, var_t *func, int index) int i, id, next_idx; int decoded_size, extra_attr = 0; int num_params = 0, num_optional = 0, num_defaults = 0; + int has_arg_custdata = 0; var_t *arg; unsigned char *namedata; const attr_t *attr; unsigned int funcflags = 0, callconv = 4 /* CC_STDCALL */; unsigned int funckind, invokekind = 1 /* INVOKE_FUNC */; int help_context = 0, help_string_context = 0, help_string_offset = -1; + int func_custdata_offset = -1; int entry = -1, entry_is_ord = 0; int lcid_retval_count = 0;
@@ -1337,6 +1359,8 @@ static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, var_t *func, int index) num_defaults++; else if(attr->type == ATTR_OPTIONAL) num_optional++; + else if(attr->type == ATTR_CUSTOM) + has_arg_custdata = 1; } }
@@ -1350,6 +1374,9 @@ static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, var_t *func, int index) case ATTR_BINDABLE: funcflags |= 0x4; /* FUNCFLAG_FBINDABLE */ break; + case ATTR_CUSTOM: + set_custdata_attr(typeinfo->typelib, attr->u.pval, &func_custdata_offset); + break; case ATTR_DEFAULTBIND: funcflags |= 0x20; /* FUNCFLAG_FDEFAULTBIND */ break; @@ -1430,6 +1457,10 @@ static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, var_t *func, int index) } }
+ if(has_arg_custdata || func_custdata_offset != -1) { + extra_attr = max(extra_attr, 7 + num_params); + } + /* allocate type data space for us */ typedata_size = 0x18 + extra_attr * sizeof(int) + (num_params * (num_defaults ? 16 : 12));
@@ -1476,6 +1507,7 @@ static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, var_t *func, int index) typedata[2] = funcflags; typedata[3] = ((52 /*sizeof(FUNCDESC)*/ + decoded_size) << 16) | typeinfo->typeinfo->cbSizeVft; typedata[4] = (next_idx << 16) | (callconv << 8) | (invokekind << 3) | funckind; + if(has_arg_custdata || func_custdata_offset != -1) typedata[4] |= 0x0080; if(num_defaults) typedata[4] |= 0x1000; if(entry_is_ord) typedata[4] |= 0x2000; typedata[5] = (num_optional << 16) | num_params; @@ -1486,6 +1518,10 @@ static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, var_t *func, int index) typedata[3] += (24 /*sizeof(PARAMDESCEX)*/ * num_defaults) << 16;
switch(extra_attr) { + default: + if(extra_attr > 7 + num_params) warning("unknown number of optional attrs\n"); + /* typedata[13..+num_params] = arg_custdata_offset handled in below loop */ + case 7: typedata[12] = func_custdata_offset; case 6: typedata[11] = help_string_context; case 5: typedata[10] = -1; case 4: typedata[9] = -1; @@ -1494,8 +1530,6 @@ static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, var_t *func, int index) case 1: typedata[6] = help_context; case 0: break; - default: - warning("unknown number of optional attrs\n"); }
if (type_function_get_args(func->declspec.type)) @@ -1506,12 +1540,16 @@ static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, var_t *func, int index) int paramflags = 0; int *paramdata = typedata + 6 + extra_attr + (num_defaults ? num_params : 0) + i * 3; int *defaultdata = num_defaults ? typedata + 6 + extra_attr + i : NULL; + int arg_custdata_offset = -1;
if(defaultdata) *defaultdata = -1;
encode_var(typeinfo->typelib, arg->declspec.type, arg, paramdata, &decoded_size); if (arg->attrs) LIST_FOR_EACH_ENTRY( attr, arg->attrs, const attr_t, entry ) { switch(attr->type) { + case ATTR_CUSTOM: + set_custdata_attr(typeinfo->typelib, attr->u.pval, &arg_custdata_offset); + break; case ATTR_DEFAULTVALUE: { paramflags |= 0x30; /* PARAMFLAG_FHASDEFAULT | PARAMFLAG_FOPT */ @@ -1539,6 +1577,9 @@ static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, var_t *func, int index) chat("unhandled param attr %d\n", attr->type); break; } + if(extra_attr > 7 + i) { + typedata[13+i] = arg_custdata_offset; + } } paramdata[1] = -1; paramdata[2] = paramflags; @@ -1621,6 +1662,7 @@ static HRESULT add_var_desc(msft_typeinfo_t *typeinfo, UINT index, var_t* var) { int offset, id; unsigned int typedata_size; + int extra_attr = 0; INT *typedata; unsigned int var_datawidth, var_alignment = 0; int var_type_size, var_kind = 0 /* VAR_PERINSTANCE */; @@ -1629,6 +1671,7 @@ static HRESULT add_var_desc(msft_typeinfo_t *typeinfo, UINT index, var_t* var) const attr_t *attr; unsigned char *namedata; int var_num = (typeinfo->typeinfo->cElement >> 16) & 0xffff; + int var_custdata_offset = -1;
if (!var->name) var->name = gen_name(); @@ -1643,6 +1686,10 @@ static HRESULT add_var_desc(msft_typeinfo_t *typeinfo, UINT index, var_t* var) case ATTR_BINDABLE: varflags |= 0x04; /* VARFLAG_FBINDABLE */ break; + case ATTR_CUSTOM: + extra_attr = max(extra_attr,4); + set_custdata_attr(typeinfo->typelib, attr->u.pval, &var_custdata_offset); + break; case ATTR_DEFAULTBIND: varflags |= 0x20; /* VARFLAG_FDEFAULTBIND */ break; @@ -1686,7 +1733,7 @@ static HRESULT add_var_desc(msft_typeinfo_t *typeinfo, UINT index, var_t* var) }
/* allocate type data space for us */ - typedata_size = 0x14; + typedata_size = 0x14 + extra_attr * sizeof(int);
if (!typeinfo->var_data) { typeinfo->var_data = xmalloc(0x100); @@ -1762,6 +1809,17 @@ static HRESULT add_var_desc(msft_typeinfo_t *typeinfo, UINT index, var_t* var) /* add type description size to total required allocation */ typedata[3] += var_type_size << 16 | var_kind;
+ switch(extra_attr) { + case 5: typedata[9] = -1 /*help_context*/; + case 4: typedata[8] = var_custdata_offset; + case 3: typedata[7] = -1; + case 2: typedata[6] = -1 /*help_string_offset*/; + case 1: typedata[5] = -1 /*help_context*/; + break; + default: + warning("unknown number of optional attrs\n"); + } + /* fix type alignment */ alignment = (typeinfo->typeinfo->typekind >> 11) & 0x1f; if (alignment < var_alignment) { @@ -1871,7 +1929,9 @@ static msft_typeinfo_t *create_msft_typeinfo(msft_typelib_t *typelib, enum type_ if (kind == TKIND_COCLASS) typeinfo->flags |= 0x20; /* TYPEFLAG_FCONTROL */ break; - + case ATTR_CUSTOM: + set_custdata_attr(typelib, attr->u.pval, &typeinfo->oCustData); + break; case ATTR_DLLNAME: { int offset = ctl2_alloc_string(typelib, attr->u.pval); @@ -2699,6 +2759,7 @@ int create_msft_typelib(typelib_t *typelib) msft_typelib_t *msft; int failed = 0; const statement_t *stmt; + const attr_t *attr; time_t cur_time; char *time_override; unsigned int version = 7 << 24 | 555; /* 7.00.0555 */ @@ -2746,6 +2807,16 @@ int create_msft_typelib(typelib_t *typelib) set_help_string_dll(msft); set_help_string_context(msft);
+ if (typelib->attrs) LIST_FOR_EACH_ENTRY( attr, typelib->attrs, const attr_t, entry ) { + switch(attr->type) { + case ATTR_CUSTOM: + set_custdata_attr(msft, attr->u.pval, &msft->typelib_header.CustomDataOffset); + break; + default: + break; + } + } + /* midl adds two sets of custom data to the library: the current unix time and midl's version number */ time_override = getenv( "WIDL_TIME_OVERRIDE");
e.g. using the same kind of custdata in multiple interfaces
Signed-off-by: Kevin Puetz PuetzKevinA@JohnDeere.com --- tools/widl/write_msft.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-)
diff --git a/tools/widl/write_msft.c b/tools/widl/write_msft.c index 4fc5d46050..5cf6389149 100644 --- a/tools/widl/write_msft.c +++ b/tools/widl/write_msft.c @@ -1263,18 +1263,25 @@ static void write_default_value(msft_typelib_t *typelib, type_t *type, expr_t *e static HRESULT set_custdata(msft_typelib_t *typelib, REFGUID guid, int vt, const void *value, int *offset) { - MSFT_GuidEntry guidentry; int guidoffset; int custoffset; int *custdata; int data_out; + int hash_key;
- guidentry.guid = *guid; + hash_key = ctl2_hash_guid(guid); + guidoffset = ctl2_find_guid(typelib, hash_key, guid); + if(guidoffset == -1) { + /* add GUID that was not already present */ + MSFT_GuidEntry guidentry; + guidentry.guid = *guid;
- guidentry.hreftype = -1; - guidentry.next_hash = -1; + guidentry.hreftype = -1; + guidentry.next_hash = -1; + + guidoffset = ctl2_alloc_guid(typelib, &guidentry); + }
- guidoffset = ctl2_alloc_guid(typelib, &guidentry); if(vt == VT_BSTR) /* TODO midl appears to share a single reference if the same string is used as custdata in multiple places */ write_string_value(typelib, &data_out, value);