/*================== Implementation Structures ===================================*/
/* Used for storing cyclic list. Tail address is kept */
+enum tagCyclicListElementType {
+ CyclicListFunc,
+ CyclicListVar
+};
typedef struct tagCyclicList {
struct tagCyclicList *next;
int indice;
int name;
+ enum tagCyclicListElementType type;
union {
int val;
struct tagCyclicList *typedata; /* tail of cyclic list */
+ TYPEKIND typekind;
int datawidth;
struct tagICreateTypeInfo2Impl *next_typeinfo;
+ struct tagICreateTypeInfo2Impl *dual;
} ICreateTypeInfo2Impl;
static inline ICreateTypeInfo2Impl *impl_from_ITypeInfo2( ITypeInfo2 *iface )
while (offset != -1) {
guidentry = (MSFT_GuidEntry *)&This->typelib_segment_data[MSFT_SEG_GUID][offset];
- if (!memcmp(guidentry, guid, sizeof(GUID))) return offset;
+ if (IsEqualGUID(guidentry, guid)) return offset;
offset = guidentry->next_hash;
}
encoded_string[0] |= 1;
for (offset = 0; offset < This->typelib_segdir[MSFT_SEG_IMPORTFILES].length;
- offset += ((((This->typelib_segment_data[MSFT_SEG_IMPORTFILES][offset + 0xd] << 8) & 0xff)
- | (This->typelib_segment_data[MSFT_SEG_IMPORTFILES][offset + 0xc] & 0xff)) >> 2) + 0xc) {
+ offset += ((((((This->typelib_segment_data[MSFT_SEG_IMPORTFILES][offset + 0xd] << 8) & 0xff00)
+ | (This->typelib_segment_data[MSFT_SEG_IMPORTFILES][offset + 0xc] & 0xff)) >> 2) + 5) & 0xfffc) + 0xc) {
if (!memcmp(encoded_string, This->typelib_segment_data[MSFT_SEG_IMPORTFILES] + offset + 0xc, length)) return offset;
}
}
/****************************************************************************
- * ctl2_alloc_custdata
+ * ctl2_encode_variant
*
- * Allocates and initializes a "custom data" value in a type library.
+ * Encodes a variant, inline if possible or in custom data segment
*
* RETURNS
*
- * Success: The offset of the new custdata.
- * Failure:
- *
- * -1: Out of memory.
- * -2: Unable to encode VARIANT data (typically a bug).
+ * Success: S_OK
+ * Failure: Error code from winerror.h
*/
-static int ctl2_alloc_custdata(
- ICreateTypeLib2Impl *This, /* [I] The type library in which to encode the value. */
- VARIANT *pVarVal) /* [I] The value to encode. */
+static HRESULT ctl2_encode_variant(
+ ICreateTypeLib2Impl *This, /* [I] The typelib to allocate data in */
+ int *encoded_value, /* [O] The encoded default value or data offset */
+ VARIANT *value, /* [I] Default value to be encoded */
+ VARTYPE arg_type) /* [I] Argument type */
{
- int offset;
+ VARIANT v;
+ HRESULT hres;
+ int mask = 0;
+
+ TRACE("%p %d %d\n", This, V_VT(value), arg_type);
- TRACE("(%p,%p(%d))\n",This,pVarVal,V_VT(pVarVal));
+ if(arg_type == VT_INT)
+ arg_type = VT_I4;
+ if(arg_type == VT_UINT)
+ arg_type = VT_UI4;
+
+ v = *value;
+ if(V_VT(value) != arg_type) {
+ hres = VariantChangeType(&v, value, 0, arg_type);
+ if(FAILED(hres))
+ return hres;
+ }
- switch (V_VT(pVarVal)) {
+ /* Check if default value can be stored in encoded_value */
+ switch(arg_type) {
+ case VT_I4:
case VT_UI4:
- offset = ctl2_alloc_segment(This, MSFT_SEG_CUSTDATA, 8, 0);
- if (offset == -1) return offset;
+ mask = 0x3ffffff;
+ if(V_UI4(&v)>0x3ffffff)
+ break;
+ case VT_I1:
+ case VT_UI1:
+ case VT_BOOL:
+ if(!mask)
+ mask = 0xff;
+ case VT_I2:
+ case VT_UI2:
+ if(!mask)
+ mask = 0xffff;
+ *encoded_value = (V_UI4(&v)&mask) | ((0x80+0x4*arg_type)<<24);
+ return S_OK;
+ }
- *((unsigned short *)&This->typelib_segment_data[MSFT_SEG_CUSTDATA][offset]) = VT_UI4;
- *((unsigned int *)&This->typelib_segment_data[MSFT_SEG_CUSTDATA][offset+2]) = V_UI4(pVarVal);
- break;
+ switch(arg_type) {
+ case VT_I4:
+ case VT_R4:
+ case VT_UI4:
+ case VT_INT:
+ case VT_UINT:
+ case VT_HRESULT:
+ case VT_PTR: {
+ /* Construct the data to be allocated */
+ int data[2];
+ data[0] = arg_type + (V_UI4(&v)<<16);
+ data[1] = (V_UI4(&v)>>16) + 0x57570000;
- default:
- FIXME("Unknown variable encoding vt %d.\n", V_VT(pVarVal));
- return -2;
+ /* Check if the data was already allocated */
+ /* Currently the structures doesn't allow to do it in a nice way */
+ for(*encoded_value=0; *encoded_value<=This->typelib_segdir[MSFT_SEG_CUSTDATA].length-8; *encoded_value+=4)
+ if(!memcmp(&This->typelib_segment_data[MSFT_SEG_CUSTDATA][*encoded_value], data, 8))
+ return S_OK;
+
+ /* Allocate the data */
+ *encoded_value = ctl2_alloc_segment(This, MSFT_SEG_CUSTDATA, 8, 0);
+ if(*encoded_value == -1)
+ return E_OUTOFMEMORY;
+
+ memcpy(&This->typelib_segment_data[MSFT_SEG_CUSTDATA][*encoded_value], data, 8);
+ return S_OK;
}
+ case VT_BSTR: {
+ /* Construct the data */
+ int i, len = (6+SysStringLen(V_BSTR(&v))+3) & ~0x3;
+ char *data = HeapAlloc(GetProcessHeap(), 0, len);
- return offset;
+ if(!data)
+ return E_OUTOFMEMORY;
+
+ *((unsigned short*)data) = arg_type;
+ *((unsigned*)(data+2)) = SysStringLen(V_BSTR(&v));
+ for(i=0; i<SysStringLen(V_BSTR(&v)); i++) {
+ if(V_BSTR(&v)[i] <= 0x7f)
+ data[i+6] = V_BSTR(&v)[i];
+ else
+ data[i+6] = '?';
+ }
+ WideCharToMultiByte(CP_ACP, 0, V_BSTR(&v), SysStringLen(V_BSTR(&v)), &data[6], len-6, NULL, NULL);
+ for(i=6+SysStringLen(V_BSTR(&v)); i<len; i++)
+ data[i] = 0x57;
+
+ /* Check if the data was already allocated */
+ for(*encoded_value=0; *encoded_value<=This->typelib_segdir[MSFT_SEG_CUSTDATA].length-len; *encoded_value+=4)
+ if(!memcmp(&This->typelib_segment_data[MSFT_SEG_CUSTDATA][*encoded_value], data, len)) {
+ HeapFree(GetProcessHeap(), 0, data);
+ return S_OK;
+ }
+
+ /* Allocate the data */
+ *encoded_value = ctl2_alloc_segment(This, MSFT_SEG_CUSTDATA, len, 0);
+ if(*encoded_value == -1) {
+ HeapFree(GetProcessHeap(), 0, data);
+ return E_OUTOFMEMORY;
+ }
+
+ memcpy(&This->typelib_segment_data[MSFT_SEG_CUSTDATA][*encoded_value], data, len);
+ HeapFree(GetProcessHeap(), 0, data);
+ return S_OK;
+ }
+ default:
+ FIXME("Argument type not yet handled\n");
+ return E_NOTIMPL;
+ }
}
/****************************************************************************
int *offset) /* [I/O] The list of custom data to prepend to. */
{
MSFT_GuidEntry guidentry;
+ HRESULT status;
int dataoffset;
int guidoffset;
int custoffset;
int *custdata;
+ switch(V_VT(pVarVal))
+ {
+ case VT_I4:
+ case VT_R4:
+ case VT_UI4:
+ case VT_INT:
+ case VT_UINT:
+ case VT_HRESULT:
+ case VT_BSTR:
+ /* empty */
+ break;
+ default:
+ return DISP_E_BADVARTYPE;
+ }
+
guidentry.guid = *guid;
guidentry.hreftype = -1;
guidoffset = ctl2_alloc_guid(This, &guidentry);
if (guidoffset == -1) return E_OUTOFMEMORY;
- dataoffset = ctl2_alloc_custdata(This, pVarVal);
- if (dataoffset == -1) return E_OUTOFMEMORY;
- if (dataoffset == -2) return E_INVALIDARG;
+
+ status = ctl2_encode_variant(This, &dataoffset, pVarVal, V_VT(pVarVal));
+ if (status)
+ return status;
custoffset = ctl2_alloc_segment(This, MSFT_SEG_CUSTDATAGUID, 12, 0);
if (custoffset == -1) return E_OUTOFMEMORY;
break;
case VT_PTR:
- /* FIXME: Make with the error checking. */
- FIXME("PTR vartype, may not work correctly.\n");
-
- ctl2_encode_typedesc(This, tdesc->u.lptdesc, &target_type, NULL, NULL, &child_size);
-
- for (typeoffset = 0; typeoffset < This->typelib_segdir[MSFT_SEG_TYPEDESC].length; typeoffset += 8) {
- typedata = (void *)&This->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
- if (((typedata[0] & 0xffff) == VT_PTR) && (typedata[1] == target_type)) break;
- }
-
- if (typeoffset == This->typelib_segdir[MSFT_SEG_TYPEDESC].length) {
- int mix_field;
-
- if (target_type & 0x80000000) {
- mix_field = ((target_type >> 16) & 0x3fff) | VT_BYREF;
- } else {
- typedata = (void *)&This->typelib_segment_data[MSFT_SEG_TYPEDESC][target_type];
- mix_field = ((typedata[0] >> 16) == 0x7fff)? 0x7fff: 0x7ffe;
- }
-
- typeoffset = ctl2_alloc_segment(This, MSFT_SEG_TYPEDESC, 8, 0);
- typedata = (void *)&This->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
-
- typedata[0] = (mix_field << 16) | VT_PTR;
- typedata[1] = target_type;
- }
-
- *encoded_tdesc = typeoffset;
-
- *width = 4;
- *alignment = 4;
- *decoded_size = sizeof(TYPEDESC) + child_size;
- break;
-
case VT_SAFEARRAY:
/* FIXME: Make with the error checking. */
- FIXME("SAFEARRAY vartype, may not work correctly.\n");
+ FIXME("PTR or SAFEARRAY vartype, may not work correctly.\n");
ctl2_encode_typedesc(This, tdesc->u.lptdesc, &target_type, NULL, NULL, &child_size);
for (typeoffset = 0; typeoffset < This->typelib_segdir[MSFT_SEG_TYPEDESC].length; typeoffset += 8) {
typedata = (void *)&This->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
- if (((typedata[0] & 0xffff) == VT_SAFEARRAY) && (typedata[1] == target_type)) break;
+ if (((typedata[0] & 0xffff) == tdesc->vt) && (typedata[1] == target_type)) break;
}
if (typeoffset == This->typelib_segdir[MSFT_SEG_TYPEDESC].length) {
int mix_field;
if (target_type & 0x80000000) {
- mix_field = ((target_type >> 16) & VT_TYPEMASK) | VT_ARRAY;
+ mix_field = (target_type >> 16) & VT_TYPEMASK;
} else {
typedata = (void *)&This->typelib_segment_data[MSFT_SEG_TYPEDESC][target_type];
- mix_field = ((typedata[0] >> 16) == 0x7fff)? 0x7fff: 0x7ffe;
+ switch((typedata[0]>>16) & ~VT_ARRAY)
+ {
+ case VT_UI1:
+ case VT_I1:
+ case VT_UI2:
+ case VT_I2:
+ case VT_I4:
+ case VT_UI4:
+ mix_field = typedata[0]>>16;
+ break;
+ default:
+ mix_field = 0x7fff;
+ break;
+ }
}
+ if (tdesc->vt == VT_PTR)
+ mix_field |= VT_BYREF;
+ else if (tdesc->vt == VT_SAFEARRAY)
+ mix_field |= VT_ARRAY;
+
typeoffset = ctl2_alloc_segment(This, MSFT_SEG_TYPEDESC, 8, 0);
typedata = (void *)&This->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
- typedata[0] = (mix_field << 16) | VT_SAFEARRAY;
+ typedata[0] = (mix_field << 16) | tdesc->vt;
typedata[1] = target_type;
}
break;
}
case VT_USERDEFINED:
+ {
+ const MSFT_TypeInfoBase *basetype;
+ INT basevt = 0x7fff;
+
TRACE("USERDEFINED.\n");
+ if (tdesc->u.hreftype % sizeof(*basetype) == 0 && tdesc->u.hreftype < This->typelib_segdir[MSFT_SEG_TYPEINFO].length)
+ {
+ basetype = (MSFT_TypeInfoBase*)&(This->typelib_segment_data[MSFT_SEG_TYPEINFO][tdesc->u.hreftype]);
+ switch(basetype->typekind & 0xf)
+ {
+ case TKIND_ENUM:
+ basevt = VT_I4;
+ break;
+ default:
+ FIXME("USERDEFINED basetype %d not handled\n", basetype->typekind & 0xf);
+ break;
+ }
+ }
for (typeoffset = 0; typeoffset < This->typelib_segdir[MSFT_SEG_TYPEDESC].length; typeoffset += 8) {
typedata = (void *)&This->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
- if ((typedata[0] == ((0x7fff << 16) | VT_USERDEFINED)) && (typedata[1] == tdesc->u.hreftype)) break;
+ if ((typedata[0] == ((basevt << 16) | VT_USERDEFINED)) && (typedata[1] == tdesc->u.hreftype)) break;
}
if (typeoffset == This->typelib_segdir[MSFT_SEG_TYPEDESC].length) {
typeoffset = ctl2_alloc_segment(This, MSFT_SEG_TYPEDESC, 8, 0);
typedata = (void *)&This->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
- typedata[0] = (0x7fff << 16) | VT_USERDEFINED;
+ typedata[0] = (basevt << 16) | VT_USERDEFINED;
typedata[1] = tdesc->u.hreftype;
}
*width = 0;
*alignment = 1;
break;
+ }
default:
FIXME("Unrecognized type %d.\n", tdesc->vt);
}
/****************************************************************************
- * ctl2_add_default_value
+ * funcrecord_reallochdr
+ *
+ * Ensure FuncRecord data block contains header of required size
*
- * Adds default value of an argument
+ * PARAMS
+ *
+ * typedata [IO] - reference to pointer to data block
+ * need [I] - required size of block in bytes
*
* RETURNS
*
- * Success: S_OK
- * Failure: Error code from winerror.h
+ * Number of additionally allocated bytes
*/
-static HRESULT ctl2_add_default_value(
- ICreateTypeLib2Impl *This, /* [I] The typelib to allocate data in */
- int *encoded_value, /* [O] The encoded default value or data offset */
- VARIANT *value, /* [I] Default value to be encoded */
- VARTYPE arg_type) /* [I] Argument type */
+static INT funcrecord_reallochdr(INT **typedata, int need)
{
- VARIANT v;
- HRESULT hres;
-
- TRACE("%p %d %d\n", This, V_VT(value), arg_type);
-
- if(arg_type == VT_INT)
- arg_type = VT_I4;
- if(arg_type == VT_UINT)
- arg_type = VT_UI4;
-
- v = *value;
- if(V_VT(value) != arg_type) {
- hres = VariantChangeType(&v, value, 0, arg_type);
- if(FAILED(hres))
- return hres;
- }
-
- /* Check if default value can be stored in encoded_value */
- switch(arg_type) {
- int mask = 0;
- case VT_I4:
- case VT_UI4:
- mask = 0x3ffffff;
- if(V_UI4(&v)>0x3ffffff)
- break;
- case VT_I1:
- case VT_UI1:
- case VT_BOOL:
- if(!mask)
- mask = 0xff;
- case VT_I2:
- case VT_UI2:
- if(!mask)
- mask = 0xffff;
- *encoded_value = (V_UI4(&v)&mask) | ((0x80+0x4*arg_type)<<24);
- return S_OK;
- }
-
- switch(arg_type) {
- case VT_I4:
- case VT_R4:
- case VT_UI4:
- case VT_INT:
- case VT_UINT:
- case VT_HRESULT:
- case VT_PTR: {
- /* Construct the data to be allocated */
- int data[2];
- data[0] = arg_type + (V_UI4(&v)<<16);
- data[1] = (V_UI4(&v)>>16) + 0x57570000;
-
- /* Check if the data was already allocated */
- /* Currently the structures doesn't allow to do it in a nice way */
- for(*encoded_value=0; *encoded_value<=This->typelib_segdir[MSFT_SEG_CUSTDATA].length-8; *encoded_value+=4)
- if(!memcmp(&This->typelib_segment_data[MSFT_SEG_CUSTDATA][*encoded_value], data, 8))
- return S_OK;
-
- /* Allocate the data */
- *encoded_value = ctl2_alloc_segment(This, MSFT_SEG_CUSTDATA, 8, 0);
- if(*encoded_value == -1)
- return E_OUTOFMEMORY;
-
- memcpy(&This->typelib_segment_data[MSFT_SEG_CUSTDATA][*encoded_value], data, 8);
- return S_OK;
- }
- case VT_BSTR: {
- /* Construct the data */
- int i, len = (6+SysStringLen(V_BSTR(&v))+3) & ~0x3;
- char *data = HeapAlloc(GetProcessHeap(), 0, len);
+ int tail = (*typedata)[5]*((*typedata)[4]&0x1000?16:12);
+ int hdr = (*typedata)[0] - tail;
+ int i;
- if(!data)
- return E_OUTOFMEMORY;
+ if (hdr >= need)
+ return 0;
- *((unsigned short*)data) = arg_type;
- *((unsigned*)(data+2)) = SysStringLen(V_BSTR(&v));
- for(i=0; i<SysStringLen(V_BSTR(&v)); i++) {
- if(V_BSTR(&v)[i] <= 0x7f)
- data[i+6] = V_BSTR(&v)[i];
- else
- data[i+6] = '?';
- }
- WideCharToMultiByte(CP_ACP, 0, V_BSTR(&v), SysStringLen(V_BSTR(&v)), &data[6], len-6, NULL, NULL);
- for(i=6+SysStringLen(V_BSTR(&v)); i<len; i++)
- data[i] = 0x57;
+ *typedata = HeapReAlloc(GetProcessHeap(), 0, *typedata, need + tail);
+ if (!*typedata)
+ return -1;
- /* Check if the data was already allocated */
- for(*encoded_value=0; *encoded_value<=This->typelib_segdir[MSFT_SEG_CUSTDATA].length-len; *encoded_value+=4)
- if(!memcmp(&This->typelib_segment_data[MSFT_SEG_CUSTDATA][*encoded_value], data, len)) {
- HeapFree(GetProcessHeap(), 0, data);
- return S_OK;
- }
+ if (tail)
+ memmove((char*)*typedata + need, (const char*)*typedata + hdr, tail);
+ (*typedata)[0] = need + tail;
- /* Allocate the data */
- *encoded_value = ctl2_alloc_segment(This, MSFT_SEG_CUSTDATA, len, 0);
- if(*encoded_value == -1) {
- HeapFree(GetProcessHeap(), 0, data);
- return E_OUTOFMEMORY;
+ /* fill in default values */
+ for(i = (hdr+3)/4; (i+1)*4 <= need; i++)
+ {
+ switch(i)
+ {
+ case 2:
+ (*typedata)[i] = 0;
+ break;
+ case 7:
+ (*typedata)[i] = -1;
+ break;
+ case 8:
+ (*typedata)[i] = -1;
+ break;
+ case 9:
+ (*typedata)[i] = -1;
+ break;
+ case 10:
+ (*typedata)[i] = -1;
+ break;
+ case 11:
+ (*typedata)[i] = 0;
+ break;
+ case 12:
+ (*typedata)[i] = -1;
+ break;
}
-
- memcpy(&This->typelib_segment_data[MSFT_SEG_CUSTDATA][*encoded_value], data, len);
- HeapFree(GetProcessHeap(), 0, data);
- return S_OK;
- }
- default:
- FIXME("Argument type not yet handled\n");
- return E_NOTIMPL;
}
+
+ return need - hdr;
}
/*================== ICreateTypeInfo2 Implementation ===================================*/
if(*ppvObject)
{
- ICreateTypeLib2_AddRef(iface);
+ ICreateTypeInfo2_AddRef(iface);
TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
return S_OK;
}
TRACE("(%p)->ref was %u\n",This, ref - 1);
+ if(ref==1 && This->typelib)
+ ICreateTypeLib2_AddRef((ICreateTypeLib2 *)This->typelib);
+
return ref;
}
TRACE("(%p,0x%x)\n", iface, uTypeFlags);
- This->typeinfo->flags = uTypeFlags;
+ if(uTypeFlags & TYPEFLAG_FDUAL) {
+ This->typeinfo->typekind |= 0x10;
+ This->typeinfo->typekind &= ~0x0f;
+ This->typeinfo->typekind |= TKIND_DISPATCH;
+
+ if(!This->dual) {
+ This->dual = HeapAlloc(GetProcessHeap(), 0, sizeof(ICreateTypeInfo2Impl));
+ if(!This->dual)
+ return E_OUTOFMEMORY;
+
+ memcpy(This->dual, This, sizeof(ICreateTypeInfo2Impl));
+ This->dual->ref = 0;
+ This->dual->typekind = This->typekind==TKIND_DISPATCH ?
+ TKIND_INTERFACE : TKIND_DISPATCH;
+ This->dual->dual = This;
+ }
+
+ /* Make sure dispatch is in typeinfos queue */
+ if(This->typekind != TKIND_DISPATCH) {
+ if(This->typelib->last_typeinfo == This)
+ This->typelib->last_typeinfo = This->dual;
+
+ if(This->typelib->typeinfos == This)
+ This->typelib->typeinfos = This->dual;
+ else {
+ ICreateTypeInfo2Impl *iter;
+
+ for(iter=This->typelib->typeinfos; iter->next_typeinfo!=This; iter=iter->next_typeinfo);
+ iter->next_typeinfo = This->dual;
+ }
+ } else
+ iface = (ICreateTypeInfo2*)&This->dual->lpVtbl;
+ }
- if (uTypeFlags & TYPEFLAG_FDISPATCHABLE) {
- MSFT_GuidEntry foo;
- int guidoffset;
- int fileoffset;
- MSFT_ImpInfo impinfo;
- static const WCHAR stdole2tlb[] = { 's','t','d','o','l','e','2','.','t','l','b',0 };
-
- foo.guid = IID_StdOle;
- foo.hreftype = 2;
- foo.next_hash = -1;
- guidoffset = ctl2_alloc_guid(This->typelib, &foo);
- if (guidoffset == -1) return E_OUTOFMEMORY;
-
- fileoffset = ctl2_alloc_importfile(This->typelib, guidoffset,
- This->typelib->typelib_header.lcid2, 2, 0, stdole2tlb);
- if (fileoffset == -1) return E_OUTOFMEMORY;
-
- foo.guid = IID_IDispatch;
- foo.hreftype = 1;
- foo.next_hash = -1;
- guidoffset = ctl2_alloc_guid(This->typelib, &foo);
- if (guidoffset == -1) return E_OUTOFMEMORY;
-
- impinfo.flags = TKIND_INTERFACE << 24 | MSFT_IMPINFO_OFFSET_IS_GUID;
- impinfo.oImpFile = fileoffset;
- impinfo.oGuid = guidoffset;
- ctl2_alloc_importinfo(This->typelib, &impinfo);
-
- This->typelib->typelib_header.dispatchpos = 1;
-
- This->typeinfo->typekind |= 0x10;
- This->typeinfo->typekind &= ~0x0f;
- This->typeinfo->typekind |= TKIND_DISPATCH;
+ if (uTypeFlags & (TYPEFLAG_FDISPATCHABLE|TYPEFLAG_FDUAL)) {
+ static const WCHAR stdole2tlb[] = { 's','t','d','o','l','e','2','.','t','l','b',0 };
+ ITypeLib *stdole;
+ ITypeInfo *dispatch;
+ HREFTYPE hreftype;
+ HRESULT hres;
+
+ hres = LoadTypeLib(stdole2tlb, &stdole);
+ if(FAILED(hres))
+ return hres;
+
+ hres = ITypeLib_GetTypeInfoOfGuid(stdole, &IID_IDispatch, &dispatch);
+ ITypeLib_Release(stdole);
+ if(FAILED(hres))
+ return hres;
+
+ hres = ICreateTypeInfo2_AddRefTypeInfo(iface, dispatch, &hreftype);
+ ITypeInfo_Release(dispatch);
+ if(FAILED(hres))
+ return hres;
}
+ This->typeinfo->flags = uTypeFlags;
return S_OK;
}
/* Process locally defined TypeInfo */
*phRefType = This->typelib->typelib_typeinfo_offsets[index];
} else {
- static const WCHAR regkey[] = {'T','y','p','e','L','i','b','\\','{',
- '%','0','8','x','-','%','0','4','x','-','%','0','4','x','-','%',
- '0','2','x','%','0','2','x','-','%','0','2','x','%','0','2','x',
- '%','0','2','x','%','0','2','x','%','0','2','x','%','0','2','x',
- '}','\\','%','d','.','%','d','\\','0','\\','w','i','n','3','2',0};
-
- WCHAR name[MAX_PATH], *p;
+ BSTR name;
TLIBATTR *tlibattr;
TYPEATTR *typeattr;
+ TYPEKIND typekind;
MSFT_GuidEntry guid, *check_guid;
MSFT_ImpInfo impinfo;
int guid_offset, import_offset;
- DWORD len;
HRESULT hres;
/* Allocate container GUID */
hres = ITypeLib_GetLibAttr(container, &tlibattr);
- if(FAILED(hres))
+ if(FAILED(hres)) {
+ ITypeLib_Release(container);
return hres;
+ }
guid.guid = tlibattr->guid;
- guid.hreftype = This->typelib->typelib_guids*12+2;
+ guid.hreftype = This->typelib->typelib_segdir[MSFT_SEG_IMPORTFILES].length+2;
guid.next_hash = -1;
guid_offset = ctl2_alloc_guid(This->typelib, &guid);
if(guid_offset == -1) {
ITypeLib_ReleaseTLibAttr(container, tlibattr);
+ ITypeLib_Release(container);
return E_OUTOFMEMORY;
}
This->typelib->typelib_guids++;
/* Get import file name */
- /* Check HKEY_CLASSES_ROOT\TypeLib\{GUID}\{Ver}\0\win32 */
- len = MAX_PATH;
- sprintfW(name, regkey, guid.guid.Data1, guid.guid.Data2,
- guid.guid.Data3, guid.guid.Data4[0], guid.guid.Data4[1],
- guid.guid.Data4[2], guid.guid.Data4[3], guid.guid.Data4[4],
- guid.guid.Data4[5], guid.guid.Data4[6], guid.guid.Data4[7],
- tlibattr->wMajorVerNum, tlibattr->wMinorVerNum);
-
- if(RegGetValueW(HKEY_CLASSES_ROOT, name, NULL, RRF_RT_REG_SZ, NULL, name, &len)!=ERROR_SUCCESS
- || (p=strrchrW(name, '\\'))==NULL) {
- ERR("Error guessing typelib filename\n");
+ hres = QueryPathOfRegTypeLib(&guid.guid, tlibattr->wMajorVerNum,
+ tlibattr->wMinorVerNum, tlibattr->lcid, &name);
+ if(FAILED(hres)) {
ITypeLib_ReleaseTLibAttr(container, tlibattr);
- return E_NOTIMPL;
+ ITypeLib_Release(container);
+ return hres;
}
- memmove(name, p+1, strlenW(p)*sizeof(WCHAR));
/* Import file */
- import_offset = ctl2_alloc_importfile(This->typelib, guid_offset,
- tlibattr->lcid, tlibattr->wMajorVerNum, tlibattr->wMinorVerNum, name);
+ import_offset = ctl2_alloc_importfile(This->typelib, guid_offset, tlibattr->lcid,
+ tlibattr->wMajorVerNum, tlibattr->wMinorVerNum, strrchrW(name, '\\')+1);
ITypeLib_ReleaseTLibAttr(container, tlibattr);
+ SysFreeString(name);
- if(import_offset == -1)
+ if(import_offset == -1) {
+ ITypeLib_Release(container);
return E_OUTOFMEMORY;
+ }
/* Allocate referenced guid */
hres = ITypeInfo_GetTypeAttr(pTInfo, &typeattr);
- if(FAILED(hres))
+ if(FAILED(hres)) {
+ ITypeLib_Release(container);
return hres;
+ }
guid.guid = typeattr->guid;
guid.hreftype = This->typelib->typeinfo_guids*12+1;
guid.next_hash = -1;
+ typekind = typeattr->typekind;
ITypeInfo_ReleaseTypeAttr(pTInfo, typeattr);
guid_offset = ctl2_alloc_guid(This->typelib, &guid);
- if(guid_offset == -1)
+ if(guid_offset == -1) {
+ ITypeLib_Release(container);
return E_OUTOFMEMORY;
+ }
check_guid = (MSFT_GuidEntry*)&This->typelib->typelib_segment_data[MSFT_SEG_GUID][guid_offset];
if(check_guid->hreftype == guid.hreftype)
This->typelib->typeinfo_guids++;
/* Allocate importinfo */
- impinfo.flags = ((This->typeinfo->typekind&0xf)<<24) | MSFT_IMPINFO_OFFSET_IS_GUID;
+ impinfo.flags = (typekind<<24) | MSFT_IMPINFO_OFFSET_IS_GUID;
impinfo.oImpFile = import_offset;
impinfo.oGuid = guid_offset;
*phRefType = ctl2_alloc_importinfo(This->typelib, &impinfo)+1;
- if(!memcmp(&guid.guid, &IID_IDispatch, sizeof(GUID)))
+ if(IsEqualGUID(&guid.guid, &IID_IDispatch))
This->typelib->typelib_header.dispatchpos = *phRefType;
}
CyclicList *iter, *insert;
int *typedata;
- int i, num_defaults = 0;
+ int i, num_defaults = 0, num_retval = 0;
int decoded_size;
HRESULT hres;
TRACE("(%p,%d,%p)\n", iface, index, pFuncDesc);
- if(!pFuncDesc || (pFuncDesc->memid>0x7fffffff && pFuncDesc->memid!=MEMBERID_NIL))
+ if(!pFuncDesc || pFuncDesc->oVft&3)
return E_INVALIDARG;
TRACE("{%d,%p,%p,%d,%d,%d,%d,%d,%d,%d,{%d},%d}\n", pFuncDesc->memid,
pFuncDesc->cParamsOpt, pFuncDesc->oVft, pFuncDesc->cScodes,
pFuncDesc->elemdescFunc.tdesc.vt, pFuncDesc->wFuncFlags);
- switch(This->typeinfo->typekind&0xf) {
+ if(pFuncDesc->cParamsOpt || pFuncDesc->cScodes)
+ FIXME("Unimplemented parameter - created typelib will be incorrect\n");
+
+ switch(This->typekind) {
case TKIND_MODULE:
if(pFuncDesc->funckind != FUNC_STATIC)
return TYPE_E_BADMODULEKIND;
return TYPE_E_INCONSISTENTPROPFUNCS;
/* get number of arguments with default values specified */
- for (i = 0; i < pFuncDesc->cParams; i++)
+ for (i = 0; i < pFuncDesc->cParams; i++) {
if(pFuncDesc->lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
num_defaults++;
+ if(pFuncDesc->lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL)
+ num_retval++;
+ }
if (!This->typedata) {
- This->typedata = HeapAlloc(GetProcessHeap(), 0, sizeof(CyclicList));
+ This->typedata = HeapAlloc(GetProcessHeap(), 0, sizeof(CyclicList));
if(!This->typedata)
return E_OUTOFMEMORY;
This->typedata->next = This->typedata;
- This->typedata->u.val = 0;
+ This->typedata->u.val = 0;
+
+ if(This->dual)
+ This->dual->typedata = This->typedata;
}
/* allocate type data space for us */
typedata[0] = 0x18 + pFuncDesc->cParams*(num_defaults?16:12);
ctl2_encode_typedesc(This->typelib, &pFuncDesc->elemdescFunc.tdesc, &typedata[1], NULL, NULL, &decoded_size);
typedata[2] = pFuncDesc->wFuncFlags;
- typedata[3] = ((sizeof(FUNCDESC) + decoded_size) << 16) | This->typeinfo->cbSizeVft;
+ typedata[3] = ((sizeof(FUNCDESC) + decoded_size) << 16) | (unsigned short)(pFuncDesc->oVft?pFuncDesc->oVft+1:0);
typedata[4] = (pFuncDesc->callconv << 8) | (pFuncDesc->invkind << 3) | pFuncDesc->funckind;
if(num_defaults) typedata[4] |= 0x1000;
+ if (num_retval) typedata[4] |= 0x4000;
typedata[5] = pFuncDesc->cParams;
/* NOTE: High word of typedata[3] is total size of FUNCDESC + size of all ELEMDESCs for params + TYPEDESCs for pointer params and return types. */
if(num_defaults) {
for (i = 0; i < pFuncDesc->cParams; i++)
if(pFuncDesc->lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) {
- hres = ctl2_add_default_value(This->typelib, typedata+6+i,
+ hres = ctl2_encode_variant(This->typelib, typedata+6+i,
&pFuncDesc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue,
pFuncDesc->lprgelemdescParam[i].tdesc.vt);
/* update the index data */
insert->indice = pFuncDesc->memid;
insert->name = -1;
+ insert->type = CyclicListFunc;
/* insert type data to list */
if(index == This->typeinfo->cElement) {
insert->next = This->typedata->next;
This->typedata->next = insert;
This->typedata = insert;
+
+ if(This->dual)
+ This->dual->typedata = This->typedata;
} else {
iter = This->typedata->next;
for(i=0; i<index; i++)
TRACE("(%p,%d,%d)\n", iface, index, hRefType);
- if ((This->typeinfo->typekind & 15) == TKIND_COCLASS) {
+ if (This->typekind == TKIND_COCLASS) {
int offset;
MSFT_RefRecord *ref;
ref->flags = 0;
ref->oCustData = -1;
ref->onext = -1;
- } else if ((This->typeinfo->typekind & 15) == TKIND_DISPATCH) {
- FIXME("dispatch case unhandled.\n");
- } else if ((This->typeinfo->typekind & 15) == TKIND_INTERFACE) {
+ This->typeinfo->cImplTypes++;
+ } else if (This->typekind == TKIND_INTERFACE) {
if (This->typeinfo->cImplTypes && index==1)
return TYPE_E_BADMODULEKIND;
if( index != 0) return TYPE_E_ELEMENTNOTFOUND;
This->typeinfo->datatype1 = hRefType;
+ This->typeinfo->cImplTypes = 1;
+ } else if (This->typekind == TKIND_DISPATCH) {
+ if(index != 0) return TYPE_E_ELEMENTNOTFOUND;
+
+ /* FIXME: Check if referenced typeinfo is IDispatch */
+ This->typeinfo->flags |= TYPEFLAG_FDISPATCHABLE;
+ This->typeinfo->cImplTypes = 1;
} else {
- FIXME("AddImplType unsupported on typekind %d\n", This->typeinfo->typekind & 15);
+ FIXME("AddImplType unsupported on typekind %d\n", This->typekind);
return E_OUTOFMEMORY;
}
- This->typeinfo->cImplTypes++;
return S_OK;
}
TRACE("(%p,%d,0x%x)\n", iface, index, implTypeFlags);
- if ((This->typeinfo->typekind & 15) != TKIND_COCLASS) {
+ if (This->typekind != TKIND_COCLASS) {
return TYPE_E_BADMODULEKIND;
}
This->typeinfo->typekind |= cbAlignment << 6;
/* FIXME: There's probably some way to simplify this. */
- switch (This->typeinfo->typekind & 15) {
+ switch (This->typekind) {
case TKIND_ALIAS:
default:
break;
{
ICreateTypeInfo2Impl *This = (ICreateTypeInfo2Impl *)iface;
+ HRESULT status = S_OK;
CyclicList *insert;
INT *typedata;
int var_datawidth;
This->typedata->next = This->typedata;
This->typedata->u.val = 0;
+
+ if(This->dual)
+ This->dual->typedata = This->typedata;
}
/* allocate type data space for us */
This->typedata->next = insert;
This->typedata = insert;
+ if(This->dual)
+ This->dual->typedata = This->typedata;
+
This->typedata->next->u.val += 0x14;
typedata = This->typedata->u.data;
/* fill out the basic type information */
typedata[0] = 0x14 | (index << 16);
typedata[2] = pVarDesc->wVarFlags;
- typedata[3] = (sizeof(VARDESC) << 16) | 0;
+ typedata[3] = (sizeof(VARDESC) << 16) | pVarDesc->varkind;
/* update the index data */
insert->indice = 0x40000000 + index;
insert->name = -1;
+ insert->type = CyclicListVar;
/* figure out type widths and whatnot */
ctl2_encode_typedesc(This->typelib, &pVarDesc->elemdescVar.tdesc,
&typedata[1], &var_datawidth, &var_alignment,
&var_type_size);
- /* pad out starting position to data width */
- This->datawidth += var_alignment - 1;
- This->datawidth &= ~(var_alignment - 1);
- typedata[4] = This->datawidth;
-
- /* add the new variable to the total data width */
- This->datawidth += var_datawidth;
-
- /* add type description size to total required allocation */
- typedata[3] += var_type_size << 16;
-
- /* fix type alignment */
- alignment = (This->typeinfo->typekind >> 11) & 0x1f;
- if (alignment < var_alignment) {
- alignment = var_alignment;
- This->typeinfo->typekind &= ~0xf800;
- This->typeinfo->typekind |= alignment << 11;
- }
+ if (pVarDesc->varkind != VAR_CONST)
+ {
+ /* pad out starting position to data width */
+ This->datawidth += var_alignment - 1;
+ This->datawidth &= ~(var_alignment - 1);
+ typedata[4] = This->datawidth;
+
+ /* add the new variable to the total data width */
+ This->datawidth += var_datawidth;
+ if(This->dual)
+ This->dual->datawidth = This->datawidth;
+
+ /* add type description size to total required allocation */
+ typedata[3] += var_type_size << 16;
+
+ /* fix type alignment */
+ alignment = (This->typeinfo->typekind >> 11) & 0x1f;
+ if (alignment < var_alignment) {
+ alignment = var_alignment;
+ This->typeinfo->typekind &= ~0xf800;
+ This->typeinfo->typekind |= alignment << 11;
+ }
- /* ??? */
- if (!This->typeinfo->res2) This->typeinfo->res2 = 0x1a;
- if ((index == 0) || (index == 1) || (index == 2) || (index == 4) || (index == 9)) {
- This->typeinfo->res2 <<= 1;
- }
+ /* ??? */
+ if (!This->typeinfo->res2) This->typeinfo->res2 = 0x1a;
+ if ((index == 0) || (index == 1) || (index == 2) || (index == 4) || (index == 9)) {
+ This->typeinfo->res2 <<= 1;
+ }
+
+ /* ??? */
+ if (This->typeinfo->res3 == -1) This->typeinfo->res3 = 0;
+ This->typeinfo->res3 += 0x2c;
- /* ??? */
- if (This->typeinfo->res3 == -1) This->typeinfo->res3 = 0;
- This->typeinfo->res3 += 0x2c;
+ /* pad data width to alignment */
+ This->typeinfo->size = (This->datawidth + (alignment - 1)) & ~(alignment - 1);
+ } else {
+ VARIANT *value = pVarDesc->DUMMYUNIONNAME.lpvarValue;
+ status = ctl2_encode_variant(This->typelib, typedata+4, value, V_VT(value));
+ /* ??? native sets size 0x34 */
+ typedata[3] += 0x10 << 16;
+ }
/* increment the number of variable elements */
This->typeinfo->cElement += 0x10000;
- /* pad data width to alignment */
- This->typeinfo->size = (This->datawidth + (alignment - 1)) & ~(alignment - 1);
-
- return S_OK;
+ return status;
}
/******************************************************************************
if(!rgszNames)
return E_INVALIDARG;
- if(index >= This->typeinfo->cElement || !cNames)
+ if(index >= (This->typeinfo->cElement&0xFFFF) || !cNames)
return TYPE_E_ELEMENTNOTFOUND;
- len = ctl2_encode_name(This->typelib, rgszNames[0], &namedata);
- for(iter2=This->typedata->next->next; iter2!=This->typedata->next; iter2=iter2->next) {
- if(i == index)
- iter = iter2;
- else if(iter2->name!=-1 && !memcmp(namedata,
- This->typelib->typelib_segment_data[MSFT_SEG_NAME]+iter2->name+8, len))
- return TYPE_E_AMBIGUOUSNAME;
-
- i++;
- }
+ for(iter=This->typedata->next->next, i=0; /* empty */; iter=iter->next)
+ if (iter->type == CyclicListFunc)
+ if (i++ >= index)
+ break;
/* cNames == cParams for put or putref accessor, cParams+1 otherwise */
if(cNames != iter->u.data[5] + ((iter->u.data[4]>>3)&(INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF) ? 0 : 1))
return TYPE_E_ELEMENTNOTFOUND;
+ len = ctl2_encode_name(This->typelib, rgszNames[0], &namedata);
+ for(iter2=This->typedata->next->next; iter2!=This->typedata->next; iter2=iter2->next) {
+ if(iter2->name!=-1 && !memcmp(namedata,
+ This->typelib->typelib_segment_data[MSFT_SEG_NAME]+iter2->name+8, len)) {
+ /* getters/setters can have a same name */
+ if (iter2->type == CyclicListFunc) {
+ INT inv1 = iter2->u.data[4] >> 3;
+ INT inv2 = iter->u.data[4] >> 3;
+ if (((inv1&(INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF)) && (inv2&INVOKE_PROPERTYGET)) ||
+ ((inv2&(INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF)) && (inv1&INVOKE_PROPERTYGET)))
+ continue;
+ }
+
+ return TYPE_E_AMBIGUOUSNAME;
+ }
+ }
+
offset = ctl2_alloc_name(This->typelib, rgszNames[0]);
if(offset == -1)
return E_OUTOFMEMORY;
iter->name = offset;
namedata = This->typelib->typelib_segment_data[MSFT_SEG_NAME] + offset;
- *((INT *)namedata) = This->typelib->typelib_typeinfo_offsets[This->typeinfo->typekind >> 16];
+ if (*((INT*)namedata) == -1)
+ *((INT *)namedata) = This->typelib->typelib_typeinfo_offsets[This->typeinfo->typekind >> 16];
- if(iter->u.data[4]&0x1000)
- len = iter->u.data[5];
- else
- len = 0;
+ len = iter->u.data[0]/4 - iter->u.data[5]*3;
for (i = 1; i < cNames; i++) {
offset = ctl2_alloc_name(This->typelib, rgszNames[i]);
- iter->u.data[(i*3) + 4 + len] = offset;
+ iter->u.data[len + ((i-1)*3) + 1] = offset;
}
return S_OK;
*((INT *)namedata) = This->typelib->typelib_typeinfo_offsets[This->typeinfo->typekind >> 16];
namedata[9] |= 0x10;
}
- if ((This->typeinfo->typekind & 15) == TKIND_ENUM) {
+ if (This->typekind == TKIND_ENUM) {
namedata[9] |= 0x20;
}
- iter = This->typedata->next->next;
- for(i=0; i<index; i++)
- iter = iter->next;
+ for(iter = This->typedata->next->next, i = 0; /* empty */; iter = iter->next)
+ if (iter->type == CyclicListVar)
+ if (i++ >= index)
+ break;
iter->name = offset;
return S_OK;
int encoded_typedesc;
int width;
- if ((This->typeinfo->typekind & 15) != TKIND_ALIAS) {
+ if (This->typekind != TKIND_ALIAS) {
return TYPE_E_WRONGTYPEKIND;
}
UINT index,
DWORD dwHelpContext)
{
- FIXME("(%p,%d,%d), stub!\n", iface, index, dwHelpContext);
- return E_OUTOFMEMORY;
+ ICreateTypeInfo2Impl *This = (ICreateTypeInfo2Impl *)iface;
+ CyclicList *func;
+
+ TRACE("(%p,%d,%d)\n", iface, index, dwHelpContext);
+
+ if(This->typeinfo->cElement<index)
+ return TYPE_E_ELEMENTNOTFOUND;
+
+ if(This->typeinfo->cElement == index && This->typedata->type == CyclicListFunc)
+ func = This->typedata;
+ else
+ for(func=This->typedata->next->next; func!=This->typedata; func=func->next)
+ if (func->type == CyclicListFunc)
+ if(index-- == 0)
+ break;
+
+ This->typedata->next->u.val += funcrecord_reallochdr(&func->u.data, 7*sizeof(int));
+ if(!func->u.data)
+ return E_OUTOFMEMORY;
+
+ func->u.data[6] = dwHelpContext;
+ return S_OK;
}
/******************************************************************************
ICreateTypeInfo2* iface)
{
ICreateTypeInfo2Impl *This = (ICreateTypeInfo2Impl *)iface;
- CyclicList *iter, *iter2, **typedata;
+ CyclicList *iter, *iter2, *last = NULL, **typedata;
HREFTYPE hreftype;
HRESULT hres;
+ unsigned user_vft = 0;
int i;
TRACE("(%p)\n", iface);
- if((This->typeinfo->typekind&0xf) == TKIND_COCLASS)
+ /* FIXME: LayOut should be run on all ImplTypes */
+ if(This->typekind == TKIND_COCLASS)
return S_OK;
/* Validate inheritance */
return hres;
hres = ITypeInfo_GetRefTypeInfo(next, hreftype, &cur);
+ ITypeInfo_Release(next);
if(FAILED(hres))
return hres;
- ITypeInfo_Release(next);
while(1) {
hres = ITypeInfo_GetTypeAttr(cur, &typeattr);
- if(FAILED(hres))
+ if(FAILED(hres)) {
+ ITypeInfo_Release(cur);
return hres;
+ }
- if(!memcmp(&typeattr->guid, &IID_IDispatch, sizeof(IDispatch)))
+ if(IsEqualGUID(&typeattr->guid, &IID_IDispatch))
This->typeinfo->flags |= TYPEFLAG_FDISPATCHABLE;
This->typeinfo->datatype2 += (typeattr->cFuncs<<16) + 1;
hres = ITypeInfo_GetRefTypeOfImplType(cur, 0, &hreftype);
if(hres == TYPE_E_ELEMENTNOTFOUND)
break;
- if(FAILED(hres))
+ if(FAILED(hres)) {
+ ITypeInfo_Release(cur);
return hres;
+ }
hres = ITypeInfo_GetRefTypeInfo(cur, hreftype, &next);
- if(FAILED(hres))
+ if(FAILED(hres)) {
+ ITypeInfo_Release(cur);
return hres;
+ }
ITypeInfo_Release(cur);
cur = next;
}
+ ITypeInfo_Release(cur);
}
- This->typeinfo->cbSizeVft = (This->typeinfo->datatype2>>16) * 4;
+ /* Get cbSizeVft of inherited interface */
+ /* Makes LayOut running recursively */
+ if(This->typeinfo->datatype1 != -1) {
+ ITypeInfo *cur, *inherited;
+ TYPEATTR *typeattr;
+
+ hres = ICreateTypeInfo_QueryInterface(iface, &IID_ITypeInfo, (void**)&cur);
+ if(FAILED(hres))
+ return hres;
+
+ hres = ITypeInfo_GetRefTypeInfo(cur, This->typeinfo->datatype1, &inherited);
+ ITypeInfo_Release(cur);
+ if(FAILED(hres))
+ return hres;
+
+ hres = ITypeInfo_GetTypeAttr(inherited, &typeattr);
+ if(FAILED(hres)) {
+ ITypeInfo_Release(inherited);
+ return hres;
+ }
+
+ This->typeinfo->cbSizeVft = typeattr->cbSizeVft * 4 / sizeof(void *);
+
+ ITypeInfo_ReleaseTypeAttr(inherited, typeattr);
+ ITypeInfo_Release(inherited);
+ } else
+ This->typeinfo->cbSizeVft = 0;
+
if(!This->typedata)
return S_OK;
return E_OUTOFMEMORY;
/* Assign IDs and VTBL entries */
+ for(iter=This->typedata->next->next; iter!=This->typedata->next; iter=iter->next)
+ if (iter->type == CyclicListFunc)
+ last = iter;
+
+ if(last && last->u.data[3]&1)
+ user_vft = last->u.data[3]&0xffff;
+
i = 0;
for(iter=This->typedata->next->next; iter!=This->typedata->next; iter=iter->next) {
/* Assign MEMBERID if MEMBERID_NIL was specified */
for(iter2=This->typedata->next->next; iter2!=This->typedata->next; iter2=iter2->next) {
if(iter == iter2) continue;
- if(iter2->indice == iter->indice)
+ if(iter2->indice == iter->indice) {
+ HeapFree(GetProcessHeap(), 0, typedata);
return E_ACCESSDENIED;
+ }
}
break;
}
}
+ if (iter->type != CyclicListFunc)
+ continue;
+
typedata[i] = iter;
iter->u.data[0] = (iter->u.data[0]&0xffff) | (i<<16);
- if((This->typeinfo->typekind&0xf) != TKIND_MODULE) {
+ if((iter->u.data[3]&1) != (user_vft&1)) {
+ HeapFree(GetProcessHeap(), 0, typedata);
+ return TYPE_E_INVALIDID;
+ }
+
+ if(user_vft&1) {
+ if(user_vft < (iter->u.data[3]&0xffff))
+ user_vft = (iter->u.data[3]&0xffff);
+
+ if((iter->u.data[3]&0xffff) < This->typeinfo->cbSizeVft) {
+ HeapFree(GetProcessHeap(), 0, typedata);
+ return TYPE_E_INVALIDID;
+ }
+ } else if(This->typekind != TKIND_MODULE) {
iter->u.data[3] = (iter->u.data[3]&0xffff0000) | This->typeinfo->cbSizeVft;
This->typeinfo->cbSizeVft += 4;
}
i++;
}
+ if(user_vft)
+ This->typeinfo->cbSizeVft = user_vft+3;
+
for(i=0; i<(This->typeinfo->cElement&0xffff); i++) {
if(typedata[i]->u.data[4]>>16 > i) {
int inv;
REFGUID guid, /* [I] The GUID used as a key to retrieve the custom data. */
VARIANT* pVarVal) /* [I] The custom data. */
{
- FIXME("(%p,%s,%p), stub!\n", iface, debugstr_guid(guid), pVarVal);
- return E_OUTOFMEMORY;
+ ICreateTypeInfo2Impl *This = (ICreateTypeInfo2Impl *)iface;
+
+ TRACE("(%p,%s,%p)!\n", iface, debugstr_guid(guid), pVarVal);
+
+ if (!pVarVal)
+ return E_INVALIDARG;
+
+ return ctl2_set_custdata(This->typelib, guid, pVarVal, &This->typeinfo->oCustData);
}
/******************************************************************************
REFGUID guid, /* [I] The GUID used as a key to retrieve the custom data. */
VARIANT* pVarVal) /* [I] The custom data. */
{
- FIXME("(%p,%d,%s,%p), stub!\n", iface, index, debugstr_guid(guid), pVarVal);
- return E_OUTOFMEMORY;
+ ICreateTypeInfo2Impl *This = (ICreateTypeInfo2Impl *)iface;
+ CyclicList *iter;
+
+ TRACE("(%p,%d,%s,%p)\n", iface, index, debugstr_guid(guid), pVarVal);
+
+ if(index >= (This->typeinfo->cElement&0xFFFF))
+ return TYPE_E_ELEMENTNOTFOUND;
+
+ for(iter=This->typedata->next->next; /* empty */; iter=iter->next)
+ if (iter->type == CyclicListFunc)
+ if (index-- == 0)
+ break;
+
+ This->typedata->next->u.val += funcrecord_reallochdr(&iter->u.data, 13*sizeof(int));
+ if(!iter->u.data)
+ return E_OUTOFMEMORY;
+
+ iter->u.data[4] |= 0x80;
+ return ctl2_set_custdata(This->typelib, guid, pVarVal, &iter->u.data[12]);
}
/******************************************************************************
(*ppTypeAttr)->lcid = This->typelib->typelib_header.lcid;
(*ppTypeAttr)->cbSizeInstance = This->typeinfo->size;
- (*ppTypeAttr)->typekind = This->typeinfo->typekind&0xf;
+ (*ppTypeAttr)->typekind = This->typekind;
(*ppTypeAttr)->cFuncs = This->typeinfo->cElement&0xffff;
+ if(This->typeinfo->flags&TYPEFLAG_FDUAL && This->typekind==TKIND_DISPATCH)
+ (*ppTypeAttr)->cFuncs += 7;
(*ppTypeAttr)->cVars = This->typeinfo->cElement>>16;
(*ppTypeAttr)->cImplTypes = This->typeinfo->cImplTypes;
- (*ppTypeAttr)->cbSizeVft = This->typeinfo->cbSizeVft;
+ (*ppTypeAttr)->cbSizeVft = This->typekind==TKIND_DISPATCH ? 7 * sizeof(void*) : This->typeinfo->cbSizeVft;
(*ppTypeAttr)->cbAlignment = (This->typeinfo->typekind>>11) & 0x1f;
(*ppTypeAttr)->wTypeFlags = This->typeinfo->flags;
(*ppTypeAttr)->wMajorVerNum = This->typeinfo->version&0xffff;
if(!pRefType)
return E_INVALIDARG;
- if(index == -1) {
- FIXME("Dual interfaces not handled yet\n");
- return E_NOTIMPL;
+ if(This->typeinfo->flags&TYPEFLAG_FDUAL) {
+ if(index == -1) {
+ *pRefType = -2;
+ return S_OK;
+ }
+
+ if(This->typekind == TKIND_DISPATCH)
+ return ITypeInfo2_GetRefTypeOfImplType((ITypeInfo2*)&This->dual->lpVtblTypeInfo2,
+ index, pRefType);
}
- if(index >= This->typeinfo->cImplTypes)
+ if(index>=This->typeinfo->cImplTypes)
return TYPE_E_ELEMENTNOTFOUND;
- if((This->typeinfo->typekind&0xf) == TKIND_INTERFACE) {
+ if(This->typekind == TKIND_INTERFACE) {
*pRefType = This->typeinfo->datatype1 + 2;
return S_OK;
}
if(index >= This->typeinfo->cImplTypes)
return TYPE_E_ELEMENTNOTFOUND;
- if((This->typeinfo->typekind&0xf) != TKIND_COCLASS) {
+ if(This->typekind != TKIND_COCLASS) {
*pImplTypeFlags = 0;
return S_OK;
}
DWORD* pdwHelpContext,
BSTR* pBstrHelpFile)
{
- FIXME("(%p,%d,%p,%p,%p,%p), stub!\n", iface, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
- return E_OUTOFMEMORY;
+ ICreateTypeInfo2Impl *This = impl_from_ITypeInfo2(iface);
+ HRESULT status = TYPE_E_ELEMENTNOTFOUND;
+ INT nameoffset, docstringoffset, helpcontext;
+
+ TRACE("(%p,%d,%p,%p,%p,%p)\n", iface, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
+
+ if (memid == -1)
+ {
+ nameoffset = This->typeinfo->NameOffset;
+ docstringoffset = This->typeinfo->docstringoffs;
+ helpcontext = This->typeinfo->helpcontext;
+ status = S_OK;
+ } else {
+ CyclicList *iter;
+ if (This->typedata) {
+ for(iter=This->typedata->next->next; iter!=This->typedata->next; iter=iter->next) {
+ if (iter->indice == memid) {
+ if (iter->type == CyclicListFunc) {
+ const int *typedata = iter->u.data;
+ int size = typedata[0] - typedata[5]*(typedata[4]&0x1000?16:12);
+
+ nameoffset = iter->name;
+ /* FIXME implement this once SetFuncDocString is implemented */
+ docstringoffset = -1;
+ helpcontext = (size < 7*sizeof(int)) ? 0 : typedata[6];
+
+ status = S_OK;
+ } else {
+ FIXME("Not implemented for variable members\n");
+ }
+
+ break;
+ }
+ }
+ }
+ }
+
+ if (!status) {
+ WCHAR *string;
+ if (pBstrName) {
+ if (nameoffset == -1)
+ *pBstrName = NULL;
+ else {
+ MSFT_NameIntro *name = (MSFT_NameIntro*)&This->typelib->
+ typelib_segment_data[MSFT_SEG_NAME][nameoffset];
+ ctl2_decode_name((char*)&name->namelen, &string);
+ *pBstrName = SysAllocString(string);
+ if(!*pBstrName)
+ return E_OUTOFMEMORY;
+ }
+ }
+
+ if (pBstrDocString) {
+ if (docstringoffset == -1)
+ *pBstrDocString = NULL;
+ else {
+ MSFT_NameIntro *name = (MSFT_NameIntro*)&This->typelib->
+ typelib_segment_data[MSFT_SEG_NAME][docstringoffset];
+ ctl2_decode_name((char*)&name->namelen, &string);
+ *pBstrDocString = SysAllocString(string);
+ if(!*pBstrDocString) {
+ if (pBstrName) SysFreeString(*pBstrName);
+ return E_OUTOFMEMORY;
+ }
+ }
+ }
+
+ if (pdwHelpContext) {
+ *pdwHelpContext = helpcontext;
+ }
+
+ if (pBstrHelpFile) {
+ status = ITypeLib_GetDocumentation((ITypeLib*)&This->typelib->lpVtblTypeLib2,
+ -1, NULL, NULL, NULL, pBstrHelpFile);
+ if (status) {
+ if (pBstrName) SysFreeString(*pBstrName);
+ if (pBstrDocString) SysFreeString(*pBstrDocString);
+ }
+ }
+ }
+
+ return status;
}
/******************************************************************************
if(!ppTInfo)
return E_INVALIDARG;
+ if(hRefType==-2 && This->dual) {
+ *ppTInfo = (ITypeInfo*)&This->dual->lpVtblTypeInfo2;
+ ITypeInfo_AddRef(*ppTInfo);
+ return S_OK;
+ }
+
if(hRefType&1) {
ITypeLib *tl;
MSFT_ImpInfo *impinfo;
TRACE("(%p,%p,%p)\n", iface, ppTLib, pIndex);
*ppTLib = (ITypeLib *)&This->typelib->lpVtblTypeLib2;
- This->typelib->ref++;
+ ICreateTypeLib_AddRef((ICreateTypeLib*)This->typelib);
*pIndex = This->typeinfo->typekind >> 16;
return S_OK;
pCreateTypeInfo2Impl->ref = 1;
pCreateTypeInfo2Impl->typelib = typelib;
- typelib->ref++;
+ ICreateTypeLib_AddRef((ICreateTypeLib*)typelib);
nameoffset = ctl2_alloc_name(typelib, szName);
typeinfo_offset = ctl2_alloc_typeinfo(typelib, nameoffset);
pCreateTypeInfo2Impl->typeinfo = typeinfo;
+ pCreateTypeInfo2Impl->typekind = tkind;
typeinfo->typekind |= tkind | 0x20;
ICreateTypeInfo2_SetAlignment((ICreateTypeInfo2 *)pCreateTypeInfo2Impl, 4);
HeapFree(GetProcessHeap(), 0, rem);
}
}
- HeapFree(GetProcessHeap(), 0, typeinfo);
+
+ HeapFree(GetProcessHeap(), 0, typeinfo->dual);
+ HeapFree(GetProcessHeap(), 0, typeinfo);
}
HeapFree(GetProcessHeap(),0,This);
if(!iter)
return TYPE_E_ELEMENTNOTFOUND;
- return ITypeInfo_GetDocumentation((ITypeInfo*)iter->lpVtblTypeInfo2,
+ return ITypeInfo_GetDocumentation((ITypeInfo*)&iter->lpVtblTypeInfo2,
-1, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
}