Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygentmarshal.c
Go to the documentation of this file.
00001 /* 00002 * TYPELIB Marshaler 00003 * 00004 * Copyright 2002,2005 Marcus Meissner 00005 * 00006 * The olerelay debug channel allows you to see calls marshalled by 00007 * the typelib marshaller. It is not a generic COM relaying system. 00008 * 00009 * This library is free software; you can redistribute it and/or 00010 * modify it under the terms of the GNU Lesser General Public 00011 * License as published by the Free Software Foundation; either 00012 * version 2.1 of the License, or (at your option) any later version. 00013 * 00014 * This library is distributed in the hope that it will be useful, 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00017 * Lesser General Public License for more details. 00018 * 00019 * You should have received a copy of the GNU Lesser General Public 00020 * License along with this library; if not, write to the Free Software 00021 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00022 */ 00023 00024 #include "config.h" 00025 #include "wine/port.h" 00026 00027 #include <assert.h> 00028 #include <stdlib.h> 00029 #include <string.h> 00030 #include <stdarg.h> 00031 #include <stdio.h> 00032 #include <ctype.h> 00033 00034 #define COBJMACROS 00035 #define NONAMELESSUNION 00036 #define NONAMELESSSTRUCT 00037 00038 #include "winerror.h" 00039 #include "windef.h" 00040 #include "winbase.h" 00041 #include "winnls.h" 00042 #include "winreg.h" 00043 #include "winuser.h" 00044 00045 #include "ole2.h" 00046 #include "propidl.h" /* for LPSAFEARRAY_User* functions */ 00047 #include "typelib.h" 00048 #include "variant.h" 00049 #include "wine/debug.h" 00050 #include "wine/exception.h" 00051 00052 static const WCHAR IDispatchW[] = { 'I','D','i','s','p','a','t','c','h',0}; 00053 00054 WINE_DEFAULT_DEBUG_CHANNEL(ole); 00055 WINE_DECLARE_DEBUG_CHANNEL(olerelay); 00056 00057 #define ICOM_THIS_MULTI(impl,field,iface) impl* const This=(impl*)((char*)(iface) - offsetof(impl,field)) 00058 00059 static HRESULT TMarshalDispatchChannel_Create( 00060 IRpcChannelBuffer *pDelegateChannel, REFIID tmarshal_riid, 00061 IRpcChannelBuffer **ppChannel); 00062 00063 typedef struct _marshal_state { 00064 LPBYTE base; 00065 int size; 00066 int curoff; 00067 } marshal_state; 00068 00069 /* used in the olerelay code to avoid having the L"" stuff added by debugstr_w */ 00070 static char *relaystr(WCHAR *in) { 00071 char *tmp = (char *)debugstr_w(in); 00072 tmp += 2; 00073 tmp[strlen(tmp)-1] = '\0'; 00074 return tmp; 00075 } 00076 00077 static HRESULT 00078 xbuf_resize(marshal_state *buf, DWORD newsize) 00079 { 00080 if(buf->size >= newsize) 00081 return S_FALSE; 00082 00083 if(buf->base) 00084 { 00085 buf->base = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, buf->base, newsize); 00086 if(!buf->base) 00087 return E_OUTOFMEMORY; 00088 } 00089 else 00090 { 00091 buf->base = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, newsize); 00092 if(!buf->base) 00093 return E_OUTOFMEMORY; 00094 } 00095 buf->size = newsize; 00096 return S_OK; 00097 } 00098 00099 static HRESULT 00100 xbuf_add(marshal_state *buf, const BYTE *stuff, DWORD size) 00101 { 00102 HRESULT hr; 00103 00104 if(buf->size - buf->curoff < size) 00105 { 00106 hr = xbuf_resize(buf, buf->size + size + 100); 00107 if(FAILED(hr)) return hr; 00108 } 00109 memcpy(buf->base+buf->curoff,stuff,size); 00110 buf->curoff += size; 00111 return S_OK; 00112 } 00113 00114 static HRESULT 00115 xbuf_get(marshal_state *buf, LPBYTE stuff, DWORD size) { 00116 if (buf->size < buf->curoff+size) return E_FAIL; 00117 memcpy(stuff,buf->base+buf->curoff,size); 00118 buf->curoff += size; 00119 return S_OK; 00120 } 00121 00122 static HRESULT 00123 xbuf_skip(marshal_state *buf, DWORD size) { 00124 if (buf->size < buf->curoff+size) return E_FAIL; 00125 buf->curoff += size; 00126 return S_OK; 00127 } 00128 00129 static HRESULT 00130 _unmarshal_interface(marshal_state *buf, REFIID riid, LPUNKNOWN *pUnk) { 00131 IStream *pStm; 00132 ULARGE_INTEGER newpos; 00133 LARGE_INTEGER seekto; 00134 ULONG res; 00135 HRESULT hres; 00136 DWORD xsize; 00137 00138 TRACE("...%s...\n",debugstr_guid(riid)); 00139 00140 *pUnk = NULL; 00141 hres = xbuf_get(buf,(LPBYTE)&xsize,sizeof(xsize)); 00142 if (hres) { 00143 ERR("xbuf_get failed\n"); 00144 return hres; 00145 } 00146 00147 if (xsize == 0) return S_OK; 00148 00149 hres = CreateStreamOnHGlobal(0,TRUE,&pStm); 00150 if (hres) { 00151 ERR("Stream create failed %x\n",hres); 00152 return hres; 00153 } 00154 00155 hres = IStream_Write(pStm,buf->base+buf->curoff,xsize,&res); 00156 if (hres) { 00157 ERR("stream write %x\n",hres); 00158 return hres; 00159 } 00160 00161 memset(&seekto,0,sizeof(seekto)); 00162 hres = IStream_Seek(pStm,seekto,SEEK_SET,&newpos); 00163 if (hres) { 00164 ERR("Failed Seek %x\n",hres); 00165 return hres; 00166 } 00167 00168 hres = CoUnmarshalInterface(pStm,riid,(LPVOID*)pUnk); 00169 if (hres) { 00170 ERR("Unmarshalling interface %s failed with %x\n",debugstr_guid(riid),hres); 00171 return hres; 00172 } 00173 00174 IStream_Release(pStm); 00175 return xbuf_skip(buf,xsize); 00176 } 00177 00178 static HRESULT 00179 _marshal_interface(marshal_state *buf, REFIID riid, LPUNKNOWN pUnk) { 00180 LPBYTE tempbuf = NULL; 00181 IStream *pStm = NULL; 00182 STATSTG ststg; 00183 ULARGE_INTEGER newpos; 00184 LARGE_INTEGER seekto; 00185 ULONG res; 00186 DWORD xsize; 00187 HRESULT hres; 00188 00189 if (!pUnk) { 00190 /* this is valid, if for instance we serialize 00191 * a VT_DISPATCH with NULL ptr which apparently 00192 * can happen. S_OK to make sure we continue 00193 * serializing. 00194 */ 00195 WARN("pUnk is NULL\n"); 00196 xsize = 0; 00197 return xbuf_add(buf,(LPBYTE)&xsize,sizeof(xsize)); 00198 } 00199 00200 hres = E_FAIL; 00201 00202 TRACE("...%s...\n",debugstr_guid(riid)); 00203 00204 hres = CreateStreamOnHGlobal(0,TRUE,&pStm); 00205 if (hres) { 00206 ERR("Stream create failed %x\n",hres); 00207 goto fail; 00208 } 00209 00210 hres = CoMarshalInterface(pStm,riid,pUnk,0,NULL,0); 00211 if (hres) { 00212 ERR("Marshalling interface %s failed with %x\n", debugstr_guid(riid), hres); 00213 goto fail; 00214 } 00215 00216 hres = IStream_Stat(pStm,&ststg,STATFLAG_NONAME); 00217 if (hres) { 00218 ERR("Stream stat failed\n"); 00219 goto fail; 00220 } 00221 00222 tempbuf = HeapAlloc(GetProcessHeap(), 0, ststg.cbSize.u.LowPart); 00223 memset(&seekto,0,sizeof(seekto)); 00224 hres = IStream_Seek(pStm,seekto,SEEK_SET,&newpos); 00225 if (hres) { 00226 ERR("Failed Seek %x\n",hres); 00227 goto fail; 00228 } 00229 00230 hres = IStream_Read(pStm,tempbuf,ststg.cbSize.u.LowPart,&res); 00231 if (hres) { 00232 ERR("Failed Read %x\n",hres); 00233 goto fail; 00234 } 00235 00236 xsize = ststg.cbSize.u.LowPart; 00237 xbuf_add(buf,(LPBYTE)&xsize,sizeof(xsize)); 00238 hres = xbuf_add(buf,tempbuf,ststg.cbSize.u.LowPart); 00239 00240 HeapFree(GetProcessHeap(),0,tempbuf); 00241 IStream_Release(pStm); 00242 00243 return hres; 00244 00245 fail: 00246 xsize = 0; 00247 xbuf_add(buf,(LPBYTE)&xsize,sizeof(xsize)); 00248 if (pStm) IUnknown_Release(pStm); 00249 HeapFree(GetProcessHeap(), 0, tempbuf); 00250 return hres; 00251 } 00252 00253 /********************* OLE Proxy/Stub Factory ********************************/ 00254 static HRESULT WINAPI 00255 PSFacBuf_QueryInterface(LPPSFACTORYBUFFER iface, REFIID iid, LPVOID *ppv) { 00256 if (IsEqualIID(iid,&IID_IPSFactoryBuffer)||IsEqualIID(iid,&IID_IUnknown)) { 00257 *ppv = iface; 00258 /* No ref counting, static class */ 00259 return S_OK; 00260 } 00261 FIXME("(%s) unknown IID?\n",debugstr_guid(iid)); 00262 return E_NOINTERFACE; 00263 } 00264 00265 static ULONG WINAPI PSFacBuf_AddRef(LPPSFACTORYBUFFER iface) { return 2; } 00266 static ULONG WINAPI PSFacBuf_Release(LPPSFACTORYBUFFER iface) { return 1; } 00267 00268 static HRESULT 00269 _get_typeinfo_for_iid(REFIID riid, ITypeInfo**ti) { 00270 HRESULT hres; 00271 HKEY ikey; 00272 char tlguid[200],typelibkey[300],interfacekey[300],ver[100]; 00273 char tlfn[260]; 00274 OLECHAR tlfnW[260]; 00275 DWORD tlguidlen, verlen, type; 00276 LONG tlfnlen; 00277 ITypeLib *tl; 00278 00279 sprintf( interfacekey, "Interface\\{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\Typelib", 00280 riid->Data1, riid->Data2, riid->Data3, 00281 riid->Data4[0], riid->Data4[1], riid->Data4[2], riid->Data4[3], 00282 riid->Data4[4], riid->Data4[5], riid->Data4[6], riid->Data4[7] 00283 ); 00284 00285 if (RegOpenKeyA(HKEY_CLASSES_ROOT,interfacekey,&ikey)) { 00286 ERR("No %s key found.\n",interfacekey); 00287 return E_FAIL; 00288 } 00289 tlguidlen = sizeof(tlguid); 00290 if (RegQueryValueExA(ikey,NULL,NULL,&type,(LPBYTE)tlguid,&tlguidlen)) { 00291 ERR("Getting typelib guid failed.\n"); 00292 RegCloseKey(ikey); 00293 return E_FAIL; 00294 } 00295 verlen = sizeof(ver); 00296 if (RegQueryValueExA(ikey,"Version",NULL,&type,(LPBYTE)ver,&verlen)) { 00297 ERR("Could not get version value?\n"); 00298 RegCloseKey(ikey); 00299 return E_FAIL; 00300 } 00301 RegCloseKey(ikey); 00302 sprintf(typelibkey,"Typelib\\%s\\%s\\0\\win%u",tlguid,ver,(sizeof(void*) == 8) ? 64 : 32); 00303 tlfnlen = sizeof(tlfn); 00304 if (RegQueryValueA(HKEY_CLASSES_ROOT,typelibkey,tlfn,&tlfnlen)) { 00305 ERR("Could not get typelib fn?\n"); 00306 return E_FAIL; 00307 } 00308 MultiByteToWideChar(CP_ACP, 0, tlfn, -1, tlfnW, sizeof(tlfnW) / sizeof(tlfnW[0])); 00309 hres = LoadTypeLib(tlfnW,&tl); 00310 if (hres) { 00311 ERR("Failed to load typelib for %s, but it should be there.\n",debugstr_guid(riid)); 00312 return hres; 00313 } 00314 hres = ITypeLib_GetTypeInfoOfGuid(tl,riid,ti); 00315 if (hres) { 00316 ERR("typelib does not contain info for %s?\n",debugstr_guid(riid)); 00317 ITypeLib_Release(tl); 00318 return hres; 00319 } 00320 ITypeLib_Release(tl); 00321 return hres; 00322 } 00323 00324 /* 00325 * Determine the number of functions including all inherited functions. 00326 * Note for non-dual dispinterfaces we simply return the size of IDispatch. 00327 */ 00328 static HRESULT num_of_funcs(ITypeInfo *tinfo, unsigned int *num) 00329 { 00330 HRESULT hres; 00331 TYPEATTR *attr; 00332 ITypeInfo *tinfo2; 00333 00334 *num = 0; 00335 hres = ITypeInfo_GetTypeAttr(tinfo, &attr); 00336 if (hres) { 00337 ERR("GetTypeAttr failed with %x\n",hres); 00338 return hres; 00339 } 00340 00341 if(attr->typekind == TKIND_DISPATCH && (attr->wTypeFlags & TYPEFLAG_FDUAL)) 00342 { 00343 HREFTYPE href; 00344 hres = ITypeInfo_GetRefTypeOfImplType(tinfo, -1, &href); 00345 if(FAILED(hres)) 00346 { 00347 ERR("Unable to get interface href from dual dispinterface\n"); 00348 goto end; 00349 } 00350 hres = ITypeInfo_GetRefTypeInfo(tinfo, href, &tinfo2); 00351 if(FAILED(hres)) 00352 { 00353 ERR("Unable to get interface from dual dispinterface\n"); 00354 goto end; 00355 } 00356 hres = num_of_funcs(tinfo2, num); 00357 ITypeInfo_Release(tinfo2); 00358 } 00359 else 00360 { 00361 *num = attr->cbSizeVft / 4; 00362 } 00363 00364 end: 00365 ITypeInfo_ReleaseTypeAttr(tinfo, attr); 00366 return hres; 00367 } 00368 00369 #ifdef __i386__ 00370 00371 #include "pshpack1.h" 00372 00373 typedef struct _TMAsmProxy { 00374 BYTE popleax; 00375 BYTE pushlval; 00376 DWORD nr; 00377 BYTE pushleax; 00378 BYTE lcall; 00379 DWORD xcall; 00380 BYTE lret; 00381 WORD bytestopop; 00382 BYTE nop; 00383 } TMAsmProxy; 00384 00385 #include "poppack.h" 00386 00387 #else /* __i386__ */ 00388 #ifdef _MSC_VER 00389 #pragma message("You need to implement stubless proxies for your architecture") 00390 #else 00391 # warning You need to implement stubless proxies for your architecture 00392 #endif 00393 typedef struct _TMAsmProxy { 00394 char a; 00395 } TMAsmProxy; 00396 #endif 00397 00398 typedef struct _TMProxyImpl { 00399 LPVOID *lpvtbl; 00400 const IRpcProxyBufferVtbl *lpvtbl2; 00401 LONG ref; 00402 00403 TMAsmProxy *asmstubs; 00404 ITypeInfo* tinfo; 00405 IRpcChannelBuffer* chanbuf; 00406 IID iid; 00407 CRITICAL_SECTION crit; 00408 IUnknown *outerunknown; 00409 IDispatch *dispatch; 00410 IRpcProxyBuffer *dispatch_proxy; 00411 } TMProxyImpl; 00412 00413 static HRESULT WINAPI 00414 TMProxyImpl_QueryInterface(LPRPCPROXYBUFFER iface, REFIID riid, LPVOID *ppv) 00415 { 00416 TRACE("()\n"); 00417 if (IsEqualIID(riid,&IID_IUnknown)||IsEqualIID(riid,&IID_IRpcProxyBuffer)) { 00418 *ppv = iface; 00419 IRpcProxyBuffer_AddRef(iface); 00420 return S_OK; 00421 } 00422 FIXME("no interface for %s\n",debugstr_guid(riid)); 00423 return E_NOINTERFACE; 00424 } 00425 00426 static ULONG WINAPI 00427 TMProxyImpl_AddRef(LPRPCPROXYBUFFER iface) 00428 { 00429 ICOM_THIS_MULTI(TMProxyImpl,lpvtbl2,iface); 00430 ULONG refCount = InterlockedIncrement(&This->ref); 00431 00432 TRACE("(%p)->(ref before=%u)\n",This, refCount - 1); 00433 00434 return refCount; 00435 } 00436 00437 static ULONG WINAPI 00438 TMProxyImpl_Release(LPRPCPROXYBUFFER iface) 00439 { 00440 ICOM_THIS_MULTI(TMProxyImpl,lpvtbl2,iface); 00441 ULONG refCount = InterlockedDecrement(&This->ref); 00442 00443 TRACE("(%p)->(ref before=%u)\n",This, refCount + 1); 00444 00445 if (!refCount) 00446 { 00447 if (This->dispatch_proxy) IRpcProxyBuffer_Release(This->dispatch_proxy); 00448 This->crit.DebugInfo->Spare[0] = 0; 00449 DeleteCriticalSection(&This->crit); 00450 if (This->chanbuf) IRpcChannelBuffer_Release(This->chanbuf); 00451 VirtualFree(This->asmstubs, 0, MEM_RELEASE); 00452 HeapFree(GetProcessHeap(), 0, This->lpvtbl); 00453 ITypeInfo_Release(This->tinfo); 00454 CoTaskMemFree(This); 00455 } 00456 return refCount; 00457 } 00458 00459 static HRESULT WINAPI 00460 TMProxyImpl_Connect( 00461 LPRPCPROXYBUFFER iface,IRpcChannelBuffer* pRpcChannelBuffer) 00462 { 00463 ICOM_THIS_MULTI(TMProxyImpl, lpvtbl2, iface); 00464 00465 TRACE("(%p)\n", pRpcChannelBuffer); 00466 00467 EnterCriticalSection(&This->crit); 00468 00469 IRpcChannelBuffer_AddRef(pRpcChannelBuffer); 00470 This->chanbuf = pRpcChannelBuffer; 00471 00472 LeaveCriticalSection(&This->crit); 00473 00474 if (This->dispatch_proxy) 00475 { 00476 IRpcChannelBuffer *pDelegateChannel; 00477 HRESULT hr = TMarshalDispatchChannel_Create(pRpcChannelBuffer, &This->iid, &pDelegateChannel); 00478 if (FAILED(hr)) 00479 return hr; 00480 hr = IRpcProxyBuffer_Connect(This->dispatch_proxy, pDelegateChannel); 00481 IRpcChannelBuffer_Release(pDelegateChannel); 00482 return hr; 00483 } 00484 00485 return S_OK; 00486 } 00487 00488 static void WINAPI 00489 TMProxyImpl_Disconnect(LPRPCPROXYBUFFER iface) 00490 { 00491 ICOM_THIS_MULTI(TMProxyImpl, lpvtbl2, iface); 00492 00493 TRACE("()\n"); 00494 00495 EnterCriticalSection(&This->crit); 00496 00497 IRpcChannelBuffer_Release(This->chanbuf); 00498 This->chanbuf = NULL; 00499 00500 LeaveCriticalSection(&This->crit); 00501 00502 if (This->dispatch_proxy) 00503 IRpcProxyBuffer_Disconnect(This->dispatch_proxy); 00504 } 00505 00506 00507 static const IRpcProxyBufferVtbl tmproxyvtable = { 00508 TMProxyImpl_QueryInterface, 00509 TMProxyImpl_AddRef, 00510 TMProxyImpl_Release, 00511 TMProxyImpl_Connect, 00512 TMProxyImpl_Disconnect 00513 }; 00514 00515 /* how much space do we use on stack in DWORD steps. */ 00516 static int 00517 _argsize(TYPEDESC *tdesc, ITypeInfo *tinfo) { 00518 switch (tdesc->vt) { 00519 case VT_I8: 00520 case VT_UI8: 00521 return 8/sizeof(DWORD); 00522 case VT_R8: 00523 return sizeof(double)/sizeof(DWORD); 00524 case VT_CY: 00525 return sizeof(CY)/sizeof(DWORD); 00526 case VT_DATE: 00527 return sizeof(DATE)/sizeof(DWORD); 00528 case VT_DECIMAL: 00529 return (sizeof(DECIMAL)+3)/sizeof(DWORD); 00530 case VT_VARIANT: 00531 return (sizeof(VARIANT)+3)/sizeof(DWORD); 00532 case VT_USERDEFINED: 00533 { 00534 ITypeInfo *tinfo2; 00535 TYPEATTR *tattr; 00536 HRESULT hres; 00537 DWORD ret; 00538 00539 hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.hreftype,&tinfo2); 00540 if (FAILED(hres)) 00541 return 0; /* should fail critically in serialize_param */ 00542 ITypeInfo_GetTypeAttr(tinfo2,&tattr); 00543 ret = (tattr->cbSizeInstance+3)/sizeof(DWORD); 00544 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr); 00545 ITypeInfo_Release(tinfo2); 00546 return ret; 00547 } 00548 default: 00549 return 1; 00550 } 00551 } 00552 00553 /* how much space do we use on the heap (in bytes) */ 00554 static int 00555 _xsize(const TYPEDESC *td, ITypeInfo *tinfo) { 00556 switch (td->vt) { 00557 case VT_DATE: 00558 return sizeof(DATE); 00559 case VT_CY: 00560 return sizeof(CY); 00561 /* FIXME: VT_BOOL should return 2? */ 00562 case VT_VARIANT: 00563 return sizeof(VARIANT)+3; /* FIXME: why the +3? */ 00564 case VT_CARRAY: { 00565 int i, arrsize = 1; 00566 const ARRAYDESC *adesc = td->u.lpadesc; 00567 00568 for (i=0;i<adesc->cDims;i++) 00569 arrsize *= adesc->rgbounds[i].cElements; 00570 return arrsize*_xsize(&adesc->tdescElem, tinfo); 00571 } 00572 case VT_UI8: 00573 case VT_I8: 00574 case VT_R8: 00575 return 8; 00576 case VT_UI2: 00577 case VT_I2: 00578 return 2; 00579 case VT_UI1: 00580 case VT_I1: 00581 return 1; 00582 case VT_USERDEFINED: 00583 { 00584 ITypeInfo *tinfo2; 00585 TYPEATTR *tattr; 00586 HRESULT hres; 00587 DWORD ret; 00588 00589 hres = ITypeInfo_GetRefTypeInfo(tinfo,td->u.hreftype,&tinfo2); 00590 if (FAILED(hres)) 00591 return 0; 00592 ITypeInfo_GetTypeAttr(tinfo2,&tattr); 00593 ret = tattr->cbSizeInstance; 00594 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr); 00595 ITypeInfo_Release(tinfo2); 00596 return ret; 00597 } 00598 default: 00599 return 4; 00600 } 00601 } 00602 00603 static HRESULT 00604 serialize_param( 00605 ITypeInfo *tinfo, 00606 BOOL writeit, 00607 BOOL debugout, 00608 BOOL dealloc, 00609 TYPEDESC *tdesc, 00610 DWORD *arg, 00611 marshal_state *buf) 00612 { 00613 HRESULT hres = S_OK; 00614 VARTYPE vartype; 00615 00616 TRACE("(tdesc.vt %s)\n",debugstr_vt(tdesc->vt)); 00617 00618 vartype = tdesc->vt; 00619 if ((vartype & 0xf000) == VT_ARRAY) 00620 vartype = VT_SAFEARRAY; 00621 00622 switch (vartype) { 00623 case VT_I8: 00624 case VT_UI8: 00625 case VT_R8: 00626 case VT_CY: 00627 hres = S_OK; 00628 if (debugout) TRACE_(olerelay)("%x%x\n",arg[0],arg[1]); 00629 if (writeit) 00630 hres = xbuf_add(buf,(LPBYTE)arg,8); 00631 return hres; 00632 case VT_BOOL: 00633 case VT_ERROR: 00634 case VT_INT: 00635 case VT_UINT: 00636 case VT_I4: 00637 case VT_R4: 00638 case VT_UI4: 00639 hres = S_OK; 00640 if (debugout) TRACE_(olerelay)("%x\n",*arg); 00641 if (writeit) 00642 hres = xbuf_add(buf,(LPBYTE)arg,sizeof(DWORD)); 00643 return hres; 00644 case VT_I2: 00645 case VT_UI2: 00646 hres = S_OK; 00647 if (debugout) TRACE_(olerelay)("%04x\n",*arg & 0xffff); 00648 if (writeit) 00649 hres = xbuf_add(buf,(LPBYTE)arg,sizeof(DWORD)); 00650 return hres; 00651 case VT_I1: 00652 case VT_UI1: 00653 hres = S_OK; 00654 if (debugout) TRACE_(olerelay)("%02x\n",*arg & 0xff); 00655 if (writeit) 00656 hres = xbuf_add(buf,(LPBYTE)arg,sizeof(DWORD)); 00657 return hres; 00658 case VT_VARIANT: { 00659 if (debugout) TRACE_(olerelay)("Vt(%s%s)(",debugstr_vt(V_VT((VARIANT *)arg)),debugstr_vf(V_VT((VARIANT *)arg))); 00660 if (writeit) 00661 { 00662 ULONG flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION); 00663 ULONG size = VARIANT_UserSize(&flags, buf->curoff, (VARIANT *)arg); 00664 xbuf_resize(buf, size); 00665 VARIANT_UserMarshal(&flags, buf->base + buf->curoff, (VARIANT *)arg); 00666 buf->curoff = size; 00667 } 00668 if (dealloc) 00669 { 00670 ULONG flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION); 00671 VARIANT_UserFree(&flags, (VARIANT *)arg); 00672 } 00673 return S_OK; 00674 } 00675 case VT_BSTR: { 00676 if (debugout) { 00677 if (*arg) 00678 TRACE_(olerelay)("%s",relaystr((WCHAR*)*arg)); 00679 else 00680 TRACE_(olerelay)("<bstr NULL>"); 00681 } 00682 if (writeit) 00683 { 00684 ULONG flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION); 00685 ULONG size = BSTR_UserSize(&flags, buf->curoff, (BSTR *)arg); 00686 xbuf_resize(buf, size); 00687 BSTR_UserMarshal(&flags, buf->base + buf->curoff, (BSTR *)arg); 00688 buf->curoff = size; 00689 } 00690 if (dealloc) 00691 { 00692 ULONG flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION); 00693 BSTR_UserFree(&flags, (BSTR *)arg); 00694 } 00695 return S_OK; 00696 } 00697 case VT_PTR: { 00698 DWORD cookie; 00699 BOOL derefhere = TRUE; 00700 00701 if (tdesc->u.lptdesc->vt == VT_USERDEFINED) { 00702 ITypeInfo *tinfo2; 00703 TYPEATTR *tattr; 00704 00705 hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.lptdesc->u.hreftype,&tinfo2); 00706 if (hres) { 00707 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED.\n",tdesc->u.lptdesc->u.hreftype); 00708 return hres; 00709 } 00710 ITypeInfo_GetTypeAttr(tinfo2,&tattr); 00711 switch (tattr->typekind) { 00712 case TKIND_ALIAS: 00713 if (tattr->tdescAlias.vt == VT_USERDEFINED) 00714 { 00715 DWORD href = tattr->tdescAlias.u.hreftype; 00716 ITypeInfo_ReleaseTypeAttr(tinfo, tattr); 00717 ITypeInfo_Release(tinfo2); 00718 hres = ITypeInfo_GetRefTypeInfo(tinfo,href,&tinfo2); 00719 if (hres) { 00720 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED.\n",tdesc->u.lptdesc->u.hreftype); 00721 return hres; 00722 } 00723 ITypeInfo_GetTypeAttr(tinfo2,&tattr); 00724 derefhere = (tattr->typekind != TKIND_DISPATCH && tattr->typekind != TKIND_INTERFACE); 00725 } 00726 break; 00727 case TKIND_ENUM: /* confirmed */ 00728 case TKIND_RECORD: /* FIXME: mostly untested */ 00729 break; 00730 case TKIND_DISPATCH: /* will be done in VT_USERDEFINED case */ 00731 case TKIND_INTERFACE: /* will be done in VT_USERDEFINED case */ 00732 derefhere=FALSE; 00733 break; 00734 default: 00735 FIXME("unhandled switch cases tattr->typekind %d\n", tattr->typekind); 00736 derefhere=FALSE; 00737 break; 00738 } 00739 ITypeInfo_ReleaseTypeAttr(tinfo, tattr); 00740 ITypeInfo_Release(tinfo2); 00741 } 00742 00743 if (debugout) TRACE_(olerelay)("*"); 00744 /* Write always, so the other side knows when it gets a NULL pointer. 00745 */ 00746 cookie = *arg ? 0x42424242 : 0; 00747 hres = xbuf_add(buf,(LPBYTE)&cookie,sizeof(cookie)); 00748 if (hres) 00749 return hres; 00750 if (!*arg) { 00751 if (debugout) TRACE_(olerelay)("NULL"); 00752 return S_OK; 00753 } 00754 hres = serialize_param(tinfo,writeit,debugout,dealloc,tdesc->u.lptdesc,(DWORD*)*arg,buf); 00755 if (derefhere && dealloc) HeapFree(GetProcessHeap(),0,(LPVOID)*arg); 00756 return hres; 00757 } 00758 case VT_UNKNOWN: 00759 if (debugout) TRACE_(olerelay)("unk(0x%x)",*arg); 00760 if (writeit) 00761 hres = _marshal_interface(buf,&IID_IUnknown,(LPUNKNOWN)*arg); 00762 if (dealloc && *(IUnknown **)arg) 00763 IUnknown_Release((LPUNKNOWN)*arg); 00764 return hres; 00765 case VT_DISPATCH: 00766 if (debugout) TRACE_(olerelay)("idisp(0x%x)",*arg); 00767 if (writeit) 00768 hres = _marshal_interface(buf,&IID_IDispatch,(LPUNKNOWN)*arg); 00769 if (dealloc && *(IUnknown **)arg) 00770 IUnknown_Release((LPUNKNOWN)*arg); 00771 return hres; 00772 case VT_VOID: 00773 if (debugout) TRACE_(olerelay)("<void>"); 00774 return S_OK; 00775 case VT_USERDEFINED: { 00776 ITypeInfo *tinfo2; 00777 TYPEATTR *tattr; 00778 00779 hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.hreftype,&tinfo2); 00780 if (hres) { 00781 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED.\n",tdesc->u.hreftype); 00782 return hres; 00783 } 00784 ITypeInfo_GetTypeAttr(tinfo2,&tattr); 00785 switch (tattr->typekind) { 00786 case TKIND_DISPATCH: 00787 case TKIND_INTERFACE: 00788 if (writeit) 00789 hres=_marshal_interface(buf,&(tattr->guid),(LPUNKNOWN)arg); 00790 if (dealloc) 00791 IUnknown_Release((LPUNKNOWN)arg); 00792 break; 00793 case TKIND_RECORD: { 00794 int i; 00795 if (debugout) TRACE_(olerelay)("{"); 00796 for (i=0;i<tattr->cVars;i++) { 00797 VARDESC *vdesc; 00798 ELEMDESC *elem2; 00799 TYPEDESC *tdesc2; 00800 00801 hres = ITypeInfo2_GetVarDesc(tinfo2, i, &vdesc); 00802 if (hres) { 00803 ERR("Could not get vardesc of %d\n",i); 00804 return hres; 00805 } 00806 elem2 = &vdesc->elemdescVar; 00807 tdesc2 = &elem2->tdesc; 00808 hres = serialize_param( 00809 tinfo2, 00810 writeit, 00811 debugout, 00812 dealloc, 00813 tdesc2, 00814 (DWORD*)(((LPBYTE)arg)+vdesc->u.oInst), 00815 buf 00816 ); 00817 ITypeInfo_ReleaseVarDesc(tinfo2, vdesc); 00818 if (hres!=S_OK) 00819 return hres; 00820 if (debugout && (i<(tattr->cVars-1))) 00821 TRACE_(olerelay)(","); 00822 } 00823 if (debugout) TRACE_(olerelay)("}"); 00824 break; 00825 } 00826 case TKIND_ALIAS: 00827 hres = serialize_param(tinfo2,writeit,debugout,dealloc,&tattr->tdescAlias,arg,buf); 00828 break; 00829 case TKIND_ENUM: 00830 hres = S_OK; 00831 if (debugout) TRACE_(olerelay)("%x",*arg); 00832 if (writeit) 00833 hres = xbuf_add(buf,(LPBYTE)arg,sizeof(DWORD)); 00834 break; 00835 default: 00836 FIXME("Unhandled typekind %d\n",tattr->typekind); 00837 hres = E_FAIL; 00838 break; 00839 } 00840 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr); 00841 ITypeInfo_Release(tinfo2); 00842 return hres; 00843 } 00844 case VT_CARRAY: { 00845 ARRAYDESC *adesc = tdesc->u.lpadesc; 00846 int i, arrsize = 1; 00847 00848 if (debugout) TRACE_(olerelay)("carr"); 00849 for (i=0;i<adesc->cDims;i++) { 00850 if (debugout) TRACE_(olerelay)("[%d]",adesc->rgbounds[i].cElements); 00851 arrsize *= adesc->rgbounds[i].cElements; 00852 } 00853 if (debugout) TRACE_(olerelay)("(vt %s)",debugstr_vt(adesc->tdescElem.vt)); 00854 if (debugout) TRACE_(olerelay)("["); 00855 for (i=0;i<arrsize;i++) { 00856 hres = serialize_param(tinfo, writeit, debugout, dealloc, &adesc->tdescElem, (DWORD*)((LPBYTE)(*arg)+i*_xsize(&adesc->tdescElem, tinfo)), buf); 00857 if (hres) 00858 return hres; 00859 if (debugout && (i<arrsize-1)) TRACE_(olerelay)(","); 00860 } 00861 if (debugout) TRACE_(olerelay)("]"); 00862 if (dealloc) 00863 HeapFree(GetProcessHeap(), 0, *(void **)arg); 00864 return S_OK; 00865 } 00866 case VT_SAFEARRAY: { 00867 if (writeit) 00868 { 00869 ULONG flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION); 00870 ULONG size = LPSAFEARRAY_UserSize(&flags, buf->curoff, (LPSAFEARRAY *)arg); 00871 xbuf_resize(buf, size); 00872 LPSAFEARRAY_UserMarshal(&flags, buf->base + buf->curoff, (LPSAFEARRAY *)arg); 00873 buf->curoff = size; 00874 } 00875 if (dealloc) 00876 { 00877 ULONG flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION); 00878 LPSAFEARRAY_UserFree(&flags, (LPSAFEARRAY *)arg); 00879 } 00880 return S_OK; 00881 } 00882 default: 00883 ERR("Unhandled marshal type %d.\n",tdesc->vt); 00884 return S_OK; 00885 } 00886 } 00887 00888 static HRESULT 00889 deserialize_param( 00890 ITypeInfo *tinfo, 00891 BOOL readit, 00892 BOOL debugout, 00893 BOOL alloc, 00894 TYPEDESC *tdesc, 00895 DWORD *arg, 00896 marshal_state *buf) 00897 { 00898 HRESULT hres = S_OK; 00899 VARTYPE vartype; 00900 00901 TRACE("vt %s at %p\n",debugstr_vt(tdesc->vt),arg); 00902 00903 vartype = tdesc->vt; 00904 if ((vartype & 0xf000) == VT_ARRAY) 00905 vartype = VT_SAFEARRAY; 00906 00907 while (1) { 00908 switch (vartype) { 00909 case VT_VARIANT: { 00910 if (readit) 00911 { 00912 ULONG flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION); 00913 unsigned char *buffer; 00914 buffer = VARIANT_UserUnmarshal(&flags, buf->base + buf->curoff, (VARIANT *)arg); 00915 buf->curoff = buffer - buf->base; 00916 } 00917 return S_OK; 00918 } 00919 case VT_I8: 00920 case VT_UI8: 00921 case VT_R8: 00922 case VT_CY: 00923 if (readit) { 00924 hres = xbuf_get(buf,(LPBYTE)arg,8); 00925 if (hres) ERR("Failed to read integer 8 byte\n"); 00926 } 00927 if (debugout) TRACE_(olerelay)("%x%x",arg[0],arg[1]); 00928 return hres; 00929 case VT_ERROR: 00930 case VT_BOOL: 00931 case VT_I4: 00932 case VT_INT: 00933 case VT_UINT: 00934 case VT_R4: 00935 case VT_UI4: 00936 if (readit) { 00937 hres = xbuf_get(buf,(LPBYTE)arg,sizeof(DWORD)); 00938 if (hres) ERR("Failed to read integer 4 byte\n"); 00939 } 00940 if (debugout) TRACE_(olerelay)("%x",*arg); 00941 return hres; 00942 case VT_I2: 00943 case VT_UI2: 00944 if (readit) { 00945 DWORD x; 00946 hres = xbuf_get(buf,(LPBYTE)&x,sizeof(DWORD)); 00947 if (hres) ERR("Failed to read integer 4 byte\n"); 00948 memcpy(arg,&x,2); 00949 } 00950 if (debugout) TRACE_(olerelay)("%04x",*arg & 0xffff); 00951 return hres; 00952 case VT_I1: 00953 case VT_UI1: 00954 if (readit) { 00955 DWORD x; 00956 hres = xbuf_get(buf,(LPBYTE)&x,sizeof(DWORD)); 00957 if (hres) ERR("Failed to read integer 4 byte\n"); 00958 memcpy(arg,&x,1); 00959 } 00960 if (debugout) TRACE_(olerelay)("%02x",*arg & 0xff); 00961 return hres; 00962 case VT_BSTR: { 00963 if (readit) 00964 { 00965 ULONG flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION); 00966 unsigned char *buffer; 00967 buffer = BSTR_UserUnmarshal(&flags, buf->base + buf->curoff, (BSTR *)arg); 00968 buf->curoff = buffer - buf->base; 00969 if (debugout) TRACE_(olerelay)("%s",debugstr_w(*(BSTR *)arg)); 00970 } 00971 return S_OK; 00972 } 00973 case VT_PTR: { 00974 DWORD cookie; 00975 BOOL derefhere = TRUE; 00976 00977 if (tdesc->u.lptdesc->vt == VT_USERDEFINED) { 00978 ITypeInfo *tinfo2; 00979 TYPEATTR *tattr; 00980 00981 hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.lptdesc->u.hreftype,&tinfo2); 00982 if (hres) { 00983 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED.\n",tdesc->u.lptdesc->u.hreftype); 00984 return hres; 00985 } 00986 ITypeInfo_GetTypeAttr(tinfo2,&tattr); 00987 switch (tattr->typekind) { 00988 case TKIND_ALIAS: 00989 if (tattr->tdescAlias.vt == VT_USERDEFINED) 00990 { 00991 DWORD href = tattr->tdescAlias.u.hreftype; 00992 ITypeInfo_ReleaseTypeAttr(tinfo, tattr); 00993 ITypeInfo_Release(tinfo2); 00994 hres = ITypeInfo_GetRefTypeInfo(tinfo,href,&tinfo2); 00995 if (hres) { 00996 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED.\n",tdesc->u.lptdesc->u.hreftype); 00997 return hres; 00998 } 00999 ITypeInfo_GetTypeAttr(tinfo2,&tattr); 01000 derefhere = (tattr->typekind != TKIND_DISPATCH && tattr->typekind != TKIND_INTERFACE); 01001 } 01002 break; 01003 case TKIND_ENUM: /* confirmed */ 01004 case TKIND_RECORD: /* FIXME: mostly untested */ 01005 break; 01006 case TKIND_DISPATCH: /* will be done in VT_USERDEFINED case */ 01007 case TKIND_INTERFACE: /* will be done in VT_USERDEFINED case */ 01008 derefhere=FALSE; 01009 break; 01010 default: 01011 FIXME("unhandled switch cases tattr->typekind %d\n", tattr->typekind); 01012 derefhere=FALSE; 01013 break; 01014 } 01015 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr); 01016 ITypeInfo_Release(tinfo2); 01017 } 01018 /* read it in all cases, we need to know if we have 01019 * NULL pointer or not. 01020 */ 01021 hres = xbuf_get(buf,(LPBYTE)&cookie,sizeof(cookie)); 01022 if (hres) { 01023 ERR("Failed to load pointer cookie.\n"); 01024 return hres; 01025 } 01026 if (cookie != 0x42424242) { 01027 /* we read a NULL ptr from the remote side */ 01028 if (debugout) TRACE_(olerelay)("NULL"); 01029 *arg = 0; 01030 return S_OK; 01031 } 01032 if (debugout) TRACE_(olerelay)("*"); 01033 if (alloc) { 01034 /* Allocate space for the referenced struct */ 01035 if (derefhere) 01036 *arg=(DWORD)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,_xsize(tdesc->u.lptdesc, tinfo)); 01037 } 01038 if (derefhere) 01039 return deserialize_param(tinfo, readit, debugout, alloc, tdesc->u.lptdesc, (LPDWORD)*arg, buf); 01040 else 01041 return deserialize_param(tinfo, readit, debugout, alloc, tdesc->u.lptdesc, arg, buf); 01042 } 01043 case VT_UNKNOWN: 01044 /* FIXME: UNKNOWN is unknown ..., but allocate 4 byte for it */ 01045 if (alloc) 01046 *arg=(DWORD)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DWORD)); 01047 hres = S_OK; 01048 if (readit) 01049 hres = _unmarshal_interface(buf,&IID_IUnknown,(LPUNKNOWN*)arg); 01050 if (debugout) 01051 TRACE_(olerelay)("unk(%p)",arg); 01052 return hres; 01053 case VT_DISPATCH: 01054 hres = S_OK; 01055 if (readit) 01056 hres = _unmarshal_interface(buf,&IID_IDispatch,(LPUNKNOWN*)arg); 01057 if (debugout) 01058 TRACE_(olerelay)("idisp(%p)",arg); 01059 return hres; 01060 case VT_VOID: 01061 if (debugout) TRACE_(olerelay)("<void>"); 01062 return S_OK; 01063 case VT_USERDEFINED: { 01064 ITypeInfo *tinfo2; 01065 TYPEATTR *tattr; 01066 01067 hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.hreftype,&tinfo2); 01068 if (hres) { 01069 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED.\n",tdesc->u.hreftype); 01070 return hres; 01071 } 01072 hres = ITypeInfo_GetTypeAttr(tinfo2,&tattr); 01073 if (hres) { 01074 ERR("Could not get typeattr in VT_USERDEFINED.\n"); 01075 } else { 01076 switch (tattr->typekind) { 01077 case TKIND_DISPATCH: 01078 case TKIND_INTERFACE: 01079 if (readit) 01080 hres = _unmarshal_interface(buf,&(tattr->guid),(LPUNKNOWN*)arg); 01081 break; 01082 case TKIND_RECORD: { 01083 int i; 01084 01085 if (debugout) TRACE_(olerelay)("{"); 01086 for (i=0;i<tattr->cVars;i++) { 01087 VARDESC *vdesc; 01088 01089 hres = ITypeInfo2_GetVarDesc(tinfo2, i, &vdesc); 01090 if (hres) { 01091 ERR("Could not get vardesc of %d\n",i); 01092 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr); 01093 ITypeInfo_Release(tinfo2); 01094 return hres; 01095 } 01096 hres = deserialize_param( 01097 tinfo2, 01098 readit, 01099 debugout, 01100 alloc, 01101 &vdesc->elemdescVar.tdesc, 01102 (DWORD*)(((LPBYTE)arg)+vdesc->u.oInst), 01103 buf 01104 ); 01105 ITypeInfo2_ReleaseVarDesc(tinfo2, vdesc); 01106 if (debugout && (i<tattr->cVars-1)) TRACE_(olerelay)(","); 01107 } 01108 if (debugout) TRACE_(olerelay)("}"); 01109 break; 01110 } 01111 case TKIND_ALIAS: 01112 hres = deserialize_param(tinfo2,readit,debugout,alloc,&tattr->tdescAlias,arg,buf); 01113 break; 01114 case TKIND_ENUM: 01115 if (readit) { 01116 hres = xbuf_get(buf,(LPBYTE)arg,sizeof(DWORD)); 01117 if (hres) ERR("Failed to read enum (4 byte)\n"); 01118 } 01119 if (debugout) TRACE_(olerelay)("%x",*arg); 01120 break; 01121 default: 01122 ERR("Unhandled typekind %d\n",tattr->typekind); 01123 hres = E_FAIL; 01124 break; 01125 } 01126 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr); 01127 } 01128 if (hres) 01129 ERR("failed to stuballoc in TKIND_RECORD.\n"); 01130 ITypeInfo_Release(tinfo2); 01131 return hres; 01132 } 01133 case VT_CARRAY: { 01134 /* arg is pointing to the start of the array. */ 01135 ARRAYDESC *adesc = tdesc->u.lpadesc; 01136 int arrsize,i; 01137 arrsize = 1; 01138 if (adesc->cDims > 1) FIXME("cDims > 1 in VT_CARRAY. Does it work?\n"); 01139 for (i=0;i<adesc->cDims;i++) 01140 arrsize *= adesc->rgbounds[i].cElements; 01141 *arg=(DWORD)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,_xsize(tdesc->u.lptdesc, tinfo) * arrsize); 01142 for (i=0;i<arrsize;i++) 01143 deserialize_param( 01144 tinfo, 01145 readit, 01146 debugout, 01147 alloc, 01148 &adesc->tdescElem, 01149 (DWORD*)((LPBYTE)(*arg)+i*_xsize(&adesc->tdescElem, tinfo)), 01150 buf 01151 ); 01152 return S_OK; 01153 } 01154 case VT_SAFEARRAY: { 01155 if (readit) 01156 { 01157 ULONG flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION); 01158 unsigned char *buffer; 01159 buffer = LPSAFEARRAY_UserUnmarshal(&flags, buf->base + buf->curoff, (LPSAFEARRAY *)arg); 01160 buf->curoff = buffer - buf->base; 01161 } 01162 return S_OK; 01163 } 01164 default: 01165 ERR("No handler for VT type %d!\n",tdesc->vt); 01166 return S_OK; 01167 } 01168 } 01169 } 01170 01171 /* Retrieves a function's funcdesc, searching back into inherited interfaces. */ 01172 static HRESULT get_funcdesc(ITypeInfo *tinfo, int iMethod, ITypeInfo **tactual, const FUNCDESC **fdesc, 01173 BSTR *iname, BSTR *fname, UINT *num) 01174 { 01175 HRESULT hr; 01176 UINT i, impl_types; 01177 UINT inherited_funcs = 0; 01178 TYPEATTR *attr; 01179 01180 if (fname) *fname = NULL; 01181 if (iname) *iname = NULL; 01182 if (num) *num = 0; 01183 *tactual = NULL; 01184 01185 hr = ITypeInfo_GetTypeAttr(tinfo, &attr); 01186 if (FAILED(hr)) 01187 { 01188 ERR("GetTypeAttr failed with %x\n",hr); 01189 return hr; 01190 } 01191 01192 if(attr->typekind == TKIND_DISPATCH) 01193 { 01194 if(attr->wTypeFlags & TYPEFLAG_FDUAL) 01195 { 01196 HREFTYPE href; 01197 ITypeInfo *tinfo2; 01198 01199 hr = ITypeInfo_GetRefTypeOfImplType(tinfo, -1, &href); 01200 if(FAILED(hr)) 01201 { 01202 ERR("Cannot get interface href from dual dispinterface\n"); 01203 ITypeInfo_ReleaseTypeAttr(tinfo, attr); 01204 return hr; 01205 } 01206 hr = ITypeInfo_GetRefTypeInfo(tinfo, href, &tinfo2); 01207 if(FAILED(hr)) 01208 { 01209 ERR("Cannot get interface from dual dispinterface\n"); 01210 ITypeInfo_ReleaseTypeAttr(tinfo, attr); 01211 return hr; 01212 } 01213 hr = get_funcdesc(tinfo2, iMethod, tactual, fdesc, iname, fname, num); 01214 ITypeInfo_Release(tinfo2); 01215 ITypeInfo_ReleaseTypeAttr(tinfo, attr); 01216 return hr; 01217 } 01218 ERR("Shouldn't be called with a non-dual dispinterface\n"); 01219 return E_FAIL; 01220 } 01221 01222 impl_types = attr->cImplTypes; 01223 ITypeInfo_ReleaseTypeAttr(tinfo, attr); 01224 01225 for (i = 0; i < impl_types; i++) 01226 { 01227 HREFTYPE href; 01228 ITypeInfo *pSubTypeInfo; 01229 UINT sub_funcs; 01230 01231 hr = ITypeInfo_GetRefTypeOfImplType(tinfo, i, &href); 01232 if (FAILED(hr)) return hr; 01233 hr = ITypeInfo_GetRefTypeInfo(tinfo, href, &pSubTypeInfo); 01234 if (FAILED(hr)) return hr; 01235 01236 hr = get_funcdesc(pSubTypeInfo, iMethod, tactual, fdesc, iname, fname, &sub_funcs); 01237 inherited_funcs += sub_funcs; 01238 ITypeInfo_Release(pSubTypeInfo); 01239 if(SUCCEEDED(hr)) return hr; 01240 } 01241 if(iMethod < inherited_funcs) 01242 { 01243 ERR("shouldn't be here\n"); 01244 return E_INVALIDARG; 01245 } 01246 01247 for(i = inherited_funcs; i <= iMethod; i++) 01248 { 01249 hr = ITypeInfoImpl_GetInternalFuncDesc(tinfo, i - inherited_funcs, fdesc); 01250 if(FAILED(hr)) 01251 { 01252 if(num) *num = i; 01253 return hr; 01254 } 01255 } 01256 01257 /* found it. We don't care about num so zero it */ 01258 if(num) *num = 0; 01259 *tactual = tinfo; 01260 ITypeInfo_AddRef(*tactual); 01261 if (fname) ITypeInfo_GetDocumentation(tinfo,(*fdesc)->memid,fname,NULL,NULL,NULL); 01262 if (iname) ITypeInfo_GetDocumentation(tinfo,-1,iname,NULL,NULL,NULL); 01263 return S_OK; 01264 } 01265 01266 static inline BOOL is_in_elem(const ELEMDESC *elem) 01267 { 01268 return (elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN || !elem->u.paramdesc.wParamFlags); 01269 } 01270 01271 static inline BOOL is_out_elem(const ELEMDESC *elem) 01272 { 01273 return (elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT || !elem->u.paramdesc.wParamFlags); 01274 } 01275 01276 static DWORD 01277 xCall(LPVOID retptr, int method, TMProxyImpl *tpinfo /*, args */) 01278 { 01279 DWORD *args = ((DWORD*)&tpinfo)+1, *xargs; 01280 const FUNCDESC *fdesc; 01281 HRESULT hres; 01282 int i, relaydeb = TRACE_ON(olerelay); 01283 marshal_state buf; 01284 RPCOLEMESSAGE msg; 01285 ULONG status; 01286 BSTR fname,iname; 01287 BSTR names[10]; 01288 UINT nrofnames; 01289 DWORD remoteresult = 0; 01290 ITypeInfo *tinfo; 01291 IRpcChannelBuffer *chanbuf; 01292 01293 EnterCriticalSection(&tpinfo->crit); 01294 01295 hres = get_funcdesc(tpinfo->tinfo,method,&tinfo,&fdesc,&iname,&fname,NULL); 01296 if (hres) { 01297 ERR("Did not find typeinfo/funcdesc entry for method %d!\n",method); 01298 LeaveCriticalSection(&tpinfo->crit); 01299 return E_FAIL; 01300 } 01301 01302 if (!tpinfo->chanbuf) 01303 { 01304 WARN("Tried to use disconnected proxy\n"); 01305 ITypeInfo_Release(tinfo); 01306 LeaveCriticalSection(&tpinfo->crit); 01307 return RPC_E_DISCONNECTED; 01308 } 01309 chanbuf = tpinfo->chanbuf; 01310 IRpcChannelBuffer_AddRef(chanbuf); 01311 01312 LeaveCriticalSection(&tpinfo->crit); 01313 01314 if (relaydeb) { 01315 TRACE_(olerelay)("->"); 01316 if (iname) 01317 TRACE_(olerelay)("%s:",relaystr(iname)); 01318 if (fname) 01319 TRACE_(olerelay)("%s(%d)",relaystr(fname),method); 01320 else 01321 TRACE_(olerelay)("%d",method); 01322 TRACE_(olerelay)("("); 01323 } 01324 01325 SysFreeString(iname); 01326 SysFreeString(fname); 01327 01328 memset(&buf,0,sizeof(buf)); 01329 01330 /* normal typelib driven serializing */ 01331 01332 /* Need them for hack below */ 01333 memset(names,0,sizeof(names)); 01334 if (ITypeInfo_GetNames(tinfo,fdesc->memid,names,sizeof(names)/sizeof(names[0]),&nrofnames)) 01335 nrofnames = 0; 01336 if (nrofnames > sizeof(names)/sizeof(names[0])) 01337 ERR("Need more names!\n"); 01338 01339 xargs = args; 01340 for (i=0;i<fdesc->cParams;i++) { 01341 ELEMDESC *elem = fdesc->lprgelemdescParam+i; 01342 if (relaydeb) { 01343 if (i) TRACE_(olerelay)(","); 01344 if (i+1<nrofnames && names[i+1]) 01345 TRACE_(olerelay)("%s=",relaystr(names[i+1])); 01346 } 01347 /* No need to marshal other data than FIN and any VT_PTR. */ 01348 if (!is_in_elem(elem) && (elem->tdesc.vt != VT_PTR)) { 01349 xargs+=_argsize(&elem->tdesc, tinfo); 01350 if (relaydeb) TRACE_(olerelay)("[out]"); 01351 continue; 01352 } 01353 hres = serialize_param( 01354 tinfo, 01355 is_in_elem(elem), 01356 relaydeb, 01357 FALSE, 01358 &elem->tdesc, 01359 xargs, 01360 &buf 01361 ); 01362 01363 if (hres) { 01364 ERR("Failed to serialize param, hres %x\n",hres); 01365 break; 01366 } 01367 xargs+=_argsize(&elem->tdesc, tinfo); 01368 } 01369 if (relaydeb) TRACE_(olerelay)(")"); 01370 01371 memset(&msg,0,sizeof(msg)); 01372 msg.cbBuffer = buf.curoff; 01373 msg.iMethod = method; 01374 hres = IRpcChannelBuffer_GetBuffer(chanbuf,&msg,&(tpinfo->iid)); 01375 if (hres) { 01376 ERR("RpcChannelBuffer GetBuffer failed, %x\n",hres); 01377 goto exit; 01378 } 01379 memcpy(msg.Buffer,buf.base,buf.curoff); 01380 if (relaydeb) TRACE_(olerelay)("\n"); 01381 hres = IRpcChannelBuffer_SendReceive(chanbuf,&msg,&status); 01382 if (hres) { 01383 ERR("RpcChannelBuffer SendReceive failed, %x\n",hres); 01384 goto exit; 01385 } 01386 01387 if (relaydeb) TRACE_(olerelay)(" status = %08x (",status); 01388 if (buf.base) 01389 buf.base = HeapReAlloc(GetProcessHeap(),0,buf.base,msg.cbBuffer); 01390 else 01391 buf.base = HeapAlloc(GetProcessHeap(),0,msg.cbBuffer); 01392 buf.size = msg.cbBuffer; 01393 memcpy(buf.base,msg.Buffer,buf.size); 01394 buf.curoff = 0; 01395 01396 /* generic deserializer using typelib description */ 01397 xargs = args; 01398 status = S_OK; 01399 for (i=0;i<fdesc->cParams;i++) { 01400 ELEMDESC *elem = fdesc->lprgelemdescParam+i; 01401 01402 if (relaydeb) { 01403 if (i) TRACE_(olerelay)(","); 01404 if (i+1<nrofnames && names[i+1]) TRACE_(olerelay)("%s=",relaystr(names[i+1])); 01405 } 01406 /* No need to marshal other data than FOUT and any VT_PTR */ 01407 if (!is_out_elem(elem) && (elem->tdesc.vt != VT_PTR)) { 01408 xargs += _argsize(&elem->tdesc, tinfo); 01409 if (relaydeb) TRACE_(olerelay)("[in]"); 01410 continue; 01411 } 01412 hres = deserialize_param( 01413 tinfo, 01414 is_out_elem(elem), 01415 relaydeb, 01416 FALSE, 01417 &(elem->tdesc), 01418 xargs, 01419 &buf 01420 ); 01421 if (hres) { 01422 ERR("Failed to unmarshall param, hres %x\n",hres); 01423 status = hres; 01424 break; 01425 } 01426 xargs += _argsize(&elem->tdesc, tinfo); 01427 } 01428 01429 hres = xbuf_get(&buf, (LPBYTE)&remoteresult, sizeof(DWORD)); 01430 if (hres != S_OK) 01431 goto exit; 01432 if (relaydeb) TRACE_(olerelay)(") = %08x\n", remoteresult); 01433 01434 hres = remoteresult; 01435 01436 exit: 01437 IRpcChannelBuffer_FreeBuffer(chanbuf,&msg); 01438 for (i = 0; i < nrofnames; i++) 01439 SysFreeString(names[i]); 01440 HeapFree(GetProcessHeap(),0,buf.base); 01441 IRpcChannelBuffer_Release(chanbuf); 01442 ITypeInfo_Release(tinfo); 01443 TRACE("-- 0x%08x\n", hres); 01444 return hres; 01445 } 01446 01447 static HRESULT WINAPI ProxyIUnknown_QueryInterface(IUnknown *iface, REFIID riid, void **ppv) 01448 { 01449 TMProxyImpl *proxy = (TMProxyImpl *)iface; 01450 01451 TRACE("(%s, %p)\n", debugstr_guid(riid), ppv); 01452 01453 if (proxy->outerunknown) 01454 return IUnknown_QueryInterface(proxy->outerunknown, riid, ppv); 01455 01456 FIXME("No interface\n"); 01457 return E_NOINTERFACE; 01458 } 01459 01460 static ULONG WINAPI ProxyIUnknown_AddRef(IUnknown *iface) 01461 { 01462 TMProxyImpl *proxy = (TMProxyImpl *)iface; 01463 01464 TRACE("\n"); 01465 01466 if (proxy->outerunknown) 01467 return IUnknown_AddRef(proxy->outerunknown); 01468 01469 return 2; /* FIXME */ 01470 } 01471 01472 static ULONG WINAPI ProxyIUnknown_Release(IUnknown *iface) 01473 { 01474 TMProxyImpl *proxy = (TMProxyImpl *)iface; 01475 01476 TRACE("\n"); 01477 01478 if (proxy->outerunknown) 01479 return IUnknown_Release(proxy->outerunknown); 01480 01481 return 1; /* FIXME */ 01482 } 01483 01484 static HRESULT WINAPI ProxyIDispatch_GetTypeInfoCount(LPDISPATCH iface, UINT * pctinfo) 01485 { 01486 TMProxyImpl *This = (TMProxyImpl *)iface; 01487 01488 TRACE("(%p)\n", pctinfo); 01489 01490 return IDispatch_GetTypeInfoCount(This->dispatch, pctinfo); 01491 } 01492 01493 static HRESULT WINAPI ProxyIDispatch_GetTypeInfo(LPDISPATCH iface, UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo) 01494 { 01495 TMProxyImpl *This = (TMProxyImpl *)iface; 01496 01497 TRACE("(%d, %x, %p)\n", iTInfo, lcid, ppTInfo); 01498 01499 return IDispatch_GetTypeInfo(This->dispatch, iTInfo, lcid, ppTInfo); 01500 } 01501 01502 static HRESULT WINAPI ProxyIDispatch_GetIDsOfNames(LPDISPATCH iface, REFIID riid, LPOLESTR * rgszNames, UINT cNames, LCID lcid, DISPID * rgDispId) 01503 { 01504 TMProxyImpl *This = (TMProxyImpl *)iface; 01505 01506 TRACE("(%s, %p, %d, 0x%x, %p)\n", debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId); 01507 01508 return IDispatch_GetIDsOfNames(This->dispatch, riid, rgszNames, 01509 cNames, lcid, rgDispId); 01510 } 01511 01512 static HRESULT WINAPI ProxyIDispatch_Invoke(LPDISPATCH iface, DISPID dispIdMember, REFIID riid, LCID lcid, 01513 WORD wFlags, DISPPARAMS * pDispParams, VARIANT * pVarResult, 01514 EXCEPINFO * pExcepInfo, UINT * puArgErr) 01515 { 01516 TMProxyImpl *This = (TMProxyImpl *)iface; 01517 01518 TRACE("(%d, %s, 0x%x, 0x%x, %p, %p, %p, %p)\n", dispIdMember, 01519 debugstr_guid(riid), lcid, wFlags, pDispParams, pVarResult, 01520 pExcepInfo, puArgErr); 01521 01522 return IDispatch_Invoke(This->dispatch, dispIdMember, riid, lcid, 01523 wFlags, pDispParams, pVarResult, pExcepInfo, 01524 puArgErr); 01525 } 01526 01527 typedef struct 01528 { 01529 const IRpcChannelBufferVtbl *lpVtbl; 01530 LONG refs; 01531 /* the IDispatch-derived interface we are handling */ 01532 IID tmarshal_iid; 01533 IRpcChannelBuffer *pDelegateChannel; 01534 } TMarshalDispatchChannel; 01535 01536 static HRESULT WINAPI TMarshalDispatchChannel_QueryInterface(LPRPCCHANNELBUFFER iface, REFIID riid, LPVOID *ppv) 01537 { 01538 *ppv = NULL; 01539 if (IsEqualIID(riid,&IID_IRpcChannelBuffer) || IsEqualIID(riid,&IID_IUnknown)) 01540 { 01541 *ppv = iface; 01542 IUnknown_AddRef(iface); 01543 return S_OK; 01544 } 01545 return E_NOINTERFACE; 01546 } 01547 01548 static ULONG WINAPI TMarshalDispatchChannel_AddRef(LPRPCCHANNELBUFFER iface) 01549 { 01550 TMarshalDispatchChannel *This = (TMarshalDispatchChannel *)iface; 01551 return InterlockedIncrement(&This->refs); 01552 } 01553 01554 static ULONG WINAPI TMarshalDispatchChannel_Release(LPRPCCHANNELBUFFER iface) 01555 { 01556 TMarshalDispatchChannel *This = (TMarshalDispatchChannel *)iface; 01557 ULONG ref; 01558 01559 ref = InterlockedDecrement(&This->refs); 01560 if (ref) 01561 return ref; 01562 01563 IRpcChannelBuffer_Release(This->pDelegateChannel); 01564 HeapFree(GetProcessHeap(), 0, This); 01565 return 0; 01566 } 01567 01568 static HRESULT WINAPI TMarshalDispatchChannel_GetBuffer(LPRPCCHANNELBUFFER iface, RPCOLEMESSAGE* olemsg, REFIID riid) 01569 { 01570 TMarshalDispatchChannel *This = (TMarshalDispatchChannel *)iface; 01571 TRACE("(%p, %s)\n", olemsg, debugstr_guid(riid)); 01572 /* Note: we are pretending to invoke a method on the interface identified 01573 * by tmarshal_iid so that we can re-use the IDispatch proxy/stub code 01574 * without the RPC runtime getting confused by not exporting an IDispatch interface */ 01575 return IRpcChannelBuffer_GetBuffer(This->pDelegateChannel, olemsg, &This->tmarshal_iid); 01576 } 01577 01578 static HRESULT WINAPI TMarshalDispatchChannel_SendReceive(LPRPCCHANNELBUFFER iface, RPCOLEMESSAGE *olemsg, ULONG *pstatus) 01579 { 01580 TMarshalDispatchChannel *This = (TMarshalDispatchChannel *)iface; 01581 TRACE("(%p, %p)\n", olemsg, pstatus); 01582 return IRpcChannelBuffer_SendReceive(This->pDelegateChannel, olemsg, pstatus); 01583 } 01584 01585 static HRESULT WINAPI TMarshalDispatchChannel_FreeBuffer(LPRPCCHANNELBUFFER iface, RPCOLEMESSAGE* olemsg) 01586 { 01587 TMarshalDispatchChannel *This = (TMarshalDispatchChannel *)iface; 01588 TRACE("(%p)\n", olemsg); 01589 return IRpcChannelBuffer_FreeBuffer(This->pDelegateChannel, olemsg); 01590 } 01591 01592 static HRESULT WINAPI TMarshalDispatchChannel_GetDestCtx(LPRPCCHANNELBUFFER iface, DWORD* pdwDestContext, void** ppvDestContext) 01593 { 01594 TMarshalDispatchChannel *This = (TMarshalDispatchChannel *)iface; 01595 TRACE("(%p,%p)\n", pdwDestContext, ppvDestContext); 01596 return IRpcChannelBuffer_GetDestCtx(This->pDelegateChannel, pdwDestContext, ppvDestContext); 01597 } 01598 01599 static HRESULT WINAPI TMarshalDispatchChannel_IsConnected(LPRPCCHANNELBUFFER iface) 01600 { 01601 TMarshalDispatchChannel *This = (TMarshalDispatchChannel *)iface; 01602 TRACE("()\n"); 01603 return IRpcChannelBuffer_IsConnected(This->pDelegateChannel); 01604 } 01605 01606 static const IRpcChannelBufferVtbl TMarshalDispatchChannelVtbl = 01607 { 01608 TMarshalDispatchChannel_QueryInterface, 01609 TMarshalDispatchChannel_AddRef, 01610 TMarshalDispatchChannel_Release, 01611 TMarshalDispatchChannel_GetBuffer, 01612 TMarshalDispatchChannel_SendReceive, 01613 TMarshalDispatchChannel_FreeBuffer, 01614 TMarshalDispatchChannel_GetDestCtx, 01615 TMarshalDispatchChannel_IsConnected 01616 }; 01617 01618 static HRESULT TMarshalDispatchChannel_Create( 01619 IRpcChannelBuffer *pDelegateChannel, REFIID tmarshal_riid, 01620 IRpcChannelBuffer **ppChannel) 01621 { 01622 TMarshalDispatchChannel *This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This)); 01623 if (!This) 01624 return E_OUTOFMEMORY; 01625 01626 This->lpVtbl = &TMarshalDispatchChannelVtbl; 01627 This->refs = 1; 01628 IRpcChannelBuffer_AddRef(pDelegateChannel); 01629 This->pDelegateChannel = pDelegateChannel; 01630 This->tmarshal_iid = *tmarshal_riid; 01631 01632 *ppChannel = (IRpcChannelBuffer *)&This->lpVtbl; 01633 return S_OK; 01634 } 01635 01636 01637 static inline HRESULT get_facbuf_for_iid(REFIID riid, IPSFactoryBuffer **facbuf) 01638 { 01639 HRESULT hr; 01640 CLSID clsid; 01641 01642 if ((hr = CoGetPSClsid(riid, &clsid))) 01643 return hr; 01644 return CoGetClassObject(&clsid, CLSCTX_INPROC_SERVER, NULL, 01645 &IID_IPSFactoryBuffer, (LPVOID*)facbuf); 01646 } 01647 01648 static HRESULT init_proxy_entry_point(TMProxyImpl *proxy, unsigned int num) 01649 { 01650 int j; 01651 /* nrofargs without This */ 01652 int nrofargs; 01653 ITypeInfo *tinfo2; 01654 TMAsmProxy *xasm = proxy->asmstubs + num; 01655 HRESULT hres; 01656 const FUNCDESC *fdesc; 01657 01658 hres = get_funcdesc(proxy->tinfo, num, &tinfo2, &fdesc, NULL, NULL, NULL); 01659 if (hres) { 01660 ERR("GetFuncDesc %x should not fail here.\n",hres); 01661 return hres; 01662 } 01663 ITypeInfo_Release(tinfo2); 01664 /* some args take more than 4 byte on the stack */ 01665 nrofargs = 0; 01666 for (j=0;j<fdesc->cParams;j++) 01667 nrofargs += _argsize(&fdesc->lprgelemdescParam[j].tdesc, proxy->tinfo); 01668 01669 #ifdef __i386__ 01670 if (fdesc->callconv != CC_STDCALL) { 01671 ERR("calling convention is not stdcall????\n"); 01672 return E_FAIL; 01673 } 01674 /* popl %eax - return ptr 01675 * pushl <nr> 01676 * pushl %eax 01677 * call xCall 01678 * lret <nr> (+4) 01679 * 01680 * 01681 * arg3 arg2 arg1 <method> <returnptr> 01682 */ 01683 xasm->popleax = 0x58; 01684 xasm->pushlval = 0x68; 01685 xasm->nr = num; 01686 xasm->pushleax = 0x50; 01687 xasm->lcall = 0xe8; /* relative jump */ 01688 xasm->xcall = (DWORD)xCall; 01689 xasm->xcall -= (DWORD)&(xasm->lret); 01690 xasm->lret = 0xc2; 01691 xasm->bytestopop = (nrofargs+2)*4; /* pop args, This, iMethod */ 01692 xasm->nop = 0x90; 01693 proxy->lpvtbl[num] = xasm; 01694 #else 01695 FIXME("not implemented on non i386\n"); 01696 return E_FAIL; 01697 #endif 01698 return S_OK; 01699 } 01700 01701 static HRESULT WINAPI 01702 PSFacBuf_CreateProxy( 01703 LPPSFACTORYBUFFER iface, IUnknown* pUnkOuter, REFIID riid, 01704 IRpcProxyBuffer **ppProxy, LPVOID *ppv) 01705 { 01706 HRESULT hres; 01707 ITypeInfo *tinfo; 01708 unsigned int i, nroffuncs; 01709 TMProxyImpl *proxy; 01710 TYPEATTR *typeattr; 01711 BOOL defer_to_dispatch = FALSE; 01712 01713 TRACE("(...%s...)\n",debugstr_guid(riid)); 01714 hres = _get_typeinfo_for_iid(riid,&tinfo); 01715 if (hres) { 01716 ERR("No typeinfo for %s?\n",debugstr_guid(riid)); 01717 return hres; 01718 } 01719 01720 hres = num_of_funcs(tinfo, &nroffuncs); 01721 if (FAILED(hres)) { 01722 ERR("Cannot get number of functions for typeinfo %s\n",debugstr_guid(riid)); 01723 ITypeInfo_Release(tinfo); 01724 return hres; 01725 } 01726 01727 proxy = CoTaskMemAlloc(sizeof(TMProxyImpl)); 01728 if (!proxy) return E_OUTOFMEMORY; 01729 01730 assert(sizeof(TMAsmProxy) == 16); 01731 01732 proxy->dispatch = NULL; 01733 proxy->dispatch_proxy = NULL; 01734 proxy->outerunknown = pUnkOuter; 01735 proxy->asmstubs = VirtualAlloc(NULL, sizeof(TMAsmProxy) * nroffuncs, MEM_COMMIT, PAGE_EXECUTE_READWRITE); 01736 if (!proxy->asmstubs) { 01737 ERR("Could not commit pages for proxy thunks\n"); 01738 CoTaskMemFree(proxy); 01739 return E_OUTOFMEMORY; 01740 } 01741 proxy->lpvtbl2 = &tmproxyvtable; 01742 /* one reference for the proxy */ 01743 proxy->ref = 1; 01744 proxy->tinfo = tinfo; 01745 proxy->iid = *riid; 01746 proxy->chanbuf = 0; 01747 01748 InitializeCriticalSection(&proxy->crit); 01749 proxy->crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": TMProxyImpl.crit"); 01750 01751 proxy->lpvtbl = HeapAlloc(GetProcessHeap(),0,sizeof(LPBYTE)*nroffuncs); 01752 01753 /* if we derive from IDispatch then defer to its proxy for its methods */ 01754 hres = ITypeInfo_GetTypeAttr(tinfo, &typeattr); 01755 if (hres == S_OK) 01756 { 01757 if (typeattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE) 01758 { 01759 IPSFactoryBuffer *factory_buffer; 01760 hres = get_facbuf_for_iid(&IID_IDispatch, &factory_buffer); 01761 if (hres == S_OK) 01762 { 01763 hres = IPSFactoryBuffer_CreateProxy(factory_buffer, NULL, 01764 &IID_IDispatch, &proxy->dispatch_proxy, 01765 (void **)&proxy->dispatch); 01766 IPSFactoryBuffer_Release(factory_buffer); 01767 } 01768 if ((hres == S_OK) && (nroffuncs < 7)) 01769 { 01770 ERR("nroffuncs calculated incorrectly (%d)\n", nroffuncs); 01771 hres = E_UNEXPECTED; 01772 } 01773 if (hres == S_OK) 01774 { 01775 defer_to_dispatch = TRUE; 01776 } 01777 } 01778 ITypeInfo_ReleaseTypeAttr(tinfo, typeattr); 01779 } 01780 01781 for (i=0;i<nroffuncs;i++) { 01782 switch (i) { 01783 case 0: 01784 proxy->lpvtbl[i] = ProxyIUnknown_QueryInterface; 01785 break; 01786 case 1: 01787 proxy->lpvtbl[i] = ProxyIUnknown_AddRef; 01788 break; 01789 case 2: 01790 proxy->lpvtbl[i] = ProxyIUnknown_Release; 01791 break; 01792 case 3: 01793 if(!defer_to_dispatch) 01794 { 01795 hres = init_proxy_entry_point(proxy, i); 01796 if(FAILED(hres)) return hres; 01797 } 01798 else proxy->lpvtbl[3] = ProxyIDispatch_GetTypeInfoCount; 01799 break; 01800 case 4: 01801 if(!defer_to_dispatch) 01802 { 01803 hres = init_proxy_entry_point(proxy, i); 01804 if(FAILED(hres)) return hres; 01805 } 01806 else proxy->lpvtbl[4] = ProxyIDispatch_GetTypeInfo; 01807 break; 01808 case 5: 01809 if(!defer_to_dispatch) 01810 { 01811 hres = init_proxy_entry_point(proxy, i); 01812 if(FAILED(hres)) return hres; 01813 } 01814 else proxy->lpvtbl[5] = ProxyIDispatch_GetIDsOfNames; 01815 break; 01816 case 6: 01817 if(!defer_to_dispatch) 01818 { 01819 hres = init_proxy_entry_point(proxy, i); 01820 if(FAILED(hres)) return hres; 01821 } 01822 else proxy->lpvtbl[6] = ProxyIDispatch_Invoke; 01823 break; 01824 default: 01825 hres = init_proxy_entry_point(proxy, i); 01826 if(FAILED(hres)) return hres; 01827 } 01828 } 01829 01830 if (hres == S_OK) 01831 { 01832 *ppv = proxy; 01833 *ppProxy = (IRpcProxyBuffer *)&(proxy->lpvtbl2); 01834 IUnknown_AddRef((IUnknown *)*ppv); 01835 return S_OK; 01836 } 01837 else 01838 TMProxyImpl_Release((IRpcProxyBuffer *)&proxy->lpvtbl2); 01839 return hres; 01840 } 01841 01842 typedef struct _TMStubImpl { 01843 const IRpcStubBufferVtbl *lpvtbl; 01844 LONG ref; 01845 01846 LPUNKNOWN pUnk; 01847 ITypeInfo *tinfo; 01848 IID iid; 01849 IRpcStubBuffer *dispatch_stub; 01850 BOOL dispatch_derivative; 01851 } TMStubImpl; 01852 01853 static HRESULT WINAPI 01854 TMStubImpl_QueryInterface(LPRPCSTUBBUFFER iface, REFIID riid, LPVOID *ppv) 01855 { 01856 if (IsEqualIID(riid,&IID_IRpcStubBuffer)||IsEqualIID(riid,&IID_IUnknown)){ 01857 *ppv = iface; 01858 IRpcStubBuffer_AddRef(iface); 01859 return S_OK; 01860 } 01861 FIXME("%s, not supported IID.\n",debugstr_guid(riid)); 01862 return E_NOINTERFACE; 01863 } 01864 01865 static ULONG WINAPI 01866 TMStubImpl_AddRef(LPRPCSTUBBUFFER iface) 01867 { 01868 TMStubImpl *This = (TMStubImpl *)iface; 01869 ULONG refCount = InterlockedIncrement(&This->ref); 01870 01871 TRACE("(%p)->(ref before=%u)\n", This, refCount - 1); 01872 01873 return refCount; 01874 } 01875 01876 static ULONG WINAPI 01877 TMStubImpl_Release(LPRPCSTUBBUFFER iface) 01878 { 01879 TMStubImpl *This = (TMStubImpl *)iface; 01880 ULONG refCount = InterlockedDecrement(&This->ref); 01881 01882 TRACE("(%p)->(ref before=%u)\n", This, refCount + 1); 01883 01884 if (!refCount) 01885 { 01886 IRpcStubBuffer_Disconnect(iface); 01887 ITypeInfo_Release(This->tinfo); 01888 if (This->dispatch_stub) 01889 IRpcStubBuffer_Release(This->dispatch_stub); 01890 CoTaskMemFree(This); 01891 } 01892 return refCount; 01893 } 01894 01895 static HRESULT WINAPI 01896 TMStubImpl_Connect(LPRPCSTUBBUFFER iface, LPUNKNOWN pUnkServer) 01897 { 01898 TMStubImpl *This = (TMStubImpl *)iface; 01899 01900 TRACE("(%p)->(%p)\n", This, pUnkServer); 01901 01902 IUnknown_AddRef(pUnkServer); 01903 This->pUnk = pUnkServer; 01904 01905 if (This->dispatch_stub) 01906 IRpcStubBuffer_Connect(This->dispatch_stub, pUnkServer); 01907 01908 return S_OK; 01909 } 01910 01911 static void WINAPI 01912 TMStubImpl_Disconnect(LPRPCSTUBBUFFER iface) 01913 { 01914 TMStubImpl *This = (TMStubImpl *)iface; 01915 01916 TRACE("(%p)->()\n", This); 01917 01918 if (This->pUnk) 01919 { 01920 IUnknown_Release(This->pUnk); 01921 This->pUnk = NULL; 01922 } 01923 01924 if (This->dispatch_stub) 01925 IRpcStubBuffer_Disconnect(This->dispatch_stub); 01926 } 01927 01928 static HRESULT WINAPI 01929 TMStubImpl_Invoke( 01930 LPRPCSTUBBUFFER iface, RPCOLEMESSAGE* xmsg,IRpcChannelBuffer*rpcchanbuf) 01931 { 01932 #ifdef __i386__ 01933 int i; 01934 const FUNCDESC *fdesc; 01935 TMStubImpl *This = (TMStubImpl *)iface; 01936 HRESULT hres; 01937 DWORD *args = NULL, res, *xargs, nrofargs; 01938 marshal_state buf; 01939 UINT nrofnames = 0; 01940 BSTR names[10]; 01941 BSTR iname = NULL; 01942 ITypeInfo *tinfo = NULL; 01943 01944 TRACE("...\n"); 01945 01946 if (xmsg->iMethod < 3) { 01947 ERR("IUnknown methods cannot be marshaled by the typelib marshaler\n"); 01948 return E_UNEXPECTED; 01949 } 01950 01951 if (This->dispatch_derivative && xmsg->iMethod < sizeof(IDispatchVtbl)/sizeof(void *)) 01952 { 01953 IPSFactoryBuffer *factory_buffer; 01954 hres = get_facbuf_for_iid(&IID_IDispatch, &factory_buffer); 01955 if (hres == S_OK) 01956 { 01957 hres = IPSFactoryBuffer_CreateStub(factory_buffer, &IID_IDispatch, 01958 This->pUnk, &This->dispatch_stub); 01959 IPSFactoryBuffer_Release(factory_buffer); 01960 } 01961 if (hres != S_OK) 01962 return hres; 01963 return IRpcStubBuffer_Invoke(This->dispatch_stub, xmsg, rpcchanbuf); 01964 } 01965 01966 memset(&buf,0,sizeof(buf)); 01967 buf.size = xmsg->cbBuffer; 01968 buf.base = HeapAlloc(GetProcessHeap(), 0, xmsg->cbBuffer); 01969 memcpy(buf.base, xmsg->Buffer, xmsg->cbBuffer); 01970 buf.curoff = 0; 01971 01972 hres = get_funcdesc(This->tinfo,xmsg->iMethod,&tinfo,&fdesc,&iname,NULL,NULL); 01973 if (hres) { 01974 ERR("GetFuncDesc on method %d failed with %x\n",xmsg->iMethod,hres); 01975 return hres; 01976 } 01977 01978 if (iname && !lstrcmpW(iname, IDispatchW)) 01979 { 01980 ERR("IDispatch cannot be marshaled by the typelib marshaler\n"); 01981 hres = E_UNEXPECTED; 01982 SysFreeString (iname); 01983 goto exit; 01984 } 01985 01986 SysFreeString (iname); 01987 01988 /* Need them for hack below */ 01989 memset(names,0,sizeof(names)); 01990 ITypeInfo_GetNames(tinfo,fdesc->memid,names,sizeof(names)/sizeof(names[0]),&nrofnames); 01991 if (nrofnames > sizeof(names)/sizeof(names[0])) { 01992 ERR("Need more names!\n"); 01993 } 01994 01995 /*dump_FUNCDESC(fdesc);*/ 01996 nrofargs = 0; 01997 for (i=0;i<fdesc->cParams;i++) 01998 nrofargs += _argsize(&fdesc->lprgelemdescParam[i].tdesc, tinfo); 01999 args = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,(nrofargs+1)*sizeof(DWORD)); 02000 if (!args) 02001 { 02002 hres = E_OUTOFMEMORY; 02003 goto exit; 02004 } 02005 02006 /* Allocate all stuff used by call. */ 02007 xargs = args+1; 02008 for (i=0;i<fdesc->cParams;i++) { 02009 ELEMDESC *elem = fdesc->lprgelemdescParam+i; 02010 02011 hres = deserialize_param( 02012 tinfo, 02013 is_in_elem(elem), 02014 FALSE, 02015 TRUE, 02016 &(elem->tdesc), 02017 xargs, 02018 &buf 02019 ); 02020 xargs += _argsize(&elem->tdesc, tinfo); 02021 if (hres) { 02022 ERR("Failed to deserialize param %s, hres %x\n",relaystr(names[i+1]),hres); 02023 break; 02024 } 02025 } 02026 02027 args[0] = (DWORD)This->pUnk; 02028 02029 __TRY 02030 { 02031 res = _invoke( 02032 (*((FARPROC**)args[0]))[fdesc->oVft/4], 02033 fdesc->callconv, 02034 (xargs-args), 02035 args 02036 ); 02037 } 02038 __EXCEPT_ALL 02039 { 02040 DWORD dwExceptionCode = GetExceptionCode(); 02041 ERR("invoke call failed with exception 0x%08x (%d)\n", dwExceptionCode, dwExceptionCode); 02042 if (FAILED(dwExceptionCode)) 02043 hres = dwExceptionCode; 02044 else 02045 hres = HRESULT_FROM_WIN32(dwExceptionCode); 02046 } 02047 __ENDTRY 02048 02049 if (hres != S_OK) 02050 goto exit; 02051 02052 buf.curoff = 0; 02053 02054 xargs = args+1; 02055 for (i=0;i<fdesc->cParams;i++) { 02056 ELEMDESC *elem = fdesc->lprgelemdescParam+i; 02057 hres = serialize_param( 02058 tinfo, 02059 is_out_elem(elem), 02060 FALSE, 02061 TRUE, 02062 &elem->tdesc, 02063 xargs, 02064 &buf 02065 ); 02066 xargs += _argsize(&elem->tdesc, tinfo); 02067 if (hres) { 02068 ERR("Failed to stuballoc param, hres %x\n",hres); 02069 break; 02070 } 02071 } 02072 02073 hres = xbuf_add (&buf, (LPBYTE)&res, sizeof(DWORD)); 02074 02075 if (hres != S_OK) 02076 goto exit; 02077 02078 xmsg->cbBuffer = buf.curoff; 02079 hres = IRpcChannelBuffer_GetBuffer(rpcchanbuf, xmsg, &This->iid); 02080 if (hres != S_OK) 02081 ERR("IRpcChannelBuffer_GetBuffer failed with error 0x%08x\n", hres); 02082 02083 if (hres == S_OK) 02084 memcpy(xmsg->Buffer, buf.base, buf.curoff); 02085 02086 exit: 02087 for (i = 0; i < nrofnames; i++) 02088 SysFreeString(names[i]); 02089 02090 ITypeInfo_Release(tinfo); 02091 HeapFree(GetProcessHeap(), 0, args); 02092 02093 HeapFree(GetProcessHeap(), 0, buf.base); 02094 02095 TRACE("returning\n"); 02096 return hres; 02097 #else 02098 FIXME( "not implemented on non-i386\n" ); 02099 return E_FAIL; 02100 #endif 02101 } 02102 02103 static LPRPCSTUBBUFFER WINAPI 02104 TMStubImpl_IsIIDSupported(LPRPCSTUBBUFFER iface, REFIID riid) { 02105 FIXME("Huh (%s)?\n",debugstr_guid(riid)); 02106 return NULL; 02107 } 02108 02109 static ULONG WINAPI 02110 TMStubImpl_CountRefs(LPRPCSTUBBUFFER iface) { 02111 TMStubImpl *This = (TMStubImpl *)iface; 02112 02113 FIXME("()\n"); 02114 return This->ref; /*FIXME? */ 02115 } 02116 02117 static HRESULT WINAPI 02118 TMStubImpl_DebugServerQueryInterface(LPRPCSTUBBUFFER iface, LPVOID *ppv) { 02119 return E_NOTIMPL; 02120 } 02121 02122 static void WINAPI 02123 TMStubImpl_DebugServerRelease(LPRPCSTUBBUFFER iface, LPVOID ppv) { 02124 return; 02125 } 02126 02127 static const IRpcStubBufferVtbl tmstubvtbl = { 02128 TMStubImpl_QueryInterface, 02129 TMStubImpl_AddRef, 02130 TMStubImpl_Release, 02131 TMStubImpl_Connect, 02132 TMStubImpl_Disconnect, 02133 TMStubImpl_Invoke, 02134 TMStubImpl_IsIIDSupported, 02135 TMStubImpl_CountRefs, 02136 TMStubImpl_DebugServerQueryInterface, 02137 TMStubImpl_DebugServerRelease 02138 }; 02139 02140 static HRESULT WINAPI 02141 PSFacBuf_CreateStub( 02142 LPPSFACTORYBUFFER iface, REFIID riid,IUnknown *pUnkServer, 02143 IRpcStubBuffer** ppStub 02144 ) { 02145 HRESULT hres; 02146 ITypeInfo *tinfo; 02147 TMStubImpl *stub; 02148 TYPEATTR *typeattr; 02149 02150 TRACE("(%s,%p,%p)\n",debugstr_guid(riid),pUnkServer,ppStub); 02151 02152 hres = _get_typeinfo_for_iid(riid,&tinfo); 02153 if (hres) { 02154 ERR("No typeinfo for %s?\n",debugstr_guid(riid)); 02155 return hres; 02156 } 02157 02158 stub = CoTaskMemAlloc(sizeof(TMStubImpl)); 02159 if (!stub) 02160 return E_OUTOFMEMORY; 02161 stub->lpvtbl = &tmstubvtbl; 02162 stub->ref = 1; 02163 stub->tinfo = tinfo; 02164 stub->dispatch_stub = NULL; 02165 stub->dispatch_derivative = FALSE; 02166 stub->iid = *riid; 02167 hres = IRpcStubBuffer_Connect((LPRPCSTUBBUFFER)stub,pUnkServer); 02168 *ppStub = (LPRPCSTUBBUFFER)stub; 02169 TRACE("IRpcStubBuffer: %p\n", stub); 02170 if (hres) 02171 ERR("Connect to pUnkServer failed?\n"); 02172 02173 /* if we derive from IDispatch then defer to its stub for some of its methods */ 02174 hres = ITypeInfo_GetTypeAttr(tinfo, &typeattr); 02175 if (hres == S_OK) 02176 { 02177 if (typeattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE) 02178 stub->dispatch_derivative = TRUE; 02179 ITypeInfo_ReleaseTypeAttr(tinfo, typeattr); 02180 } 02181 02182 return hres; 02183 } 02184 02185 static const IPSFactoryBufferVtbl psfacbufvtbl = { 02186 PSFacBuf_QueryInterface, 02187 PSFacBuf_AddRef, 02188 PSFacBuf_Release, 02189 PSFacBuf_CreateProxy, 02190 PSFacBuf_CreateStub 02191 }; 02192 02193 /* This is the whole PSFactoryBuffer object, just the vtableptr */ 02194 static const IPSFactoryBufferVtbl *lppsfac = &psfacbufvtbl; 02195 02196 /*********************************************************************** 02197 * TMARSHAL_DllGetClassObject 02198 */ 02199 HRESULT TMARSHAL_DllGetClassObject(REFCLSID rclsid, REFIID iid,LPVOID *ppv) 02200 { 02201 if (IsEqualIID(iid,&IID_IPSFactoryBuffer)) { 02202 *ppv = &lppsfac; 02203 return S_OK; 02204 } 02205 return E_NOINTERFACE; 02206 } Generated on Sat May 26 2012 04:24:17 for ReactOS by
1.7.6.1
|