Sync to Wine-20050419:
authorGé van Geldorp <ge@gse.nl>
Thu, 5 May 2005 18:29:41 +0000 (18:29 +0000)
committerGé van Geldorp <ge@gse.nl>
Thu, 5 May 2005 18:29:41 +0000 (18:29 +0000)
Daniel Remenak <dtremenak@gmail.com>
- 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 <meissner@suse.de>
- 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 <mike@navi.cx>
- Fix BSTR tracing in the typelib marshaller.
- Fix PARAMFLAG_FOUT typo in the tmarshaller.
Mike Hearn <mh@codeweavers.com>
Robert Shearman <rob@codeweavers.com>
- 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 <rob@codeweavers.com>
- Add outer unknown support for typelib marshaler.
Jakob Eriksson <jakov@vmlinux.org>
- Get rid of HeapAlloc casts.
Francois Gouget <fgouget@free.fr>
- Assorted spelling fixes.
Alex Villacis Lasso <a_villacis@palosanto.com>
- 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
reactos/lib/oleaut32/oleaut32.spec
reactos/lib/oleaut32/olepicture.c
reactos/lib/oleaut32/safearray.c
reactos/lib/oleaut32/tmarshal.c
reactos/lib/oleaut32/typelib.c
reactos/lib/oleaut32/typelib.h
reactos/lib/oleaut32/variant.c
reactos/lib/oleaut32/vartype.c

index 1b2f8f3..6105baa 100644 (file)
@@ -235,9 +235,8 @@ BSTR WINAPI SysAllocStringLen(const OLECHAR *str, unsigned int len)
      * buffer for the character count and an extra character at the\r
      * end for the NULL.\r
      */\r
-    newBuffer = (DWORD*)HeapAlloc(GetProcessHeap(),\r
-                                 0,\r
-                                 bufferSize + sizeof(WCHAR) + sizeof(DWORD));\r
+    newBuffer = HeapAlloc(GetProcessHeap(), 0,\r
+                          bufferSize + sizeof(WCHAR) + sizeof(DWORD));\r
 \r
     /*\r
      * If the memory allocation failed, return a null pointer.\r
@@ -350,9 +349,8 @@ BSTR WINAPI SysAllocStringByteLen(LPCSTR str, UINT len)
      * buffer for the character count and an extra character at the\r
      * end for the NULL.\r
      */\r
-    newBuffer = (DWORD*)HeapAlloc(GetProcessHeap(),\r
-                                 0,\r
-                                 len + sizeof(WCHAR) + sizeof(DWORD));\r
+    newBuffer = HeapAlloc(GetProcessHeap(), 0,\r
+                          len + sizeof(WCHAR) + sizeof(DWORD));\r
 \r
     /*\r
      * If the memory allocation failed, return a null pointer.\r
index a3a67a1..0a8ac66 100644 (file)
 149 stdcall SysStringByteLen(ptr)\r
 150 stdcall SysAllocStringByteLen(ptr long)\r
 152 stdcall VarEqv(ptr ptr ptr)\r
-153 stub VarIdiv # stdcall (ptr ptr ptr)\r
+153 stdcall VarIdiv(ptr ptr ptr)\r
 154 stub VarImp # stdcall (ptr ptr ptr)\r
 155 stdcall VarMod(ptr ptr ptr)\r
 156 stdcall VarMul(ptr ptr ptr)\r
index 2883c34..2dd60cb 100644 (file)
@@ -185,6 +185,36 @@ static void OLEPictureImpl_SetBitmap(OLEPictureImpl*This) {
   DeleteDC(hdcRef);\r
 }\r
 \r
+static void OLEPictureImpl_SetIcon(OLEPictureImpl * This)\r
+{\r
+    ICONINFO infoIcon;\r
+\r
+    TRACE("icon handle %p\n", This->desc.u.icon.hicon);\r
+    if (GetIconInfo(This->desc.u.icon.hicon, &infoIcon)) {\r
+        HDC hdcRef;\r
+        BITMAP bm;\r
+\r
+        TRACE("bitmap handle for icon is %p\n", infoIcon.hbmColor);\r
+        if(GetObjectA(infoIcon.hbmColor ? infoIcon.hbmColor : infoIcon.hbmMask, sizeof(bm), &bm) != sizeof(bm)) {\r
+            ERR("GetObject fails on icon bitmap\n");\r
+            return;\r
+        }\r
+\r
+        This->origWidth = bm.bmWidth;\r
+        This->origHeight = infoIcon.hbmColor ? bm.bmHeight : bm.bmHeight / 2;\r
+        /* see comment on HIMETRIC on OLEPictureImpl_SetBitmap() */\r
+        hdcRef = GetDC(0);\r
+        This->himetricWidth = (This->origWidth *2540)/GetDeviceCaps(hdcRef, LOGPIXELSX);\r
+        This->himetricHeight= (This->origHeight *2540)/GetDeviceCaps(hdcRef, LOGPIXELSY);\r
+        ReleaseDC(0, hdcRef);\r
+\r
+        DeleteObject(infoIcon.hbmMask);\r
+        if (infoIcon.hbmColor) DeleteObject(infoIcon.hbmColor);\r
+    } else {\r
+        ERR("GetIconInfo() fails on icon %p\n", This->desc.u.icon.hicon);\r
+    }\r
+}\r
+\r
 /************************************************************************\r
  * OLEPictureImpl_Construct\r
  *\r
@@ -260,6 +290,8 @@ static OLEPictureImpl* OLEPictureImpl_Construct(LPPICTDESC pictDesc, BOOL fOwn)
        break;\r
 \r
       case PICTYPE_ICON:\r
+        OLEPictureImpl_SetIcon(newObject);\r
+        break;\r
       case PICTYPE_ENHMETAFILE:\r
       default:\r
        FIXME("Unsupported type %d\n", pictDesc->picType);\r
@@ -1071,7 +1103,7 @@ static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) {
        eb = si->ExtensionBlocks + i;\r
        if (eb->Function == 0xF9 && eb->ByteCount == 4) {\r
            if ((eb->Bytes[0] & 1) == 1) {\r
-               transparent = eb->Bytes[3];\r
+               transparent = (unsigned char)eb->Bytes[3];\r
            }\r
        }\r
     }\r
@@ -1145,7 +1177,7 @@ static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) {
 \r
        This->hbmMask = CreateBitmap(bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight, 1, 1, NULL);\r
 \r
-       hOldbitmap = SelectObject(hdc,This->desc.u.bmp.hbitmap); \r
+       hOldbitmap = SelectObject(hdc,This->desc.u.bmp.hbitmap);\r
        hOldbitmapmask = SelectObject(hdcMask, This->hbmMask);\r
        SetBkColor(hdc, This->rgbTrans);\r
        BitBlt(hdcMask, 0, 0, bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight, hdc, 0, 0, SRCCOPY);\r
@@ -1501,7 +1533,7 @@ static int serializeBMP(HBITMAP hBitmap, void ** ppBuffer, unsigned int * pLengt
     BITMAPFILEHEADER * pFileHeader;\r
     BITMAPINFO * pInfoHeader;\r
 \r
-    pInfoBitmap = (BITMAPINFO *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,\r
+    pInfoBitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,\r
         sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));\r
 \r
     /* Find out bitmap size and padded length */\r
@@ -1511,8 +1543,7 @@ static int serializeBMP(HBITMAP hBitmap, void ** ppBuffer, unsigned int * pLengt
 \r
     /* Fetch bitmap palette & pixel data */\r
 \r
-    pPixelData = (unsigned char *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,\r
-        pInfoBitmap->bmiHeader.biSizeImage);\r
+    pPixelData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, pInfoBitmap->bmiHeader.biSizeImage);\r
     GetDIBits(hDC, hBitmap, 0, pInfoBitmap->bmiHeader.biHeight, pPixelData, pInfoBitmap, DIB_RGB_COLORS);\r
 \r
     /* Calculate the total length required for the BMP data */\r
@@ -1530,7 +1561,7 @@ static int serializeBMP(HBITMAP hBitmap, void ** ppBuffer, unsigned int * pLengt
         sizeof(BITMAPINFOHEADER) +\r
         iNumPaletteEntries * sizeof(RGBQUAD) +\r
         pInfoBitmap->bmiHeader.biSizeImage;\r
-    *ppBuffer = (void *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *pLength);\r
+    *ppBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *pLength);\r
 \r
     /* Fill the BITMAPFILEHEADER */\r
     pFileHeader = (BITMAPFILEHEADER *)(*ppBuffer);\r
@@ -1569,7 +1600,7 @@ static int serializeIcon(HICON hIcon, void ** ppBuffer, unsigned int * pLength)
                unsigned char * pIconData = NULL;\r
                unsigned int iDataSize = 0;\r
 \r
