Sync to Wine-20050419:
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().
Modified: trunk/reactos/lib/oleaut32/oleaut.c
Modified: trunk/reactos/lib/oleaut32/oleaut32.spec
Modified: trunk/reactos/lib/oleaut32/olepicture.c
Modified: trunk/reactos/lib/oleaut32/safearray.c
Modified: trunk/reactos/lib/oleaut32/tmarshal.c
Modified: trunk/reactos/lib/oleaut32/typelib.c
Modified: trunk/reactos/lib/oleaut32/typelib.h
Modified: trunk/reactos/lib/oleaut32/variant.c
Modified: trunk/reactos/lib/oleaut32/vartype.c

Modified: trunk/reactos/lib/oleaut32/oleaut.c
--- trunk/reactos/lib/oleaut32/oleaut.c	2005-05-05 18:16:09 UTC (rev 15010)
+++ trunk/reactos/lib/oleaut32/oleaut.c	2005-05-05 18:29:41 UTC (rev 15011)
@@ -235,9 +235,8 @@
      * 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 @@
      * 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.

Modified: trunk/reactos/lib/oleaut32/oleaut32.spec
--- trunk/reactos/lib/oleaut32/oleaut32.spec	2005-05-05 18:16:09 UTC (rev 15010)
+++ trunk/reactos/lib/oleaut32/oleaut32.spec	2005-05-05 18:29:41 UTC (rev 15011)
@@ -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)

Modified: trunk/reactos/lib/oleaut32/olepicture.c
--- trunk/reactos/lib/oleaut32/olepicture.c	2005-05-05 18:16:09 UTC (rev 15010)
+++ trunk/reactos/lib/oleaut32/olepicture.c	2005-05-05 18:29:41 UTC (rev 15011)
@@ -185,6 +185,36 @@
   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 @@
 	break;
 
       case PICTYPE_ICON:
+        OLEPictureImpl_SetIcon(newObject);
+        break;
       case PICTYPE_ENHMETAFILE:
       default:
 	FIXME("Unsupported type %d\n", pictDesc->picType);
