From ba29140448094fa89394d44881369a4c65ed6dfb Mon Sep 17 00:00:00 2001 From: The Wine Synchronizer Date: Fri, 27 Jul 2007 09:59:17 +0000 Subject: [PATCH] Autosyncing with Wine HEAD svn path=/trunk/; revision=27914 --- reactos/dll/win32/oleaut32/dispatch.c | 2 - reactos/dll/win32/oleaut32/oleaut.c | 6 +- reactos/dll/win32/oleaut32/oleaut32_En.rc | 2 +- reactos/dll/win32/oleaut32/oleaut32_Ko.rc | 2 +- reactos/dll/win32/oleaut32/oleaut32_No.rc | 2 +- reactos/dll/win32/oleaut32/oleaut32_Pt.rc | 2 +- reactos/dll/win32/oleaut32/oleaut32_Sv.rc | 2 +- reactos/dll/win32/oleaut32/oleaut32_ros.diff | 14 +- reactos/dll/win32/oleaut32/olefont.c | 4 +- reactos/dll/win32/oleaut32/olepicture.c | 265 ++++++++- reactos/dll/win32/oleaut32/safearray.c | 2 +- reactos/dll/win32/oleaut32/tmarshal.c | 386 +++++++------ reactos/dll/win32/oleaut32/typelib.c | 542 +++++++++++++------ reactos/dll/win32/oleaut32/typelib16.c | 1 - reactos/dll/win32/oleaut32/typelib2.c | 1 - reactos/dll/win32/oleaut32/usrmarshal.c | 62 ++- reactos/dll/win32/oleaut32/variant.c | 94 +++- reactos/dll/win32/oleaut32/vartype.c | 3 +- 18 files changed, 1024 insertions(+), 368 deletions(-) diff --git a/reactos/dll/win32/oleaut32/dispatch.c b/reactos/dll/win32/oleaut32/dispatch.c index 707428f73c5..8ab1c5e73f5 100644 --- a/reactos/dll/win32/oleaut32/dispatch.c +++ b/reactos/dll/win32/oleaut32/dispatch.c @@ -34,8 +34,6 @@ #include "objbase.h" #include "oleauto.h" #include "winerror.h" -#include "winreg.h" -#include "winnls.h" /* for PRIMARYLANGID */ #include "wine/debug.h" diff --git a/reactos/dll/win32/oleaut32/oleaut.c b/reactos/dll/win32/oleaut32/oleaut.c index 1fe68b8d635..202db67e1db 100644 --- a/reactos/dll/win32/oleaut32/oleaut.c +++ b/reactos/dll/win32/oleaut32/oleaut.c @@ -266,7 +266,7 @@ BSTR WINAPI SysAllocStringLen(const OLECHAR *str, unsigned int len) * string. */ stringBuffer = (WCHAR*)newBuffer; - stringBuffer[len] = L'\0'; + stringBuffer[len] = '\0'; return (LPWSTR)stringBuffer; } @@ -691,8 +691,8 @@ HRESULT WINAPI OleTranslateColor( extern HRESULT OLEAUTPS_DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv); -extern void _get_STDFONT_CF(LPVOID); -extern void _get_STDPIC_CF(LPVOID); +extern void _get_STDFONT_CF(LPVOID *); +extern void _get_STDPIC_CF(LPVOID *); static HRESULT WINAPI PSDispatchFacBuf_QueryInterface(IPSFactoryBuffer *iface, REFIID riid, void **ppv) { diff --git a/reactos/dll/win32/oleaut32/oleaut32_En.rc b/reactos/dll/win32/oleaut32/oleaut32_En.rc index 6a338ce590c..e56eb11d6e3 100644 --- a/reactos/dll/win32/oleaut32/oleaut32_En.rc +++ b/reactos/dll/win32/oleaut32/oleaut32_En.rc @@ -18,7 +18,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT STRINGTABLE DISCARDABLE { diff --git a/reactos/dll/win32/oleaut32/oleaut32_Ko.rc b/reactos/dll/win32/oleaut32/oleaut32_Ko.rc index 0134c7a54b9..b3b5296df7f 100644 --- a/reactos/dll/win32/oleaut32/oleaut32_Ko.rc +++ b/reactos/dll/win32/oleaut32/oleaut32_Ko.rc @@ -18,7 +18,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -LANGUAGE LANG_KOREAN, SUBLANG_DEFAULT +LANGUAGE LANG_KOREAN, SUBLANG_NEUTRAL STRINGTABLE DISCARDABLE { diff --git a/reactos/dll/win32/oleaut32/oleaut32_No.rc b/reactos/dll/win32/oleaut32/oleaut32_No.rc index 4b5ac6771fb..7ca883c350d 100644 --- a/reactos/dll/win32/oleaut32/oleaut32_No.rc +++ b/reactos/dll/win32/oleaut32/oleaut32_No.rc @@ -18,7 +18,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -LANGUAGE LANG_NORWEGIAN, SUBLANG_NEUTRAL +LANGUAGE LANG_NORWEGIAN, SUBLANG_NORWEGIAN_BOKMAL STRINGTABLE DISCARDABLE { diff --git a/reactos/dll/win32/oleaut32/oleaut32_Pt.rc b/reactos/dll/win32/oleaut32/oleaut32_Pt.rc index 1cbd389209a..9a4953b25b9 100644 --- a/reactos/dll/win32/oleaut32/oleaut32_Pt.rc +++ b/reactos/dll/win32/oleaut32/oleaut32_Pt.rc @@ -18,7 +18,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -LANGUAGE LANG_PORTUGUESE, SUBLANG_NEUTRAL +LANGUAGE LANG_PORTUGUESE, SUBLANG_PORTUGUESE_BRAZILIAN STRINGTABLE DISCARDABLE { diff --git a/reactos/dll/win32/oleaut32/oleaut32_Sv.rc b/reactos/dll/win32/oleaut32/oleaut32_Sv.rc index d39d014ccfb..f8e2fc43d20 100644 --- a/reactos/dll/win32/oleaut32/oleaut32_Sv.rc +++ b/reactos/dll/win32/oleaut32/oleaut32_Sv.rc @@ -18,7 +18,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -LANGUAGE LANG_SWEDISH, SUBLANG_NEUTRAL +LANGUAGE LANG_SWEDISH, SUBLANG_DEFAULT STRINGTABLE DISCARDABLE { diff --git a/reactos/dll/win32/oleaut32/oleaut32_ros.diff b/reactos/dll/win32/oleaut32/oleaut32_ros.diff index b89f365b46a..e4edd3b346a 100644 --- a/reactos/dll/win32/oleaut32/oleaut32_ros.diff +++ b/reactos/dll/win32/oleaut32/oleaut32_ros.diff @@ -39,7 +39,7 @@ Index: oleaut32_Ja.rc --- oleaut32_Ja.rc (revision 23782) +++ oleaut32_Ja.rc (working copy) @@ -0,0 +1,11 @@ -+LANGUAGE LANG_JAPANESE, SUBLANG_NEUTRAL ++LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT + +STRINGTABLE DISCARDABLE +{ @@ -109,3 +109,15 @@ Index: oleaut32.rc /* * FIXME: +Index: oleaut32.rbuild +=================================================================== +--- oleaut32.rbuild (revision 23782) ++++ oleaut32.rbuild (working copy) +@@ -20,6 +20,7 @@ + comctl32 + urlmon + uuid ++ pseh + connpt.c + dispatch.c + hash.c diff --git a/reactos/dll/win32/oleaut32/olefont.c b/reactos/dll/win32/oleaut32/olefont.c index 5aba82e68fc..3376c0cbc4b 100644 --- a/reactos/dll/win32/oleaut32/olefont.c +++ b/reactos/dll/win32/oleaut32/olefont.c @@ -176,7 +176,7 @@ static inline OLEFontImpl *impl_from_IPersistStreamInit( IPersistStreamInit *ifa * Prototypes for the implementation functions for the IFont * interface */ -static OLEFontImpl* OLEFontImpl_Construct(LPFONTDESC fontDesc); +static OLEFontImpl* OLEFontImpl_Construct(const FONTDESC *fontDesc); static void OLEFontImpl_Destroy(OLEFontImpl* fontDesc); static ULONG WINAPI OLEFontImpl_AddRef(IFont* iface); @@ -2201,7 +2201,7 @@ static const IPersistStreamInitVtbl OLEFontImpl_IPersistStreamInit_VTable = * The caller of this method must release the object when it's * done with it. */ -static OLEFontImpl* OLEFontImpl_Construct(LPFONTDESC fontDesc) +static OLEFontImpl* OLEFontImpl_Construct(const FONTDESC *fontDesc) { OLEFontImpl* newObject = 0; diff --git a/reactos/dll/win32/oleaut32/olepicture.c b/reactos/dll/win32/oleaut32/olepicture.c index 6485c7d1007..01e766dd2b1 100644 --- a/reactos/dll/win32/oleaut32/olepicture.c +++ b/reactos/dll/win32/oleaut32/olepicture.c @@ -67,7 +67,7 @@ #include "wine/wingdi16.h" -#ifdef HAVE_JPEGLIB_H +#ifdef SONAME_LIBJPEG /* This is a hack, so jpeglib.h does not redefine INT32 and the like*/ #define XMD_H #define UINT8 JPEG_UINT8 @@ -77,9 +77,11 @@ # include #undef jpeg_boolean #undef UINT16 -#ifndef SONAME_LIBJPEG -#define SONAME_LIBJPEG "libjpeg.so" #endif + +#ifdef HAVE_PNG_H +#undef FAR +#include #endif #include "ungif.h" @@ -365,6 +367,7 @@ static void OLEPictureImpl_Destroy(OLEPictureImpl* Obj) DeleteEnhMetaFile(Obj->desc.u.emf.hemf); break; case PICTYPE_NONE: + case PICTYPE_UNINITIALIZED: /* Nothing to do */ break; default: @@ -505,6 +508,7 @@ static HRESULT WINAPI OLEPictureImpl_get_Handle(IPicture *iface, TRACE("(%p)->(%p)\n", This, phandle); switch(This->desc.picType) { case PICTYPE_NONE: + case PICTYPE_UNINITIALIZED: *phandle = 0; break; case PICTYPE_BITMAP: @@ -674,7 +678,16 @@ static HRESULT WINAPI OLEPictureImpl_Render(IPicture *iface, HDC hdc, break; case PICTYPE_METAFILE: + PlayMetaFile(hdc, This->desc.u.wmf.hmeta); + break; + case PICTYPE_ENHMETAFILE: + { + RECT rc = { x, y, cx, cy }; + PlayEnhMetaFile(hdc, This->desc.u.emf.hemf, &rc); + break; + } + default: FIXME("type %d not implemented\n", This->desc.picType); return E_NOTIMPL; @@ -795,6 +808,7 @@ static HRESULT WINAPI OLEPictureImpl_get_Attributes(IPicture *iface, switch (This->desc.picType) { case PICTYPE_BITMAP: if (This->hbmMask) *pdwAttr = PICTURE_TRANSPARENT; break; /* not 'truly' scalable, see MSDN. */ case PICTYPE_ICON: *pdwAttr = PICTURE_TRANSPARENT;break; + case PICTYPE_ENHMETAFILE: /* fall through */ case PICTYPE_METAFILE: *pdwAttr = PICTURE_TRANSPARENT|PICTURE_SCALABLE;break; default:FIXME("Unknown pictype %d\n",This->desc.picType);break; } @@ -925,7 +939,7 @@ static HRESULT WINAPI OLEPictureImpl_IsDirty( return E_NOTIMPL; } -#ifdef HAVE_JPEGLIB_H +#ifdef SONAME_LIBJPEG static void *libjpeg_handle; #define MAKE_FUNCPTR(f) static typeof(f) * p##f @@ -979,7 +993,7 @@ static boolean _jpeg_resync_to_restart(j_decompress_ptr cinfo, int desired) { return FALSE; } static void _jpeg_term_source(j_decompress_ptr cinfo) { } -#endif /* HAVE_JPEGLIB_H */ +#endif /* SONAME_LIBJPEG */ struct gifdata { unsigned char *data; @@ -1198,7 +1212,7 @@ static HRESULT OLEPictureImpl_LoadGif(OLEPictureImpl *This, BYTE *xbuf, ULONG xr static HRESULT OLEPictureImpl_LoadJpeg(OLEPictureImpl *This, BYTE *xbuf, ULONG xread) { -#ifdef HAVE_JPEGLIB_H +#ifdef SONAME_LIBJPEG struct jpeg_decompress_struct jd; struct jpeg_error_mgr jerr; int ret; @@ -1325,6 +1339,193 @@ static HRESULT OLEPictureImpl_LoadDIB(OLEPictureImpl *This, BYTE *xbuf, ULONG xr return S_OK; } +/***************************************************** +* start of PNG-specific code +* currently only supports colortype PNG_COLOR_TYPE_RGB +*/ +#ifdef SONAME_LIBPNG +typedef struct{ + ULONG position; + ULONG size; + BYTE * buff; +} png_io; + +static void png_stream_read_data(png_structp png_ptr, png_bytep data, + png_size_t length) +{ + png_io * io_ptr = png_ptr->io_ptr; + + if(length + io_ptr->position > io_ptr->size){ + length = io_ptr->size - io_ptr->position; + } + + memcpy(data, io_ptr->buff + io_ptr->position, length); + + io_ptr->position += length; +} + +static void *libpng_handle; +#define MAKE_FUNCPTR(f) static typeof(f) * p##f +MAKE_FUNCPTR(png_create_read_struct); +MAKE_FUNCPTR(png_create_info_struct); +MAKE_FUNCPTR(png_set_read_fn); +MAKE_FUNCPTR(png_read_info); +MAKE_FUNCPTR(png_read_image); +MAKE_FUNCPTR(png_get_rowbytes); +MAKE_FUNCPTR(png_set_bgr); +MAKE_FUNCPTR(png_destroy_read_struct); +MAKE_FUNCPTR(png_set_palette_to_rgb); +MAKE_FUNCPTR(png_read_update_info); +#undef MAKE_FUNCPTR + +static void *load_libpng(void) +{ + if((libpng_handle = wine_dlopen(SONAME_LIBPNG, RTLD_NOW, NULL, 0)) != NULL) { + +#define LOAD_FUNCPTR(f) \ + if((p##f = wine_dlsym(libpng_handle, #f, NULL, 0)) == NULL) { \ + libpng_handle = NULL; \ + return NULL; \ + } + LOAD_FUNCPTR(png_create_read_struct); + LOAD_FUNCPTR(png_create_info_struct); + LOAD_FUNCPTR(png_set_read_fn); + LOAD_FUNCPTR(png_read_info); + LOAD_FUNCPTR(png_read_image); + LOAD_FUNCPTR(png_get_rowbytes); + LOAD_FUNCPTR(png_set_bgr); + LOAD_FUNCPTR(png_destroy_read_struct); + LOAD_FUNCPTR(png_set_palette_to_rgb); + LOAD_FUNCPTR(png_read_update_info); + +#undef LOAD_FUNCPTR + } + return libpng_handle; +} +#endif /* SONAME_LIBPNG */ + +static HRESULT OLEPictureImpl_LoadPNG(OLEPictureImpl *This, BYTE *xbuf, ULONG xread) +{ +#ifdef SONAME_LIBPNG + png_io io; + png_structp png_ptr = NULL; + png_infop info_ptr = NULL; + INT row, rowsize, height, width; + png_bytep* row_pointers = NULL; + png_bytep pngdata = NULL; + BITMAPINFOHEADER bmi; + HDC hdcref = NULL; + HRESULT ret; + BOOL set_bgr = FALSE; + + if(!libpng_handle) { + if(!load_libpng()) { + ERR("Failed reading PNG because unable to find %s\n",SONAME_LIBPNG); + return E_FAIL; + } + } + + io.size = xread; + io.position = 0; + io.buff = xbuf; + + png_ptr = ppng_create_read_struct(PNG_LIBPNG_VER_STRING, + NULL, NULL, NULL); + + if(setjmp(png_jmpbuf(png_ptr))){ + TRACE("Error in libpng\n"); + ret = E_FAIL; + goto pngend; + } + + info_ptr = ppng_create_info_struct(png_ptr); + ppng_set_read_fn(png_ptr, &io, png_stream_read_data); + ppng_read_info(png_ptr, info_ptr); + + if(!(png_ptr->color_type == PNG_COLOR_TYPE_RGB || + png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)){ + FIXME("Unsupported .PNG type: %d\n", png_ptr->color_type); + ret = E_FAIL; + goto pngend; + } + + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE){ + ppng_set_palette_to_rgb(png_ptr); + set_bgr = TRUE; + } + + if (png_ptr->color_type == PNG_COLOR_TYPE_RGB || + png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA || + set_bgr){ + ppng_set_bgr(png_ptr); + } + + ppng_read_update_info(png_ptr, info_ptr); + + rowsize = ppng_get_rowbytes(png_ptr, info_ptr); + /* align rowsize to 4-byte boundary */ + rowsize = (rowsize + 3) & ~3; + height = info_ptr->height; + width = info_ptr->width; + + pngdata = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, height * rowsize); + row_pointers = HeapAlloc(GetProcessHeap(), 0, height * (sizeof(VOID *))); + + if(!pngdata || !row_pointers){ + ret = E_FAIL; + goto pngend; + } + + for (row = 0; row < height; row++){ + row_pointers[row] = pngdata + row * rowsize; + } + + ppng_read_image(png_ptr, row_pointers); + + bmi.biSize = sizeof(bmi); + bmi.biWidth = width; + bmi.biHeight = -height; + bmi.biPlanes = 1; + bmi.biBitCount = info_ptr->channels * 8; + bmi.biCompression = BI_RGB; + bmi.biSizeImage = height * rowsize; + bmi.biXPelsPerMeter = 0; + bmi.biYPelsPerMeter = 0; + bmi.biClrUsed = 0; + bmi.biClrImportant = 0; + + hdcref = GetDC(0); + This->desc.u.bmp.hbitmap = CreateDIBitmap( + hdcref, + &bmi, + CBM_INIT, + pngdata, + (BITMAPINFO*)&bmi, + DIB_RGB_COLORS + ); + ReleaseDC(0, hdcref); + This->desc.picType = PICTYPE_BITMAP; + OLEPictureImpl_SetBitmap(This); + ret = S_OK; + +pngend: + if(png_ptr) + ppng_destroy_read_struct(&png_ptr, + (info_ptr ? &info_ptr : (png_infopp) NULL), + (png_infopp)NULL); + HeapFree(GetProcessHeap(), 0, row_pointers); + HeapFree(GetProcessHeap(), 0, pngdata); + return ret; +#else /* SONAME_LIBPNG */ + ERR("Trying to load PNG picture, but PNG supported not compiled in.\n"); + return E_FAIL; +#endif +} + +/***************************************************** +* start of Icon-specific code +*/ + static HRESULT OLEPictureImpl_LoadIcon(OLEPictureImpl *This, BYTE *xbuf, ULONG xread) { HICON hicon; @@ -1385,6 +1586,43 @@ static HRESULT OLEPictureImpl_LoadIcon(OLEPictureImpl *This, BYTE *xbuf, ULONG x } } +static HRESULT OLEPictureImpl_LoadMetafile(OLEPictureImpl *This, + const BYTE *data, ULONG size) +{ + HMETAFILE hmf; + HENHMETAFILE hemf; + + /* SetMetaFileBitsEx performs data check on its own */ + hmf = SetMetaFileBitsEx(size, data); + if (hmf) + { + This->desc.picType = PICTYPE_METAFILE; + This->desc.u.wmf.hmeta = hmf; + This->desc.u.wmf.xExt = 0; + This->desc.u.wmf.yExt = 0; + + This->origWidth = 0; + This->origHeight = 0; + This->himetricWidth = 0; + This->himetricHeight = 0; + + return S_OK; + } + + hemf = SetEnhMetaFileBits(size, data); + if (!hemf) return E_FAIL; + + This->desc.picType = PICTYPE_ENHMETAFILE; + This->desc.u.emf.hemf = hemf; + + This->origWidth = 0; + This->origHeight = 0; + This->himetricWidth = 0; + This->himetricHeight = 0; + + return S_OK; +} + /************************************************************************ * OLEPictureImpl_IPersistStream_Load (IUnknown) * @@ -1393,7 +1631,7 @@ static HRESULT OLEPictureImpl_LoadIcon(OLEPictureImpl *This, BYTE *xbuf, ULONG x * DWORD magic; * DWORD len; * - * Currently implemented: BITMAP, ICON, JPEG, GIF + * Currently implemented: BITMAP, ICON, JPEG, GIF, WMF, EMF */ static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) { HRESULT hr = E_FAIL; @@ -1527,6 +1765,8 @@ static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) { */ magic = xbuf[0] + (xbuf[1]<<8); + This->loadtime_format = magic; + switch (magic) { case 0x4947: /* GIF */ hr = OLEPictureImpl_LoadGif(This, xbuf, xread); @@ -1537,6 +1777,9 @@ static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) { case 0x4d42: /* Bitmap */ hr = OLEPictureImpl_LoadDIB(This, xbuf, xread); break; + case 0x5089: /* PNG */ + hr = OLEPictureImpl_LoadPNG(This, xbuf, xread); + break; case 0x0000: { /* ICON , first word is dwReserved */ hr = OLEPictureImpl_LoadIcon(This, xbuf, xread); break; @@ -1544,6 +1787,11 @@ static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) { default: { unsigned int i; + + /* let's see if it's a metafile */ + hr = OLEPictureImpl_LoadMetafile(This, xbuf, xread); + if (hr == S_OK) break; + FIXME("Unknown magic %04x, %d read bytes:\n",magic,xread); hr=E_FAIL; for (i=0;icImplTypes;j++) { + + if(attr->typekind == TKIND_DISPATCH && (attr->wTypeFlags & TYPEFLAG_FDUAL)) + { HREFTYPE href; - hres = ITypeInfo_GetRefTypeOfImplType(tinfo, j, &href); - if (hres) { - ERR("Did not find a reftype for interface offset %d?\n",j); - break; + hres = ITypeInfo_GetRefTypeOfImplType(tinfo, -1, &href); + if(FAILED(hres)) + { + ERR("Unable to get interface href from dual dispinterface\n"); + goto end; } hres = ITypeInfo_GetRefTypeInfo(tinfo, href, &tinfo2); - if (hres) { - ERR("Did not find a typeinfo for reftype %d?\n",href); - continue; + if(FAILED(hres)) + { + ERR("Unable to get interface from dual dispinterface\n"); + goto end; } - n += _nroffuncs(tinfo2); + hres = num_of_funcs(tinfo2, num); ITypeInfo_Release(tinfo2); } - ITypeInfo_ReleaseTypeAttr(tinfo, attr); - i = 0; - while (1) { - hres = ITypeInfoImpl_GetInternalFuncDesc(tinfo,i,&fdesc); - if (hres) - return n; - n++; - i++; + else + { + *num = attr->cbSizeVft / 4; } - /*NOTREACHED*/ + + end: + ITypeInfo_ReleaseTypeAttr(tinfo, attr); + return hres; } #ifdef __i386__ @@ -526,7 +523,7 @@ _argsize(DWORD vt) { } static int -_xsize(TYPEDESC *td) { +_xsize(const TYPEDESC *td) { switch (td->vt) { case VT_DATE: return sizeof(DATE); @@ -534,7 +531,7 @@ _xsize(TYPEDESC *td) { return sizeof(VARIANT)+3; case VT_CARRAY: { int i, arrsize = 1; - ARRAYDESC *adesc = td->u.lpadesc; + const ARRAYDESC *adesc = td->u.lpadesc; for (i=0;icDims;i++) arrsize *= adesc->rgbounds[i].cElements; @@ -1198,63 +1195,99 @@ deserialize_param( } } -/* Searches function, also in inherited interfaces */ -static HRESULT -_get_funcdesc( - ITypeInfo *tinfo, int iMethod, ITypeInfo **tactual, const FUNCDESC **fdesc, BSTR *iname, BSTR *fname) +/* Retrieves a function's funcdesc, searching back into inherited interfaces. */ +static HRESULT get_funcdesc(ITypeInfo *tinfo, int iMethod, ITypeInfo **tactual, const FUNCDESC **fdesc, + BSTR *iname, BSTR *fname, UINT *num) { - int i = 0, j = 0; - HRESULT hres; + HRESULT hr; + UINT i, impl_types; + UINT inherited_funcs = 0; + TYPEATTR *attr; if (fname) *fname = NULL; if (iname) *iname = NULL; + if (num) *num = 0; + *tactual = NULL; - while (1) { - hres = ITypeInfoImpl_GetInternalFuncDesc(tinfo, i, fdesc); - - if (hres) { - ITypeInfo *tinfo2; - HREFTYPE href; - TYPEATTR *attr; - - hres = ITypeInfo_GetTypeAttr(tinfo, &attr); - if (hres) { - ERR("GetTypeAttr failed with %x\n",hres); - return hres; - } - /* Not found, so look in inherited ifaces. */ - for (j=0;jcImplTypes;j++) { - hres = ITypeInfo_GetRefTypeOfImplType(tinfo, j, &href); - if (hres) { - ERR("Did not find a reftype for interface offset %d?\n",j); - break; - } - hres = ITypeInfo_GetRefTypeInfo(tinfo, href, &tinfo2); - if (hres) { - ERR("Did not find a typeinfo for reftype %d?\n",href); - continue; - } - hres = _get_funcdesc(tinfo2,iMethod,tactual,fdesc,iname,fname); - ITypeInfo_Release(tinfo2); - if (!hres) { - ITypeInfo_ReleaseTypeAttr(tinfo, attr); - return S_OK; - } - } - ITypeInfo_ReleaseTypeAttr(tinfo, attr); - return hres; - } - if (((*fdesc)->oVft/4) == iMethod) { - if (fname) - ITypeInfo_GetDocumentation(tinfo,(*fdesc)->memid,fname,NULL,NULL,NULL); - if (iname) - ITypeInfo_GetDocumentation(tinfo,-1,iname,NULL,NULL,NULL); - *tactual = tinfo; - ITypeInfo_AddRef(*tactual); - return S_OK; - } - i++; + hr = ITypeInfo_GetTypeAttr(tinfo, &attr); + if (FAILED(hr)) + { + ERR("GetTypeAttr failed with %x\n",hr); + return hr; } + + if(attr->typekind == TKIND_DISPATCH) + { + if(attr->wTypeFlags & TYPEFLAG_FDUAL) + { + HREFTYPE href; + ITypeInfo *tinfo2; + + hr = ITypeInfo_GetRefTypeOfImplType(tinfo, -1, &href); + if(FAILED(hr)) + { + ERR("Cannot get interface href from dual dispinterface\n"); + ITypeInfo_ReleaseTypeAttr(tinfo, attr); + return hr; + } + hr = ITypeInfo_GetRefTypeInfo(tinfo, href, &tinfo2); + if(FAILED(hr)) + { + ERR("Cannot get interface from dual dispinterface\n"); + ITypeInfo_ReleaseTypeAttr(tinfo, attr); + return hr; + } + hr = get_funcdesc(tinfo2, iMethod, tactual, fdesc, iname, fname, num); + ITypeInfo_Release(tinfo2); + ITypeInfo_ReleaseTypeAttr(tinfo, attr); + return hr; + } + ERR("Shouldn't be called with a non-dual dispinterface\n"); + return E_FAIL; + } + + impl_types = attr->cImplTypes; + ITypeInfo_ReleaseTypeAttr(tinfo, attr); + + for (i = 0; i < impl_types; i++) + { + HREFTYPE href; + ITypeInfo *pSubTypeInfo; + UINT sub_funcs; + + hr = ITypeInfo_GetRefTypeOfImplType(tinfo, i, &href); + if (FAILED(hr)) return hr; + hr = ITypeInfo_GetRefTypeInfo(tinfo, href, &pSubTypeInfo); + if (FAILED(hr)) return hr; + + hr = get_funcdesc(pSubTypeInfo, iMethod, tactual, fdesc, iname, fname, &sub_funcs); + inherited_funcs += sub_funcs; + ITypeInfo_Release(pSubTypeInfo); + if(SUCCEEDED(hr)) return hr; + } + if(iMethod < inherited_funcs) + { + ERR("shouldn't be here\n"); + return E_INVALIDARG; + } + + for(i = inherited_funcs; i <= iMethod; i++) + { + hr = ITypeInfoImpl_GetInternalFuncDesc(tinfo, i - inherited_funcs, fdesc); + if(FAILED(hr)) + { + if(num) *num = i; + return hr; + } + } + + /* found it. We don't care about num so zero it */ + if(num) *num = 0; + *tactual = tinfo; + ITypeInfo_AddRef(*tactual); + if (fname) ITypeInfo_GetDocumentation(tinfo,(*fdesc)->memid,fname,NULL,NULL,NULL); + if (iname) ITypeInfo_GetDocumentation(tinfo,-1,iname,NULL,NULL,NULL); + return S_OK; } static inline BOOL is_in_elem(const ELEMDESC *elem) @@ -1286,10 +1319,9 @@ xCall(LPVOID retptr, int method, TMProxyImpl *tpinfo /*, args */) EnterCriticalSection(&tpinfo->crit); - hres = _get_funcdesc(tpinfo->tinfo,method,&tinfo,&fdesc,&iname,&fname); + hres = get_funcdesc(tpinfo->tinfo,method,&tinfo,&fdesc,&iname,&fname,NULL); if (hres) { ERR("Did not find typeinfo/funcdesc entry for method %d!\n",method); - ITypeInfo_Release(tinfo); LeaveCriticalSection(&tpinfo->crit); return E_FAIL; } @@ -1639,6 +1671,58 @@ static inline HRESULT get_facbuf_for_iid(REFIID riid, IPSFactoryBuffer **facbuf) &IID_IPSFactoryBuffer, (LPVOID*)facbuf); } +static HRESULT init_proxy_entry_point(TMProxyImpl *proxy, unsigned int num) +{ + int j; + /* nrofargs without This */ + int nrofargs; + ITypeInfo *tinfo2; + TMAsmProxy *xasm = proxy->asmstubs + num; + HRESULT hres; + const FUNCDESC *fdesc; + + hres = get_funcdesc(proxy->tinfo, num, &tinfo2, &fdesc, NULL, NULL, NULL); + if (hres) { + ERR("GetFuncDesc %x should not fail here.\n",hres); + return hres; + } + ITypeInfo_Release(tinfo2); + /* some args take more than 4 byte on the stack */ + nrofargs = 0; + for (j=0;jcParams;j++) + nrofargs += _argsize(fdesc->lprgelemdescParam[j].tdesc.vt); + +#ifdef __i386__ + if (fdesc->callconv != CC_STDCALL) { + ERR("calling convention is not stdcall????\n"); + return E_FAIL; + } +/* popl %eax - return ptr + * pushl + * pushl %eax + * call xCall + * lret (+4) + * + * + * arg3 arg2 arg1 + */ + xasm->popleax = 0x58; + xasm->pushlval = 0x6a; + xasm->nr = num; + xasm->pushleax = 0x50; + xasm->lcall = 0xe8; /* relative jump */ + xasm->xcall = (DWORD)xCall; + xasm->xcall -= (DWORD)&(xasm->lret); + xasm->lret = 0xc2; + xasm->bytestopop = (nrofargs+2)*4; /* pop args, This, iMethod */ + proxy->lpvtbl[num] = xasm; +#else + FIXME("not implemented on non i386\n"); + return E_FAIL; +#endif + return S_OK; +} + static HRESULT WINAPI PSFacBuf_CreateProxy( LPPSFACTORYBUFFER iface, IUnknown* pUnkOuter, REFIID riid, @@ -1646,10 +1730,10 @@ PSFacBuf_CreateProxy( { HRESULT hres; ITypeInfo *tinfo; - int i, nroffuncs; - const FUNCDESC *fdesc; + unsigned int i, nroffuncs; TMProxyImpl *proxy; TYPEATTR *typeattr; + BOOL defer_to_dispatch = FALSE; TRACE("(...%s...)\n",debugstr_guid(riid)); hres = _get_typeinfo_for_iid(riid,&tinfo); @@ -1657,7 +1741,14 @@ PSFacBuf_CreateProxy( ERR("No typeinfo for %s?\n",debugstr_guid(riid)); return hres; } - nroffuncs = _nroffuncs(tinfo); + + hres = num_of_funcs(tinfo, &nroffuncs); + if (FAILED(hres)) { + ERR("Cannot get number of functions for typeinfo %s\n",debugstr_guid(riid)); + ITypeInfo_Release(tinfo); + return hres; + } + proxy = CoTaskMemAlloc(sizeof(TMProxyImpl)); if (!proxy) return E_OUTOFMEMORY; @@ -1683,67 +1774,6 @@ PSFacBuf_CreateProxy( proxy->crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": TMProxyImpl.crit"); proxy->lpvtbl = HeapAlloc(GetProcessHeap(),0,sizeof(LPBYTE)*nroffuncs); - for (i=0;iasmstubs+i; - - switch (i) { - case 0: - proxy->lpvtbl[i] = ProxyIUnknown_QueryInterface; - break; - case 1: - proxy->lpvtbl[i] = ProxyIUnknown_AddRef; - break; - case 2: - proxy->lpvtbl[i] = ProxyIUnknown_Release; - break; - default: { - int j; - /* nrofargs without This */ - int nrofargs; - ITypeInfo *tinfo2; - hres = _get_funcdesc(tinfo,i,&tinfo2,&fdesc,NULL,NULL); - ITypeInfo_Release(tinfo2); - if (hres) { - ERR("GetFuncDesc %x should not fail here.\n",hres); - return hres; - } - /* some args take more than 4 byte on the stack */ - nrofargs = 0; - for (j=0;jcParams;j++) - nrofargs += _argsize(fdesc->lprgelemdescParam[j].tdesc.vt); - -#ifdef __i386__ - if (fdesc->callconv != CC_STDCALL) { - ERR("calling convention is not stdcall????\n"); - return E_FAIL; - } -/* popl %eax - return ptr - * pushl - * pushl %eax - * call xCall - * lret (+4) - * - * - * arg3 arg2 arg1 - */ - xasm->popleax = 0x58; - xasm->pushlval = 0x6a; - xasm->nr = i; - xasm->pushleax = 0x50; - xasm->lcall = 0xe8; /* relative jump */ - xasm->xcall = (DWORD)xCall; - xasm->xcall -= (DWORD)&(xasm->lret); - xasm->lret = 0xc2; - xasm->bytestopop= (nrofargs+2)*4; /* pop args, This, iMethod */ - proxy->lpvtbl[i] = xasm; - break; -#else - FIXME("not implemented on non i386\n"); - return E_FAIL; -#endif - } - } - } /* if we derive from IDispatch then defer to its proxy for its methods */ hres = ITypeInfo_GetTypeAttr(tinfo, &typeattr); @@ -1767,15 +1797,61 @@ PSFacBuf_CreateProxy( } if (hres == S_OK) { - proxy->lpvtbl[3] = ProxyIDispatch_GetTypeInfoCount; - proxy->lpvtbl[4] = ProxyIDispatch_GetTypeInfo; - proxy->lpvtbl[5] = ProxyIDispatch_GetIDsOfNames; - proxy->lpvtbl[6] = ProxyIDispatch_Invoke; + defer_to_dispatch = TRUE; } } ITypeInfo_ReleaseTypeAttr(tinfo, typeattr); } + for (i=0;ilpvtbl[i] = ProxyIUnknown_QueryInterface; + break; + case 1: + proxy->lpvtbl[i] = ProxyIUnknown_AddRef; + break; + case 2: + proxy->lpvtbl[i] = ProxyIUnknown_Release; + break; + case 3: + if(!defer_to_dispatch) + { + hres = init_proxy_entry_point(proxy, i); + if(FAILED(hres)) return hres; + } + else proxy->lpvtbl[3] = ProxyIDispatch_GetTypeInfoCount; + break; + case 4: + if(!defer_to_dispatch) + { + hres = init_proxy_entry_point(proxy, i); + if(FAILED(hres)) return hres; + } + else proxy->lpvtbl[4] = ProxyIDispatch_GetTypeInfo; + break; + case 5: + if(!defer_to_dispatch) + { + hres = init_proxy_entry_point(proxy, i); + if(FAILED(hres)) return hres; + } + else proxy->lpvtbl[5] = ProxyIDispatch_GetIDsOfNames; + break; + case 6: + if(!defer_to_dispatch) + { + hres = init_proxy_entry_point(proxy, i); + if(FAILED(hres)) return hres; + } + else proxy->lpvtbl[6] = ProxyIDispatch_Invoke; + break; + default: + hres = init_proxy_entry_point(proxy, i); + if(FAILED(hres)) return hres; + } + } + if (hres == S_OK) { *ppv = (LPVOID)proxy; @@ -1917,7 +1993,7 @@ TMStubImpl_Invoke( memcpy(buf.base, xmsg->Buffer, xmsg->cbBuffer); buf.curoff = 0; - hres = _get_funcdesc(This->tinfo,xmsg->iMethod,&tinfo,&fdesc,&iname,NULL); + hres = get_funcdesc(This->tinfo,xmsg->iMethod,&tinfo,&fdesc,&iname,NULL,NULL); if (hres) { ERR("GetFuncDesc on method %d failed with %x\n",xmsg->iMethod,hres); return hres; diff --git a/reactos/dll/win32/oleaut32/typelib.c b/reactos/dll/win32/oleaut32/typelib.c index 50b29280d1d..b55599fba2d 100644 --- a/reactos/dll/win32/oleaut32/typelib.c +++ b/reactos/dll/win32/oleaut32/typelib.c @@ -70,6 +70,7 @@ #include "typelib.h" #include "wine/debug.h" #include "variant.h" +#include "wine/list.h" WINE_DEFAULT_DEBUG_CHANNEL(ole); WINE_DECLARE_DEBUG_CHANNEL(typelib); @@ -103,6 +104,8 @@ static DWORD FromLEDWord(DWORD p_iVal) #define FromLEDWord(X) (X) #endif +#define DISPATCH_HREF_OFFSET 0x01000000 +#define DISPATCH_HREF_MASK 0xff000000 /**************************************************************************** * FromLExxx @@ -894,8 +897,11 @@ typedef struct tagITypeLibImpl TLBImpLib * pImpLibs; /* linked list to all imported typelibs */ int ctTypeDesc; /* number of items in type desc array */ TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the - library. Only used while read MSFT + library. Only used while reading MSFT typelibs */ + struct list ref_list; /* list of ref types in this typelib */ + HREFTYPE dispatch_href; /* reference to IDispatch, -1 if unused */ + /* typelibs are cached, keyed by path and index, so store the linked list info within them */ struct tagITypeLibImpl *next, *prev; @@ -932,7 +938,7 @@ typedef struct tagTLBRefType TLB_REF_INTERNAL for internal refs TLB_REF_NOT_FOUND for broken refs */ - struct tagTLBRefType * next; + struct list entry; } TLBRefType; #define TLB_REF_USE_GUID -2 @@ -1015,7 +1021,6 @@ typedef struct tagITypeInfoImpl /* Implemented Interfaces */ TLBImplType * impltypelist; - TLBRefType * reflist; int ctCustData; TLBCustData * pCustData; /* linked list to cust data; */ struct tagITypeInfoImpl * next; @@ -1042,7 +1047,7 @@ typedef struct tagTLBContext } TLBContext; -static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI, int offset); +static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL, int offset); /* debug @@ -1200,23 +1205,24 @@ static void dump_TLBImpLib(const TLBImpLib *import) import->wVersionMinor, import->lcid, import->offset); } -static void dump_TLBRefType(const TLBRefType * prt) +static void dump_TLBRefType(const ITypeLibImpl *pTL) { - while (prt) - { - TRACE_(typelib)("href:0x%08x\n", prt->reference); - if(prt->index == -1) - TRACE_(typelib)("%s\n", debugstr_guid(&(prt->guid))); - else - TRACE_(typelib)("type no: %d\n", prt->index); + TLBRefType *ref; - if(prt->pImpTLInfo != TLB_REF_INTERNAL && - prt->pImpTLInfo != TLB_REF_NOT_FOUND) { - TRACE_(typelib)("in lib\n"); - dump_TLBImpLib(prt->pImpTLInfo); - } - prt = prt->next; - }; + LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry) + { + TRACE_(typelib)("href:0x%08x\n", ref->reference); + if(ref->index == -1) + TRACE_(typelib)("%s\n", debugstr_guid(&(ref->guid))); + else + TRACE_(typelib)("type no: %d\n", ref->index); + + if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND) + { + TRACE_(typelib)("in lib\n"); + dump_TLBImpLib(ref->pImpTLInfo); + } + } } static void dump_TLBImplType(const TLBImplType * impl) @@ -1630,7 +1636,7 @@ static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx ) MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */ V_BSTR(pVar)=SysAllocStringLen(NULL,size); /* FIXME: do we need a AtoW conversion here? */ - V_UNION(pVar, bstrVal[size])=L'\0'; + V_UNION(pVar, bstrVal[size])='\0'; while(size--) V_UNION(pVar, bstrVal[size])=ptr[size]; TLB_Free(ptr); } @@ -1697,7 +1703,7 @@ static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd, *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))]; if(pTd->vt == VT_USERDEFINED) - MSFT_DoRefType(pcx, pTI, pTd->u.hreftype); + MSFT_DoRefType(pcx, pTI->pTypeLib, pTd->u.hreftype); TRACE_(typelib)("vt type = %X\n", pTd->vt); } @@ -1718,7 +1724,7 @@ static void MSFT_ResolveReferencedTypes(TLBContext *pcx, ITypeInfoImpl *pTI, TYP break; case VT_USERDEFINED: - MSFT_DoRefType(pcx, pTI, + MSFT_DoRefType(pcx, pTI->pTypeLib, lpTypeDesc->u.hreftype); lpTypeDesc = NULL; @@ -2002,22 +2008,21 @@ static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs, * in the typelib, it's just an (file) offset in the type info base dir. * If comes from import, it's an offset+1 in the ImpInfo table * */ -static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI, +static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL, int offset) { int j; - TLBRefType **ppRefType = &pTI->reflist; + TLBRefType *ref; TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset); - while(*ppRefType) { - if((*ppRefType)->reference == offset) - return; - ppRefType = &(*ppRefType)->next; + LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry) + { + if(ref->reference == offset) return; } - *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, - sizeof(**ppRefType)); + ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref)); + list_add_tail(&pTL->ref_list, &ref->entry); if(!MSFT_HREFTYPE_INTHISFILE( offset)) { /* external typelib */ @@ -2033,24 +2038,24 @@ static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI, pImpLib=pImpLib->next; } if(pImpLib){ - (*ppRefType)->reference=offset; - (*ppRefType)->pImpTLInfo = pImpLib; + ref->reference = offset; + ref->pImpTLInfo = pImpLib; if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) { - MSFT_ReadGuid(&(*ppRefType)->guid, impinfo.oGuid, pcx); - TRACE("importing by guid %s\n", debugstr_guid(&(*ppRefType)->guid)); - (*ppRefType)->index = TLB_REF_USE_GUID; + MSFT_ReadGuid(&ref->guid, impinfo.oGuid, pcx); + TRACE("importing by guid %s\n", debugstr_guid(&ref->guid)); + ref->index = TLB_REF_USE_GUID; } else - (*ppRefType)->index = impinfo.oGuid; + ref->index = impinfo.oGuid; }else{ ERR("Cannot find a reference\n"); - (*ppRefType)->reference=-1; - (*ppRefType)->pImpTLInfo=TLB_REF_NOT_FOUND; + ref->reference = -1; + ref->pImpTLInfo = TLB_REF_NOT_FOUND; } }else{ /* in this typelib */ - (*ppRefType)->index = MSFT_HREFTYPE_INDEX(offset); - (*ppRefType)->reference=offset; - (*ppRefType)->pImpTLInfo=TLB_REF_INTERNAL; + ref->index = MSFT_HREFTYPE_INDEX(offset); + ref->reference = offset; + ref->pImpTLInfo = TLB_REF_INTERNAL; } } @@ -2068,7 +2073,7 @@ static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count, if(offset<0) break; /* paranoia */ *ppImpl=TLB_Alloc(sizeof(**ppImpl)); MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset); - MSFT_DoRefType(pcx, pTI, refrec.reftype); + MSFT_DoRefType(pcx, pTI->pTypeLib, refrec.reftype); (*ppImpl)->hRef = refrec.reftype; (*ppImpl)->implflags=refrec.flags; (*ppImpl)->ctCustData= @@ -2083,7 +2088,6 @@ static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count, static ITypeInfoImpl * MSFT_DoTypeInfo( TLBContext *pcx, int count, - INT dispatch_href, ITypeLibImpl * pLibInfo) { MSFT_TypeInfoBase tiBase; @@ -2153,22 +2157,22 @@ static ITypeInfoImpl * MSFT_DoTypeInfo( tiBase.datatype1); break; case TKIND_DISPATCH: - ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType)); + /* This is not -1 when the interface is a non-base dual interface or + when a dispinterface wraps an interface ie the idl 'dispinterface x {interface y;};'. + Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and + not this interface. + */ if (tiBase.datatype1 != -1) { - MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1); - ptiRet->impltypelist->hRef = tiBase.datatype1; + ptiRet->impltypelist = TLB_Alloc(sizeof(TLBImplType)); + ptiRet->impltypelist->hRef = tiBase.datatype1; + MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1); } - else - { - MSFT_DoRefType(pcx, ptiRet, dispatch_href); - ptiRet->impltypelist->hRef = dispatch_href; - } - break; + break; default: ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType)); - MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1); + MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1); ptiRet->impltypelist->hRef = tiBase.datatype1; break; } @@ -2362,6 +2366,9 @@ static ITypeLibImpl* TypeLibImpl_Constructor(void) pTypeLibImpl->lpVtblTypeComp = &tlbtcvt; pTypeLibImpl->ref = 1; + list_init(&pTypeLibImpl->ref_list); + pTypeLibImpl->dispatch_href = -1; + return pTypeLibImpl; } @@ -2556,6 +2563,10 @@ static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength) } } + pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos; + if(pTypeLibImpl->dispatch_href != -1) + MSFT_DoRefType(&cx, pTypeLibImpl, pTypeLibImpl->dispatch_href); + /* type info's */ if(tlbHeader.nrtypeinfos >= 0 ) { @@ -2565,7 +2576,7 @@ static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength) for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++) { - *ppTI = MSFT_DoTypeInfo(&cx, i, tlbHeader.dispatchpos, pTypeLibImpl); + *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl); ppTI = &((*ppTI)->next); (pTypeLibImpl->TypeInfoCount)++; @@ -2693,7 +2704,27 @@ static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl) return ptr - (char*)pLibBlk; } -static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD) +/* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */ +typedef struct +{ + unsigned int num; + HREFTYPE refs[1]; +} sltg_ref_lookup_t; + +static HRESULT sltg_get_typelib_ref(sltg_ref_lookup_t *table, DWORD typeinfo_ref, HREFTYPE *typelib_ref) +{ + if(typeinfo_ref < table->num) + { + *typelib_ref = table->refs[typeinfo_ref]; + return S_OK; + } + + ERR("Unable to find reference\n"); + *typelib_ref = -1; + return E_FAIL; +} + +static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, sltg_ref_lookup_t *ref_lookup) { BOOL done = FALSE; @@ -2714,7 +2745,7 @@ static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD) case VT_USERDEFINED: pTD->vt = VT_USERDEFINED; - pTD->u.hreftype = *(++pType) / 4; + sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype); done = TRUE; break; @@ -2759,7 +2790,7 @@ static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD) return pType; } -static WORD *SLTG_DoElem(WORD *pType, char *pBlk, ELEMDESC *pElem) +static WORD *SLTG_DoElem(WORD *pType, char *pBlk, ELEMDESC *pElem, sltg_ref_lookup_t *ref_lookup) { /* Handle [in/out] first */ if((*pType & 0xc000) == 0xc000) @@ -2777,36 +2808,44 @@ static WORD *SLTG_DoElem(WORD *pType, char *pBlk, ELEMDESC *pElem) if(*pType & 0x80) pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL; - return SLTG_DoType(pType, pBlk, &pElem->tdesc); + return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup); } -static void SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeInfoImpl *pTI, +static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL, char *pNameTable) { int ref; char *name; - TLBRefType **ppRefType; + TLBRefType *ref_type; + sltg_ref_lookup_t *table; + HREFTYPE typelib_ref; if(pRef->magic != SLTG_REF_MAGIC) { FIXME("Ref magic = %x\n", pRef->magic); - return; + return NULL; } name = ( (char*)(&pRef->names) + pRef->number); - ppRefType = &pTI->reflist; + table = HeapAlloc(GetProcessHeap(), 0, sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0])); + table->num = pRef->number >> 3; + + /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */ + + /* We don't want the first href to be 0 */ + typelib_ref = (list_count(&pTL->ref_list) + 1) << 2; + for(ref = 0; ref < pRef->number >> 3; ref++) { char *refname; unsigned int lib_offs, type_num; - *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, - sizeof(**ppRefType)); + ref_type = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref_type)); name += SLTG_ReadStringA(name, &refname); if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2) FIXME("Can't sscanf ref\n"); if(lib_offs != 0xffff) { - TLBImpLib **import = &pTI->pTypeLib->pImpLibs; + TLBImpLib **import = &pTL->pImpLibs; while(*import) { if((*import)->offset == lib_offs) @@ -2835,23 +2874,32 @@ static void SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeInfoImpl *pTI, fname[len-1] = '\0'; (*import)->name = TLB_MultiByteToBSTR(fname); } - (*ppRefType)->pImpTLInfo = *import; + ref_type->pImpTLInfo = *import; + + /* Store a reference to IDispatch */ + if(pTL->dispatch_href == -1 && IsEqualGUID(&(*import)->guid, &IID_StdOle) && type_num == 4) + pTL->dispatch_href = typelib_ref; + } else { /* internal ref */ - (*ppRefType)->pImpTLInfo = TLB_REF_INTERNAL; + ref_type->pImpTLInfo = TLB_REF_INTERNAL; } - (*ppRefType)->reference = ref; - (*ppRefType)->index = type_num; + ref_type->reference = typelib_ref; + ref_type->index = type_num; HeapFree(GetProcessHeap(), 0, refname); - ppRefType = &(*ppRefType)->next; + list_add_tail(&pTL->ref_list, &ref_type->entry); + + table->refs[ref] = typelib_ref; + typelib_ref += 4; } if((BYTE)*name != SLTG_REF_MAGIC) FIXME("End of ref block magic = %x\n", *name); - dump_TLBRefType(pTI->reflist); + dump_TLBRefType(pTL); + return table; } static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI, - BOOL OneOnly) + BOOL OneOnly, sltg_ref_lookup_t *ref_lookup) { SLTG_ImplInfo *info; TLBImplType **ppImplType = &pTI->impltypelist; @@ -2866,7 +2914,7 @@ static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI, while(1) { *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(**ppImplType)); - (*ppImplType)->hRef = info->ref; + sltg_get_typelib_ref(ref_lookup, info->ref, &(*ppImplType)->hRef); (*ppImplType)->implflags = info->impltypeflags; pTI->TypeAttr.cImplTypes++; ppImplType = &(*ppImplType)->next; @@ -2881,7 +2929,7 @@ static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI, return (char*)info; } -static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars, char *pNameTable) +static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars, char *pNameTable, sltg_ref_lookup_t *ref_lookup) { TLBVarDesc **ppVarDesc = &pTI->varlist; BSTR bstrPrevName = NULL; @@ -2945,7 +2993,7 @@ static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsign FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xd2); SLTG_DoElem(pType, pBlk, - &(*ppVarDesc)->vardesc.elemdescVar); + &(*ppVarDesc)->vardesc.elemdescVar, ref_lookup); dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf); @@ -2955,7 +3003,7 @@ static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsign pTI->TypeAttr.cVars = cVars; } -static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cFuncs, char *pNameTable) +static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cFuncs, char *pNameTable, sltg_ref_lookup_t *ref_lookup) { SLTG_Function *pFunc; unsigned short i; @@ -3003,7 +3051,7 @@ static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsig else pType = (WORD*)(pBlk + pFunc->rettype); - SLTG_DoElem(pType, pBlk, &(*ppFuncDesc)->funcdesc.elemdescFunc); + SLTG_DoElem(pType, pBlk, &(*ppFuncDesc)->funcdesc.elemdescFunc, ref_lookup); (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, @@ -3041,13 +3089,13 @@ static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsig if(HaveOffs) { /* the next word is an offset to type */ pType = (WORD*)(pBlk + *pArg); SLTG_DoElem(pType, pBlk, - &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]); + &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup); pArg++; } else { if(paramName) paramName--; pArg = SLTG_DoElem(pArg, pBlk, - &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]); + &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup); } /* Are we an optional param ? */ @@ -3072,17 +3120,19 @@ static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI, SLTG_TypeInfoTail *pTITail) { char *pFirstItem, *pNextItem; + sltg_ref_lookup_t *ref_lookup = NULL; if(pTIHeader->href_table != 0xffffffff) { - SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI, + ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib, pNameTable); } pFirstItem = pNextItem = pBlk; if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) { - pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE); + pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup); } + HeapFree(GetProcessHeap(), 0, ref_lookup); } @@ -3091,20 +3141,23 @@ static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI, SLTG_TypeInfoTail *pTITail) { char *pFirstItem, *pNextItem; + sltg_ref_lookup_t *ref_lookup = NULL; if(pTIHeader->href_table != 0xffffffff) { - SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI, + ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib, pNameTable); } pFirstItem = pNextItem = pBlk; if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) { - pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE); + pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup); } if (pTITail->funcs_off != 0xffff) - SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable); + SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup); + + HeapFree(GetProcessHeap(), 0, ref_lookup); if (TRACE_ON(typelib)) dump_TLBFuncDesc(pTI->funclist); @@ -3114,7 +3167,7 @@ static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI, char *pNameTable, SLTG_TypeInfoHeader *pTIHeader, SLTG_TypeInfoTail *pTITail) { - SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable); + SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL); } static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI, @@ -3122,6 +3175,7 @@ static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI, SLTG_TypeInfoTail *pTITail) { WORD *pType; + sltg_ref_lookup_t *ref_lookup = NULL; if (pTITail->simple_alias) { /* if simple alias, no more processing required */ @@ -3130,35 +3184,39 @@ static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI, } if(pTIHeader->href_table != 0xffffffff) { - SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI, + ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib, pNameTable); } /* otherwise it is an offset to a type */ pType = (WORD *)(pBlk + pTITail->tdescalias_vt); - SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias); + SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias, ref_lookup); + + HeapFree(GetProcessHeap(), 0, ref_lookup); } static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI, char *pNameTable, SLTG_TypeInfoHeader *pTIHeader, SLTG_TypeInfoTail *pTITail) { + sltg_ref_lookup_t *ref_lookup = NULL; if (pTIHeader->href_table != 0xffffffff) - SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI, + ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib, pNameTable); if (pTITail->vars_off != 0xffff) - SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable); + SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup); if (pTITail->funcs_off != 0xffff) - SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable); + SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup); /* this is necessary to cope with MSFT typelibs that set cFuncs to the number * of dispinterface functons including the IDispatch ones, so * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */ pTI->TypeAttr.cbSizeVft = pTI->TypeAttr.cFuncs * sizeof(void *); + HeapFree(GetProcessHeap(), 0, ref_lookup); if (TRACE_ON(typelib)) dump_TLBFuncDesc(pTI->funclist); } @@ -3167,22 +3225,24 @@ static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI, char *pNameTable, SLTG_TypeInfoHeader *pTIHeader, SLTG_TypeInfoTail *pTITail) { - SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable); + SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL); } static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI, char *pNameTable, SLTG_TypeInfoHeader *pTIHeader, SLTG_TypeInfoTail *pTITail) { + sltg_ref_lookup_t *ref_lookup = NULL; if (pTIHeader->href_table != 0xffffffff) - SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI, + ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib, pNameTable); if (pTITail->vars_off != 0xffff) - SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable); + SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup); if (pTITail->funcs_off != 0xffff) - SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable); + SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup); + HeapFree(GetProcessHeap(), 0, ref_lookup); } /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more @@ -3553,6 +3613,8 @@ static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface) { TLBImpLib *pImpLib, *pImpLibNext; TLBCustData *pCustData, *pCustDataNext; + TLBRefType *ref_type; + void *cursor2; int i; /* remove cache entry */ @@ -3616,6 +3678,12 @@ static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface) TLB_Free(pImpLib); } + LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry) + { + list_remove(&ref_type->entry); + TLB_Free(ref_type); + } + if (This->pTypeInfo) /* can be NULL */ ITypeInfo_Release((ITypeInfo*) This->pTypeInfo); HeapFree(GetProcessHeap(),0,This); @@ -4402,7 +4470,6 @@ static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface) TLBFuncDesc *pFInfo, *pFInfoNext; TLBVarDesc *pVInfo, *pVInfoNext; TLBImplType *pImpl, *pImplNext; - TLBRefType *pRefType,*pRefTypeNext; TLBCustData *pCustData, *pCustDataNext; TRACE("destroying ITypeInfo(%p)\n",This); @@ -4481,11 +4548,6 @@ static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface) pImplNext = pImpl->next; TLB_Free(pImpl); } - for(pRefType = This->reflist; pRefType; pRefType = pRefTypeNext) - { - pRefTypeNext = pRefType->next; - TLB_Free(pRefType); - } TLB_Free(This->pCustData); finish_free: @@ -4690,47 +4752,47 @@ HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const F return S_OK; } - return E_INVALIDARG; + return TYPE_E_ELEMENTNOTFOUND; } /* internal function to make the inherited interfaces' methods appear * part of the interface */ static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface, - UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs) + UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset) { ITypeInfoImpl *This = (ITypeInfoImpl *)iface; HRESULT hr; - UINT i; UINT implemented_funcs = 0; if (funcs) *funcs = 0; + else + *hrefoffset = DISPATCH_HREF_OFFSET; - for (i = 0; i < This->TypeAttr.cImplTypes; i++) + if(This->impltypelist) { - HREFTYPE href; ITypeInfo *pSubTypeInfo; UINT sub_funcs; - hr = ITypeInfo_GetRefTypeOfImplType(iface, i, &href); - if (FAILED(hr)) - return hr; - hr = ITypeInfo_GetRefTypeInfo(iface, href, &pSubTypeInfo); + hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo); if (FAILED(hr)) return hr; hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo, index, ppFuncDesc, - &sub_funcs); + &sub_funcs, hrefoffset); implemented_funcs += sub_funcs; ITypeInfo_Release(pSubTypeInfo); if (SUCCEEDED(hr)) return hr; + *hrefoffset += DISPATCH_HREF_OFFSET; } if (funcs) *funcs = implemented_funcs + This->TypeAttr.cFuncs; + else + *hrefoffset = 0; if (index < implemented_funcs) return E_INVALIDARG; @@ -4738,6 +4800,37 @@ static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface, ppFuncDesc); } +static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset) +{ + TYPEDESC *pTypeDesc = &pElemDesc->tdesc; + while (TRUE) + { + switch (pTypeDesc->vt) + { + case VT_USERDEFINED: + pTypeDesc->u.hreftype += hrefoffset; + return; + case VT_PTR: + case VT_SAFEARRAY: + pTypeDesc = pTypeDesc->u.lptdesc; + break; + case VT_CARRAY: + pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem; + break; + default: + return; + } + } +} + +static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset) +{ + SHORT i; + for (i = 0; i < pFuncDesc->cParams; i++) + ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset); + ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset); +} + /* ITypeInfo::GetFuncDesc * * Retrieves the FUNCDESC structure that contains information about a @@ -4750,13 +4843,14 @@ static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index, ITypeInfoImpl *This = (ITypeInfoImpl *)iface; const FUNCDESC *internal_funcdesc; HRESULT hr; + UINT hrefoffset = 0; TRACE("(%p) index %d\n", This, index); - if ((This->TypeAttr.typekind == TKIND_DISPATCH) && - (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL)) + if (This->TypeAttr.typekind == TKIND_DISPATCH) hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index, - &internal_funcdesc, NULL); + &internal_funcdesc, NULL, + &hrefoffset); else hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index, &internal_funcdesc); @@ -4766,10 +4860,16 @@ static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index, return hr; } - return TLB_AllocAndInitFuncDesc( + hr = TLB_AllocAndInitFuncDesc( internal_funcdesc, ppFuncDesc, This->TypeAttr.typekind == TKIND_DISPATCH); + + if ((This->TypeAttr.typekind == TKIND_DISPATCH) && hrefoffset) + ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset); + + TRACE("-- 0x%08x\n", hr); + return hr; } static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr ) @@ -4885,7 +4985,7 @@ static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid, } else { - if(This->TypeAttr.cImplTypes && + if(This->impltypelist && (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) { /* recursive search */ ITypeInfo *pTInfo; @@ -4950,6 +5050,11 @@ static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType( hr = TYPE_E_ELEMENTNOTFOUND; } } + else if(index == 0 && This->TypeAttr.typekind == TKIND_DISPATCH) + { + /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */ + *pRefType = This->pTypeLib->dispatch_href; + } else { /* get element n from linked list */ @@ -5043,7 +5148,7 @@ static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface, } } /* not found, see if it can be found in an inherited interface */ - if(This->TypeAttr.cImplTypes) { + if(This->impltypelist) { /* recursive search */ ITypeInfo *pTInfo; ret=ITypeInfo_GetRefTypeInfo(iface, @@ -5151,6 +5256,27 @@ _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) { case 23: res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22]); break; + case 24: + res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23]); + break; + case 25: + res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23],args[24]); + break; + case 26: + res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23],args[24],args[25]); + break; + case 27: + res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23],args[24],args[25],args[26]); + break; + case 28: + res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23],args[24],args[25],args[26],args[27]); + break; + case 29: + res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23],args[24],args[25],args[26],args[27],args[28]); + break; + case 30: + res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23],args[24],args[25],args[26],args[27],args[28],args[29]); + break; default: FIXME("unsupported number of arguments %d in stdcall\n",nrargs); res = -1; @@ -5202,7 +5328,7 @@ static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, break; case TKIND_INTERFACE: - if (IsEqualIID(&IID_IDispatch, &tattr->guid)) + if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE) *vt |= VT_DISPATCH; else *vt |= VT_UNKNOWN; @@ -5489,6 +5615,13 @@ static HRESULT WINAPI ITypeInfo_fnInvoke( rgdispidNamedArgs++; } + if (func_desc->cParamsOpt < 0 && cNamedArgs) + { + ERR("functions with the vararg attribute do not support named arguments\n"); + hres = DISP_E_NONAMEDARGS; + goto func_fail; + } + for (i = 0; i < func_desc->cParams; i++) { TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc; @@ -5569,6 +5702,36 @@ static HRESULT WINAPI ITypeInfo_fnInvoke( } V_VT(&rgvarg[i]) = rgvt[i]; } + else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1) + { + SAFEARRAY *a; + SAFEARRAYBOUND bound; + VARIANT *v; + LONG j; + bound.lLbound = 0; + bound.cElements = pDispParams->cArgs-i; + if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound))) + { + ERR("SafeArrayCreate failed\n"); + break; + } + hres = SafeArrayAccessData(a, (LPVOID)&v); + if (hres != S_OK) + { + ERR("SafeArrayAccessData failed with %x\n", hres); + break; + } + for (j = 0; j < bound.cElements; j++) + VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]); + hres = SafeArrayUnaccessData(a); + if (hres != S_OK) + { + ERR("SafeArrayUnaccessData failed with %x\n", hres); + break; + } + V_ARRAY(&rgvarg[i]) = a; + V_VT(&rgvarg[i]) = rgvt[i]; + } else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg)) { VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams); @@ -5635,12 +5798,6 @@ static HRESULT WINAPI ITypeInfo_fnInvoke( } } if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */ - if (func_desc->cParamsOpt < 0) - { - FIXME("Does not support safearray optional parameters\n"); - hres = DISP_E_BADPARAMCOUNT; - goto func_fail; /* FIXME: we don't free changed types here */ - } /* VT_VOID is a special case for return types, so it is not * handled in the general function */ @@ -5704,6 +5861,34 @@ static HRESULT WINAPI ITypeInfo_fnInvoke( break; } } + else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) && + func_desc->cParamsOpt < 0 && + i == func_desc->cParams-1) + { + SAFEARRAY *a = V_ARRAY(prgpvarg[i]); + LONG j, ubound; + VARIANT *v; + hres = SafeArrayGetUBound(a, 1, &ubound); + if (hres != S_OK) + { + ERR("SafeArrayGetUBound failed with %x\n", hres); + break; + } + hres = SafeArrayAccessData(a, (LPVOID)&v); + if (hres != S_OK) + { + ERR("SafeArrayAccessData failed with %x\n", hres); + break; + } + for (j = 0; j <= ubound; j++) + VariantClear(&v[j]); + hres = SafeArrayUnaccessData(a); + if (hres != S_OK) + { + ERR("SafeArrayUnaccessData failed with %x\n", hres); + break; + } + } VariantClear(&rgvarg[i]); } else if (wParamFlags & PARAMFLAG_FOPT) @@ -5747,7 +5932,7 @@ static HRESULT WINAPI ITypeInfo_fnInvoke( } if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) && - (wFlags == INVOKE_PROPERTYGET) && + (func_desc->invkind & INVOKE_PROPERTYGET) && (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) && (pDispParams->cArgs != 0)) { @@ -5814,11 +5999,10 @@ func_fail: /* not found, look for it in inherited interfaces */ ITypeInfo2_GetTypeKind(iface, &type_kind); if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) { - HREFTYPE ref_type; - if(SUCCEEDED(ITypeInfo2_GetRefTypeOfImplType(iface, 0, &ref_type))) { + if(This->impltypelist) { /* recursive search */ ITypeInfo *pTInfo; - hres = ITypeInfo_GetRefTypeInfo(iface, ref_type, &pTInfo); + hres = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo); if(SUCCEEDED(hres)){ hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr); ITypeInfo_Release(pTInfo); @@ -5881,7 +6065,7 @@ static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface, } } - if(This->TypeAttr.cImplTypes && + if(This->impltypelist && (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) { /* recursive search */ ITypeInfo *pTInfo; @@ -5947,6 +6131,38 @@ static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid return TYPE_E_ELEMENTNOTFOUND; } +/* internal function to make the inherited interfaces' methods appear + * part of the interface */ +static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface, + HREFTYPE *hRefType, ITypeInfo **ppTInfo) +{ + ITypeInfoImpl *This = (ITypeInfoImpl *)iface; + HRESULT hr; + + TRACE("%p, 0x%x\n", iface, *hRefType); + + if (This->impltypelist && (*hRefType & DISPATCH_HREF_MASK)) + { + ITypeInfo *pSubTypeInfo; + + hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo); + if (FAILED(hr)) + return hr; + + hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo, + hRefType, ppTInfo); + ITypeInfo_Release(pSubTypeInfo); + if (SUCCEEDED(hr)) + return hr; + } + *hRefType -= DISPATCH_HREF_OFFSET; + + if (!(*hRefType & DISPATCH_HREF_MASK)) + return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo); + else + return E_FAIL; +} + /* ITypeInfo::GetRefTypeInfo * * If a type description references other type descriptions, it retrieves @@ -5967,8 +6183,8 @@ static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo( result = S_OK; } else if (hRefType == -1 && - (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) && - (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL)) + (This->TypeAttr.typekind == TKIND_DISPATCH) && + (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL)) { /* when we meet a DUAL dispinterface, we must create the interface * version of it. @@ -5998,52 +6214,62 @@ static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo( result = S_OK; + } else if ((hRefType != -1) && (hRefType & DISPATCH_HREF_MASK) && + (This->TypeAttr.typekind == TKIND_DISPATCH) && + (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL)) + { + HREFTYPE href_dispatch = hRefType; + result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo); } else { - TLBRefType *pRefType; - for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) { - if(pRefType->reference == hRefType) - break; - } - if(!pRefType) - FIXME("Can't find pRefType for ref %x\n", hRefType); - if(pRefType && hRefType != -1) { + TLBRefType *ref_type; + LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry) + { + if(ref_type->reference == hRefType) + break; + } + if(&ref_type->entry == &This->pTypeLib->ref_list) + { + FIXME("Can't find pRefType for ref %x\n", hRefType); + goto end; + } + if(hRefType != -1) { ITypeLib *pTLib = NULL; - if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) { + if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) { UINT Index; result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index); } else { - if(pRefType->pImpTLInfo->pImpTypeLib) { + if(ref_type->pImpTLInfo->pImpTypeLib) { TRACE("typeinfo in imported typelib that is already loaded\n"); - pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib; + pTLib = (ITypeLib*)ref_type->pImpTLInfo->pImpTypeLib; ITypeLib2_AddRef((ITypeLib*) pTLib); result = S_OK; } else { TRACE("typeinfo in imported typelib that isn't already loaded\n"); - result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid, - pRefType->pImpTLInfo->wVersionMajor, - pRefType->pImpTLInfo->wVersionMinor, - pRefType->pImpTLInfo->lcid, + result = LoadRegTypeLib( &ref_type->pImpTLInfo->guid, + ref_type->pImpTLInfo->wVersionMajor, + ref_type->pImpTLInfo->wVersionMinor, + ref_type->pImpTLInfo->lcid, &pTLib); if(!SUCCEEDED(result)) { - BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name); + BSTR libnam=SysAllocString(ref_type->pImpTLInfo->name); result=LoadTypeLib(libnam, &pTLib); SysFreeString(libnam); } if(SUCCEEDED(result)) { - pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib; + ref_type->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib; ITypeLib2_AddRef(pTLib); } } } if(SUCCEEDED(result)) { - if(pRefType->index == TLB_REF_USE_GUID) + if(ref_type->index == TLB_REF_USE_GUID) result = ITypeLib2_GetTypeInfoOfGuid(pTLib, - &pRefType->guid, + &ref_type->guid, ppTInfo); else - result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index, + result = ITypeLib2_GetTypeInfo(pTLib, ref_type->index, ppTInfo); } if (pTLib != NULL) @@ -6051,6 +6277,7 @@ static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo( } } +end: TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType, SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo); return result; @@ -6809,6 +7036,7 @@ HRESULT WINAPI CreateDispTypeInfo( ITypeLibImpl *pTypeLibImpl; int param, func; TLBFuncDesc **ppFuncDesc; + TLBRefType *ref; TRACE("\n"); pTypeLibImpl = TypeLibImpl_Constructor(); @@ -6865,6 +7093,7 @@ HRESULT WINAPI CreateDispTypeInfo( (*ppFuncDesc)->ctCustData = 0; (*ppFuncDesc)->pCustData = NULL; (*ppFuncDesc)->next = NULL; + pTIIface->TypeAttr.cFuncs++; ppFuncDesc = &(*ppFuncDesc)->next; } @@ -6892,12 +7121,13 @@ HRESULT WINAPI CreateDispTypeInfo( pTIClass->TypeAttr.wTypeFlags = 0; pTIClass->impltypelist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->impltypelist)); - pTIClass->impltypelist->hRef = 1; + pTIClass->impltypelist->hRef = 0; - pTIClass->reflist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->reflist)); - pTIClass->reflist->index = 0; - pTIClass->reflist->reference = 1; - pTIClass->reflist->pImpTLInfo = TLB_REF_INTERNAL; + ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref)); + ref->index = 0; + ref->reference = 0; + ref->pImpTLInfo = TLB_REF_INTERNAL; + list_add_head(&pTypeLibImpl->ref_list, &ref->entry); dump_TypeInfo(pTIClass); @@ -6989,7 +7219,7 @@ static HRESULT WINAPI ITypeComp_fnBind( } } /* FIXME: search each inherited interface, not just the first */ - if (hr == DISP_E_MEMBERNOTFOUND && This->TypeAttr.cImplTypes) { + if (hr == DISP_E_MEMBERNOTFOUND && This->impltypelist) { /* recursive search */ ITypeInfo *pTInfo; ITypeComp *pTComp; diff --git a/reactos/dll/win32/oleaut32/typelib16.c b/reactos/dll/win32/oleaut32/typelib16.c index 69b4f65f941..a010f7de03a 100644 --- a/reactos/dll/win32/oleaut32/typelib16.c +++ b/reactos/dll/win32/oleaut32/typelib16.c @@ -33,7 +33,6 @@ #include "winerror.h" #include "windef.h" #include "winbase.h" -#include "winnls.h" #include "winreg.h" #include "winuser.h" diff --git a/reactos/dll/win32/oleaut32/typelib2.c b/reactos/dll/win32/oleaut32/typelib2.c index 5f3ead17a2c..874d8a8180f 100644 --- a/reactos/dll/win32/oleaut32/typelib2.c +++ b/reactos/dll/win32/oleaut32/typelib2.c @@ -43,7 +43,6 @@ #include "windef.h" #include "winbase.h" #include "winnls.h" -#include "winreg.h" #include "winuser.h" #include "wine/unicode.h" diff --git a/reactos/dll/win32/oleaut32/usrmarshal.c b/reactos/dll/win32/oleaut32/usrmarshal.c index eea46c606bd..67faf2080c0 100644 --- a/reactos/dll/win32/oleaut32/usrmarshal.c +++ b/reactos/dll/win32/oleaut32/usrmarshal.c @@ -277,14 +277,14 @@ static unsigned int get_type_alignment(ULONG *pFlags, VARIANT *pvar) return 7; } -static unsigned interface_variant_size(ULONG *pFlags, REFIID riid, VARIANT *pvar) +static unsigned interface_variant_size(ULONG *pFlags, REFIID riid, IUnknown *punk) { ULONG size; HRESULT hr; /* find the buffer size of the marshalled dispatch interface */ - hr = CoGetMarshalSizeMax(&size, riid, V_UNKNOWN(pvar), LOWORD(*pFlags), NULL, MSHLFLAGS_NORMAL); + hr = CoGetMarshalSizeMax(&size, riid, punk, LOWORD(*pFlags), NULL, MSHLFLAGS_NORMAL); if (FAILED(hr)) { - if (!V_DISPATCH(pvar)) + if (!punk) WARN("NULL dispatch pointer\n"); else ERR("Dispatch variant buffer size calculation failed, HRESULT=0x%x\n", hr); @@ -313,9 +313,13 @@ static ULONG wire_extra_user_size(ULONG *pFlags, ULONG Start, VARIANT *pvar) case VT_VARIANT | VT_BYREF: return VARIANT_UserSize(pFlags, Start, V_VARIANTREF(pvar)); case VT_UNKNOWN: - return Start + interface_variant_size(pFlags, &IID_IUnknown, pvar); + return Start + interface_variant_size(pFlags, &IID_IUnknown, V_UNKNOWN(pvar)); + case VT_UNKNOWN | VT_BYREF: + return Start + interface_variant_size(pFlags, &IID_IUnknown, *V_UNKNOWNREF(pvar)); case VT_DISPATCH: - return Start + interface_variant_size(pFlags, &IID_IDispatch, pvar); + return Start + interface_variant_size(pFlags, &IID_IDispatch, (IUnknown*)V_DISPATCH(pvar)); + case VT_DISPATCH | VT_BYREF: + return Start + interface_variant_size(pFlags, &IID_IDispatch, (IUnknown*)*V_DISPATCHREF(pvar)); case VT_RECORD: FIXME("wire-size record\n"); return Start; @@ -329,7 +333,7 @@ static ULONG wire_extra_user_size(ULONG *pFlags, ULONG Start, VARIANT *pvar) } /* helper: called for VT_DISPATCH variants to marshal the IDispatch* into the buffer. returns Buffer on failure, new position otherwise */ -static unsigned char* interface_variant_marshal(ULONG *pFlags, unsigned char *Buffer, REFIID riid, VARIANT *pvar) +static unsigned char* interface_variant_marshal(ULONG *pFlags, unsigned char *Buffer, REFIID riid, IUnknown *punk) { IStream *working; HGLOBAL working_mem; @@ -338,7 +342,7 @@ static unsigned char* interface_variant_marshal(ULONG *pFlags, unsigned char *Bu ULONG size; HRESULT hr; - TRACE("pFlags=%d, Buffer=%p, pvar=%p\n", *pFlags, Buffer, pvar); + TRACE("pFlags=%d, Buffer=%p, pUnk=%p\n", *pFlags, Buffer, punk); oldpos = Buffer; @@ -348,7 +352,7 @@ static unsigned char* interface_variant_marshal(ULONG *pFlags, unsigned char *Bu * but that would be overkill here, hence this implementation. We save the size because the unmarshal * code has no way to know how long the marshalled buffer is. */ - size = wire_extra_user_size(pFlags, 0, pvar); + size = interface_variant_size(pFlags, riid, punk); working_mem = GlobalAlloc(0, size); if (!working_mem) return oldpos; @@ -359,7 +363,7 @@ static unsigned char* interface_variant_marshal(ULONG *pFlags, unsigned char *Bu return oldpos; } - hr = CoMarshalInterface(working, riid, V_UNKNOWN(pvar), LOWORD(*pFlags), NULL, MSHLFLAGS_NORMAL); + hr = CoMarshalInterface(working, riid, punk, LOWORD(*pFlags), NULL, MSHLFLAGS_NORMAL); if (hr != S_OK) { IStream_Release(working); /* this also releases the hglobal */ return oldpos; @@ -378,7 +382,7 @@ static unsigned char* interface_variant_marshal(ULONG *pFlags, unsigned char *Bu } /* helper: called for VT_DISPATCH / VT_UNKNOWN variants to unmarshal the buffer. returns Buffer on failure, new position otherwise */ -static unsigned char *interface_variant_unmarshal(ULONG *pFlags, unsigned char *Buffer, REFIID riid, VARIANT *pvar) +static unsigned char *interface_variant_unmarshal(ULONG *pFlags, unsigned char *Buffer, REFIID riid, IUnknown **ppunk) { IStream *working; HGLOBAL working_mem; @@ -387,10 +391,10 @@ static unsigned char *interface_variant_unmarshal(ULONG *pFlags, unsigned char * ULONG size; HRESULT hr; - TRACE("pFlags=%d, Buffer=%p, pvar=%p\n", *pFlags, Buffer, pvar); + TRACE("pFlags=%d, Buffer=%p, ppUnk=%p\n", *pFlags, Buffer, ppunk); oldpos = Buffer; - + /* get the buffersize */ memcpy(&size, Buffer, sizeof(ULONG)); TRACE("buffersize=%d\n", size); @@ -410,7 +414,7 @@ static unsigned char *interface_variant_unmarshal(ULONG *pFlags, unsigned char * memcpy(working_memlocked, Buffer + sizeof(ULONG), size); GlobalUnlock(working_mem); - hr = CoUnmarshalInterface(working, riid, (void**)&V_UNKNOWN(pvar)); + hr = CoUnmarshalInterface(working, riid, (void**)ppunk); if (hr != S_OK) { IStream_Release(working); return oldpos; @@ -520,16 +524,21 @@ unsigned char * WINAPI VARIANT_UserMarshal(ULONG *pFlags, unsigned char *Buffer, case VT_VARIANT | VT_BYREF: Pos = VARIANT_UserMarshal(pFlags, Pos, V_VARIANTREF(pvar)); break; - case VT_DISPATCH | VT_BYREF: - FIXME("handle DISPATCH by ref\n"); - break; case VT_UNKNOWN: /* this should probably call WdtpInterfacePointer_UserMarshal in ole32.dll */ - Pos = interface_variant_marshal(pFlags, Pos, &IID_IUnknown, pvar); + Pos = interface_variant_marshal(pFlags, Pos, &IID_IUnknown, V_UNKNOWN(pvar)); + break; + case VT_UNKNOWN | VT_BYREF: + /* this should probably call WdtpInterfacePointer_UserMarshal in ole32.dll */ + Pos = interface_variant_marshal(pFlags, Pos, &IID_IUnknown, *V_UNKNOWNREF(pvar)); break; case VT_DISPATCH: /* this should probably call WdtpInterfacePointer_UserMarshal in ole32.dll */ - Pos = interface_variant_marshal(pFlags, Pos, &IID_IDispatch, pvar); + Pos = interface_variant_marshal(pFlags, Pos, &IID_IDispatch, (IUnknown*)V_DISPATCH(pvar)); + break; + case VT_DISPATCH | VT_BYREF: + /* this should probably call WdtpInterfacePointer_UserMarshal in ole32.dll */ + Pos = interface_variant_marshal(pFlags, Pos, &IID_IDispatch, (IUnknown*)*V_DISPATCHREF(pvar)); break; case VT_RECORD: FIXME("handle BRECORD by val\n"); @@ -609,16 +618,21 @@ unsigned char * WINAPI VARIANT_UserUnmarshal(ULONG *pFlags, unsigned char *Buffe case VT_VARIANT | VT_BYREF: Pos = VARIANT_UserUnmarshal(pFlags, Pos, V_VARIANTREF(pvar)); break; - case VT_DISPATCH | VT_BYREF: - FIXME("handle DISPATCH by ref\n"); - break; case VT_UNKNOWN: /* this should probably call WdtpInterfacePointer_UserUnmarshal in ole32.dll */ - Pos = interface_variant_unmarshal(pFlags, Pos, &IID_IUnknown, pvar); + Pos = interface_variant_unmarshal(pFlags, Pos, &IID_IUnknown, &V_UNKNOWN(pvar)); + break; + case VT_UNKNOWN | VT_BYREF: + /* this should probably call WdtpInterfacePointer_UserUnmarshal in ole32.dll */ + Pos = interface_variant_unmarshal(pFlags, Pos, &IID_IUnknown, V_UNKNOWNREF(pvar)); break; case VT_DISPATCH: /* this should probably call WdtpInterfacePointer_UserUnmarshal in ole32.dll */ - Pos = interface_variant_unmarshal(pFlags, Pos, &IID_IDispatch, pvar); + Pos = interface_variant_unmarshal(pFlags, Pos, &IID_IDispatch, (IUnknown**)&V_DISPATCH(pvar)); + break; + case VT_DISPATCH | VT_BYREF: + /* this should probably call WdtpInterfacePointer_UserUnmarshal in ole32.dll */ + Pos = interface_variant_unmarshal(pFlags, Pos, &IID_IDispatch, (IUnknown**)V_DISPATCHREF(pvar)); break; case VT_RECORD: FIXME("handle BRECORD by val\n"); @@ -697,6 +711,8 @@ static inline SF_TYPE SAFEARRAY_GetUnionType(SAFEARRAY *psa) hr = SafeArrayGetVartype(psa, &vt); if (FAILED(hr)) { + if(psa->fFeatures & FADF_VARIANT) return SF_VARIANT; + switch(psa->cbElements) { case 1: vt = VT_I1; break; diff --git a/reactos/dll/win32/oleaut32/variant.c b/reactos/dll/win32/oleaut32/variant.c index d851a9b1403..0540e956eb2 100644 --- a/reactos/dll/win32/oleaut32/variant.c +++ b/reactos/dll/win32/oleaut32/variant.c @@ -2929,7 +2929,7 @@ HRESULT WINAPI VarAnd(LPVARIANT left, LPVARIANT right, LPVARIANT result) } ExtraFlags = leftExtraFlags; - /* Native VarAnd always returns a error when using any extra + /* Native VarAnd always returns an error when using extra * flags or if the variant combination is I8 and INT. */ if ((leftvt == VT_I8 && rightvt == VT_INT) || @@ -3563,7 +3563,7 @@ HRESULT WINAPI VarDiv(LPVARIANT left, LPVARIANT right, LPVARIANT result) } ExtraFlags = leftExtraFlags; - /* Native VarDiv always returns a error when using any extra flags */ + /* Native VarDiv always returns an error when using extra flags */ if (ExtraFlags != 0) { hres = DISP_E_BADVARTYPE; @@ -4273,15 +4273,28 @@ HRESULT WINAPI VarAbs(LPVARIANT pVarIn, LPVARIANT pVarOut) { VARIANT varIn; HRESULT hRet = S_OK; + VARIANT temp; + + VariantInit(&temp); TRACE("(%p->(%s%s),%p)\n", pVarIn, debugstr_VT(pVarIn), debugstr_VF(pVarIn), pVarOut); + /* Handle VT_DISPATCH by storing and taking address of returned value */ + if ((V_VT(pVarIn) & VT_TYPEMASK) == VT_DISPATCH && ((V_VT(pVarIn) & ~VT_TYPEMASK) == 0)) + { + hRet = VARIANT_FetchDispatchValue(pVarIn, &temp); + if (FAILED(hRet)) goto VarAbs_Exit; + pVarIn = &temp; + } + if (V_ISARRAY(pVarIn) || V_VT(pVarIn) == VT_UNKNOWN || V_VT(pVarIn) == VT_DISPATCH || V_VT(pVarIn) == VT_RECORD || V_VT(pVarIn) == VT_ERROR) - return DISP_E_TYPEMISMATCH; - + { + hRet = DISP_E_TYPEMISMATCH; + goto VarAbs_Exit; + } *pVarOut = *pVarIn; /* Shallow copy the value, and invert it if needed */ #define ABS_CASE(typ,min) \ @@ -4331,6 +4344,8 @@ HRESULT WINAPI VarAbs(LPVARIANT pVarIn, LPVARIANT pVarOut) hRet = DISP_E_BADVARTYPE; } +VarAbs_Exit: + VariantClear(&temp); return hRet; } @@ -4362,10 +4377,20 @@ HRESULT WINAPI VarAbs(LPVARIANT pVarIn, LPVARIANT pVarOut) HRESULT WINAPI VarFix(LPVARIANT pVarIn, LPVARIANT pVarOut) { HRESULT hRet = S_OK; + VARIANT temp; + + VariantInit(&temp); TRACE("(%p->(%s%s),%p)\n", pVarIn, debugstr_VT(pVarIn), debugstr_VF(pVarIn), pVarOut); + /* Handle VT_DISPATCH by storing and taking address of returned value */ + if ((V_VT(pVarIn) & VT_TYPEMASK) == VT_DISPATCH && ((V_VT(pVarIn) & ~VT_TYPEMASK) == 0)) + { + hRet = VARIANT_FetchDispatchValue(pVarIn, &temp); + if (FAILED(hRet)) goto VarFix_Exit; + pVarIn = &temp; + } V_VT(pVarOut) = V_VT(pVarIn); switch (V_VT(pVarIn)) @@ -4423,8 +4448,10 @@ HRESULT WINAPI VarFix(LPVARIANT pVarIn, LPVARIANT pVarOut) else hRet = DISP_E_TYPEMISMATCH; } +VarFix_Exit: if (FAILED(hRet)) V_VT(pVarOut) = VT_EMPTY; + VariantClear(&temp); return hRet; } @@ -4457,10 +4484,20 @@ HRESULT WINAPI VarFix(LPVARIANT pVarIn, LPVARIANT pVarOut) HRESULT WINAPI VarInt(LPVARIANT pVarIn, LPVARIANT pVarOut) { HRESULT hRet = S_OK; + VARIANT temp; + + VariantInit(&temp); TRACE("(%p->(%s%s),%p)\n", pVarIn, debugstr_VT(pVarIn), debugstr_VF(pVarIn), pVarOut); + /* Handle VT_DISPATCH by storing and taking address of returned value */ + if ((V_VT(pVarIn) & VT_TYPEMASK) == VT_DISPATCH && ((V_VT(pVarIn) & ~VT_TYPEMASK) == 0)) + { + hRet = VARIANT_FetchDispatchValue(pVarIn, &temp); + if (FAILED(hRet)) goto VarInt_Exit; + pVarIn = &temp; + } V_VT(pVarOut) = V_VT(pVarIn); switch (V_VT(pVarIn)) @@ -4484,8 +4521,10 @@ HRESULT WINAPI VarInt(LPVARIANT pVarIn, LPVARIANT pVarOut) hRet = VarDecInt(&V_DECIMAL(pVarIn), &V_DECIMAL(pVarOut)); break; default: - return VarFix(pVarIn, pVarOut); + hRet = VarFix(pVarIn, pVarOut); } +VarInt_Exit: + VariantClear(&temp); return hRet; } @@ -4758,10 +4797,20 @@ HRESULT WINAPI VarEqv(LPVARIANT pVarLeft, LPVARIANT pVarRight, LPVARIANT pVarOut HRESULT WINAPI VarNeg(LPVARIANT pVarIn, LPVARIANT pVarOut) { HRESULT hRet = S_OK; + VARIANT temp; + + VariantInit(&temp); TRACE("(%p->(%s%s),%p)\n", pVarIn, debugstr_VT(pVarIn), debugstr_VF(pVarIn), pVarOut); + /* Handle VT_DISPATCH by storing and taking address of returned value */ + if ((V_VT(pVarIn) & VT_TYPEMASK) == VT_DISPATCH && ((V_VT(pVarIn) & ~VT_TYPEMASK) == 0)) + { + hRet = VARIANT_FetchDispatchValue(pVarIn, &temp); + if (FAILED(hRet)) goto VarNeg_Exit; + pVarIn = &temp; + } V_VT(pVarOut) = V_VT(pVarIn); switch (V_VT(pVarIn)) @@ -4833,8 +4882,10 @@ HRESULT WINAPI VarNeg(LPVARIANT pVarIn, LPVARIANT pVarOut) else hRet = DISP_E_TYPEMISMATCH; } +VarNeg_Exit: if (FAILED(hRet)) V_VT(pVarOut) = VT_EMPTY; + VariantClear(&temp); return hRet; } @@ -4876,10 +4927,21 @@ HRESULT WINAPI VarNot(LPVARIANT pVarIn, LPVARIANT pVarOut) { VARIANT varIn; HRESULT hRet = S_OK; + VARIANT temp; + + VariantInit(&temp); TRACE("(%p->(%s%s),%p)\n", pVarIn, debugstr_VT(pVarIn), debugstr_VF(pVarIn), pVarOut); + /* Handle VT_DISPATCH by storing and taking address of returned value */ + if ((V_VT(pVarIn) & VT_TYPEMASK) == VT_DISPATCH && ((V_VT(pVarIn) & ~VT_TYPEMASK) == 0)) + { + hRet = VARIANT_FetchDispatchValue(pVarIn, &temp); + if (FAILED(hRet)) goto VarNot_Exit; + pVarIn = &temp; + } + V_VT(pVarOut) = V_VT(pVarIn); switch (V_VT(pVarIn)) @@ -4951,8 +5013,10 @@ HRESULT WINAPI VarNot(LPVARIANT pVarIn, LPVARIANT pVarOut) else hRet = DISP_E_TYPEMISMATCH; } +VarNot_Exit: if (FAILED(hRet)) V_VT(pVarOut) = VT_EMPTY; + VariantClear(&temp); return hRet; } @@ -4981,9 +5045,20 @@ HRESULT WINAPI VarRound(LPVARIANT pVarIn, int deci, LPVARIANT pVarOut) VARIANT varIn; HRESULT hRet = S_OK; float factor; + VARIANT temp; + + VariantInit(&temp); TRACE("(%p->(%s%s),%d)\n", pVarIn, debugstr_VT(pVarIn), debugstr_VF(pVarIn), deci); + /* Handle VT_DISPATCH by storing and taking address of returned value */ + if ((V_VT(pVarIn) & VT_TYPEMASK) == VT_DISPATCH && ((V_VT(pVarIn) & ~VT_TYPEMASK) == 0)) + { + hRet = VARIANT_FetchDispatchValue(pVarIn, &temp); + if (FAILED(hRet)) goto VarRound_Exit; + pVarIn = &temp; + } + switch (V_VT(pVarIn)) { /* cases that fail on windows */ @@ -5074,9 +5149,10 @@ HRESULT WINAPI VarRound(LPVARIANT pVarIn, int deci, LPVARIANT pVarOut) V_VT(pVarIn) & VT_TYPEMASK, deci); hRet = DISP_E_BADVARTYPE; } - +VarRound_Exit: if (FAILED(hRet)) V_VT(pVarOut) = VT_EMPTY; + VariantClear(&temp); TRACE("returning 0x%08x (%s%s),%f\n", hRet, debugstr_VT(pVarOut), debugstr_VF(pVarOut), (V_VT(pVarOut) == VT_R4) ? V_R4(pVarOut) : @@ -5131,7 +5207,7 @@ HRESULT WINAPI VarIdiv(LPVARIANT left, LPVARIANT right, LPVARIANT result) } ExtraFlags = leftExtraFlags; - /* Native VarIdiv always returns a error when using any extra + /* Native VarIdiv always returns an error when using extra * flags or if the variant combination is I8 and INT. */ if ((leftvt == VT_I8 && rightvt == VT_INT) || @@ -5543,7 +5619,7 @@ HRESULT WINAPI VarPow(LPVARIANT left, LPVARIANT right, LPVARIANT result) } ExtraFlags = leftExtraFlags; - /* Native VarPow always returns a error when using any extra flags */ + /* Native VarPow always returns an error when using extra flags */ if (ExtraFlags != 0) { hr = DISP_E_BADVARTYPE; @@ -5659,7 +5735,7 @@ HRESULT WINAPI VarImp(LPVARIANT left, LPVARIANT right, LPVARIANT result) } ExtraFlags = leftExtraFlags; - /* Native VarImp always returns a error when using any extra + /* Native VarImp always returns an error when using extra * flags or if the variants are I8 and INT. */ if ((leftvt == VT_I8 && rightvt == VT_INT) || diff --git a/reactos/dll/win32/oleaut32/vartype.c b/reactos/dll/win32/oleaut32/vartype.c index fd4e56e3973..f3da2819e7e 100644 --- a/reactos/dll/win32/oleaut32/vartype.c +++ b/reactos/dll/win32/oleaut32/vartype.c @@ -3523,7 +3523,6 @@ HRESULT WINAPI VarCyFromR8(double dblIn, CY* pCyOut) if (result_fpstatus & 0x9) /* Overflow | Invalid */ return DISP_E_OVERFLOW; - return S_OK; #else /* This version produces slightly different results for boundary cases */ if (dblIn < -922337203685477.5807 || dblIn >= 922337203685477.5807) @@ -7425,7 +7424,7 @@ HRESULT WINAPI VarDateFromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, DATE* pd /* Parse the string into our structure */ while (*strIn) { - if (dp.dwCount > 6) + if (dp.dwCount >= 6) break; if (isdigitW(*strIn))