Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1 | /* |
| 2 | * TYPELIB Marshaler |
| 3 | * |
Marcus Meissner | 4107986 | 2005-03-29 13:06:44 +0000 | [diff] [blame] | 4 | * Copyright 2002,2005 Marcus Meissner |
Alexandre Julliard | 0799c1a | 2002-03-09 23:29:33 +0000 | [diff] [blame] | 5 | * |
Mike Hearn | d440ca4 | 2004-06-17 23:03:26 +0000 | [diff] [blame] | 6 | * The olerelay debug channel allows you to see calls marshalled by |
| 7 | * the typelib marshaller. It is not a generic COM relaying system. |
| 8 | * |
Alexandre Julliard | 0799c1a | 2002-03-09 23:29:33 +0000 | [diff] [blame] | 9 | * This library is free software; you can redistribute it and/or |
| 10 | * modify it under the terms of the GNU Lesser General Public |
| 11 | * License as published by the Free Software Foundation; either |
| 12 | * version 2.1 of the License, or (at your option) any later version. |
| 13 | * |
| 14 | * This library is distributed in the hope that it will be useful, |
| 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 17 | * Lesser General Public License for more details. |
| 18 | * |
| 19 | * You should have received a copy of the GNU Lesser General Public |
| 20 | * License along with this library; if not, write to the Free Software |
| 21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 22 | */ |
| 23 | |
| 24 | #include "config.h" |
| 25 | |
| 26 | #include <assert.h> |
| 27 | #include <stdlib.h> |
| 28 | #include <string.h> |
Alexandre Julliard | e37c6e1 | 2003-09-05 23:08:26 +0000 | [diff] [blame] | 29 | #include <stdarg.h> |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 30 | #include <stdio.h> |
| 31 | #include <ctype.h> |
| 32 | |
Francois Gouget | 486d020 | 2004-10-07 03:06:48 +0000 | [diff] [blame] | 33 | #define COBJMACROS |
Dimitrie O. Paun | 297f3d8 | 2003-01-07 20:36:20 +0000 | [diff] [blame] | 34 | #define NONAMELESSUNION |
| 35 | #define NONAMELESSSTRUCT |
Francois Gouget | 486d020 | 2004-10-07 03:06:48 +0000 | [diff] [blame] | 36 | |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 37 | #include "winerror.h" |
Alexandre Julliard | e37c6e1 | 2003-09-05 23:08:26 +0000 | [diff] [blame] | 38 | #include "windef.h" |
Alexandre Julliard | 864ca06 | 2003-08-20 18:22:31 +0000 | [diff] [blame] | 39 | #include "winbase.h" |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 40 | #include "winnls.h" |
| 41 | #include "winreg.h" |
| 42 | #include "winuser.h" |
| 43 | |
| 44 | #include "ole2.h" |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 45 | #include "typelib.h" |
Alexandre Julliard | 0799c1a | 2002-03-09 23:29:33 +0000 | [diff] [blame] | 46 | #include "wine/debug.h" |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 47 | |
| 48 | static const WCHAR riidW[5] = {'r','i','i','d',0}; |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 49 | static const WCHAR pdispparamsW[] = {'p','d','i','s','p','p','a','r','a','m','s',0}; |
| 50 | static const WCHAR ppvObjectW[] = {'p','p','v','O','b','j','e','c','t',0}; |
Marcus Meissner | e6260a3 | 2005-03-27 17:51:59 +0000 | [diff] [blame] | 51 | static const WCHAR IDispatchW[] = { 'I','D','i','s','p','a','t','c','h',0}; |
| 52 | static const WCHAR GetIDsOfNamesW[] = { 'G','e','t','I','D','s','O','f','N','a','m','e','s',0}; |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 53 | |
Alexandre Julliard | 0799c1a | 2002-03-09 23:29:33 +0000 | [diff] [blame] | 54 | WINE_DEFAULT_DEBUG_CHANNEL(ole); |
| 55 | WINE_DECLARE_DEBUG_CHANNEL(olerelay); |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 56 | |
Alexandre Julliard | 936198c | 2004-08-13 00:44:22 +0000 | [diff] [blame] | 57 | #define ICOM_THIS_MULTI(impl,field,iface) impl* const This=(impl*)((char*)(iface) - offsetof(impl,field)) |
| 58 | |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 59 | typedef struct _marshal_state { |
| 60 | LPBYTE base; |
| 61 | int size; |
| 62 | int curoff; |
| 63 | |
| 64 | BOOL thisisiid; |
| 65 | IID iid; /* HACK: for VT_VOID */ |
| 66 | } marshal_state; |
| 67 | |
Mike Hearn | d440ca4 | 2004-06-17 23:03:26 +0000 | [diff] [blame] | 68 | /* used in the olerelay code to avoid having the L"" stuff added by debugstr_w */ |
| 69 | static char *relaystr(WCHAR *in) { |
| 70 | char *tmp = (char *)debugstr_w(in); |
| 71 | tmp += 2; |
| 72 | tmp[strlen(tmp)-1] = '\0'; |
| 73 | return tmp; |
| 74 | } |
| 75 | |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 76 | static HRESULT |
| 77 | xbuf_add(marshal_state *buf, LPBYTE stuff, DWORD size) { |
| 78 | while (buf->size - buf->curoff < size) { |
| 79 | if (buf->base) { |
| 80 | buf->size += 100; |
| 81 | buf->base = HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,buf->base,buf->size); |
| 82 | if (!buf->base) |
| 83 | return E_OUTOFMEMORY; |
| 84 | } else { |
| 85 | buf->base = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,32); |
| 86 | buf->size = 32; |
| 87 | if (!buf->base) |
| 88 | return E_OUTOFMEMORY; |
| 89 | } |
| 90 | } |
| 91 | memcpy(buf->base+buf->curoff,stuff,size); |
| 92 | buf->curoff += size; |
| 93 | return S_OK; |
| 94 | } |
| 95 | |
| 96 | static HRESULT |
| 97 | xbuf_get(marshal_state *buf, LPBYTE stuff, DWORD size) { |
| 98 | if (buf->size < buf->curoff+size) return E_FAIL; |
| 99 | memcpy(stuff,buf->base+buf->curoff,size); |
| 100 | buf->curoff += size; |
| 101 | return S_OK; |
| 102 | } |
| 103 | |
| 104 | static HRESULT |
| 105 | xbuf_skip(marshal_state *buf, DWORD size) { |
| 106 | if (buf->size < buf->curoff+size) return E_FAIL; |
| 107 | buf->curoff += size; |
| 108 | return S_OK; |
| 109 | } |
| 110 | |
| 111 | static HRESULT |
| 112 | _unmarshal_interface(marshal_state *buf, REFIID riid, LPUNKNOWN *pUnk) { |
| 113 | IStream *pStm; |
| 114 | ULARGE_INTEGER newpos; |
| 115 | LARGE_INTEGER seekto; |
| 116 | ULONG res; |
| 117 | HRESULT hres; |
| 118 | DWORD xsize; |
| 119 | |
| 120 | TRACE("...%s...\n",debugstr_guid(riid)); |
Mike Hearn | 64eac75 | 2005-01-27 11:11:32 +0000 | [diff] [blame] | 121 | |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 122 | *pUnk = NULL; |
| 123 | hres = xbuf_get(buf,(LPBYTE)&xsize,sizeof(xsize)); |
Mike Hearn | 64eac75 | 2005-01-27 11:11:32 +0000 | [diff] [blame] | 124 | if (hres) { |
| 125 | ERR("xbuf_get failed\n"); |
| 126 | return hres; |
| 127 | } |
| 128 | |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 129 | if (xsize == 0) return S_OK; |
Mike Hearn | 64eac75 | 2005-01-27 11:11:32 +0000 | [diff] [blame] | 130 | |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 131 | hres = CreateStreamOnHGlobal(0,TRUE,&pStm); |
| 132 | if (hres) { |
Mike Hearn | 64eac75 | 2005-01-27 11:11:32 +0000 | [diff] [blame] | 133 | ERR("Stream create failed %lx\n",hres); |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 134 | return hres; |
| 135 | } |
Mike Hearn | 64eac75 | 2005-01-27 11:11:32 +0000 | [diff] [blame] | 136 | |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 137 | hres = IStream_Write(pStm,buf->base+buf->curoff,xsize,&res); |
Mike Hearn | 64eac75 | 2005-01-27 11:11:32 +0000 | [diff] [blame] | 138 | if (hres) { |
| 139 | ERR("stream write %lx\n",hres); |
| 140 | return hres; |
| 141 | } |
| 142 | |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 143 | memset(&seekto,0,sizeof(seekto)); |
| 144 | hres = IStream_Seek(pStm,seekto,SEEK_SET,&newpos); |
Mike Hearn | 64eac75 | 2005-01-27 11:11:32 +0000 | [diff] [blame] | 145 | if (hres) { |
| 146 | ERR("Failed Seek %lx\n",hres); |
| 147 | return hres; |
| 148 | } |
| 149 | |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 150 | hres = CoUnmarshalInterface(pStm,riid,(LPVOID*)pUnk); |
| 151 | if (hres) { |
Mike Hearn | 64eac75 | 2005-01-27 11:11:32 +0000 | [diff] [blame] | 152 | ERR("Unmarshalling interface %s failed with %lx\n",debugstr_guid(riid),hres); |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 153 | return hres; |
| 154 | } |
Mike Hearn | 64eac75 | 2005-01-27 11:11:32 +0000 | [diff] [blame] | 155 | |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 156 | IStream_Release(pStm); |
| 157 | return xbuf_skip(buf,xsize); |
| 158 | } |
| 159 | |
| 160 | static HRESULT |
| 161 | _marshal_interface(marshal_state *buf, REFIID riid, LPUNKNOWN pUnk) { |
Mike Hearn | 64eac75 | 2005-01-27 11:11:32 +0000 | [diff] [blame] | 162 | LPBYTE tempbuf = NULL; |
| 163 | IStream *pStm = NULL; |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 164 | STATSTG ststg; |
| 165 | ULARGE_INTEGER newpos; |
| 166 | LARGE_INTEGER seekto; |
| 167 | ULONG res; |
| 168 | DWORD xsize; |
| 169 | HRESULT hres; |
| 170 | |
Mike Hearn | 64eac75 | 2005-01-27 11:11:32 +0000 | [diff] [blame] | 171 | if (!pUnk) { |
Marcus Meissner | 4107986 | 2005-03-29 13:06:44 +0000 | [diff] [blame] | 172 | /* this is valid, if for instance we serialize |
| 173 | * a VT_DISPATCH with NULL ptr which apparently |
| 174 | * can happen. S_OK to make sure we continue |
| 175 | * serializing. |
| 176 | */ |
Mike Hearn | 64eac75 | 2005-01-27 11:11:32 +0000 | [diff] [blame] | 177 | ERR("pUnk is NULL?\n"); |
Marcus Meissner | 4107986 | 2005-03-29 13:06:44 +0000 | [diff] [blame] | 178 | xsize = 0; |
| 179 | return xbuf_add(buf,(LPBYTE)&xsize,sizeof(xsize)); |
Mike Hearn | 64eac75 | 2005-01-27 11:11:32 +0000 | [diff] [blame] | 180 | } |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 181 | |
Marcus Meissner | 4107986 | 2005-03-29 13:06:44 +0000 | [diff] [blame] | 182 | hres = E_FAIL; |
| 183 | |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 184 | TRACE("...%s...\n",debugstr_guid(riid)); |
Mike Hearn | 64eac75 | 2005-01-27 11:11:32 +0000 | [diff] [blame] | 185 | |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 186 | hres = CreateStreamOnHGlobal(0,TRUE,&pStm); |
| 187 | if (hres) { |
Mike Hearn | 64eac75 | 2005-01-27 11:11:32 +0000 | [diff] [blame] | 188 | ERR("Stream create failed %lx\n",hres); |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 189 | goto fail; |
| 190 | } |
Mike Hearn | 64eac75 | 2005-01-27 11:11:32 +0000 | [diff] [blame] | 191 | |
Robert Shearman | 4519b1b | 2005-08-24 09:44:41 +0000 | [diff] [blame^] | 192 | hres = CoMarshalInterface(pStm,riid,pUnk,0,NULL,0); |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 193 | if (hres) { |
Mike Hearn | 64eac75 | 2005-01-27 11:11:32 +0000 | [diff] [blame] | 194 | ERR("Marshalling interface %s failed with %lx\n", debugstr_guid(riid), hres); |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 195 | goto fail; |
| 196 | } |
Mike Hearn | 64eac75 | 2005-01-27 11:11:32 +0000 | [diff] [blame] | 197 | |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 198 | hres = IStream_Stat(pStm,&ststg,0); |
Mike Hearn | 64eac75 | 2005-01-27 11:11:32 +0000 | [diff] [blame] | 199 | if (hres) { |
| 200 | ERR("Stream stat failed\n"); |
| 201 | goto fail; |
| 202 | } |
| 203 | |
Ge van Geldorp | 399901e | 2004-01-23 01:51:33 +0000 | [diff] [blame] | 204 | tempbuf = HeapAlloc(GetProcessHeap(), 0, ststg.cbSize.u.LowPart); |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 205 | memset(&seekto,0,sizeof(seekto)); |
| 206 | hres = IStream_Seek(pStm,seekto,SEEK_SET,&newpos); |
Mike Hearn | 64eac75 | 2005-01-27 11:11:32 +0000 | [diff] [blame] | 207 | if (hres) { |
| 208 | ERR("Failed Seek %lx\n",hres); |
| 209 | goto fail; |
| 210 | } |
| 211 | |
Ge van Geldorp | 399901e | 2004-01-23 01:51:33 +0000 | [diff] [blame] | 212 | hres = IStream_Read(pStm,tempbuf,ststg.cbSize.u.LowPart,&res); |
Mike Hearn | 64eac75 | 2005-01-27 11:11:32 +0000 | [diff] [blame] | 213 | if (hres) { |
| 214 | ERR("Failed Read %lx\n",hres); |
| 215 | goto fail; |
| 216 | } |
| 217 | |
Ge van Geldorp | 399901e | 2004-01-23 01:51:33 +0000 | [diff] [blame] | 218 | xsize = ststg.cbSize.u.LowPart; |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 219 | xbuf_add(buf,(LPBYTE)&xsize,sizeof(xsize)); |
Ge van Geldorp | 399901e | 2004-01-23 01:51:33 +0000 | [diff] [blame] | 220 | hres = xbuf_add(buf,tempbuf,ststg.cbSize.u.LowPart); |
Mike Hearn | 64eac75 | 2005-01-27 11:11:32 +0000 | [diff] [blame] | 221 | |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 222 | HeapFree(GetProcessHeap(),0,tempbuf); |
Mike Hearn | 64eac75 | 2005-01-27 11:11:32 +0000 | [diff] [blame] | 223 | IStream_Release(pStm); |
| 224 | |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 225 | return hres; |
Mike Hearn | 64eac75 | 2005-01-27 11:11:32 +0000 | [diff] [blame] | 226 | |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 227 | fail: |
| 228 | xsize = 0; |
| 229 | xbuf_add(buf,(LPBYTE)&xsize,sizeof(xsize)); |
Mike Hearn | 64eac75 | 2005-01-27 11:11:32 +0000 | [diff] [blame] | 230 | if (pStm) IUnknown_Release(pStm); |
Mike Hearn | 64eac75 | 2005-01-27 11:11:32 +0000 | [diff] [blame] | 231 | HeapFree(GetProcessHeap(), 0, tempbuf); |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 232 | return hres; |
| 233 | } |
| 234 | |
| 235 | /********************* OLE Proxy/Stub Factory ********************************/ |
| 236 | static HRESULT WINAPI |
| 237 | PSFacBuf_QueryInterface(LPPSFACTORYBUFFER iface, REFIID iid, LPVOID *ppv) { |
| 238 | if (IsEqualIID(iid,&IID_IPSFactoryBuffer)||IsEqualIID(iid,&IID_IUnknown)) { |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 239 | *ppv = (LPVOID)iface; |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 240 | /* No ref counting, static class */ |
| 241 | return S_OK; |
| 242 | } |
| 243 | FIXME("(%s) unknown IID?\n",debugstr_guid(iid)); |
| 244 | return E_NOINTERFACE; |
| 245 | } |
| 246 | |
| 247 | static ULONG WINAPI PSFacBuf_AddRef(LPPSFACTORYBUFFER iface) { return 2; } |
| 248 | static ULONG WINAPI PSFacBuf_Release(LPPSFACTORYBUFFER iface) { return 1; } |
| 249 | |
| 250 | static HRESULT |
| 251 | _get_typeinfo_for_iid(REFIID riid, ITypeInfo**ti) { |
| 252 | HRESULT hres; |
| 253 | HKEY ikey; |
| 254 | char tlguid[200],typelibkey[300],interfacekey[300],ver[100]; |
| 255 | char tlfn[260]; |
| 256 | OLECHAR tlfnW[260]; |
Mike McCormack | d7b9a23 | 2005-07-06 19:08:05 +0000 | [diff] [blame] | 257 | DWORD tlguidlen, verlen, type; |
| 258 | LONG tlfnlen; |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 259 | ITypeLib *tl; |
| 260 | |
| 261 | sprintf( interfacekey, "Interface\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\Typelib", |
| 262 | riid->Data1, riid->Data2, riid->Data3, |
| 263 | riid->Data4[0], riid->Data4[1], riid->Data4[2], riid->Data4[3], |
| 264 | riid->Data4[4], riid->Data4[5], riid->Data4[6], riid->Data4[7] |
| 265 | ); |
| 266 | |
| 267 | if (RegOpenKeyA(HKEY_CLASSES_ROOT,interfacekey,&ikey)) { |
Mike Hearn | 64eac75 | 2005-01-27 11:11:32 +0000 | [diff] [blame] | 268 | ERR("No %s key found.\n",interfacekey); |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 269 | return E_FAIL; |
| 270 | } |
| 271 | type = (1<<REG_SZ); |
| 272 | tlguidlen = sizeof(tlguid); |
Mike McCormack | d7b9a23 | 2005-07-06 19:08:05 +0000 | [diff] [blame] | 273 | if (RegQueryValueExA(ikey,NULL,NULL,&type,(LPBYTE)tlguid,&tlguidlen)) { |
Mike Hearn | 64eac75 | 2005-01-27 11:11:32 +0000 | [diff] [blame] | 274 | ERR("Getting typelib guid failed.\n"); |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 275 | RegCloseKey(ikey); |
| 276 | return E_FAIL; |
| 277 | } |
| 278 | type = (1<<REG_SZ); |
| 279 | verlen = sizeof(ver); |
Mike McCormack | d7b9a23 | 2005-07-06 19:08:05 +0000 | [diff] [blame] | 280 | if (RegQueryValueExA(ikey,"Version",NULL,&type,(LPBYTE)ver,&verlen)) { |
Mike Hearn | 64eac75 | 2005-01-27 11:11:32 +0000 | [diff] [blame] | 281 | ERR("Could not get version value?\n"); |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 282 | RegCloseKey(ikey); |
| 283 | return E_FAIL; |
| 284 | } |
| 285 | RegCloseKey(ikey); |
| 286 | sprintf(typelibkey,"Typelib\\%s\\%s\\0\\win32",tlguid,ver); |
| 287 | tlfnlen = sizeof(tlfn); |
| 288 | if (RegQueryValueA(HKEY_CLASSES_ROOT,typelibkey,tlfn,&tlfnlen)) { |
Mike Hearn | 64eac75 | 2005-01-27 11:11:32 +0000 | [diff] [blame] | 289 | ERR("Could not get typelib fn?\n"); |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 290 | return E_FAIL; |
| 291 | } |
| 292 | MultiByteToWideChar(CP_ACP, 0, tlfn, -1, tlfnW, -1); |
| 293 | hres = LoadTypeLib(tlfnW,&tl); |
| 294 | if (hres) { |
| 295 | ERR("Failed to load typelib for %s, but it should be there.\n",debugstr_guid(riid)); |
| 296 | return hres; |
| 297 | } |
| 298 | hres = ITypeLib_GetTypeInfoOfGuid(tl,riid,ti); |
| 299 | if (hres) { |
| 300 | ERR("typelib does not contain info for %s?\n",debugstr_guid(riid)); |
| 301 | ITypeLib_Release(tl); |
| 302 | return hres; |
| 303 | } |
| 304 | /* FIXME: do this? ITypeLib_Release(tl); */ |
| 305 | return hres; |
| 306 | } |
| 307 | |
| 308 | /* Determine nr of functions. Since we use the toplevel interface and all |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 309 | * inherited ones have lower numbers, we are ok to not to descent into |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 310 | * the inheritance tree I think. |
| 311 | */ |
| 312 | static int _nroffuncs(ITypeInfo *tinfo) { |
| 313 | int n, max = 0; |
| 314 | FUNCDESC *fdesc; |
| 315 | HRESULT hres; |
| 316 | |
| 317 | n=0; |
| 318 | while (1) { |
| 319 | hres = ITypeInfo_GetFuncDesc(tinfo,n,&fdesc); |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 320 | if (hres) |
| 321 | return max+1; |
Marcus Meissner | 995389e | 2003-09-22 19:21:32 +0000 | [diff] [blame] | 322 | if (fdesc->oVft/4 > max) |
| 323 | max = fdesc->oVft/4; |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 324 | n++; |
| 325 | } |
| 326 | /*NOTREACHED*/ |
| 327 | } |
| 328 | |
Robert Shearman | 2a54aac | 2004-09-07 20:42:26 +0000 | [diff] [blame] | 329 | #ifdef __i386__ |
| 330 | |
Alexandre Julliard | e828308 | 2004-01-09 22:18:49 +0000 | [diff] [blame] | 331 | #include "pshpack1.h" |
| 332 | |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 333 | typedef struct _TMAsmProxy { |
| 334 | BYTE popleax; |
| 335 | BYTE pushlval; |
| 336 | BYTE nr; |
| 337 | BYTE pushleax; |
| 338 | BYTE lcall; |
| 339 | DWORD xcall; |
| 340 | BYTE lret; |
| 341 | WORD bytestopop; |
Alexandre Julliard | e828308 | 2004-01-09 22:18:49 +0000 | [diff] [blame] | 342 | } TMAsmProxy; |
| 343 | |
| 344 | #include "poppack.h" |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 345 | |
Robert Shearman | 2a54aac | 2004-09-07 20:42:26 +0000 | [diff] [blame] | 346 | #else /* __i386__ */ |
| 347 | # error You need to implement stubless proxies for your architecture |
| 348 | #endif |
| 349 | |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 350 | typedef struct _TMProxyImpl { |
Dmitry Timoshkov | eba47f1 | 2005-06-06 19:50:35 +0000 | [diff] [blame] | 351 | LPVOID *lpvtbl; |
| 352 | const IRpcProxyBufferVtbl *lpvtbl2; |
Mike McCormack | fc200d0 | 2005-07-11 10:25:19 +0000 | [diff] [blame] | 353 | LONG ref; |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 354 | |
| 355 | TMAsmProxy *asmstubs; |
| 356 | ITypeInfo* tinfo; |
| 357 | IRpcChannelBuffer* chanbuf; |
| 358 | IID iid; |
Robert Shearman | 2a54aac | 2004-09-07 20:42:26 +0000 | [diff] [blame] | 359 | CRITICAL_SECTION crit; |
Robert Shearman | ac23f2c | 2005-03-11 10:18:31 +0000 | [diff] [blame] | 360 | IUnknown *outerunknown; |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 361 | } TMProxyImpl; |
| 362 | |
| 363 | static HRESULT WINAPI |
Robert Shearman | 2a54aac | 2004-09-07 20:42:26 +0000 | [diff] [blame] | 364 | TMProxyImpl_QueryInterface(LPRPCPROXYBUFFER iface, REFIID riid, LPVOID *ppv) |
| 365 | { |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 366 | TRACE("()\n"); |
| 367 | if (IsEqualIID(riid,&IID_IUnknown)||IsEqualIID(riid,&IID_IRpcProxyBuffer)) { |
Robert Shearman | 2a54aac | 2004-09-07 20:42:26 +0000 | [diff] [blame] | 368 | *ppv = (LPVOID)iface; |
| 369 | IRpcProxyBuffer_AddRef(iface); |
| 370 | return S_OK; |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 371 | } |
| 372 | FIXME("no interface for %s\n",debugstr_guid(riid)); |
| 373 | return E_NOINTERFACE; |
| 374 | } |
| 375 | |
| 376 | static ULONG WINAPI |
Robert Shearman | 2a54aac | 2004-09-07 20:42:26 +0000 | [diff] [blame] | 377 | TMProxyImpl_AddRef(LPRPCPROXYBUFFER iface) |
| 378 | { |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 379 | ICOM_THIS_MULTI(TMProxyImpl,lpvtbl2,iface); |
James Hawkins | ba92d29 | 2005-01-14 16:02:20 +0000 | [diff] [blame] | 380 | ULONG refCount = InterlockedIncrement(&This->ref); |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 381 | |
James Hawkins | ba92d29 | 2005-01-14 16:02:20 +0000 | [diff] [blame] | 382 | TRACE("(%p)->(ref before=%lu)\n",This, refCount - 1); |
Robert Shearman | 2a54aac | 2004-09-07 20:42:26 +0000 | [diff] [blame] | 383 | |
James Hawkins | ba92d29 | 2005-01-14 16:02:20 +0000 | [diff] [blame] | 384 | return refCount; |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 385 | } |
| 386 | |
| 387 | static ULONG WINAPI |
Robert Shearman | 2a54aac | 2004-09-07 20:42:26 +0000 | [diff] [blame] | 388 | TMProxyImpl_Release(LPRPCPROXYBUFFER iface) |
| 389 | { |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 390 | ICOM_THIS_MULTI(TMProxyImpl,lpvtbl2,iface); |
James Hawkins | ba92d29 | 2005-01-14 16:02:20 +0000 | [diff] [blame] | 391 | ULONG refCount = InterlockedDecrement(&This->ref); |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 392 | |
James Hawkins | ba92d29 | 2005-01-14 16:02:20 +0000 | [diff] [blame] | 393 | TRACE("(%p)->(ref before=%lu)\n",This, refCount + 1); |
Robert Shearman | 2a54aac | 2004-09-07 20:42:26 +0000 | [diff] [blame] | 394 | |
James Hawkins | ba92d29 | 2005-01-14 16:02:20 +0000 | [diff] [blame] | 395 | if (!refCount) |
Robert Shearman | 2a54aac | 2004-09-07 20:42:26 +0000 | [diff] [blame] | 396 | { |
| 397 | DeleteCriticalSection(&This->crit); |
| 398 | if (This->chanbuf) IRpcChannelBuffer_Release(This->chanbuf); |
| 399 | VirtualFree(This->asmstubs, 0, MEM_RELEASE); |
| 400 | CoTaskMemFree(This); |
| 401 | } |
James Hawkins | ba92d29 | 2005-01-14 16:02:20 +0000 | [diff] [blame] | 402 | return refCount; |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 403 | } |
| 404 | |
| 405 | static HRESULT WINAPI |
| 406 | TMProxyImpl_Connect( |
Robert Shearman | 2a54aac | 2004-09-07 20:42:26 +0000 | [diff] [blame] | 407 | LPRPCPROXYBUFFER iface,IRpcChannelBuffer* pRpcChannelBuffer) |
| 408 | { |
| 409 | ICOM_THIS_MULTI(TMProxyImpl, lpvtbl2, iface); |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 410 | |
Robert Shearman | 2a54aac | 2004-09-07 20:42:26 +0000 | [diff] [blame] | 411 | TRACE("(%p)\n", pRpcChannelBuffer); |
| 412 | |
| 413 | EnterCriticalSection(&This->crit); |
| 414 | |
| 415 | IRpcChannelBuffer_AddRef(pRpcChannelBuffer); |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 416 | This->chanbuf = pRpcChannelBuffer; |
Robert Shearman | 2a54aac | 2004-09-07 20:42:26 +0000 | [diff] [blame] | 417 | |
| 418 | LeaveCriticalSection(&This->crit); |
| 419 | |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 420 | return S_OK; |
| 421 | } |
| 422 | |
| 423 | static void WINAPI |
Robert Shearman | 2a54aac | 2004-09-07 20:42:26 +0000 | [diff] [blame] | 424 | TMProxyImpl_Disconnect(LPRPCPROXYBUFFER iface) |
| 425 | { |
| 426 | ICOM_THIS_MULTI(TMProxyImpl, lpvtbl2, iface); |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 427 | |
Robert Shearman | 2a54aac | 2004-09-07 20:42:26 +0000 | [diff] [blame] | 428 | TRACE("()\n"); |
| 429 | |
| 430 | EnterCriticalSection(&This->crit); |
| 431 | |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 432 | IRpcChannelBuffer_Release(This->chanbuf); |
| 433 | This->chanbuf = NULL; |
Robert Shearman | 2a54aac | 2004-09-07 20:42:26 +0000 | [diff] [blame] | 434 | |
| 435 | LeaveCriticalSection(&This->crit); |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 436 | } |
| 437 | |
| 438 | |
Dmitry Timoshkov | eba47f1 | 2005-06-06 19:50:35 +0000 | [diff] [blame] | 439 | static const IRpcProxyBufferVtbl tmproxyvtable = { |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 440 | TMProxyImpl_QueryInterface, |
| 441 | TMProxyImpl_AddRef, |
| 442 | TMProxyImpl_Release, |
| 443 | TMProxyImpl_Connect, |
| 444 | TMProxyImpl_Disconnect |
| 445 | }; |
| 446 | |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 447 | /* how much space do we use on stack in DWORD steps. */ |
Marcus Meissner | 5539e28 | 2004-09-27 20:33:27 +0000 | [diff] [blame] | 448 | int |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 449 | _argsize(DWORD vt) { |
| 450 | switch (vt) { |
Robert Shearman | 1329f87 | 2005-06-09 09:43:38 +0000 | [diff] [blame] | 451 | case VT_R8: |
| 452 | return sizeof(double)/sizeof(DWORD); |
| 453 | case VT_CY: |
| 454 | return sizeof(CY)/sizeof(DWORD); |
Marcus Meissner | c18a6aa | 2002-06-14 00:36:42 +0000 | [diff] [blame] | 455 | case VT_DATE: |
| 456 | return sizeof(DATE)/sizeof(DWORD); |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 457 | case VT_VARIANT: |
| 458 | return (sizeof(VARIANT)+3)/sizeof(DWORD); |
| 459 | default: |
| 460 | return 1; |
| 461 | } |
| 462 | } |
| 463 | |
| 464 | static int |
| 465 | _xsize(TYPEDESC *td) { |
| 466 | switch (td->vt) { |
Marcus Meissner | c18a6aa | 2002-06-14 00:36:42 +0000 | [diff] [blame] | 467 | case VT_DATE: |
| 468 | return sizeof(DATE); |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 469 | case VT_VARIANT: |
| 470 | return sizeof(VARIANT)+3; |
| 471 | case VT_CARRAY: { |
| 472 | int i, arrsize = 1; |
| 473 | ARRAYDESC *adesc = td->u.lpadesc; |
| 474 | |
| 475 | for (i=0;i<adesc->cDims;i++) |
| 476 | arrsize *= adesc->rgbounds[i].cElements; |
| 477 | return arrsize*_xsize(&adesc->tdescElem); |
| 478 | } |
| 479 | case VT_UI2: |
| 480 | case VT_I2: |
| 481 | return 2; |
| 482 | case VT_UI1: |
| 483 | case VT_I1: |
| 484 | return 1; |
| 485 | default: |
| 486 | return 4; |
| 487 | } |
| 488 | } |
| 489 | |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 490 | static HRESULT |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 491 | serialize_param( |
| 492 | ITypeInfo *tinfo, |
| 493 | BOOL writeit, |
| 494 | BOOL debugout, |
| 495 | BOOL dealloc, |
| 496 | TYPEDESC *tdesc, |
| 497 | DWORD *arg, |
Robert Shearman | 2a54aac | 2004-09-07 20:42:26 +0000 | [diff] [blame] | 498 | marshal_state *buf) |
| 499 | { |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 500 | HRESULT hres = S_OK; |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 501 | |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 502 | TRACE("(tdesc.vt %d)\n",tdesc->vt); |
| 503 | |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 504 | switch (tdesc->vt) { |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 505 | case VT_EMPTY: /* nothing. empty variant for instance */ |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 506 | return S_OK; |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 507 | case VT_BOOL: |
| 508 | case VT_ERROR: |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 509 | case VT_UINT: |
| 510 | case VT_I4: |
Marcus Meissner | d344849 | 2002-12-05 19:12:50 +0000 | [diff] [blame] | 511 | case VT_R4: |
Alexandre Julliard | 232760d | 2005-03-14 10:09:11 +0000 | [diff] [blame] | 512 | case VT_UI4: |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 513 | hres = S_OK; |
Mike Hearn | d440ca4 | 2004-06-17 23:03:26 +0000 | [diff] [blame] | 514 | if (debugout) TRACE_(olerelay)("%lx",*arg); |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 515 | if (writeit) |
| 516 | hres = xbuf_add(buf,(LPBYTE)arg,sizeof(DWORD)); |
| 517 | return hres; |
Marcus Meissner | c91df67 | 2005-03-27 18:17:19 +0000 | [diff] [blame] | 518 | case VT_I2: |
| 519 | case VT_UI2: |
| 520 | hres = S_OK; |
| 521 | if (debugout) TRACE_(olerelay)("%04lx",*arg & 0xffff); |
| 522 | if (writeit) |
| 523 | hres = xbuf_add(buf,(LPBYTE)arg,sizeof(DWORD)); |
| 524 | return hres; |
| 525 | case VT_I1: |
| 526 | case VT_UI1: |
| 527 | hres = S_OK; |
| 528 | if (debugout) TRACE_(olerelay)("%02lx",*arg & 0xff); |
| 529 | if (writeit) |
| 530 | hres = xbuf_add(buf,(LPBYTE)arg,sizeof(DWORD)); |
| 531 | return hres; |
Marcus Meissner | 4b5f3c6 | 2005-03-29 11:29:11 +0000 | [diff] [blame] | 532 | case VT_I4|VT_BYREF: |
| 533 | hres = S_OK; |
| 534 | if (debugout) TRACE_(olerelay)("&0x%lx",*arg); |
| 535 | if (writeit) |
| 536 | hres = xbuf_add(buf,(LPBYTE)(DWORD*)*arg,sizeof(DWORD)); |
| 537 | /* do not dealloc at this time */ |
| 538 | return hres; |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 539 | case VT_VARIANT: { |
| 540 | TYPEDESC tdesc2; |
| 541 | VARIANT *vt = (VARIANT*)arg; |
| 542 | DWORD vttype = V_VT(vt); |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 543 | |
Mike Hearn | d440ca4 | 2004-06-17 23:03:26 +0000 | [diff] [blame] | 544 | if (debugout) TRACE_(olerelay)("Vt(%ld)(",vttype); |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 545 | tdesc2.vt = vttype; |
| 546 | if (writeit) { |
| 547 | hres = xbuf_add(buf,(LPBYTE)&vttype,sizeof(vttype)); |
| 548 | if (hres) return hres; |
| 549 | } |
| 550 | /* need to recurse since we need to free the stuff */ |
Mike McCormack | a04b77d | 2005-08-08 18:38:29 +0000 | [diff] [blame] | 551 | hres = serialize_param(tinfo,writeit,debugout,dealloc,&tdesc2,(DWORD*)&(V_I4(vt)),buf); |
Mike Hearn | d440ca4 | 2004-06-17 23:03:26 +0000 | [diff] [blame] | 552 | if (debugout) TRACE_(olerelay)(")"); |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 553 | return hres; |
| 554 | } |
Alexandre Julliard | 232760d | 2005-03-14 10:09:11 +0000 | [diff] [blame] | 555 | case VT_BSTR|VT_BYREF: { |
Marcus Meissner | 4b5f3c6 | 2005-03-29 11:29:11 +0000 | [diff] [blame] | 556 | if (debugout) TRACE_(olerelay)("[byref]'%s'", *(BSTR*)*arg ? relaystr(*((BSTR*)*arg)) : "<bstr NULL>"); |
Alexandre Julliard | 232760d | 2005-03-14 10:09:11 +0000 | [diff] [blame] | 557 | if (writeit) { |
| 558 | /* ptr to ptr to magic widestring, basically */ |
| 559 | BSTR *bstr = (BSTR *) *arg; |
Robert Shearman | d8780c7 | 2005-07-19 19:42:50 +0000 | [diff] [blame] | 560 | DWORD len; |
Marcus Meissner | 4b5f3c6 | 2005-03-29 11:29:11 +0000 | [diff] [blame] | 561 | if (!*bstr) { |
Alexandre Julliard | 232760d | 2005-03-14 10:09:11 +0000 | [diff] [blame] | 562 | /* -1 means "null string" which is equivalent to empty string */ |
Robert Shearman | d8780c7 | 2005-07-19 19:42:50 +0000 | [diff] [blame] | 563 | len = -1; |
| 564 | hres = xbuf_add(buf, (LPBYTE)&len,sizeof(DWORD)); |
| 565 | if (hres) return hres; |
Alexandre Julliard | 232760d | 2005-03-14 10:09:11 +0000 | [diff] [blame] | 566 | } else { |
Robert Shearman | d8780c7 | 2005-07-19 19:42:50 +0000 | [diff] [blame] | 567 | len = *((DWORD*)*bstr-1)/sizeof(WCHAR); |
| 568 | hres = xbuf_add(buf,(LPBYTE)&len,sizeof(DWORD)); |
| 569 | if (hres) return hres; |
| 570 | hres = xbuf_add(buf,(LPBYTE)*bstr,len * sizeof(WCHAR)); |
| 571 | if (hres) return hres; |
Alexandre Julliard | 232760d | 2005-03-14 10:09:11 +0000 | [diff] [blame] | 572 | } |
| 573 | } |
| 574 | |
| 575 | if (dealloc && arg) { |
| 576 | BSTR *str = *((BSTR **)arg); |
| 577 | SysFreeString(*str); |
| 578 | } |
| 579 | return S_OK; |
| 580 | } |
| 581 | |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 582 | case VT_BSTR: { |
| 583 | if (debugout) { |
Mike Hearn | edcbd13 | 2005-03-27 18:20:10 +0000 | [diff] [blame] | 584 | if (*arg) |
| 585 | TRACE_(olerelay)("%s",relaystr((WCHAR*)*arg)); |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 586 | else |
Mike Hearn | d440ca4 | 2004-06-17 23:03:26 +0000 | [diff] [blame] | 587 | TRACE_(olerelay)("<bstr NULL>"); |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 588 | } |
| 589 | if (writeit) { |
Robert Shearman | d8780c7 | 2005-07-19 19:42:50 +0000 | [diff] [blame] | 590 | BSTR bstr = (BSTR)*arg; |
| 591 | DWORD len; |
| 592 | if (!bstr) { |
| 593 | len = -1; |
| 594 | hres = xbuf_add(buf,(LPBYTE)&len,sizeof(DWORD)); |
| 595 | if (hres) return hres; |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 596 | } else { |
Robert Shearman | d8780c7 | 2005-07-19 19:42:50 +0000 | [diff] [blame] | 597 | len = *((DWORD*)bstr-1)/sizeof(WCHAR); |
| 598 | hres = xbuf_add(buf,(LPBYTE)&len,sizeof(DWORD)); |
| 599 | if (hres) return hres; |
| 600 | hres = xbuf_add(buf,(LPBYTE)bstr,len * sizeof(WCHAR)); |
| 601 | if (hres) return hres; |
Marcus Meissner | 5b63cc2 | 2002-05-06 20:12:11 +0000 | [diff] [blame] | 602 | } |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 603 | } |
Marcus Meissner | 236ad0d | 2003-12-01 22:36:49 +0000 | [diff] [blame] | 604 | |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 605 | if (dealloc && arg) |
Marcus Meissner | 236ad0d | 2003-12-01 22:36:49 +0000 | [diff] [blame] | 606 | SysFreeString((BSTR)*arg); |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 607 | return S_OK; |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 608 | } |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 609 | case VT_PTR: { |
| 610 | DWORD cookie; |
Robert Shearman | 1329f87 | 2005-06-09 09:43:38 +0000 | [diff] [blame] | 611 | BOOL derefhere; |
| 612 | |
| 613 | derefhere = (tdesc->u.lptdesc->vt != VT_USERDEFINED); |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 614 | |
Mike Hearn | d440ca4 | 2004-06-17 23:03:26 +0000 | [diff] [blame] | 615 | if (debugout) TRACE_(olerelay)("*"); |
Marcus Meissner | e6260a3 | 2005-03-27 17:51:59 +0000 | [diff] [blame] | 616 | /* Write always, so the other side knows when it gets a NULL pointer. |
| 617 | */ |
| 618 | cookie = *arg ? 0x42424242 : 0; |
| 619 | hres = xbuf_add(buf,(LPBYTE)&cookie,sizeof(cookie)); |
| 620 | if (hres) |
| 621 | return hres; |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 622 | if (!*arg) { |
Mike Hearn | d440ca4 | 2004-06-17 23:03:26 +0000 | [diff] [blame] | 623 | if (debugout) TRACE_(olerelay)("NULL"); |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 624 | return S_OK; |
| 625 | } |
| 626 | hres = serialize_param(tinfo,writeit,debugout,dealloc,tdesc->u.lptdesc,(DWORD*)*arg,buf); |
Robert Shearman | 1329f87 | 2005-06-09 09:43:38 +0000 | [diff] [blame] | 627 | if (derefhere && dealloc) HeapFree(GetProcessHeap(),0,(LPVOID)*arg); |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 628 | return hres; |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 629 | } |
| 630 | case VT_UNKNOWN: |
Mike Hearn | d440ca4 | 2004-06-17 23:03:26 +0000 | [diff] [blame] | 631 | if (debugout) TRACE_(olerelay)("unk(0x%lx)",*arg); |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 632 | if (writeit) |
| 633 | hres = _marshal_interface(buf,&IID_IUnknown,(LPUNKNOWN)*arg); |
| 634 | return hres; |
| 635 | case VT_DISPATCH: |
Mike Hearn | d440ca4 | 2004-06-17 23:03:26 +0000 | [diff] [blame] | 636 | if (debugout) TRACE_(olerelay)("idisp(0x%lx)",*arg); |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 637 | if (writeit) |
| 638 | hres = _marshal_interface(buf,&IID_IDispatch,(LPUNKNOWN)*arg); |
| 639 | return hres; |
| 640 | case VT_VOID: |
Mike Hearn | d440ca4 | 2004-06-17 23:03:26 +0000 | [diff] [blame] | 641 | if (debugout) TRACE_(olerelay)("<void>"); |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 642 | return S_OK; |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 643 | case VT_USERDEFINED: { |
| 644 | ITypeInfo *tinfo2; |
| 645 | TYPEATTR *tattr; |
| 646 | |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 647 | hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.hreftype,&tinfo2); |
| 648 | if (hres) { |
Mike Hearn | 64eac75 | 2005-01-27 11:11:32 +0000 | [diff] [blame] | 649 | ERR("Could not get typeinfo of hreftype %lx for VT_USERDEFINED.\n",tdesc->u.hreftype); |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 650 | return hres; |
| 651 | } |
| 652 | ITypeInfo_GetTypeAttr(tinfo2,&tattr); |
| 653 | switch (tattr->typekind) { |
Marcus Meissner | 26ffca4 | 2002-12-12 22:25:07 +0000 | [diff] [blame] | 654 | case TKIND_DISPATCH: |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 655 | case TKIND_INTERFACE: |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 656 | if (writeit) |
| 657 | hres=_marshal_interface(buf,&(tattr->guid),(LPUNKNOWN)arg); |
Robert Shearman | 4519b1b | 2005-08-24 09:44:41 +0000 | [diff] [blame^] | 658 | if (dealloc) |
| 659 | IUnknown_Release((LPUNKNOWN)arg); |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 660 | break; |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 661 | case TKIND_RECORD: { |
| 662 | int i; |
Mike Hearn | d440ca4 | 2004-06-17 23:03:26 +0000 | [diff] [blame] | 663 | if (debugout) TRACE_(olerelay)("{"); |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 664 | for (i=0;i<tattr->cVars;i++) { |
| 665 | VARDESC *vdesc; |
| 666 | ELEMDESC *elem2; |
| 667 | TYPEDESC *tdesc2; |
| 668 | |
| 669 | hres = ITypeInfo2_GetVarDesc(tinfo2, i, &vdesc); |
| 670 | if (hres) { |
Mike Hearn | 64eac75 | 2005-01-27 11:11:32 +0000 | [diff] [blame] | 671 | ERR("Could not get vardesc of %d\n",i); |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 672 | return hres; |
| 673 | } |
| 674 | /* Need them for hack below */ |
| 675 | /* |
| 676 | memset(names,0,sizeof(names)); |
| 677 | hres = ITypeInfo_GetNames(tinfo2,vdesc->memid,names,sizeof(names)/sizeof(names[0]),&nrofnames); |
| 678 | if (nrofnames > sizeof(names)/sizeof(names[0])) { |
| 679 | ERR("Need more names!\n"); |
| 680 | } |
| 681 | if (!hres && debugout) |
Mike Hearn | d440ca4 | 2004-06-17 23:03:26 +0000 | [diff] [blame] | 682 | TRACE_(olerelay)("%s=",relaystr(names[0])); |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 683 | */ |
| 684 | elem2 = &vdesc->elemdescVar; |
| 685 | tdesc2 = &elem2->tdesc; |
| 686 | hres = serialize_param( |
| 687 | tinfo2, |
| 688 | writeit, |
| 689 | debugout, |
| 690 | dealloc, |
| 691 | tdesc2, |
| 692 | (DWORD*)(((LPBYTE)arg)+vdesc->u.oInst), |
| 693 | buf |
| 694 | ); |
Robert Shearman | c6296c4 | 2005-06-01 11:03:40 +0000 | [diff] [blame] | 695 | ITypeInfo_ReleaseVarDesc(tinfo2, vdesc); |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 696 | if (hres!=S_OK) |
| 697 | return hres; |
| 698 | if (debugout && (i<(tattr->cVars-1))) |
Mike Hearn | d440ca4 | 2004-06-17 23:03:26 +0000 | [diff] [blame] | 699 | TRACE_(olerelay)(","); |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 700 | } |
| 701 | if (buf->thisisiid && (tattr->cbSizeInstance==sizeof(GUID))) |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 702 | memcpy(&(buf->iid),arg,sizeof(buf->iid)); |
Mike Hearn | d440ca4 | 2004-06-17 23:03:26 +0000 | [diff] [blame] | 703 | if (debugout) TRACE_(olerelay)("}"); |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 704 | break; |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 705 | } |
Robert Shearman | d2e2e85 | 2005-07-19 19:13:23 +0000 | [diff] [blame] | 706 | case TKIND_ALIAS: |
| 707 | return serialize_param(tinfo2,writeit,debugout,dealloc,&tattr->tdescAlias,arg,buf); |
| 708 | case TKIND_ENUM: |
| 709 | hres = S_OK; |
| 710 | if (debugout) TRACE_(olerelay)("%lx",*arg); |
| 711 | if (writeit) |
| 712 | hres = xbuf_add(buf,(LPBYTE)arg,sizeof(DWORD)); |
| 713 | return hres; |
Marcus Meissner | 26ffca4 | 2002-12-12 22:25:07 +0000 | [diff] [blame] | 714 | default: |
| 715 | FIXME("Unhandled typekind %d\n",tattr->typekind); |
| 716 | hres = E_FAIL; |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 717 | break; |
| 718 | } |
| 719 | ITypeInfo_Release(tinfo2); |
| 720 | return hres; |
| 721 | } |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 722 | case VT_CARRAY: { |
| 723 | ARRAYDESC *adesc = tdesc->u.lpadesc; |
| 724 | int i, arrsize = 1; |
| 725 | |
Mike Hearn | d440ca4 | 2004-06-17 23:03:26 +0000 | [diff] [blame] | 726 | if (debugout) TRACE_(olerelay)("carr"); |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 727 | for (i=0;i<adesc->cDims;i++) { |
Mike Hearn | d440ca4 | 2004-06-17 23:03:26 +0000 | [diff] [blame] | 728 | if (debugout) TRACE_(olerelay)("[%ld]",adesc->rgbounds[i].cElements); |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 729 | arrsize *= adesc->rgbounds[i].cElements; |
| 730 | } |
Marcus Meissner | e6260a3 | 2005-03-27 17:51:59 +0000 | [diff] [blame] | 731 | if (debugout) TRACE_(olerelay)("(vt %d)",adesc->tdescElem.vt); |
Mike Hearn | d440ca4 | 2004-06-17 23:03:26 +0000 | [diff] [blame] | 732 | if (debugout) TRACE_(olerelay)("["); |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 733 | for (i=0;i<arrsize;i++) { |
| 734 | hres = serialize_param(tinfo, writeit, debugout, dealloc, &adesc->tdescElem, (DWORD*)((LPBYTE)arg+i*_xsize(&adesc->tdescElem)), buf); |
| 735 | if (hres) |
| 736 | return hres; |
Mike Hearn | d440ca4 | 2004-06-17 23:03:26 +0000 | [diff] [blame] | 737 | if (debugout && (i<arrsize-1)) TRACE_(olerelay)(","); |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 738 | } |
Mike Hearn | d440ca4 | 2004-06-17 23:03:26 +0000 | [diff] [blame] | 739 | if (debugout) TRACE_(olerelay)("]"); |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 740 | return S_OK; |
| 741 | } |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 742 | default: |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 743 | ERR("Unhandled marshal type %d.\n",tdesc->vt); |
| 744 | return S_OK; |
| 745 | } |
| 746 | } |
| 747 | |
Marcus Meissner | e6260a3 | 2005-03-27 17:51:59 +0000 | [diff] [blame] | 748 | /* IDL desc: |
| 749 | * HRESULT GetIDsOfNames( |
| 750 | * [in] REFIID riid, args[1] |
| 751 | * [in, size_is(cNames)] LPOLESTR *rgszNames, args[2] |
| 752 | * [in] UINT cNames, args[3] |
| 753 | * [in] LCID lcid, args[4] |
| 754 | * [out, size_is(cNames)] DISPID *rgDispId); args[5] |
| 755 | * |
| 756 | * line format: |
| 757 | * IID iid; |
| 758 | * DWORD cNames; |
| 759 | * LPOLESTR rgszNames[cNames]; |
| 760 | * DWORD bytestrlen (incl 0) |
| 761 | * BYTE data[bytestrlen] (incl 0) |
| 762 | * LCID |
| 763 | */ |
| 764 | static HRESULT |
| 765 | serialize_IDispatch_GetIDsOfNames( |
| 766 | BOOL inputparams, |
| 767 | BOOL debugout, |
| 768 | DWORD *args, |
| 769 | marshal_state *buf) |
| 770 | { |
| 771 | HRESULT hres; |
| 772 | DWORD cNames = args[2]; |
| 773 | LPOLESTR *rgszNames = (LPOLESTR*)args[1]; |
| 774 | int i; |
| 775 | |
| 776 | if (inputparams) { |
| 777 | if (debugout) TRACE_(olerelay)("riid=%s,",debugstr_guid((REFIID)args[0])); |
| 778 | hres = xbuf_add(buf, (LPBYTE)args[0], sizeof(IID)); |
| 779 | if (hres) { |
| 780 | FIXME("serialize of IID failed.\n"); |
| 781 | return hres; |
| 782 | } |
| 783 | if (debugout) TRACE_(olerelay)("cNames=%ld,",cNames); |
| 784 | hres = xbuf_add(buf, (LPBYTE)&cNames, sizeof(DWORD)); |
| 785 | if (hres) { |
| 786 | FIXME("serialize of cNames failed.\n"); |
| 787 | return hres; |
| 788 | } |
| 789 | if (debugout) TRACE_(olerelay)("rgszNames=["); |
| 790 | for (i=0;i<cNames;i++) { |
| 791 | DWORD len = 2*(lstrlenW(rgszNames[i])+1); |
| 792 | |
| 793 | if (debugout) TRACE_(olerelay)("%s,",relaystr(rgszNames[i])); |
| 794 | hres = xbuf_add(buf, (LPBYTE)&len, sizeof(DWORD)); |
| 795 | if (hres) { |
| 796 | FIXME("serialize of len failed.\n"); |
| 797 | return hres; |
| 798 | } |
| 799 | hres = xbuf_add(buf, (LPBYTE)rgszNames[i], len); |
| 800 | if (hres) { |
| 801 | FIXME("serialize of rgszNames[i] failed.\n"); |
| 802 | return hres; |
| 803 | } |
| 804 | } |
| 805 | if (debugout) TRACE_(olerelay)("],lcid=%04lx)",args[3]); |
| 806 | hres = xbuf_add(buf, (LPBYTE)&args[3], sizeof(DWORD)); |
| 807 | if (hres) { |
| 808 | FIXME("serialize of lcid failed.\n"); |
| 809 | return hres; |
| 810 | } |
| 811 | } else { |
| 812 | DISPID *rgDispId = (DISPID*)args[4]; |
| 813 | |
| 814 | hres = xbuf_add(buf, (LPBYTE)rgDispId, sizeof(DISPID) * cNames); |
| 815 | if (hres) { |
| 816 | FIXME("serialize of rgDispId failed.\n"); |
| 817 | return hres; |
| 818 | } |
| 819 | if (debugout) { |
| 820 | TRACE_(olerelay)("riid=[in],rgszNames=[in],cNames=[in],rgDispId=["); |
| 821 | for (i=0;i<cNames;i++) |
| 822 | TRACE_(olerelay)("%08lx,",rgDispId[i]); |
| 823 | TRACE_(olerelay)("])"); |
| 824 | } |
| 825 | HeapFree(GetProcessHeap(),0,(IID*)args[0]); |
| 826 | rgszNames = (LPOLESTR*)args[1]; |
| 827 | for (i=0;i<cNames;i++) HeapFree(GetProcessHeap(),0,rgszNames[i]); |
| 828 | HeapFree(GetProcessHeap(),0,rgszNames); |
| 829 | HeapFree(GetProcessHeap(),0,rgDispId); |
| 830 | } |
| 831 | return S_OK; |
| 832 | } |
| 833 | |
| 834 | static HRESULT |
| 835 | deserialize_IDispatch_GetIDsOfNames( |
| 836 | BOOL inputparams, |
| 837 | BOOL debugout, |
| 838 | DWORD *args, |
| 839 | marshal_state *buf) |
| 840 | { |
| 841 | HRESULT hres; |
| 842 | DWORD cNames; |
| 843 | LPOLESTR *rgszNames; |
| 844 | int i; |
| 845 | |
| 846 | if (inputparams) { |
| 847 | args[0] = (DWORD)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IID)); |
| 848 | if (!args[0]) return E_FAIL; |
| 849 | hres = xbuf_get(buf, (LPBYTE)args[0], sizeof(IID)); |
| 850 | if (hres) { |
| 851 | FIXME("deserialize of IID failed.\n"); |
| 852 | return hres; |
| 853 | } |
| 854 | if (debugout) TRACE_(olerelay)("riid=%s,",debugstr_guid((REFIID)args[0])); |
| 855 | |
| 856 | hres = xbuf_get(buf, (LPBYTE)&cNames, sizeof(DWORD)); |
| 857 | if (hres) { |
| 858 | FIXME("deserialize of cNames failed.\n"); |
| 859 | return hres; |
| 860 | } |
| 861 | args[2] = cNames; |
| 862 | if (debugout) TRACE_(olerelay)("cNames=%ld,",cNames); |
| 863 | if (debugout) TRACE_(olerelay)("rgszNames=["); |
| 864 | rgszNames = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(LPOLESTR) * cNames); |
| 865 | if (!rgszNames) return E_FAIL; |
| 866 | args[1] = (DWORD)rgszNames; |
| 867 | for (i=0;i<cNames;i++) { |
| 868 | DWORD len; |
| 869 | |
| 870 | hres = xbuf_get(buf, (LPBYTE)&len, sizeof(DWORD)); |
| 871 | if (hres) { |
| 872 | FIXME("serialize of len failed.\n"); |
| 873 | return hres; |
| 874 | } |
| 875 | rgszNames[i] = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len); |
| 876 | if (!rgszNames[i]) { |
| 877 | FIXME("heapalloc of %ld bytes failed\n", len); |
| 878 | return E_FAIL; |
| 879 | } |
| 880 | hres = xbuf_get(buf, (LPBYTE)rgszNames[i], len); |
| 881 | if (hres) { |
| 882 | FIXME("serialize of rgszNames[i] failed.\n"); |
| 883 | return hres; |
| 884 | } |
| 885 | if (debugout) TRACE_(olerelay)("%s,",relaystr(rgszNames[i])); |
| 886 | } |
| 887 | hres = xbuf_get(buf, (LPBYTE)&args[3], sizeof(DWORD)); |
| 888 | if (hres) { |
| 889 | FIXME("deserialize of lcid failed.\n"); |
| 890 | return hres; |
| 891 | } |
| 892 | if (debugout) TRACE_(olerelay)("],lcid=%04lx,rgDispId=[out])",args[3]); |
| 893 | args[4] = (DWORD)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DISPID) * cNames); |
| 894 | } else { |
| 895 | hres = xbuf_get(buf, (LPBYTE)args[4], sizeof(DISPID) * args[2]); |
| 896 | if (hres) { |
| 897 | FIXME("serialize of rgDispId failed.\n"); |
| 898 | return hres; |
| 899 | } |
| 900 | if (debugout) { |
| 901 | TRACE_(olerelay)("dispid=["); |
| 902 | for (i=0;i<args[2];i++) |
| 903 | TRACE_(olerelay)("%08lx,",((DISPID*)args[4])[i]); |
| 904 | TRACE_(olerelay)("])"); |
| 905 | } |
| 906 | } |
| 907 | return S_OK; |
| 908 | } |
| 909 | |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 910 | static HRESULT |
| 911 | serialize_LPVOID_ptr( |
| 912 | ITypeInfo *tinfo, |
| 913 | BOOL writeit, |
| 914 | BOOL debugout, |
| 915 | BOOL dealloc, |
| 916 | TYPEDESC *tdesc, |
| 917 | DWORD *arg, |
Robert Shearman | 2a54aac | 2004-09-07 20:42:26 +0000 | [diff] [blame] | 918 | marshal_state *buf) |
| 919 | { |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 920 | HRESULT hres; |
| 921 | DWORD cookie; |
| 922 | |
| 923 | if ((tdesc->vt != VT_PTR) || |
| 924 | (tdesc->u.lptdesc->vt != VT_PTR) || |
| 925 | (tdesc->u.lptdesc->u.lptdesc->vt != VT_VOID) |
| 926 | ) { |
| 927 | FIXME("ppvObject not expressed as VT_PTR -> VT_PTR -> VT_VOID?\n"); |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 928 | return E_FAIL; |
| 929 | } |
Marcus Meissner | 89feaca | 2005-03-28 10:00:49 +0000 | [diff] [blame] | 930 | cookie = (*(DWORD*)*arg) ? 0x42424242: 0x0; |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 931 | if (writeit) { |
| 932 | hres = xbuf_add(buf, (LPVOID)&cookie, sizeof(cookie)); |
| 933 | if (hres) |
| 934 | return hres; |
| 935 | } |
Marcus Meissner | 89feaca | 2005-03-28 10:00:49 +0000 | [diff] [blame] | 936 | if (!*(DWORD*)*arg) { |
Mike Hearn | d440ca4 | 2004-06-17 23:03:26 +0000 | [diff] [blame] | 937 | if (debugout) TRACE_(olerelay)("<lpvoid NULL>"); |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 938 | return S_OK; |
| 939 | } |
| 940 | if (debugout) |
Mike Hearn | d440ca4 | 2004-06-17 23:03:26 +0000 | [diff] [blame] | 941 | TRACE_(olerelay)("ppv(%p)",*(LPUNKNOWN*)*arg); |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 942 | if (writeit) { |
| 943 | hres = _marshal_interface(buf,&(buf->iid),*(LPUNKNOWN*)*arg); |
| 944 | if (hres) |
| 945 | return hres; |
| 946 | } |
| 947 | if (dealloc) |
| 948 | HeapFree(GetProcessHeap(),0,(LPVOID)*arg); |
| 949 | return S_OK; |
| 950 | } |
| 951 | |
| 952 | static HRESULT |
| 953 | serialize_DISPPARAM_ptr( |
| 954 | ITypeInfo *tinfo, |
| 955 | BOOL writeit, |
| 956 | BOOL debugout, |
| 957 | BOOL dealloc, |
| 958 | TYPEDESC *tdesc, |
| 959 | DWORD *arg, |
Robert Shearman | 2a54aac | 2004-09-07 20:42:26 +0000 | [diff] [blame] | 960 | marshal_state *buf) |
| 961 | { |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 962 | DWORD cookie; |
| 963 | HRESULT hres; |
| 964 | DISPPARAMS *disp; |
| 965 | int i; |
| 966 | |
| 967 | if ((tdesc->vt != VT_PTR) || (tdesc->u.lptdesc->vt != VT_USERDEFINED)) { |
| 968 | FIXME("DISPPARAMS not expressed as VT_PTR -> VT_USERDEFINED?\n"); |
| 969 | return E_FAIL; |
| 970 | } |
| 971 | |
| 972 | cookie = *arg ? 0x42424242 : 0x0; |
| 973 | if (writeit) { |
| 974 | hres = xbuf_add(buf,(LPBYTE)&cookie,sizeof(cookie)); |
| 975 | if (hres) |
| 976 | return hres; |
| 977 | } |
| 978 | if (!*arg) { |
Mike Hearn | d440ca4 | 2004-06-17 23:03:26 +0000 | [diff] [blame] | 979 | if (debugout) TRACE_(olerelay)("<DISPPARAMS NULL>"); |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 980 | return S_OK; |
| 981 | } |
| 982 | disp = (DISPPARAMS*)*arg; |
| 983 | if (writeit) { |
| 984 | hres = xbuf_add(buf,(LPBYTE)&disp->cArgs,sizeof(disp->cArgs)); |
| 985 | if (hres) |
| 986 | return hres; |
| 987 | } |
Mike Hearn | d440ca4 | 2004-06-17 23:03:26 +0000 | [diff] [blame] | 988 | if (debugout) TRACE_(olerelay)("D{"); |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 989 | for (i=0;i<disp->cArgs;i++) { |
| 990 | TYPEDESC vtdesc; |
| 991 | |
| 992 | vtdesc.vt = VT_VARIANT; |
| 993 | serialize_param( |
| 994 | tinfo, |
| 995 | writeit, |
| 996 | debugout, |
| 997 | dealloc, |
| 998 | &vtdesc, |
| 999 | (DWORD*)(disp->rgvarg+i), |
| 1000 | buf |
| 1001 | ); |
| 1002 | if (debugout && (i<disp->cArgs-1)) |
Mike Hearn | d440ca4 | 2004-06-17 23:03:26 +0000 | [diff] [blame] | 1003 | TRACE_(olerelay)(","); |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 1004 | } |
| 1005 | if (dealloc) |
| 1006 | HeapFree(GetProcessHeap(),0,disp->rgvarg); |
| 1007 | if (writeit) { |
| 1008 | hres = xbuf_add(buf,(LPBYTE)&disp->cNamedArgs,sizeof(disp->cNamedArgs)); |
| 1009 | if (hres) |
| 1010 | return hres; |
| 1011 | } |
Mike Hearn | d440ca4 | 2004-06-17 23:03:26 +0000 | [diff] [blame] | 1012 | if (debugout) TRACE_(olerelay)("}{"); |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 1013 | for (i=0;i<disp->cNamedArgs;i++) { |
| 1014 | TYPEDESC vtdesc; |
| 1015 | |
| 1016 | vtdesc.vt = VT_UINT; |
| 1017 | serialize_param( |
| 1018 | tinfo, |
| 1019 | writeit, |
| 1020 | debugout, |
| 1021 | dealloc, |
| 1022 | &vtdesc, |
| 1023 | (DWORD*)(disp->rgdispidNamedArgs+i), |
| 1024 | buf |
| 1025 | ); |
| 1026 | if (debugout && (i<disp->cNamedArgs-1)) |
Mike Hearn | d440ca4 | 2004-06-17 23:03:26 +0000 | [diff] [blame] | 1027 | TRACE_(olerelay)(","); |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 1028 | } |
Mike Hearn | d440ca4 | 2004-06-17 23:03:26 +0000 | [diff] [blame] | 1029 | if (debugout) TRACE_(olerelay)("}"); |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 1030 | if (dealloc) { |
| 1031 | HeapFree(GetProcessHeap(),0,disp->rgdispidNamedArgs); |
| 1032 | HeapFree(GetProcessHeap(),0,disp); |
| 1033 | } |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1034 | return S_OK; |
| 1035 | } |
| 1036 | |
| 1037 | static HRESULT |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 1038 | deserialize_param( |
| 1039 | ITypeInfo *tinfo, |
| 1040 | BOOL readit, |
| 1041 | BOOL debugout, |
| 1042 | BOOL alloc, |
| 1043 | TYPEDESC *tdesc, |
| 1044 | DWORD *arg, |
Robert Shearman | 2a54aac | 2004-09-07 20:42:26 +0000 | [diff] [blame] | 1045 | marshal_state *buf) |
| 1046 | { |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1047 | HRESULT hres = S_OK; |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1048 | |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 1049 | TRACE("vt %d at %p\n",tdesc->vt,arg); |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1050 | |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 1051 | while (1) { |
| 1052 | switch (tdesc->vt) { |
| 1053 | case VT_EMPTY: |
Mike Hearn | d440ca4 | 2004-06-17 23:03:26 +0000 | [diff] [blame] | 1054 | if (debugout) TRACE_(olerelay)("<empty>"); |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 1055 | return S_OK; |
| 1056 | case VT_NULL: |
Mike Hearn | d440ca4 | 2004-06-17 23:03:26 +0000 | [diff] [blame] | 1057 | if (debugout) TRACE_(olerelay)("<null>"); |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 1058 | return S_OK; |
| 1059 | case VT_VARIANT: { |
| 1060 | VARIANT *vt = (VARIANT*)arg; |
| 1061 | |
| 1062 | if (readit) { |
| 1063 | DWORD vttype; |
| 1064 | TYPEDESC tdesc2; |
| 1065 | hres = xbuf_get(buf,(LPBYTE)&vttype,sizeof(vttype)); |
| 1066 | if (hres) { |
| 1067 | FIXME("vt type not read?\n"); |
| 1068 | return hres; |
| 1069 | } |
| 1070 | memset(&tdesc2,0,sizeof(tdesc2)); |
| 1071 | tdesc2.vt = vttype; |
| 1072 | V_VT(vt) = vttype; |
Mike Hearn | d440ca4 | 2004-06-17 23:03:26 +0000 | [diff] [blame] | 1073 | if (debugout) TRACE_(olerelay)("Vt(%ld)(",vttype); |
Mike McCormack | a04b77d | 2005-08-08 18:38:29 +0000 | [diff] [blame] | 1074 | hres = deserialize_param(tinfo, readit, debugout, alloc, &tdesc2, (DWORD*)&(V_I4(vt)), buf); |
Mike Hearn | d440ca4 | 2004-06-17 23:03:26 +0000 | [diff] [blame] | 1075 | TRACE_(olerelay)(")"); |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 1076 | return hres; |
| 1077 | } else { |
| 1078 | VariantInit(vt); |
| 1079 | return S_OK; |
| 1080 | } |
| 1081 | } |
| 1082 | case VT_ERROR: |
Alexandre Julliard | 232760d | 2005-03-14 10:09:11 +0000 | [diff] [blame] | 1083 | case VT_BOOL: |
| 1084 | case VT_I4: |
Alexandre Julliard | 232760d | 2005-03-14 10:09:11 +0000 | [diff] [blame] | 1085 | case VT_UINT: |
| 1086 | case VT_R4: |
| 1087 | case VT_UI4: |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 1088 | if (readit) { |
| 1089 | hres = xbuf_get(buf,(LPBYTE)arg,sizeof(DWORD)); |
Mike Hearn | 64eac75 | 2005-01-27 11:11:32 +0000 | [diff] [blame] | 1090 | if (hres) ERR("Failed to read integer 4 byte\n"); |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 1091 | } |
Mike Hearn | d440ca4 | 2004-06-17 23:03:26 +0000 | [diff] [blame] | 1092 | if (debugout) TRACE_(olerelay)("%lx",*arg); |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 1093 | return hres; |
Marcus Meissner | c91df67 | 2005-03-27 18:17:19 +0000 | [diff] [blame] | 1094 | case VT_I2: |
| 1095 | case VT_UI2: |
| 1096 | if (readit) { |
| 1097 | DWORD x; |
| 1098 | hres = xbuf_get(buf,(LPBYTE)&x,sizeof(DWORD)); |
| 1099 | if (hres) ERR("Failed to read integer 4 byte\n"); |
| 1100 | memcpy(arg,&x,2); |
| 1101 | } |
| 1102 | if (debugout) TRACE_(olerelay)("%04lx",*arg & 0xffff); |
| 1103 | return hres; |
| 1104 | case VT_I1: |
| 1105 | case VT_UI1: |
| 1106 | if (readit) { |
| 1107 | DWORD x; |
| 1108 | hres = xbuf_get(buf,(LPBYTE)&x,sizeof(DWORD)); |
| 1109 | if (hres) ERR("Failed to read integer 4 byte\n"); |
| 1110 | memcpy(arg,&x,1); |
| 1111 | } |
| 1112 | if (debugout) TRACE_(olerelay)("%02lx",*arg & 0xff); |
| 1113 | return hres; |
Marcus Meissner | 4b5f3c6 | 2005-03-29 11:29:11 +0000 | [diff] [blame] | 1114 | case VT_I4|VT_BYREF: |
| 1115 | hres = S_OK; |
| 1116 | if (alloc) |
| 1117 | *arg = (DWORD)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DWORD)); |
| 1118 | if (readit) { |
| 1119 | hres = xbuf_get(buf,(LPBYTE)*arg,sizeof(DWORD)); |
| 1120 | if (hres) ERR("Failed to read integer 4 byte\n"); |
| 1121 | } |
| 1122 | if (debugout) TRACE_(olerelay)("&0x%lx",*(DWORD*)*arg); |
| 1123 | return hres; |
Alexandre Julliard | 232760d | 2005-03-14 10:09:11 +0000 | [diff] [blame] | 1124 | case VT_BSTR|VT_BYREF: { |
| 1125 | BSTR **bstr = (BSTR **)arg; |
| 1126 | WCHAR *str; |
| 1127 | DWORD len; |
| 1128 | |
| 1129 | if (readit) { |
| 1130 | hres = xbuf_get(buf,(LPBYTE)&len,sizeof(DWORD)); |
| 1131 | if (hres) { |
| 1132 | ERR("failed to read bstr klen\n"); |
| 1133 | return hres; |
| 1134 | } |
| 1135 | if (len == -1) { |
Marcus Meissner | 4b5f3c6 | 2005-03-29 11:29:11 +0000 | [diff] [blame] | 1136 | *bstr = CoTaskMemAlloc(sizeof(BSTR *)); |
| 1137 | **bstr = NULL; |
Alexandre Julliard | 232760d | 2005-03-14 10:09:11 +0000 | [diff] [blame] | 1138 | if (debugout) TRACE_(olerelay)("<bstr NULL>"); |
| 1139 | } else { |
Robert Shearman | d8780c7 | 2005-07-19 19:42:50 +0000 | [diff] [blame] | 1140 | str = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,(len+1)*sizeof(WCHAR)); |
| 1141 | hres = xbuf_get(buf,(LPBYTE)str,len*sizeof(WCHAR)); |
Alexandre Julliard | 232760d | 2005-03-14 10:09:11 +0000 | [diff] [blame] | 1142 | if (hres) { |
| 1143 | ERR("Failed to read BSTR.\n"); |
| 1144 | return hres; |
| 1145 | } |
| 1146 | *bstr = CoTaskMemAlloc(sizeof(BSTR *)); |
| 1147 | **bstr = SysAllocStringLen(str,len); |
| 1148 | if (debugout) TRACE_(olerelay)("%s",relaystr(str)); |
| 1149 | HeapFree(GetProcessHeap(),0,str); |
| 1150 | } |
| 1151 | } else { |
| 1152 | *bstr = NULL; |
| 1153 | } |
| 1154 | return S_OK; |
| 1155 | } |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 1156 | case VT_BSTR: { |
| 1157 | WCHAR *str; |
| 1158 | DWORD len; |
| 1159 | |
| 1160 | if (readit) { |
| 1161 | hres = xbuf_get(buf,(LPBYTE)&len,sizeof(DWORD)); |
| 1162 | if (hres) { |
Mike Hearn | 64eac75 | 2005-01-27 11:11:32 +0000 | [diff] [blame] | 1163 | ERR("failed to read bstr klen\n"); |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 1164 | return hres; |
| 1165 | } |
| 1166 | if (len == -1) { |
| 1167 | *arg = 0; |
Mike Hearn | d440ca4 | 2004-06-17 23:03:26 +0000 | [diff] [blame] | 1168 | if (debugout) TRACE_(olerelay)("<bstr NULL>"); |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 1169 | } else { |
Robert Shearman | d8780c7 | 2005-07-19 19:42:50 +0000 | [diff] [blame] | 1170 | str = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,(len+1)*sizeof(WCHAR)); |
| 1171 | hres = xbuf_get(buf,(LPBYTE)str,len*sizeof(WCHAR)); |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 1172 | if (hres) { |
Mike Hearn | 64eac75 | 2005-01-27 11:11:32 +0000 | [diff] [blame] | 1173 | ERR("Failed to read BSTR.\n"); |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 1174 | return hres; |
| 1175 | } |
| 1176 | *arg = (DWORD)SysAllocStringLen(str,len); |
Mike Hearn | d440ca4 | 2004-06-17 23:03:26 +0000 | [diff] [blame] | 1177 | if (debugout) TRACE_(olerelay)("%s",relaystr(str)); |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 1178 | HeapFree(GetProcessHeap(),0,str); |
| 1179 | } |
| 1180 | } else { |
| 1181 | *arg = 0; |
| 1182 | } |
| 1183 | return S_OK; |
| 1184 | } |
| 1185 | case VT_PTR: { |
| 1186 | DWORD cookie; |
Marcus Meissner | e6260a3 | 2005-03-27 17:51:59 +0000 | [diff] [blame] | 1187 | BOOL derefhere = 0; |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 1188 | |
| 1189 | derefhere = (tdesc->u.lptdesc->vt != VT_USERDEFINED); |
Marcus Meissner | e6260a3 | 2005-03-27 17:51:59 +0000 | [diff] [blame] | 1190 | /* read it in all cases, we need to know if we have |
| 1191 | * NULL pointer or not. |
| 1192 | */ |
| 1193 | hres = xbuf_get(buf,(LPBYTE)&cookie,sizeof(cookie)); |
| 1194 | if (hres) { |
| 1195 | ERR("Failed to load pointer cookie.\n"); |
| 1196 | return hres; |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 1197 | } |
Marcus Meissner | e6260a3 | 2005-03-27 17:51:59 +0000 | [diff] [blame] | 1198 | if (cookie != 0x42424242) { |
| 1199 | /* we read a NULL ptr from the remote side */ |
| 1200 | if (debugout) TRACE_(olerelay)("NULL"); |
| 1201 | *arg = 0; |
| 1202 | return S_OK; |
| 1203 | } |
| 1204 | if (debugout) TRACE_(olerelay)("*"); |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 1205 | if (alloc) { |
Marcus Meissner | e6260a3 | 2005-03-27 17:51:59 +0000 | [diff] [blame] | 1206 | /* Allocate space for the referenced struct */ |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 1207 | if (derefhere) |
| 1208 | *arg=(DWORD)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,_xsize(tdesc->u.lptdesc)); |
| 1209 | } |
| 1210 | if (derefhere) |
| 1211 | return deserialize_param(tinfo, readit, debugout, alloc, tdesc->u.lptdesc, (LPDWORD)*arg, buf); |
| 1212 | else |
| 1213 | return deserialize_param(tinfo, readit, debugout, alloc, tdesc->u.lptdesc, arg, buf); |
| 1214 | } |
| 1215 | case VT_UNKNOWN: |
| 1216 | /* FIXME: UNKNOWN is unknown ..., but allocate 4 byte for it */ |
| 1217 | if (alloc) |
| 1218 | *arg=(DWORD)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DWORD)); |
| 1219 | hres = S_OK; |
| 1220 | if (readit) |
| 1221 | hres = _unmarshal_interface(buf,&IID_IUnknown,(LPUNKNOWN*)arg); |
| 1222 | if (debugout) |
Mike Hearn | d440ca4 | 2004-06-17 23:03:26 +0000 | [diff] [blame] | 1223 | TRACE_(olerelay)("unk(%p)",arg); |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 1224 | return hres; |
| 1225 | case VT_DISPATCH: |
| 1226 | hres = S_OK; |
| 1227 | if (readit) |
| 1228 | hres = _unmarshal_interface(buf,&IID_IDispatch,(LPUNKNOWN*)arg); |
| 1229 | if (debugout) |
Mike Hearn | d440ca4 | 2004-06-17 23:03:26 +0000 | [diff] [blame] | 1230 | TRACE_(olerelay)("idisp(%p)",arg); |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 1231 | return hres; |
| 1232 | case VT_VOID: |
Mike Hearn | d440ca4 | 2004-06-17 23:03:26 +0000 | [diff] [blame] | 1233 | if (debugout) TRACE_(olerelay)("<void>"); |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 1234 | return S_OK; |
| 1235 | case VT_USERDEFINED: { |
| 1236 | ITypeInfo *tinfo2; |
| 1237 | TYPEATTR *tattr; |
| 1238 | |
| 1239 | hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.hreftype,&tinfo2); |
| 1240 | if (hres) { |
Mike Hearn | 64eac75 | 2005-01-27 11:11:32 +0000 | [diff] [blame] | 1241 | ERR("Could not get typeinfo of hreftype %lx for VT_USERDEFINED.\n",tdesc->u.hreftype); |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 1242 | return hres; |
| 1243 | } |
| 1244 | hres = ITypeInfo_GetTypeAttr(tinfo2,&tattr); |
| 1245 | if (hres) { |
Mike Hearn | 64eac75 | 2005-01-27 11:11:32 +0000 | [diff] [blame] | 1246 | ERR("Could not get typeattr in VT_USERDEFINED.\n"); |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 1247 | } else { |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 1248 | switch (tattr->typekind) { |
Marcus Meissner | 26ffca4 | 2002-12-12 22:25:07 +0000 | [diff] [blame] | 1249 | case TKIND_DISPATCH: |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 1250 | case TKIND_INTERFACE: |
| 1251 | if (readit) |
| 1252 | hres = _unmarshal_interface(buf,&(tattr->guid),(LPUNKNOWN*)arg); |
| 1253 | break; |
| 1254 | case TKIND_RECORD: { |
| 1255 | int i; |
| 1256 | |
Alexandre Julliard | 232760d | 2005-03-14 10:09:11 +0000 | [diff] [blame] | 1257 | if (alloc) |
| 1258 | *arg = (DWORD)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,tattr->cbSizeInstance); |
| 1259 | |
Mike Hearn | d440ca4 | 2004-06-17 23:03:26 +0000 | [diff] [blame] | 1260 | if (debugout) TRACE_(olerelay)("{"); |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 1261 | for (i=0;i<tattr->cVars;i++) { |
| 1262 | VARDESC *vdesc; |
| 1263 | |
| 1264 | hres = ITypeInfo2_GetVarDesc(tinfo2, i, &vdesc); |
| 1265 | if (hres) { |
Mike Hearn | 64eac75 | 2005-01-27 11:11:32 +0000 | [diff] [blame] | 1266 | ERR("Could not get vardesc of %d\n",i); |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 1267 | return hres; |
| 1268 | } |
| 1269 | hres = deserialize_param( |
| 1270 | tinfo2, |
| 1271 | readit, |
| 1272 | debugout, |
| 1273 | alloc, |
| 1274 | &vdesc->elemdescVar.tdesc, |
| 1275 | (DWORD*)(((LPBYTE)*arg)+vdesc->u.oInst), |
| 1276 | buf |
| 1277 | ); |
Mike Hearn | d440ca4 | 2004-06-17 23:03:26 +0000 | [diff] [blame] | 1278 | if (debugout && (i<tattr->cVars-1)) TRACE_(olerelay)(","); |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 1279 | } |
| 1280 | if (buf->thisisiid && (tattr->cbSizeInstance==sizeof(GUID))) |
| 1281 | memcpy(&(buf->iid),(LPBYTE)*arg,sizeof(buf->iid)); |
Mike Hearn | d440ca4 | 2004-06-17 23:03:26 +0000 | [diff] [blame] | 1282 | if (debugout) TRACE_(olerelay)("}"); |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 1283 | break; |
| 1284 | } |
Robert Shearman | d2e2e85 | 2005-07-19 19:13:23 +0000 | [diff] [blame] | 1285 | case TKIND_ALIAS: |
| 1286 | return deserialize_param(tinfo2,readit,debugout,alloc,&tattr->tdescAlias,arg,buf); |
| 1287 | case TKIND_ENUM: |
| 1288 | if (readit) { |
| 1289 | hres = xbuf_get(buf,(LPBYTE)arg,sizeof(DWORD)); |
| 1290 | if (hres) ERR("Failed to read enum (4 byte)\n"); |
| 1291 | } |
| 1292 | if (debugout) TRACE_(olerelay)("%lx",*arg); |
| 1293 | return hres; |
Marcus Meissner | 26ffca4 | 2002-12-12 22:25:07 +0000 | [diff] [blame] | 1294 | default: |
| 1295 | ERR("Unhandled typekind %d\n",tattr->typekind); |
| 1296 | hres = E_FAIL; |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 1297 | break; |
| 1298 | } |
| 1299 | } |
| 1300 | if (hres) |
Mike Hearn | 64eac75 | 2005-01-27 11:11:32 +0000 | [diff] [blame] | 1301 | ERR("failed to stuballoc in TKIND_RECORD.\n"); |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 1302 | ITypeInfo_Release(tinfo2); |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1303 | return hres; |
| 1304 | } |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 1305 | case VT_CARRAY: { |
| 1306 | /* arg is pointing to the start of the array. */ |
| 1307 | ARRAYDESC *adesc = tdesc->u.lpadesc; |
| 1308 | int arrsize,i; |
| 1309 | arrsize = 1; |
| 1310 | if (adesc->cDims > 1) FIXME("cDims > 1 in VT_CARRAY. Does it work?\n"); |
| 1311 | for (i=0;i<adesc->cDims;i++) |
| 1312 | arrsize *= adesc->rgbounds[i].cElements; |
| 1313 | for (i=0;i<arrsize;i++) |
| 1314 | deserialize_param( |
| 1315 | tinfo, |
| 1316 | readit, |
| 1317 | debugout, |
| 1318 | alloc, |
| 1319 | &adesc->tdescElem, |
| 1320 | (DWORD*)((LPBYTE)(arg)+i*_xsize(&adesc->tdescElem)), |
| 1321 | buf |
| 1322 | ); |
| 1323 | return S_OK; |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1324 | } |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1325 | default: |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 1326 | ERR("No handler for VT type %d!\n",tdesc->vt); |
| 1327 | return S_OK; |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1328 | } |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 1329 | } |
| 1330 | } |
| 1331 | |
| 1332 | static HRESULT |
| 1333 | deserialize_LPVOID_ptr( |
| 1334 | ITypeInfo *tinfo, |
| 1335 | BOOL readit, |
| 1336 | BOOL debugout, |
| 1337 | BOOL alloc, |
| 1338 | TYPEDESC *tdesc, |
| 1339 | DWORD *arg, |
| 1340 | marshal_state *buf |
| 1341 | ) { |
| 1342 | HRESULT hres; |
| 1343 | DWORD cookie; |
| 1344 | |
| 1345 | if ((tdesc->vt != VT_PTR) || |
| 1346 | (tdesc->u.lptdesc->vt != VT_PTR) || |
| 1347 | (tdesc->u.lptdesc->u.lptdesc->vt != VT_VOID) |
| 1348 | ) { |
| 1349 | FIXME("ppvObject not expressed as VT_PTR -> VT_PTR -> VT_VOID?\n"); |
| 1350 | return E_FAIL; |
| 1351 | } |
| 1352 | if (alloc) |
| 1353 | *arg=(DWORD)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(LPVOID)); |
| 1354 | if (readit) { |
| 1355 | hres = xbuf_get(buf, (LPVOID)&cookie, sizeof(cookie)); |
| 1356 | if (hres) |
| 1357 | return hres; |
| 1358 | if (cookie != 0x42424242) { |
| 1359 | *(DWORD*)*arg = 0; |
Mike Hearn | d440ca4 | 2004-06-17 23:03:26 +0000 | [diff] [blame] | 1360 | if (debugout) TRACE_(olerelay)("<lpvoid NULL>"); |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 1361 | return S_OK; |
| 1362 | } |
| 1363 | } |
| 1364 | if (readit) { |
| 1365 | hres = _unmarshal_interface(buf,&buf->iid,(LPUNKNOWN*)*arg); |
Marcus Meissner | e6260a3 | 2005-03-27 17:51:59 +0000 | [diff] [blame] | 1366 | if (hres) { |
| 1367 | FIXME("_unmarshal_interface of %s , %p failed with %lx\n", debugstr_guid(&buf->iid), (LPUNKNOWN*)*arg, hres); |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 1368 | return hres; |
Marcus Meissner | e6260a3 | 2005-03-27 17:51:59 +0000 | [diff] [blame] | 1369 | } |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 1370 | } |
Mike Hearn | d440ca4 | 2004-06-17 23:03:26 +0000 | [diff] [blame] | 1371 | if (debugout) TRACE_(olerelay)("ppv(%p)",(LPVOID)*arg); |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 1372 | return S_OK; |
| 1373 | } |
| 1374 | |
| 1375 | static HRESULT |
| 1376 | deserialize_DISPPARAM_ptr( |
| 1377 | ITypeInfo *tinfo, |
| 1378 | BOOL readit, |
| 1379 | BOOL debugout, |
| 1380 | BOOL alloc, |
| 1381 | TYPEDESC *tdesc, |
| 1382 | DWORD *arg, |
Robert Shearman | 2a54aac | 2004-09-07 20:42:26 +0000 | [diff] [blame] | 1383 | marshal_state *buf) |
| 1384 | { |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 1385 | DWORD cookie; |
| 1386 | DISPPARAMS *disps; |
| 1387 | HRESULT hres; |
| 1388 | int i; |
| 1389 | |
| 1390 | if ((tdesc->vt != VT_PTR) || (tdesc->u.lptdesc->vt != VT_USERDEFINED)) { |
| 1391 | FIXME("DISPPARAMS not expressed as VT_PTR -> VT_USERDEFINED?\n"); |
| 1392 | return E_FAIL; |
| 1393 | } |
| 1394 | if (readit) { |
| 1395 | hres = xbuf_get(buf,(LPBYTE)&cookie,sizeof(cookie)); |
| 1396 | if (hres) |
| 1397 | return hres; |
| 1398 | if (cookie == 0) { |
| 1399 | *arg = 0; |
Mike Hearn | d440ca4 | 2004-06-17 23:03:26 +0000 | [diff] [blame] | 1400 | if (debugout) TRACE_(olerelay)("<DISPPARAMS NULL>"); |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 1401 | return S_OK; |
| 1402 | } |
| 1403 | } |
| 1404 | if (alloc) |
| 1405 | *arg = (DWORD)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DISPPARAMS)); |
| 1406 | disps = (DISPPARAMS*)*arg; |
| 1407 | if (!readit) |
| 1408 | return S_OK; |
| 1409 | hres = xbuf_get(buf, (LPBYTE)&disps->cArgs, sizeof(disps->cArgs)); |
| 1410 | if (hres) |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1411 | return hres; |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 1412 | if (alloc) |
| 1413 | disps->rgvarg = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(VARIANT)*disps->cArgs); |
Mike Hearn | d440ca4 | 2004-06-17 23:03:26 +0000 | [diff] [blame] | 1414 | if (debugout) TRACE_(olerelay)("D{"); |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 1415 | for (i=0; i< disps->cArgs; i++) { |
| 1416 | TYPEDESC vdesc; |
| 1417 | |
| 1418 | vdesc.vt = VT_VARIANT; |
| 1419 | hres = deserialize_param( |
| 1420 | tinfo, |
| 1421 | readit, |
| 1422 | debugout, |
| 1423 | alloc, |
| 1424 | &vdesc, |
| 1425 | (DWORD*)(disps->rgvarg+i), |
| 1426 | buf |
| 1427 | ); |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1428 | } |
Mike Hearn | d440ca4 | 2004-06-17 23:03:26 +0000 | [diff] [blame] | 1429 | if (debugout) TRACE_(olerelay)("}{"); |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 1430 | hres = xbuf_get(buf, (LPBYTE)&disps->cNamedArgs, sizeof(disps->cNamedArgs)); |
| 1431 | if (hres) |
| 1432 | return hres; |
| 1433 | if (disps->cNamedArgs) { |
| 1434 | if (alloc) |
| 1435 | disps->rgdispidNamedArgs = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DISPID)*disps->cNamedArgs); |
| 1436 | for (i=0; i< disps->cNamedArgs; i++) { |
| 1437 | TYPEDESC vdesc; |
| 1438 | |
| 1439 | vdesc.vt = VT_UINT; |
| 1440 | hres = deserialize_param( |
| 1441 | tinfo, |
| 1442 | readit, |
| 1443 | debugout, |
| 1444 | alloc, |
| 1445 | &vdesc, |
| 1446 | (DWORD*)(disps->rgdispidNamedArgs+i), |
| 1447 | buf |
| 1448 | ); |
Mike Hearn | d440ca4 | 2004-06-17 23:03:26 +0000 | [diff] [blame] | 1449 | if (debugout && i<(disps->cNamedArgs-1)) TRACE_(olerelay)(","); |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 1450 | } |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1451 | } |
Mike Hearn | d440ca4 | 2004-06-17 23:03:26 +0000 | [diff] [blame] | 1452 | if (debugout) TRACE_(olerelay)("}"); |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1453 | return S_OK; |
| 1454 | } |
| 1455 | |
| 1456 | /* Searches function, also in inherited interfaces */ |
| 1457 | static HRESULT |
| 1458 | _get_funcdesc( |
Robert Shearman | c6296c4 | 2005-06-01 11:03:40 +0000 | [diff] [blame] | 1459 | ITypeInfo *tinfo, int iMethod, ITypeInfo **tactual, FUNCDESC **fdesc, BSTR *iname, BSTR *fname) |
Robert Shearman | 2a54aac | 2004-09-07 20:42:26 +0000 | [diff] [blame] | 1460 | { |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1461 | int i = 0, j = 0; |
| 1462 | HRESULT hres; |
| 1463 | |
| 1464 | if (fname) *fname = NULL; |
| 1465 | if (iname) *iname = NULL; |
| 1466 | |
Robert Shearman | c6296c4 | 2005-06-01 11:03:40 +0000 | [diff] [blame] | 1467 | *tactual = tinfo; |
| 1468 | ITypeInfo_AddRef(*tactual); |
| 1469 | |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1470 | while (1) { |
| 1471 | hres = ITypeInfo_GetFuncDesc(tinfo, i, fdesc); |
| 1472 | if (hres) { |
| 1473 | ITypeInfo *tinfo2; |
| 1474 | HREFTYPE href; |
| 1475 | TYPEATTR *attr; |
| 1476 | |
| 1477 | hres = ITypeInfo_GetTypeAttr(tinfo, &attr); |
| 1478 | if (hres) { |
Mike Hearn | 64eac75 | 2005-01-27 11:11:32 +0000 | [diff] [blame] | 1479 | ERR("GetTypeAttr failed with %lx\n",hres); |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1480 | return hres; |
| 1481 | } |
| 1482 | /* Not found, so look in inherited ifaces. */ |
| 1483 | for (j=0;j<attr->cImplTypes;j++) { |
| 1484 | hres = ITypeInfo_GetRefTypeOfImplType(tinfo, j, &href); |
| 1485 | if (hres) { |
Mike Hearn | 64eac75 | 2005-01-27 11:11:32 +0000 | [diff] [blame] | 1486 | ERR("Did not find a reftype for interface offset %d?\n",j); |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1487 | break; |
| 1488 | } |
| 1489 | hres = ITypeInfo_GetRefTypeInfo(tinfo, href, &tinfo2); |
| 1490 | if (hres) { |
Mike Hearn | 64eac75 | 2005-01-27 11:11:32 +0000 | [diff] [blame] | 1491 | ERR("Did not find a typeinfo for reftype %ld?\n",href); |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1492 | continue; |
| 1493 | } |
Robert Shearman | c6296c4 | 2005-06-01 11:03:40 +0000 | [diff] [blame] | 1494 | hres = _get_funcdesc(tinfo2,iMethod,tactual,fdesc,iname,fname); |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1495 | ITypeInfo_Release(tinfo2); |
| 1496 | if (!hres) return S_OK; |
| 1497 | } |
Mike Hearn | 6c093f3 | 2005-01-26 19:42:17 +0000 | [diff] [blame] | 1498 | return hres; |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1499 | } |
| 1500 | if (((*fdesc)->oVft/4) == iMethod) { |
| 1501 | if (fname) |
| 1502 | ITypeInfo_GetDocumentation(tinfo,(*fdesc)->memid,fname,NULL,NULL,NULL); |
| 1503 | if (iname) |
| 1504 | ITypeInfo_GetDocumentation(tinfo,-1,iname,NULL,NULL,NULL); |
| 1505 | return S_OK; |
| 1506 | } |
| 1507 | i++; |
| 1508 | } |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1509 | } |
| 1510 | |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1511 | static DWORD |
Robert Shearman | 2a54aac | 2004-09-07 20:42:26 +0000 | [diff] [blame] | 1512 | xCall(LPVOID retptr, int method, TMProxyImpl *tpinfo /*, args */) |
| 1513 | { |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1514 | DWORD *args = ((DWORD*)&tpinfo)+1, *xargs; |
| 1515 | FUNCDESC *fdesc; |
| 1516 | HRESULT hres; |
| 1517 | int i, relaydeb = TRACE_ON(olerelay); |
| 1518 | marshal_state buf; |
| 1519 | RPCOLEMESSAGE msg; |
| 1520 | ULONG status; |
| 1521 | BSTR fname,iname; |
| 1522 | BSTR names[10]; |
Mike McCormack | a04b77d | 2005-08-08 18:38:29 +0000 | [diff] [blame] | 1523 | UINT nrofnames; |
Marcus Meissner | e6260a3 | 2005-03-27 17:51:59 +0000 | [diff] [blame] | 1524 | int is_idispatch_getidsofnames = 0; |
Marcus Meissner | 89feaca | 2005-03-28 10:00:49 +0000 | [diff] [blame] | 1525 | DWORD remoteresult = 0; |
Robert Shearman | c6296c4 | 2005-06-01 11:03:40 +0000 | [diff] [blame] | 1526 | ITypeInfo *tinfo; |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1527 | |
Robert Shearman | 2a54aac | 2004-09-07 20:42:26 +0000 | [diff] [blame] | 1528 | EnterCriticalSection(&tpinfo->crit); |
| 1529 | |
Robert Shearman | c6296c4 | 2005-06-01 11:03:40 +0000 | [diff] [blame] | 1530 | hres = _get_funcdesc(tpinfo->tinfo,method,&tinfo,&fdesc,&iname,&fname); |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1531 | if (hres) { |
| 1532 | ERR("Did not find typeinfo/funcdesc entry for method %d!\n",method); |
Robert Shearman | c6296c4 | 2005-06-01 11:03:40 +0000 | [diff] [blame] | 1533 | ITypeInfo_Release(tinfo); |
Robert Shearman | 2a54aac | 2004-09-07 20:42:26 +0000 | [diff] [blame] | 1534 | LeaveCriticalSection(&tpinfo->crit); |
| 1535 | return E_FAIL; |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1536 | } |
| 1537 | |
Robert Shearman | 6794279 | 2004-12-14 11:44:11 +0000 | [diff] [blame] | 1538 | if (!tpinfo->chanbuf) |
| 1539 | { |
| 1540 | WARN("Tried to use disconnected proxy\n"); |
Robert Shearman | c6296c4 | 2005-06-01 11:03:40 +0000 | [diff] [blame] | 1541 | ITypeInfo_Release(tinfo); |
Robert Shearman | 6794279 | 2004-12-14 11:44:11 +0000 | [diff] [blame] | 1542 | LeaveCriticalSection(&tpinfo->crit); |
| 1543 | return RPC_E_DISCONNECTED; |
| 1544 | } |
| 1545 | |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1546 | if (relaydeb) { |
Mike Hearn | 86cc2d5 | 2004-06-23 00:10:29 +0000 | [diff] [blame] | 1547 | TRACE_(olerelay)("->"); |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1548 | if (iname) |
Mike Hearn | d440ca4 | 2004-06-17 23:03:26 +0000 | [diff] [blame] | 1549 | TRACE_(olerelay)("%s:",relaystr(iname)); |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1550 | if (fname) |
Mike Hearn | d440ca4 | 2004-06-17 23:03:26 +0000 | [diff] [blame] | 1551 | TRACE_(olerelay)("%s(%d)",relaystr(fname),method); |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1552 | else |
Mike Hearn | d440ca4 | 2004-06-17 23:03:26 +0000 | [diff] [blame] | 1553 | TRACE_(olerelay)("%d",method); |
| 1554 | TRACE_(olerelay)("("); |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1555 | } |
Marcus Meissner | e6260a3 | 2005-03-27 17:51:59 +0000 | [diff] [blame] | 1556 | if (iname && fname && !lstrcmpW(iname,IDispatchW) && !lstrcmpW(fname,GetIDsOfNamesW)) |
| 1557 | is_idispatch_getidsofnames = 1; |
| 1558 | |
| 1559 | if (iname) SysFreeString(iname); |
| 1560 | if (fname) SysFreeString(fname); |
| 1561 | |
| 1562 | memset(&buf,0,sizeof(buf)); |
| 1563 | buf.iid = IID_IUnknown; |
| 1564 | |
| 1565 | /* Special IDispatch::GetIDsOfNames() serializer */ |
| 1566 | if (is_idispatch_getidsofnames) { |
| 1567 | hres = serialize_IDispatch_GetIDsOfNames(TRUE,relaydeb,args,&buf); |
| 1568 | if (hres != S_OK) { |
| 1569 | FIXME("serialize of IDispatch::GetIDsOfNames failed!\n"); |
Robert Shearman | c6296c4 | 2005-06-01 11:03:40 +0000 | [diff] [blame] | 1570 | ITypeInfo_Release(tinfo); |
| 1571 | LeaveCriticalSection(&tpinfo->crit); |
Marcus Meissner | e6260a3 | 2005-03-27 17:51:59 +0000 | [diff] [blame] | 1572 | return hres; |
| 1573 | } |
| 1574 | goto afterserialize; |
| 1575 | } |
| 1576 | |
| 1577 | /* special QueryInterface serialize */ |
| 1578 | if (method == 0) { |
| 1579 | xbuf_add(&buf,(LPBYTE)args[0],sizeof(IID)); |
| 1580 | if (relaydeb) TRACE_(olerelay)("riid=%s,[out])",debugstr_guid((REFIID)args[0])); |
| 1581 | goto afterserialize; |
| 1582 | } |
| 1583 | |
| 1584 | /* normal typelib driven serializing */ |
| 1585 | |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1586 | /* Need them for hack below */ |
| 1587 | memset(names,0,sizeof(names)); |
Robert Shearman | c6296c4 | 2005-06-01 11:03:40 +0000 | [diff] [blame] | 1588 | if (ITypeInfo_GetNames(tinfo,fdesc->memid,names,sizeof(names)/sizeof(names[0]),&nrofnames)) |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 1589 | nrofnames = 0; |
| 1590 | if (nrofnames > sizeof(names)/sizeof(names[0])) |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1591 | ERR("Need more names!\n"); |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 1592 | |
Marcus Meissner | e6260a3 | 2005-03-27 17:51:59 +0000 | [diff] [blame] | 1593 | xargs = args; |
| 1594 | for (i=0;i<fdesc->cParams;i++) { |
| 1595 | ELEMDESC *elem = fdesc->lprgelemdescParam+i; |
| 1596 | BOOL isserialized = FALSE; |
| 1597 | if (relaydeb) { |
| 1598 | if (i) TRACE_(olerelay)(","); |
| 1599 | if (i+1<nrofnames && names[i+1]) |
| 1600 | TRACE_(olerelay)("%s=",relaystr(names[i+1])); |
| 1601 | } |
| 1602 | /* No need to marshal other data than FIN and any VT_PTR. */ |
| 1603 | if (!(elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN) && (elem->tdesc.vt != VT_PTR)) { |
| 1604 | xargs+=_argsize(elem->tdesc.vt); |
| 1605 | if (relaydeb) TRACE_(olerelay)("[out]"); |
| 1606 | continue; |
| 1607 | } |
| 1608 | if (((i+1)<nrofnames) && !IsBadStringPtrW(names[i+1],1)) { |
| 1609 | /* If the parameter is 'riid', we use it as interface IID |
| 1610 | * for a later ppvObject serialization. |
| 1611 | */ |
| 1612 | buf.thisisiid = !lstrcmpW(names[i+1],riidW); |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 1613 | |
Marcus Meissner | e6260a3 | 2005-03-27 17:51:59 +0000 | [diff] [blame] | 1614 | /* DISPPARAMS* needs special serializer */ |
| 1615 | if (!lstrcmpW(names[i+1],pdispparamsW)) { |
| 1616 | hres = serialize_DISPPARAM_ptr( |
Robert Shearman | c6296c4 | 2005-06-01 11:03:40 +0000 | [diff] [blame] | 1617 | tinfo, |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 1618 | elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN, |
| 1619 | relaydeb, |
| 1620 | FALSE, |
| 1621 | &elem->tdesc, |
| 1622 | xargs, |
| 1623 | &buf |
| 1624 | ); |
Marcus Meissner | e6260a3 | 2005-03-27 17:51:59 +0000 | [diff] [blame] | 1625 | isserialized = TRUE; |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1626 | } |
Marcus Meissner | e6260a3 | 2005-03-27 17:51:59 +0000 | [diff] [blame] | 1627 | if (!lstrcmpW(names[i+1],ppvObjectW)) { |
| 1628 | hres = serialize_LPVOID_ptr( |
Robert Shearman | c6296c4 | 2005-06-01 11:03:40 +0000 | [diff] [blame] | 1629 | tinfo, |
Marcus Meissner | e6260a3 | 2005-03-27 17:51:59 +0000 | [diff] [blame] | 1630 | elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN, |
| 1631 | relaydeb, |
| 1632 | FALSE, |
| 1633 | &elem->tdesc, |
| 1634 | xargs, |
| 1635 | &buf |
| 1636 | ); |
| 1637 | if (hres == S_OK) |
| 1638 | isserialized = TRUE; |
| 1639 | } |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1640 | } |
Marcus Meissner | e6260a3 | 2005-03-27 17:51:59 +0000 | [diff] [blame] | 1641 | if (!isserialized) |
| 1642 | hres = serialize_param( |
Robert Shearman | c6296c4 | 2005-06-01 11:03:40 +0000 | [diff] [blame] | 1643 | tinfo, |
Marcus Meissner | e6260a3 | 2005-03-27 17:51:59 +0000 | [diff] [blame] | 1644 | elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN, |
| 1645 | relaydeb, |
| 1646 | FALSE, |
| 1647 | &elem->tdesc, |
| 1648 | xargs, |
| 1649 | &buf |
| 1650 | ); |
| 1651 | |
| 1652 | if (hres) { |
| 1653 | ERR("Failed to serialize param, hres %lx\n",hres); |
| 1654 | break; |
| 1655 | } |
| 1656 | xargs+=_argsize(elem->tdesc.vt); |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1657 | } |
Mike Hearn | d440ca4 | 2004-06-17 23:03:26 +0000 | [diff] [blame] | 1658 | if (relaydeb) TRACE_(olerelay)(")"); |
Marcus Meissner | e6260a3 | 2005-03-27 17:51:59 +0000 | [diff] [blame] | 1659 | |
| 1660 | afterserialize: |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1661 | memset(&msg,0,sizeof(msg)); |
| 1662 | msg.cbBuffer = buf.curoff; |
| 1663 | msg.iMethod = method; |
| 1664 | hres = IRpcChannelBuffer_GetBuffer(tpinfo->chanbuf,&msg,&(tpinfo->iid)); |
| 1665 | if (hres) { |
Mike Hearn | 64eac75 | 2005-01-27 11:11:32 +0000 | [diff] [blame] | 1666 | ERR("RpcChannelBuffer GetBuffer failed, %lx\n",hres); |
Robert Shearman | 2a54aac | 2004-09-07 20:42:26 +0000 | [diff] [blame] | 1667 | LeaveCriticalSection(&tpinfo->crit); |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1668 | return hres; |
| 1669 | } |
| 1670 | memcpy(msg.Buffer,buf.base,buf.curoff); |
Mike Hearn | d440ca4 | 2004-06-17 23:03:26 +0000 | [diff] [blame] | 1671 | if (relaydeb) TRACE_(olerelay)("\n"); |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1672 | hres = IRpcChannelBuffer_SendReceive(tpinfo->chanbuf,&msg,&status); |
| 1673 | if (hres) { |
Mike Hearn | 64eac75 | 2005-01-27 11:11:32 +0000 | [diff] [blame] | 1674 | ERR("RpcChannelBuffer SendReceive failed, %lx\n",hres); |
Robert Shearman | 2a54aac | 2004-09-07 20:42:26 +0000 | [diff] [blame] | 1675 | LeaveCriticalSection(&tpinfo->crit); |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1676 | return hres; |
| 1677 | } |
Mike Hearn | d440ca4 | 2004-06-17 23:03:26 +0000 | [diff] [blame] | 1678 | |
Marcus Meissner | 89feaca | 2005-03-28 10:00:49 +0000 | [diff] [blame] | 1679 | if (relaydeb) TRACE_(olerelay)(" status = %08lx (",status); |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1680 | if (buf.base) |
| 1681 | buf.base = HeapReAlloc(GetProcessHeap(),0,buf.base,msg.cbBuffer); |
| 1682 | else |
| 1683 | buf.base = HeapAlloc(GetProcessHeap(),0,msg.cbBuffer); |
| 1684 | buf.size = msg.cbBuffer; |
| 1685 | memcpy(buf.base,msg.Buffer,buf.size); |
| 1686 | buf.curoff = 0; |
Marcus Meissner | e6260a3 | 2005-03-27 17:51:59 +0000 | [diff] [blame] | 1687 | |
| 1688 | /* Special IDispatch::GetIDsOfNames() deserializer */ |
| 1689 | if (is_idispatch_getidsofnames) { |
| 1690 | hres = deserialize_IDispatch_GetIDsOfNames(FALSE,relaydeb,args,&buf); |
| 1691 | if (hres != S_OK) { |
| 1692 | FIXME("deserialize of IDispatch::GetIDsOfNames failed!\n"); |
| 1693 | return hres; |
| 1694 | } |
| 1695 | goto after_deserialize; |
| 1696 | } |
| 1697 | /* Special QueryInterface deserializer */ |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1698 | if (method == 0) { |
| 1699 | _unmarshal_interface(&buf,(REFIID)args[0],(LPUNKNOWN*)args[1]); |
Mike Hearn | d440ca4 | 2004-06-17 23:03:26 +0000 | [diff] [blame] | 1700 | if (relaydeb) TRACE_(olerelay)("[in],%p",*((DWORD**)args[1])); |
Marcus Meissner | e6260a3 | 2005-03-27 17:51:59 +0000 | [diff] [blame] | 1701 | goto after_deserialize; |
| 1702 | } |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1703 | |
Marcus Meissner | e6260a3 | 2005-03-27 17:51:59 +0000 | [diff] [blame] | 1704 | /* generic deserializer using typelib description */ |
| 1705 | xargs = args; |
Marcus Meissner | 89feaca | 2005-03-28 10:00:49 +0000 | [diff] [blame] | 1706 | status = S_OK; |
Marcus Meissner | e6260a3 | 2005-03-27 17:51:59 +0000 | [diff] [blame] | 1707 | for (i=0;i<fdesc->cParams;i++) { |
| 1708 | ELEMDESC *elem = fdesc->lprgelemdescParam+i; |
| 1709 | BOOL isdeserialized = FALSE; |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 1710 | |
Marcus Meissner | e6260a3 | 2005-03-27 17:51:59 +0000 | [diff] [blame] | 1711 | if (relaydeb) { |
| 1712 | if (i) TRACE_(olerelay)(","); |
| 1713 | if (i+1<nrofnames && names[i+1]) TRACE_(olerelay)("%s=",relaystr(names[i+1])); |
| 1714 | } |
| 1715 | /* No need to marshal other data than FOUT and any VT_PTR */ |
| 1716 | if (!(elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT) && (elem->tdesc.vt != VT_PTR)) { |
| 1717 | xargs += _argsize(elem->tdesc.vt); |
| 1718 | if (relaydeb) TRACE_(olerelay)("[in]"); |
| 1719 | continue; |
| 1720 | } |
| 1721 | if (((i+1)<nrofnames) && !IsBadStringPtrW(names[i+1],1)) { |
| 1722 | /* If the parameter is 'riid', we use it as interface IID |
| 1723 | * for a later ppvObject serialization. |
| 1724 | */ |
| 1725 | buf.thisisiid = !lstrcmpW(names[i+1],riidW); |
| 1726 | |
| 1727 | /* deserialize DISPPARAM */ |
| 1728 | if (!lstrcmpW(names[i+1],pdispparamsW)) { |
| 1729 | hres = deserialize_DISPPARAM_ptr( |
Robert Shearman | c6296c4 | 2005-06-01 11:03:40 +0000 | [diff] [blame] | 1730 | tinfo, |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 1731 | elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT, |
| 1732 | relaydeb, |
| 1733 | FALSE, |
| 1734 | &(elem->tdesc), |
| 1735 | xargs, |
| 1736 | &buf |
| 1737 | ); |
Marcus Meissner | e6260a3 | 2005-03-27 17:51:59 +0000 | [diff] [blame] | 1738 | if (hres) { |
| 1739 | ERR("Failed to deserialize DISPPARAM*, hres %lx\n",hres); |
| 1740 | break; |
| 1741 | } |
| 1742 | isdeserialized = TRUE; |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1743 | } |
Marcus Meissner | e6260a3 | 2005-03-27 17:51:59 +0000 | [diff] [blame] | 1744 | if (!lstrcmpW(names[i+1],ppvObjectW)) { |
| 1745 | hres = deserialize_LPVOID_ptr( |
Robert Shearman | c6296c4 | 2005-06-01 11:03:40 +0000 | [diff] [blame] | 1746 | tinfo, |
Marcus Meissner | e6260a3 | 2005-03-27 17:51:59 +0000 | [diff] [blame] | 1747 | elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT, |
| 1748 | relaydeb, |
| 1749 | FALSE, |
| 1750 | &elem->tdesc, |
| 1751 | xargs, |
| 1752 | &buf |
| 1753 | ); |
| 1754 | if (hres == S_OK) |
| 1755 | isdeserialized = TRUE; |
| 1756 | } |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1757 | } |
Marcus Meissner | e6260a3 | 2005-03-27 17:51:59 +0000 | [diff] [blame] | 1758 | if (!isdeserialized) |
| 1759 | hres = deserialize_param( |
Robert Shearman | c6296c4 | 2005-06-01 11:03:40 +0000 | [diff] [blame] | 1760 | tinfo, |
Marcus Meissner | e6260a3 | 2005-03-27 17:51:59 +0000 | [diff] [blame] | 1761 | elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT, |
| 1762 | relaydeb, |
| 1763 | FALSE, |
| 1764 | &(elem->tdesc), |
| 1765 | xargs, |
| 1766 | &buf |
| 1767 | ); |
| 1768 | if (hres) { |
| 1769 | ERR("Failed to unmarshall param, hres %lx\n",hres); |
| 1770 | status = hres; |
| 1771 | break; |
| 1772 | } |
| 1773 | xargs += _argsize(elem->tdesc.vt); |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1774 | } |
Marcus Meissner | e6260a3 | 2005-03-27 17:51:59 +0000 | [diff] [blame] | 1775 | after_deserialize: |
Marcus Meissner | 89feaca | 2005-03-28 10:00:49 +0000 | [diff] [blame] | 1776 | hres = xbuf_get(&buf, (LPBYTE)&remoteresult, sizeof(DWORD)); |
| 1777 | if (hres != S_OK) |
| 1778 | return hres; |
| 1779 | if (relaydeb) TRACE_(olerelay)(") = %08lx\n", remoteresult); |
| 1780 | |
| 1781 | if (status != S_OK) /* OLE/COM internal error */ |
| 1782 | return status; |
| 1783 | |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1784 | HeapFree(GetProcessHeap(),0,buf.base); |
Robert Shearman | c6296c4 | 2005-06-01 11:03:40 +0000 | [diff] [blame] | 1785 | ITypeInfo_Release(tinfo); |
Robert Shearman | 2a54aac | 2004-09-07 20:42:26 +0000 | [diff] [blame] | 1786 | LeaveCriticalSection(&tpinfo->crit); |
Marcus Meissner | 89feaca | 2005-03-28 10:00:49 +0000 | [diff] [blame] | 1787 | return remoteresult; |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1788 | } |
| 1789 | |
Robert Shearman | ac23f2c | 2005-03-11 10:18:31 +0000 | [diff] [blame] | 1790 | HRESULT WINAPI ProxyIUnknown_QueryInterface(IUnknown *iface, REFIID riid, void **ppv) |
| 1791 | { |
| 1792 | TMProxyImpl *proxy = (TMProxyImpl *)iface; |
| 1793 | |
| 1794 | TRACE("(%s, %p)\n", debugstr_guid(riid), ppv); |
| 1795 | |
| 1796 | if (proxy->outerunknown) |
| 1797 | return IUnknown_QueryInterface(proxy->outerunknown, riid, ppv); |
| 1798 | |
| 1799 | FIXME("No interface\n"); |
| 1800 | return E_NOINTERFACE; |
| 1801 | } |
| 1802 | |
| 1803 | ULONG WINAPI ProxyIUnknown_AddRef(IUnknown *iface) |
| 1804 | { |
| 1805 | TMProxyImpl *proxy = (TMProxyImpl *)iface; |
| 1806 | |
| 1807 | TRACE("\n"); |
| 1808 | |
| 1809 | if (proxy->outerunknown) |
| 1810 | return IUnknown_AddRef(proxy->outerunknown); |
| 1811 | |
| 1812 | return 2; /* FIXME */ |
| 1813 | } |
| 1814 | |
| 1815 | ULONG WINAPI ProxyIUnknown_Release(IUnknown *iface) |
| 1816 | { |
| 1817 | TMProxyImpl *proxy = (TMProxyImpl *)iface; |
| 1818 | |
| 1819 | TRACE("\n"); |
| 1820 | |
| 1821 | if (proxy->outerunknown) |
| 1822 | return IUnknown_Release(proxy->outerunknown); |
| 1823 | |
| 1824 | return 1; /* FIXME */ |
| 1825 | } |
| 1826 | |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1827 | static HRESULT WINAPI |
| 1828 | PSFacBuf_CreateProxy( |
| 1829 | LPPSFACTORYBUFFER iface, IUnknown* pUnkOuter, REFIID riid, |
Robert Shearman | 2a54aac | 2004-09-07 20:42:26 +0000 | [diff] [blame] | 1830 | IRpcProxyBuffer **ppProxy, LPVOID *ppv) |
| 1831 | { |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1832 | HRESULT hres; |
| 1833 | ITypeInfo *tinfo; |
| 1834 | int i, nroffuncs; |
| 1835 | FUNCDESC *fdesc; |
| 1836 | TMProxyImpl *proxy; |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 1837 | |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1838 | TRACE("(...%s...)\n",debugstr_guid(riid)); |
| 1839 | hres = _get_typeinfo_for_iid(riid,&tinfo); |
| 1840 | if (hres) { |
Mike Hearn | 64eac75 | 2005-01-27 11:11:32 +0000 | [diff] [blame] | 1841 | ERR("No typeinfo for %s?\n",debugstr_guid(riid)); |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1842 | return hres; |
| 1843 | } |
| 1844 | nroffuncs = _nroffuncs(tinfo); |
Robert Shearman | 2a54aac | 2004-09-07 20:42:26 +0000 | [diff] [blame] | 1845 | proxy = CoTaskMemAlloc(sizeof(TMProxyImpl)); |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1846 | if (!proxy) return E_OUTOFMEMORY; |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1847 | |
| 1848 | assert(sizeof(TMAsmProxy) == 12); |
| 1849 | |
Robert Shearman | ac23f2c | 2005-03-11 10:18:31 +0000 | [diff] [blame] | 1850 | proxy->outerunknown = pUnkOuter; |
Mike Hearn | 3186bd2 | 2004-06-28 23:51:24 +0000 | [diff] [blame] | 1851 | proxy->asmstubs = VirtualAlloc(NULL, sizeof(TMAsmProxy) * nroffuncs, MEM_COMMIT, PAGE_EXECUTE_READWRITE); |
| 1852 | if (!proxy->asmstubs) { |
| 1853 | ERR("Could not commit pages for proxy thunks\n"); |
Robert Shearman | 2a54aac | 2004-09-07 20:42:26 +0000 | [diff] [blame] | 1854 | CoTaskMemFree(proxy); |
Mike Hearn | 3186bd2 | 2004-06-28 23:51:24 +0000 | [diff] [blame] | 1855 | return E_OUTOFMEMORY; |
| 1856 | } |
| 1857 | |
Robert Shearman | 2a54aac | 2004-09-07 20:42:26 +0000 | [diff] [blame] | 1858 | InitializeCriticalSection(&proxy->crit); |
| 1859 | |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1860 | proxy->lpvtbl = HeapAlloc(GetProcessHeap(),0,sizeof(LPBYTE)*nroffuncs); |
| 1861 | for (i=0;i<nroffuncs;i++) { |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1862 | TMAsmProxy *xasm = proxy->asmstubs+i; |
| 1863 | |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1864 | switch (i) { |
Robert Shearman | ac23f2c | 2005-03-11 10:18:31 +0000 | [diff] [blame] | 1865 | case 0: |
| 1866 | proxy->lpvtbl[i] = ProxyIUnknown_QueryInterface; |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1867 | break; |
Robert Shearman | ac23f2c | 2005-03-11 10:18:31 +0000 | [diff] [blame] | 1868 | case 1: |
| 1869 | proxy->lpvtbl[i] = ProxyIUnknown_AddRef; |
| 1870 | break; |
| 1871 | case 2: |
| 1872 | proxy->lpvtbl[i] = ProxyIUnknown_Release; |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1873 | break; |
| 1874 | default: { |
| 1875 | int j; |
Robert Shearman | ac23f2c | 2005-03-11 10:18:31 +0000 | [diff] [blame] | 1876 | /* nrofargs without This */ |
| 1877 | int nrofargs; |
Robert Shearman | c6296c4 | 2005-06-01 11:03:40 +0000 | [diff] [blame] | 1878 | ITypeInfo *tinfo2; |
| 1879 | hres = _get_funcdesc(tinfo,i,&tinfo2,&fdesc,NULL,NULL); |
| 1880 | ITypeInfo_Release(tinfo2); |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1881 | if (hres) { |
Mike Hearn | 64eac75 | 2005-01-27 11:11:32 +0000 | [diff] [blame] | 1882 | ERR("GetFuncDesc %lx should not fail here.\n",hres); |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1883 | return hres; |
| 1884 | } |
| 1885 | /* some args take more than 4 byte on the stack */ |
| 1886 | nrofargs = 0; |
| 1887 | for (j=0;j<fdesc->cParams;j++) |
| 1888 | nrofargs += _argsize(fdesc->lprgelemdescParam[j].tdesc.vt); |
| 1889 | |
| 1890 | if (fdesc->callconv != CC_STDCALL) { |
| 1891 | ERR("calling convention is not stdcall????\n"); |
| 1892 | return E_FAIL; |
| 1893 | } |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1894 | /* popl %eax - return ptr |
| 1895 | * pushl <nr> |
| 1896 | * pushl %eax |
| 1897 | * call xCall |
| 1898 | * lret <nr> (+4) |
| 1899 | * |
| 1900 | * |
| 1901 | * arg3 arg2 arg1 <method> <returnptr> |
| 1902 | */ |
Robert Shearman | ac23f2c | 2005-03-11 10:18:31 +0000 | [diff] [blame] | 1903 | xasm->popleax = 0x58; |
| 1904 | xasm->pushlval = 0x6a; |
| 1905 | xasm->nr = i; |
| 1906 | xasm->pushleax = 0x50; |
| 1907 | xasm->lcall = 0xe8; /* relative jump */ |
| 1908 | xasm->xcall = (DWORD)xCall; |
| 1909 | xasm->xcall -= (DWORD)&(xasm->lret); |
| 1910 | xasm->lret = 0xc2; |
| 1911 | xasm->bytestopop= (nrofargs+2)*4; /* pop args, This, iMethod */ |
| 1912 | proxy->lpvtbl[i] = xasm; |
| 1913 | break; |
| 1914 | } |
| 1915 | } |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1916 | } |
| 1917 | proxy->lpvtbl2 = &tmproxyvtable; |
Robert Shearman | bc06d4b | 2004-06-14 17:58:03 +0000 | [diff] [blame] | 1918 | /* 1 reference for the proxy and 1 for the object */ |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1919 | proxy->ref = 2; |
| 1920 | proxy->tinfo = tinfo; |
| 1921 | memcpy(&proxy->iid,riid,sizeof(*riid)); |
Bill Medland | 405abd5 | 2004-12-20 17:05:44 +0000 | [diff] [blame] | 1922 | proxy->chanbuf = 0; |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1923 | *ppv = (LPVOID)proxy; |
| 1924 | *ppProxy = (IRpcProxyBuffer *)&(proxy->lpvtbl2); |
| 1925 | return S_OK; |
| 1926 | } |
| 1927 | |
| 1928 | typedef struct _TMStubImpl { |
Dmitry Timoshkov | eba47f1 | 2005-06-06 19:50:35 +0000 | [diff] [blame] | 1929 | const IRpcStubBufferVtbl *lpvtbl; |
Mike McCormack | fc200d0 | 2005-07-11 10:25:19 +0000 | [diff] [blame] | 1930 | LONG ref; |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1931 | |
| 1932 | LPUNKNOWN pUnk; |
| 1933 | ITypeInfo *tinfo; |
| 1934 | IID iid; |
| 1935 | } TMStubImpl; |
| 1936 | |
| 1937 | static HRESULT WINAPI |
Robert Shearman | 2a54aac | 2004-09-07 20:42:26 +0000 | [diff] [blame] | 1938 | TMStubImpl_QueryInterface(LPRPCSTUBBUFFER iface, REFIID riid, LPVOID *ppv) |
| 1939 | { |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1940 | if (IsEqualIID(riid,&IID_IRpcStubBuffer)||IsEqualIID(riid,&IID_IUnknown)){ |
| 1941 | *ppv = (LPVOID)iface; |
| 1942 | IRpcStubBuffer_AddRef(iface); |
| 1943 | return S_OK; |
| 1944 | } |
| 1945 | FIXME("%s, not supported IID.\n",debugstr_guid(riid)); |
| 1946 | return E_NOINTERFACE; |
| 1947 | } |
| 1948 | |
| 1949 | static ULONG WINAPI |
Robert Shearman | 2a54aac | 2004-09-07 20:42:26 +0000 | [diff] [blame] | 1950 | TMStubImpl_AddRef(LPRPCSTUBBUFFER iface) |
| 1951 | { |
Alexandre Julliard | 241a4c3 | 2004-09-09 21:03:58 +0000 | [diff] [blame] | 1952 | TMStubImpl *This = (TMStubImpl *)iface; |
James Hawkins | ba92d29 | 2005-01-14 16:02:20 +0000 | [diff] [blame] | 1953 | ULONG refCount = InterlockedIncrement(&This->ref); |
Mike Hearn | 6545d99 | 2004-07-30 18:43:27 +0000 | [diff] [blame] | 1954 | |
James Hawkins | ba92d29 | 2005-01-14 16:02:20 +0000 | [diff] [blame] | 1955 | TRACE("(%p)->(ref before=%lu)\n", This, refCount - 1); |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1956 | |
James Hawkins | ba92d29 | 2005-01-14 16:02:20 +0000 | [diff] [blame] | 1957 | return refCount; |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1958 | } |
| 1959 | |
| 1960 | static ULONG WINAPI |
Robert Shearman | 2a54aac | 2004-09-07 20:42:26 +0000 | [diff] [blame] | 1961 | TMStubImpl_Release(LPRPCSTUBBUFFER iface) |
| 1962 | { |
Alexandre Julliard | 241a4c3 | 2004-09-09 21:03:58 +0000 | [diff] [blame] | 1963 | TMStubImpl *This = (TMStubImpl *)iface; |
James Hawkins | ba92d29 | 2005-01-14 16:02:20 +0000 | [diff] [blame] | 1964 | ULONG refCount = InterlockedDecrement(&This->ref); |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1965 | |
James Hawkins | ba92d29 | 2005-01-14 16:02:20 +0000 | [diff] [blame] | 1966 | TRACE("(%p)->(ref before=%lu)\n", This, refCount + 1); |
Mike Hearn | 6545d99 | 2004-07-30 18:43:27 +0000 | [diff] [blame] | 1967 | |
James Hawkins | ba92d29 | 2005-01-14 16:02:20 +0000 | [diff] [blame] | 1968 | if (!refCount) |
Robert Shearman | 2a54aac | 2004-09-07 20:42:26 +0000 | [diff] [blame] | 1969 | { |
| 1970 | IRpcStubBuffer_Disconnect(iface); |
Robert Shearman | 6bfae1a | 2005-07-19 20:00:07 +0000 | [diff] [blame] | 1971 | ITypeInfo_Release(This->tinfo); |
Robert Shearman | 2a54aac | 2004-09-07 20:42:26 +0000 | [diff] [blame] | 1972 | CoTaskMemFree(This); |
| 1973 | } |
James Hawkins | ba92d29 | 2005-01-14 16:02:20 +0000 | [diff] [blame] | 1974 | return refCount; |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1975 | } |
| 1976 | |
| 1977 | static HRESULT WINAPI |
Robert Shearman | 2a54aac | 2004-09-07 20:42:26 +0000 | [diff] [blame] | 1978 | TMStubImpl_Connect(LPRPCSTUBBUFFER iface, LPUNKNOWN pUnkServer) |
| 1979 | { |
Alexandre Julliard | 241a4c3 | 2004-09-09 21:03:58 +0000 | [diff] [blame] | 1980 | TMStubImpl *This = (TMStubImpl *)iface; |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1981 | |
Mike Hearn | 6545d99 | 2004-07-30 18:43:27 +0000 | [diff] [blame] | 1982 | TRACE("(%p)->(%p)\n", This, pUnkServer); |
| 1983 | |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1984 | IUnknown_AddRef(pUnkServer); |
| 1985 | This->pUnk = pUnkServer; |
| 1986 | return S_OK; |
| 1987 | } |
| 1988 | |
| 1989 | static void WINAPI |
Robert Shearman | 2a54aac | 2004-09-07 20:42:26 +0000 | [diff] [blame] | 1990 | TMStubImpl_Disconnect(LPRPCSTUBBUFFER iface) |
| 1991 | { |
Alexandre Julliard | 241a4c3 | 2004-09-09 21:03:58 +0000 | [diff] [blame] | 1992 | TMStubImpl *This = (TMStubImpl *)iface; |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 1993 | |
Mike Hearn | 6545d99 | 2004-07-30 18:43:27 +0000 | [diff] [blame] | 1994 | TRACE("(%p)->()\n", This); |
| 1995 | |
Robert Shearman | 6bfae1a | 2005-07-19 20:00:07 +0000 | [diff] [blame] | 1996 | if (This->pUnk) |
| 1997 | { |
| 1998 | IUnknown_Release(This->pUnk); |
| 1999 | This->pUnk = NULL; |
| 2000 | } |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 2001 | } |
| 2002 | |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 2003 | static HRESULT WINAPI |
| 2004 | TMStubImpl_Invoke( |
Robert Shearman | 2a54aac | 2004-09-07 20:42:26 +0000 | [diff] [blame] | 2005 | LPRPCSTUBBUFFER iface, RPCOLEMESSAGE* xmsg,IRpcChannelBuffer*rpcchanbuf) |
| 2006 | { |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 2007 | int i; |
| 2008 | FUNCDESC *fdesc; |
Alexandre Julliard | 241a4c3 | 2004-09-09 21:03:58 +0000 | [diff] [blame] | 2009 | TMStubImpl *This = (TMStubImpl *)iface; |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 2010 | HRESULT hres; |
| 2011 | DWORD *args, res, *xargs, nrofargs; |
| 2012 | marshal_state buf; |
Mike McCormack | a04b77d | 2005-08-08 18:38:29 +0000 | [diff] [blame] | 2013 | UINT nrofnames; |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 2014 | BSTR names[10]; |
Marcus Meissner | e6260a3 | 2005-03-27 17:51:59 +0000 | [diff] [blame] | 2015 | BSTR fname = NULL,iname = NULL; |
| 2016 | BOOL is_idispatch_getidsofnames = 0; |
Robert Shearman | c6296c4 | 2005-06-01 11:03:40 +0000 | [diff] [blame] | 2017 | ITypeInfo *tinfo; |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 2018 | |
| 2019 | memset(&buf,0,sizeof(buf)); |
| 2020 | buf.size = xmsg->cbBuffer; |
Robert Shearman | 5ef4748 | 2005-05-11 15:56:59 +0000 | [diff] [blame] | 2021 | buf.base = HeapAlloc(GetProcessHeap(), 0, xmsg->cbBuffer); |
| 2022 | memcpy(buf.base, xmsg->Buffer, xmsg->cbBuffer); |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 2023 | buf.curoff = 0; |
| 2024 | buf.iid = IID_IUnknown; |
| 2025 | |
| 2026 | TRACE("...\n"); |
| 2027 | if (xmsg->iMethod == 0) { /* QI */ |
| 2028 | IID xiid; |
| 2029 | /* in: IID, out: <iface> */ |
| 2030 | |
| 2031 | xbuf_get(&buf,(LPBYTE)&xiid,sizeof(xiid)); |
| 2032 | buf.curoff = 0; |
| 2033 | hres = _marshal_interface(&buf,&xiid,This->pUnk); |
| 2034 | xmsg->Buffer = buf.base; /* Might have been reallocated */ |
| 2035 | xmsg->cbBuffer = buf.size; |
| 2036 | return hres; |
| 2037 | } |
Robert Shearman | c6296c4 | 2005-06-01 11:03:40 +0000 | [diff] [blame] | 2038 | hres = _get_funcdesc(This->tinfo,xmsg->iMethod,&tinfo,&fdesc,&iname,&fname); |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 2039 | if (hres) { |
Mike Hearn | 64eac75 | 2005-01-27 11:11:32 +0000 | [diff] [blame] | 2040 | ERR("GetFuncDesc on method %ld failed with %lx\n",xmsg->iMethod,hres); |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 2041 | return hres; |
| 2042 | } |
Marcus Meissner | e6260a3 | 2005-03-27 17:51:59 +0000 | [diff] [blame] | 2043 | |
| 2044 | if (iname && fname && !lstrcmpW(iname, IDispatchW) && !lstrcmpW(fname, GetIDsOfNamesW)) |
| 2045 | is_idispatch_getidsofnames = 1; |
| 2046 | |
| 2047 | if (iname) SysFreeString (iname); |
| 2048 | if (fname) SysFreeString (fname); |
| 2049 | |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 2050 | /* Need them for hack below */ |
| 2051 | memset(names,0,sizeof(names)); |
Robert Shearman | c6296c4 | 2005-06-01 11:03:40 +0000 | [diff] [blame] | 2052 | ITypeInfo_GetNames(tinfo,fdesc->memid,names,sizeof(names)/sizeof(names[0]),&nrofnames); |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 2053 | if (nrofnames > sizeof(names)/sizeof(names[0])) { |
| 2054 | ERR("Need more names!\n"); |
| 2055 | } |
| 2056 | |
| 2057 | /*dump_FUNCDESC(fdesc);*/ |
| 2058 | nrofargs = 0; |
| 2059 | for (i=0;i<fdesc->cParams;i++) |
| 2060 | nrofargs += _argsize(fdesc->lprgelemdescParam[i].tdesc.vt); |
| 2061 | args = HeapAlloc(GetProcessHeap(),0,(nrofargs+1)*sizeof(DWORD)); |
| 2062 | if (!args) return E_OUTOFMEMORY; |
| 2063 | |
Marcus Meissner | e6260a3 | 2005-03-27 17:51:59 +0000 | [diff] [blame] | 2064 | if (is_idispatch_getidsofnames) { |
| 2065 | hres = deserialize_IDispatch_GetIDsOfNames(TRUE,FALSE,args+1,&buf); |
| 2066 | if (hres != S_OK) { |
| 2067 | FIXME("deserialize_IDispatch_GetIDsOfNames failed!\n"); |
| 2068 | return hres; |
| 2069 | } |
| 2070 | xargs = args+1+5; |
| 2071 | goto afterdeserialize; |
| 2072 | } |
| 2073 | |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 2074 | /* Allocate all stuff used by call. */ |
| 2075 | xargs = args+1; |
| 2076 | for (i=0;i<fdesc->cParams;i++) { |
| 2077 | ELEMDESC *elem = fdesc->lprgelemdescParam+i; |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 2078 | BOOL isdeserialized = FALSE; |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 2079 | |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 2080 | if (((i+1)<nrofnames) && !IsBadStringPtrW(names[i+1],1)) { |
| 2081 | /* If the parameter is 'riid', we use it as interface IID |
| 2082 | * for a later ppvObject serialization. |
| 2083 | */ |
| 2084 | buf.thisisiid = !lstrcmpW(names[i+1],riidW); |
| 2085 | |
| 2086 | /* deserialize DISPPARAM */ |
| 2087 | if (!lstrcmpW(names[i+1],pdispparamsW)) { |
| 2088 | hres = deserialize_DISPPARAM_ptr( |
Robert Shearman | c6296c4 | 2005-06-01 11:03:40 +0000 | [diff] [blame] | 2089 | tinfo, |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 2090 | elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN, |
| 2091 | FALSE, |
| 2092 | TRUE, |
| 2093 | &(elem->tdesc), |
| 2094 | xargs, |
| 2095 | &buf |
| 2096 | ); |
| 2097 | if (hres) { |
Mike Hearn | 64eac75 | 2005-01-27 11:11:32 +0000 | [diff] [blame] | 2098 | ERR("Failed to deserialize DISPPARAM*, hres %lx\n",hres); |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 2099 | break; |
| 2100 | } |
| 2101 | isdeserialized = TRUE; |
| 2102 | } |
| 2103 | if (!lstrcmpW(names[i+1],ppvObjectW)) { |
| 2104 | hres = deserialize_LPVOID_ptr( |
Robert Shearman | c6296c4 | 2005-06-01 11:03:40 +0000 | [diff] [blame] | 2105 | tinfo, |
Mike Hearn | 9b79651 | 2005-03-25 16:38:37 +0000 | [diff] [blame] | 2106 | elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN, |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 2107 | FALSE, |
| 2108 | TRUE, |
| 2109 | &elem->tdesc, |
| 2110 | xargs, |
| 2111 | &buf |
| 2112 | ); |
| 2113 | if (hres == S_OK) |
| 2114 | isdeserialized = TRUE; |
| 2115 | } |
| 2116 | } |
| 2117 | if (!isdeserialized) |
| 2118 | hres = deserialize_param( |
Robert Shearman | c6296c4 | 2005-06-01 11:03:40 +0000 | [diff] [blame] | 2119 | tinfo, |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 2120 | elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN, |
| 2121 | FALSE, |
| 2122 | TRUE, |
| 2123 | &(elem->tdesc), |
| 2124 | xargs, |
| 2125 | &buf |
| 2126 | ); |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 2127 | xargs += _argsize(elem->tdesc.vt); |
| 2128 | if (hres) { |
Mike Hearn | 64eac75 | 2005-01-27 11:11:32 +0000 | [diff] [blame] | 2129 | ERR("Failed to deserialize param %s, hres %lx\n",relaystr(names[i+1]),hres); |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 2130 | break; |
| 2131 | } |
| 2132 | } |
Marcus Meissner | e6260a3 | 2005-03-27 17:51:59 +0000 | [diff] [blame] | 2133 | afterdeserialize: |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 2134 | hres = IUnknown_QueryInterface(This->pUnk,&(This->iid),(LPVOID*)&(args[0])); |
| 2135 | if (hres) { |
Marcus Meissner | e6260a3 | 2005-03-27 17:51:59 +0000 | [diff] [blame] | 2136 | ERR("Does not support iface %s, returning %lx\n",debugstr_guid(&(This->iid)), hres); |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 2137 | return hres; |
| 2138 | } |
| 2139 | res = _invoke( |
Marcus Meissner | e6260a3 | 2005-03-27 17:51:59 +0000 | [diff] [blame] | 2140 | (*((FARPROC**)args[0]))[fdesc->oVft/4], |
| 2141 | fdesc->callconv, |
| 2142 | (xargs-args), |
| 2143 | args |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 2144 | ); |
| 2145 | IUnknown_Release((LPUNKNOWN)args[0]); |
| 2146 | buf.curoff = 0; |
Marcus Meissner | e6260a3 | 2005-03-27 17:51:59 +0000 | [diff] [blame] | 2147 | |
| 2148 | /* special IDispatch::GetIDsOfNames serializer */ |
| 2149 | if (is_idispatch_getidsofnames) { |
| 2150 | hres = serialize_IDispatch_GetIDsOfNames(FALSE,FALSE,args+1,&buf); |
| 2151 | if (hres != S_OK) { |
| 2152 | FIXME("serialize of IDispatch::GetIDsOfNames failed!\n"); |
| 2153 | return hres; |
| 2154 | } |
| 2155 | goto afterserialize; |
| 2156 | } |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 2157 | xargs = args+1; |
| 2158 | for (i=0;i<fdesc->cParams;i++) { |
| 2159 | ELEMDESC *elem = fdesc->lprgelemdescParam+i; |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 2160 | BOOL isserialized = FALSE; |
| 2161 | |
| 2162 | if (((i+1)<nrofnames) && !IsBadStringPtrW(names[i+1],1)) { |
| 2163 | /* If the parameter is 'riid', we use it as interface IID |
| 2164 | * for a later ppvObject serialization. |
| 2165 | */ |
| 2166 | buf.thisisiid = !lstrcmpW(names[i+1],riidW); |
| 2167 | |
| 2168 | /* DISPPARAMS* needs special serializer */ |
| 2169 | if (!lstrcmpW(names[i+1],pdispparamsW)) { |
| 2170 | hres = serialize_DISPPARAM_ptr( |
Robert Shearman | c6296c4 | 2005-06-01 11:03:40 +0000 | [diff] [blame] | 2171 | tinfo, |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 2172 | elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT, |
| 2173 | FALSE, |
| 2174 | TRUE, |
| 2175 | &elem->tdesc, |
| 2176 | xargs, |
| 2177 | &buf |
| 2178 | ); |
| 2179 | isserialized = TRUE; |
| 2180 | } |
| 2181 | if (!lstrcmpW(names[i+1],ppvObjectW)) { |
| 2182 | hres = serialize_LPVOID_ptr( |
Robert Shearman | c6296c4 | 2005-06-01 11:03:40 +0000 | [diff] [blame] | 2183 | tinfo, |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 2184 | elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT, |
| 2185 | FALSE, |
| 2186 | TRUE, |
| 2187 | &elem->tdesc, |
| 2188 | xargs, |
| 2189 | &buf |
| 2190 | ); |
| 2191 | if (hres == S_OK) |
| 2192 | isserialized = TRUE; |
| 2193 | } |
| 2194 | } |
| 2195 | if (!isserialized) |
| 2196 | hres = serialize_param( |
Robert Shearman | c6296c4 | 2005-06-01 11:03:40 +0000 | [diff] [blame] | 2197 | tinfo, |
Marcus Meissner | e81f10c | 2002-06-10 02:30:20 +0000 | [diff] [blame] | 2198 | elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT, |
| 2199 | FALSE, |
| 2200 | TRUE, |
| 2201 | &elem->tdesc, |
| 2202 | xargs, |
| 2203 | &buf |
| 2204 | ); |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 2205 | xargs += _argsize(elem->tdesc.vt); |
| 2206 | if (hres) { |
Mike Hearn | 64eac75 | 2005-01-27 11:11:32 +0000 | [diff] [blame] | 2207 | ERR("Failed to stuballoc param, hres %lx\n",hres); |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 2208 | break; |
| 2209 | } |
| 2210 | } |
Marcus Meissner | e6260a3 | 2005-03-27 17:51:59 +0000 | [diff] [blame] | 2211 | afterserialize: |
Marcus Meissner | 89feaca | 2005-03-28 10:00:49 +0000 | [diff] [blame] | 2212 | hres = xbuf_add (&buf, (LPBYTE)&res, sizeof(DWORD)); |
| 2213 | if (hres != S_OK) |
| 2214 | return hres; |
Robert Shearman | c6296c4 | 2005-06-01 11:03:40 +0000 | [diff] [blame] | 2215 | |
| 2216 | ITypeInfo_Release(tinfo); |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 2217 | xmsg->cbBuffer = buf.curoff; |
Robert Shearman | 5ef4748 | 2005-05-11 15:56:59 +0000 | [diff] [blame] | 2218 | I_RpcGetBuffer((RPC_MESSAGE *)xmsg); |
| 2219 | memcpy(xmsg->Buffer, buf.base, buf.curoff); |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 2220 | HeapFree(GetProcessHeap(),0,args); |
Marcus Meissner | 89feaca | 2005-03-28 10:00:49 +0000 | [diff] [blame] | 2221 | return S_OK; |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 2222 | } |
| 2223 | |
| 2224 | static LPRPCSTUBBUFFER WINAPI |
| 2225 | TMStubImpl_IsIIDSupported(LPRPCSTUBBUFFER iface, REFIID riid) { |
| 2226 | FIXME("Huh (%s)?\n",debugstr_guid(riid)); |
| 2227 | return NULL; |
| 2228 | } |
| 2229 | |
| 2230 | static ULONG WINAPI |
| 2231 | TMStubImpl_CountRefs(LPRPCSTUBBUFFER iface) { |
Alexandre Julliard | 241a4c3 | 2004-09-09 21:03:58 +0000 | [diff] [blame] | 2232 | TMStubImpl *This = (TMStubImpl *)iface; |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 2233 | |
| 2234 | return This->ref; /*FIXME? */ |
| 2235 | } |
| 2236 | |
| 2237 | static HRESULT WINAPI |
| 2238 | TMStubImpl_DebugServerQueryInterface(LPRPCSTUBBUFFER iface, LPVOID *ppv) { |
| 2239 | return E_NOTIMPL; |
| 2240 | } |
| 2241 | |
| 2242 | static void WINAPI |
| 2243 | TMStubImpl_DebugServerRelease(LPRPCSTUBBUFFER iface, LPVOID ppv) { |
| 2244 | return; |
| 2245 | } |
| 2246 | |
Dmitry Timoshkov | eba47f1 | 2005-06-06 19:50:35 +0000 | [diff] [blame] | 2247 | static const IRpcStubBufferVtbl tmstubvtbl = { |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 2248 | TMStubImpl_QueryInterface, |
| 2249 | TMStubImpl_AddRef, |
| 2250 | TMStubImpl_Release, |
| 2251 | TMStubImpl_Connect, |
| 2252 | TMStubImpl_Disconnect, |
| 2253 | TMStubImpl_Invoke, |
| 2254 | TMStubImpl_IsIIDSupported, |
| 2255 | TMStubImpl_CountRefs, |
| 2256 | TMStubImpl_DebugServerQueryInterface, |
| 2257 | TMStubImpl_DebugServerRelease |
| 2258 | }; |
| 2259 | |
| 2260 | static HRESULT WINAPI |
| 2261 | PSFacBuf_CreateStub( |
| 2262 | LPPSFACTORYBUFFER iface, REFIID riid,IUnknown *pUnkServer, |
| 2263 | IRpcStubBuffer** ppStub |
| 2264 | ) { |
| 2265 | HRESULT hres; |
| 2266 | ITypeInfo *tinfo; |
| 2267 | TMStubImpl *stub; |
| 2268 | |
| 2269 | TRACE("(%s,%p,%p)\n",debugstr_guid(riid),pUnkServer,ppStub); |
| 2270 | hres = _get_typeinfo_for_iid(riid,&tinfo); |
| 2271 | if (hres) { |
Mike Hearn | 64eac75 | 2005-01-27 11:11:32 +0000 | [diff] [blame] | 2272 | ERR("No typeinfo for %s?\n",debugstr_guid(riid)); |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 2273 | return hres; |
| 2274 | } |
Robert Shearman | 2a54aac | 2004-09-07 20:42:26 +0000 | [diff] [blame] | 2275 | stub = CoTaskMemAlloc(sizeof(TMStubImpl)); |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 2276 | if (!stub) |
| 2277 | return E_OUTOFMEMORY; |
| 2278 | stub->lpvtbl = &tmstubvtbl; |
| 2279 | stub->ref = 1; |
| 2280 | stub->tinfo = tinfo; |
| 2281 | memcpy(&(stub->iid),riid,sizeof(*riid)); |
| 2282 | hres = IRpcStubBuffer_Connect((LPRPCSTUBBUFFER)stub,pUnkServer); |
| 2283 | *ppStub = (LPRPCSTUBBUFFER)stub; |
Mike Hearn | 6545d99 | 2004-07-30 18:43:27 +0000 | [diff] [blame] | 2284 | TRACE("IRpcStubBuffer: %p\n", stub); |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 2285 | if (hres) |
Mike Hearn | 64eac75 | 2005-01-27 11:11:32 +0000 | [diff] [blame] | 2286 | ERR("Connect to pUnkServer failed?\n"); |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 2287 | return hres; |
| 2288 | } |
| 2289 | |
Dmitry Timoshkov | eba47f1 | 2005-06-06 19:50:35 +0000 | [diff] [blame] | 2290 | static const IPSFactoryBufferVtbl psfacbufvtbl = { |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 2291 | PSFacBuf_QueryInterface, |
| 2292 | PSFacBuf_AddRef, |
| 2293 | PSFacBuf_Release, |
| 2294 | PSFacBuf_CreateProxy, |
| 2295 | PSFacBuf_CreateStub |
| 2296 | }; |
| 2297 | |
| 2298 | /* This is the whole PSFactoryBuffer object, just the vtableptr */ |
Dmitry Timoshkov | eba47f1 | 2005-06-06 19:50:35 +0000 | [diff] [blame] | 2299 | static const IPSFactoryBufferVtbl *lppsfac = &psfacbufvtbl; |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 2300 | |
| 2301 | /*********************************************************************** |
Alexandre Julliard | b8d0f4c | 2005-08-09 10:38:54 +0000 | [diff] [blame] | 2302 | * TMARSHAL_DllGetClassObject |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 2303 | */ |
Alexandre Julliard | b8d0f4c | 2005-08-09 10:38:54 +0000 | [diff] [blame] | 2304 | HRESULT TMARSHAL_DllGetClassObject(REFCLSID rclsid, REFIID iid,LPVOID *ppv) |
Marcus Meissner | 0749fc2 | 2002-02-05 18:11:17 +0000 | [diff] [blame] | 2305 | { |
| 2306 | if (IsEqualIID(iid,&IID_IPSFactoryBuffer)) { |
| 2307 | *ppv = &lppsfac; |
| 2308 | return S_OK; |
| 2309 | } |
| 2310 | return E_NOINTERFACE; |
| 2311 | } |