Andrew Eikum : oleaut32: Resize 32-bit typeinfos when loaded in 64-bit.
Alexandre Julliard
julliard at winehq.org
Tue Aug 27 14:47:55 CDT 2013
Module: wine
Branch: master
Commit: 56aa7d015d559dc8dafed52c4456673a3974dac9
URL: http://source.winehq.org/git/wine.git/?a=commit;h=56aa7d015d559dc8dafed52c4456673a3974dac9
Author: Andrew Eikum <aeikum at codeweavers.com>
Date: Mon Aug 26 12:39:48 2013 -0500
oleaut32: Resize 32-bit typeinfos when loaded in 64-bit.
---
dlls/oleaut32/typelib.c | 172 ++++++++++++++++++++++++++++++++++++++++++++---
1 files changed, 163 insertions(+), 9 deletions(-)
diff --git a/dlls/oleaut32/typelib.c b/dlls/oleaut32/typelib.c
index 118e1f0..8985a02 100644
--- a/dlls/oleaut32/typelib.c
+++ b/dlls/oleaut32/typelib.c
@@ -1909,6 +1909,120 @@ static TLBString *TLB_append_str(struct list *string_list, BSTR new_str)
return str;
}
+static HRESULT TLB_get_size_from_hreftype(ITypeInfoImpl *info, HREFTYPE href,
+ ULONG *size, WORD *align)
+{
+ ITypeInfo *other;
+ TYPEATTR *attr;
+ HRESULT hr;
+
+ hr = ITypeInfo2_GetRefTypeInfo(&info->ITypeInfo2_iface, href, &other);
+ if(FAILED(hr))
+ return hr;
+
+ hr = ITypeInfo_GetTypeAttr(other, &attr);
+ if(FAILED(hr)){
+ ITypeInfo_Release(other);
+ return hr;
+ }
+
+ if(size)
+ *size = attr->cbSizeInstance;
+ if(align)
+ *align = attr->cbAlignment;
+
+ ITypeInfo_ReleaseTypeAttr(other, attr);
+ ITypeInfo_Release(other);
+
+ return S_OK;
+}
+
+static HRESULT TLB_size_instance(ITypeInfoImpl *info, SYSKIND sys,
+ TYPEDESC *tdesc, ULONG *size, WORD *align)
+{
+ ULONG i, sub, ptr_size;
+ HRESULT hr;
+
+ ptr_size = get_ptr_size(sys);
+
+ switch(tdesc->vt){
+ case VT_VOID:
+ *size = 0;
+ break;
+ case VT_I1:
+ case VT_UI1:
+ *size = 1;
+ break;
+ case VT_I2:
+ case VT_BOOL:
+ case VT_UI2:
+ *size = 2;
+ break;
+ case VT_I4:
+ case VT_R4:
+ case VT_ERROR:
+ case VT_UI4:
+ case VT_INT:
+ case VT_UINT:
+ case VT_HRESULT:
+ *size = 4;
+ break;
+ case VT_R8:
+ case VT_I8:
+ case VT_UI8:
+ *size = 8;
+ break;
+ case VT_BSTR:
+ case VT_DISPATCH:
+ case VT_UNKNOWN:
+ case VT_PTR:
+ case VT_SAFEARRAY:
+ case VT_LPSTR:
+ case VT_LPWSTR:
+ *size = ptr_size;
+ break;
+ case VT_DATE:
+ *size = sizeof(DATE);
+ break;
+ case VT_VARIANT:
+ *size = sizeof(VARIANT);
+#ifdef _WIN64
+ if(sys == SYS_WIN32)
+ *size -= 8; /* 32-bit VARIANT is 8 bytes smaller than 64-bit VARIANT */
+#endif
+ break;
+ case VT_DECIMAL:
+ *size = sizeof(DECIMAL);
+ break;
+ case VT_CY:
+ *size = sizeof(CY);
+ break;
+ case VT_CARRAY:
+ *size = 0;
+ for(i = 0; i < tdesc->u.lpadesc->cDims; ++i)
+ *size += tdesc->u.lpadesc->rgbounds[i].cElements;
+ hr = TLB_size_instance(info, sys, &tdesc->u.lpadesc->tdescElem, &sub, align);
+ if(FAILED(hr))
+ return hr;
+ *size *= sub;
+ return S_OK;
+ case VT_USERDEFINED:
+ return TLB_get_size_from_hreftype(info, tdesc->u.hreftype, size, align);
+ default:
+ FIXME("Unsized VT: 0x%x\n", tdesc->vt);
+ return E_FAIL;
+ }
+
+ if(align){
+ if(*size < 4)
+ *align = *size;
+ else
+ *align = 4;
+ }
+
+ return S_OK;
+}
+
/**********************************************************************
*
* Functions for reading MSFT typelibs (those created by CreateTypeLib2)
@@ -2512,6 +2626,47 @@ static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
++pImpl;
}
}
+
+#ifdef _WIN64
+/* when a 32-bit typelib is loaded in 64-bit mode, we need to resize pointers
+ * and some structures, and fix the alignment */
+static void TLB_fix_32on64_typeinfo(ITypeInfoImpl *info)
+{
+ if(info->typekind == TKIND_ALIAS){
+ switch(info->tdescAlias.vt){
+ case VT_BSTR:
+ case VT_DISPATCH:
+ case VT_UNKNOWN:
+ case VT_PTR:
+ case VT_SAFEARRAY:
+ case VT_LPSTR:
+ case VT_LPWSTR:
+ info->cbSizeInstance = sizeof(void*);
+ info->cbAlignment = sizeof(void*);
+ break;
+ case VT_CARRAY:
+ case VT_USERDEFINED:
+ TLB_size_instance(info, SYS_WIN64, &info->tdescAlias, &info->cbSizeInstance, &info->cbAlignment);
+ break;
+ case VT_VARIANT:
+ info->cbSizeInstance = sizeof(VARIANT);
+ info->cbAlignment = 8;
+ default:
+ if(info->cbSizeInstance < sizeof(void*))
+ info->cbAlignment = info->cbSizeInstance;
+ else
+ info->cbAlignment = sizeof(void*);
+ break;
+ }
+ }else if(info->typekind == TKIND_INTERFACE ||
+ info->typekind == TKIND_DISPATCH ||
+ info->typekind == TKIND_COCLASS){
+ info->cbSizeInstance = sizeof(void*);
+ info->cbAlignment = sizeof(void*);
+ }
+}
+#endif
+
/*
* process a typeinfo record
*/
@@ -2537,18 +2692,10 @@ static ITypeInfoImpl * MSFT_DoTypeInfo(
ptiRet->lcid=pLibInfo->set_lcid; /* FIXME: correct? */
ptiRet->lpstrSchema=NULL; /* reserved */
ptiRet->cbSizeInstance=tiBase.size;
-#ifdef _WIN64
- if(pLibInfo->syskind == SYS_WIN32)
- ptiRet->cbSizeInstance=sizeof(void*);
-#endif
ptiRet->typekind=tiBase.typekind & 0xF;
ptiRet->cFuncs=LOWORD(tiBase.cElement);
ptiRet->cVars=HIWORD(tiBase.cElement);
ptiRet->cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
-#ifdef _WIN64
- if(pLibInfo->syskind == SYS_WIN32)
- ptiRet->cbAlignment = 8;
-#endif
ptiRet->wTypeFlags=tiBase.flags;
ptiRet->wMajorVerNum=LOWORD(tiBase.version);
ptiRet->wMinorVerNum=HIWORD(tiBase.version);
@@ -3318,6 +3465,7 @@ static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
MSFT_Header tlbHeader;
MSFT_SegDir tlbSegDir;
ITypeLibImpl * pTypeLibImpl;
+ int i;
TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
@@ -3503,7 +3651,6 @@ static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
if(tlbHeader.nrtypeinfos >= 0 )
{
ITypeInfoImpl **ppTI;
- int i;
ppTI = pTypeLibImpl->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*) * tlbHeader.nrtypeinfos);
@@ -3516,6 +3663,13 @@ static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
}
}
+#ifdef _WIN64
+ if(pTypeLibImpl->syskind == SYS_WIN32){
+ for(i = 0; i < pTypeLibImpl->TypeInfoCount; ++i)
+ TLB_fix_32on64_typeinfo(pTypeLibImpl->typeinfos[i]);
+ }
+#endif
+
TRACE("(%p)\n", pTypeLibImpl);
return &pTypeLibImpl->ITypeLib2_iface;
}
More information about the wine-cvs
mailing list