@@ -1071,7 +1103,7 @@
 	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 @@
 
 	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 @@
     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 @@
 
     /* 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 @@
         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 @@
 		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 @@
 */
 			/* 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 @@
 			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));

Modified: trunk/reactos/lib/oleaut32/safearray.c
--- trunk/reactos/lib/oleaut32/safearray.c	2005-05-05 18:16:09 UTC (rev 15010)
+++ trunk/reactos/lib/oleaut32/safearray.c	2005-05-05 18:29:41 UTC (rev 15011)
@@ -647,7 +647,7 @@
 /************************************************************************
  *		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 @@
 /************************************************************************
  *		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

Modified: trunk/reactos/lib/oleaut32/tmarshal.c
--- trunk/reactos/lib/oleaut32/tmarshal.c	2005-05-05 18:16:09 UTC (rev 15010)
+++ trunk/reactos/lib/oleaut32/tmarshal.c	2005-05-05 18:29:41 UTC (rev 15011)
@@ -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 @@
     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 @@
     IRpcChannelBuffer*			chanbuf;
     IID					iid;
     CRITICAL_SECTION	crit;
+    IUnknown				*outerunknown;
 } TMProxyImpl;
 
 static HRESULT WINAPI
@@ -499,17 +509,36 @@
 	return S_OK;
     case VT_BOOL:
     case VT_ERROR:
-    case VT_UI4:
     case VT_UINT:
     case VT_I4:
     case VT_R4:
+    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)("%lx",*arg);
+	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 @@
 	if (debugout) TRACE_(olerelay)(")");
 	return hres;
     }
+    case VT_BSTR|VT_BYREF: {
+	if (debugout) TRACE_(olerelay)("[byref]'%s'", *(BSTR*)*arg ? relaystr(*((BSTR*)*arg)) : "<bstr NULL>");
+        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)("<bstr NULL>");
 	}
@@ -556,12 +609,12 @@
 	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 @@
 	    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;i<arrsize;i++) {
 	    hres = serialize_param(tinfo, writeit, debugout, dealloc, &adesc->tdescElem, (DWORD*)((LPBYTE)arg+i*_xsize(&adesc->tdescElem)), buf);
@@ -676,7 +730,169 @@
     }
 }
 
+/* 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<cNames;i++) {
+	    DWORD len = 2*(lstrlenW(rgszNames[i])+1);
+
+	    if (debugout) TRACE_(olerelay)("%s,",relaystr(rgszNames[i]));
+	    hres = xbuf_add(buf, (LPBYTE)&len, sizeof(DWORD));
+	    if (hres) {
+		FIXME("serialize of len failed.\n");
+		return hres;
+	    }
+	    hres = xbuf_add(buf, (LPBYTE)rgszNames[i], len);
+	    if (hres) {
+		FIXME("serialize of rgszNames[i] failed.\n");
+		return hres;
+	    }
+        }
+	if (debugout) TRACE_(olerelay)("],lcid=%04lx)",args[3]);
+	hres = xbuf_add(buf, (LPBYTE)&args[3], sizeof(DWORD));
+	if (hres) {
+	    FIXME("serialize of lcid failed.\n");
+	    return hres;
+	}
+    } else {
+	DISPID *rgDispId = (DISPID*)args[4];
+
+	hres = xbuf_add(buf, (LPBYTE)rgDispId, sizeof(DISPID) * cNames);
+	if (hres) {
+	    FIXME("serialize of rgDispId failed.\n");
+	    return hres;
+	}
+	if (debugout) {
+	    TRACE_(olerelay)("riid=[in],rgszNames=[in],cNames=[in],rgDispId=[");
+	    for (i=0;i<cNames;i++)
+		TRACE_(olerelay)("%08lx,",rgDispId[i]);
+	    TRACE_(olerelay)("])");
+	}
+	HeapFree(GetProcessHeap(),0,(IID*)args[0]);
+	rgszNames = (LPOLESTR*)args[1];
+	for (i=0;i<cNames;i++) HeapFree(GetProcessHeap(),0,rgszNames[i]);
+	HeapFree(GetProcessHeap(),0,rgszNames);
+	HeapFree(GetProcessHeap(),0,rgDispId);
+    }
+    return S_OK;
+}
+
+static HRESULT
+deserialize_IDispatch_GetIDsOfNames(
+    BOOL		inputparams,
+    BOOL		debugout,
+    DWORD		*args,
+    marshal_state	*buf)
+{
+    HRESULT	hres;
+    DWORD	cNames;
+    LPOLESTR    *rgszNames;
+    int		i;
+
+    if (inputparams) {
+	args[0] = (DWORD)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IID));
+	if (!args[0]) return E_FAIL;
+	hres = xbuf_get(buf, (LPBYTE)args[0], sizeof(IID));
+	if (hres) {
+	    FIXME("deserialize of IID failed.\n");
+	    return hres;
+	}
+	if (debugout) TRACE_(olerelay)("riid=%s,",debugstr_guid((REFIID)args[0]));
+
+	hres = xbuf_get(buf, (LPBYTE)&cNames, sizeof(DWORD));
+	if (hres) {
+	    FIXME("deserialize of cNames failed.\n");
+	    return hres;
+	}
+        args[2] = cNames;
+	if (debugout) TRACE_(olerelay)("cNames=%ld,",cNames);
+	if (debugout) TRACE_(olerelay)("rgszNames=[");
+        rgszNames = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(LPOLESTR) * cNames);
+	if (!rgszNames) return E_FAIL;
+	args[1] = (DWORD)rgszNames;
+        for (i=0;i<cNames;i++) {
+	    DWORD len;
+
+	    hres = xbuf_get(buf, (LPBYTE)&len, sizeof(DWORD));
+	    if (hres) {
+		FIXME("serialize of len failed.\n");
+		return hres;
+	    }
+	    rgszNames[i] = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
+	    if (!rgszNames[i]) {
+		FIXME("heapalloc of %ld bytes failed\n", len);
+		return E_FAIL;
+	    }
+	    hres = xbuf_get(buf, (LPBYTE)rgszNames[i], len);
+	    if (hres) {
+		FIXME("serialize of rgszNames[i] failed.\n");
+		return hres;
+	    }
+	    if (debugout) TRACE_(olerelay)("%s,",relaystr(rgszNames[i]));
+        }
+	hres = xbuf_get(buf, (LPBYTE)&args[3], sizeof(DWORD));
+	if (hres) {
+	    FIXME("deserialize of lcid failed.\n");
+	    return hres;
+	}
+	if (debugout) TRACE_(olerelay)("],lcid=%04lx,rgDispId=[out])",args[3]);
+        args[4] = (DWORD)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DISPID) * cNames);
+    } else {
+	hres = xbuf_get(buf, (LPBYTE)args[4], sizeof(DISPID) * args[2]);
+	if (hres) {
+	    FIXME("serialize of rgDispId failed.\n");
+	    return hres;
+	}
+	if (debugout) {
+	    TRACE_(olerelay)("dispid=[");
+	    for (i=0;i<args[2];i++)
+		TRACE_(olerelay)("%08lx,",((DISPID*)args[4])[i]);
+	    TRACE_(olerelay)("])");
+	}
+    }
+    return S_OK;
+}
+
+static HRESULT
 serialize_LPVOID_ptr(
     ITypeInfo		*tinfo,
     BOOL		writeit,
@@ -696,13 +912,13 @@
 	FIXME("ppvObject not expressed as VT_PTR -> 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)("<lpvoid NULL>");
 	return S_OK;
     }
@@ -849,15 +1065,79 @@
 	    }
 	}
         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)("<bstr NULL>");
+		} 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 @@
 	}
 	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 @@
 	    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 @@
 		case TKIND_RECORD: {
 		    int i;
 
+		    if (alloc)
+			*arg = (DWORD)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,tattr->cbSizeInstance);
+
 		    if (debugout) TRACE_(olerelay)("{");
 		    for (i=0;i<tattr->cVars;i++) {
 			VARDESC *vdesc;
@@ -1056,8 +1339,10 @@
     }
     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 @@
     BSTR		fname,iname;
     BSTR		names[10];
     int			nrofnames;
+    int			is_idispatch_getidsofnames = 0;
+    DWORD		remoteresult = 0;
 
     EnterCriticalSection(&tpinfo->crit);
 
@@ -1235,9 +1522,35 @@
 	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,42 @@
     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;i<fdesc->cParams;i++) {
-	    ELEMDESC	*elem = fdesc->lprgelemdescParam+i;
-	    BOOL	isserialized = FALSE;
-	    if (relaydeb) {
-		if (i) TRACE_(olerelay)(",");
-		if (i+1<nrofnames && names[i+1])
-		    TRACE_(olerelay)("%s=",relaystr(names[i+1]));
-	    }
-	    /* No need to marshal other data than FIN */
-	    if (!(elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN)) {
-		xargs+=_argsize(elem->tdesc.vt);
-		if (relaydeb) TRACE_(olerelay)("[out]");
-		continue;
-	    }
-	    if (((i+1)<nrofnames) && !IsBadStringPtrW(names[i+1],1)) {
-		/* If the parameter is 'riid', we use it as interface IID
-		 * for a later ppvObject serialization.
-		 */
-		buf.thisisiid = !lstrcmpW(names[i+1],riidW);
+    xargs = args;
+    for (i=0;i<fdesc->cParams;i++) {
+	ELEMDESC	*elem = fdesc->lprgelemdescParam+i;
+	BOOL	isserialized = FALSE;
+	if (relaydeb) {
+	    if (i) TRACE_(olerelay)(",");
+	    if (i+1<nrofnames && names[i+1])
+		TRACE_(olerelay)("%s=",relaystr(names[i+1]));
+	}
+	/* No need to marshal other data than FIN and any VT_PTR. */
+	if (!(elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN) && (elem->tdesc.vt != VT_PTR)) {
+	    xargs+=_argsize(elem->tdesc.vt);
+	    if (relaydeb) TRACE_(olerelay)("[out]");
+	    continue;
+	}
+	if (((i+1)<nrofnames) && !IsBadStringPtrW(names[i+1],1)) {
+	    /* If the parameter is 'riid', we use it as interface IID
+	     * for a later ppvObject serialization.
+	     */
+	    buf.thisisiid = !lstrcmpW(names[i+1],riidW);
 
-		/* DISPPARAMS* needs special serializer */
-		if (!lstrcmpW(names[i+1],pdispparamsW)) {
-		    hres = serialize_DISPPARAM_ptr(
-			tpinfo->tinfo,
-			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;
-		}
+	    /* DISPPARAMS* needs special serializer */
+	    if (!lstrcmpW(names[i+1],pdispparamsW)) {
+		hres = serialize_DISPPARAM_ptr(
+		    tpinfo->tinfo,
+		    elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN,
+		    relaydeb,
+		    FALSE,
+		    &elem->tdesc,
+		    xargs,
+		    &buf
+		);
+		isserialized = TRUE;
 	    }
-	    if (!isserialized)
-		hres = serialize_param(
+	    if (!lstrcmpW(names[i+1],ppvObjectW)) {
+		hres = serialize_LPVOID_ptr(
 		    tpinfo->tinfo,
 		    elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN,
 		    relaydeb,
@@ -1309,15 +1602,30 @@
 		    xargs,
 		    &buf
 		);
-
-	    if (hres) {
-		ERR("Failed to serialize param, hres %lx\n",hres);
-		break;
+		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 @@
 	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,88 +1652,145 @@
     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;i<fdesc->cParams;i++) {
-	    ELEMDESC	*elem = fdesc->lprgelemdescParam+i;
-	    BOOL	isdeserialized = FALSE;
+	goto after_deserialize;
+    }
 
-	    if (relaydeb) {
-		if (i) TRACE_(olerelay)(",");
-		if (i+1<nrofnames && names[i+1]) TRACE_(olerelay)("%s=",relaystr(names[i+1]));
-	    }
-	    /* No need to marshal other data than FOUT I think */
-	    if (!(elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT)) {
-		xargs += _argsize(elem->tdesc.vt);
-		if (relaydeb) TRACE_(olerelay)("[in]");
-		continue;
-	    }
-	    if (((i+1)<nrofnames) && !IsBadStringPtrW(names[i+1],1)) {
-		/* If the parameter is 'riid', we use it as interface IID
-		 * for a later ppvObject serialization.
-		 */
-		buf.thisisiid = !lstrcmpW(names[i+1],riidW);
+    /* generic deserializer using typelib description */
+    xargs = args;
+    status = S_OK;
+    for (i=0;i<fdesc->cParams;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 (relaydeb) {
+	    if (i) TRACE_(olerelay)(",");
+	    if (i+1<nrofnames && names[i+1]) TRACE_(olerelay)("%s=",relaystr(names[i+1]));
+	}
+	/* No need to marshal other data than FOUT and any VT_PTR */
+	if (!(elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT) && (elem->tdesc.vt != VT_PTR)) {
+	    xargs += _argsize(elem->tdesc.vt);
+	    if (relaydeb) TRACE_(olerelay)("[in]");
+	    continue;
+	}
+	if (((i+1)<nrofnames) && !IsBadStringPtrW(names[i+1],1)) {
+	    /* If the parameter is 'riid', we use it as interface IID
+	     * for a later ppvObject serialization.
+	     */
+	    buf.thisisiid = !lstrcmpW(names[i+1],riidW);
+
+	    /* 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;
 		}
-		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;
-		}
+		isdeserialized = TRUE;
 	    }
-	    if (!isdeserialized)
-		hres = deserialize_param(
+	    if (!lstrcmpW(names[i+1],ppvObjectW)) {
+		hres = deserialize_LPVOID_ptr(
 		    tpinfo->tinfo,
 		    elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT,
 		    relaydeb,
 		    FALSE,
-		    &(elem->tdesc),
+		    &elem->tdesc,
 		    xargs,
 		    &buf
 		);
-	    if (hres) {
-		ERR("Failed to unmarshall param, hres %lx\n",hres);
-		status = hres;
-		break;
+		if (hres == S_OK)
+		    isdeserialized = TRUE;
[truncated at 1000 lines; 474 more skipped]