Commit 49eb0b70 authored by Huw Davies's avatar Huw Davies Committed by Alexandre Julliard

Add support for dispinterfaces (slightly hacked because we force the

import of stdole2.tlb). Add propputref attribute.
parent 7266da3e
......@@ -271,6 +271,7 @@ static struct keyword {
{"properties", tPROPERTIES},
{"propget", tPROPGET},
{"propput", tPROPPUT},
{"propputref", tPROPPUTREF},
/* ... */
{"public", tPUBLIC},
/* ... */
......
......@@ -162,7 +162,7 @@ static type_t std_uhyper = { "MIDL_uhyper" };
%token tOUT
%token tPOINTERDEFAULT
%token tPROPERTIES
%token tPROPGET tPROPPUT
%token tPROPGET tPROPPUT tPROPPUTREF
%token tPUBLIC
%token tREADONLY tREF
%token tRESTRICTED
......@@ -368,6 +368,7 @@ attribute:
| tPOINTERDEFAULT '(' pointer_type ')' { $$ = make_attrv(ATTR_POINTERDEFAULT, $3); }
| tPROPGET { $$ = make_attr(ATTR_PROPGET); }
| tPROPPUT { $$ = make_attr(ATTR_PROPPUT); }
| tPROPPUTREF { $$ = make_attr(ATTR_PROPPUTREF); }
| tPUBLIC { $$ = make_attr(ATTR_PUBLIC); }
| tREADONLY { $$ = make_attr(ATTR_READONLY); }
| tRESTRICTED { $$ = make_attr(ATTR_RESTRICTED); }
......
......@@ -182,6 +182,7 @@ typedef struct {
/* bits 8 - 11: CALLCONV */
/* bit 12: parameters have default values */
/* bit 13: oEntry is numeric */
/* bits 16 - 31: index of next function with same id */
#ifdef WORDS_BIGENDIAN
INT16 nroargs; /* nr of optional arguments */
INT16 nrargs; /* number of arguments (including optional ????) */
......
......@@ -92,6 +92,7 @@ enum attr_type
ATTR_POINTERTYPE,
ATTR_PROPGET,
ATTR_PROPPUT,
ATTR_PROPPUTREF,
ATTR_PUBLIC,
ATTR_READONLY,
ATTR_RESTRICTED,
......
......@@ -583,7 +583,7 @@ static int ctl2_alloc_string(
}
/****************************************************************************
* ctl2_alloc_importinfo
* alloc_importinfo
*
* Allocates and initializes an import information structure in a type library.
*
......@@ -592,7 +592,7 @@ static int ctl2_alloc_string(
* Success: The offset of the new importinfo.
* Failure: -1 (this is invariably an out of memory condition).
*/
static int ctl2_alloc_importinfo(
static int alloc_importinfo(
msft_typelib_t *typelib, /* [I] The type library to allocate in. */
MSFT_ImpInfo *impinfo) /* [I] The import information to store. */
{
......@@ -618,7 +618,7 @@ static int ctl2_alloc_importinfo(
}
/****************************************************************************
* ctl2_alloc_importfile
* alloc_importfile
*
* Allocates and initializes an import file definition in a type library.
*
......@@ -627,7 +627,7 @@ static int ctl2_alloc_importinfo(
* Success: The offset of the new importinfo.
* Failure: -1 (this is invariably an out of memory condition).
*/
static int ctl2_alloc_importfile(
static int alloc_importfile(
msft_typelib_t *typelib, /* [I] The type library to allocate in. */
int guidoffset, /* [I] The offset to the GUID for the imported library. */
int major_version, /* [I] The major version number of the imported library. */
......@@ -1065,32 +1065,6 @@ static int encode_var(
}
/****************************************************************************
* ctl2_find_nth_reference
*
* Finds a reference by index into the linked list of reference records.
*
* RETURNS
*
* Success: Offset of the desired reference record.
* Failure: -1.
*/
static int ctl2_find_nth_reference(
msft_typelib_t *typelib, /* [I] The type library in which to search. */
int offset, /* [I] The starting offset of the reference list. */
int index) /* [I] The index of the reference to find. */
{
MSFT_RefRecord *ref;
for (; index && (offset != -1); index--) {
ref = (MSFT_RefRecord *)&typelib->typelib_segment_data[MSFT_SEG_REFERENCES][offset];
offset = ref->onext;
}
return offset;
}
static void write_value(msft_typelib_t* typelib, int *out, int vt, void *value)
{
switch(vt) {
......@@ -1177,7 +1151,7 @@ static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, func_t *func, int index)
{
int offset;
int *typedata, typedata_size;
int i, id;
int i, id, next_idx;
int decoded_size, extra_attr = 0;
int num_params = 0, num_defaults = 0;
var_t *arg, *last_arg = NULL;
......@@ -1189,6 +1163,9 @@ static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, func_t *func, int index)
id = ((0x6000 | (typeinfo->typeinfo->datatype2 & 0xffff)) << 16) | index;
if((typeinfo->typeinfo->typekind & 15) == TKIND_DISPATCH)
funckind = 0x4; /* FUNC_DISPATCH */
chat("add_func_desc(%p,%d)\n", typeinfo, index);
for(attr = func->def->attrs; attr; attr = NEXT_LINK(attr)) {
......@@ -1240,6 +1217,9 @@ static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, func_t *func, int index)
case ATTR_PROPPUT:
invokekind = 0x4; /* INVOKE_PROPERTYPUT */
break;
case ATTR_PROPPUTREF:
invokekind = 0x8; /* INVOKE_PROPERTYPUTREF */
break;
case ATTR_RESTRICTED:
funcflags |= 0x1; /* FUNCFLAG_FRESTRICTED */
break;
......@@ -1248,6 +1228,25 @@ static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, func_t *func, int index)
break;
}
}
switch(invokekind) {
case 0x2: /* INVOKE_PROPERTYGET */
if(num_params != 0) {
error("expecting no args on a propget func\n");
return S_FALSE;
}
break;
case 0x4: /* INVOKE_PROPERTYPUT */
case 0x8: /* INVOKE_PROPERTYPUTREF */
if(num_params != 1) {
error("expecting one arg on a propput func\n");
return S_FALSE;
}
break;
default:
break;
}
/* allocate type data space for us */
typedata_size = 0x18 + extra_attr * sizeof(int) + (num_params * (num_defaults ? 16 : 12));
......@@ -1267,12 +1266,23 @@ static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, func_t *func, int index)
typeinfo->func_data[0] += typedata_size;
typedata = typeinfo->func_data + (offset >> 2) + 1;
/* find the first func with the same id and link via the hiword of typedata[4] */
next_idx = index;
for(i = 0; i < (typeinfo->typeinfo->cElement & 0xffff); i++) {
if(id == typeinfo->func_indices[i]) {
next_idx = typeinfo->func_data[(typeinfo->func_offsets[i] >> 2) + 1 + 4] >> 16;
typeinfo->func_data[(typeinfo->func_offsets[i] >> 2) + 1 + 4] &= 0xffff;
typeinfo->func_data[(typeinfo->func_offsets[i] >> 2) + 1 + 4] |= (index << 16);
break;
}
}
/* fill out the basic type information */
typedata[0] = typedata_size | (index << 16);
encode_var(typeinfo->typelib, func->def, &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) | (invokekind << 3) | funckind;
typedata[4] = (next_idx << 16) | (callconv << 8) | (invokekind << 3) | funckind;
if(num_defaults) typedata[4] |= 0x1000;
typedata[5] = num_params;
......@@ -1385,18 +1395,19 @@ static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, func_t *func, int index)
namedata[9] &= ~0x10;
}
if(invokekind == 0x1 /* INVOKE_FUNC */) { /* don't give the arg of a [prop*] func a name */
for (arg = last_arg, i = 0; arg; arg = PREV_LINK(arg), i++) {
int *paramdata = typedata + 6 + extra_attr + (num_defaults ? num_params : 0) + i * 3;
offset = ctl2_alloc_name(typeinfo->typelib, arg->name);
paramdata[1] = offset;
chat("param %d name %s offset %d\n", i, arg->name, offset);
}
}
return S_OK;
}
static HRESULT add_var_desc(msft_typeinfo_t *typeinfo, UINT index, var_t* var)
{
int offset, typedata_size;
int offset, typedata_size, id;
INT *typedata;
int var_datawidth;
int var_alignment;
......@@ -1409,14 +1420,14 @@ static HRESULT add_var_desc(msft_typeinfo_t *typeinfo, UINT index, var_t* var)
chat("add_var_desc(%d,%s) array %p\n", index, var->name, var->array);
if (var_num != index) {
error("Out-of-order element.\n");
return TYPE_E_ELEMENTNOTFOUND;
}
id = 0x40000000 + index;
for(attr = var->attrs; attr; attr = NEXT_LINK(attr)) {
expr_t *expr = attr->u.pval;
switch(attr->type) {
case ATTR_ID:
id = expr->u.lval;
break;
default:
warning("AddVarDesc: unhandled attr type %d\n", attr->type);
break;
......@@ -1460,7 +1471,7 @@ static HRESULT add_var_desc(msft_typeinfo_t *typeinfo, UINT index, var_t* var)
typeinfo->var_offsets = xrealloc(typeinfo->var_offsets, typeinfo->vars_allocated * sizeof(int));
}
/* update the index data */
typeinfo->var_indices[var_num] = 0x40000000 + index;
typeinfo->var_indices[var_num] = id;
typeinfo->var_names[var_num] = -1;
typeinfo->var_offsets[var_num] = offset;
......@@ -1472,14 +1483,25 @@ static HRESULT add_var_desc(msft_typeinfo_t *typeinfo, UINT index, var_t* var)
typeinfo->datawidth += var_alignment - 1;
typeinfo->datawidth &= ~(var_alignment - 1);
if((typeinfo->typeinfo->typekind & 0xf) == TKIND_ENUM) {
switch(typeinfo->typeinfo->typekind & 0xf) {
case TKIND_ENUM:
write_value(typeinfo->typelib, &typedata[4], VT_I4, &var->lval);
var_kind = 2; /* VAR_CONST */
var_type_size += 16; /* sizeof(VARIANT) */
typeinfo->datawidth = var_datawidth;
} else {
break;
case TKIND_RECORD:
typedata[4] = typeinfo->datawidth;
typeinfo->datawidth += var_datawidth;
break;
case TKIND_DISPATCH:
var_kind = 3; /* VAR_DISPATCH */
typeinfo->datawidth = 4;
var_alignment = 4;
break;
default:
error("add_var_desc: unhandled type kind %d\n", typeinfo->typeinfo->typekind & 0xf);
break;
}
/* add type description size to total required allocation */
......@@ -1515,6 +1537,7 @@ static HRESULT add_var_desc(msft_typeinfo_t *typeinfo, UINT index, var_t* var)
namedata = typeinfo->typelib->typelib_segment_data[MSFT_SEG_NAME] + offset;
if (*((INT *)namedata) == -1) {
*((INT *)namedata) = typeinfo->typelib->typelib_typeinfo_offsets[typeinfo->typeinfo->typekind >> 16];
if((typeinfo->typeinfo->typekind & 15) != TKIND_DISPATCH)
namedata[9] |= 0x10;
} else
namedata[9] &= ~0x10;
......@@ -1627,6 +1650,78 @@ static msft_typeinfo_t *create_msft_typeinfo(msft_typelib_t *typelib, enum type_
return msft_typeinfo;
}
static void add_dispatch(msft_typelib_t *typelib)
{
int guid_offset, impfile_offset;
MSFT_GuidEntry guidentry;
MSFT_ImpInfo impinfo;
GUID stdole = {0x00020430,0x0000,0x0000,{0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}};
GUID iid_idispatch = {0x00020400,0x0000,0x0000,{0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}};
if(typelib->typelib_header.dispatchpos != -1) return;
guidentry.guid = stdole;
guidentry.hreftype = 2;
guidentry.next_hash = -1;
guid_offset = ctl2_alloc_guid(typelib, &guidentry);
impfile_offset = alloc_importfile(typelib, guid_offset, 2, 0, "stdole2.tlb");
guidentry.guid = iid_idispatch;
guidentry.hreftype = 1;
guidentry.next_hash = -1;
impinfo.res0 = 0x301 << 16;
impinfo.oImpFile = impfile_offset;
impinfo.oGuid = ctl2_alloc_guid(typelib, &guidentry);
typelib->typelib_header.dispatchpos = alloc_importinfo(typelib, &impinfo) | 0x01;
typelib->typelib_header.res50 = 1;
}
static void add_dispinterface_typeinfo(msft_typelib_t *typelib, type_t *dispinterface)
{
int idx = 0;
func_t *func;
var_t *var;
msft_typeinfo_t *msft_typeinfo;
msft_typeinfo = create_msft_typeinfo(typelib, TKIND_DISPATCH, dispinterface->name,
dispinterface->attrs, typelib->typelib_header.nrtypeinfos);
msft_typeinfo->typeinfo->size = 4;
msft_typeinfo->typeinfo->typekind |= 0x2100;
msft_typeinfo->typeinfo->flags |= 0x1000; /* TYPEFLAG_FDISPATCHABLE */
add_dispatch(typelib);
msft_typeinfo->typeinfo->cImplTypes = 1;
/* count the no of funcs, as the variable indicies come after the funcs */
if((func = dispinterface->funcs)) {
idx++;
while(NEXT_LINK(func)) {
func = NEXT_LINK(func);
idx++;
}
}
if((var = dispinterface->fields)) {
while(NEXT_LINK(var)) var = NEXT_LINK(var);
while(var) {
add_var_desc(msft_typeinfo, idx, var);
idx++;
var = PREV_LINK(var);
}
}
idx = 0;
/* the func count above has already left us pointing at the first func */
while(func) {
if(add_func_desc(msft_typeinfo, func, idx) == S_OK)
idx++;
func = PREV_LINK(func);
}
}
static void add_interface_typeinfo(msft_typelib_t *typelib, type_t *interface)
{
int idx = 0;
......@@ -1634,6 +1729,11 @@ static void add_interface_typeinfo(msft_typelib_t *typelib, type_t *interface)
type_t *ref;
msft_typeinfo_t *msft_typeinfo;
int num_parents = 0, num_funcs = 0;
attr_t *attr;
for(attr = interface->attrs; attr; attr = NEXT_LINK(attr))
if(attr->type == ATTR_DISPINTERFACE)
return add_dispinterface_typeinfo(typelib, interface);
/* midl adds the parent interface first, unless the parent itself
has no parent (i.e. it stops before IUnknown). */
......@@ -1946,15 +2046,25 @@ static void ctl2_write_typeinfos(msft_typelib_t *typelib, int fd)
ctl2_write_chunk(fd, typeinfo->func_data + 1, typeinfo->func_data[0]);
if (typeinfo->var_data)
ctl2_write_chunk(fd, typeinfo->var_data + 1, typeinfo->var_data[0]);
if (typeinfo->func_indices) {
if (typeinfo->func_indices)
ctl2_write_chunk(fd, typeinfo->func_indices, (typeinfo->typeinfo->cElement & 0xffff) * 4);
if (typeinfo->var_indices)
ctl2_write_chunk(fd, typeinfo->var_indices, (typeinfo->typeinfo->cElement >> 16) * 4);
if (typeinfo->func_names)
ctl2_write_chunk(fd, typeinfo->func_names, (typeinfo->typeinfo->cElement & 0xffff) * 4);
if (typeinfo->var_names)
ctl2_write_chunk(fd, typeinfo->var_names, (typeinfo->typeinfo->cElement >> 16) * 4);
if (typeinfo->func_offsets)
ctl2_write_chunk(fd, typeinfo->func_offsets, (typeinfo->typeinfo->cElement & 0xffff) * 4);
if (typeinfo->var_offsets) {
int add = 0, i, offset;
if(typeinfo->func_data)
add = typeinfo->func_data[0];
for(i = 0; i < (typeinfo->typeinfo->cElement >> 16); i++) {
offset = typeinfo->var_offsets[i];
offset += add;
ctl2_write_chunk(fd, &offset, 4);
}
if (typeinfo->var_indices) {
ctl2_write_chunk(fd, typeinfo->var_indices, (typeinfo->typeinfo->cElement >> 16) * 4);
ctl2_write_chunk(fd, typeinfo->var_names, (typeinfo->typeinfo->cElement >> 16) * 4);
ctl2_write_chunk(fd, typeinfo->var_offsets, (typeinfo->typeinfo->cElement >> 16) * 4);
}
}
}
......
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