Commit a3026ca8 authored by Huw Davies's avatar Huw Davies Committed by Alexandre Julliard

Add support for optional arguments and some suppport for the

defaultvalue attributes. Better calculation of the typeinfo's res3 member (at least for interfaces).
parent c2ccf0f4
......@@ -350,8 +350,8 @@ attribute:
| tCONTEXTHANDLESERIALIZE { $$ = make_attrv(ATTR_CONTEXTHANDLE, 0); /* RPC_CONTEXT_HANDLE_SERIALIZE */ }
| tCONTROL { $$ = make_attr(ATTR_CONTROL); }
| tDEFAULT { $$ = make_attr(ATTR_DEFAULT); }
| tDEFAULTVALUE '(' expr_const ')' { $$ = make_attrp(ATTR_DEFAULTVALUE, $3); }
| tDEFAULTVALUE '(' aSTRING ')' { $$ = make_attrp(ATTR_DEFAULTVALUE, $3); }
| tDEFAULTVALUE '(' expr_const ')' { $$ = make_attrp(ATTR_DEFAULTVALUE_EXPR, $3); }
| tDEFAULTVALUE '(' aSTRING ')' { $$ = make_attrp(ATTR_DEFAULTVALUE_STRING, $3); }
| tDLLNAME '(' aSTRING ')' { $$ = make_attrp(ATTR_DLLNAME, $3); }
| tDUAL { $$ = make_attr(ATTR_DUAL); }
| tENDPOINT '(' aSTRING ')' { $$ = make_attrp(ATTR_ENDPOINT, $3); }
......
......@@ -62,7 +62,8 @@ enum attr_type
ATTR_CONTEXTHANDLE,
ATTR_CONTROL,
ATTR_DEFAULT,
ATTR_DEFAULTVALUE,
ATTR_DEFAULTVALUE_EXPR,
ATTR_DEFAULTVALUE_STRING,
ATTR_DLLNAME,
ATTR_DUAL,
ATTR_ENDPOINT,
......
......@@ -648,9 +648,9 @@ static int ctl2_alloc_importfile(
/****************************************************************************
* ctl2_encode_typedesc
* ctl2_encode_type
*
* Encodes a type description, storing information in the TYPEDESC and ARRAYDESC
* Encodes a type, storing information in the TYPEDESC and ARRAYDESC
* segments as needed.
*
* RETURNS
......@@ -927,13 +927,53 @@ static int ctl2_find_nth_reference(
}
static void write_value(msft_typeinfo_t* typeinfo, int *out, var_t *arg, int type, void *value)
{
int vt = (type >> 16) & 0x1ff;
switch(vt) {
case VT_I2:
case VT_I4:
case VT_R4:
case VT_BOOL:
case VT_I1:
case VT_UI1:
case VT_UI2:
case VT_UI4:
case VT_INT:
case VT_UINT:
case VT_HRESULT:
{
unsigned long *lv = value;
if((*lv & 0x3ffffff) == *lv) {
*out = 0x80000000;
*out |= vt << 26;
*out |= *lv;
} else {
int offset = ctl2_alloc_segment(typeinfo->typelib, MSFT_SEG_CUSTDATA, 8, 0);
*((unsigned short *)&typeinfo->typelib->typelib_segment_data[MSFT_SEG_CUSTDATA][offset]) = vt;
memcpy(&typeinfo->typelib->typelib_segment_data[MSFT_SEG_CUSTDATA][offset+2], value, 4);
*((unsigned short *)&typeinfo->typelib->typelib_segment_data[MSFT_SEG_CUSTDATA][offset+6]) = 0x5757;
*out = offset;
}
return;
}
case VT_BSTR:
warning("default value BSTR %s\n", (char*)value);
break;
default:
warning("can't write value of type %d yet\n", vt);
}
return;
}
static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, func_t *func)
{
int offset;
int *typedata;
int i, index = func->idx, id;
int decoded_size;
int num_params = 0;
int num_params = 0, num_defaults = 0;
var_t *arg, *last_arg = NULL;
char *namedata;
attr_t *attr;
......@@ -951,6 +991,12 @@ static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, func_t *func)
for(arg = func->args; arg; arg = NEXT_LINK(arg)) {
last_arg = arg;
num_params++;
for(attr = arg->attrs; attr; attr = NEXT_LINK(attr)) {
if(attr->type == ATTR_DEFAULTVALUE_EXPR || attr->type == ATTR_DEFAULTVALUE_STRING) {
num_defaults++;
break;
}
}
}
chat("num of params %d\n", num_params);
......@@ -973,30 +1019,56 @@ static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, func_t *func)
}
/* allocate type data space for us */
offset = typeinfo->typedata[0];
typeinfo->typedata[0] += 0x18 + (num_params * 12);
typeinfo->typedata[0] += 0x18 + (num_params * (num_defaults ? 16 : 12));
typedata = typeinfo->typedata + (offset >> 2) + 1;
/* fill out the basic type information */
typedata[0] = (0x18 + (num_params * 12)) | (index << 16);
typedata[0] = (0x18 + (num_params * (num_defaults ? 16 : 12))) | (index << 16);
ctl2_encode_type(typeinfo->typelib, func->def->type, func->def->ptr_level, func->def->array, &typedata[1], NULL, NULL, &decoded_size);
typedata[2] = funcflags;
typedata[3] = ((52 /*sizeof(FUNCDESC)*/ + decoded_size) << 16) | typeinfo->typeinfo->cbSizeVft;
typedata[4] = (index << 16) | (callconv << 8) | 9;
if(num_defaults) typedata[4] |= 0x10;
typedata[5] = num_params;
/* NOTE: High word of typedata[3] is total size of FUNCDESC + size of all ELEMDESCs for params + TYPEDESCs for pointer params and return types. */
/* That is, total memory allocation required to reconstitute the FUNCDESC in its entirety. */
typedata[3] += (16 /*sizeof(ELEMDESC)*/ * num_params) << 16;
typedata[3] += (24 /*sizeof(PARAMDESCEX)*/ * num_defaults) << 16;
for (arg = last_arg, i = 0; arg; arg = PREV_LINK(arg), i++) {
attr_t *attr;
int paramflags = 0;
int *paramdata = typedata + 6 + (num_defaults ? num_params : 0) + i * 3;
int *defaultdata = num_defaults ? typedata + 6 + i : NULL;
if(defaultdata) *defaultdata = -1;
ctl2_encode_type(typeinfo->typelib, arg->type, arg->ptr_level, arg->array, paramdata, NULL, NULL, &decoded_size);
for(attr = arg->attrs; attr; attr = NEXT_LINK(attr)) {
switch(attr->type) {
case ATTR_DEFAULTVALUE_EXPR:
{
expr_t *expr = (expr_t *)attr->u.pval;
paramflags |= 0x30; /* PARAMFLAG_FHASDEFAULT | PARAMFLAG_FOPT */
chat("default value %ld\n", expr->cval);
write_value(typeinfo, defaultdata, arg, *paramdata, &expr->cval);
break;
}
case ATTR_DEFAULTVALUE_STRING:
{
char *s = (char *)attr->u.pval;
paramflags |= 0x30; /* PARAMFLAG_FHASDEFAULT | PARAMFLAG_FOPT */
chat("default value '%s'\n", s);
write_value(typeinfo, defaultdata, arg, *paramdata, s);
break;
}
case ATTR_IN:
paramflags |= 0x01; /* PARAMFLAG_FIN */
break;
case ATTR_OPTIONAL:
paramflags |= 0x10; /* PARAMFLAG_FOPT */
break;
case ATTR_OUT:
paramflags |= 0x02; /* PARAMFLAG_FOUT */
break;
......@@ -1008,17 +1080,9 @@ static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, func_t *func)
break;
}
}
ctl2_encode_type(typeinfo->typelib, arg->type, arg->ptr_level, arg->array, &typedata[6+(i*3)], NULL, NULL, &decoded_size);
typedata[7+(i*3)] = -1;
typedata[8+(i*3)] = paramflags;
paramdata[1] = -1;
paramdata[2] = paramflags;
typedata[3] += decoded_size << 16;
#if 0
/* FIXME: Doesn't work. Doesn't even come up with usable VTs for varDefaultValue. */
if (pFuncDesc->lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) {
ctl2_alloc_custdata(This->typelib, &pFuncDesc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
}
#endif
}
/* update the index data */
......@@ -1029,14 +1093,12 @@ static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, func_t *func)
/* ??? */
if (!typeinfo->typeinfo->res2) typeinfo->typeinfo->res2 = 0x20;
typeinfo->typeinfo->res2 <<= 1;
/* ??? */
if (typeinfo->typeinfo->res3 == -1) typeinfo->typeinfo->res3 = 0;
typeinfo->typeinfo->res3 += 0x38;
/* ??? */
if (index < 2) typeinfo->typeinfo->res2 += num_params << 4;
typeinfo->typeinfo->res3 += num_params << 4;
if (typeinfo->typeinfo->res3 == -1) typeinfo->typeinfo->res3 = 0;
typeinfo->typeinfo->res3 += 0x38 + num_params * 0x10;
if(num_defaults) typeinfo->typeinfo->res3 += num_params * 0x4;
/* adjust size of VTBL */
typeinfo->typeinfo->cbSizeVft += 4;
......@@ -1058,9 +1120,9 @@ static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, func_t *func)
for (arg = last_arg, i = 0; arg; arg = PREV_LINK(arg), i++) {
/* FIXME: Almost certainly easy to break */
int *paramdata = &typeinfo->typedata[typeinfo->offsets[index] >> 2];
paramdata += 7 + (num_defaults ? num_params : 0) + i * 3;
offset = ctl2_alloc_name(typeinfo->typelib, arg->name);
paramdata[(i * 3) + 8] = offset;
paramdata[1] = offset;
chat("param %d name %s offset %d\n", i, arg->name, offset);
}
return S_OK;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment