Author: fireball Date: Mon Mar 27 20:44:53 2006 New Revision: 21399
URL: http://svn.reactos.ru/svn/reactos?rev=21399&view=rev Log: - Sync oleaut32.dll to Wine-0.9.10 - Change related header files
Added: trunk/reactos/dll/win32/oleaut32/oleaut32_Tr.rc - copied unchanged from r21360, vendor/wine/dlls/oleaut32/current/oleaut32_Tr.rc Modified: trunk/reactos/dll/win32/oleaut32/connpt.c trunk/reactos/dll/win32/oleaut32/hash.c trunk/reactos/dll/win32/oleaut32/oleaut.c trunk/reactos/dll/win32/oleaut32/oleaut32.rc trunk/reactos/dll/win32/oleaut32/oleaut32.spec trunk/reactos/dll/win32/oleaut32/olefont.c trunk/reactos/dll/win32/oleaut32/olepicture.c trunk/reactos/dll/win32/oleaut32/tmarshal.c trunk/reactos/dll/win32/oleaut32/typelib.c trunk/reactos/dll/win32/oleaut32/usrmarshal.c trunk/reactos/dll/win32/oleaut32/varformat.c trunk/reactos/dll/win32/oleaut32/variant.c trunk/reactos/dll/win32/oleaut32/variant.h trunk/reactos/dll/win32/oleaut32/vartype.c trunk/reactos/include/oaidl.h trunk/reactos/include/ocidl.h trunk/reactos/include/olectl.h trunk/reactos/include/olectlid.h
Modified: trunk/reactos/dll/win32/oleaut32/connpt.c URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/dll/win32/oleaut32/connpt.c?... ============================================================================== --- trunk/reactos/dll/win32/oleaut32/connpt.c (original) +++ trunk/reactos/dll/win32/oleaut32/connpt.c Mon Mar 27 20:44:53 2006 @@ -160,14 +160,10 @@ /* * Compare the riid with the interface IDs implemented by this object. */ - if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0) - { + if (IsEqualIID(&IID_IUnknown, riid)) *ppvObject = (IConnectionPoint*)This; - } - else if (memcmp(&IID_IConnectionPoint, riid, sizeof(IID_IConnectionPoint)) == 0) - { + else if (IsEqualIID(&IID_IConnectionPoint, riid)) *ppvObject = (IConnectionPoint*)This; - }
/* * Check that we obtained an interface. @@ -433,14 +429,10 @@ /* * Compare the riid with the interface IDs implemented by this object. */ - if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0) - { + if (IsEqualIID(&IID_IUnknown, riid)) *ppvObject = (IEnumConnections*)This; - } - else if (memcmp(&IID_IEnumConnections, riid, sizeof(IID_IEnumConnections)) == 0) - { + else if (IsEqualIID(&IID_IEnumConnections, riid)) *ppvObject = (IEnumConnections*)This; - }
/* * Check that we obtained an interface.
Modified: trunk/reactos/dll/win32/oleaut32/hash.c URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/dll/win32/oleaut32/hash.c?re... ============================================================================== --- trunk/reactos/dll/win32/oleaut32/hash.c (original) +++ trunk/reactos/dll/win32/oleaut32/hash.c Mon Mar 27 20:44:53 2006 @@ -539,8 +539,8 @@ case LANG_TATAR: case LANG_TELUGU: case LANG_THAI: case LANG_UKRAINIAN: case LANG_URDU: case LANG_UZBEK: case LANG_VIETNAMESE: case LANG_GAELIC: case LANG_MALTESE: - case LANG_MAORI: case LANG_RHAETO_ROMANCE: - case LANG_SAAMI: case LANG_SORBIAN: case LANG_SUTU: + case LANG_MAORI: case LANG_ROMANSH: case LANG_IRISH: + case LANG_SAMI: case LANG_UPPER_SORBIAN: case LANG_SUTU: case LANG_TSONGA: case LANG_TSWANA: case LANG_VENDA: case LANG_XHOSA: case LANG_ZULU: case LANG_ESPERANTO: case LANG_WALON: case LANG_CORNISH: case LANG_WELSH:
Modified: trunk/reactos/dll/win32/oleaut32/oleaut.c URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/dll/win32/oleaut32/oleaut.c?... ============================================================================== --- trunk/reactos/dll/win32/oleaut32/oleaut.c (original) +++ trunk/reactos/dll/win32/oleaut32/oleaut.c Mon Mar 27 20:44:53 2006 @@ -446,8 +446,8 @@ BSTR_bCache = FALSE; }
-static WCHAR _delimiter[2] = {'!',0}; /* default delimiter apparently */ -static WCHAR *pdelimiter = &_delimiter[0]; +static const WCHAR _delimiter[2] = {'!',0}; /* default delimiter apparently */ +static const WCHAR *pdelimiter = &_delimiter[0];
/*********************************************************************** * RegisterActiveObject (OLEAUT32.33)
Modified: trunk/reactos/dll/win32/oleaut32/oleaut32.rc URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/dll/win32/oleaut32/oleaut32.... ============================================================================== --- trunk/reactos/dll/win32/oleaut32/oleaut32.rc (original) +++ trunk/reactos/dll/win32/oleaut32/oleaut32.rc Mon Mar 27 20:44:53 2006 @@ -42,6 +42,7 @@ #include "oleaut32_Ru.rc" #include "oleaut32_Sv.rc" #include "oleaut32_Th.rc" +#include "oleaut32_Tr.rc" #include "oleaut32_Uk.rc"
/*
Modified: trunk/reactos/dll/win32/oleaut32/oleaut32.spec URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/dll/win32/oleaut32/oleaut32.... ============================================================================== --- trunk/reactos/dll/win32/oleaut32/oleaut32.spec (original) +++ trunk/reactos/dll/win32/oleaut32/oleaut32.spec Mon Mar 27 20:44:53 2006 @@ -111,7 +111,7 @@ 112 stdcall VarBstrFromR8(double long long ptr) 113 stdcall VarBstrFromCy(double long long ptr) 114 stdcall VarBstrFromDate(double long long ptr) -115 stub VarBstrFromDisp +115 stdcall VarBstrFromDisp(ptr long long ptr) 116 stdcall VarBstrFromBool(long long long ptr) 117 stdcall VarFormatPercent(ptr long long long long long ptr) 118 stdcall VarBoolFromUI1(long ptr) @@ -285,10 +285,10 @@ 288 stdcall VARIANT_UserMarshal(ptr ptr ptr) 289 stdcall VARIANT_UserUnmarshal(ptr ptr ptr) 290 stdcall VARIANT_UserFree(ptr ptr) -291 stub LPSAFEARRAY_UserSize -292 stub LPSAFEARRAY_UserMarshal -293 stub LPSAFEARRAY_UserUnmarshal -294 stub LPSAFEARRAY_UserFree +291 stdcall LPSAFEARRAY_UserSize(ptr long ptr) +292 stdcall LPSAFEARRAY_UserMarshal(ptr ptr ptr) +293 stdcall LPSAFEARRAY_UserUnmarshal(ptr ptr ptr) +294 stdcall LPSAFEARRAY_UserFree(ptr ptr) 295 stub LPSAFEARRAY_Size 296 stub LPSAFEARRAY_Marshal 297 stub LPSAFEARRAY_Unmarshal
Modified: trunk/reactos/dll/win32/oleaut32/olefont.c URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/dll/win32/oleaut32/olefont.c... ============================================================================== --- trunk/reactos/dll/win32/oleaut32/olefont.c (original) +++ trunk/reactos/dll/win32/oleaut32/olefont.c Mon Mar 27 20:44:53 2006 @@ -40,6 +40,7 @@ #include "olectl.h" #include "wine/debug.h" #include "connpt.h" /* for CreateConnectionPoint */ +#include "oaidl.h"
WINE_DEFAULT_DEBUG_CHANNEL(ole);
@@ -95,7 +96,8 @@ long cyLogical; long cyHimetric;
- IConnectionPoint *pCP; + IConnectionPoint *pPropertyNotifyCP; + IConnectionPoint *pFontEventsCP; };
/* @@ -378,24 +380,74 @@ */ static void OLEFont_SendNotify(OLEFontImpl* this, DISPID dispID) { + static const WCHAR wszName[] = {'N','a','m','e',0}; + static const WCHAR wszSize[] = {'S','i','z','e',0}; + static const WCHAR wszBold[] = {'B','o','l','d',0}; + static const WCHAR wszItalic[] = {'I','t','a','l','i','c',0}; + static const WCHAR wszUnder[] = {'U','n','d','e','r','l','i','n','e',0}; + static const WCHAR wszStrike[] = {'S','t','r','i','k','e','t','h','r','o','u','g','h',0}; + static const WCHAR wszWeight[] = {'W','e','i','g','h','t',0}; + static const WCHAR wszCharset[] = {'C','h','a','r','s','s','e','t',0}; + static const LPCWSTR dispid_mapping[] = + { + wszName, + NULL, + wszSize, + wszBold, + wszItalic, + wszUnder, + wszStrike, + wszWeight, + wszCharset + }; + IEnumConnections *pEnum; CONNECTDATA CD; HRESULT hres;
- hres = IConnectionPoint_EnumConnections(this->pCP, &pEnum); - if (FAILED(hres)) /* When we have 0 connections. */ - return; - - while(IEnumConnections_Next(pEnum, 1, &CD, NULL) == S_OK) { - IPropertyNotifySink *sink; - - IUnknown_QueryInterface(CD.pUnk, &IID_IPropertyNotifySink, (LPVOID)&sink); - IPropertyNotifySink_OnChanged(sink, dispID); - IPropertyNotifySink_Release(sink); - IUnknown_Release(CD.pUnk); + hres = IConnectionPoint_EnumConnections(this->pPropertyNotifyCP, &pEnum); + if (SUCCEEDED(hres)) + { + while(IEnumConnections_Next(pEnum, 1, &CD, NULL) == S_OK) { + IPropertyNotifySink *sink; + + IUnknown_QueryInterface(CD.pUnk, &IID_IPropertyNotifySink, (LPVOID)&sink); + IPropertyNotifySink_OnChanged(sink, dispID); + IPropertyNotifySink_Release(sink); + IUnknown_Release(CD.pUnk); + } + IEnumConnections_Release(pEnum); } - IEnumConnections_Release(pEnum); - return; + + hres = IConnectionPoint_EnumConnections(this->pFontEventsCP, &pEnum); + if (SUCCEEDED(hres)) + { + DISPPARAMS dispparams; + VARIANTARG vararg; + + VariantInit(&vararg); + V_VT(&vararg) = VT_BSTR; + V_BSTR(&vararg) = SysAllocString(dispid_mapping[dispID]); + + dispparams.cArgs = 1; + dispparams.cNamedArgs = 0; + dispparams.rgdispidNamedArgs = NULL; + dispparams.rgvarg = &vararg; + + while(IEnumConnections_Next(pEnum, 1, &CD, NULL) == S_OK) { + IFontEventsDisp *disp; + + IUnknown_QueryInterface(CD.pUnk, &IID_IFontEventsDisp, (LPVOID)&disp); + IDispatch_Invoke(disp, DISPID_FONT_CHANGED, &IID_NULL, + LOCALE_NEUTRAL, INVOKE_FUNC, &dispparams, NULL, + NULL, NULL); + + IDispatch_Release(disp); + IUnknown_Release(CD.pUnk); + } + VariantClear(&vararg); + IEnumConnections_Release(pEnum); + } }
/************************************************************************ @@ -459,7 +511,18 @@ newObject->fontLock = 0; newObject->cyLogical = 72L; newObject->cyHimetric = 2540L; - CreateConnectionPoint((IUnknown*)newObject, &IID_IPropertyNotifySink, &newObject->pCP); + newObject->pPropertyNotifyCP = NULL; + newObject->pFontEventsCP = NULL; + + CreateConnectionPoint((IUnknown*)newObject, &IID_IPropertyNotifySink, &newObject->pPropertyNotifyCP); + CreateConnectionPoint((IUnknown*)newObject, &IID_IFontEventsDisp, &newObject->pFontEventsCP); + + if (!newObject->pPropertyNotifyCP || !newObject->pFontEventsCP) + { + OLEFontImpl_Destroy(newObject); + return NULL; + } + TRACE("returning %p\n", newObject); return newObject; } @@ -479,6 +542,11 @@
if (fontDesc->gdiFont!=0) DeleteObject(fontDesc->gdiFont); + + if (fontDesc->pPropertyNotifyCP) + IConnectionPoint_Release(fontDesc->pPropertyNotifyCP); + if (fontDesc->pFontEventsCP) + IConnectionPoint_Release(fontDesc->pFontEventsCP);
HeapFree(GetProcessHeap(), 0, fontDesc); } @@ -1041,6 +1109,17 @@
newObject->gdiFont = CreateFontIndirectW(&logFont);
+ /* create new connection points */ + newObject->pPropertyNotifyCP = NULL; + newObject->pFontEventsCP = NULL; + CreateConnectionPoint((IUnknown*)newObject, &IID_IPropertyNotifySink, &newObject->pPropertyNotifyCP); + CreateConnectionPoint((IUnknown*)newObject, &IID_IFontEventsDisp, &newObject->pFontEventsCP); + + if (!newObject->pPropertyNotifyCP || !newObject->pFontEventsCP) + { + OLEFontImpl_Destroy(newObject); + return E_OUTOFMEMORY; + }
/* The cloned object starts with a reference count of 1 */ newObject->ref = 1; @@ -1839,12 +1918,17 @@ OLEFontImpl *this = impl_from_IConnectionPointContainer(iface); TRACE("(%p)->(%s, %p): stub\n", this, debugstr_guid(riid), ppCp);
- if(memcmp(riid, &IID_IPropertyNotifySink, sizeof(IID_IPropertyNotifySink)) == 0) { - return IConnectionPoint_QueryInterface(this->pCP, &IID_IConnectionPoint, - (LPVOID)ppCp); + if(IsEqualIID(riid, &IID_IPropertyNotifySink)) { + return IConnectionPoint_QueryInterface(this->pPropertyNotifyCP, + &IID_IConnectionPoint, + (LPVOID)ppCp); + } else if(IsEqualIID(riid, &IID_IFontEventsDisp)) { + return IConnectionPoint_QueryInterface(this->pFontEventsCP, + &IID_IConnectionPoint, + (LPVOID)ppCp); } else { - FIXME("Tried to find connection point on %s\n", debugstr_guid(riid)); - return E_NOINTERFACE; + FIXME("no connection point for %s\n", debugstr_guid(riid)); + return CONNECT_E_NOCONNECTION; } }
Modified: trunk/reactos/dll/win32/oleaut32/olepicture.c URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/dll/win32/oleaut32/olepictur... ============================================================================== --- trunk/reactos/dll/win32/oleaut32/olepicture.c (original) +++ trunk/reactos/dll/win32/oleaut32/olepicture.c Mon Mar 27 20:44:53 2006 @@ -279,7 +279,13 @@ newObject->lpvtblIPersistStream = &OLEPictureImpl_IPersistStream_VTable; newObject->lpvtblIConnectionPointContainer = &OLEPictureImpl_IConnectionPointContainer_VTable;
+ newObject->pCP = NULL; CreateConnectionPoint((IUnknown*)newObject,&IID_IPropertyNotifySink,&newObject->pCP); + if (!newObject->pCP) + { + HeapFree(GetProcessHeap(), 0, newObject); + return NULL; + }
/* * Start with one reference count. The caller of this function @@ -348,6 +354,9 @@ static void OLEPictureImpl_Destroy(OLEPictureImpl* Obj) { TRACE("(%p)\n", Obj); + + if (Obj->pCP) + IConnectionPoint_Release(Obj->pCP);
if(Obj->fOwn) { /* We need to destroy the picture */ switch(Obj->desc.picType) { @@ -377,7 +386,43 @@ HeapFree(GetProcessHeap(), 0, Obj); }
-static ULONG WINAPI OLEPictureImpl_AddRef(IPicture* iface); + +/************************************************************************ + * OLEPictureImpl_AddRef (IUnknown) + * + * See Windows documentation for more details on IUnknown methods. + */ +static ULONG WINAPI OLEPictureImpl_AddRef( + IPicture* iface) +{ + OLEPictureImpl *This = (OLEPictureImpl *)iface; + ULONG refCount = InterlockedIncrement(&This->ref); + + TRACE("(%p)->(ref before=%ld)\n", This, refCount - 1); + + return refCount; +} + +/************************************************************************ + * OLEPictureImpl_Release (IUnknown) + * + * See Windows documentation for more details on IUnknown methods. + */ +static ULONG WINAPI OLEPictureImpl_Release( + IPicture* iface) +{ + OLEPictureImpl *This = (OLEPictureImpl *)iface; + ULONG refCount = InterlockedDecrement(&This->ref); + + TRACE("(%p)->(ref before=%ld)\n", This, refCount + 1); + + /* + * If the reference count goes down to 0, perform suicide. + */ + if (!refCount) OLEPictureImpl_Destroy(This); + + return refCount; +}
/************************************************************************ * OLEPictureImpl_QueryInterface (IUnknown) @@ -447,6 +492,7 @@
return S_OK; } + /*********************************************************************** * OLEPicture_SendNotify (internal) * @@ -471,44 +517,6 @@ IEnumConnections_Release(pEnum); return; } - -/************************************************************************ - * OLEPictureImpl_AddRef (IUnknown) - * - * See Windows documentation for more details on IUnknown methods. - */ -static ULONG WINAPI OLEPictureImpl_AddRef( - IPicture* iface) -{ - OLEPictureImpl *This = (OLEPictureImpl *)iface; - ULONG refCount = InterlockedIncrement(&This->ref); - - TRACE("(%p)->(ref before=%ld)\n", This, refCount - 1); - - return refCount; -} - -/************************************************************************ - * OLEPictureImpl_Release (IUnknown) - * - * See Windows documentation for more details on IUnknown methods. - */ -static ULONG WINAPI OLEPictureImpl_Release( - IPicture* iface) -{ - OLEPictureImpl *This = (OLEPictureImpl *)iface; - ULONG refCount = InterlockedDecrement(&This->ref); - - TRACE("(%p)->(ref before=%ld)\n", This, refCount + 1); - - /* - * If the reference count goes down to 0, perform suicide. - */ - if (!refCount) OLEPictureImpl_Destroy(This); - - return refCount; -} -
/************************************************************************ * OLEPictureImpl_get_Handle @@ -820,7 +828,6 @@ /************************************************************************ * IConnectionPointContainer */ - static HRESULT WINAPI OLEPictureImpl_IConnectionPointContainer_QueryInterface( IConnectionPointContainer* iface, REFIID riid, @@ -869,12 +876,15 @@ *ppCP = NULL; if (IsEqualGUID(riid,&IID_IPropertyNotifySink)) return IConnectionPoint_QueryInterface(This->pCP,&IID_IConnectionPoint,(LPVOID)ppCP); - FIXME("tried to find connection point on %s?\n",debugstr_guid(riid)); - return 0x80040200; -} + FIXME("no connection point for %s\n",debugstr_guid(riid)); + return CONNECT_E_NOCONNECTION; +} + + /************************************************************************ * IPersistStream */ + /************************************************************************ * OLEPictureImpl_IPersistStream_QueryInterface (IUnknown) * @@ -1043,137 +1053,9 @@
#endif /* HAVE_GIF_LIB_H */
-/************************************************************************ - * OLEPictureImpl_IPersistStream_Load (IUnknown) - * - * Loads the binary data from the IStream. Starts at current position. - * There appears to be an 2 DWORD header: - * DWORD magic; - * DWORD len; - * - * Currently implemented: BITMAP, ICON, JPEG, GIF - */ -static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) { - HRESULT hr = E_FAIL; - BOOL headerisdata = FALSE; - BOOL statfailed = FALSE; - ULONG xread, toread; - BYTE *xbuf; - DWORD header[2]; - WORD magic; - STATSTG statstg; - OLEPictureImpl *This = impl_from_IPersistStream(iface); - - TRACE("(%p,%p)\n",This,pStm); - - /**************************************************************************************** - * Part 1: Load the data - */ - /* Sometimes we have a header, sometimes we don't. Apply some guesses to find - * out whether we do. - * - * UPDATE: the IStream can be mapped to a plain file instead of a stream in a - * compound file. This may explain most, if not all, of the cases of "no - * header", and the header validation should take this into account. - * At least in Visual Basic 6, resource streams, valid headers are - * header[0] == "lt\0\0", - * header[1] == length_of_stream. - * - * Also handle streams where we do not have a working "Stat" method by - * reading all data until the end of the stream. - */ - hr=IStream_Stat(pStm,&statstg,STATFLAG_NONAME); - if (hr) { - TRACE("stat failed with hres %lx, proceeding to read all data.\n",hr); - statfailed = TRUE; - /* we will read at least 8 byte ... just right below */ - statstg.cbSize.QuadPart = 8; - } - hr=IStream_Read(pStm,header,8,&xread); - if (hr || xread!=8) { - FIXME("Failure while reading picture header (hr is %lx, nread is %ld).\n",hr,xread); - return hr; - } - - headerisdata = FALSE; - xread = 0; - if (!memcmp(&(header[0]),"lt\0\0", 4) && (header[1] <= statstg.cbSize.QuadPart-8)) { - toread = header[1]; - } else { - if (!memcmp(&(header[0]), "GIF8", 4) || /* GIF header */ - !memcmp(&(header[0]), "BM", 2) || /* BMP header */ - !memcmp(&(header[0]), "\xff\xd8", 2) || /* JPEG header */ - (header[1] > statstg.cbSize.QuadPart)|| /* invalid size */ - (header[1]==0) - ) {/* Incorrect header, assume none. */ - headerisdata = TRUE; - toread = statstg.cbSize.QuadPart-8; - xread = 8; - } else { - FIXME("Unknown stream header magic: %08lx\n", header[0]); - toread = header[1]; - } - } - - if (statfailed) { /* we don't know the size ... read all we get */ - int sizeinc = 4096; - int origsize = sizeinc; - ULONG nread = 42; - - TRACE("Reading all data from stream.\n"); - xbuf = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, origsize); - if (headerisdata) - memcpy (xbuf, &header, 8); - while (1) { - while (xread < origsize) { - hr = IStream_Read(pStm,xbuf+xread,origsize-xread,&nread); - xread+=nread; - if (hr || !nread) - break; - } - if (!nread || hr) /* done, or error */ - break; - if (xread == origsize) { - origsize += sizeinc; - sizeinc = 2*sizeinc; /* exponential increase */ - xbuf = HeapReAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, xbuf, origsize); - } - } - if (hr) - TRACE("hr in no-stat loader case is %08lx\n", hr); - TRACE("loaded %ld bytes.\n", xread); - This->datalen = xread; - This->data = xbuf; - } else { - This->datalen = toread+(headerisdata?8:0); - xbuf = This->data = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, This->datalen); - - if (headerisdata) - memcpy (xbuf, &header, 8); - - while (xread < This->datalen) { - ULONG nread; - hr = IStream_Read(pStm,xbuf+xread,This->datalen-xread,&nread); - xread+=nread; - if (hr || !nread) - break; - } - if (xread != This->datalen) - FIXME("Could only read %ld of %d bytes out of stream?\n",xread,This->datalen); - } - if (This->datalen == 0) { /* Marks the "NONE" picture */ - This->desc.picType = PICTYPE_NONE; - return S_OK; - } - - - /**************************************************************************************** - * Part 2: Process the loaded data - */ - - magic = xbuf[0] + (xbuf[1]<<8); - switch (magic) { - case 0x4947: { /* GIF */ + +static HRESULT OLEPictureImpl_LoadGif(OLEPictureImpl *This, BYTE *xbuf, ULONG xread) +{ #ifdef HAVE_GIF_LIB_H struct gifdata gd; GifFileType *gif; @@ -1378,8 +1260,10 @@ FIXME("Trying to load GIF, but no support for libgif/libungif compiled in.\n"); return E_FAIL; #endif - } - case 0xd8ff: { /* JPEG */ +} + +static HRESULT OLEPictureImpl_LoadJpeg(OLEPictureImpl *This, BYTE *xbuf, ULONG xread) +{ #ifdef HAVE_JPEGLIB_H struct jpeg_decompress_struct jd; struct jpeg_error_mgr jerr; @@ -1475,15 +1359,16 @@ DeleteDC(hdcref); This->desc.picType = PICTYPE_BITMAP; OLEPictureImpl_SetBitmap(This); - hr = S_OK; HeapFree(GetProcessHeap(),0,bits); + return S_OK; #else ERR("Trying to load JPEG picture, but JPEG supported not compiled in.\n"); - hr = E_FAIL; + return E_FAIL; #endif - break; - } - case 0x4d42: { /* Bitmap */ +} + +static HRESULT OLEPictureImpl_LoadDIB(OLEPictureImpl *This, BYTE *xbuf, ULONG xread) +{ BITMAPFILEHEADER *bfh = (BITMAPFILEHEADER*)xbuf; BITMAPINFO *bi = (BITMAPINFO*)(bfh+1); HDC hdcref; @@ -1503,10 +1388,11 @@ DeleteDC(hdcref); This->desc.picType = PICTYPE_BITMAP; OLEPictureImpl_SetBitmap(This); - hr = S_OK; - break; - } - case 0x0000: { /* ICON , first word is dwReserved */ + return S_OK; +} + +static HRESULT OLEPictureImpl_LoadIcon(OLEPictureImpl *This, BYTE *xbuf, ULONG xread) +{ HICON hicon; CURSORICONFILEDIR *cifd = (CURSORICONFILEDIR*)xbuf; HDC hdcRef; @@ -1551,7 +1437,7 @@ ); if (!hicon) { FIXME("CreateIcon failed.\n"); - hr = E_FAIL; + return E_FAIL; } else { This->desc.picType = PICTYPE_ICON; This->desc.u.icon.hicon = hicon; @@ -1561,8 +1447,151 @@ This->himetricWidth =(cifd->idEntries[i].bWidth *2540)/GetDeviceCaps(hdcRef, LOGPIXELSX); This->himetricHeight=(cifd->idEntries[i].bHeight*2540)/GetDeviceCaps(hdcRef, LOGPIXELSY); DeleteDC(hdcRef); - hr = S_OK; + return S_OK; } +} + +/************************************************************************ + * OLEPictureImpl_IPersistStream_Load (IUnknown) + * + * Loads the binary data from the IStream. Starts at current position. + * There appears to be an 2 DWORD header: + * DWORD magic; + * DWORD len; + * + * Currently implemented: BITMAP, ICON, JPEG, GIF + */ +static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) { + HRESULT hr = E_FAIL; + BOOL headerisdata = FALSE; + BOOL statfailed = FALSE; + ULONG xread, toread; + BYTE *xbuf; + DWORD header[2]; + WORD magic; + STATSTG statstg; + OLEPictureImpl *This = impl_from_IPersistStream(iface); + + TRACE("(%p,%p)\n",This,pStm); + + /**************************************************************************************** + * Part 1: Load the data + */ + /* Sometimes we have a header, sometimes we don't. Apply some guesses to find + * out whether we do. + * + * UPDATE: the IStream can be mapped to a plain file instead of a stream in a + * compound file. This may explain most, if not all, of the cases of "no + * header", and the header validation should take this into account. + * At least in Visual Basic 6, resource streams, valid headers are + * header[0] == "lt\0\0", + * header[1] == length_of_stream. + * + * Also handle streams where we do not have a working "Stat" method by + * reading all data until the end of the stream. + */ + hr=IStream_Stat(pStm,&statstg,STATFLAG_NONAME); + if (hr) { + TRACE("stat failed with hres %lx, proceeding to read all data.\n",hr); + statfailed = TRUE; + /* we will read at least 8 byte ... just right below */ + statstg.cbSize.QuadPart = 8; + } + hr=IStream_Read(pStm,header,8,&xread); + if (hr || xread!=8) { + FIXME("Failure while reading picture header (hr is %lx, nread is %ld).\n",hr,xread); + return hr; + } + + headerisdata = FALSE; + xread = 0; + if (!memcmp(&(header[0]),"lt\0\0", 4) && (header[1] <= statstg.cbSize.QuadPart-8)) { + toread = header[1]; + } else { + if (!memcmp(&(header[0]), "GIF8", 4) || /* GIF header */ + !memcmp(&(header[0]), "BM", 2) || /* BMP header */ + !memcmp(&(header[0]), "\xff\xd8", 2) || /* JPEG header */ + (header[1] > statstg.cbSize.QuadPart)|| /* invalid size */ + (header[1]==0) + ) {/* Incorrect header, assume none. */ + headerisdata = TRUE; + toread = statstg.cbSize.QuadPart-8; + xread = 8; + } else { + FIXME("Unknown stream header magic: %08lx\n", header[0]); + toread = header[1]; + } + } + + if (statfailed) { /* we don't know the size ... read all we get */ + int sizeinc = 4096; + int origsize = sizeinc; + ULONG nread = 42; + + TRACE("Reading all data from stream.\n"); + xbuf = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, origsize); + if (headerisdata) + memcpy (xbuf, &header, 8); + while (1) { + while (xread < origsize) { + hr = IStream_Read(pStm,xbuf+xread,origsize-xread,&nread); + xread+=nread; + if (hr || !nread) + break; + } + if (!nread || hr) /* done, or error */ + break; + if (xread == origsize) { + origsize += sizeinc; + sizeinc = 2*sizeinc; /* exponential increase */ + xbuf = HeapReAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, xbuf, origsize); + } + } + if (hr) + TRACE("hr in no-stat loader case is %08lx\n", hr); + TRACE("loaded %ld bytes.\n", xread); + This->datalen = xread; + This->data = xbuf; + } else { + This->datalen = toread+(headerisdata?8:0); + xbuf = This->data = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, This->datalen); + + if (headerisdata) + memcpy (xbuf, &header, 8); + + while (xread < This->datalen) { + ULONG nread; + hr = IStream_Read(pStm,xbuf+xread,This->datalen-xread,&nread); + xread+=nread; + if (hr || !nread) + break; + } + if (xread != This->datalen) + FIXME("Could only read %ld of %d bytes out of stream?\n",xread,This->datalen); + } + if (This->datalen == 0) { /* Marks the "NONE" picture */ + This->desc.picType = PICTYPE_NONE; + return S_OK; + } + + + /**************************************************************************************** + * Part 2: Process the loaded data + */ + + magic = xbuf[0] + (xbuf[1]<<8); + switch (magic) { + case 0x4947: /* GIF */ + hr = OLEPictureImpl_LoadGif(This, xbuf, xread); + break; + case 0xd8ff: /* JPEG */ + hr = OLEPictureImpl_LoadJpeg(This, xbuf, xread); + break; + case 0x4d42: /* Bitmap */ + hr = OLEPictureImpl_LoadDIB(This, xbuf, xread); + break; + case 0x0000: { /* ICON , first word is dwReserved */ + hr = OLEPictureImpl_LoadIcon(This, xbuf, xread); break; } default: @@ -1587,8 +1616,223 @@ return hr; }
-static int serializeIcon(HICON hIcon, void ** ppBuffer, unsigned int * pLength); -static int serializeBMP(HBITMAP hBitmap, void ** ppBuffer, unsigned int * pLength); +static int serializeBMP(HBITMAP hBitmap, void ** ppBuffer, unsigned int * pLength) +{ + int iSuccess = 0; + HDC hDC; + BITMAPINFO * pInfoBitmap; + int iNumPaletteEntries; + unsigned char * pPixelData; + BITMAPFILEHEADER * pFileHeader; + BITMAPINFO * pInfoHeader; + + pInfoBitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)); + + /* Find out bitmap size and padded length */ + hDC = GetDC(0); + pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader); + GetDIBits(hDC, hBitmap, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS); + + /* Fetch bitmap palette & pixel data */ + + pPixelData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, pInfoBitmap->bmiHeader.biSizeImage); + GetDIBits(hDC, hBitmap, 0, pInfoBitmap->bmiHeader.biHeight, pPixelData, pInfoBitmap, DIB_RGB_COLORS); + + /* Calculate the total length required for the BMP data */ + if (pInfoBitmap->bmiHeader.biClrUsed != 0) { + iNumPaletteEntries = pInfoBitmap->bmiHeader.biClrUsed; + if (iNumPaletteEntries > 256) iNumPaletteEntries = 256; + } else { + if (pInfoBitmap->bmiHeader.biBitCount <= 8) + iNumPaletteEntries = 1 << pInfoBitmap->bmiHeader.biBitCount; + else + iNumPaletteEntries = 0; + } + *pLength = + sizeof(BITMAPFILEHEADER) + + sizeof(BITMAPINFOHEADER) + + iNumPaletteEntries * sizeof(RGBQUAD) + + pInfoBitmap->bmiHeader.biSizeImage; + *ppBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *pLength); + + /* Fill the BITMAPFILEHEADER */ + pFileHeader = (BITMAPFILEHEADER *)(*ppBuffer); + pFileHeader->bfType = 0x4d42; + pFileHeader->bfSize = *pLength; + pFileHeader->bfOffBits = + sizeof(BITMAPFILEHEADER) + + sizeof(BITMAPINFOHEADER) + + iNumPaletteEntries * sizeof(RGBQUAD); + + /* Fill the BITMAPINFOHEADER and the palette data */ + pInfoHeader = (BITMAPINFO *)((unsigned char *)(*ppBuffer) + sizeof(BITMAPFILEHEADER)); + memcpy(pInfoHeader, pInfoBitmap, sizeof(BITMAPINFOHEADER) + iNumPaletteEntries * sizeof(RGBQUAD)); + memcpy( + (unsigned char *)(*ppBuffer) + + sizeof(BITMAPFILEHEADER) + + sizeof(BITMAPINFOHEADER) + + iNumPaletteEntries * sizeof(RGBQUAD), + pPixelData, pInfoBitmap->bmiHeader.biSizeImage); + iSuccess = 1; + + HeapFree(GetProcessHeap(), 0, pPixelData); + HeapFree(GetProcessHeap(), 0, pInfoBitmap); + return iSuccess; +} + +static int serializeIcon(HICON hIcon, void ** ppBuffer, unsigned int * pLength) +{ + ICONINFO infoIcon; + int iSuccess = 0; + + *ppBuffer = NULL; *pLength = 0; + if (GetIconInfo(hIcon, &infoIcon)) { + HDC hDC; + BITMAPINFO * pInfoBitmap; + unsigned char * pIconData = NULL; + unsigned int iDataSize = 0; + + pInfoBitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)); + + /* Find out icon size */ + hDC = GetDC(0); + pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader); + GetDIBits(hDC, infoIcon.hbmColor, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS); + if (1) { + /* Auxiliary pointers */ + CURSORICONFILEDIR * pIconDir; + CURSORICONFILEDIRENTRY * pIconEntry; + BITMAPINFOHEADER * pIconBitmapHeader; + unsigned int iOffsetPalette; + unsigned int iOffsetColorData; + unsigned int iOffsetMaskData; + + unsigned int iLengthScanLineColor; + unsigned int iLengthScanLineMask; + unsigned int iNumEntriesPalette; + + iLengthScanLineMask = ((pInfoBitmap->bmiHeader.biWidth + 31) >> 5) << 2; + iLengthScanLineColor = ((pInfoBitmap->bmiHeader.biWidth * pInfoBitmap->bmiHeader.biBitCount + 31) >> 5) << 2; +/* + FIXME("DEBUG: bitmap size is %d x %d\n", + pInfoBitmap->bmiHeader.biWidth, + pInfoBitmap->bmiHeader.biHeight); + FIXME("DEBUG: bitmap bpp is %d\n", + pInfoBitmap->bmiHeader.biBitCount); + FIXME("DEBUG: bitmap nplanes is %d\n", + pInfoBitmap->bmiHeader.biPlanes); + FIXME("DEBUG: bitmap biSizeImage is %lu\n", + pInfoBitmap->bmiHeader.biSizeImage); +*/ + /* Let's start with one CURSORICONFILEDIR and one CURSORICONFILEDIRENTRY */ + iDataSize += 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY) + sizeof(BITMAPINFOHEADER); + pIconData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, iDataSize); + + /* Fill out the CURSORICONFILEDIR */ + pIconDir = (CURSORICONFILEDIR *)pIconData; + pIconDir->idType = 1; + pIconDir->idCount = 1; + + /* Fill out the CURSORICONFILEDIRENTRY */ + pIconEntry = (CURSORICONFILEDIRENTRY *)(pIconData + 3 * sizeof(WORD)); + pIconEntry->bWidth = (unsigned char)pInfoBitmap->bmiHeader.biWidth; + pIconEntry->bHeight = (unsigned char)pInfoBitmap->bmiHeader.biHeight; + pIconEntry->bColorCount = + (pInfoBitmap->bmiHeader.biBitCount < 8) + ? 1 << pInfoBitmap->bmiHeader.biBitCount + : 0; + pIconEntry->xHotspot = pInfoBitmap->bmiHeader.biPlanes; + pIconEntry->yHotspot = pInfoBitmap->bmiHeader.biBitCount; + pIconEntry->dwDIBSize = 0; + pIconEntry->dwDIBOffset = 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY); + + /* Fill out the BITMAPINFOHEADER */ + pIconBitmapHeader = (BITMAPINFOHEADER *)(pIconData + 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY)); + memcpy(pIconBitmapHeader, &pInfoBitmap->bmiHeader, sizeof(BITMAPINFOHEADER)); + + /* Find out whether a palette exists for the bitmap */ + if ( (pInfoBitmap->bmiHeader.biBitCount == 16 && pInfoBitmap->bmiHeader.biCompression == BI_RGB) + || (pInfoBitmap->bmiHeader.biBitCount == 24) + || (pInfoBitmap->bmiHeader.biBitCount == 32 && pInfoBitmap->bmiHeader.biCompression == BI_RGB)) { + iNumEntriesPalette = pInfoBitmap->bmiHeader.biClrUsed; + if (iNumEntriesPalette > 256) iNumEntriesPalette = 256; + } else if ((pInfoBitmap->bmiHeader.biBitCount == 16 || pInfoBitmap->bmiHeader.biBitCount == 32) + && pInfoBitmap->bmiHeader.biCompression == BI_BITFIELDS) { + iNumEntriesPalette = 3; + } else if (pInfoBitmap->bmiHeader.biBitCount <= 8) { + iNumEntriesPalette = 1 << pInfoBitmap->bmiHeader.biBitCount; + } else { + iNumEntriesPalette = 0; + } + + /* Add bitmap size and header size to icon data size. */ + iOffsetPalette = iDataSize; + iDataSize += iNumEntriesPalette * sizeof(DWORD); + iOffsetColorData = iDataSize; + iDataSize += pIconBitmapHeader->biSizeImage; + iOffsetMaskData = iDataSize; + iDataSize += pIconBitmapHeader->biHeight * iLengthScanLineMask; + pIconBitmapHeader->biSizeImage += pIconBitmapHeader->biHeight * iLengthScanLineMask; + pIconBitmapHeader->biHeight *= 2; + pIconData = HeapReAlloc(GetProcessHeap(), 0, pIconData, iDataSize); + pIconEntry = (CURSORICONFILEDIRENTRY *)(pIconData + 3 * sizeof(WORD)); + pIconBitmapHeader = (BITMAPINFOHEADER *)(pIconData + 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY)); + pIconEntry->dwDIBSize = iDataSize - (3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY)); + + /* Get the actual bitmap data from the icon bitmap */ + GetDIBits(hDC, infoIcon.hbmColor, 0, pInfoBitmap->bmiHeader.biHeight, + pIconData + iOffsetColorData, pInfoBitmap, DIB_RGB_COLORS); + if (iNumEntriesPalette > 0) { + memcpy(pIconData + iOffsetPalette, pInfoBitmap->bmiColors, + iNumEntriesPalette * sizeof(RGBQUAD)); + } + + /* Reset all values so that GetDIBits call succeeds */ + memset(pIconData + iOffsetMaskData, 0, iDataSize - iOffsetMaskData); + memset(pInfoBitmap, 0, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)); + pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader); +/* + if (!(GetDIBits(hDC, infoIcon.hbmMask, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS) + && GetDIBits(hDC, infoIcon.hbmMask, 0, pIconEntry->bHeight, + pIconData + iOffsetMaskData, pInfoBitmap, DIB_RGB_COLORS))) { + + printf("ERROR: unable to get bitmap mask (error %lu)\n", + GetLastError()); + + } +*/ + GetDIBits(hDC, infoIcon.hbmMask, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS); + GetDIBits(hDC, infoIcon.hbmMask, 0, pIconEntry->bHeight, pIconData + iOffsetMaskData, pInfoBitmap, DIB_RGB_COLORS); + + /* Write out everything produced so far to the stream */ + *ppBuffer = pIconData; *pLength = iDataSize; + iSuccess = 1; + } else { +/* + printf("ERROR: unable to get bitmap information via GetDIBits() (error %lu)\n", + GetLastError()); +*/ + } + /* + Remarks (from MSDN entry on GetIconInfo): + + GetIconInfo creates bitmaps for the hbmMask and hbmColor + members of ICONINFO. The calling application must manage + these bitmaps and delete them when they are no longer + necessary. + */ + if (hDC) ReleaseDC(0, hDC); + DeleteObject(infoIcon.hbmMask); + if (infoIcon.hbmColor) DeleteObject(infoIcon.hbmColor); + HeapFree(GetProcessHeap(), 0, pInfoBitmap); + } else { + printf("ERROR: Unable to get icon information (error %lu)\n", + GetLastError()); + } + return iSuccess; +} + static HRESULT WINAPI OLEPictureImpl_Save( IPersistStream* iface,IStream*pStm,BOOL fClearDirty) { @@ -1696,223 +1940,6 @@ return hResult; }
-static int serializeBMP(HBITMAP hBitmap, void ** ppBuffer, unsigned int * pLength) -{ - int iSuccess = 0; - HDC hDC; - BITMAPINFO * pInfoBitmap; - int iNumPaletteEntries; - unsigned char * pPixelData; - BITMAPFILEHEADER * pFileHeader; - BITMAPINFO * pInfoHeader; - - pInfoBitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, - sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)); - - /* Find out bitmap size and padded length */ - hDC = GetDC(0); - pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader); - GetDIBits(hDC, hBitmap, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS); - - /* Fetch bitmap palette & pixel data */ - - pPixelData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, pInfoBitmap->bmiHeader.biSizeImage); - GetDIBits(hDC, hBitmap, 0, pInfoBitmap->bmiHeader.biHeight, pPixelData, pInfoBitmap, DIB_RGB_COLORS); - - /* Calculate the total length required for the BMP data */ - if (pInfoBitmap->bmiHeader.biClrUsed != 0) { - iNumPaletteEntries = pInfoBitmap->bmiHeader.biClrUsed; - if (iNumPaletteEntries > 256) iNumPaletteEntries = 256; - } else { - if (pInfoBitmap->bmiHeader.biBitCount <= 8) - iNumPaletteEntries = 1 << pInfoBitmap->bmiHeader.biBitCount; - else - iNumPaletteEntries = 0; - } - *pLength = - sizeof(BITMAPFILEHEADER) + - sizeof(BITMAPINFOHEADER) + - iNumPaletteEntries * sizeof(RGBQUAD) + - pInfoBitmap->bmiHeader.biSizeImage; - *ppBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *pLength); - - /* Fill the BITMAPFILEHEADER */ - pFileHeader = (BITMAPFILEHEADER *)(*ppBuffer); - pFileHeader->bfType = 0x4d42; - pFileHeader->bfSize = *pLength; - pFileHeader->bfOffBits = - sizeof(BITMAPFILEHEADER) + - sizeof(BITMAPINFOHEADER) + - iNumPaletteEntries * sizeof(RGBQUAD); - - /* Fill the BITMAPINFOHEADER and the palette data */ - pInfoHeader = (BITMAPINFO *)((unsigned char *)(*ppBuffer) + sizeof(BITMAPFILEHEADER)); - memcpy(pInfoHeader, pInfoBitmap, sizeof(BITMAPINFOHEADER) + iNumPaletteEntries * sizeof(RGBQUAD)); - memcpy( - (unsigned char *)(*ppBuffer) + - sizeof(BITMAPFILEHEADER) + - sizeof(BITMAPINFOHEADER) + - iNumPaletteEntries * sizeof(RGBQUAD), - pPixelData, pInfoBitmap->bmiHeader.biSizeImage); - iSuccess = 1; - - HeapFree(GetProcessHeap(), 0, pPixelData); - HeapFree(GetProcessHeap(), 0, pInfoBitmap); - return iSuccess; -} - -static int serializeIcon(HICON hIcon, void ** ppBuffer, unsigned int * pLength) -{ - ICONINFO infoIcon; - int iSuccess = 0; - - *ppBuffer = NULL; *pLength = 0; - if (GetIconInfo(hIcon, &infoIcon)) { - HDC hDC; - BITMAPINFO * pInfoBitmap; - unsigned char * pIconData = NULL; - unsigned int iDataSize = 0; - - pInfoBitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)); - - /* Find out icon size */ - hDC = GetDC(0); - pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader); - GetDIBits(hDC, infoIcon.hbmColor, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS); - if (1) { - /* Auxiliary pointers */ - CURSORICONFILEDIR * pIconDir; - CURSORICONFILEDIRENTRY * pIconEntry; - BITMAPINFOHEADER * pIconBitmapHeader; - unsigned int iOffsetPalette; - unsigned int iOffsetColorData; - unsigned int iOffsetMaskData; - - unsigned int iLengthScanLineColor; - unsigned int iLengthScanLineMask; - unsigned int iNumEntriesPalette; - - iLengthScanLineMask = ((pInfoBitmap->bmiHeader.biWidth + 31) >> 5) << 2; - iLengthScanLineColor = ((pInfoBitmap->bmiHeader.biWidth * pInfoBitmap->bmiHeader.biBitCount + 31) >> 5) << 2; -/* - FIXME("DEBUG: bitmap size is %d x %d\n", - pInfoBitmap->bmiHeader.biWidth, - pInfoBitmap->bmiHeader.biHeight); - FIXME("DEBUG: bitmap bpp is %d\n", - pInfoBitmap->bmiHeader.biBitCount); - FIXME("DEBUG: bitmap nplanes is %d\n", - pInfoBitmap->bmiHeader.biPlanes); - FIXME("DEBUG: bitmap biSizeImage is %lu\n", - pInfoBitmap->bmiHeader.biSizeImage); -*/ - /* Let's start with one CURSORICONFILEDIR and one CURSORICONFILEDIRENTRY */ - iDataSize += 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY) + sizeof(BITMAPINFOHEADER); - pIconData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, iDataSize); - - /* Fill out the CURSORICONFILEDIR */ - pIconDir = (CURSORICONFILEDIR *)pIconData; - pIconDir->idType = 1; - pIconDir->idCount = 1; - - /* Fill out the CURSORICONFILEDIRENTRY */ - pIconEntry = (CURSORICONFILEDIRENTRY *)(pIconData + 3 * sizeof(WORD)); - pIconEntry->bWidth = (unsigned char)pInfoBitmap->bmiHeader.biWidth; - pIconEntry->bHeight = (unsigned char)pInfoBitmap->bmiHeader.biHeight; - pIconEntry->bColorCount = - (pInfoBitmap->bmiHeader.biBitCount < 8) - ? 1 << pInfoBitmap->bmiHeader.biBitCount - : 0; - pIconEntry->xHotspot = pInfoBitmap->bmiHeader.biPlanes; - pIconEntry->yHotspot = pInfoBitmap->bmiHeader.biBitCount; - pIconEntry->dwDIBSize = 0; - pIconEntry->dwDIBOffset = 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY); - - /* Fill out the BITMAPINFOHEADER */ - pIconBitmapHeader = (BITMAPINFOHEADER *)(pIconData + 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY)); - memcpy(pIconBitmapHeader, &pInfoBitmap->bmiHeader, sizeof(BITMAPINFOHEADER)); - - /* Find out whether a palette exists for the bitmap */ - if ( (pInfoBitmap->bmiHeader.biBitCount == 16 && pInfoBitmap->bmiHeader.biCompression == BI_RGB) - || (pInfoBitmap->bmiHeader.biBitCount == 24) - || (pInfoBitmap->bmiHeader.biBitCount == 32 && pInfoBitmap->bmiHeader.biCompression == BI_RGB)) { - iNumEntriesPalette = pInfoBitmap->bmiHeader.biClrUsed; - if (iNumEntriesPalette > 256) iNumEntriesPalette = 256; - } else if ((pInfoBitmap->bmiHeader.biBitCount == 16 || pInfoBitmap->bmiHeader.biBitCount == 32) - && pInfoBitmap->bmiHeader.biCompression == BI_BITFIELDS) { - iNumEntriesPalette = 3; - } else if (pInfoBitmap->bmiHeader.biBitCount <= 8) { - iNumEntriesPalette = 1 << pInfoBitmap->bmiHeader.biBitCount; - } else { - iNumEntriesPalette = 0; - } - - /* Add bitmap size and header size to icon data size. */ - iOffsetPalette = iDataSize; - iDataSize += iNumEntriesPalette * sizeof(DWORD); - iOffsetColorData = iDataSize; - iDataSize += pIconBitmapHeader->biSizeImage; - iOffsetMaskData = iDataSize; - iDataSize += pIconBitmapHeader->biHeight * iLengthScanLineMask; - pIconBitmapHeader->biSizeImage += pIconBitmapHeader->biHeight * iLengthScanLineMask; - pIconBitmapHeader->biHeight *= 2; - pIconData = HeapReAlloc(GetProcessHeap(), 0, pIconData, iDataSize); - pIconEntry = (CURSORICONFILEDIRENTRY *)(pIconData + 3 * sizeof(WORD)); - pIconBitmapHeader = (BITMAPINFOHEADER *)(pIconData + 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY)); - pIconEntry->dwDIBSize = iDataSize - (3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY)); - - /* Get the actual bitmap data from the icon bitmap */ - GetDIBits(hDC, infoIcon.hbmColor, 0, pInfoBitmap->bmiHeader.biHeight, - pIconData + iOffsetColorData, pInfoBitmap, DIB_RGB_COLORS); - if (iNumEntriesPalette > 0) { - memcpy(pIconData + iOffsetPalette, pInfoBitmap->bmiColors, - iNumEntriesPalette * sizeof(RGBQUAD)); - } - - /* Reset all values so that GetDIBits call succeeds */ - memset(pIconData + iOffsetMaskData, 0, iDataSize - iOffsetMaskData); - memset(pInfoBitmap, 0, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)); - pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader); -/* - if (!(GetDIBits(hDC, infoIcon.hbmMask, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS) - && GetDIBits(hDC, infoIcon.hbmMask, 0, pIconEntry->bHeight, - pIconData + iOffsetMaskData, pInfoBitmap, DIB_RGB_COLORS))) { - - printf("ERROR: unable to get bitmap mask (error %lu)\n", - GetLastError()); - - } -*/ - GetDIBits(hDC, infoIcon.hbmMask, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS); - GetDIBits(hDC, infoIcon.hbmMask, 0, pIconEntry->bHeight, pIconData + iOffsetMaskData, pInfoBitmap, DIB_RGB_COLORS); - - /* Write out everything produced so far to the stream */ - *ppBuffer = pIconData; *pLength = iDataSize; - iSuccess = 1; - } else { -/* - printf("ERROR: unable to get bitmap information via GetDIBits() (error %lu)\n", - GetLastError()); -*/ - } - /* - Remarks (from MSDN entry on GetIconInfo): - - GetIconInfo creates bitmaps for the hbmMask and hbmColor - members of ICONINFO. The calling application must manage - these bitmaps and delete them when they are no longer - necessary. - */ - if (hDC) ReleaseDC(0, hDC); - DeleteObject(infoIcon.hbmMask); - if (infoIcon.hbmColor) DeleteObject(infoIcon.hbmColor); - HeapFree(GetProcessHeap(), 0, pInfoBitmap); - } else { - printf("ERROR: Unable to get icon information (error %lu)\n", - GetLastError()); - } - return iSuccess; -} - static HRESULT WINAPI OLEPictureImpl_GetSizeMax( IPersistStream* iface,ULARGE_INTEGER*pcbSize) { @@ -1921,9 +1948,11 @@ return E_NOTIMPL; }
+ /************************************************************************ * IDispatch */ + /************************************************************************ * OLEPictureImpl_IDispatch_QueryInterface (IUnknown) * @@ -2029,12 +2058,31 @@ EXCEPINFO* pExepInfo, UINT* puArgErr) { - FIXME("(dispid: %ld):Stub\n",dispIdMember); - - VariantInit(pVarResult); - V_VT(pVarResult) = VT_BOOL; - V_BOOL(pVarResult) = FALSE; - return S_OK; + OLEPictureImpl *This = impl_from_IDispatch(iface); + if (dispIdMember == DISPID_PICT_TYPE) + { + TRACE("DISPID_PICT_TYPE\n"); + if (!(wFlags & INVOKE_PROPERTYGET)) + return DISP_E_PARAMNOTFOUND; + if (pDispParams->cArgs != 0) + return DISP_E_BADPARAMCOUNT; + if (pVarResult) + { + VariantInit(pVarResult); + V_VT(pVarResult) = VT_I2; + return OLEPictureImpl_get_Type((IPicture *)&This->lpVtbl, &V_I2(pVarResult)); + } + return S_OK; + } + else + { + FIXME("(dispid: %ld):Stub\n",dispIdMember); + + VariantInit(pVarResult); + V_VT(pVarResult) = VT_BOOL; + V_BOOL(pVarResult) = FALSE; + return S_OK; + } }
Modified: trunk/reactos/dll/win32/oleaut32/tmarshal.c URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/dll/win32/oleaut32/tmarshal.... ============================================================================== --- trunk/reactos/dll/win32/oleaut32/tmarshal.c (original) +++ trunk/reactos/dll/win32/oleaut32/tmarshal.c Mon Mar 27 20:44:53 2006 @@ -43,6 +43,7 @@
#include "ole2.h" #include "typelib.h" +#include "variant.h" #include "wine/debug.h"
static const WCHAR IDispatchW[] = { 'I','D','i','s','p','a','t','c','h',0}; @@ -167,7 +168,7 @@ * can happen. S_OK to make sure we continue * serializing. */ - ERR("pUnk is NULL?\n"); + WARN("pUnk is NULL\n"); xsize = 0; return xbuf_add(buf,(LPBYTE)&xsize,sizeof(xsize)); } @@ -354,6 +355,7 @@ CRITICAL_SECTION crit; IUnknown *outerunknown; IDispatch *dispatch; + IRpcProxyBuffer *dispatch_proxy; } TMProxyImpl;
static HRESULT WINAPI @@ -390,7 +392,7 @@
if (!refCount) { - if (This->dispatch) IDispatch_Release(This->dispatch); + if (This->dispatch_proxy) IRpcProxyBuffer_Release(This->dispatch_proxy); DeleteCriticalSection(&This->crit); if (This->chanbuf) IRpcChannelBuffer_Release(This->chanbuf); VirtualFree(This->asmstubs, 0, MEM_RELEASE); @@ -414,6 +416,9 @@
LeaveCriticalSection(&This->crit);
+ if (This->dispatch_proxy) + IRpcProxyBuffer_Connect(This->dispatch_proxy, pRpcChannelBuffer); + return S_OK; }
@@ -430,6 +435,9 @@ This->chanbuf = NULL;
LeaveCriticalSection(&This->crit); + + if (This->dispatch_proxy) + IRpcProxyBuffer_Disconnect(This->dispatch_proxy); }
@@ -501,13 +509,14 @@ { HRESULT hres = S_OK;
- TRACE("(tdesc.vt %d)\n",tdesc->vt); + TRACE("(tdesc.vt %s)\n",debugstr_vt(tdesc->vt));
switch (tdesc->vt) { case VT_EMPTY: /* nothing. empty variant for instance */ return S_OK; case VT_I8: case VT_UI8: + case VT_CY: hres = S_OK; if (debugout) TRACE_(olerelay)("%lx%lx",arg[0],arg[1]); if (writeit) @@ -515,6 +524,7 @@ return hres; case VT_BOOL: case VT_ERROR: + case VT_INT: case VT_UINT: case VT_I4: case VT_R4: @@ -550,7 +560,7 @@ VARIANT *vt = (VARIANT*)arg; DWORD vttype = V_VT(vt);
- if (debugout) TRACE_(olerelay)("Vt(%ld)(",vttype); + if (debugout) TRACE_(olerelay)("Vt(%s%s)(",debugstr_vt(vttype),debugstr_vf(vttype)); tdesc2.vt = vttype; if (writeit) { hres = xbuf_add(buf,(LPBYTE)&vttype,sizeof(vttype)); @@ -666,11 +676,15 @@ if (debugout) TRACE_(olerelay)("unk(0x%lx)",*arg); if (writeit) hres = _marshal_interface(buf,&IID_IUnknown,(LPUNKNOWN)*arg); + if (dealloc && *(IUnknown **)arg) + IUnknown_Release((LPUNKNOWN)*arg); return hres; case VT_DISPATCH: if (debugout) TRACE_(olerelay)("idisp(0x%lx)",*arg); if (writeit) hres = _marshal_interface(buf,&IID_IDispatch,(LPUNKNOWN)*arg); + if (dealloc && *(IUnknown **)arg) + IUnknown_Release((LPUNKNOWN)*arg); return hres; case VT_VOID: if (debugout) TRACE_(olerelay)("<void>"); @@ -761,7 +775,7 @@ if (debugout) TRACE_(olerelay)("[%ld]",adesc->rgbounds[i].cElements); arrsize *= adesc->rgbounds[i].cElements; } - if (debugout) TRACE_(olerelay)("(vt %d)",adesc->tdescElem.vt); + if (debugout) TRACE_(olerelay)("(vt %s)",debugstr_vt(adesc->tdescElem.vt)); if (debugout) TRACE_(olerelay)("["); for (i=0;i<arrsize;i++) { hres = serialize_param(tinfo, writeit, debugout, dealloc, &adesc->tdescElem, (DWORD*)((LPBYTE)arg+i*_xsize(&adesc->tdescElem)), buf); @@ -790,7 +804,7 @@ { HRESULT hres = S_OK;
- TRACE("vt %d at %p\n",tdesc->vt,arg); + TRACE("vt %s at %p\n",debugstr_vt(tdesc->vt),arg);
while (1) { switch (tdesc->vt) { @@ -814,7 +828,7 @@ memset(&tdesc2,0,sizeof(tdesc2)); tdesc2.vt = vttype; V_VT(vt) = vttype; - if (debugout) TRACE_(olerelay)("Vt(%ld)(",vttype); + if (debugout) TRACE_(olerelay)("Vt(%s%s)(",debugstr_vt(vttype),debugstr_vf(vttype)); hres = deserialize_param(tinfo, readit, debugout, alloc, &tdesc2, (DWORD*)&(V_I4(vt)), buf); TRACE_(olerelay)(")"); return hres; @@ -825,6 +839,7 @@ } case VT_I8: case VT_UI8: + case VT_CY: if (readit) { hres = xbuf_get(buf,(LPBYTE)arg,8); if (hres) ERR("Failed to read integer 8 byte\n"); @@ -834,6 +849,7 @@ case VT_ERROR: case VT_BOOL: case VT_I4: + case VT_INT: case VT_UINT: case VT_R4: case VT_UI4: @@ -1371,56 +1387,29 @@ static HRESULT WINAPI ProxyIDispatch_GetTypeInfoCount(LPDISPATCH iface, UINT * pctinfo) { TMProxyImpl *This = (TMProxyImpl *)iface; - HRESULT hr;
TRACE("(%p)\n", pctinfo);
- if (!This->dispatch) - { - hr = IUnknown_QueryInterface(This->outerunknown, &IID_IDispatch, - (LPVOID *)&This->dispatch); - } - if (This->dispatch) - hr = IDispatch_GetTypeInfoCount(This->dispatch, pctinfo); - - return hr; + return IDispatch_GetTypeInfoCount(This->dispatch, pctinfo); }
static HRESULT WINAPI ProxyIDispatch_GetTypeInfo(LPDISPATCH iface, UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo) { TMProxyImpl *This = (TMProxyImpl *)iface; - HRESULT hr = S_OK;
TRACE("(%d, %lx, %p)\n", iTInfo, lcid, ppTInfo);
- if (!This->dispatch) - { - hr = IUnknown_QueryInterface(This->outerunknown, &IID_IDispatch, - (LPVOID *)&This->dispatch); - } - if (This->dispatch) - hr = IDispatch_GetTypeInfo(This->dispatch, iTInfo, lcid, ppTInfo); - - return hr; + return IDispatch_GetTypeInfo(This->dispatch, iTInfo, lcid, ppTInfo); }
static HRESULT WINAPI ProxyIDispatch_GetIDsOfNames(LPDISPATCH iface, REFIID riid, LPOLESTR * rgszNames, UINT cNames, LCID lcid, DISPID * rgDispId) { TMProxyImpl *This = (TMProxyImpl *)iface; - HRESULT hr;
TRACE("(%s, %p, %d, 0x%lx, %p)\n", debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
- if (!This->dispatch) - { - hr = IUnknown_QueryInterface(This->outerunknown, &IID_IDispatch, - (LPVOID *)&This->dispatch); - } - if (This->dispatch) - hr = IDispatch_GetIDsOfNames(This->dispatch, riid, rgszNames, - cNames, lcid, rgDispId); - - return hr; + return IDispatch_GetIDsOfNames(This->dispatch, riid, rgszNames, + cNames, lcid, rgDispId); }
static HRESULT WINAPI ProxyIDispatch_Invoke(LPDISPATCH iface, DISPID dispIdMember, REFIID riid, LCID lcid, @@ -1428,21 +1417,25 @@ EXCEPINFO * pExcepInfo, UINT * puArgErr) { TMProxyImpl *This = (TMProxyImpl *)iface; - HRESULT hr; - - TRACE("(%ld, %s, 0x%lx, 0x%x, %p, %p, %p, %p)\n", dispIdMember, debugstr_guid(riid), lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); - - if (!This->dispatch) - { - hr = IUnknown_QueryInterface(This->outerunknown, &IID_IDispatch, - (LPVOID *)&This->dispatch); - } - if (This->dispatch) - hr = IDispatch_Invoke(This->dispatch, dispIdMember, riid, lcid, - wFlags, pDispParams, pVarResult, pExcepInfo, - puArgErr); - - return hr; + + TRACE("(%ld, %s, 0x%lx, 0x%x, %p, %p, %p, %p)\n", dispIdMember, + debugstr_guid(riid), lcid, wFlags, pDispParams, pVarResult, + pExcepInfo, puArgErr); + + return IDispatch_Invoke(This->dispatch, dispIdMember, riid, lcid, + wFlags, pDispParams, pVarResult, pExcepInfo, + puArgErr); +} + +static inline HRESULT get_facbuf_for_iid(REFIID riid, IPSFactoryBuffer **facbuf) +{ + HRESULT hr; + CLSID clsid; + + if ((hr = CoGetPSClsid(riid, &clsid))) + return hr; + return CoGetClassObject(&clsid, CLSCTX_INPROC_SERVER, NULL, + &IID_IPSFactoryBuffer, (LPVOID*)facbuf); }
static HRESULT WINAPI @@ -1470,6 +1463,7 @@ assert(sizeof(TMAsmProxy) == 12);
proxy->dispatch = NULL; + proxy->dispatch_proxy = NULL; proxy->outerunknown = pUnkOuter; proxy->asmstubs = VirtualAlloc(NULL, sizeof(TMAsmProxy) * nroffuncs, MEM_COMMIT, PAGE_EXECUTE_READWRITE); if (!proxy->asmstubs) { @@ -1549,10 +1543,22 @@ { if (typeattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE) { - proxy->lpvtbl[3] = ProxyIDispatch_GetTypeInfoCount; - proxy->lpvtbl[4] = ProxyIDispatch_GetTypeInfo; - proxy->lpvtbl[5] = ProxyIDispatch_GetIDsOfNames; - proxy->lpvtbl[6] = ProxyIDispatch_Invoke; + IPSFactoryBuffer *factory_buffer; + hres = get_facbuf_for_iid(&IID_IDispatch, &factory_buffer); + if (hres == S_OK) + { + hres = IPSFactoryBuffer_CreateProxy(factory_buffer, NULL, + &IID_IDispatch, &proxy->dispatch_proxy, + (void **)&proxy->dispatch); + IPSFactoryBuffer_Release(factory_buffer); + } + if (hres == S_OK) + { + proxy->lpvtbl[3] = ProxyIDispatch_GetTypeInfoCount; + proxy->lpvtbl[4] = ProxyIDispatch_GetTypeInfo; + proxy->lpvtbl[5] = ProxyIDispatch_GetIDsOfNames; + proxy->lpvtbl[6] = ProxyIDispatch_Invoke; + } } ITypeInfo_ReleaseTypeAttr(tinfo, typeattr); } @@ -1563,10 +1569,16 @@ proxy->tinfo = tinfo; memcpy(&proxy->iid,riid,sizeof(*riid)); proxy->chanbuf = 0; - *ppv = (LPVOID)proxy; - *ppProxy = (IRpcProxyBuffer *)&(proxy->lpvtbl2); - IUnknown_AddRef((IUnknown *)*ppv); - return S_OK; + if (hres == S_OK) + { + *ppv = (LPVOID)proxy; + *ppProxy = (IRpcProxyBuffer *)&(proxy->lpvtbl2); + IUnknown_AddRef((IUnknown *)*ppv); + return S_OK; + } + else + TMProxyImpl_Release((IRpcProxyBuffer *)&proxy->lpvtbl2); + return hres; }
typedef struct _TMStubImpl { @@ -1576,6 +1588,7 @@ LPUNKNOWN pUnk; ITypeInfo *tinfo; IID iid; + IRpcStubBuffer *dispatch_stub; } TMStubImpl;
static HRESULT WINAPI @@ -1627,6 +1640,10 @@
IUnknown_AddRef(pUnkServer); This->pUnk = pUnkServer; + + if (This->dispatch_stub) + IRpcStubBuffer_Connect(This->dispatch_stub, pUnkServer); + return S_OK; }
@@ -1642,6 +1659,9 @@ IUnknown_Release(This->pUnk); This->pUnk = NULL; } + + if (This->dispatch_stub) + IRpcStubBuffer_Disconnect(This->dispatch_stub); }
static HRESULT WINAPI @@ -1659,18 +1679,21 @@ BSTR iname = NULL; ITypeInfo *tinfo;
+ TRACE("...\n"); + + if (xmsg->iMethod < 3) { + ERR("IUnknown methods cannot be marshaled by the typelib marshaler\n"); + return E_UNEXPECTED; + } + + if (This->dispatch_stub && xmsg->iMethod < sizeof(IDispatchVtbl)/sizeof(void *)) + return IRpcStubBuffer_Invoke(This->dispatch_stub, xmsg, rpcchanbuf); + memset(&buf,0,sizeof(buf)); buf.size = xmsg->cbBuffer; buf.base = HeapAlloc(GetProcessHeap(), 0, xmsg->cbBuffer); memcpy(buf.base, xmsg->Buffer, xmsg->cbBuffer); buf.curoff = 0; - - TRACE("...\n"); - - if (xmsg->iMethod < 3) { - ERR("IUnknown methods cannot be marshaled by the typelib marshaler\n"); - return E_UNEXPECTED; - }
hres = _get_funcdesc(This->tinfo,xmsg->iMethod,&tinfo,&fdesc,&iname,NULL); if (hres) { @@ -1830,25 +1853,48 @@ HRESULT hres; ITypeInfo *tinfo; TMStubImpl *stub; + TYPEATTR *typeattr;
TRACE("(%s,%p,%p)\n",debugstr_guid(riid),pUnkServer,ppStub); + hres = _get_typeinfo_for_iid(riid,&tinfo); if (hres) { ERR("No typeinfo for %s?\n",debugstr_guid(riid)); return hres; } + stub = CoTaskMemAlloc(sizeof(TMStubImpl)); if (!stub) return E_OUTOFMEMORY; stub->lpvtbl = &tmstubvtbl; stub->ref = 1; stub->tinfo = tinfo; + stub->dispatch_stub = NULL; memcpy(&(stub->iid),riid,sizeof(*riid)); hres = IRpcStubBuffer_Connect((LPRPCSTUBBUFFER)stub,pUnkServer); *ppStub = (LPRPCSTUBBUFFER)stub; TRACE("IRpcStubBuffer: %p\n", stub); if (hres) ERR("Connect to pUnkServer failed?\n"); + + /* if we derive from IDispatch then defer to its stub for some of its methods */ + hres = ITypeInfo_GetTypeAttr(tinfo, &typeattr); + if (hres == S_OK) + { + if (typeattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE) + { + IPSFactoryBuffer *factory_buffer; + hres = get_facbuf_for_iid(&IID_IDispatch, &factory_buffer); + if (hres == S_OK) + { + hres = IPSFactoryBuffer_CreateStub(factory_buffer, &IID_IDispatch, + pUnkServer, &stub->dispatch_stub); + IPSFactoryBuffer_Release(factory_buffer); + } + } + ITypeInfo_ReleaseTypeAttr(tinfo, typeattr); + } + return hres; }
Modified: trunk/reactos/dll/win32/oleaut32/typelib.c URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/dll/win32/oleaut32/typelib.c... ============================================================================== --- trunk/reactos/dll/win32/oleaut32/typelib.c (original) +++ trunk/reactos/dll/win32/oleaut32/typelib.c Mon Mar 27 20:44:53 2006 @@ -196,7 +196,7 @@ return buffer; }
-int TLB_ReadTypeLib(LPCWSTR file, INT index, ITypeLib2 **ppTypelib); +static int TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib);
/**************************************************************************** @@ -333,38 +333,14 @@ REGKIND regkind, /* [in] Specify kind of registration */ ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */ { - WCHAR szPath[MAX_PATH+1], szFileCopy[MAX_PATH+1]; - WCHAR *pIndexStr; + WCHAR szPath[MAX_PATH+1]; HRESULT res; - INT index = 1;
TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
- /* by default try and load using LoadLibrary (for builtin stdole32.tlb) */ - memcpy(szPath, szFile, (strlenW(szFile)+1)*sizeof(WCHAR)); - *pptLib = NULL; - if(!SearchPathW(NULL,szFile,NULL,sizeof(szPath)/sizeof(WCHAR),szPath, - NULL)) { - - /* Look for a trailing '\' followed by an index */ - pIndexStr = strrchrW(szFile, '\'); - if(pIndexStr && pIndexStr != szFile && *++pIndexStr != '\0') { - index = atoiW(pIndexStr); - memcpy(szFileCopy, szFile, - (pIndexStr - szFile - 1) * sizeof(WCHAR)); - szFileCopy[pIndexStr - szFile - 1] = '\0'; - if(!SearchPathW(NULL,szFileCopy,NULL,sizeof(szPath)/sizeof(WCHAR), - szPath,NULL)) - return TYPE_E_CANTLOADLIBRARY; - if (GetFileAttributesW(szFileCopy) & FILE_ATTRIBUTE_DIRECTORY) - return TYPE_E_CANTLOADLIBRARY; - } - } - - TRACE("File %s index %d\n", debugstr_w(szPath), index); - - res = TLB_ReadTypeLib(szPath, index, (ITypeLib2**)pptLib); + + res = TLB_ReadTypeLib(szFile, szPath, MAX_PATH + 1, (ITypeLib2**)pptLib);
if (SUCCEEDED(res)) switch(regkind) @@ -1224,7 +1200,7 @@ } else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar)) { - TRACE(",FIXME"); + TRACE(",%p", V_ARRAY(pvar)); } else switch (V_TYPE(pvar)) { @@ -1988,9 +1964,10 @@ (*ppRefType)->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; } else - (*ppRefType)->index = impinfo.oGuid; + (*ppRefType)->index = impinfo.oGuid; }else{ ERR("Cannot find a reference\n"); (*ppRefType)->reference=-1; @@ -2033,6 +2010,7 @@ static ITypeInfoImpl * MSFT_DoTypeInfo( TLBContext *pcx, int count, + INT dispatch_href, ITypeLibImpl * pLibInfo) { MSFT_TypeInfoBase tiBase; @@ -2113,38 +2091,10 @@ ptiRet->impltypelist->hRef = tiBase.datatype1; } else - { /* FIXME: This is a really bad hack to add IDispatch */ - const char* szStdOle = "stdole2.tlb\0"; - int nStdOleLen = strlen(szStdOle); - TLBRefType **ppRef = &ptiRet->reflist; - - while(*ppRef) { - if((*ppRef)->reference == -1) - break; - ppRef = &(*ppRef)->next; - } - if(!*ppRef) { - *ppRef = TLB_Alloc(sizeof(**ppRef)); - (*ppRef)->guid = IID_IDispatch; - (*ppRef)->reference = -1; - (*ppRef)->index = TLB_REF_USE_GUID; - (*ppRef)->pImpTLInfo = TLB_Alloc(sizeof(TLBImpLib)); - (*ppRef)->pImpTLInfo->guid = IID_StdOle; - (*ppRef)->pImpTLInfo->name = SysAllocStringLen(NULL, - nStdOleLen + 1); - - MultiByteToWideChar(CP_ACP, - MB_PRECOMPOSED, - szStdOle, - -1, - (*ppRef)->pImpTLInfo->name, - SysStringLen((*ppRef)->pImpTLInfo->name)); - - (*ppRef)->pImpTLInfo->lcid = 0; - (*ppRef)->pImpTLInfo->wVersionMajor = 2; - (*ppRef)->pImpTLInfo->wVersionMinor = 0; - } - } + { + MSFT_DoRefType(pcx, ptiRet, dispatch_href); + ptiRet->impltypelist->hRef = dispatch_href; + } break; default: ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType)); @@ -2188,22 +2138,50 @@ */ #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */ #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */ -int TLB_ReadTypeLib(LPCWSTR pszFileName, INT index, ITypeLib2 **ppTypeLib) +static int TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib) { ITypeLibImpl *entry; int ret = TYPE_E_CANTLOADLIBRARY; - DWORD dwSignature = 0; - HANDLE hFile; - - TRACE_(typelib)("%s:%d\n", debugstr_w(pszFileName), index); + INT index = 1; + HINSTANCE hinstDLL;
*ppTypeLib = NULL; + + lstrcpynW(pszPath, pszFileName, cchPath); + + /* first try loading as a dll and access the typelib as a resource */ + hinstDLL = LoadLibraryExW(pszFileName, 0, DONT_RESOLVE_DLL_REFERENCES | + LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH); + if (!hinstDLL) + { + /* it may have been specified with resource index appended to the + * path, so remove it and try again */ + const WCHAR *pIndexStr = strrchrW(pszFileName, '\'); + if(pIndexStr && pIndexStr != pszFileName && *++pIndexStr != '\0') + { + index = atoiW(pIndexStr); + pszPath[pIndexStr - pszFileName - 1] = '\0'; + + hinstDLL = LoadLibraryExW(pszPath, 0, DONT_RESOLVE_DLL_REFERENCES | + LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH); + } + } + + /* get the path to the specified typelib file */ + if (!hinstDLL) + { + /* otherwise, try loading as a regular file */ + if (!SearchPathW(NULL, pszFileName, NULL, cchPath, pszPath, NULL)) + return TYPE_E_CANTLOADLIBRARY; + } + + TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
/* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */ EnterCriticalSection(&cache_section); for (entry = tlb_cache_first; entry != NULL; entry = entry->next) { - if (!strcmpiW(entry->path, pszFileName) && entry->index == index) + if (!strcmpiW(entry->path, pszPath) && entry->index == index) { TRACE("cache hit\n"); *ppTypeLib = (ITypeLib2*)entry; @@ -2214,88 +2192,69 @@ } LeaveCriticalSection(&cache_section);
- /* check the signature of the file */ - hFile = CreateFileW( pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 ); - if (INVALID_HANDLE_VALUE != hFile) - { - HANDLE hMapping = CreateFileMappingW( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL ); - if (hMapping) - { - LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0); - if(pBase) - { - /* retrieve file size */ - DWORD dwTLBLength = GetFileSize(hFile, NULL); - - /* first try to load as *.tlb */ - dwSignature = FromLEDWord(*((DWORD*) pBase)); - if ( dwSignature == MSFT_SIGNATURE) - { - *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength); - } - else if ( dwSignature == SLTG_SIGNATURE) - { - *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength); - } - UnmapViewOfFile(pBase); - } - CloseHandle(hMapping); - } - CloseHandle(hFile); - } - else - { - TRACE("not found, trying to load %s as library\n", debugstr_w(pszFileName)); - } - - /* if the file is a DLL or not found, try loading it with LoadLibrary */ - if (((WORD)dwSignature == IMAGE_DOS_SIGNATURE) || (dwSignature == 0)) - { - /* find the typelibrary resource*/ - HINSTANCE hinstDLL = LoadLibraryExW(pszFileName, 0, DONT_RESOLVE_DLL_REFERENCES| - LOAD_LIBRARY_AS_DATAFILE|LOAD_WITH_ALTERED_SEARCH_PATH); - if (hinstDLL) - { + /* now actually load and parse the typelib */ + if (hinstDLL) + { static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0}; HRSRC hrsrc = FindResourceW(hinstDLL, MAKEINTRESOURCEW(index), TYPELIBW); if (hrsrc) { - HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc); - if (hGlobal) - { - LPVOID pBase = LockResource(hGlobal); - DWORD dwTLBLength = SizeofResource(hinstDLL, hrsrc); - - if (pBase) + HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc); + if (hGlobal) { - /* try to load as incore resource */ - dwSignature = FromLEDWord(*((DWORD*) pBase)); - if ( dwSignature == MSFT_SIGNATURE) - { - *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength); - } - else if ( dwSignature == SLTG_SIGNATURE) - { - *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength); - } - else - { - FIXME("Header type magic 0x%08lx not supported.\n",dwSignature); - } + LPVOID pBase = LockResource(hGlobal); + DWORD dwTLBLength = SizeofResource(hinstDLL, hrsrc); + + if (pBase) + { + /* try to load as incore resource */ + DWORD dwSignature = FromLEDWord(*((DWORD*) pBase)); + if (dwSignature == MSFT_SIGNATURE) + *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength); + else if (dwSignature == SLTG_SIGNATURE) + *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength); + else + FIXME("Header type magic 0x%08lx not supported.\n",dwSignature); + } + FreeResource( hGlobal ); } - FreeResource( hGlobal ); - } } FreeLibrary(hinstDLL); - } + } + else + { + HANDLE hFile = CreateFileW(pszPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 ); + if (INVALID_HANDLE_VALUE != hFile) + { + HANDLE hMapping = CreateFileMappingW( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL ); + if (hMapping) + { + LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0); + if(pBase) + { + /* retrieve file size */ + DWORD dwTLBLength = GetFileSize(hFile, NULL); + DWORD dwSignature = FromLEDWord(*((DWORD*) pBase)); + + if (dwSignature == MSFT_SIGNATURE) + *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength); + else if (dwSignature == SLTG_SIGNATURE) + *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength); + + UnmapViewOfFile(pBase); + } + CloseHandle(hMapping); + } + CloseHandle(hFile); + } }
if(*ppTypeLib) { ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
TRACE("adding to cache\n"); - impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszFileName)+1) * sizeof(WCHAR)); - lstrcpyW(impl->path, pszFileName); + impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszPath)+1) * sizeof(WCHAR)); + lstrcpyW(impl->path, pszPath); /* We should really canonicalise the path here. */ impl->index = index;
@@ -2314,6 +2273,20 @@
/*================== ITypeLib(2) Methods ===================================*/
+static ITypeLibImpl* TypeLibImpl_Constructor(void) +{ + ITypeLibImpl* pTypeLibImpl; + + pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl)); + if (!pTypeLibImpl) return NULL; + + pTypeLibImpl->lpVtbl = &tlbvt; + pTypeLibImpl->lpVtblTypeComp = &tlbtcvt; + pTypeLibImpl->ref = 1; + + return pTypeLibImpl; +} + /**************************************************************************** * ITypeLib2_Constructor_MSFT * @@ -2329,12 +2302,8 @@
TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
- pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl)); + pTypeLibImpl = TypeLibImpl_Constructor(); if (!pTypeLibImpl) return NULL; - - pTypeLibImpl->lpVtbl = &tlbvt; - pTypeLibImpl->lpVtblTypeComp = &tlbtcvt; - pTypeLibImpl->ref = 1;
/* get pointer to beginning of typelib data */ cx.pos = 0; @@ -2345,12 +2314,14 @@
/* read header */ MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0); - TRACE("header:\n"); - TRACE("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 ); + TRACE_(typelib)("header:\n"); + TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 ); if (tlbHeader.magic1 != MSFT_SIGNATURE) { FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1); return NULL; } + TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos); + /* there is a small amount of information here until the next important * part: * the segment directory . Try to calculate the amount of data */ @@ -2515,7 +2486,7 @@
for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++) { - *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl); + *ppTI = MSFT_DoTypeInfo(&cx, i, tlbHeader.dispatchpos, pTypeLibImpl);
ppTI = &((*ppTI)->next); (pTypeLibImpl->TypeInfoCount)++; @@ -3155,11 +3126,9 @@
TRACE_(typelib)("%p, TLB length = %ld\n", pLib, dwTLBLength);
- pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl)); + + pTypeLibImpl = TypeLibImpl_Constructor(); if (!pTypeLibImpl) return NULL; - - pTypeLibImpl->lpVtbl = &tlbvt; - pTypeLibImpl->ref = 1;
pHeader = pLib;
@@ -3475,13 +3444,16 @@ if (!ref) { /* remove cache entry */ - TRACE("removing from cache list\n"); - EnterCriticalSection(&cache_section); - if (This->next) This->next->prev = This->prev; - if (This->prev) This->prev->next = This->next; - else tlb_cache_first = This->next; - LeaveCriticalSection(&cache_section); - + if(This->path) + { + TRACE("removing from cache list\n"); + EnterCriticalSection(&cache_section); + if (This->next) This->next->prev = This->prev; + if (This->prev) This->prev->next = This->next; + else tlb_cache_first = This->next; + LeaveCriticalSection(&cache_section); + HeapFree(GetProcessHeap(), 0, This->path); + } /* FIXME destroy child objects */ TRACE(" destroying ITypeLib(%p)\n",This);
@@ -4287,7 +4259,12 @@ it means that function is called by ITypeLib2_Release */ ITypeLib2_Release((ITypeLib2*)This->pTypeLib); } else { - FIXME("destroy child objects\n"); + static int once = 0; + if (!once) + { + once = 1; + FIXME("destroy child objects\n"); + }
TRACE("destroying ITypeInfo(%p)\n",This); if (This->Name) @@ -4623,8 +4600,8 @@ BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames) { ITypeInfoImpl *This = (ITypeInfoImpl *)iface; - TLBFuncDesc * pFDesc; - TLBVarDesc * pVDesc; + const TLBFuncDesc *pFDesc; + const TLBVarDesc *pVDesc; int i; TRACE("(%p) memid=0x%08lx Maxname=%d\n", This, memid, cMaxNames); for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next); @@ -4693,7 +4670,7 @@ ITypeInfoImpl *This = (ITypeInfoImpl *)iface; int i; HRESULT hr = S_OK; - TLBImplType *pImpl = This->impltypelist; + const TLBImplType *pImpl = This->impltypelist;
TRACE("(%p) index %d\n", This, index); if (TRACE_ON(ole)) dump_TypeInfo(This); @@ -4772,8 +4749,8 @@ LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId) { ITypeInfoImpl *This = (ITypeInfoImpl *)iface; - TLBFuncDesc * pFDesc; - TLBVarDesc * pVDesc; + const TLBFuncDesc *pFDesc; + const TLBVarDesc *pVDesc; HRESULT ret=S_OK; int i;
@@ -4899,6 +4876,24 @@ case 17: 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]); break; + case 18: + 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]); + break; + case 19: + 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]); + break; + case 20: + 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]); + break; + case 21: + 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]); + break; + case 22: + 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]); + break; + 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; default: FIXME("unsupported number of arguments %d in stdcall\n",nrargs); res = -1; @@ -4916,165 +4911,6 @@
extern int _argsize(DWORD vt);
-/**************************************************************************** - * Helper functions for Dispcall / Invoke, which copies one variant - * with target type onto the argument stack. - */ -static HRESULT -_copy_arg( ITypeInfo2 *tinfo, TYPEDESC *tdesc, - DWORD *argpos, VARIANT *arg, VARTYPE vt -) { - UINT arglen = _argsize(vt)*sizeof(DWORD); - VARIANT va; - - if ((vt==VT_PTR) && tdesc && (tdesc->u.lptdesc->vt == VT_VARIANT)) { - memcpy(argpos,&arg,sizeof(void*)); - return S_OK; - } - - if (V_VT(arg) == vt) { - memcpy(argpos, &V_I4(arg), arglen); - return S_OK; - } - - if (V_ISARRAY(arg) && (vt == VT_SAFEARRAY)) { - memcpy(argpos, &V_ARRAY(arg), sizeof(SAFEARRAY*)); - return S_OK; - } - - if (vt == VT_VARIANT) { - memcpy(argpos, arg, arglen); - return S_OK; - } - /* Deref BYREF vars if there is need */ - if(V_ISBYREF(arg) && ((V_VT(arg) & ~VT_BYREF)==vt)) { - memcpy(argpos,(void*)V_I4(arg), arglen); - return S_OK; - } - if (vt==VT_UNKNOWN && V_VT(arg)==VT_DISPATCH) { - /* in this context, if the type lib specifies IUnknown*, giving an - IDispatch* is correct; so, don't invoke VariantChangeType */ - memcpy(argpos,&V_I4(arg), arglen); - return S_OK; - } - if ((vt == VT_PTR) && tdesc) - return _copy_arg(tinfo, tdesc->u.lptdesc, argpos, arg, tdesc->u.lptdesc->vt); - - if ((vt == VT_USERDEFINED) && tdesc && tinfo) { - ITypeInfo *tinfo2 = NULL; - TYPEATTR *tattr = NULL; - HRESULT hres; - - hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.hreftype,&tinfo2); - if (hres) { - FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, " - "while coercing from vt 0x%x. Copying 4 byte.\n", - tdesc->u.hreftype,V_VT(arg)); - memcpy(argpos, &V_I4(arg), 4); - return S_OK; - } - hres = ITypeInfo_GetTypeAttr(tinfo2,&tattr); - if( hres ) - { - ERR("GetTypeAttr failed\n"); - ITypeInfo_Release(tinfo2); - return hres; - } - switch (tattr->typekind) { - case TKIND_ENUM: - switch ( V_VT( arg ) ) { - case VT_I2: - *argpos = V_I2(arg); - hres = S_OK; - break; - case VT_I4: - memcpy(argpos, &V_I4(arg), 4); - hres = S_OK; - break; - case VT_BYREF|VT_I4: - memcpy(argpos, V_I4REF(arg), 4); - hres = S_OK; - break; - default: - FIXME("vt 0x%x -> TKIND_ENUM unhandled.\n",V_VT(arg)); - hres = E_FAIL; - break; - } - break; - - case TKIND_ALIAS: - tdesc = &(tattr->tdescAlias); - hres = _copy_arg((ITypeInfo2*)tinfo2, tdesc, argpos, arg, tdesc->vt); - break; - - case TKIND_INTERFACE: - if (V_VT(arg) == VT_DISPATCH) { - IDispatch *disp; - if (IsEqualIID(&IID_IDispatch,&(tattr->guid))) { - memcpy(argpos, &V_DISPATCH(arg), 4); - hres = S_OK; - break; - } - hres=IUnknown_QueryInterface(V_DISPATCH(arg), - &IID_IDispatch,(LPVOID*)&disp); - if (SUCCEEDED(hres)) { - memcpy(argpos,&disp,4); - IUnknown_Release(V_DISPATCH(arg)); - hres = S_OK; - break; - } - FIXME("Failed to query IDispatch interface from %s while " - "converting to VT_DISPATCH!\n",debugstr_guid(&(tattr->guid))); - hres = E_FAIL; - break; - } - if (V_VT(arg) == VT_UNKNOWN) { - memcpy(argpos, &V_UNKNOWN(arg), 4); - hres = S_OK; - break; - } - FIXME("vt 0x%x -> TKIND_INTERFACE(%s) unhandled\n", - V_VT(arg),debugstr_guid(&(tattr->guid))); - hres = E_FAIL; - break; - - case TKIND_DISPATCH: - if (V_VT(arg) == VT_DISPATCH) { - memcpy(argpos, &V_DISPATCH(arg), 4); - hres = S_OK; - } - else { - hres = E_FAIL; - FIXME("TKIND_DISPATCH unhandled for target vt 0x%x.\n",V_VT(arg)); - } - break; - case TKIND_RECORD: - FIXME("TKIND_RECORD unhandled.\n"); - hres = E_FAIL; - break; - default: - FIXME("TKIND %d unhandled.\n",tattr->typekind); - hres = E_FAIL; - break; - } - ITypeInfo_ReleaseTypeAttr(tinfo2, tattr); - ITypeInfo_Release(tinfo2); - return hres; - } - - VariantInit(&va); - if (VariantChangeType(&va,arg,0,vt)==S_OK) { - memcpy(argpos,&V_I4(&va), arglen); - FIXME("Should not use VariantChangeType here." - " (conversion from 0x%x -> 0x%x) %08lx\n", - V_VT(arg), vt, *argpos - ); - return S_OK; - } - ERR("Set arg to disparg type 0x%x vs 0x%x\n",V_VT(arg),vt); - return E_FAIL; -} - static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt) { HRESULT hr = S_OK; @@ -5144,7 +4980,7 @@ HRESULT hr = S_OK;
/* enforce only one level of pointer indirection */ - if (!(*vt & VT_BYREF) && (tdesc->vt == VT_PTR)) + if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR)) { tdesc = tdesc->u.lptdesc;
@@ -5181,9 +5017,17 @@ case VT_USERDEFINED: hr = userdefined_to_variantvt(tinfo, tdesc, vt); break; + case VT_VOID: + case VT_CARRAY: case VT_PTR: - ERR("cannot convert VT_PTR into variant VT\n"); - hr = E_FAIL; + case VT_LPSTR: + case VT_LPWSTR: + ERR("cannot convert type %d into variant VT\n", tdesc->vt); + hr = DISP_E_BADVARTYPE; + break; + case VT_SAFEARRAY: + *vt |= VT_ARRAY; + hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt); break; default: *vt |= tdesc->vt; @@ -5229,10 +5073,6 @@ *|CC_MPWCDECL *|CC_MPWPASCAL * - * BUGS - * Native accepts arguments in the reverse order. I.e. the first item in the - * prgpvarg array is the last argument in the C/C++ declaration of the - * function to be called. */ HRESULT WINAPI DispCallFunc( @@ -5294,6 +5134,17 @@ HeapFree(GetProcessHeap(),0,args); return S_OK; } + +#define INVBUF_ELEMENT_SIZE \ + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE)) +#define INVBUF_GET_ARG_ARRAY(buffer, params) \ + ((VARIANTARG *)(buffer)) +#define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \ + ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params))) +#define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \ + ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params))) +#define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \ + ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
static HRESULT WINAPI ITypeInfo_fnInvoke( ITypeInfo2 *iface, @@ -5335,163 +5186,179 @@ switch (func_desc->funckind) { case FUNC_PUREVIRTUAL: case FUNC_VIRTUAL: { - DWORD res; - int numargs, numargs2, argspos, args2pos; - DWORD *args , *args2; - VARIANT *rgvarg = HeapAlloc(GetProcessHeap(), 0, sizeof(VARIANT) * func_desc->cParams); - memcpy(rgvarg,pDispParams->rgvarg,sizeof(VARIANT)*pDispParams->cArgs); + void *buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INVBUF_ELEMENT_SIZE * func_desc->cParams); + VARIANT varresult; + VARIANT retval; /* pointer for storing byref retvals in */ + VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams); + VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams); + VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
hres = S_OK; - numargs = 1; /* sizeof(thisptr) */ - numargs2 = 0; for (i = 0; i < func_desc->cParams; i++) { TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc; - - numargs += _argsize(tdesc->vt); - if (i>=pDispParams->cArgs) { /* arguments to return */ - if (tdesc->vt == VT_PTR) { - numargs2 += _argsize(tdesc->u.lptdesc->vt); - } else { - FIXME("The variant type here should have been VT_PTR, not vt %d\n", tdesc->vt); - numargs2 += _argsize(tdesc->vt); + hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]); + if (FAILED(hres)) + goto func_fail; + } + + TRACE("changing args\n"); + for (i = 0; i < func_desc->cParams; i++) + { + USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags; + + if (wParamFlags & PARAMFLAG_FRETVAL) + { + /* note: this check is placed so that if the caller passes + * in a VARIANTARG for the retval we just ignore it, like + * native does */ + if (i == func_desc->cParams - 1) + { + VARIANTARG *arg; + arg = prgpvarg[i] = &rgvarg[i]; + memset(arg, 0, sizeof(*arg)); + V_VT(arg) = rgvt[i]; + memset(&retval, 0, sizeof(retval)); + V_BYREF(arg) = &retval; + } + else + { + ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams); + hres = E_UNEXPECTED; + break; } } - } - - args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs); - args2 = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DWORD)*numargs2); - - args[0] = (DWORD)pIUnk; - argspos = 1; args2pos = 0; - for (i = 0; i < func_desc->cParams; i++) - { - ELEMDESC *elemdesc = &(func_desc->lprgelemdescParam[i]); - TYPEDESC *tdesc = &(elemdesc->tdesc); - USHORT paramFlags = elemdesc->u.paramdesc.wParamFlags; - int arglen = _argsize(tdesc->vt); - - if (i<pDispParams->cArgs) + else if (i < pDispParams->cArgs) { - VARIANT *arg = &rgvarg[pDispParams->cArgs-i-1]; - - if (paramFlags & PARAMFLAG_FOPT) { - if(i < func_desc->cParams - func_desc->cParamsOpt) - ERR("Parameter has PARAMFLAG_FOPT flag but is not one of last cParamOpt parameters\n"); - if(V_VT(arg) == VT_EMPTY - || ((V_ISBYREF(arg)) && !V_BYREF(arg))) { - /* FIXME: Documentation says that we do this when parameter is left unspecified. - How to determine it? */ - - if(paramFlags & PARAMFLAG_FHASDEFAULT) - FIXME("PARAMFLAG_FHASDEFAULT flag not supported\n"); - V_VT(arg) = VT_ERROR; - V_ERROR(arg) = DISP_E_PARAMNOTFOUND; - arglen = _argsize(VT_ERROR); - } + VARIANTARG *src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - i]; + V_VT(&rgvarg[i]) = V_VT(src_arg); + dump_Variant(src_arg); + + /* FIXME: this doesn't work for VT_BYREF arguments if + * they are not the same type as in the paramdesc */ + if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg)) + { + VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams); + V_VT(&missing_arg[i]) = V_VT(src_arg); + hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF); + V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]); } - hres = _copy_arg(iface, tdesc, &args[argspos], arg, tdesc->vt); - if (FAILED(hres)) goto func_fail; - argspos += arglen; + else + hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]); + + if (FAILED(hres)) + { + ERR("failed to convert param %d to %s%s from %s%s\n", i, + debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]), + debugstr_VT(src_arg), debugstr_VF(src_arg)); + break; + } + V_VT(&rgvarg[i]) = rgvt[i]; + prgpvarg[i] = &rgvarg[i]; } - else if (paramFlags & PARAMFLAG_FOPT) + else if (wParamFlags & PARAMFLAG_FOPT) { - VARIANT *arg = &rgvarg[i]; - - if (i < func_desc->cParams - func_desc->cParamsOpt) - ERR("Parameter has PARAMFLAG_FOPT flag but is not one of last cParamOpt parameters\n"); - if (paramFlags & PARAMFLAG_FHASDEFAULT) - FIXME("PARAMFLAG_FHASDEFAULT flag not supported\n"); - - V_VT(arg) = VT_ERROR; - V_ERROR(arg) = DISP_E_PARAMNOTFOUND; - arglen = _argsize(VT_ERROR); - hres = _copy_arg(iface, tdesc, &args[argspos], arg, tdesc->vt); - if (FAILED(hres)) goto func_fail; - argspos += arglen; + VARIANTARG *arg; + arg = prgpvarg[i] = &rgvarg[i]; + if (wParamFlags & PARAMFLAG_FHASDEFAULT) + { + hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue); + if (FAILED(hres)) + break; + } + else + { + VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams); + V_VT(arg) = VT_VARIANT | VT_BYREF; + V_VARIANTREF(arg) = &missing_arg[i]; + V_VT(V_VARIANTREF(arg)) = VT_ERROR; + V_ERROR(V_VARIANTREF(arg)) = DISP_E_PARAMNOTFOUND; + } } else { - if (tdesc->vt == VT_PTR) - arglen = _argsize(tdesc->u.lptdesc->vt); - else - FIXME("set %d to pointer for get (type is %d)\n",i,tdesc->vt); - - /* Supply pointers for the rest, so propertyget works*/ - args[argspos] = (DWORD)&args2[args2pos]; - - /* If pointer to variant, pass reference it. */ - if ((tdesc->vt == VT_PTR) && - (tdesc->u.lptdesc->vt == VT_VARIANT) && - pVarResult - ) - args[argspos]= (DWORD)pVarResult; - argspos += 1; - args2pos += arglen; + hres = DISP_E_BADPARAMCOUNT; + break; } } + if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */ if (func_desc->cParamsOpt < 0) - FIXME("Does not support optional parameters (%d)\n", func_desc->cParamsOpt); - - res = _invoke((*(FARPROC**)pIUnk)[func_desc->oVft/4], - func_desc->callconv, - numargs, - args - ); + { + FIXME("Does not support safearray optional parameters\n"); + hres = DISP_E_BADPARAMCOUNT; + goto func_fail; /* FIXME: we don't free changed types here */ + } + + V_VT(&varresult) = 0; + hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult)); + if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */ + + hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv, + V_VT(&varresult), func_desc->cParams, rgvt, + prgpvarg, &varresult);
for (i = 0; i < func_desc->cParams; i++) { USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags; if (wParamFlags & PARAMFLAG_FRETVAL) { - ELEMDESC *elemdesc = &func_desc->lprgelemdescParam[i]; - TYPEDESC *tdesc = &elemdesc->tdesc; - VARIANTARG varresult; - V_VT(&varresult) = 0; - hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &V_VT(&varresult)); - if (hres) - break; - /* FIXME: this is really messy - we should keep the - * args in VARIANTARGs rather than a DWORD array */ - memcpy(&V_UI4(&varresult), &args[i+1], sizeof(DWORD)); if (TRACE_ON(ole)) { - TRACE("varresult: "); - dump_Variant(&varresult); + TRACE("[retval] value: "); + dump_Variant(prgpvarg[i]); }
if (pVarResult) /* deref return value */ - hres = VariantCopyInd(pVarResult, &varresult); + hres = VariantCopyInd(pVarResult, prgpvarg[i]);
/* free data stored in varresult. Note that * VariantClear doesn't do what we want because we are * working with byref types. */ /* FIXME: clear safearrays, bstrs, records and - * variants here too */ - if ((V_VT(&varresult) == (VT_UNKNOWN | VT_BYREF)) || - (V_VT(&varresult) == (VT_DISPATCH | VT_BYREF))) + * variants here too */ + if ((V_VT(prgpvarg[i]) == (VT_UNKNOWN | VT_BYREF)) || + (V_VT(prgpvarg[i]) == (VT_DISPATCH | VT_BYREF))) { - if(*V_UNKNOWNREF(&varresult)) - IUnknown_Release(*V_UNKNOWNREF(&varresult)); + if(*V_UNKNOWNREF(prgpvarg[i])) + IUnknown_Release(*V_UNKNOWNREF(prgpvarg[i])); } break; } + else if (i < pDispParams->cArgs) + { + if (wParamFlags & PARAMFLAG_FOUT) + { + hres = VariantChangeType(&pDispParams->rgvarg[pDispParams->cArgs - 1 - i], + &rgvarg[i], 0, + V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - i])); + if (FAILED(hres)) + { + ERR("failed to convert param %d to vt %d\n", i, + V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - i])); + break; + } + } + VariantClear(&rgvarg[i]); + } + else if (wParamFlags & PARAMFLAG_FOPT) + { + if (wParamFlags & PARAMFLAG_FHASDEFAULT) + VariantClear(&rgvarg[i]); + } }
- if ((func_desc->elemdescFunc.tdesc.vt == VT_HRESULT) && FAILED(res)) + if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult))) { - WARN("invoked function failed with error 0x%08lx\n", res); + WARN("invoked function failed with error 0x%08lx\n", V_ERROR(&varresult)); hres = DISP_E_EXCEPTION; - if (pExcepInfo) pExcepInfo->scode = res; + if (pExcepInfo) pExcepInfo->scode = V_ERROR(&varresult); }
func_fail: - HeapFree(GetProcessHeap(), 0, rgvarg); - HeapFree(GetProcessHeap(),0,args2); - HeapFree(GetProcessHeap(),0,args); + HeapFree(GetProcessHeap(), 0, buffer); break; - } + } case FUNC_DISPATCH: { IDispatch *disp;
@@ -5562,8 +5429,8 @@ DWORD *pdwHelpContext, BSTR *pBstrHelpFile) { ITypeInfoImpl *This = (ITypeInfoImpl *)iface; - TLBFuncDesc * pFDesc; - TLBVarDesc * pVDesc; + const TLBFuncDesc *pFDesc; + const TLBVarDesc *pVDesc; TRACE("(%p) memid %ld Name(%p) DocString(%p)" " HelpContext(%p) HelpFile(%p)\n", This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile); @@ -5613,7 +5480,7 @@ WORD *pwOrdinal) { ITypeInfoImpl *This = (ITypeInfoImpl *)iface; - TLBFuncDesc *pFDesc; + const TLBFuncDesc *pFDesc;
TRACE("(%p)->(memid %lx, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
@@ -5947,7 +5814,7 @@ MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex) { ITypeInfoImpl *This = (ITypeInfoImpl *)iface; - TLBFuncDesc *pFuncInfo; + const TLBFuncDesc *pFuncInfo; int i; HRESULT result;
@@ -6171,8 +6038,8 @@ BSTR *pbstrHelpStringDll) { ITypeInfoImpl *This = (ITypeInfoImpl *)iface; - TLBFuncDesc * pFDesc; - TLBVarDesc * pVDesc; + const TLBFuncDesc *pFDesc; + const TLBVarDesc *pVDesc; TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) " "HelpStringContext(%p) HelpStringDll(%p)\n", This, memid, lcid, pbstrHelpString, pdwHelpStringContext, @@ -6458,41 +6325,49 @@ LCID lcid, /* [I] Locale Id */ ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */ { - ITypeInfoImpl *pTIImpl; + ITypeInfoImpl *pTIClass, *pTIIface; + ITypeLibImpl *pTypeLibImpl; int param, func; TLBFuncDesc **ppFuncDesc;
- pTIImpl = (ITypeInfoImpl*)ITypeInfo_Constructor(); - pTIImpl->pTypeLib = NULL; - pTIImpl->index = 0; - pTIImpl->Name = NULL; - pTIImpl->dwHelpContext = -1; - memset(&pTIImpl->TypeAttr.guid, 0, sizeof(GUID)); - pTIImpl->TypeAttr.lcid = lcid; - pTIImpl->TypeAttr.typekind = TKIND_COCLASS; - pTIImpl->TypeAttr.wMajorVerNum = 0; - pTIImpl->TypeAttr.wMinorVerNum = 0; - pTIImpl->TypeAttr.cbAlignment = 2; - pTIImpl->TypeAttr.cbSizeInstance = -1; - pTIImpl->TypeAttr.cbSizeVft = -1; - pTIImpl->TypeAttr.cFuncs = 0; - pTIImpl->TypeAttr.cImplTypes = 1; - pTIImpl->TypeAttr.cVars = 0; - pTIImpl->TypeAttr.wTypeFlags = 0; - - ppFuncDesc = &pTIImpl->funclist; + TRACE_(typelib)("\n"); + pTypeLibImpl = TypeLibImpl_Constructor(); + if (!pTypeLibImpl) return E_FAIL; + + pTIIface = (ITypeInfoImpl*)ITypeInfo_Constructor(); + pTIIface->pTypeLib = pTypeLibImpl; + pTIIface->index = 0; + pTIIface->Name = NULL; + pTIIface->dwHelpContext = -1; + memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID)); + pTIIface->TypeAttr.lcid = lcid; + pTIIface->TypeAttr.typekind = TKIND_INTERFACE; + pTIIface->TypeAttr.wMajorVerNum = 0; + pTIIface->TypeAttr.wMinorVerNum = 0; + pTIIface->TypeAttr.cbAlignment = 2; + pTIIface->TypeAttr.cbSizeInstance = -1; + pTIIface->TypeAttr.cbSizeVft = -1; + pTIIface->TypeAttr.cFuncs = 0; + pTIIface->TypeAttr.cImplTypes = 0; + pTIIface->TypeAttr.cVars = 0; + pTIIface->TypeAttr.wTypeFlags = 0; + + ppFuncDesc = &pTIIface->funclist; for(func = 0; func < pidata->cMembers; func++) { METHODDATA *md = pidata->pmethdata + func; *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc)); (*ppFuncDesc)->Name = SysAllocString(md->szName); (*ppFuncDesc)->funcdesc.memid = md->dispid; + (*ppFuncDesc)->funcdesc.funckind = FUNC_VIRTUAL; (*ppFuncDesc)->funcdesc.invkind = md->wFlags; (*ppFuncDesc)->funcdesc.callconv = md->cc; (*ppFuncDesc)->funcdesc.cParams = md->cArgs; (*ppFuncDesc)->funcdesc.cParamsOpt = 0; - (*ppFuncDesc)->funcdesc.oVft = md->iMeth; - (*ppFuncDesc)->funcdesc.wFuncFlags = 0; /*??*/ + (*ppFuncDesc)->funcdesc.oVft = md->iMeth << 2; + (*ppFuncDesc)->funcdesc.wFuncFlags = 0; (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn; + (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE; + (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL; (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, md->cArgs * sizeof(ELEMDESC)); (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, @@ -6501,9 +6376,49 @@ (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt; (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName); } + (*ppFuncDesc)->helpcontext = 0; + (*ppFuncDesc)->HelpStringContext = 0; + (*ppFuncDesc)->HelpString = NULL; + (*ppFuncDesc)->Entry = NULL; + (*ppFuncDesc)->ctCustData = 0; + (*ppFuncDesc)->pCustData = NULL; + (*ppFuncDesc)->next = NULL; ppFuncDesc = &(*ppFuncDesc)->next; - } - *pptinfo = (ITypeInfo*)pTIImpl; + } + + pTypeLibImpl->pTypeInfo = pTIIface; + pTypeLibImpl->TypeInfoCount++; + + pTIClass = (ITypeInfoImpl*)ITypeInfo_Constructor(); + pTIClass->pTypeLib = pTypeLibImpl; + pTIClass->index = 1; + pTIClass->Name = NULL; + pTIClass->dwHelpContext = -1; + memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID)); + pTIClass->TypeAttr.lcid = lcid; + pTIClass->TypeAttr.typekind = TKIND_COCLASS; + pTIClass->TypeAttr.wMajorVerNum = 0; + pTIClass->TypeAttr.wMinorVerNum = 0; + pTIClass->TypeAttr.cbAlignment = 2; + pTIClass->TypeAttr.cbSizeInstance = -1; + pTIClass->TypeAttr.cbSizeVft = -1; + pTIClass->TypeAttr.cFuncs = 0; + pTIClass->TypeAttr.cImplTypes = 1; + pTIClass->TypeAttr.cVars = 0; + pTIClass->TypeAttr.wTypeFlags = 0; + + pTIClass->impltypelist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->impltypelist)); + pTIClass->impltypelist->hRef = 1; + + pTIClass->reflist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->reflist)); + pTIClass->reflist->index = 0; + pTIClass->reflist->reference = 1; + pTIClass->reflist->pImpTLInfo = TLB_REF_INTERNAL; + + pTIIface->next = pTIClass; + pTypeLibImpl->TypeInfoCount++; + + *pptinfo = (ITypeInfo*)pTIClass; return S_OK;
} @@ -6539,8 +6454,8 @@ BINDPTR * pBindPtr) { ITypeInfoImpl *This = info_impl_from_ITypeComp(iface); - TLBFuncDesc * pFDesc; - TLBVarDesc * pVDesc; + const TLBFuncDesc *pFDesc; + const TLBVarDesc *pVDesc;
TRACE("(%s, %lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
Modified: trunk/reactos/dll/win32/oleaut32/usrmarshal.c URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/dll/win32/oleaut32/usrmarsha... ============================================================================== --- trunk/reactos/dll/win32/oleaut32/usrmarshal.c (original) +++ trunk/reactos/dll/win32/oleaut32/usrmarshal.c Mon Mar 27 20:44:53 2006 @@ -60,6 +60,22 @@ { return NdrDllGetClassObject(rclsid, riid, ppv, OLEAUT32_ProxyFileList, &CLSID_PSDispatch, &PSFactoryBuffer); +} + +static void dump_user_flags(unsigned long *pFlags) +{ + if (HIWORD(*pFlags) == NDR_LOCAL_DATA_REPRESENTATION) + TRACE("MAKELONG(NDR_LOCAL_REPRESENTATION, "); + else + TRACE("MAKELONG(0x%04x, ", HIWORD(*pFlags)); + switch (LOWORD(*pFlags)) + { + case MSHCTX_LOCAL: TRACE("MSHCTX_LOCAL)"); break; + case MSHCTX_NOSHAREDMEM: TRACE("MSHCTX_NOSHAREDMEM)"); break; + case MSHCTX_DIFFERENTMACHINE: TRACE("MSHCTX_DIFFERENTMACHINE)"); break; + case MSHCTX_INPROC: TRACE("MSHCTX_INPROC)"); break; + default: TRACE("%d)", LOWORD(*pFlags)); + } }
/* CLEANLOCALSTORAGE */ @@ -516,6 +532,402 @@ CoTaskMemFree(ref); }
+/* LPSAFEARRAY */ + +/* Get the number of cells in a SafeArray */ +static ULONG SAFEARRAY_GetCellCount(const SAFEARRAY *psa) +{ + const SAFEARRAYBOUND* psab = psa->rgsabound; + USHORT cCount = psa->cDims; + ULONG ulNumCells = 1; + + while (cCount--) + { + /* This is a valid bordercase. See testcases. -Marcus */ + if (!psab->cElements) + return 0; + ulNumCells *= psab->cElements; + psab++; + } + return ulNumCells; +} + +static inline SF_TYPE SAFEARRAY_GetUnionType(SAFEARRAY *psa) +{ + VARTYPE vt; + HRESULT hr; + + hr = SafeArrayGetVartype(psa, &vt); + if (FAILED(hr)) + RpcRaiseException(hr); + + if (psa->fFeatures & FADF_HAVEIID) + return SF_HAVEIID; + + switch (vt) + { + case VT_I1: + case VT_UI1: return SF_I1; + case VT_BOOL: + case VT_I2: + case VT_UI2: return SF_I2; + case VT_INT: + case VT_UINT: + case VT_I4: + case VT_UI4: + case VT_R4: return SF_I4; + case VT_DATE: + case VT_CY: + case VT_R8: + case VT_I8: + case VT_UI8: return SF_I8; + case VT_INT_PTR: + case VT_UINT_PTR: return (sizeof(UINT_PTR) == 4 ? SF_I4 : SF_I8); + case VT_BSTR: return SF_BSTR; + case VT_DISPATCH: return SF_DISPATCH; + case VT_VARIANT: return SF_VARIANT; + case VT_UNKNOWN: return SF_UNKNOWN; + /* Note: Return a non-zero size to indicate vt is valid. The actual size + * of a UDT is taken from the result of IRecordInfo_GetSize(). + */ + case VT_RECORD: return SF_RECORD; + default: return SF_ERROR; + } +} + +unsigned long WINAPI LPSAFEARRAY_UserSize(unsigned long *pFlags, unsigned long StartingSize, LPSAFEARRAY *ppsa) +{ + unsigned long size = StartingSize; + + TRACE("("); dump_user_flags(pFlags); TRACE(", %ld, %p\n", StartingSize, *ppsa); + + size += sizeof(ULONG_PTR); + if (*ppsa) + { + SAFEARRAY *psa = *ppsa; + ULONG ulCellCount = SAFEARRAY_GetCellCount(psa); + SF_TYPE sftype; + HRESULT hr; + + size += sizeof(ULONG); + size += FIELD_OFFSET(struct _wireSAFEARRAY, uArrayStructs); + + sftype = SAFEARRAY_GetUnionType(psa); + size += sizeof(ULONG); + + size += sizeof(ULONG); + size += sizeof(ULONG_PTR); + if (sftype == SF_HAVEIID) + size += sizeof(IID); + + size += sizeof(psa->rgsabound[0]) * psa->cDims; + + size += sizeof(ULONG); + + switch (sftype) + { + case SF_BSTR: + { + BSTR* lpBstr; + + for (lpBstr = (BSTR*)psa->pvData; ulCellCount; ulCellCount--, lpBstr++) + size = BSTR_UserSize(pFlags, size, lpBstr); + + break; + } + case SF_DISPATCH: + case SF_UNKNOWN: + case SF_HAVEIID: + FIXME("size interfaces\n"); + break; + case SF_VARIANT: + { + VARIANT* lpVariant; + + for (lpVariant = (VARIANT*)psa->pvData; ulCellCount; ulCellCount--, lpVariant++) + size = VARIANT_UserSize(pFlags, size, lpVariant); + + break; + } + case SF_RECORD: + { + IRecordInfo* pRecInfo = NULL; + + hr = SafeArrayGetRecordInfo(psa, &pRecInfo); + if (FAILED(hr)) + RpcRaiseException(hr); + + if (pRecInfo) + { + FIXME("size record info %p\n", pRecInfo); + + IRecordInfo_Release(pRecInfo); + } + break; + } + case SF_I1: + case SF_I2: + case SF_I4: + case SF_I8: + size += ulCellCount * psa->cbElements; + break; + default: + break; + } + + } + + return size; +} + +unsigned char * WINAPI LPSAFEARRAY_UserMarshal(unsigned long *pFlags, unsigned char *Buffer, LPSAFEARRAY *ppsa) +{ + HRESULT hr; + + TRACE("("); dump_user_flags(pFlags); TRACE(", %p, &%p\n", Buffer, *ppsa); + + *(ULONG_PTR *)Buffer = *ppsa ? TRUE : FALSE; + Buffer += sizeof(ULONG_PTR); + if (*ppsa) + { + VARTYPE vt; + SAFEARRAY *psa = *ppsa; + ULONG ulCellCount = SAFEARRAY_GetCellCount(psa); + wireSAFEARRAY wiresa; + SF_TYPE sftype; + GUID guid; + + *(ULONG *)Buffer = psa->cDims; + Buffer += sizeof(ULONG); + wiresa = (wireSAFEARRAY)Buffer; + wiresa->cDims = psa->cDims; + wiresa->fFeatures = psa->fFeatures; + wiresa->cbElements = psa->cbElements; + + hr = SafeArrayGetVartype(psa, &vt); + if (FAILED(hr)) + RpcRaiseException(hr); + wiresa->cLocks = (USHORT)psa->cLocks | (vt << 16); + + Buffer += FIELD_OFFSET(struct _wireSAFEARRAY, uArrayStructs); + + sftype = SAFEARRAY_GetUnionType(psa); + *(ULONG *)Buffer = sftype; + Buffer += sizeof(ULONG); + + *(ULONG *)Buffer = ulCellCount; + Buffer += sizeof(ULONG); + *(ULONG_PTR *)Buffer = (ULONG_PTR)psa->pvData; + Buffer += sizeof(ULONG_PTR); + if (sftype == SF_HAVEIID) + { + SafeArrayGetIID(psa, &guid); + memcpy(Buffer, &guid, sizeof(guid)); + Buffer += sizeof(guid); + } + + memcpy(Buffer, psa->rgsabound, sizeof(psa->rgsabound[0]) * psa->cDims); + Buffer += sizeof(psa->rgsabound[0]) * psa->cDims; + + *(ULONG *)Buffer = ulCellCount; + Buffer += sizeof(ULONG); + + if (psa->pvData) + { + switch (sftype) + { + case SF_BSTR: + { + BSTR* lpBstr; + + for (lpBstr = (BSTR*)psa->pvData; ulCellCount; ulCellCount--, lpBstr++) + Buffer = BSTR_UserMarshal(pFlags, Buffer, lpBstr); + + break; + } + case SF_DISPATCH: + case SF_UNKNOWN: + case SF_HAVEIID: + FIXME("marshal interfaces\n"); + break; + case SF_VARIANT: + { + VARIANT* lpVariant; + + for (lpVariant = (VARIANT*)psa->pvData; ulCellCount; ulCellCount--, lpVariant++) + Buffer = VARIANT_UserMarshal(pFlags, Buffer, lpVariant); + + break; + } + case SF_RECORD: + { + IRecordInfo* pRecInfo = NULL; + + hr = SafeArrayGetRecordInfo(psa, &pRecInfo); + if (FAILED(hr)) + RpcRaiseException(hr); + + if (pRecInfo) + { + FIXME("write record info %p\n", pRecInfo); + + IRecordInfo_Release(pRecInfo); + } + break; + } + case SF_I1: + case SF_I2: + case SF_I4: + case SF_I8: + /* Just copy the data over */ + memcpy(Buffer, psa->pvData, ulCellCount * psa->cbElements); + Buffer += ulCellCount * psa->cbElements; + break; + default: + break; + } + } + + } + return Buffer; +} + +#define FADF_AUTOSETFLAGS (FADF_HAVEIID | FADF_RECORD | FADF_HAVEVARTYPE | \ + FADF_BSTR | FADF_UNKNOWN | FADF_DISPATCH | \ + FADF_VARIANT | FADF_CREATEVECTOR) + +unsigned char * WINAPI LPSAFEARRAY_UserUnmarshal(unsigned long *pFlags, unsigned char *Buffer, LPSAFEARRAY *ppsa) +{ + ULONG_PTR ptr; + wireSAFEARRAY wiresa; + ULONG cDims; + HRESULT hr; + SF_TYPE sftype; + ULONG cell_count; + GUID guid; + VARTYPE vt; + SAFEARRAYBOUND *wiresab; + + TRACE("("); dump_user_flags(pFlags); TRACE(", %p, %p\n", Buffer, ppsa); + + ptr = *(ULONG_PTR *)Buffer; + Buffer += sizeof(ULONG_PTR); + + if (!ptr) + { + *ppsa = NULL; + + TRACE("NULL safe array unmarshaled\n"); + + return Buffer; + } + + cDims = *(ULONG *)Buffer; + Buffer += sizeof(ULONG); + + wiresa = (wireSAFEARRAY)Buffer; + Buffer += FIELD_OFFSET(struct _wireSAFEARRAY, uArrayStructs); + + if (cDims != wiresa->cDims) + RpcRaiseException(RPC_S_INVALID_BOUND); + + /* FIXME: there should be a limit on how large cDims can be */ + + vt = HIWORD(wiresa->cLocks); + + sftype = *(ULONG *)Buffer; + Buffer += sizeof(ULONG); + + cell_count = *(ULONG *)Buffer; + Buffer += sizeof(ULONG); + ptr = *(ULONG_PTR *)Buffer; + Buffer += sizeof(ULONG_PTR); + if (sftype == SF_HAVEIID) + { + memcpy(&guid, Buffer, sizeof(guid)); + Buffer += sizeof(guid); + } + + wiresab = (SAFEARRAYBOUND *)Buffer; + Buffer += sizeof(wiresab[0]) * wiresa->cDims; + + *ppsa = SafeArrayCreateEx(vt, wiresa->cDims, wiresab, NULL); + if (!ppsa) + RpcRaiseException(E_OUTOFMEMORY); + + /* be careful about which flags we set since they could be a security + * risk */ + (*ppsa)->fFeatures = wiresa->fFeatures & ~(FADF_AUTOSETFLAGS); + /* FIXME: there should be a limit on how large wiresa->cbElements can be */ + (*ppsa)->cbElements = wiresa->cbElements; + (*ppsa)->cLocks = LOWORD(wiresa->cLocks); + + hr = SafeArrayAllocData(*ppsa); + if (FAILED(hr)) + RpcRaiseException(hr); + + if ((*(ULONG *)Buffer != cell_count) || (SAFEARRAY_GetCellCount(*ppsa) != cell_count)) + RpcRaiseException(RPC_S_INVALID_BOUND); + Buffer += sizeof(ULONG); + + if (ptr) + { + switch (sftype) + { + case SF_BSTR: + { + BSTR* lpBstr; + + for (lpBstr = (BSTR*)(*ppsa)->pvData; cell_count; cell_count--, lpBstr++) + Buffer = BSTR_UserUnmarshal(pFlags, Buffer, lpBstr); + + break; + } + case SF_DISPATCH: + case SF_UNKNOWN: + case SF_HAVEIID: + FIXME("marshal interfaces\n"); + break; + case SF_VARIANT: + { + VARIANT* lpVariant; + + for (lpVariant = (VARIANT*)(*ppsa)->pvData; cell_count; cell_count--, lpVariant++) + Buffer = VARIANT_UserUnmarshal(pFlags, Buffer, lpVariant); + + break; + } + case SF_RECORD: + { + FIXME("set record info\n"); + + break; + } + case SF_I1: + case SF_I2: + case SF_I4: + case SF_I8: + /* Just copy the data over */ + memcpy((*ppsa)->pvData, Buffer, cell_count * (*ppsa)->cbElements); + Buffer += cell_count * (*ppsa)->cbElements; + break; + default: + break; + } + } + + TRACE("safe array unmarshaled: %p\n", *ppsa); + + return Buffer; +} + +void WINAPI LPSAFEARRAY_UserFree(unsigned long *pFlags, LPSAFEARRAY *ppsa) +{ + TRACE("("); dump_user_flags(pFlags); TRACE(", &%p\n", *ppsa); + + SafeArrayDestroy(*ppsa); +} + /* IDispatch */ /* exactly how Invoke is marshalled is not very clear to me yet, * but the way I've done it seems to work for me */
Modified: trunk/reactos/dll/win32/oleaut32/varformat.c URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/dll/win32/oleaut32/varformat... ============================================================================== --- trunk/reactos/dll/win32/oleaut32/varformat.c (original) +++ trunk/reactos/dll/win32/oleaut32/varformat.c Mon Mar 27 20:44:53 2006 @@ -1983,7 +1983,7 @@ #define NUMBER_VTBITS (VTBIT_I1|VTBIT_UI1|VTBIT_I2|VTBIT_UI2| \ VTBIT_I4|VTBIT_UI4|VTBIT_I8|VTBIT_UI8| \ VTBIT_R4|VTBIT_R8|VTBIT_CY|VTBIT_DECIMAL| \ - (1<<VT_BOOL)|(1<<VT_INT)|(1<<VT_UINT)) + VTBIT_BOOL|VTBIT_INT|VTBIT_UINT)
/********************************************************************** * VarFormatFromTokens [OLEAUT32.139] @@ -2006,6 +2006,9 @@
if (!pVarIn || !rgbTok) return E_INVALIDARG; + + if (V_VT(pVarIn) == VT_NULL) + return S_OK;
if (*rgbTok == FMT_TO_STRING || header->type == FMT_TYPE_GENERAL) {
Modified: trunk/reactos/dll/win32/oleaut32/variant.c URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/dll/win32/oleaut32/variant.c... ============================================================================== --- trunk/reactos/dll/win32/oleaut32/variant.c (original) +++ trunk/reactos/dll/win32/oleaut32/variant.c Mon Mar 27 20:44:53 2006 @@ -2500,199 +2500,231 @@ return S_OK; }
+/* Wrapper around VariantChangeTypeEx() which permits changing a + variant with VT_RESERVED flag set. Needed by VarCmp. */ +static HRESULT _VarChangeTypeExWrap (VARIANTARG* pvargDest, + VARIANTARG* pvargSrc, LCID lcid, USHORT wFlags, VARTYPE vt) +{ + HRESULT res; + VARTYPE flags; + + flags = V_VT(pvargSrc) & ~VT_TYPEMASK; + V_VT(pvargSrc) &= ~VT_RESERVED; + res = VariantChangeTypeEx(pvargDest,pvargSrc,lcid,wFlags,vt); + V_VT(pvargSrc) |= flags; + + return res; +} + /********************************************************************** * VarCmp [OLEAUT32.176] * - * flags can be: - * NORM_IGNORECASE, NORM_IGNORENONSPACE, NORM_IGNORESYMBOLS - * NORM_IGNOREWIDTH, NORM_IGNOREKANATYPE, NORM_IGNOREKASHIDA - * + * Compare two variants. + * + * PARAMS + * left [I] First variant + * right [I] Second variant + * lcid [I] LCID (locale identifier) for the comparison + * flags [I] Flags to be used in the comparision: + * NORM_IGNORECASE, NORM_IGNORENONSPACE, NORM_IGNORESYMBOLS, + * NORM_IGNOREWIDTH, NORM_IGNOREKANATYPE, NORM_IGNOREKASHIDA + * + * RETURNS + * VARCMP_LT: left variant is less than right variant. + * VARCMP_EQ: input variants are equal. + * VARCMP_LT: left variant is greater than right variant. + * VARCMP_NULL: either one of the input variants is NULL. + * Failure: An HRESULT error code indicating the error. + * + * NOTES + * Native VarCmp up to and including WinXP dosn't like as input variants + * I1, UI2, VT_UI4, UI8 and UINT. INT is accepted only as left variant. + * + * If both input variants are ERROR then VARCMP_EQ will be returned, else + * an ERROR variant will trigger an error. + * + * Both input variants can have VT_RESERVED flag set which is ignored + * unless one and only one of the variants is a BSTR and the other one + * is not an EMPTY variant. All four VT_RESERVED combinations have a + * different meaning: + * - BSTR and other: BSTR is always greater than the other variant. + * - BSTR|VT_RESERVED and other: a string comparision is performed. + * - BSTR and other|VT_RESERVED: If the BSTR is a number a numeric + * comparision will take place else the BSTR is always greater. + * - BSTR|VT_RESERVED and other|VT_RESERVED: It seems that the other + * variant is ignored and the return value depends only on the sign + * of the BSTR if it is a number else the BSTR is always greater. A + * positive BSTR is greater, a negative one is smaller than the other + * variant. + * + * SEE + * VarBstrCmp for the lcid and flags usage. */ HRESULT WINAPI VarCmp(LPVARIANT left, LPVARIANT right, LCID lcid, DWORD flags) { - BOOL lOk = TRUE; - BOOL rOk = TRUE; - BOOL l_isR = FALSE; - BOOL r_isR = FALSE; - LONGLONG lVal = -1; - LONGLONG rVal = -1; - VARIANT rv,lv; - DWORD xmask; - HRESULT rc; - double lDouble =0.0,rDouble=0.0; + VARTYPE lvt, rvt, vt; + VARIANT rv,lv; + DWORD xmask; + HRESULT rc;
TRACE("(%p->(%s%s),%p->(%s%s),0x%08lx,0x%08lx)\n", left, debugstr_VT(left), debugstr_VF(left), right, debugstr_VT(right), debugstr_VF(right), lcid, flags);
- VariantInit(&lv);VariantInit(&rv); - V_VT(right) &= ~0x8000; /* hack since we sometime get this flag. */ - V_VT(left) &= ~0x8000; /* hack since we sometime get this flag. */ - - /* If either are null, then return VARCMP_NULL */ - if ((V_VT(left)&VT_TYPEMASK) == VT_NULL || - (V_VT(right)&VT_TYPEMASK) == VT_NULL) + lvt = V_VT(left) & VT_TYPEMASK; + rvt = V_VT(right) & VT_TYPEMASK; + xmask = (1 << lvt) | (1 << rvt); + + /* If we have any flag set except VT_RESERVED bail out. + Same for the left input variant type > VT_INT and for the + right input variant type > VT_I8. Yes, VT_INT is only supported + as left variant. Go figure */ + if (((V_VT(left) | V_VT(right)) & ~VT_TYPEMASK & ~VT_RESERVED) || + lvt > VT_INT || rvt > VT_I8) { + return DISP_E_BADVARTYPE; + } + + /* Don't ask me why but native VarCmp cannot handle: VT_I1, VT_UI2, VT_UI4, + VT_UINT and VT_UI8. Tested with DCOM98, Win2k, WinXP */ + if (rvt == VT_INT || xmask & (VTBIT_I1 | VTBIT_UI2 | VTBIT_UI4 | VTBIT_UI8 | + VTBIT_DISPATCH | VTBIT_VARIANT | VTBIT_UNKNOWN | VTBIT_15)) + return DISP_E_TYPEMISMATCH; + + /* If both variants are VT_ERROR return VARCMP_EQ */ + if (xmask == VTBIT_ERROR) + return VARCMP_EQ; + else if (xmask & VTBIT_ERROR) + return DISP_E_TYPEMISMATCH; + + if (xmask & VTBIT_NULL) return VARCMP_NULL;
- /* Strings - use VarBstrCmp */ - if ((V_VT(left)&VT_TYPEMASK) == VT_BSTR && - (V_VT(right)&VT_TYPEMASK) == VT_BSTR) { + VariantInit(&lv); + VariantInit(&rv); + + /* Two BSTRs, ignore VT_RESERVED */ + if (xmask == VTBIT_BSTR) return VarBstrCmp(V_BSTR(left), V_BSTR(right), lcid, flags); - } - - xmask = (1<<(V_VT(left)&VT_TYPEMASK))|(1<<(V_VT(right)&VT_TYPEMASK)); - if (xmask & VTBIT_DECIMAL) { - rc = VariantChangeType(&lv,left,0,VT_DECIMAL); - if (FAILED(rc)) return rc; - rc = VariantChangeType(&rv,right,0,VT_DECIMAL); - if (FAILED(rc)) return rc; - return VarDecCmp(&V_DECIMAL(&lv), &V_DECIMAL(&rv)); - } - if (xmask & VTBIT_R8) { - rc = VariantChangeType(&lv,left,0,VT_R8); - if (FAILED(rc)) return rc; - rc = VariantChangeType(&rv,right,0,VT_R8); - if (FAILED(rc)) return rc; - - if (V_R8(&lv) == V_R8(&rv)) return VARCMP_EQ; - if (V_R8(&lv) < V_R8(&rv)) return VARCMP_LT; - if (V_R8(&lv) > V_R8(&rv)) return VARCMP_GT; - return E_FAIL; /* can't get here */ - } - if (xmask & VTBIT_R4) { - rc = VariantChangeType(&lv,left,0,VT_R4); - if (FAILED(rc)) return rc; - rc = VariantChangeType(&rv,right,0,VT_R4); - if (FAILED(rc)) return rc; - - if (V_R4(&lv) == V_R4(&rv)) return VARCMP_EQ; - if (V_R4(&lv) < V_R4(&rv)) return VARCMP_LT; - if (V_R4(&lv) > V_R4(&rv)) return VARCMP_GT; - return E_FAIL; /* can't get here */ - } - - /* Integers - Ideally like to use VarDecCmp, but no Dec support yet - Use LONGLONG to maximize ranges */ - lOk = TRUE; - switch (V_VT(left)&VT_TYPEMASK) { - case VT_I1 : lVal = V_I1(left); break; - case VT_I2 : lVal = V_I2(left); break; - case VT_I4 : - case VT_INT : lVal = V_I4(left); break; - case VT_UI1 : lVal = V_UI1(left); break; - case VT_UI2 : lVal = V_UI2(left); break; - case VT_UI4 : - case VT_UINT : lVal = V_UI4(left); break; - case VT_BOOL : lVal = V_BOOL(left); break; - case VT_EMPTY : lVal = 0; break; - case VT_R4 : lDouble = V_R4(left); lOk = FALSE; l_isR= TRUE; break; - case VT_R8 : lDouble = V_R8(left); lOk = FALSE; l_isR= TRUE; break; - default: lOk = FALSE; - } - - rOk = TRUE; - switch (V_VT(right)&VT_TYPEMASK) { - case VT_I1 : rVal = V_I1(right); break; - case VT_I2 : rVal = V_I2(right); break; - case VT_I4 : - case VT_INT : rVal = V_I4(right); break; - case VT_UI1 : rVal = V_UI1(right); break; - case VT_UI2 : rVal = V_UI2(right); break; - case VT_UI4 : - case VT_UINT : rVal = V_UI4(right); break; - case VT_BOOL : rVal = V_BOOL(right); break; - case VT_EMPTY : rVal = 0; break; - case VT_R4 : rDouble = V_R4(right); rOk = FALSE;r_isR= TRUE; break; - case VT_R8 : rDouble = V_R8(right); rOk = FALSE;r_isR= TRUE; break; - default: rOk = FALSE; - } - - if (lOk && rOk) { - if (lVal < rVal) { - return VARCMP_LT; - } else if (lVal > rVal) { - return VARCMP_GT; + + /* A BSTR and an other variant; we have to take care of VT_RESERVED */ + if (xmask & VTBIT_BSTR) { + VARIANT *bstrv, *nonbv; + VARTYPE nonbvt; + int swap = 0; + + /* Swap the variants so the BSTR is always on the left */ + if (lvt == VT_BSTR) { + bstrv = left; + nonbv = right; + nonbvt = rvt; } else { - return VARCMP_EQ; + swap = 1; + bstrv = right; + nonbv = left; + nonbvt = lvt; } - } - else if (l_isR && r_isR) { - if (lDouble < rDouble) { - return VARCMP_LT; - } else if (lDouble > rDouble) { - return VARCMP_GT; - } else { - return VARCMP_EQ; + + /* BSTR and EMPTY: ignore VT_RESERVED */ + if (nonbvt == VT_EMPTY) + rc = (!V_BSTR(bstrv) || !*V_BSTR(bstrv)) ? VARCMP_EQ : VARCMP_GT; + else { + VARTYPE breserv = V_VT(bstrv) & ~VT_TYPEMASK; + VARTYPE nreserv = V_VT(nonbv) & ~VT_TYPEMASK; + + if (!breserv && !nreserv) + /* No VT_RESERVED set ==> BSTR always greater */ + rc = VARCMP_GT; + else if (breserv && !nreserv) { + /* BSTR has VT_RESERVED set. Do a string comparision */ + rc = VariantChangeTypeEx(&rv,nonbv,lcid,0,VT_BSTR); + if (FAILED(rc)) + return rc; + rc = VarBstrCmp(V_BSTR(bstrv), V_BSTR(&rv), lcid, flags); + } else if (V_BSTR(bstrv) && *V_BSTR(bstrv)) { + /* Non NULL nor empty BSTR */ + /* If the BSTR is not a number the BSTR is greater */ + rc = _VarChangeTypeExWrap(&lv,bstrv,lcid,0,VT_R8); + if (FAILED(rc)) + rc = VARCMP_GT; + else if (breserv && nreserv) + /* FIXME: This is strange: with both VT_RESERVED set it + looks like the result depends only on the sign of + the BSTR number */ + rc = (V_R8(&lv) >= 0) ? VARCMP_GT : VARCMP_LT; + else + /* Numeric comparision, will be handled below. + VARCMP_NULL used only to break out. */ + rc = VARCMP_NULL; + VariantClear(&lv); + VariantClear(&rv); + } else + /* Empty or NULL BSTR */ + rc = VARCMP_GT; } - } - else if (lOk && r_isR) { - if (lVal < rDouble) { - return VARCMP_LT; - } else if (lVal > rDouble) { - return VARCMP_GT; - } else { - return VARCMP_EQ; + /* Fixup the return code if we swapped left and right */ + if (swap) { + if (rc == VARCMP_GT) + rc = VARCMP_LT; + else if (rc == VARCMP_LT) + rc = VARCMP_GT; } - } - else if (l_isR && rOk) { - if (lDouble < rVal) { - return VARCMP_LT; - } else if (lDouble > rVal) { - return VARCMP_GT; - } else { - return VARCMP_EQ; - } - } - if ((V_VT(left)&VT_TYPEMASK) == VT_BSTR ) { - if(((V_VT(right)&VT_TYPEMASK) == VT_EMPTY ) && !(V_BSTR(left))) { - return VARCMP_EQ; - } else { - return VARCMP_GT; - } - } - if ((V_VT(right)&VT_TYPEMASK) == VT_BSTR ) { - if(((V_VT(left)&VT_TYPEMASK) == VT_EMPTY ) && !(V_BSTR(right))) { - return VARCMP_EQ; - } else { - return VARCMP_LT; - } - } - /* Dates */ - if ((V_VT(left)&VT_TYPEMASK) == VT_DATE && - (V_VT(right)&VT_TYPEMASK) == VT_DATE) { - - if (floor(V_DATE(left)) == floor(V_DATE(right))) { - /* Due to floating point rounding errors, calculate varDate in whole numbers) */ - double wholePart = 0.0; - double leftR; - double rightR; - - /* Get the fraction * 24*60*60 to make it into whole seconds */ - wholePart = (double) floor( V_DATE(left) ); - if (wholePart == 0) wholePart = 1; - leftR = floor(fmod( V_DATE(left), wholePart ) * (24*60*60)); - - wholePart = (double) floor( V_DATE(right) ); - if (wholePart == 0) wholePart = 1; - rightR = floor(fmod( V_DATE(right), wholePart ) * (24*60*60)); - - if (leftR < rightR) { - return VARCMP_LT; - } else if (leftR > rightR) { - return VARCMP_GT; - } else { - return VARCMP_EQ; - } - - } else if (V_DATE(left) < V_DATE(right)) { - return VARCMP_LT; - } else if (V_DATE(left) > V_DATE(right)) { - return VARCMP_GT; - } - } - else if((V_VT(right)&VT_TYPEMASK) == VT_EMPTY) - return VARCMP_GT; - FIXME("VarCmp partial implementation, doesn't support %s / %s\n",wine_vtypes[V_VT(left)], wine_vtypes[V_VT(right)]); - return E_FAIL; + if (rc != VARCMP_NULL) + return rc; + } + + if (xmask & VTBIT_DECIMAL) + vt = VT_DECIMAL; + else if (xmask & VTBIT_BSTR) + vt = VT_R8; + else if (xmask & VTBIT_R4) + vt = VT_R4; + else if (xmask & (VTBIT_R8 | VTBIT_DATE)) + vt = VT_R8; + else if (xmask & VTBIT_CY) + vt = VT_CY; + else + /* default to I8 */ + vt = VT_I8; + + /* Coerce the variants */ + rc = _VarChangeTypeExWrap(&lv,left,lcid,0,vt); + if (rc == DISP_E_OVERFLOW && vt != VT_R8) { + /* Overflow, change to R8 */ + vt = VT_R8; + rc = _VarChangeTypeExWrap(&lv,left,lcid,0,vt); + } + if (FAILED(rc)) + return rc; + rc = _VarChangeTypeExWrap(&rv,right,lcid,0,vt); + if (rc == DISP_E_OVERFLOW && vt != VT_R8) { + /* Overflow, change to R8 */ + vt = VT_R8; + rc = _VarChangeTypeExWrap(&lv,left,lcid,0,vt); + if (FAILED(rc)) + return rc; + rc = _VarChangeTypeExWrap(&rv,right,lcid,0,vt); + } + if (FAILED(rc)) + return rc; + +#define _VARCMP(a,b) \ + (((a) == (b)) ? VARCMP_EQ : (((a) < (b)) ? VARCMP_LT : VARCMP_GT)) + + switch (vt) { + case VT_CY: + return VarCyCmp(V_CY(&lv), V_CY(&rv)); + case VT_DECIMAL: + return VarDecCmp(&V_DECIMAL(&lv), &V_DECIMAL(&rv)); + case VT_I8: + return _VARCMP(V_I8(&lv), V_I8(&rv)); + case VT_R4: + return _VARCMP(V_R4(&lv), V_R4(&rv)); + case VT_R8: + return _VARCMP(V_R8(&lv), V_R8(&rv)); + default: + /* We should never get here */ + return E_FAIL; + } +#undef _VARCMP }
/********************************************************************** @@ -2920,7 +2952,6 @@
/* Do the math */ hres = S_OK; - V_VT(&tv) = tvt; V_VT(result) = resvt; switch (tvt) { case VT_DECIMAL: @@ -2941,10 +2972,13 @@ V_VT(result) = VT_R8; V_R8(result) = r8res; goto end; - } else + } else { + V_VT(&tv) = tvt; V_I8(&tv) = V_I8(&lv) + V_I8(&rv); + } break; case VT_R8: + V_VT(&tv) = tvt; /* FIXME: overflow detection */ V_R8(&tv) = V_R8(&lv) + V_R8(&rv); break; @@ -3184,7 +3218,7 @@ found = TRUE; resvt = VT_DECIMAL; } - if (!found && (((1<<lvt) | (1<<rvt)) & (VTBIT_I1|VTBIT_I2|VTBIT_UI1|VTBIT_UI2|VTBIT_I4|VTBIT_UI4|(1<<VT_INT)|(1<<VT_UINT)))) { + if (!found && (((1<<lvt) | (1<<rvt)) & (VTBIT_I1|VTBIT_I2|VTBIT_UI1|VTBIT_UI2|VTBIT_I4|VTBIT_UI4|VTBIT_INT|VTBIT_UINT))) { found = TRUE; resvt = VT_I4; } @@ -3253,7 +3287,7 @@ lvt = V_VT(left)&VT_TYPEMASK; rvt = V_VT(right)&VT_TYPEMASK; found = FALSE;resvt = VT_VOID; - if (((1<<lvt) | (1<<rvt)) & ((1<<VT_DATE)|(1<<VT_R4)|(1<<VT_R8))) { + if (((1<<lvt) | (1<<rvt)) & (VTBIT_DATE|VTBIT_R4|VTBIT_R8)) { found = TRUE; resvt = VT_R8; } @@ -3261,7 +3295,7 @@ found = TRUE; resvt = VT_DECIMAL; } - if (!found && (((1<<lvt) | (1<<rvt)) & (VTBIT_I1|VTBIT_I2|VTBIT_UI1|VTBIT_UI2|VTBIT_I4|VTBIT_UI4|(1<<VT_INT)|(1<<VT_UINT)))) { + if (!found && (((1<<lvt) | (1<<rvt)) & (VTBIT_I1|VTBIT_I2|VTBIT_UI1|VTBIT_UI2|VTBIT_I4|VTBIT_UI4|VTBIT_INT|VTBIT_UINT))) { found = TRUE; resvt = VT_I4; }
Modified: trunk/reactos/dll/win32/oleaut32/variant.h URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/dll/win32/oleaut32/variant.h... ============================================================================== --- trunk/reactos/dll/win32/oleaut32/variant.h (original) +++ trunk/reactos/dll/win32/oleaut32/variant.h Mon Mar 27 20:44:53 2006 @@ -33,6 +33,20 @@
/* Get the extra flags from a variant pointer */ #define V_EXTRA_TYPE(v) (V_VT((v)) & VT_EXTRA_TYPE) + +/* Missing in Windows but useful VTBIT_* defines */ +#define VTBIT_BOOL (1 << VT_BSTR) +#define VTBIT_BSTR (1 << VT_BSTR) +#define VTBIT_DATE (1 << VT_DATE) +#define VTBIT_DISPATCH (1 << VT_DISPATCH) +#define VTBIT_EMPTY (1 << VT_EMPTY) +#define VTBIT_ERROR (1 << VT_ERROR) +#define VTBIT_INT (1 << VT_INT) +#define VTBIT_NULL (1 << VT_NULL) +#define VTBIT_UINT (1 << VT_UINT) +#define VTBIT_UNKNOWN (1 << VT_UNKNOWN) +#define VTBIT_VARIANT (1 << VT_VARIANT) +#define VTBIT_15 (1 << 15) /* no variant type with this number */
extern const char* wine_vtypes[]; #define debugstr_vt(v) (((v)&VT_TYPEMASK) <= VT_CLSID ? wine_vtypes[((v)&VT_TYPEMASK)] : \
Modified: trunk/reactos/dll/win32/oleaut32/vartype.c URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/dll/win32/oleaut32/vartype.c... ============================================================================== --- trunk/reactos/dll/win32/oleaut32/vartype.c (original) +++ trunk/reactos/dll/win32/oleaut32/vartype.c Mon Mar 27 20:44:53 2006 @@ -110,7 +110,8 @@ }
/* Coerce VT_DISPATCH to another type */ -static HRESULT VARIANT_FromDisp(IDispatch* pdispIn, LCID lcid, void* pOut, VARTYPE vt) +static HRESULT VARIANT_FromDisp(IDispatch* pdispIn, LCID lcid, void* pOut, + VARTYPE vt, DWORD dwFlags) { static const DISPPARAMS emptyParams = { NULL, NULL, 0, 0 }; VARIANTARG srcVar, dstVar; @@ -127,7 +128,7 @@ { /* Convert the property to the requested type */ V_VT(&dstVar) = VT_EMPTY; - hRet = VariantChangeTypeEx(&dstVar, &srcVar, lcid, 0, vt); + hRet = VariantChangeTypeEx(&dstVar, &srcVar, lcid, dwFlags, vt); VariantClear(&srcVar);
if (SUCCEEDED(hRet)) @@ -448,7 +449,7 @@ */ HRESULT WINAPI VarI1FromDisp(IDispatch* pdispIn, LCID lcid, signed char* pcOut) { - return VARIANT_FromDisp(pdispIn, lcid, pcOut, VT_I1); + return VARIANT_FromDisp(pdispIn, lcid, pcOut, VT_I1, 0); }
/************************************************************************ @@ -741,7 +742,7 @@ */ HRESULT WINAPI VarUI1FromDisp(IDispatch* pdispIn, LCID lcid, BYTE* pbOut) { - return VARIANT_FromDisp(pdispIn, lcid, pbOut, VT_UI1); + return VARIANT_FromDisp(pdispIn, lcid, pbOut, VT_UI1, 0); }
/************************************************************************ @@ -1042,7 +1043,7 @@ */ HRESULT WINAPI VarI2FromDisp(IDispatch* pdispIn, LCID lcid, SHORT* psOut) { - return VARIANT_FromDisp(pdispIn, lcid, psOut, VT_I2); + return VARIANT_FromDisp(pdispIn, lcid, psOut, VT_I2, 0); }
/************************************************************************ @@ -1356,7 +1357,7 @@ */ HRESULT WINAPI VarUI2FromDisp(IDispatch* pdispIn, LCID lcid, USHORT* pusOut) { - return VARIANT_FromDisp(pdispIn, lcid, pusOut, VT_UI2); + return VARIANT_FromDisp(pdispIn, lcid, pusOut, VT_UI2, 0); }
/************************************************************************ @@ -1632,7 +1633,7 @@ */ HRESULT WINAPI VarI4FromDisp(IDispatch* pdispIn, LCID lcid, LONG *piOut) { - return VARIANT_FromDisp(pdispIn, lcid, piOut, VT_I4); + return VARIANT_FromDisp(pdispIn, lcid, piOut, VT_I4, 0); }
/************************************************************************ @@ -1941,7 +1942,7 @@ */ HRESULT WINAPI VarUI4FromDisp(IDispatch* pdispIn, LCID lcid, ULONG *pulOut) { - return VARIANT_FromDisp(pdispIn, lcid, pulOut, VT_UI4); + return VARIANT_FromDisp(pdispIn, lcid, pulOut, VT_UI4, 0); }
/************************************************************************ @@ -2248,7 +2249,7 @@ */ HRESULT WINAPI VarI8FromDisp(IDispatch* pdispIn, LCID lcid, LONG64* pi64Out) { - return VARIANT_FromDisp(pdispIn, lcid, pi64Out, VT_I8); + return VARIANT_FromDisp(pdispIn, lcid, pi64Out, VT_I8, 0); }
/************************************************************************ @@ -2576,7 +2577,7 @@ */ HRESULT WINAPI VarUI8FromDisp(IDispatch* pdispIn, LCID lcid, ULONG64* pui64Out) { - return VARIANT_FromDisp(pdispIn, lcid, pui64Out, VT_UI8); + return VARIANT_FromDisp(pdispIn, lcid, pui64Out, VT_UI8, 0); }
/************************************************************************ @@ -2851,7 +2852,7 @@ */ HRESULT WINAPI VarR4FromDisp(IDispatch* pdispIn, LCID lcid, float *pFltOut) { - return VARIANT_FromDisp(pdispIn, lcid, pFltOut, VT_R4); + return VARIANT_FromDisp(pdispIn, lcid, pFltOut, VT_R4, 0); }
/************************************************************************ @@ -3172,7 +3173,7 @@ */ HRESULT WINAPI VarR8FromDisp(IDispatch* pdispIn, LCID lcid, double *pDblOut) { - return VARIANT_FromDisp(pdispIn, lcid, pDblOut, VT_R8); + return VARIANT_FromDisp(pdispIn, lcid, pDblOut, VT_R8, 0); }
/************************************************************************ @@ -3594,7 +3595,7 @@ */ HRESULT WINAPI VarCyFromDisp(IDispatch* pdispIn, LCID lcid, CY* pCyOut) { - return VARIANT_FromDisp(pdispIn, lcid, pCyOut, VT_CY); + return VARIANT_FromDisp(pdispIn, lcid, pCyOut, VT_CY, 0); }
/************************************************************************ @@ -4265,7 +4266,7 @@ */ HRESULT WINAPI VarDecFromDisp(IDispatch* pdispIn, LCID lcid, DECIMAL* pDecOut) { - return VARIANT_FromDisp(pdispIn, lcid, pDecOut, VT_DECIMAL); + return VARIANT_FromDisp(pdispIn, lcid, pDecOut, VT_DECIMAL, 0); }
/************************************************************************ @@ -5806,7 +5807,7 @@ */ HRESULT WINAPI VarBoolFromDisp(IDispatch* pdispIn, LCID lcid, VARIANT_BOOL *pBoolOut) { - return VARIANT_FromDisp(pdispIn, lcid, pBoolOut, VT_BOOL); + return VARIANT_FromDisp(pdispIn, lcid, pBoolOut, VT_BOOL, 0); }
/************************************************************************ @@ -6544,6 +6545,27 @@ return VARIANT_BstrFromUInt(ullIn, lcid, dwFlags, pbstrOut); }
+/************************************************************************ + * VarBstrFromDisp (OLEAUT32.115) + * + * Convert a VT_DISPATCH to a BSTR. + * + * PARAMS + * pdispIn [I] Source + * lcid [I] LCID for conversion + * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h") + * pbstrOut [O] Destination + * + * RETURNS + * Success: S_OK. + * Failure: E_INVALIDARG, if the source value is invalid + * DISP_E_TYPEMISMATCH, if the type cannot be converted + */ +HRESULT WINAPI VarBstrFromDisp(IDispatch* pdispIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut) +{ + return VARIANT_FromDisp(pdispIn, lcid, pbstrOut, VT_BSTR, dwFlags); +} + /********************************************************************** * VarBstrCat (OLEAUT32.313) * @@ -6727,7 +6749,7 @@ */ HRESULT WINAPI VarDateFromDisp(IDispatch* pdispIn, LCID lcid, DATE* pdateOut) { - return VARIANT_FromDisp(pdispIn, lcid, pdateOut, VT_DATE); + return VARIANT_FromDisp(pdispIn, lcid, pdateOut, VT_DATE, 0); }
/******************************************************************************
Modified: trunk/reactos/include/oaidl.h URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/include/oaidl.h?rev=21399&am... ============================================================================== --- trunk/reactos/include/oaidl.h (original) +++ trunk/reactos/include/oaidl.h Mon Mar 27 20:44:53 2006 @@ -143,7 +143,9 @@ SF_BSTR=VT_BSTR, SF_UNKNOWN=VT_UNKNOWN, SF_DISPATCH=VT_DISPATCH, - SF_VARIANT=VT_VARIANT + SF_VARIANT=VT_VARIANT, + SF_RECORD=VT_RECORD, + SF_HAVEIID=VT_UNKNOWN|VT_RESERVED, }SF_TYPE; typedef struct _wireBRECORD { ULONG fFlags;
Modified: trunk/reactos/include/ocidl.h URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/include/ocidl.h?rev=21399&am... ============================================================================== --- trunk/reactos/include/ocidl.h (original) +++ trunk/reactos/include/ocidl.h Mon Mar 27 20:44:53 2006 @@ -20,6 +20,7 @@ typedef interface IPropertyPageSite *LPPROPERTYPAGESITE; typedef interface IFont *LPFONT; typedef interface IFontDisp *LPFONTDISP; +typedef interface IFontEventsDisp *LPFONTEVENTS; typedef interface IOleUndoManager *LPOLEUNDOMANAGER; typedef interface IQuickActivate *LPQUICKACTIVATE; typedef interface IObjectWithSite *LPOBJECTWITHSITE; @@ -638,6 +639,21 @@ }; #undef INTERFACE
+EXTERN_C const IID IID_IFontEventsDisp; +#define INTERFACE IFontEventsDisp +DECLARE_INTERFACE_(IFontEventsDisp,IDispatch) +{ + STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + STDMETHOD(GetTypeInfoCount)(THIS_ UINT*) PURE; + STDMETHOD(GetTypeInfo)(THIS_ UINT,LCID,LPTYPEINFO*) PURE; + STDMETHOD(GetIDsOfNames)(THIS_ REFIID,LPOLESTR*,UINT,LCID,DISPID*) PURE; + STDMETHOD(Invoke)(THIS_ DISPID,REFIID,LCID,WORD,DISPPARAMS*,VARIANT*,EXCEPINFO*,UINT*) PURE; + /*[id(0x9)]*/STDMETHOD(FontChanged)(THIS_ BSTR) PURE; +}; +#undef INTERFACE + EXTERN_C const IID IID_IPicture; #define INTERFACE IPicture DECLARE_INTERFACE_(IPicture,IUnknown)
Modified: trunk/reactos/include/olectl.h URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/include/olectl.h?rev=21399&a... ============================================================================== --- trunk/reactos/include/olectl.h (original) +++ trunk/reactos/include/olectl.h Mon Mar 27 20:44:53 2006 @@ -218,6 +218,9 @@ #define DISPID_FONT_STRIKE 6 #define DISPID_FONT_WEIGHT 7 #define DISPID_FONT_CHARSET 8 +#define DISPID_FONT_CHANGED 9 + +/* IPicture */ #define DISPID_PICT_HANDLE 0 #define DISPID_PICT_HPAL 2 #define DISPID_PICT_TYPE 3
Modified: trunk/reactos/include/olectlid.h URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/include/olectlid.h?rev=21399... ============================================================================== --- trunk/reactos/include/olectlid.h (original) +++ trunk/reactos/include/olectlid.h Mon Mar 27 20:44:53 2006 @@ -40,6 +40,7 @@ extern const GUID CLSID_StdPicture; extern const GUID IID_IFont; extern const GUID IID_IFontDisp; +extern const GUID IID_IFontEventsDisp; extern const GUID IID_IPicture; extern const GUID IID_IPictureDisp; extern const GUID GUID_HIMETRIC;