-        pInfoBitmap = (BITMAPINFO *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));\r
+        pInfoBitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));\r
 \r
                /* Find out icon size */\r
                hDC = GetDC(0);\r
@@ -1603,7 +1634,7 @@ static int serializeIcon(HICON hIcon, void ** ppBuffer, unsigned int * pLength)
 */\r
                        /* Let's start with one CURSORICONFILEDIR and one CURSORICONFILEDIRENTRY */\r
                        iDataSize += 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY) + sizeof(BITMAPINFOHEADER);\r
-                       pIconData = (unsigned char *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, iDataSize);\r
+                       pIconData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, iDataSize);\r
 \r
                        /* Fill out the CURSORICONFILEDIR */\r
                        pIconDir = (CURSORICONFILEDIR *)pIconData;\r
@@ -1651,7 +1682,7 @@ static int serializeIcon(HICON hIcon, void ** ppBuffer, unsigned int * pLength)
                        iDataSize += pIconBitmapHeader->biHeight * iLengthScanLineMask;\r
                        pIconBitmapHeader->biSizeImage += pIconBitmapHeader->biHeight * iLengthScanLineMask;\r
                        pIconBitmapHeader->biHeight *= 2;\r
-                       pIconData = (unsigned char *)HeapReAlloc(GetProcessHeap(), 0, pIconData, iDataSize);\r
+                       pIconData = HeapReAlloc(GetProcessHeap(), 0, pIconData, iDataSize);\r
                        pIconEntry = (CURSORICONFILEDIRENTRY *)(pIconData + 3 * sizeof(WORD));\r
                        pIconBitmapHeader = (BITMAPINFOHEADER *)(pIconData + 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));\r
                        pIconEntry->dwDIBSize = iDataSize - (3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));\r
index d183a5c..90bcf64 100644 (file)
@@ -647,7 +647,7 @@ SAFEARRAY* WINAPI SafeArrayCreateEx(VARTYPE vt, UINT cDims, SAFEARRAYBOUND *rgsa
 /************************************************************************\r
  *             SafeArrayCreateVector (OLEAUT32.411)\r
  *\r
- * Create a one dimensional, contigous SafeArray.\r
+ * Create a one dimensional, contiguous SafeArray.\r
  *\r
  * PARAMS\r
  *  vt        [I] Type to store in the safe array\r
@@ -674,7 +674,7 @@ SAFEARRAY* WINAPI SafeArrayCreateVector(VARTYPE vt, LONG lLbound, ULONG cElement
 /************************************************************************\r
  *             SafeArrayCreateVectorEx (OLEAUT32.411)\r
  *\r
- * Create a one dimensional, contigous SafeArray.\r
+ * Create a one dimensional, contiguous SafeArray.\r
  *\r
  * PARAMS\r
  *  vt        [I] Type to store in the safe array\r
index efc1f10..9159122 100644 (file)
@@ -1,7 +1,7 @@
 /*\r
  *     TYPELIB Marshaler\r
  *\r
- *     Copyright 2002  Marcus Meissner\r
+ *     Copyright 2002,2005     Marcus Meissner\r
  *\r
  * The olerelay debug channel allows you to see calls marshalled by\r
  * the typelib marshaller. It is not a generic COM relaying system.\r
@@ -48,6 +48,8 @@
 static const WCHAR riidW[5] = {'r','i','i','d',0};\r
 static const WCHAR pdispparamsW[] = {'p','d','i','s','p','p','a','r','a','m','s',0};\r
 static const WCHAR ppvObjectW[] = {'p','p','v','O','b','j','e','c','t',0};\r
+static const WCHAR IDispatchW[] = { 'I','D','i','s','p','a','t','c','h',0};\r
+static const WCHAR GetIDsOfNamesW[] = { 'G','e','t','I','D','s','O','f','N','a','m','e','s',0};\r
 \r
 WINE_DEFAULT_DEBUG_CHANNEL(ole);\r
 WINE_DECLARE_DEBUG_CHANNEL(olerelay);\r
@@ -167,12 +169,19 @@ _marshal_interface(marshal_state *buf, REFIID riid, LPUNKNOWN pUnk) {
     DWORD              xsize;\r
     HRESULT            hres;\r
 \r
-    hres = E_FAIL;\r
     if (!pUnk) {\r
+       /* this is valid, if for instance we serialize\r
+        * a VT_DISPATCH with NULL ptr which apparently\r
+        * can happen. S_OK to make sure we continue\r
+        * serializing.\r
+        */\r
         ERR("pUnk is NULL?\n");\r
-       goto fail;\r
+        xsize = 0;\r
+        return xbuf_add(buf,(LPBYTE)&xsize,sizeof(xsize));\r
     }\r
 \r
