From df82a2a2a8fa9d1e8fe0b2db1c11e24817c0ca87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9=20van=20Geldorp?= Date: Thu, 5 May 2005 18:29:41 +0000 Subject: [PATCH] Sync to Wine-20050419: Daniel Remenak - Implemented VarIdiv. - Return DISP_E_DIVBYZERO instead of crashing when asked to divide a variant by zero. - Remove unused variable in _copy_arg. Marcus Meissner - Serialize NULL pointer interfaces correctly. - Fixed VT_BSTR|VT_BYREF marshalling. - Added VT_I4|VT_BYREF marshalling. - Fixed ppvObject serializer (deref twice instead of once). - Actually pass back return value of remote call in type marshaller. - Format VT_UI1, VT_I1, VT_UI2, VT_I2 correctly. - Added IDispatch::GetIDsOfNames() special case serializing. - Handle VT_PTR / NULL marshalling correctly. Mike Hearn - Fix BSTR tracing in the typelib marshaller. - Fix PARAMFLAG_FOUT typo in the tmarshaller. Mike Hearn Robert Shearman - Implement VT_BYREF | VT_BSTR marshalling. - Add more integer types for marshaling and unmarshaling. - Implement VT_BYREF | VT_BSTR unmarshaling. - Don't allocate memory for TKIND_DISPATCH/TKIND_INTERFACE unmarshaling as it will be lost in the success case and interferes with the failure case. Robert Shearman - Add outer unknown support for typelib marshaler. Jakob Eriksson - Get rid of HeapAlloc casts. Francois Gouget - Assorted spelling fixes. Alex Villacis Lasso - Fix leftover negative sign in height parameter for transparent bitmap. - Properly announce whether bitmap is transparent in get_Attributes. - GIF transparency is now palette-index based, instead of RGB based. - Keep original bitmap and XOR mask separate, so that get_Handle returns original bitmap. - Initialize [orig|himetric][Width|Height] for PICTYPE_ICON case. - Fix failure to notice the use of a GIF palette index greater or equal to 128 for transparency. - After Float->string conversion via sprintfW(), VarDecFromR[4|8] is forced to use US locale for string->Decimal conversion, to agree with sprintfW(). svn path=/trunk/; revision=15011 --- reactos/lib/oleaut32/oleaut.c | 10 +- reactos/lib/oleaut32/oleaut32.spec | 2 +- reactos/lib/oleaut32/olepicture.c | 49 +- reactos/lib/oleaut32/safearray.c | 4 +- reactos/lib/oleaut32/tmarshal.c | 776 ++++++++++++++++++++++------- reactos/lib/oleaut32/typelib.c | 24 +- reactos/lib/oleaut32/typelib.h | 4 +- reactos/lib/oleaut32/variant.c | 54 +- reactos/lib/oleaut32/vartype.c | 6 +- 9 files changed, 708 insertions(+), 221 deletions(-) diff --git a/reactos/lib/oleaut32/oleaut.c b/reactos/lib/oleaut32/oleaut.c index 1b2f8f35c90..6105baa83b9 100644 --- a/reactos/lib/oleaut32/oleaut.c +++ b/reactos/lib/oleaut32/oleaut.c @@ -235,9 +235,8 @@ BSTR WINAPI SysAllocStringLen(const OLECHAR *str, unsigned int len) * buffer for the character count and an extra character at the * end for the NULL. */ - newBuffer = (DWORD*)HeapAlloc(GetProcessHeap(), - 0, - bufferSize + sizeof(WCHAR) + sizeof(DWORD)); + newBuffer = HeapAlloc(GetProcessHeap(), 0, + bufferSize + sizeof(WCHAR) + sizeof(DWORD)); /* * If the memory allocation failed, return a null pointer. @@ -350,9 +349,8 @@ BSTR WINAPI SysAllocStringByteLen(LPCSTR str, UINT len) * buffer for the character count and an extra character at the * end for the NULL. */ - newBuffer = (DWORD*)HeapAlloc(GetProcessHeap(), - 0, - len + sizeof(WCHAR) + sizeof(DWORD)); + newBuffer = HeapAlloc(GetProcessHeap(), 0, + len + sizeof(WCHAR) + sizeof(DWORD)); /* * If the memory allocation failed, return a null pointer. diff --git a/reactos/lib/oleaut32/oleaut32.spec b/reactos/lib/oleaut32/oleaut32.spec index a3a67a18fe9..0a8ac66aeed 100644 --- a/reactos/lib/oleaut32/oleaut32.spec +++ b/reactos/lib/oleaut32/oleaut32.spec @@ -148,7 +148,7 @@ 149 stdcall SysStringByteLen(ptr) 150 stdcall SysAllocStringByteLen(ptr long) 152 stdcall VarEqv(ptr ptr ptr) -153 stub VarIdiv # stdcall (ptr ptr ptr) +153 stdcall VarIdiv(ptr ptr ptr) 154 stub VarImp # stdcall (ptr ptr ptr) 155 stdcall VarMod(ptr ptr ptr) 156 stdcall VarMul(ptr ptr ptr) diff --git a/reactos/lib/oleaut32/olepicture.c b/reactos/lib/oleaut32/olepicture.c index 2883c3454c8..2dd60cb5721 100644 --- a/reactos/lib/oleaut32/olepicture.c +++ b/reactos/lib/oleaut32/olepicture.c @@ -185,6 +185,36 @@ static void OLEPictureImpl_SetBitmap(OLEPictureImpl*This) { DeleteDC(hdcRef); } +static void OLEPictureImpl_SetIcon(OLEPictureImpl * This) +{ + ICONINFO infoIcon; + + TRACE("icon handle %p\n", This->desc.u.icon.hicon); + if (GetIconInfo(This->desc.u.icon.hicon, &infoIcon)) { + HDC hdcRef; + BITMAP bm; + + TRACE("bitmap handle for icon is %p\n", infoIcon.hbmColor); + if(GetObjectA(infoIcon.hbmColor ? infoIcon.hbmColor : infoIcon.hbmMask, sizeof(bm), &bm) != sizeof(bm)) { + ERR("GetObject fails on icon bitmap\n"); + return; + } + + This->origWidth = bm.bmWidth; + This->origHeight = infoIcon.hbmColor ? bm.bmHeight : bm.bmHeight / 2; + /* see comment on HIMETRIC on OLEPictureImpl_SetBitmap() */ + hdcRef = GetDC(0); + This->himetricWidth = (This->origWidth *2540)/GetDeviceCaps(hdcRef, LOGPIXELSX); + This->himetricHeight= (This->origHeight *2540)/GetDeviceCaps(hdcRef, LOGPIXELSY); + ReleaseDC(0, hdcRef); + + DeleteObject(infoIcon.hbmMask); + if (infoIcon.hbmColor) DeleteObject(infoIcon.hbmColor); + } else { + ERR("GetIconInfo() fails on icon %p\n", This->desc.u.icon.hicon); + } +} + /************************************************************************ * OLEPictureImpl_Construct * @@ -260,6 +290,8 @@ static OLEPictureImpl* OLEPictureImpl_Construct(LPPICTDESC pictDesc, BOOL fOwn) break; case PICTYPE_ICON: + OLEPictureImpl_SetIcon(newObject); + break; case PICTYPE_ENHMETAFILE: default: FIXME("Unsupported type %d\n", pictDesc->picType); @@ -1071,7 +1103,7 @@ static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) { eb = si->ExtensionBlocks + i; if (eb->Function == 0xF9 && eb->ByteCount == 4) { if ((eb->Bytes[0] & 1) == 1) { - transparent = eb->Bytes[3]; + transparent = (unsigned char)eb->Bytes[3]; } } } @@ -1145,7 +1177,7 @@ static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) { This->hbmMask = CreateBitmap(bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight, 1, 1, NULL); - hOldbitmap = SelectObject(hdc,This->desc.u.bmp.hbitmap); + hOldbitmap = SelectObject(hdc,This->desc.u.bmp.hbitmap); hOldbitmapmask = SelectObject(hdcMask, This->hbmMask); SetBkColor(hdc, This->rgbTrans); BitBlt(hdcMask, 0, 0, bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight, hdc, 0, 0, SRCCOPY); @@ -1501,7 +1533,7 @@ static int serializeBMP(HBITMAP hBitmap, void ** ppBuffer, unsigned int * pLengt BITMAPFILEHEADER * pFileHeader; BITMAPINFO * pInfoHeader; - pInfoBitmap = (BITMAPINFO *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + pInfoBitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)); /* Find out bitmap size and padded length */ @@ -1511,8 +1543,7 @@ static int serializeBMP(HBITMAP hBitmap, void ** ppBuffer, unsigned int * pLengt /* Fetch bitmap palette & pixel data */ - pPixelData = (unsigned char *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, - pInfoBitmap->bmiHeader.biSizeImage); + 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 */ @@ -1530,7 +1561,7 @@ static int serializeBMP(HBITMAP hBitmap, void ** ppBuffer, unsigned int * pLengt sizeof(BITMAPINFOHEADER) + iNumPaletteEntries * sizeof(RGBQUAD) + pInfoBitmap->bmiHeader.biSizeImage; - *ppBuffer = (void *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *pLength); + *ppBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *pLength); /* Fill the BITMAPFILEHEADER */ pFileHeader = (BITMAPFILEHEADER *)(*ppBuffer); @@ -1569,7 +1600,7 @@ static int serializeIcon(HICON hIcon, void ** ppBuffer, unsigned int * pLength) unsigned char * pIconData = NULL; unsigned int iDataSize = 0; - pInfoBitmap = (BITMAPINFO *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)); + pInfoBitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)); /* Find out icon size */ hDC = GetDC(0); @@ -1603,7 +1634,7 @@ static int serializeIcon(HICON hIcon, void ** ppBuffer, unsigned int * pLength) */ /* Let's start with one CURSORICONFILEDIR and one CURSORICONFILEDIRENTRY */ iDataSize += 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY) + sizeof(BITMAPINFOHEADER); - pIconData = (unsigned char *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, iDataSize); + pIconData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, iDataSize); /* Fill out the CURSORICONFILEDIR */ pIconDir = (CURSORICONFILEDIR *)pIconData; @@ -1651,7 +1682,7 @@ static int serializeIcon(HICON hIcon, void ** ppBuffer, unsigned int * pLength) iDataSize += pIconBitmapHeader->biHeight * iLengthScanLineMask; pIconBitmapHeader->biSizeImage += pIconBitmapHeader->biHeight * iLengthScanLineMask; pIconBitmapHeader->biHeight *= 2; - pIconData = (unsigned char *)HeapReAlloc(GetProcessHeap(), 0, pIconData, iDataSize); + 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)); diff --git a/reactos/lib/oleaut32/safearray.c b/reactos/lib/oleaut32/safearray.c index d183a5cc614..90bcf6464d5 100644 --- a/reactos/lib/oleaut32/safearray.c +++ b/reactos/lib/oleaut32/safearray.c @@ -647,7 +647,7 @@ SAFEARRAY* WINAPI SafeArrayCreateEx(VARTYPE vt, UINT cDims, SAFEARRAYBOUND *rgsa /************************************************************************ * SafeArrayCreateVector (OLEAUT32.411) * - * Create a one dimensional, contigous SafeArray. + * Create a one dimensional, contiguous SafeArray. * * PARAMS * vt [I] Type to store in the safe array @@ -674,7 +674,7 @@ SAFEARRAY* WINAPI SafeArrayCreateVector(VARTYPE vt, LONG lLbound, ULONG cElement /************************************************************************ * SafeArrayCreateVectorEx (OLEAUT32.411) * - * Create a one dimensional, contigous SafeArray. + * Create a one dimensional, contiguous SafeArray. * * PARAMS * vt [I] Type to store in the safe array diff --git a/reactos/lib/oleaut32/tmarshal.c b/reactos/lib/oleaut32/tmarshal.c index efc1f1021d2..915912276ab 100644 --- a/reactos/lib/oleaut32/tmarshal.c +++ b/reactos/lib/oleaut32/tmarshal.c @@ -1,7 +1,7 @@ /* * TYPELIB Marshaler * - * Copyright 2002 Marcus Meissner + * Copyright 2002,2005 Marcus Meissner * * The olerelay debug channel allows you to see calls marshalled by * the typelib marshaller. It is not a generic COM relaying system. @@ -48,6 +48,8 @@ static const WCHAR riidW[5] = {'r','i','i','d',0}; static const WCHAR pdispparamsW[] = {'p','d','i','s','p','p','a','r','a','m','s',0}; static const WCHAR ppvObjectW[] = {'p','p','v','O','b','j','e','c','t',0}; +static const WCHAR IDispatchW[] = { 'I','D','i','s','p','a','t','c','h',0}; +static const WCHAR GetIDsOfNamesW[] = { 'G','e','t','I','D','s','O','f','N','a','m','e','s',0}; WINE_DEFAULT_DEBUG_CHANNEL(ole); WINE_DECLARE_DEBUG_CHANNEL(olerelay); @@ -167,12 +169,19 @@ _marshal_interface(marshal_state *buf, REFIID riid, LPUNKNOWN pUnk) { DWORD xsize; HRESULT hres; - hres = E_FAIL; if (!pUnk) { + /* this is valid, if for instance we serialize + * a VT_DISPATCH with NULL ptr which apparently + * can happen. S_OK to make sure we continue + * serializing. + */ ERR("pUnk is NULL?\n"); - goto fail; + xsize = 0; + return xbuf_add(buf,(LPBYTE)&xsize,sizeof(xsize)); } + hres = E_FAIL; + TRACE("...%s...\n",debugstr_guid(riid)); hres = IUnknown_QueryInterface(pUnk,riid,(LPVOID*)&newiface); if (hres) { @@ -355,6 +364,7 @@ typedef struct _TMProxyImpl { IRpcChannelBuffer* chanbuf; IID iid; CRITICAL_SECTION crit; + IUnknown *outerunknown; } TMProxyImpl; static HRESULT WINAPI @@ -499,17 +509,36 @@ serialize_param( return S_OK; case VT_BOOL: case VT_ERROR: - case VT_UI4: case VT_UINT: case VT_I4: case VT_R4: - case VT_UI2: - case VT_UI1: + case VT_UI4: hres = S_OK; if (debugout) TRACE_(olerelay)("%lx",*arg); if (writeit) hres = xbuf_add(buf,(LPBYTE)arg,sizeof(DWORD)); return hres; + case VT_I2: + case VT_UI2: + hres = S_OK; + if (debugout) TRACE_(olerelay)("%04lx",*arg & 0xffff); + if (writeit) + hres = xbuf_add(buf,(LPBYTE)arg,sizeof(DWORD)); + return hres; + case VT_I1: + case VT_UI1: + hres = S_OK; + if (debugout) TRACE_(olerelay)("%02lx",*arg & 0xff); + if (writeit) + hres = xbuf_add(buf,(LPBYTE)arg,sizeof(DWORD)); + return hres; + case VT_I4|VT_BYREF: + hres = S_OK; + if (debugout) TRACE_(olerelay)("&0x%lx",*arg); + if (writeit) + hres = xbuf_add(buf,(LPBYTE)(DWORD*)*arg,sizeof(DWORD)); + /* do not dealloc at this time */ + return hres; case VT_VARIANT: { TYPEDESC tdesc2; VARIANT *vt = (VARIANT*)arg; @@ -526,10 +555,34 @@ serialize_param( if (debugout) TRACE_(olerelay)(")"); return hres; } + case VT_BSTR|VT_BYREF: { + if (debugout) TRACE_(olerelay)("[byref]'%s'", *(BSTR*)*arg ? relaystr(*((BSTR*)*arg)) : ""); + if (writeit) { + /* ptr to ptr to magic widestring, basically */ + BSTR *bstr = (BSTR *) *arg; + if (!*bstr) { + /* -1 means "null string" which is equivalent to empty string */ + DWORD fakelen = -1; + xbuf_add(buf, (LPBYTE)&fakelen,4); + } else { + /* BSTRs store the length behind the first character */ + DWORD *len = ((DWORD *)(*bstr))-1; + hres = xbuf_add(buf, (LPBYTE) len, *len + 4); + if (hres) return hres; + } + } + + if (dealloc && arg) { + BSTR *str = *((BSTR **)arg); + SysFreeString(*str); + } + return S_OK; + } + case VT_BSTR: { if (debugout) { - if (arg) - TRACE_(olerelay)("%s",relaystr((BSTR)*arg)); + if (*arg) + TRACE_(olerelay)("%s",relaystr((WCHAR*)*arg)); else TRACE_(olerelay)(""); } @@ -556,12 +609,12 @@ serialize_param( DWORD cookie; if (debugout) TRACE_(olerelay)("*"); - if (writeit) { - cookie = *arg ? 0x42424242 : 0; - hres = xbuf_add(buf,(LPBYTE)&cookie,sizeof(cookie)); - if (hres) - return hres; - } + /* Write always, so the other side knows when it gets a NULL pointer. + */ + cookie = *arg ? 0x42424242 : 0; + hres = xbuf_add(buf,(LPBYTE)&cookie,sizeof(cookie)); + if (hres) + return hres; if (!*arg) { if (debugout) TRACE_(olerelay)("NULL"); return S_OK; @@ -660,6 +713,7 @@ serialize_param( 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)("["); for (i=0;itdescElem, (DWORD*)((LPBYTE)arg+i*_xsize(&adesc->tdescElem)), buf); @@ -676,6 +730,168 @@ serialize_param( } } +/* IDL desc: + * HRESULT GetIDsOfNames( + * [in] REFIID riid, args[1] + * [in, size_is(cNames)] LPOLESTR *rgszNames, args[2] + * [in] UINT cNames, args[3] + * [in] LCID lcid, args[4] + * [out, size_is(cNames)] DISPID *rgDispId); args[5] + * + * line format: + * IID iid; + * DWORD cNames; + * LPOLESTR rgszNames[cNames]; + * DWORD bytestrlen (incl 0) + * BYTE data[bytestrlen] (incl 0) + * LCID + */ +static HRESULT +serialize_IDispatch_GetIDsOfNames( + BOOL inputparams, + BOOL debugout, + DWORD *args, + marshal_state *buf) +{ + HRESULT hres; + DWORD cNames = args[2]; + LPOLESTR *rgszNames = (LPOLESTR*)args[1]; + int i; + + if (inputparams) { + if (debugout) TRACE_(olerelay)("riid=%s,",debugstr_guid((REFIID)args[0])); + hres = xbuf_add(buf, (LPBYTE)args[0], sizeof(IID)); + if (hres) { + FIXME("serialize of IID failed.\n"); + return hres; + } + if (debugout) TRACE_(olerelay)("cNames=%ld,",cNames); + hres = xbuf_add(buf, (LPBYTE)&cNames, sizeof(DWORD)); + if (hres) { + FIXME("serialize of cNames failed.\n"); + return hres; + } + if (debugout) TRACE_(olerelay)("rgszNames=["); + for (i=0;i VT_PTR -> VT_VOID?\n"); return E_FAIL; } - cookie = (*arg) ? 0x42424242: 0x0; + cookie = (*(DWORD*)*arg) ? 0x42424242: 0x0; if (writeit) { hres = xbuf_add(buf, (LPVOID)&cookie, sizeof(cookie)); if (hres) return hres; } - if (!*arg) { + if (!*(DWORD*)*arg) { if (debugout) TRACE_(olerelay)(""); return S_OK; } @@ -849,15 +1065,79 @@ deserialize_param( } } case VT_ERROR: - case VT_BOOL: case VT_I4: case VT_UI4: case VT_UINT: case VT_R4: - case VT_UI2: - case VT_UI1: + case VT_BOOL: + case VT_I4: + case VT_UINT: + case VT_R4: + case VT_UI4: if (readit) { hres = xbuf_get(buf,(LPBYTE)arg,sizeof(DWORD)); if (hres) ERR("Failed to read integer 4 byte\n"); } if (debugout) TRACE_(olerelay)("%lx",*arg); return hres; + case VT_I2: + case VT_UI2: + if (readit) { + DWORD x; + hres = xbuf_get(buf,(LPBYTE)&x,sizeof(DWORD)); + if (hres) ERR("Failed to read integer 4 byte\n"); + memcpy(arg,&x,2); + } + if (debugout) TRACE_(olerelay)("%04lx",*arg & 0xffff); + return hres; + case VT_I1: + case VT_UI1: + if (readit) { + DWORD x; + hres = xbuf_get(buf,(LPBYTE)&x,sizeof(DWORD)); + if (hres) ERR("Failed to read integer 4 byte\n"); + memcpy(arg,&x,1); + } + if (debugout) TRACE_(olerelay)("%02lx",*arg & 0xff); + return hres; + case VT_I4|VT_BYREF: + hres = S_OK; + if (alloc) + *arg = (DWORD)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DWORD)); + if (readit) { + hres = xbuf_get(buf,(LPBYTE)*arg,sizeof(DWORD)); + if (hres) ERR("Failed to read integer 4 byte\n"); + } + if (debugout) TRACE_(olerelay)("&0x%lx",*(DWORD*)*arg); + return hres; + case VT_BSTR|VT_BYREF: { + BSTR **bstr = (BSTR **)arg; + WCHAR *str; + DWORD len; + + if (readit) { + hres = xbuf_get(buf,(LPBYTE)&len,sizeof(DWORD)); + if (hres) { + ERR("failed to read bstr klen\n"); + return hres; + } + if (len == -1) { + *bstr = CoTaskMemAlloc(sizeof(BSTR *)); + **bstr = NULL; + if (debugout) TRACE_(olerelay)(""); + } else { + str = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,len+sizeof(WCHAR)); + hres = xbuf_get(buf,(LPBYTE)str,len); + if (hres) { + ERR("Failed to read BSTR.\n"); + return hres; + } + *bstr = CoTaskMemAlloc(sizeof(BSTR *)); + **bstr = SysAllocStringLen(str,len); + if (debugout) TRACE_(olerelay)("%s",relaystr(str)); + HeapFree(GetProcessHeap(),0,str); + } + } else { + *bstr = NULL; + } + return S_OK; + } case VT_BSTR: { WCHAR *str; DWORD len; @@ -889,24 +1169,26 @@ deserialize_param( } case VT_PTR: { DWORD cookie; - BOOL derefhere = 0; + BOOL derefhere = 0; derefhere = (tdesc->u.lptdesc->vt != VT_USERDEFINED); - - if (readit) { - hres = xbuf_get(buf,(LPBYTE)&cookie,sizeof(cookie)); - if (hres) { - ERR("Failed to load pointer cookie.\n"); - return hres; - } - if (cookie != 0x42424242) { - if (debugout) TRACE_(olerelay)("NULL"); - *arg = 0; - return S_OK; - } - if (debugout) TRACE_(olerelay)("*"); + /* read it in all cases, we need to know if we have + * NULL pointer or not. + */ + hres = xbuf_get(buf,(LPBYTE)&cookie,sizeof(cookie)); + if (hres) { + ERR("Failed to load pointer cookie.\n"); + return hres; } + if (cookie != 0x42424242) { + /* we read a NULL ptr from the remote side */ + if (debugout) TRACE_(olerelay)("NULL"); + *arg = 0; + return S_OK; + } + if (debugout) TRACE_(olerelay)("*"); if (alloc) { + /* Allocate space for the referenced struct */ if (derefhere) *arg=(DWORD)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,_xsize(tdesc->u.lptdesc)); } @@ -948,8 +1230,6 @@ deserialize_param( if (hres) { ERR("Could not get typeattr in VT_USERDEFINED.\n"); } else { - if (alloc) - *arg = (DWORD)HeapAlloc(GetProcessHeap(),0,tattr->cbSizeInstance); switch (tattr->typekind) { case TKIND_DISPATCH: case TKIND_INTERFACE: @@ -959,6 +1239,9 @@ deserialize_param( case TKIND_RECORD: { int i; + if (alloc) + *arg = (DWORD)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,tattr->cbSizeInstance); + if (debugout) TRACE_(olerelay)("{"); for (i=0;icVars;i++) { VARDESC *vdesc; @@ -1056,8 +1339,10 @@ deserialize_LPVOID_ptr( } if (readit) { hres = _unmarshal_interface(buf,&buf->iid,(LPUNKNOWN*)*arg); - if (hres) + if (hres) { + FIXME("_unmarshal_interface of %s , %p failed with %lx\n", debugstr_guid(&buf->iid), (LPUNKNOWN*)*arg, hres); return hres; + } } if (debugout) TRACE_(olerelay)("ppv(%p)",(LPVOID)*arg); return S_OK; @@ -1209,6 +1494,8 @@ xCall(LPVOID retptr, int method, TMProxyImpl *tpinfo /*, args */) BSTR fname,iname; BSTR names[10]; int nrofnames; + int is_idispatch_getidsofnames = 0; + DWORD remoteresult = 0; EnterCriticalSection(&tpinfo->crit); @@ -1235,9 +1522,35 @@ xCall(LPVOID retptr, int method, TMProxyImpl *tpinfo /*, args */) else TRACE_(olerelay)("%d",method); TRACE_(olerelay)("("); - if (iname) SysFreeString(iname); - if (fname) SysFreeString(fname); } + if (iname && fname && !lstrcmpW(iname,IDispatchW) && !lstrcmpW(fname,GetIDsOfNamesW)) + is_idispatch_getidsofnames = 1; + + if (iname) SysFreeString(iname); + if (fname) SysFreeString(fname); + + memset(&buf,0,sizeof(buf)); + buf.iid = IID_IUnknown; + + /* Special IDispatch::GetIDsOfNames() serializer */ + if (is_idispatch_getidsofnames) { + hres = serialize_IDispatch_GetIDsOfNames(TRUE,relaydeb,args,&buf); + if (hres != S_OK) { + FIXME("serialize of IDispatch::GetIDsOfNames failed!\n"); + return hres; + } + goto afterserialize; + } + + /* special QueryInterface serialize */ + if (method == 0) { + xbuf_add(&buf,(LPBYTE)args[0],sizeof(IID)); + if (relaydeb) TRACE_(olerelay)("riid=%s,[out])",debugstr_guid((REFIID)args[0])); + goto afterserialize; + } + + /* normal typelib driven serializing */ + /* Need them for hack below */ memset(names,0,sizeof(names)); if (ITypeInfo_GetNames(tpinfo->tinfo,fdesc->memid,names,sizeof(names)/sizeof(names[0]),&nrofnames)) @@ -1245,62 +1558,30 @@ xCall(LPVOID retptr, int method, TMProxyImpl *tpinfo /*, args */) if (nrofnames > sizeof(names)/sizeof(names[0])) ERR("Need more names!\n"); - memset(&buf,0,sizeof(buf)); - buf.iid = IID_IUnknown; - if (method == 0) { - xbuf_add(&buf,(LPBYTE)args[0],sizeof(IID)); - if (relaydeb) TRACE_(olerelay)("riid=%s,[out]",debugstr_guid((REFIID)args[0])); - } else { - xargs = args; - for (i=0;icParams;i++) { - ELEMDESC *elem = fdesc->lprgelemdescParam+i; - BOOL isserialized = FALSE; - if (relaydeb) { - if (i) TRACE_(olerelay)(","); - if (i+1cParams;i++) { + ELEMDESC *elem = fdesc->lprgelemdescParam+i; + BOOL isserialized = FALSE; + if (relaydeb) { + if (i) TRACE_(olerelay)(","); + if (i+1tinfo, - elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN, - relaydeb, - FALSE, - &elem->tdesc, - xargs, - &buf - ); - isserialized = TRUE; - } - if (!lstrcmpW(names[i+1],ppvObjectW)) { - hres = serialize_LPVOID_ptr( - tpinfo->tinfo, - elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN, - relaydeb, - FALSE, - &elem->tdesc, - xargs, - &buf - ); - if (hres == S_OK) - isserialized = TRUE; - } - } - if (!isserialized) - hres = serialize_param( + /* DISPPARAMS* needs special serializer */ + if (!lstrcmpW(names[i+1],pdispparamsW)) { + hres = serialize_DISPPARAM_ptr( tpinfo->tinfo, elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN, relaydeb, @@ -1309,15 +1590,42 @@ xCall(LPVOID retptr, int method, TMProxyImpl *tpinfo /*, args */) xargs, &buf ); - - if (hres) { - ERR("Failed to serialize param, hres %lx\n",hres); - break; + isserialized = TRUE; + } + if (!lstrcmpW(names[i+1],ppvObjectW)) { + hres = serialize_LPVOID_ptr( + tpinfo->tinfo, + elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN, + relaydeb, + FALSE, + &elem->tdesc, + xargs, + &buf + ); + if (hres == S_OK) + isserialized = TRUE; } - xargs+=_argsize(elem->tdesc.vt); } + if (!isserialized) + hres = serialize_param( + tpinfo->tinfo, + elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN, + relaydeb, + FALSE, + &elem->tdesc, + xargs, + &buf + ); + + if (hres) { + ERR("Failed to serialize param, hres %lx\n",hres); + break; + } + xargs+=_argsize(elem->tdesc.vt); } if (relaydeb) TRACE_(olerelay)(")"); + +afterserialize: memset(&msg,0,sizeof(msg)); msg.cbBuffer = buf.curoff; msg.iMethod = method; @@ -1336,7 +1644,7 @@ xCall(LPVOID retptr, int method, TMProxyImpl *tpinfo /*, args */) return hres; } - if (relaydeb) TRACE_(olerelay)(" = %08lx (",status); + if (relaydeb) TRACE_(olerelay)(" status = %08lx (",status); if (buf.base) buf.base = HeapReAlloc(GetProcessHeap(),0,buf.base,msg.cbBuffer); else @@ -1344,64 +1652,49 @@ xCall(LPVOID retptr, int method, TMProxyImpl *tpinfo /*, args */) buf.size = msg.cbBuffer; memcpy(buf.base,msg.Buffer,buf.size); buf.curoff = 0; + + /* Special IDispatch::GetIDsOfNames() deserializer */ + if (is_idispatch_getidsofnames) { + hres = deserialize_IDispatch_GetIDsOfNames(FALSE,relaydeb,args,&buf); + if (hres != S_OK) { + FIXME("deserialize of IDispatch::GetIDsOfNames failed!\n"); + return hres; + } + goto after_deserialize; + } + /* Special QueryInterface deserializer */ if (method == 0) { _unmarshal_interface(&buf,(REFIID)args[0],(LPUNKNOWN*)args[1]); if (relaydeb) TRACE_(olerelay)("[in],%p",*((DWORD**)args[1])); - } else { - xargs = args; - for (i=0;icParams;i++) { - ELEMDESC *elem = fdesc->lprgelemdescParam+i; - BOOL isdeserialized = FALSE; + goto after_deserialize; + } - if (relaydeb) { - if (i) TRACE_(olerelay)(","); - if (i+1cParams;i++) { + ELEMDESC *elem = fdesc->lprgelemdescParam+i; + BOOL isdeserialized = FALSE; - /* deserialize DISPPARAM */ - if (!lstrcmpW(names[i+1],pdispparamsW)) { - hres = deserialize_DISPPARAM_ptr( - tpinfo->tinfo, - elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT, - relaydeb, - FALSE, - &(elem->tdesc), - xargs, - &buf - ); - if (hres) { - ERR("Failed to deserialize DISPPARAM*, hres %lx\n",hres); - break; - } - isdeserialized = TRUE; - } - if (!lstrcmpW(names[i+1],ppvObjectW)) { - hres = deserialize_LPVOID_ptr( - tpinfo->tinfo, - elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT, - relaydeb, - FALSE, - &elem->tdesc, - xargs, - &buf - ); - if (hres == S_OK) - isdeserialized = TRUE; - } - } - if (!isdeserialized) - hres = deserialize_param( + if (relaydeb) { + if (i) TRACE_(olerelay)(","); + if (i+1tinfo, elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT, relaydeb, @@ -1410,20 +1703,92 @@ xCall(LPVOID retptr, int method, TMProxyImpl *tpinfo /*, args */) xargs, &buf ); - if (hres) { - ERR("Failed to unmarshall param, hres %lx\n",hres); - status = hres; - break; + if (hres) { + ERR("Failed to deserialize DISPPARAM*, hres %lx\n",hres); + break; + } + isdeserialized = TRUE; + } + if (!lstrcmpW(names[i+1],ppvObjectW)) { + hres = deserialize_LPVOID_ptr( + tpinfo->tinfo, + elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT, + relaydeb, + FALSE, + &elem->tdesc, + xargs, + &buf + ); + if (hres == S_OK) + isdeserialized = TRUE; } - xargs += _argsize(elem->tdesc.vt); } + if (!isdeserialized) + hres = deserialize_param( + tpinfo->tinfo, + elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT, + relaydeb, + FALSE, + &(elem->tdesc), + xargs, + &buf + ); + if (hres) { + ERR("Failed to unmarshall param, hres %lx\n",hres); + status = hres; + break; + } + xargs += _argsize(elem->tdesc.vt); } - if (relaydeb) TRACE_(olerelay)(")\n"); +after_deserialize: + hres = xbuf_get(&buf, (LPBYTE)&remoteresult, sizeof(DWORD)); + if (hres != S_OK) + return hres; + if (relaydeb) TRACE_(olerelay)(") = %08lx\n", remoteresult); + + if (status != S_OK) /* OLE/COM internal error */ + return status; + HeapFree(GetProcessHeap(),0,buf.base); - LeaveCriticalSection(&tpinfo->crit); + return remoteresult; +} - return status; +HRESULT WINAPI ProxyIUnknown_QueryInterface(IUnknown *iface, REFIID riid, void **ppv) +{ + TMProxyImpl *proxy = (TMProxyImpl *)iface; + + TRACE("(%s, %p)\n", debugstr_guid(riid), ppv); + + if (proxy->outerunknown) + return IUnknown_QueryInterface(proxy->outerunknown, riid, ppv); + + FIXME("No interface\n"); + return E_NOINTERFACE; +} + +ULONG WINAPI ProxyIUnknown_AddRef(IUnknown *iface) +{ + TMProxyImpl *proxy = (TMProxyImpl *)iface; + + TRACE("\n"); + + if (proxy->outerunknown) + return IUnknown_AddRef(proxy->outerunknown); + + return 2; /* FIXME */ +} + +ULONG WINAPI ProxyIUnknown_Release(IUnknown *iface) +{ + TMProxyImpl *proxy = (TMProxyImpl *)iface; + + TRACE("\n"); + + if (proxy->outerunknown) + return IUnknown_Release(proxy->outerunknown); + + return 1; /* FIXME */ } static HRESULT WINAPI @@ -1449,6 +1814,7 @@ PSFacBuf_CreateProxy( assert(sizeof(TMAsmProxy) == 12); + proxy->outerunknown = pUnkOuter; proxy->asmstubs = VirtualAlloc(NULL, sizeof(TMAsmProxy) * nroffuncs, MEM_COMMIT, PAGE_EXECUTE_READWRITE); if (!proxy->asmstubs) { ERR("Could not commit pages for proxy thunks\n"); @@ -1460,17 +1826,22 @@ PSFacBuf_CreateProxy( proxy->lpvtbl = HeapAlloc(GetProcessHeap(),0,sizeof(LPBYTE)*nroffuncs); for (i=0;iasmstubs+i; - /* nrofargs without This */ switch (i) { - case 0: nrofargs = 2; + case 0: + proxy->lpvtbl[i] = ProxyIUnknown_QueryInterface; break; - case 1: case 2: nrofargs = 0; + case 1: + proxy->lpvtbl[i] = ProxyIUnknown_AddRef; + break; + case 2: + proxy->lpvtbl[i] = ProxyIUnknown_Release; break; default: { int j; + /* nrofargs without This */ + int nrofargs; hres = _get_funcdesc(tinfo,i,&fdesc,NULL,NULL); if (hres) { ERR("GetFuncDesc %lx should not fail here.\n",hres); @@ -1485,9 +1856,6 @@ PSFacBuf_CreateProxy( ERR("calling convention is not stdcall????\n"); return E_FAIL; } - break; - } - } /* popl %eax - return ptr * pushl * pushl %eax @@ -1497,16 +1865,19 @@ PSFacBuf_CreateProxy( * * arg3 arg2 arg1 */ - xasm->popleax = 0x58; - xasm->pushlval = 0x6a; - xasm->nr = i; - xasm->pushleax = 0x50; - xasm->lcall = 0xe8; /* relative jump */ - xasm->xcall = (DWORD)xCall; - xasm->xcall -= (DWORD)&(xasm->lret); - xasm->lret = 0xc2; - xasm->bytestopop= (nrofargs+2)*4; /* pop args, This, iMethod */ - proxy->lpvtbl[i] = xasm; + xasm->popleax = 0x58; + xasm->pushlval = 0x6a; + xasm->nr = i; + xasm->pushleax = 0x50; + xasm->lcall = 0xe8; /* relative jump */ + xasm->xcall = (DWORD)xCall; + xasm->xcall -= (DWORD)&(xasm->lret); + xasm->lret = 0xc2; + xasm->bytestopop= (nrofargs+2)*4; /* pop args, This, iMethod */ + proxy->lpvtbl[i] = xasm; + break; + } + } } proxy->lpvtbl2 = &tmproxyvtable; /* 1 reference for the proxy and 1 for the object */ @@ -1603,6 +1974,8 @@ TMStubImpl_Invoke( marshal_state buf; int nrofnames; BSTR names[10]; + BSTR fname = NULL,iname = NULL; + BOOL is_idispatch_getidsofnames = 0; memset(&buf,0,sizeof(buf)); buf.size = xmsg->cbBuffer; @@ -1622,11 +1995,18 @@ TMStubImpl_Invoke( xmsg->cbBuffer = buf.size; return hres; } - hres = _get_funcdesc(This->tinfo,xmsg->iMethod,&fdesc,NULL,NULL); + hres = _get_funcdesc(This->tinfo,xmsg->iMethod,&fdesc,&iname,&fname); if (hres) { ERR("GetFuncDesc on method %ld failed with %lx\n",xmsg->iMethod,hres); return hres; } + + if (iname && fname && !lstrcmpW(iname, IDispatchW) && !lstrcmpW(fname, GetIDsOfNamesW)) + is_idispatch_getidsofnames = 1; + + if (iname) SysFreeString (iname); + if (fname) SysFreeString (fname); + /* Need them for hack below */ memset(names,0,sizeof(names)); ITypeInfo_GetNames(This->tinfo,fdesc->memid,names,sizeof(names)/sizeof(names[0]),&nrofnames); @@ -1641,6 +2021,16 @@ TMStubImpl_Invoke( args = HeapAlloc(GetProcessHeap(),0,(nrofargs+1)*sizeof(DWORD)); if (!args) return E_OUTOFMEMORY; + if (is_idispatch_getidsofnames) { + hres = deserialize_IDispatch_GetIDsOfNames(TRUE,FALSE,args+1,&buf); + if (hres != S_OK) { + FIXME("deserialize_IDispatch_GetIDsOfNames failed!\n"); + return hres; + } + xargs = args+1+5; + goto afterdeserialize; + } + /* Allocate all stuff used by call. */ xargs = args+1; for (i=0;icParams;i++) { @@ -1673,7 +2063,7 @@ TMStubImpl_Invoke( if (!lstrcmpW(names[i+1],ppvObjectW)) { hres = deserialize_LPVOID_ptr( This->tinfo, - elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT, + elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN, FALSE, TRUE, &elem->tdesc, @@ -1700,19 +2090,30 @@ TMStubImpl_Invoke( break; } } +afterdeserialize: hres = IUnknown_QueryInterface(This->pUnk,&(This->iid),(LPVOID*)&(args[0])); if (hres) { - ERR("Does not support iface %s\n",debugstr_guid(&(This->iid))); + ERR("Does not support iface %s, returning %lx\n",debugstr_guid(&(This->iid)), hres); return hres; } res = _invoke( - (*((FARPROC**)args[0]))[fdesc->oVft/4], - fdesc->callconv, - (xargs-args), - args + (*((FARPROC**)args[0]))[fdesc->oVft/4], + fdesc->callconv, + (xargs-args), + args ); IUnknown_Release((LPUNKNOWN)args[0]); buf.curoff = 0; + + /* special IDispatch::GetIDsOfNames serializer */ + if (is_idispatch_getidsofnames) { + hres = serialize_IDispatch_GetIDsOfNames(FALSE,FALSE,args+1,&buf); + if (hres != S_OK) { + FIXME("serialize of IDispatch::GetIDsOfNames failed!\n"); + return hres; + } + goto afterserialize; + } xargs = args+1; for (i=0;icParams;i++) { ELEMDESC *elem = fdesc->lprgelemdescParam+i; @@ -1767,11 +2168,16 @@ TMStubImpl_Invoke( break; } } +afterserialize: + hres = xbuf_add (&buf, (LPBYTE)&res, sizeof(DWORD)); + if (hres != S_OK) + return hres; + /* might need to use IRpcChannelBuffer_GetBuffer ? */ xmsg->cbBuffer = buf.curoff; xmsg->Buffer = buf.base; HeapFree(GetProcessHeap(),0,args); - return res; + return S_OK; } static LPRPCSTUBBUFFER WINAPI diff --git a/reactos/lib/oleaut32/typelib.c b/reactos/lib/oleaut32/typelib.c index c237dabacb0..1b8361c50e9 100644 --- a/reactos/lib/oleaut32/typelib.c +++ b/reactos/lib/oleaut32/typelib.c @@ -1625,25 +1625,25 @@ MSFT_DoFuncs(TLBContext* pcx, * member information is stored in a data structure at offset * indicated by the memoffset field of the typeinfo structure * There are several distinctive parts. - * the first part starts with a field that holds the total length + * The first part starts with a field that holds the total length * of this (first) part excluding this field. Then follow the records, * for each member there is one record. * - * First entry is always the length of the record (including this + * The first entry is always the length of the record (including this * length word). - * Rest of the record depends on the type of the member. If there is - * a field indicating the member type (function variable intereface etc) + * The rest of the record depends on the type of the member. If there is + * a field indicating the member type (function, variable, interface, etc) * I have not found it yet. At this time we depend on the information * in the type info and the usual order how things are stored. * - * Second follows an array sized nrMEM*sizeof(INT) with a memeber id + * Second follows an array sized nrMEM*sizeof(INT) with a member id * for each member; * - * Third is a equal sized array with file offsets to the name entry + * Third is an equal sized array with file offsets to the name entry * of each member. * - * Forth and last (?) part is an array with offsets to the records in the - * first part of this file segment. + * The fourth and last (?) part is an array with offsets to the records + * in the first part of this file segment. */ int infolen, nameoffset, reclength, nrattributes, i; @@ -4516,7 +4516,6 @@ _copy_arg( ITypeInfo2 *tinfo, TYPEDESC *tdesc, DWORD *argpos, VARIANT *arg, VARTYPE vt ) { UINT arglen = _argsize(vt)*sizeof(DWORD); - VARTYPE oldvt; VARIANT va; if ((vt==VT_PTR) && tdesc && (tdesc->u.lptdesc->vt == VT_VARIANT)) { @@ -4650,7 +4649,6 @@ _copy_arg( ITypeInfo2 *tinfo, TYPEDESC *tdesc, return hres; } - oldvt = V_VT(arg); VariantInit(&va); if (VariantChangeType(&va,arg,0,vt)==S_OK) { memcpy(argpos,&V_I4(&va), arglen); @@ -4687,7 +4685,7 @@ DispCallFunc( dump_Variant(prgpvarg[i]); argsize += _argsize(prgvt[i]); } - args = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize); + args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize); args[0] = (DWORD)pvInstance; /* this is the fake IDispatch interface pointer */ argspos = 1; for (i=0;i