+    hres = E_FAIL;\r
+\r
     TRACE("...%s...\n",debugstr_guid(riid));\r
     hres = IUnknown_QueryInterface(pUnk,riid,(LPVOID*)&newiface);\r
     if (hres) {\r
@@ -355,6 +364,7 @@ typedef struct _TMProxyImpl {
     IRpcChannelBuffer*                 chanbuf;\r
     IID                                        iid;\r
     CRITICAL_SECTION   crit;\r
+    IUnknown                           *outerunknown;\r
 } TMProxyImpl;\r
 \r
 static HRESULT WINAPI\r
@@ -499,17 +509,36 @@ serialize_param(
        return S_OK;\r
     case VT_BOOL:\r
     case VT_ERROR:\r
-    case VT_UI4:\r
     case VT_UINT:\r
     case VT_I4:\r
     case VT_R4:\r
+    case VT_UI4:\r
+       hres = S_OK;\r
+       if (debugout) TRACE_(olerelay)("%lx",*arg);\r
+       if (writeit)\r
+           hres = xbuf_add(buf,(LPBYTE)arg,sizeof(DWORD));\r
+       return hres;\r
+    case VT_I2:\r
     case VT_UI2:\r
+       hres = S_OK;\r
+       if (debugout) TRACE_(olerelay)("%04lx",*arg & 0xffff);\r
+       if (writeit)\r
+           hres = xbuf_add(buf,(LPBYTE)arg,sizeof(DWORD));\r
+       return hres;\r
+    case VT_I1:\r
     case VT_UI1:\r
        hres = S_OK;\r
-       if (debugout) TRACE_(olerelay)("%lx",*arg);\r
+       if (debugout) TRACE_(olerelay)("%02lx",*arg & 0xff);\r
        if (writeit)\r
            hres = xbuf_add(buf,(LPBYTE)arg,sizeof(DWORD));\r
        return hres;\r
+    case VT_I4|VT_BYREF:\r
+       hres = S_OK;\r
+       if (debugout) TRACE_(olerelay)("&0x%lx",*arg);\r
+       if (writeit)\r
+           hres = xbuf_add(buf,(LPBYTE)(DWORD*)*arg,sizeof(DWORD));\r
+       /* do not dealloc at this time */\r
+       return hres;\r
     case VT_VARIANT: {\r
        TYPEDESC        tdesc2;\r
        VARIANT         *vt = (VARIANT*)arg;\r
@@ -526,10 +555,34 @@ serialize_param(
        if (debugout) TRACE_(olerelay)(")");\r
        return hres;\r
     }\r
+    case VT_BSTR|VT_BYREF: {\r
+       if (debugout) TRACE_(olerelay)("[byref]'%s'", *(BSTR*)*arg ? relaystr(*((BSTR*)*arg)) : "<bstr NULL>");\r
+        if (writeit) {\r
+            /* ptr to ptr to magic widestring, basically */\r
+            BSTR *bstr = (BSTR *) *arg;\r
+            if (!*bstr) {\r
+                /* -1 means "null string" which is equivalent to empty string */\r
+                DWORD fakelen = -1;     \r
+                xbuf_add(buf, (LPBYTE)&fakelen,4);\r
+            } else {\r
+                /* BSTRs store the length behind the first character */\r
+                DWORD *len = ((DWORD *)(*bstr))-1;\r
+                hres = xbuf_add(buf, (LPBYTE) len, *len + 4);\r
+                if (hres) return hres;\r
+            }\r
+        }\r
+\r
+        if (dealloc && arg) {\r
+            BSTR *str = *((BSTR **)arg);\r
+            SysFreeString(*str);\r
+        }\r
+        return S_OK;\r
+    }\r
+    \r
     case VT_BSTR: {\r
        if (debugout) {\r
-           if (arg)\r
-                   TRACE_(olerelay)("%s",relaystr((BSTR)*arg));\r
+           if (*arg)\r
+                   TRACE_(olerelay)("%s",relaystr((WCHAR*)*arg));\r
            else\r
                    TRACE_(olerelay)("<bstr NULL>");\r
        }\r
@@ -556,12 +609,12 @@ serialize_param(
        DWORD cookie;\r
 \r
        if (debugout) TRACE_(olerelay)("*");\r
-       if (writeit) {\r
-           cookie = *arg ? 0x42424242 : 0;\r
-           hres = xbuf_add(buf,(LPBYTE)&cookie,sizeof(cookie));\r
-           if (hres)\r
-               return hres;\r
-       }\r
+       /* Write always, so the other side knows when it gets a NULL pointer.\r
+        */\r
+       cookie = *arg ? 0x42424242 : 0;\r
+       hres = xbuf_add(buf,(LPBYTE)&cookie,sizeof(cookie));\r
+       if (hres)\r
+           return hres;\r
        if (!*arg) {\r
            if (debugout) TRACE_(olerelay)("NULL");\r
            return S_OK;\r
@@ -660,6 +713,7 @@ serialize_param(
            if (debugout) TRACE_(olerelay)("[%ld]",adesc->rgbounds[i].cElements);\r
            arrsize *= adesc->rgbounds[i].cElements;\r
        }\r
+       if (debugout) TRACE_(olerelay)("(vt %d)",adesc->tdescElem.vt);\r
        if (debugout) TRACE_(olerelay)("[");\r
        for (i=0;i<arrsize;i++) {\r
            hres = serialize_param(tinfo, writeit, debugout, dealloc, &adesc->tdescElem, (DWORD*)((LPBYTE)arg+i*_xsize(&adesc->tdescElem)), buf);\r
@@ -676,6 +730,168 @@ serialize_param(
     }\r
 }\r
 \r
+/* IDL desc:\r
+ * HRESULT GetIDsOfNames(\r
+ *   [in] REFIID riid,                                 args[1]\r
+ *   [in, size_is(cNames)] LPOLESTR *rgszNames,                args[2]\r
+ *   [in] UINT cNames,                                 args[3]\r
+ *   [in] LCID lcid,                                   args[4]\r
+ *   [out, size_is(cNames)] DISPID *rgDispId);         args[5]\r
+ *\r
+ * line format:\r
+ *     IID     iid;\r
+ *     DWORD   cNames;\r
+ *     LPOLESTR rgszNames[cNames];\r
+ *             DWORD bytestrlen        (incl 0)\r
+ *             BYTE data[bytestrlen]   (incl 0)\r
+ *     LCID\r
+ */\r
+static HRESULT\r
+serialize_IDispatch_GetIDsOfNames(\r
+    BOOL               inputparams,\r
+    BOOL               debugout,\r
+    DWORD              *args,\r
+    marshal_state      *buf)\r
+{\r
+    HRESULT    hres;\r
+    DWORD      cNames = args[2];\r
+    LPOLESTR    *rgszNames = (LPOLESTR*)args[1];\r
+    int                i;\r
+\r
+    if (inputparams) {\r
+       if (debugout) TRACE_(olerelay)("riid=%s,",debugstr_guid((REFIID)args[0]));\r
+       hres = xbuf_add(buf, (LPBYTE)args[0], sizeof(IID));\r
+       if (hres) {\r
+           FIXME("serialize of IID failed.\n");\r
+           return hres;\r
+       }\r
+       if (debugout) TRACE_(olerelay)("cNames=%ld,",cNames);\r
+       hres = xbuf_add(buf, (LPBYTE)&cNames, sizeof(DWORD));\r
+       if (hres) {\r
+           FIXME("serialize of cNames failed.\n");\r
+           return hres;\r
+       }\r
+       if (debugout) TRACE_(olerelay)("rgszNames=[");\r
+        for (i=0;i<cNames;i++) {\r
+           DWORD len = 2*(lstrlenW(rgszNames[i])+1);\r
+\r
+           if (debugout) TRACE_(olerelay)("%s,",relaystr(rgszNames[i]));\r
+           hres = xbuf_add(buf, (LPBYTE)&len, sizeof(DWORD));\r
+           if (hres) {\r
+               FIXME("serialize of len failed.\n");\r
+               return hres;\r
+           }\r
+           hres = xbuf_add(buf, (LPBYTE)rgszNames[i], len);\r
+           if (hres) {\r
+               FIXME("serialize of rgszNames[i] failed.\n");\r
+               return hres;\r
+           }\r
+        }\r
+       if (debugout) TRACE_(olerelay)("],lcid=%04lx)",args[3]);\r
+       hres = xbuf_add(buf, (LPBYTE)&args[3], sizeof(DWORD));\r
+       if (hres) {\r
+           FIXME("serialize of lcid failed.\n");\r
+           return hres;\r
+       }\r
+    } else {\r
+       DISPID *rgDispId = (DISPID*)args[4];\r
+\r
+       hres = xbuf_add(buf, (LPBYTE)rgDispId, sizeof(DISPID) * cNames);\r
+       if (hres) {\r
+           FIXME("serialize of rgDispId failed.\n");\r
+           return hres;\r
+       }\r
+       if (debugout) {\r
+           TRACE_(olerelay)("riid=[in],rgszNames=[in],cNames=[in],rgDispId=[");\r
+           for (i=0;i<cNames;i++)\r
+               TRACE_(olerelay)("%08lx,",rgDispId[i]);\r
+           TRACE_(olerelay)("])");\r
+       }\r
+       HeapFree(GetProcessHeap(),0,(IID*)args[0]);\r
+       rgszNames = (LPOLESTR*)args[1];\r
+       for (i=0;i<cNames;i++) HeapFree(GetProcessHeap(),0,rgszNames[i]);\r
+       HeapFree(GetProcessHeap(),0,rgszNames);\r
+       HeapFree(GetProcessHeap(),0,rgDispId);\r
+    }\r
+    return S_OK;\r
+}\r
+\r
+static HRESULT\r
+deserialize_IDispatch_GetIDsOfNames(\r
+    BOOL               inputparams,\r
+    BOOL               debugout,\r
+    DWORD              *args,\r
+    marshal_state      *buf)\r
+{\r
+    HRESULT    hres;\r
+    DWORD      cNames;\r
+    LPOLESTR    *rgszNames;\r
+    int                i;\r
+\r
+    if (inputparams) {\r
+       args[0] = (DWORD)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IID));\r
+       if (!args[0]) return E_FAIL;\r
+       hres = xbuf_get(buf, (LPBYTE)args[0], sizeof(IID));\r
+       if (hres) {\r
+           FIXME("deserialize of IID failed.\n");\r
+           return hres;\r
+       }\r
+       if (debugout) TRACE_(olerelay)("riid=%s,",debugstr_guid((REFIID)args[0]));\r
+\r
+       hres = xbuf_get(buf, (LPBYTE)&cNames, sizeof(DWORD));\r
+       if (hres) {\r
+           FIXME("deserialize of cNames failed.\n");\r
+           return hres;\r
+       }\r
+        args[2] = cNames;\r
+       if (debugout) TRACE_(olerelay)("cNames=%ld,",cNames);\r
+       if (debugout) TRACE_(olerelay)("rgszNames=[");\r
+        rgszNames = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(LPOLESTR) * cNames);\r
+       if (!rgszNames) return E_FAIL;\r
+       args[1] = (DWORD)rgszNames;\r
+        for (i=0;i<cNames;i++) {\r
+           DWORD len;\r
+\r
+           hres = xbuf_get(buf, (LPBYTE)&len, sizeof(DWORD));\r
+           if (hres) {\r
+               FIXME("serialize of len failed.\n");\r
+               return hres;\r
+           }\r
+           rgszNames[i] = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);\r
+           if (!rgszNames[i]) {\r
+               FIXME("heapalloc of %ld bytes failed\n", len);\r
+               return E_FAIL;\r
+           }\r
+           hres = xbuf_get(buf, (LPBYTE)rgszNames[i], len);\r
+           if (hres) {\r
+               FIXME("serialize of rgszNames[i] failed.\n");\r
+               return hres;\r
+           }\r
+           if (debugout) TRACE_(olerelay)("%s,",relaystr(rgszNames[i]));\r
+        }\r
+       hres = xbuf_get(buf, (LPBYTE)&args[3], sizeof(DWORD));\r
+       if (hres) {\r
+           FIXME("deserialize of lcid failed.\n");\r
+           return hres;\r
+       }\r
+       if (debugout) TRACE_(olerelay)("],lcid=%04lx,rgDispId=[out])",args[3]);\r
+        args[4] = (DWORD)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DISPID) * cNames);\r
+    } else {\r
+       hres = xbuf_get(buf, (LPBYTE)args[4], sizeof(DISPID) * args[2]);\r
+       if (hres) {\r
+           FIXME("serialize of rgDispId failed.\n");\r
+           return hres;\r
+       }\r
+       if (debugout) {\r
+           TRACE_(olerelay)("dispid=[");\r
+           for (i=0;i<args[2];i++)\r
+               TRACE_(olerelay)("%08lx,",((DISPID*)args[4])[i]);\r
+           TRACE_(olerelay)("])");\r
+       }\r
+    }\r
+    return S_OK;\r
+}\r
+\r
 static HRESULT\r
 serialize_LPVOID_ptr(\r
     ITypeInfo          *tinfo,\r
@@ -696,13 +912,13 @@ serialize_LPVOID_ptr(
        FIXME("ppvObject not expressed as VT_PTR -> VT_PTR -> VT_VOID?\n");\r
        return E_FAIL;\r
     }\r
-    cookie = (*arg) ? 0x42424242: 0x0;\r
+    cookie = (*(DWORD*)*arg) ? 0x42424242: 0x0;\r
     if (writeit) {\r
        hres = xbuf_add(buf, (LPVOID)&cookie, sizeof(cookie));\r
        if (hres)\r
            return hres;\r
     }\r
-    if (!*arg) {\r
+    if (!*(DWORD*)*arg) {\r
        if (debugout) TRACE_(olerelay)("<lpvoid NULL>");\r
        return S_OK;\r
     }\r
@@ -849,15 +1065,79 @@ deserialize_param(
            }\r
        }\r
         case VT_ERROR:\r
-       case VT_BOOL: case VT_I4: case VT_UI4: case VT_UINT: case VT_R4:\r
-        case VT_UI2:\r
-       case VT_UI1:\r
+       case VT_BOOL:\r
+        case VT_I4:\r
+        case VT_UINT:\r
+        case VT_R4:\r
+        case VT_UI4:\r
            if (readit) {\r
                hres = xbuf_get(buf,(LPBYTE)arg,sizeof(DWORD));\r
                if (hres) ERR("Failed to read integer 4 byte\n");\r
            }\r
            if (debugout) TRACE_(olerelay)("%lx",*arg);\r
            return hres;\r
+        case VT_I2:\r
+        case VT_UI2:\r
+           if (readit) {\r
+               DWORD x;\r
+               hres = xbuf_get(buf,(LPBYTE)&x,sizeof(DWORD));\r
+               if (hres) ERR("Failed to read integer 4 byte\n");\r
+               memcpy(arg,&x,2);\r
+           }\r
+           if (debugout) TRACE_(olerelay)("%04lx",*arg & 0xffff);\r
+           return hres;\r
+        case VT_I1:\r
+       case VT_UI1:\r
+           if (readit) {\r
+               DWORD x;\r
+               hres = xbuf_get(buf,(LPBYTE)&x,sizeof(DWORD));\r
+               if (hres) ERR("Failed to read integer 4 byte\n");\r
+               memcpy(arg,&x,1);\r
+           }\r
+           if (debugout) TRACE_(olerelay)("%02lx",*arg & 0xff);\r
+           return hres;\r
+        case VT_I4|VT_BYREF:\r
+           hres = S_OK;\r
+           if (alloc)\r
+               *arg = (DWORD)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DWORD));\r
+           if (readit) {\r
+               hres = xbuf_get(buf,(LPBYTE)*arg,sizeof(DWORD));\r
+               if (hres) ERR("Failed to read integer 4 byte\n");\r
+           }\r
+           if (debugout) TRACE_(olerelay)("&0x%lx",*(DWORD*)*arg);\r
+           return hres;\r
+       case VT_BSTR|VT_BYREF: {\r
+           BSTR **bstr = (BSTR **)arg;\r
+           WCHAR       *str;\r
+           DWORD       len;\r
+\r
+           if (readit) {\r
+               hres = xbuf_get(buf,(LPBYTE)&len,sizeof(DWORD));\r
+               if (hres) {\r
+                   ERR("failed to read bstr klen\n");\r
+                   return hres;\r
+               }\r
+               if (len == -1) {\r
+                    *bstr = CoTaskMemAlloc(sizeof(BSTR *));\r
+                   **bstr = NULL;\r
+                   if (debugout) TRACE_(olerelay)("<bstr NULL>");\r
+               } else {\r
+                   str  = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,len+sizeof(WCHAR));\r
+                   hres = xbuf_get(buf,(LPBYTE)str,len);\r
+                   if (hres) {\r
+                       ERR("Failed to read BSTR.\n");\r
+                       return hres;\r
+                   }\r
+                    *bstr = CoTaskMemAlloc(sizeof(BSTR *));\r
+                   **bstr = SysAllocStringLen(str,len);\r
+                   if (debugout) TRACE_(olerelay)("%s",relaystr(str));\r
+                   HeapFree(GetProcessHeap(),0,str);\r
+               }\r
+           } else {\r
+               *bstr = NULL;\r
+           }\r
+           return S_OK;\r
+       }\r
        case VT_BSTR: {\r
            WCHAR       *str;\r
            DWORD       len;\r
@@ -889,24 +1169,26 @@ deserialize_param(
        }\r
        case VT_PTR: {\r
            DWORD       cookie;\r
-           BOOL        derefhere = 0;\r
+           BOOL        derefhere = 0;\r
 \r
            derefhere = (tdesc->u.lptdesc->vt != VT_USERDEFINED);\r
-\r
-           if (readit) {\r
-               hres = xbuf_get(buf,(LPBYTE)&cookie,sizeof(cookie));\r
-               if (hres) {\r
-                   ERR("Failed to load pointer cookie.\n");\r
-                   return hres;\r
-               }\r
-               if (cookie != 0x42424242) {\r
-                   if (debugout) TRACE_(olerelay)("NULL");\r
-                   *arg = 0;\r
-                   return S_OK;\r
-               }\r
-               if (debugout) TRACE_(olerelay)("*");\r
+           /* read it in all cases, we need to know if we have \r
+            * NULL pointer or not.\r
+            */\r
+           hres = xbuf_get(buf,(LPBYTE)&cookie,sizeof(cookie));\r
+           if (hres) {\r
+               ERR("Failed to load pointer cookie.\n");\r
+               return hres;\r
+           }\r
+           if (cookie != 0x42424242) {\r
+               /* we read a NULL ptr from the remote side */\r
+               if (debugout) TRACE_(olerelay)("NULL");\r
+               *arg = 0;\r
+               return S_OK;\r
            }\r
+           if (debugout) TRACE_(olerelay)("*");\r
            if (alloc) {\r
+               /* Allocate space for the referenced struct */\r
                if (derefhere)\r
                    *arg=(DWORD)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,_xsize(tdesc->u.lptdesc));\r
            }\r
@@ -948,8 +1230,6 @@ deserialize_param(
            if (hres) {\r
                ERR("Could not get typeattr in VT_USERDEFINED.\n");\r
            } else {\r
-               if (alloc)\r
-                   *arg = (DWORD)HeapAlloc(GetProcessHeap(),0,tattr->cbSizeInstance);\r
                switch (tattr->typekind) {\r
                case TKIND_DISPATCH:\r
                case TKIND_INTERFACE:\r
@@ -959,6 +1239,9 @@ deserialize_param(
                case TKIND_RECORD: {\r
                    int i;\r
 \r
+                   if (alloc)\r
+                       *arg = (DWORD)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,tattr->cbSizeInstance);\r
+\r
                    if (debugout) TRACE_(olerelay)("{");\r
                    for (i=0;i<tattr->cVars;i++) {\r
                        VARDESC *vdesc;\r
@@ -1056,8 +1339,10 @@ deserialize_LPVOID_ptr(
     }\r
     if (readit) {\r
        hres = _unmarshal_interface(buf,&buf->iid,(LPUNKNOWN*)*arg);\r
-       if (hres)\r
+       if (hres) {\r
+           FIXME("_unmarshal_interface of %s , %p failed with %lx\n", debugstr_guid(&buf->iid), (LPUNKNOWN*)*arg, hres);\r
            return hres;\r
+       }\r
     }\r
     if (debugout) TRACE_(olerelay)("ppv(%p)",(LPVOID)*arg);\r
     return S_OK;\r
@@ -1209,6 +1494,8 @@ xCall(LPVOID retptr, int method, TMProxyImpl *tpinfo /*, args */)
     BSTR               fname,iname;\r
     BSTR               names[10];\r
     int                        nrofnames;\r
+    int                        is_idispatch_getidsofnames = 0;\r
+    DWORD              remoteresult = 0;\r
 \r
     EnterCriticalSection(&tpinfo->crit);\r
 \r
@@ -1235,9 +1522,35 @@ xCall(LPVOID retptr, int method, TMProxyImpl *tpinfo /*, args */)
        else\r
            TRACE_(olerelay)("%d",method);\r
        TRACE_(olerelay)("(");\r
-       if (iname) SysFreeString(iname);\r
-       if (fname) SysFreeString(fname);\r
     }\r
+    if (iname && fname && !lstrcmpW(iname,IDispatchW) && !lstrcmpW(fname,GetIDsOfNamesW))\r
+        is_idispatch_getidsofnames = 1;\r
+\r
+    if (iname) SysFreeString(iname);\r
+    if (fname) SysFreeString(fname);\r
+\r
+    memset(&buf,0,sizeof(buf));\r
+    buf.iid = IID_IUnknown;\r
+\r
+    /* Special IDispatch::GetIDsOfNames() serializer */\r
+    if (is_idispatch_getidsofnames) {\r
+       hres = serialize_IDispatch_GetIDsOfNames(TRUE,relaydeb,args,&buf);\r
+       if (hres != S_OK) {\r
+           FIXME("serialize of IDispatch::GetIDsOfNames failed!\n");\r
+           return hres;\r
+       }\r
+       goto afterserialize;\r
+    }\r
+\r
+    /* special QueryInterface serialize */\r
+    if (method == 0) {\r
+       xbuf_add(&buf,(LPBYTE)args[0],sizeof(IID));\r
+       if (relaydeb) TRACE_(olerelay)("riid=%s,[out])",debugstr_guid((REFIID)args[0]));\r
+       goto afterserialize;\r
+    }\r
+\r
+    /* normal typelib driven serializing */\r
+\r
     /* Need them for hack below */\r
     memset(names,0,sizeof(names));\r
     if (ITypeInfo_GetNames(tpinfo->tinfo,fdesc->memid,names,sizeof(names)/sizeof(names[0]),&nrofnames))\r
@@ -1245,62 +1558,42 @@ xCall(LPVOID retptr, int method, TMProxyImpl *tpinfo /*, args */)
     if (nrofnames > sizeof(names)/sizeof(names[0]))\r
        ERR("Need more names!\n");\r
 \r
-    memset(&buf,0,sizeof(buf));\r
-    buf.iid = IID_IUnknown;\r
-    if (method == 0) {\r
-       xbuf_add(&buf,(LPBYTE)args[0],sizeof(IID));\r
-       if (relaydeb) TRACE_(olerelay)("riid=%s,[out]",debugstr_guid((REFIID)args[0]));\r
-    } else {\r
-       xargs = args;\r
-       for (i=0;i<fdesc->cParams;i++) {\r
-           ELEMDESC    *elem = fdesc->lprgelemdescParam+i;\r
-           BOOL        isserialized = FALSE;\r
-           if (relaydeb) {\r
-               if (i) TRACE_(olerelay)(",");\r
-               if (i+1<nrofnames && names[i+1])\r
-                   TRACE_(olerelay)("%s=",relaystr(names[i+1]));\r
-           }\r
-           /* No need to marshal other data than FIN */\r
-           if (!(elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN)) {\r
-               xargs+=_argsize(elem->tdesc.vt);\r
-               if (relaydeb) TRACE_(olerelay)("[out]");\r
-               continue;\r
-           }\r
-           if (((i+1)<nrofnames) && !IsBadStringPtrW(names[i+1],1)) {\r
-               /* If the parameter is 'riid', we use it as interface IID\r
-                * for a later ppvObject serialization.\r
-                */\r
-               buf.thisisiid = !lstrcmpW(names[i+1],riidW);\r
-\r
-               /* DISPPARAMS* needs special serializer */\r
-               if (!lstrcmpW(names[i+1],pdispparamsW)) {\r
-                   hres = serialize_DISPPARAM_ptr(\r
-                       tpinfo->tinfo,\r
-                       elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN,\r
-                       relaydeb,\r
-                       FALSE,\r
-                       &elem->tdesc,\r
-                       xargs,\r
-                       &buf\r
-                   );\r
-                   isserialized = TRUE;\r
-               }\r
-               if (!lstrcmpW(names[i+1],ppvObjectW)) {\r
-                   hres = serialize_LPVOID_ptr(\r
-                       tpinfo->tinfo,\r
-                       elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN,\r
-                       relaydeb,\r
-                       FALSE,\r
-                       &elem->tdesc,\r
-                       xargs,\r
-                       &buf\r
-                   );\r
-                   if (hres == S_OK)\r
-                       isserialized = TRUE;\r
-               }\r
+    xargs = args;\r
+    for (i=0;i<fdesc->cParams;i++) {\r
+       ELEMDESC        *elem = fdesc->lprgelemdescParam+i;\r
+       BOOL    isserialized = FALSE;\r
+       if (relaydeb) {\r
+           if (i) TRACE_(olerelay)(",");\r
+           if (i+1<nrofnames && names[i+1])\r
+               TRACE_(olerelay)("%s=",relaystr(names[i+1]));\r
+       }\r
+       /* No need to marshal other data than FIN and any VT_PTR. */\r
+       if (!(elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN) && (elem->tdesc.vt != VT_PTR)) {\r
+           xargs+=_argsize(elem->tdesc.vt);\r
+           if (relaydeb) TRACE_(olerelay)("[out]");\r
+           continue;\r
+       }\r
+       if (((i+1)<nrofnames) && !IsBadStringPtrW(names[i+1],1)) {\r
+           /* If the parameter is 'riid', we use it as interface IID\r
+            * for a later ppvObject serialization.\r
+            */\r
+           buf.thisisiid = !lstrcmpW(names[i+1],riidW);\r
+\r
+           /* DISPPARAMS* needs special serializer */\r
+           if (!lstrcmpW(names[i+1],pdispparamsW)) {\r
+               hres = serialize_DISPPARAM_ptr(\r
+                   tpinfo->tinfo,\r
+                   elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN,\r
+                   relaydeb,\r
+                   FALSE,\r
+                   &elem->tdesc,\r
+                   xargs,\r
+                   &buf\r
+               );\r
+               isserialized = TRUE;\r
            }\r
-           if (!isserialized)\r
-               hres = serialize_param(\r
+           if (!lstrcmpW(names[i+1],ppvObjectW)) {\r
+               hres = serialize_LPVOID_ptr(\r
                    tpinfo->tinfo,\r
                    elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN,\r
                    relaydeb,\r
@@ -1309,15 +1602,30 @@ xCall(LPVOID retptr, int method, TMProxyImpl *tpinfo /*, args */)
                    xargs,\r
                    &buf\r
                );\r
-\r
-           if (hres) {\r
-               ERR("Failed to serialize param, hres %lx\n",hres);\r
-               break;\r
+               if (hres == S_OK)\r
+                   isserialized = TRUE;\r
            }\r
-           xargs+=_argsize(elem->tdesc.vt);\r
        }\r
+       if (!isserialized)\r
+           hres = serialize_param(\r
+               tpinfo->tinfo,\r
+               elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN,\r
+               relaydeb,\r
+               FALSE,\r
+               &elem->tdesc,\r
+               xargs,\r
+               &buf\r
+           );\r
+\r
+       if (hres) {\r
+           ERR("Failed to serialize param, hres %lx\n",hres);\r
+           break;\r
+       }\r
+       xargs+=_argsize(elem->tdesc.vt);\r
     }\r
     if (relaydeb) TRACE_(olerelay)(")");\r
+\r
+afterserialize:\r
     memset(&msg,0,sizeof(msg));\r
     msg.cbBuffer = buf.curoff;\r
     msg.iMethod  = method;\r
@@ -1336,7 +1644,7 @@ xCall(LPVOID retptr, int method, TMProxyImpl *tpinfo /*, args */)
        return hres;\r
     }\r
 \r
-    if (relaydeb) TRACE_(olerelay)(" = %08lx (",status);\r
+    if (relaydeb) TRACE_(olerelay)(" status = %08lx (",status);\r
     if (buf.base)\r
        buf.base = HeapReAlloc(GetProcessHeap(),0,buf.base,msg.cbBuffer);\r
     else\r
@@ -1344,86 +1652,143 @@ xCall(LPVOID retptr, int method, TMProxyImpl *tpinfo /*, args */)
     buf.size = msg.cbBuffer;\r
     memcpy(buf.base,msg.Buffer,buf.size);\r
     buf.curoff = 0;\r
+\r
+    /* Special IDispatch::GetIDsOfNames() deserializer */\r
+    if (is_idispatch_getidsofnames) {\r
+       hres = deserialize_IDispatch_GetIDsOfNames(FALSE,relaydeb,args,&buf);\r
+       if (hres != S_OK) {\r
+           FIXME("deserialize of IDispatch::GetIDsOfNames failed!\n");\r
+           return hres;\r
+       }\r
+       goto after_deserialize;\r
+    }\r
+    /* Special QueryInterface deserializer */\r
     if (method == 0) {\r
        _unmarshal_interface(&buf,(REFIID)args[0],(LPUNKNOWN*)args[1]);\r
        if (relaydeb) TRACE_(olerelay)("[in],%p",*((DWORD**)args[1]));\r
-    } else {\r
-       xargs = args;\r
-       for (i=0;i<fdesc->cParams;i++) {\r
-           ELEMDESC    *elem = fdesc->lprgelemdescParam+i;\r
-           BOOL        isdeserialized = FALSE;\r
-\r
-           if (relaydeb) {\r
-               if (i) TRACE_(olerelay)(",");\r
-               if (i+1<nrofnames && names[i+1]) TRACE_(olerelay)("%s=",relaystr(names[i+1]));\r
-           }\r
-           /* No need to marshal other data than FOUT I think */\r
-           if (!(elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT)) {\r
-               xargs += _argsize(elem->tdesc.vt);\r
-               if (relaydeb) TRACE_(olerelay)("[in]");\r
-               continue;\r
-           }\r
-           if (((i+1)<nrofnames) && !IsBadStringPtrW(names[i+1],1)) {\r
-               /* If the parameter is 'riid', we use it as interface IID\r
-                * for a later ppvObject serialization.\r
-                */\r
-               buf.thisisiid = !lstrcmpW(names[i+1],riidW);\r
-\r
-               /* deserialize DISPPARAM */\r
-               if (!lstrcmpW(names[i+1],pdispparamsW)) {\r
-                   hres = deserialize_DISPPARAM_ptr(\r
-                       tpinfo->tinfo,\r
-                       elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT,\r
-                       relaydeb,\r
-                       FALSE,\r
-                       &(elem->tdesc),\r
-                       xargs,\r
-                       &buf\r
-                   );\r
-                   if (hres) {\r
-                       ERR("Failed to deserialize DISPPARAM*, hres %lx\n",hres);\r
-                       break;\r
-                   }\r
-                   isdeserialized = TRUE;\r
-               }\r
-               if (!lstrcmpW(names[i+1],ppvObjectW)) {\r
-                   hres = deserialize_LPVOID_ptr(\r
-                       tpinfo->tinfo,\r
-                       elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT,\r
-                       relaydeb,\r
-                       FALSE,\r
-                       &elem->tdesc,\r
-                       xargs,\r
-                       &buf\r
-                   );\r
-                   if (hres == S_OK)\r
-                       isdeserialized = TRUE;\r
+       goto after_deserialize;\r
+    }\r
+\r
+    /* generic deserializer using typelib description */\r
+    xargs = args;\r
+    status = S_OK;\r
+    for (i=0;i<fdesc->cParams;i++) {\r
+       ELEMDESC        *elem = fdesc->lprgelemdescParam+i;\r
+       BOOL    isdeserialized = FALSE;\r
+\r
+       if (relaydeb) {\r
+           if (i) TRACE_(olerelay)(",");\r
+           if (i+1<nrofnames && names[i+1]) TRACE_(olerelay)("%s=",relaystr(names[i+1]));\r
+       }\r
+       /* No need to marshal other data than FOUT and any VT_PTR */\r
+       if (!(elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT) && (elem->tdesc.vt != VT_PTR)) {\r
+           xargs += _argsize(elem->tdesc.vt);\r
+           if (relaydeb) TRACE_(olerelay)("[in]");\r
+           continue;\r
+       }\r
+       if (((i+1)<nrofnames) && !IsBadStringPtrW(names[i+1],1)) {\r
+           /* If the parameter is 'riid', we use it as interface IID\r
+            * for a later ppvObject serialization.\r
+            */\r
+           buf.thisisiid = !lstrcmpW(names[i+1],riidW);\r
+\r
+           /* deserialize DISPPARAM */\r
+           if (!lstrcmpW(names[i+1],pdispparamsW)) {\r
+               hres = deserialize_DISPPARAM_ptr(\r
+                   tpinfo->tinfo,\r
+                   elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT,\r
+                   relaydeb,\r
+                   FALSE,\r
+                   &(elem->tdesc),\r
+                   xargs,\r
+                   &buf\r
+               );\r
+               if (hres) {\r
+                   ERR("Failed to deserialize DISPPARAM*, hres %lx\n",hres);\r
+                   break;\r
                }\r
+               isdeserialized = TRUE;\r
            }\r
-           if (!isdeserialized)\r
-               hres = deserialize_param(\r
+           if (!lstrcmpW(names[i+1],ppvObjectW)) {\r
+               hres = deserialize_LPVOID_ptr(\r
                    tpinfo->tinfo,\r
                    elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT,\r
                    relaydeb,\r
                    FALSE,\r
-                   &(elem->tdesc),\r
+                   &elem->tdesc,\r
                    xargs,\r
                    &buf\r
                );\r
-           if (hres) {\r
-               ERR("Failed to unmarshall param, hres %lx\n",hres);\r
-               status = hres;\r
-               break;\r
+               if (hres == S_OK)\r
+                   isdeserialized = TRUE;\r
            }\r
-           xargs += _argsize(elem->tdesc.vt);\r
        }\r
+       if (!isdeserialized)\r
+           hres = deserialize_param(\r
+               tpinfo->tinfo,\r
+               elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT,\r
+               relaydeb,\r
+               FALSE,\r
+               &(elem->tdesc),\r
+               xargs,\r
+               &buf\r
+           );\r
+       if (hres) {\r
+           ERR("Failed to unmarshall param, hres %lx\n",hres);\r
+           status = hres;\r
+           break;\r
+       }\r
+       xargs += _argsize(elem->tdesc.vt);\r
     }\r
-    if (relaydeb) TRACE_(olerelay)(")\n");\r
-    HeapFree(GetProcessHeap(),0,buf.base);\r
+after_deserialize:\r
+    hres = xbuf_get(&buf, (LPBYTE)&remoteresult, sizeof(DWORD));\r
+    if (hres != S_OK)\r
+       return hres;\r
+    if (relaydeb) TRACE_(olerelay)(") = %08lx\n", remoteresult);\r
 \r
+    if (status != S_OK) /* OLE/COM internal error */\r
+       return status;\r
+\r
+    HeapFree(GetProcessHeap(),0,buf.base);\r
     LeaveCriticalSection(&tpinfo->crit);\r
+    return remoteresult;\r
+}\r
+\r
+HRESULT WINAPI ProxyIUnknown_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)\r
+{\r
+    TMProxyImpl *proxy = (TMProxyImpl *)iface;\r
+\r
+    TRACE("(%s, %p)\n", debugstr_guid(riid), ppv);\r
 \r
-    return status;\r
+    if (proxy->outerunknown)\r
+        return IUnknown_QueryInterface(proxy->outerunknown, riid, ppv);\r
+\r
+    FIXME("No interface\n");\r
+    return E_NOINTERFACE;\r
+}\r
+\r
+ULONG WINAPI ProxyIUnknown_AddRef(IUnknown *iface)\r
+{\r
+    TMProxyImpl *proxy = (TMProxyImpl *)iface;\r
+\r
+    TRACE("\n");\r
+\r
+    if (proxy->outerunknown)\r
+        return IUnknown_AddRef(proxy->outerunknown);\r
+\r
+    return 2; /* FIXME */\r
+}\r
+\r
+ULONG WINAPI ProxyIUnknown_Release(IUnknown *iface)\r
+{\r
+    TMProxyImpl *proxy = (TMProxyImpl *)iface;\r
+\r
+    TRACE("\n");\r
+\r
+    if (proxy->outerunknown)\r
+        return IUnknown_Release(proxy->outerunknown);\r
+\r
+    return 1; /* FIXME */\r
 }\r
 \r
 static HRESULT WINAPI\r
@@ -1449,6 +1814,7 @@ PSFacBuf_CreateProxy(
 \r
     assert(sizeof(TMAsmProxy) == 12);\r
 \r
+    proxy->outerunknown = pUnkOuter;\r
     proxy->asmstubs = VirtualAlloc(NULL, sizeof(TMAsmProxy) * nroffuncs, MEM_COMMIT, PAGE_EXECUTE_READWRITE);\r
     if (!proxy->asmstubs) {\r
         ERR("Could not commit pages for proxy thunks\n");\r
@@ -1460,17 +1826,22 @@ PSFacBuf_CreateProxy(
 \r
     proxy->lpvtbl = HeapAlloc(GetProcessHeap(),0,sizeof(LPBYTE)*nroffuncs);\r
     for (i=0;i<nroffuncs;i++) {\r
-       int             nrofargs;\r
        TMAsmProxy      *xasm = proxy->asmstubs+i;\r
 \r
-       /* nrofargs without This */\r
        switch (i) {\r
-       case 0: nrofargs = 2;\r
+       case 0:\r
+               proxy->lpvtbl[i] = ProxyIUnknown_QueryInterface;\r
+               break;\r
+       case 1:\r
+               proxy->lpvtbl[i] = ProxyIUnknown_AddRef;\r
                break;\r
-       case 1: case 2: nrofargs = 0;\r
+       case 2:\r
+               proxy->lpvtbl[i] = ProxyIUnknown_Release;\r
                break;\r
        default: {\r
                int j;\r
+               /* nrofargs without This */\r
+               int nrofargs;\r
                hres = _get_funcdesc(tinfo,i,&fdesc,NULL,NULL);\r
                if (hres) {\r
                    ERR("GetFuncDesc %lx should not fail here.\n",hres);\r
@@ -1485,9 +1856,6 @@ PSFacBuf_CreateProxy(
                    ERR("calling convention is not stdcall????\n");\r
                    return E_FAIL;\r
                }\r
-               break;\r
-           }\r
-       }\r
 /* popl %eax   -       return ptr\r
  * pushl <nr>\r
  * pushl %eax\r
@@ -1497,16 +1865,19 @@ PSFacBuf_CreateProxy(
  *\r
  * arg3 arg2 arg1 <method> <returnptr>\r
  */\r
-       xasm->popleax   = 0x58;\r
-       xasm->pushlval  = 0x6a;\r
-       xasm->nr        = i;\r
-       xasm->pushleax  = 0x50;\r
-       xasm->lcall     = 0xe8; /* relative jump */\r
-       xasm->xcall     = (DWORD)xCall;\r
-       xasm->xcall     -= (DWORD)&(xasm->lret);\r
-       xasm->lret      = 0xc2;\r
-       xasm->bytestopop= (nrofargs+2)*4; /* pop args, This, iMethod */\r
-       proxy->lpvtbl[i] = xasm;\r
+               xasm->popleax   = 0x58;\r
+               xasm->pushlval  = 0x6a;\r
+               xasm->nr        = i;\r
+               xasm->pushleax  = 0x50;\r
+               xasm->lcall     = 0xe8; /* relative jump */\r
+               xasm->xcall     = (DWORD)xCall;\r
+               xasm->xcall     -= (DWORD)&(xasm->lret);\r
+               xasm->lret      = 0xc2;\r
+               xasm->bytestopop= (nrofargs+2)*4; /* pop args, This, iMethod */\r
+               proxy->lpvtbl[i] = xasm;\r
+               break;\r
+           }\r
+       }\r
     }\r
     proxy->lpvtbl2     = &tmproxyvtable;\r
     /* 1 reference for the proxy and 1 for the object */\r
@@ -1603,6 +1974,8 @@ TMStubImpl_Invoke(
     marshal_state      buf;\r
     int                nrofnames;\r
     BSTR       names[10];\r
+    BSTR       fname = NULL,iname = NULL;\r
+    BOOL       is_idispatch_getidsofnames = 0;\r
 \r
     memset(&buf,0,sizeof(buf));\r
     buf.size   = xmsg->cbBuffer;\r
@@ -1622,11 +1995,18 @@ TMStubImpl_Invoke(
        xmsg->cbBuffer  = buf.size;\r
        return hres;\r
     }\r
-    hres = _get_funcdesc(This->tinfo,xmsg->iMethod,&fdesc,NULL,NULL);\r
+    hres = _get_funcdesc(This->tinfo,xmsg->iMethod,&fdesc,&iname,&fname);\r
     if (hres) {\r
        ERR("GetFuncDesc on method %ld failed with %lx\n",xmsg->iMethod,hres);\r
        return hres;\r
     }\r
+\r
+    if (iname && fname && !lstrcmpW(iname, IDispatchW) && !lstrcmpW(fname, GetIDsOfNamesW))\r
+       is_idispatch_getidsofnames = 1;\r
+\r
+    if (iname) SysFreeString (iname);\r
+    if (fname) SysFreeString (fname);\r
+\r
     /* Need them for hack below */\r
     memset(names,0,sizeof(names));\r
     ITypeInfo_GetNames(This->tinfo,fdesc->memid,names,sizeof(names)/sizeof(names[0]),&nrofnames);\r
@@ -1641,6 +2021,16 @@ TMStubImpl_Invoke(
     args = HeapAlloc(GetProcessHeap(),0,(nrofargs+1)*sizeof(DWORD));\r
     if (!args) return E_OUTOFMEMORY;\r
 \r
+    if (is_idispatch_getidsofnames) {\r
+       hres = deserialize_IDispatch_GetIDsOfNames(TRUE,FALSE,args+1,&buf);\r
+       if (hres != S_OK) {\r
+           FIXME("deserialize_IDispatch_GetIDsOfNames failed!\n");\r
+           return hres;\r
+       }\r
+       xargs = args+1+5;\r
+       goto afterdeserialize;\r
+    }\r
+\r
     /* Allocate all stuff used by call. */\r
     xargs = args+1;\r
     for (i=0;i<fdesc->cParams;i++) {\r
@@ -1673,7 +2063,7 @@ TMStubImpl_Invoke(
            if (!lstrcmpW(names[i+1],ppvObjectW)) {\r
                hres = deserialize_LPVOID_ptr(\r
                    This->tinfo,\r
-                   elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT,\r
+                   elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN,\r
                    FALSE,\r
                    TRUE,\r
                    &elem->tdesc,\r
@@ -1700,19 +2090,30 @@ TMStubImpl_Invoke(
            break;\r
        }\r
     }\r
+afterdeserialize:\r
     hres = IUnknown_QueryInterface(This->pUnk,&(This->iid),(LPVOID*)&(args[0]));\r
     if (hres) {\r
-       ERR("Does not support iface %s\n",debugstr_guid(&(This->iid)));\r
+       ERR("Does not support iface %s, returning %lx\n",debugstr_guid(&(This->iid)), hres);\r
        return hres;\r
     }\r
     res = _invoke(\r
-           (*((FARPROC**)args[0]))[fdesc->oVft/4],\r
-           fdesc->callconv,\r
-           (xargs-args),\r
-           args\r
+       (*((FARPROC**)args[0]))[fdesc->oVft/4],\r
+       fdesc->callconv,\r
+       (xargs-args),\r
+       args\r
     );\r
     IUnknown_Release((LPUNKNOWN)args[0]);\r
     buf.curoff = 0;\r
+\r
+    /* special IDispatch::GetIDsOfNames serializer */\r
+    if (is_idispatch_getidsofnames) {\r
+       hres = serialize_IDispatch_GetIDsOfNames(FALSE,FALSE,args+1,&buf);\r
+       if (hres != S_OK) {\r
+           FIXME("serialize of IDispatch::GetIDsOfNames failed!\n");\r
+           return hres;\r
+       }\r
+       goto afterserialize;\r
+    }\r
     xargs = args+1;\r
     for (i=0;i<fdesc->cParams;i++) {\r
        ELEMDESC        *elem = fdesc->lprgelemdescParam+i;\r
@@ -1767,11 +2168,16 @@ TMStubImpl_Invoke(
            break;\r
        }\r
     }\r
+afterserialize:\r
+    hres = xbuf_add (&buf, (LPBYTE)&res, sizeof(DWORD));\r
+    if (hres != S_OK)\r
+       return hres;\r
+   \r
     /* might need to use IRpcChannelBuffer_GetBuffer ? */\r
     xmsg->cbBuffer     = buf.curoff;\r
     xmsg->Buffer       = buf.base;\r
     HeapFree(GetProcessHeap(),0,args);\r
-    return res;\r
+    return S_OK;\r
 }\r
 \r
 static LPRPCSTUBBUFFER WINAPI\r
index c237dab..1b8361c 100644 (file)
@@ -1625,25 +1625,25 @@ MSFT_DoFuncs(TLBContext*     pcx,
      * member information is stored in a data structure at offset\r
      * indicated by the memoffset field of the typeinfo structure\r
      * There are several distinctive parts.\r
-     * the first part starts with a field that holds the total length\r
+     * The first part starts with a field that holds the total length\r
      * of this (first) part excluding this field. Then follow the records,\r
      * for each member there is one record.\r
      *\r
-     * First entry is always the length of the record (including this\r
+     * The first entry is always the length of the record (including this\r
      * length word).\r
-     * Rest of the record depends on the type of the member. If there is\r
-     * a field indicating the member type (function variable intereface etc)\r
+     * The rest of the record depends on the type of the member. If there is\r
+     * a field indicating the member type (function, variable, interface, etc)\r
      * I have not found it yet. At this time we depend on the information\r
      * in the type info and the usual order how things are stored.\r
      *\r
-     * Second follows an array sized nrMEM*sizeof(INT) with a memeber id\r
+     * Second follows an array sized nrMEM*sizeof(INT) with a member id\r
      * for each member;\r
      *\r
-     * Third is a equal sized array with file offsets to the name entry\r
+     * Third is an equal sized array with file offsets to the name entry\r
      * of each member.\r
      *\r
-     * Forth and last (?) part is an array with offsets to the records in the\r
-     * first part of this file segment.\r
+     * The fourth and last (?) part is an array with offsets to the records\r
+     * in the first part of this file segment.\r
      */\r
 \r
     int infolen, nameoffset, reclength, nrattributes, i;\r
@@ -4516,7 +4516,6 @@ _copy_arg(        ITypeInfo2 *tinfo, TYPEDESC *tdesc,
                DWORD *argpos, VARIANT *arg, VARTYPE vt\r
 ) {\r
     UINT arglen = _argsize(vt)*sizeof(DWORD);\r
-    VARTYPE    oldvt;\r
     VARIANT    va;\r
 \r
     if ((vt==VT_PTR) && tdesc && (tdesc->u.lptdesc->vt == VT_VARIANT)) {\r
@@ -4650,7 +4649,6 @@ _copy_arg(        ITypeInfo2 *tinfo, TYPEDESC *tdesc,
        return hres;\r
     }\r
 \r
-    oldvt = V_VT(arg);\r
     VariantInit(&va);\r
     if (VariantChangeType(&va,arg,0,vt)==S_OK) {\r
        memcpy(argpos,&V_I4(&va), arglen);\r
@@ -4687,7 +4685,7 @@ DispCallFunc(
        dump_Variant(prgpvarg[i]);\r
        argsize += _argsize(prgvt[i]);\r
     }\r
-    args = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);\r
+    args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);\r
     args[0] = (DWORD)pvInstance;      /* this is the fake IDispatch interface pointer */\r
     argspos = 1;\r
     for (i=0;i<cActuals;i++) {\r
@@ -4760,8 +4758,8 @@ static HRESULT WINAPI ITypeInfo_fnInvoke(
                }\r
            }\r
 \r
-           args = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs);\r
-           args2 = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs2);\r
+           args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs);\r
+           args2 = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs2);\r
 \r
            args[0] = (DWORD)pIUnk;\r
            argspos = 1; args2pos = 0;\r
index 0c0a385..0276b33 100644 (file)
@@ -169,7 +169,7 @@ typedef struct tagMSFT_ImpInfo {
 /* function description data */\r
 typedef struct {\r
 /*  INT   recsize;       record size including some xtra stuff */\r
-    INT   DataType;     /* data type of the memeber, eg return of function */\r
+    INT   DataType;     /* data type of the member, eg return of function */\r
     INT   Flags;        /* something to do with attribute flags (LOWORD) */\r
 #ifdef WORDS_BIGENDIAN\r
     INT16 funcdescsize; /* size of reconstituted FUNCDESC and related structs */\r
@@ -184,7 +184,7 @@ typedef struct {
                         /* bit 3 that parameter has default values */\r
                         /* calling convention (bits 4-7 ) */\r
                         /* bit 8 indicates that custom data is present */\r
-                        /* Invokation kind (bits 9-12 ) */\r
+                        /* Invocation kind (bits 9-12 ) */\r
                         /* function kind (eg virtual), bits 13-15  */\r
 #ifdef WORDS_BIGENDIAN\r
     INT16 nroargs;      /* nr of optional arguments */\r
index 43855ae..917d6bc 100644 (file)
@@ -3,6 +3,8 @@
  *\r
  * Copyright 1998 Jean-Claude Cote\r
  * Copyright 2003 Jon Griffiths\r
+ * Copyright 2005 Daniel Remenak\r
+ *\r
  * The alorithm for conversion from Julian days to day/month/year is based on\r
  * that devised by Henry Fliegel, as implemented in PostgreSQL, which is\r
  * Copyright 1994-7 Regents of the University of California\r
@@ -3008,11 +3010,13 @@ HRESULT WINAPI VarDiv(LPVARIANT left, LPVARIANT right, LPVARIANT result)
     }\r
     switch (resvt) {\r
     case VT_R8:\r
+       if (V_R8(&rv) == 0) return DISP_E_DIVBYZERO;\r
        V_VT(result) = resvt;\r
        V_R8(result) = V_R8(&lv) / V_R8(&rv);\r
        rc = S_OK;\r
        break;\r
     case VT_I4:\r
+       if (V_I4(&rv) == 0) return DISP_E_DIVBYZERO;\r
        V_VT(result) = resvt;\r
        V_I4(result) = V_I4(&lv) / V_I4(&rv);\r
        rc = S_OK;\r
@@ -4155,9 +4159,57 @@ HRESULT WINAPI VarRound(LPVARIANT pVarIn, int deci, LPVARIANT pVarOut)
     return hRet;\r
 }\r
 \r
+/**********************************************************************\r
+ *              VarIdiv [OLEAUT32.153]\r
+ *\r
+ * Converts input variants to integers and divides them. \r
+ *\r
+ * PARAMS\r
+ *  left     [I] Left hand variant\r
+ *  right    [I] Right hand variant\r
+ *  result   [O] Destination for quotient\r
+ *\r
+ * RETURNS\r
+ *  Success: S_OK.  result contains the quotient.\r
+ *  Failure: An HRESULT error code indicating the error.\r
+ *\r
+ * NOTES\r
+ *  If either expression is null, null is returned, as per MSDN\r
+ */\r
+HRESULT WINAPI VarIdiv(LPVARIANT left, LPVARIANT right, LPVARIANT result)\r
+{\r
+    VARIANT lv, rv;\r
+    HRESULT hr;\r
+    \r
+    VariantInit(&lv);\r
+    VariantInit(&rv);\r
+\r
+    if ((V_VT(left) == VT_NULL) || (V_VT(right) == VT_NULL)) {\r
+        hr = VariantChangeType(result, result, 0, VT_NULL);\r
+        if (FAILED(hr)) {\r
+            /* This should never happen */\r
+            FIXME("Failed to convert return value to VT_NULL.\n");\r
+            return hr;\r
+        }\r
+        return S_OK;\r
+    }\r
+\r
+    hr = VariantChangeType(&lv, left, 0, VT_I4);\r
+    if (FAILED(hr)) {\r
+       return hr;\r
+    }\r
+    hr = VariantChangeType(&rv, right, 0, VT_I4);\r
+    if (FAILED(hr)) {\r
+       return hr;\r
+    }\r
+\r
+    hr = VarDiv(&lv, &rv, result);\r
+    return hr;\r
+}\r
+\r
 \r
 /**********************************************************************\r
- *              VarMod [OLEAUT32.154]\r
+ *              VarMod [OLEAUT32.155]\r
  *\r
  * Perform the modulus operation of the right hand variant on the left\r
  *\r
index 8c03a5a..2e771e8 100644 (file)
@@ -3990,6 +3990,8 @@ HRESULT WINAPI VarDecFromI4(LONG lIn, DECIMAL* pDecOut)
   return S_OK;\r
 }\r
 \r
+#define LOCALE_EN_US           (MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT))\r
+\r
 /************************************************************************\r
  * VarDecFromR4 (OLEAUT32.193)\r
  *\r
@@ -4007,7 +4009,7 @@ HRESULT WINAPI VarDecFromR4(FLOAT fltIn, DECIMAL* pDecOut)
   WCHAR buff[256];\r
 \r
   sprintfW( buff, szFloatFormatW, fltIn );\r
-  return _VarDecFromStr(buff, LOCALE_SYSTEM_DEFAULT, 0, pDecOut);\r
+  return _VarDecFromStr(buff, LOCALE_EN_US, 0, pDecOut);\r
 }\r
 \r
 /************************************************************************\r
@@ -4027,7 +4029,7 @@ HRESULT WINAPI VarDecFromR8(double dblIn, DECIMAL* pDecOut)
   WCHAR buff[256];\r
 \r
   sprintfW( buff, szDoubleFormatW, dblIn );\r
-  return _VarDecFromStr(buff, LOCALE_USER_DEFAULT, 0, pDecOut);\r
+  return _VarDecFromStr(buff, LOCALE_EN_US, 0, pDecOut);\r
 }\r
 \r
 /************************************************************************\r