ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

usrmarshal.c
Go to the documentation of this file.
00001 /*
00002  * Misc marshalling routines
00003  *
00004  * Copyright 2002 Ove Kaaven
00005  * Copyright 2003 Mike Hearn
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this library; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00020  */
00021 
00022 #include <stdarg.h>
00023 #include <string.h>
00024 
00025 #define COBJMACROS
00026 #define NONAMELESSUNION
00027 #define NONAMELESSSTRUCT
00028 
00029 #include "windef.h"
00030 #include "winbase.h"
00031 #include "wingdi.h"
00032 #include "winuser.h"
00033 #include "winerror.h"
00034 
00035 #include "ole2.h"
00036 #include "oleauto.h"
00037 #include "typelib.h"
00038 #include "ocidl.h"
00039 #include "wine/debug.h"
00040 
00041 WINE_DEFAULT_DEBUG_CHANNEL(ole);
00042 
00043 #define ALIGNED_LENGTH(_Len, _Align) (((_Len)+(_Align))&~(_Align))
00044 #define ALIGNED_POINTER(_Ptr, _Align) ((LPVOID)ALIGNED_LENGTH((ULONG_PTR)(_Ptr), _Align))
00045 #define ALIGN_LENGTH(_Len, _Align) _Len = ALIGNED_LENGTH(_Len, _Align)
00046 #define ALIGN_POINTER(_Ptr, _Align) _Ptr = ALIGNED_POINTER(_Ptr, _Align)
00047 
00048 static void dump_user_flags(const ULONG *pFlags)
00049 {
00050     if (HIWORD(*pFlags) == NDR_LOCAL_DATA_REPRESENTATION)
00051         TRACE("MAKELONG(NDR_LOCAL_REPRESENTATION, ");
00052     else
00053         TRACE("MAKELONG(0x%04x, ", HIWORD(*pFlags));
00054     switch (LOWORD(*pFlags))
00055     {
00056         case MSHCTX_LOCAL: TRACE("MSHCTX_LOCAL)"); break;
00057         case MSHCTX_NOSHAREDMEM: TRACE("MSHCTX_NOSHAREDMEM)"); break;
00058         case MSHCTX_DIFFERENTMACHINE: TRACE("MSHCTX_DIFFERENTMACHINE)"); break;
00059         case MSHCTX_INPROC: TRACE("MSHCTX_INPROC)"); break;
00060         default: TRACE("%d)", LOWORD(*pFlags));
00061     }
00062 }
00063 
00064 /* CLEANLOCALSTORAGE */
00065 
00066 #define CLS_FUNCDESC  'f'
00067 #define CLS_LIBATTR   'l'
00068 #define CLS_TYPEATTR  't'
00069 #define CLS_VARDESC   'v'
00070 
00071 ULONG WINAPI CLEANLOCALSTORAGE_UserSize(ULONG *pFlags, ULONG Start, CLEANLOCALSTORAGE *pstg)
00072 {
00073     ALIGN_LENGTH(Start, 3);
00074     return Start + sizeof(DWORD);
00075 }
00076 
00077 unsigned char * WINAPI CLEANLOCALSTORAGE_UserMarshal(ULONG *pFlags, unsigned char *Buffer, CLEANLOCALSTORAGE *pstg)
00078 {
00079     ALIGN_POINTER(Buffer, 3);
00080     *(DWORD*)Buffer = pstg->flags;
00081     switch(pstg->flags)
00082     {
00083     case CLS_LIBATTR:
00084         ITypeLib_ReleaseTLibAttr((ITypeLib*)pstg->pInterface, *(TLIBATTR**)pstg->pStorage);
00085         break;
00086     case CLS_TYPEATTR:
00087         ITypeInfo_ReleaseTypeAttr((ITypeInfo*)pstg->pInterface, *(TYPEATTR**)pstg->pStorage); 
00088         break;
00089     case CLS_FUNCDESC:
00090         ITypeInfo_ReleaseFuncDesc((ITypeInfo*)pstg->pInterface, *(FUNCDESC**)pstg->pStorage); 
00091         break;
00092     case CLS_VARDESC:
00093         ITypeInfo_ReleaseVarDesc((ITypeInfo*)pstg->pInterface, *(VARDESC**)pstg->pStorage);
00094         break;
00095 
00096     default:
00097         ERR("Unknown type %x\n", pstg->flags);
00098     }
00099 
00100     *(VOID**)pstg->pStorage = NULL;
00101     IUnknown_Release(pstg->pInterface);
00102     pstg->pInterface = NULL;
00103 
00104     return Buffer + sizeof(DWORD);
00105 }
00106 
00107 unsigned char * WINAPI CLEANLOCALSTORAGE_UserUnmarshal(ULONG *pFlags, unsigned char *Buffer, CLEANLOCALSTORAGE *pstr)
00108 {
00109     ALIGN_POINTER(Buffer, 3);
00110     pstr->flags = *(DWORD*)Buffer;
00111     return Buffer + sizeof(DWORD);
00112 }
00113 
00114 void WINAPI CLEANLOCALSTORAGE_UserFree(ULONG *pFlags, CLEANLOCALSTORAGE *pstr)
00115 {
00116     /* Nothing to do */
00117 }
00118 
00119 /* BSTR */
00120 
00121 typedef struct
00122 {
00123     DWORD len;          /* No. of chars not including trailing '\0' */
00124     DWORD byte_len;     /* len * 2 or 0xffffffff if len == 0 */
00125     DWORD len2;         /* == len */
00126 } bstr_wire_t;
00127 
00128 ULONG WINAPI BSTR_UserSize(ULONG *pFlags, ULONG Start, BSTR *pstr)
00129 {
00130     TRACE("(%x,%d,%p) => %p\n", *pFlags, Start, pstr, *pstr);
00131     if (*pstr) TRACE("string=%s\n", debugstr_w(*pstr));
00132     ALIGN_LENGTH(Start, 3);
00133     Start += sizeof(bstr_wire_t) + ((SysStringByteLen(*pstr) + 1) & ~1);
00134     TRACE("returning %d\n", Start);
00135     return Start;
00136 }
00137 
00138 unsigned char * WINAPI BSTR_UserMarshal(ULONG *pFlags, unsigned char *Buffer, BSTR *pstr)
00139 {
00140     bstr_wire_t *header;
00141     DWORD len = SysStringByteLen(*pstr);
00142 
00143     TRACE("(%x,%p,%p) => %p\n", *pFlags, Buffer, pstr, *pstr);
00144     if (*pstr) TRACE("string=%s\n", debugstr_w(*pstr));
00145 
00146     ALIGN_POINTER(Buffer, 3);
00147     header = (bstr_wire_t*)Buffer;
00148     header->len = header->len2 = (len + 1) / 2;
00149     if (*pstr)
00150     {
00151         header->byte_len = len;
00152         memcpy(header + 1, *pstr, header->len * 2);
00153     }
00154     else
00155         header->byte_len = 0xffffffff; /* special case for a null bstr */
00156 
00157     return Buffer + sizeof(*header) + sizeof(OLECHAR) * header->len;
00158 }
00159 
00160 unsigned char * WINAPI BSTR_UserUnmarshal(ULONG *pFlags, unsigned char *Buffer, BSTR *pstr)
00161 {
00162     bstr_wire_t *header;
00163     TRACE("(%x,%p,%p) => %p\n", *pFlags, Buffer, pstr, *pstr);
00164 
00165     ALIGN_POINTER(Buffer, 3);
00166     header = (bstr_wire_t*)Buffer;
00167     if(header->len != header->len2)
00168         FIXME("len %08x != len2 %08x\n", header->len, header->len2);
00169 
00170     SysFreeString(*pstr);
00171     *pstr = NULL;
00172 
00173     if(header->byte_len != 0xffffffff)
00174         *pstr = SysAllocStringByteLen((char*)(header + 1), header->byte_len);
00175 
00176     if (*pstr) TRACE("string=%s\n", debugstr_w(*pstr));
00177     return Buffer + sizeof(*header) + sizeof(OLECHAR) * header->len;
00178 }
00179 
00180 void WINAPI BSTR_UserFree(ULONG *pFlags, BSTR *pstr)
00181 {
00182     TRACE("(%x,%p) => %p\n", *pFlags, pstr, *pstr);
00183     SysFreeString(*pstr);
00184     *pstr = NULL;
00185 }
00186 
00187 /* VARIANT */
00188 
00189 typedef struct
00190 {
00191     DWORD clSize;
00192     DWORD rpcReserverd;
00193     USHORT vt;
00194     USHORT wReserved1;
00195     USHORT wReserved2;
00196     USHORT wReserved3;
00197     DWORD switch_is;
00198 } variant_wire_t;
00199 
00200 static unsigned int get_type_size(ULONG *pFlags, VARTYPE vt)
00201 {
00202     if (vt & VT_ARRAY) return 4;
00203 
00204     switch (vt & ~VT_BYREF) {
00205     case VT_EMPTY:
00206     case VT_NULL:
00207         return 0;
00208     case VT_I1:
00209     case VT_UI1:
00210         return sizeof(CHAR);
00211     case VT_I2:
00212     case VT_UI2:
00213         return sizeof(SHORT);
00214     case VT_I4:
00215     case VT_UI4:
00216         return sizeof(LONG);
00217     case VT_INT:
00218     case VT_UINT:
00219         return sizeof(INT);
00220     case VT_R4:
00221         return sizeof(FLOAT);
00222     case VT_R8:
00223         return sizeof(DOUBLE);
00224     case VT_BOOL:
00225         return sizeof(VARIANT_BOOL);
00226     case VT_ERROR:
00227         return sizeof(SCODE);
00228     case VT_DATE:
00229         return sizeof(DATE);
00230     case VT_CY:
00231         return sizeof(CY);
00232     case VT_DECIMAL:
00233         return sizeof(DECIMAL);
00234     case VT_BSTR:
00235         return sizeof(ULONG);
00236     case VT_VARIANT:
00237         return sizeof(VARIANT);
00238     case VT_UNKNOWN:
00239     case VT_DISPATCH:
00240     case VT_RECORD:
00241         return 0;
00242     default:
00243         FIXME("unhandled VT %d\n", vt);
00244         return 0;
00245     }
00246 }
00247 
00248 static unsigned int get_type_alignment(ULONG *pFlags, VARTYPE vt)
00249 {
00250     unsigned int size = get_type_size(pFlags, vt);
00251     if(vt & VT_BYREF) return 3;
00252     if(size == 0) return 0;
00253     if(size <= 4) return size - 1;
00254     return 7;
00255 }
00256 
00257 static unsigned interface_variant_size(const ULONG *pFlags, REFIID riid, IUnknown *punk)
00258 {
00259     ULONG size = 0;
00260     HRESULT hr;
00261 
00262     if (punk)
00263     {
00264         hr = CoGetMarshalSizeMax(&size, riid, punk, LOWORD(*pFlags), NULL, MSHLFLAGS_NORMAL);
00265         if (FAILED(hr))
00266         {
00267             ERR("interface variant buffer size calculation failed, HRESULT=0x%x\n", hr);
00268             return 0;
00269         }
00270     }
00271     size += sizeof(ULONG); /* we have to store the buffersize in the stream */
00272     TRACE("wire-size extra of interface variant is %d\n", size);
00273     return size;
00274 }
00275 
00276 static ULONG wire_extra_user_size(ULONG *pFlags, ULONG Start, VARIANT *pvar)
00277 {
00278   if (V_ISARRAY(pvar))
00279   {
00280     if (V_ISBYREF(pvar))
00281       return LPSAFEARRAY_UserSize(pFlags, Start, V_ARRAYREF(pvar));
00282     else 
00283       return LPSAFEARRAY_UserSize(pFlags, Start, &V_ARRAY(pvar));
00284   }
00285 
00286   switch (V_VT(pvar)) {
00287   case VT_BSTR:
00288     return BSTR_UserSize(pFlags, Start, &V_BSTR(pvar));
00289   case VT_BSTR | VT_BYREF:
00290     return BSTR_UserSize(pFlags, Start, V_BSTRREF(pvar));
00291   case VT_VARIANT | VT_BYREF:
00292     return VARIANT_UserSize(pFlags, Start, V_VARIANTREF(pvar));
00293   case VT_UNKNOWN:
00294     return Start + interface_variant_size(pFlags, &IID_IUnknown, V_UNKNOWN(pvar));
00295   case VT_UNKNOWN | VT_BYREF:
00296     return Start + interface_variant_size(pFlags, &IID_IUnknown, *V_UNKNOWNREF(pvar));
00297   case VT_DISPATCH:
00298     return Start + interface_variant_size(pFlags, &IID_IDispatch, (IUnknown*)V_DISPATCH(pvar));
00299   case VT_DISPATCH | VT_BYREF:
00300     return Start + interface_variant_size(pFlags, &IID_IDispatch, (IUnknown*)*V_DISPATCHREF(pvar));
00301   case VT_RECORD:
00302     FIXME("wire-size record\n");
00303     return Start;
00304   case VT_SAFEARRAY:
00305   case VT_SAFEARRAY | VT_BYREF:
00306     FIXME("wire-size safearray: shouldn't be marshaling this\n");
00307     return Start;
00308   default:
00309     return Start;
00310   }
00311 }
00312 
00313 /* helper: called for VT_DISPATCH variants to marshal the IDispatch* into the buffer. returns Buffer on failure, new position otherwise */
00314 static unsigned char* interface_variant_marshal(const ULONG *pFlags, unsigned char *Buffer,
00315                                                 REFIID riid, IUnknown *punk)
00316 {
00317   IStream *working; 
00318   HGLOBAL working_mem;
00319   void *working_memlocked;
00320   unsigned char *oldpos;
00321   ULONG size;
00322   HRESULT hr;
00323   
00324   TRACE("pFlags=%d, Buffer=%p, pUnk=%p\n", *pFlags, Buffer, punk);
00325 
00326   if(!punk)
00327   {
00328       memset(Buffer, 0, sizeof(ULONG));
00329       return Buffer + sizeof(ULONG);
00330   }
00331 
00332   oldpos = Buffer;
00333   
00334   /* CoMarshalInterface needs a stream, whereas at this level we are operating in terms of buffers.
00335    * We create a stream on an HGLOBAL, so we can simply do a memcpy to move it to the buffer.
00336    * in rpcrt4/ndr_ole.c, a simple IStream implementation is wrapped around the buffer object,
00337    * but that would be overkill here, hence this implementation. We save the size because the unmarshal
00338    * code has no way to know how long the marshalled buffer is. */
00339 
00340   size = interface_variant_size(pFlags, riid, punk);
00341   
00342   working_mem = GlobalAlloc(0, size);
00343   if (!working_mem) return oldpos;
00344 
00345   hr = CreateStreamOnHGlobal(working_mem, TRUE, &working);
00346   if (hr != S_OK) {
00347     GlobalFree(working_mem);
00348     return oldpos;
00349   }
00350   
00351   hr = CoMarshalInterface(working, riid, punk, LOWORD(*pFlags), NULL, MSHLFLAGS_NORMAL);
00352   if (hr != S_OK) {
00353     IStream_Release(working); /* this also releases the hglobal */
00354     return oldpos;
00355   }
00356 
00357   working_memlocked = GlobalLock(working_mem);
00358   memcpy(Buffer, &size, sizeof(ULONG)); /* copy the buffersize */
00359   memcpy(Buffer + sizeof(ULONG), working_memlocked, size - sizeof(ULONG));
00360   GlobalUnlock(working_mem);
00361 
00362   IStream_Release(working);
00363 
00364   /* size includes the ULONG for the size written above */
00365   TRACE("done, size=%d\n", size);
00366   return Buffer + size;
00367 }
00368 
00369 /* helper: called for VT_DISPATCH / VT_UNKNOWN variants to unmarshal the buffer. returns Buffer on failure, new position otherwise */
00370 static unsigned char *interface_variant_unmarshal(const ULONG *pFlags, unsigned char *Buffer,
00371                                                   REFIID riid, IUnknown **ppunk)
00372 {
00373   IStream *working;
00374   HGLOBAL working_mem;
00375   void *working_memlocked;
00376   unsigned char *oldpos;
00377   ULONG size;
00378   HRESULT hr;
00379   
00380   TRACE("pFlags=%d, Buffer=%p, ppUnk=%p\n", *pFlags, Buffer, ppunk);
00381 
00382   oldpos = Buffer;
00383 
00384   /* get the buffersize */
00385   memcpy(&size, Buffer, sizeof(ULONG));
00386   TRACE("buffersize=%d\n", size);
00387 
00388   if(!size)
00389   {
00390       *ppunk = NULL;
00391       return Buffer + sizeof(ULONG);
00392   }
00393 
00394   working_mem = GlobalAlloc(0, size);
00395   if (!working_mem) return oldpos;
00396 
00397   hr = CreateStreamOnHGlobal(working_mem, TRUE, &working);
00398   if (hr != S_OK) {
00399     GlobalFree(working_mem);
00400     return oldpos;
00401   }
00402 
00403   working_memlocked = GlobalLock(working_mem);
00404   
00405   /* now we copy the contents of the marshalling buffer to working_memlocked, unlock it, and demarshal the stream */
00406   memcpy(working_memlocked, Buffer + sizeof(ULONG), size);
00407   GlobalUnlock(working_mem);
00408 
00409   hr = CoUnmarshalInterface(working, riid, (void**)ppunk);
00410   if (hr != S_OK) {
00411     IStream_Release(working);
00412     return oldpos;
00413   }
00414 
00415   IStream_Release(working); /* this also frees the underlying hglobal */
00416 
00417   /* size includes the ULONG for the size written above */
00418   TRACE("done, processed=%d bytes\n", size);
00419   return Buffer + size;
00420 }
00421 
00422 
00423 ULONG WINAPI VARIANT_UserSize(ULONG *pFlags, ULONG Start, VARIANT *pvar)
00424 {
00425     int align;
00426     TRACE("(%x,%d,%p)\n", *pFlags, Start, pvar);
00427     TRACE("vt=%04x\n", V_VT(pvar));
00428 
00429     ALIGN_LENGTH(Start, 7);
00430     Start += sizeof(variant_wire_t);
00431     if(V_VT(pvar) & VT_BYREF)
00432         Start += 4;
00433 
00434     align = get_type_alignment(pFlags, V_VT(pvar));
00435     ALIGN_LENGTH(Start, align);
00436     if(V_VT(pvar) == (VT_VARIANT | VT_BYREF))
00437         Start += 4;
00438     else
00439         Start += get_type_size(pFlags, V_VT(pvar));
00440     Start = wire_extra_user_size(pFlags, Start, pvar);
00441 
00442     TRACE("returning %d\n", Start);
00443     return Start;
00444 }
00445 
00446 unsigned char * WINAPI VARIANT_UserMarshal(ULONG *pFlags, unsigned char *Buffer, VARIANT *pvar)
00447 {
00448     variant_wire_t *header;
00449     ULONG type_size;
00450     int align;
00451     unsigned char *Pos;
00452 
00453     TRACE("(%x,%p,%p)\n", *pFlags, Buffer, pvar);
00454     TRACE("vt=%04x\n", V_VT(pvar));
00455 
00456     ALIGN_POINTER(Buffer, 7);
00457 
00458     header = (variant_wire_t *)Buffer; 
00459 
00460     header->clSize = 0; /* fixed up at the end */
00461     header->rpcReserverd = 0;
00462     header->vt = pvar->n1.n2.vt;
00463     header->wReserved1 = pvar->n1.n2.wReserved1;
00464     header->wReserved2 = pvar->n1.n2.wReserved2;
00465     header->wReserved3 = pvar->n1.n2.wReserved3;
00466     header->switch_is = pvar->n1.n2.vt;
00467     if(header->switch_is & VT_ARRAY)
00468         header->switch_is &= ~VT_TYPEMASK;
00469 
00470     Pos = (unsigned char*)(header + 1);
00471     type_size = get_type_size(pFlags, V_VT(pvar));
00472     align = get_type_alignment(pFlags, V_VT(pvar));
00473     ALIGN_POINTER(Pos, align);
00474 
00475     if(header->vt & VT_BYREF)
00476     {
00477         *(DWORD *)Pos = max(type_size, 4);
00478         Pos += 4;
00479         if((header->vt & VT_TYPEMASK) != VT_VARIANT)
00480         {
00481             memcpy(Pos, pvar->n1.n2.n3.byref, type_size);
00482             Pos += type_size;
00483         }
00484         else
00485         {
00486             *(DWORD*)Pos = 'U' | 's' << 8 | 'e' << 16 | 'r' << 24;
00487             Pos += 4;
00488         }
00489     } 
00490     else
00491     {
00492         if((header->vt & VT_TYPEMASK) == VT_DECIMAL)
00493             memcpy(Pos, pvar, type_size);
00494         else
00495             memcpy(Pos, &pvar->n1.n2.n3, type_size);
00496         Pos += type_size;
00497     }
00498 
00499     if(header->vt & VT_ARRAY)
00500     {
00501         if(header->vt & VT_BYREF)
00502             Pos = LPSAFEARRAY_UserMarshal(pFlags, Pos, V_ARRAYREF(pvar));
00503         else
00504             Pos = LPSAFEARRAY_UserMarshal(pFlags, Pos, &V_ARRAY(pvar));
00505     }
00506     else
00507     {
00508         switch (header->vt)
00509         {
00510         case VT_BSTR:
00511             Pos = BSTR_UserMarshal(pFlags, Pos, &V_BSTR(pvar));
00512             break;
00513         case VT_BSTR | VT_BYREF:
00514             Pos = BSTR_UserMarshal(pFlags, Pos, V_BSTRREF(pvar));
00515             break;
00516         case VT_VARIANT | VT_BYREF:
00517             Pos = VARIANT_UserMarshal(pFlags, Pos, V_VARIANTREF(pvar));
00518             break;
00519         case VT_UNKNOWN:
00520             /* this should probably call WdtpInterfacePointer_UserMarshal in ole32.dll */
00521             Pos = interface_variant_marshal(pFlags, Pos, &IID_IUnknown, V_UNKNOWN(pvar));
00522             break;
00523         case VT_UNKNOWN | VT_BYREF:
00524             /* this should probably call WdtpInterfacePointer_UserMarshal in ole32.dll */
00525             Pos = interface_variant_marshal(pFlags, Pos, &IID_IUnknown, *V_UNKNOWNREF(pvar));
00526             break;
00527         case VT_DISPATCH:
00528             /* this should probably call WdtpInterfacePointer_UserMarshal in ole32.dll */
00529             Pos = interface_variant_marshal(pFlags, Pos, &IID_IDispatch, (IUnknown*)V_DISPATCH(pvar));
00530             break;
00531         case VT_DISPATCH | VT_BYREF:
00532             /* this should probably call WdtpInterfacePointer_UserMarshal in ole32.dll */
00533             Pos = interface_variant_marshal(pFlags, Pos, &IID_IDispatch, (IUnknown*)*V_DISPATCHREF(pvar));
00534             break;
00535         case VT_RECORD:
00536             FIXME("handle BRECORD by val\n");
00537             break;
00538         case VT_RECORD | VT_BYREF:
00539             FIXME("handle BRECORD by ref\n");
00540             break;
00541         }
00542     }
00543     header->clSize = ((Pos - Buffer) + 7) >> 3;
00544     TRACE("marshalled size=%d\n", header->clSize);
00545     return Pos;
00546 }
00547 
00548 unsigned char * WINAPI VARIANT_UserUnmarshal(ULONG *pFlags, unsigned char *Buffer, VARIANT *pvar)
00549 {
00550     variant_wire_t *header;
00551     ULONG type_size;
00552     int align;
00553     unsigned char *Pos;
00554 
00555     TRACE("(%x,%p,%p)\n", *pFlags, Buffer, pvar);
00556 
00557     ALIGN_POINTER(Buffer, 7);
00558 
00559     header = (variant_wire_t *)Buffer; 
00560     
00561     Pos = (unsigned char*)(header + 1);
00562     type_size = get_type_size(pFlags, header->vt);
00563     align = get_type_alignment(pFlags, header->vt);
00564     ALIGN_POINTER(Pos, align);
00565 
00566     if(header->vt & VT_BYREF)
00567     {
00568         ULONG mem_size;
00569         Pos += 4;
00570 
00571         switch (header->vt & ~VT_BYREF)
00572         {
00573         /* these types have a different memory size compared to wire size */
00574         case VT_UNKNOWN:
00575         case VT_DISPATCH:
00576         case VT_BSTR:
00577             mem_size = sizeof(void *);
00578             break;
00579         default:
00580             mem_size = type_size;
00581             break;
00582         }
00583 
00584         if (V_VT(pvar) != header->vt)
00585         {
00586             VariantClear(pvar);
00587             V_BYREF(pvar) = CoTaskMemAlloc(mem_size);
00588         }
00589         else if (!V_BYREF(pvar))
00590             V_BYREF(pvar) = CoTaskMemAlloc(mem_size);
00591         memcpy(V_BYREF(pvar), Pos, type_size);
00592         if((header->vt & VT_TYPEMASK) != VT_VARIANT)
00593             Pos += type_size;
00594         else
00595             Pos += 4;
00596     }
00597     else
00598     {
00599         VariantClear(pvar);
00600         if((header->vt & VT_TYPEMASK) == VT_DECIMAL)
00601             memcpy(pvar, Pos, type_size);
00602         else
00603             memcpy(&pvar->n1.n2.n3, Pos, type_size);
00604         Pos += type_size;
00605     }
00606 
00607     pvar->n1.n2.vt = header->vt;
00608     pvar->n1.n2.wReserved1 = header->wReserved1;
00609     pvar->n1.n2.wReserved2 = header->wReserved2;
00610     pvar->n1.n2.wReserved3 = header->wReserved3;
00611 
00612     if(header->vt & VT_ARRAY)
00613     {
00614         if(header->vt & VT_BYREF)
00615             Pos = LPSAFEARRAY_UserUnmarshal(pFlags, Pos, V_ARRAYREF(pvar));
00616         else
00617             Pos = LPSAFEARRAY_UserUnmarshal(pFlags, Pos, &V_ARRAY(pvar));
00618     }
00619     else
00620     {
00621         switch (header->vt)
00622         {
00623         case VT_BSTR:
00624             V_BSTR(pvar) = NULL;
00625             Pos = BSTR_UserUnmarshal(pFlags, Pos, &V_BSTR(pvar));
00626             break;
00627         case VT_BSTR | VT_BYREF:
00628             *V_BSTRREF(pvar) = NULL;
00629             Pos = BSTR_UserUnmarshal(pFlags, Pos, V_BSTRREF(pvar));
00630             break;
00631         case VT_VARIANT | VT_BYREF:
00632             Pos = VARIANT_UserUnmarshal(pFlags, Pos, V_VARIANTREF(pvar));
00633             break;
00634         case VT_UNKNOWN:
00635             /* this should probably call WdtpInterfacePointer_UserUnmarshal in ole32.dll */
00636             Pos = interface_variant_unmarshal(pFlags, Pos, &IID_IUnknown, &V_UNKNOWN(pvar));
00637             break;
00638         case VT_UNKNOWN | VT_BYREF:
00639             /* this should probably call WdtpInterfacePointer_UserUnmarshal in ole32.dll */
00640             Pos = interface_variant_unmarshal(pFlags, Pos, &IID_IUnknown, V_UNKNOWNREF(pvar));
00641             break;
00642         case VT_DISPATCH:
00643             /* this should probably call WdtpInterfacePointer_UserUnmarshal in ole32.dll */
00644             Pos = interface_variant_unmarshal(pFlags, Pos, &IID_IDispatch, (IUnknown**)&V_DISPATCH(pvar));
00645             break;
00646         case VT_DISPATCH | VT_BYREF:
00647             /* this should probably call WdtpInterfacePointer_UserUnmarshal in ole32.dll */
00648             Pos = interface_variant_unmarshal(pFlags, Pos, &IID_IDispatch, (IUnknown**)V_DISPATCHREF(pvar));
00649             break;
00650         case VT_RECORD:
00651             FIXME("handle BRECORD by val\n");
00652             break;
00653         case VT_RECORD | VT_BYREF:
00654             FIXME("handle BRECORD by ref\n");
00655             break;
00656         }
00657     }
00658     return Pos;
00659 }
00660 
00661 void WINAPI VARIANT_UserFree(ULONG *pFlags, VARIANT *pvar)
00662 {
00663   VARTYPE vt = V_VT(pvar);
00664   PVOID ref = NULL;
00665 
00666   TRACE("(%x,%p)\n", *pFlags, pvar);
00667   TRACE("vt=%04x\n", V_VT(pvar));
00668 
00669   if (vt & VT_BYREF) ref = pvar->n1.n2.n3.byref;
00670 
00671   VariantClear(pvar);
00672   if (!ref) return;
00673 
00674   if(vt & VT_ARRAY)
00675   {
00676     if (vt & VT_BYREF)
00677       LPSAFEARRAY_UserFree(pFlags, V_ARRAYREF(pvar));
00678     else
00679       LPSAFEARRAY_UserFree(pFlags, &V_ARRAY(pvar));
00680   }
00681   else
00682   {
00683     switch (vt)
00684     {
00685     case VT_BSTR | VT_BYREF:
00686       BSTR_UserFree(pFlags, V_BSTRREF(pvar));
00687       break;
00688     case VT_VARIANT | VT_BYREF:
00689       VARIANT_UserFree(pFlags, V_VARIANTREF(pvar));
00690       break;
00691     case VT_RECORD | VT_BYREF:
00692       FIXME("handle BRECORD by ref\n");
00693       break;
00694     case VT_UNKNOWN | VT_BYREF:
00695     case VT_DISPATCH | VT_BYREF:
00696       IUnknown_Release(*V_UNKNOWNREF(pvar));
00697       break;
00698     }
00699   }
00700 
00701   CoTaskMemFree(ref);
00702 }
00703 
00704 /* LPSAFEARRAY */
00705 
00706 /* Get the number of cells in a SafeArray */
00707 static ULONG SAFEARRAY_GetCellCount(const SAFEARRAY *psa)
00708 {
00709     const SAFEARRAYBOUND* psab = psa->rgsabound;
00710     USHORT cCount = psa->cDims;
00711     ULONG ulNumCells = 1;
00712 
00713     while (cCount--)
00714     {
00715         /* This is a valid bordercase. See testcases. -Marcus */
00716         if (!psab->cElements)
00717             return 0;
00718         ulNumCells *= psab->cElements;
00719         psab++;
00720     }
00721     return ulNumCells;
00722 }
00723 
00724 static inline SF_TYPE SAFEARRAY_GetUnionType(SAFEARRAY *psa)
00725 {
00726     VARTYPE vt;
00727     HRESULT hr;
00728 
00729     hr = SafeArrayGetVartype(psa, &vt);
00730     if (FAILED(hr))
00731     {
00732         if(psa->fFeatures & FADF_VARIANT) return SF_VARIANT;
00733 
00734         switch(psa->cbElements)
00735         {
00736         case 1: vt = VT_I1; break;
00737         case 2: vt = VT_I2; break;
00738         case 4: vt = VT_I4; break;
00739         case 8: vt = VT_I8; break;
00740         default:
00741             RpcRaiseException(hr);
00742         }
00743     }
00744 
00745     if (psa->fFeatures & FADF_HAVEIID)
00746         return SF_HAVEIID;
00747 
00748     switch (vt)
00749     {
00750     case VT_I1:
00751     case VT_UI1:      return SF_I1;
00752     case VT_BOOL:
00753     case VT_I2:
00754     case VT_UI2:      return SF_I2;
00755     case VT_INT:
00756     case VT_UINT:
00757     case VT_I4:
00758     case VT_UI4:
00759     case VT_R4:       return SF_I4;
00760     case VT_DATE:
00761     case VT_CY:
00762     case VT_R8:
00763     case VT_I8:
00764     case VT_UI8:      return SF_I8;
00765     case VT_INT_PTR:
00766     case VT_UINT_PTR: return (sizeof(UINT_PTR) == 4 ? SF_I4 : SF_I8);
00767     case VT_BSTR:     return SF_BSTR;
00768     case VT_DISPATCH: return SF_DISPATCH;
00769     case VT_VARIANT:  return SF_VARIANT;
00770     case VT_UNKNOWN:  return SF_UNKNOWN;
00771     /* Note: Return a non-zero size to indicate vt is valid. The actual size
00772      * of a UDT is taken from the result of IRecordInfo_GetSize().
00773      */
00774     case VT_RECORD:   return SF_RECORD;
00775     default:          return SF_ERROR;
00776     }
00777 }
00778 
00779 static DWORD elem_wire_size(LPSAFEARRAY lpsa, SF_TYPE sftype)
00780 {
00781     if (sftype == SF_BSTR)
00782         return sizeof(DWORD);
00783     else if (sftype == SF_VARIANT)
00784         return sizeof(variant_wire_t) - sizeof(DWORD);
00785     else
00786         return lpsa->cbElements;
00787 }
00788 
00789 static DWORD elem_mem_size(wireSAFEARRAY wiresa, SF_TYPE sftype)
00790 {
00791     if (sftype == SF_BSTR)
00792         return sizeof(BSTR);
00793     else if (sftype == SF_VARIANT)
00794         return sizeof(VARIANT);
00795     else
00796         return wiresa->cbElements;
00797 }
00798 
00799 ULONG WINAPI LPSAFEARRAY_UserSize(ULONG *pFlags, ULONG StartingSize, LPSAFEARRAY *ppsa)
00800 {
00801     ULONG size = StartingSize;
00802 
00803     TRACE("("); dump_user_flags(pFlags); TRACE(", %d, %p\n", StartingSize, *ppsa);
00804 
00805     ALIGN_LENGTH(size, 3);
00806     size += sizeof(ULONG);
00807     if (*ppsa)
00808     {
00809         SAFEARRAY *psa = *ppsa;
00810         ULONG ulCellCount = SAFEARRAY_GetCellCount(psa);
00811         SF_TYPE sftype;
00812         HRESULT hr;
00813 
00814         size += sizeof(ULONG);
00815         size += 2 * sizeof(USHORT) + 2 * sizeof(ULONG);
00816 
00817         sftype = SAFEARRAY_GetUnionType(psa);
00818         size += sizeof(ULONG);
00819 
00820         size += sizeof(ULONG);
00821         size += sizeof(ULONG);
00822         if (sftype == SF_HAVEIID)
00823             size += sizeof(IID);
00824 
00825         size += sizeof(psa->rgsabound[0]) * psa->cDims;
00826 
00827         size += sizeof(ULONG);
00828 
00829         switch (sftype)
00830         {
00831             case SF_BSTR:
00832             {
00833                 BSTR* lpBstr;
00834 
00835                 for (lpBstr = psa->pvData; ulCellCount; ulCellCount--, lpBstr++)
00836                     size = BSTR_UserSize(pFlags, size, lpBstr);
00837 
00838                 break;
00839             }
00840             case SF_DISPATCH:
00841             case SF_UNKNOWN:
00842             case SF_HAVEIID:
00843                 FIXME("size interfaces\n");
00844                 break;
00845             case SF_VARIANT:
00846             {
00847                 VARIANT* lpVariant;
00848 
00849                 for (lpVariant = psa->pvData; ulCellCount; ulCellCount--, lpVariant++)
00850                     size = VARIANT_UserSize(pFlags, size, lpVariant);
00851 
00852                 break;
00853             }
00854             case SF_RECORD:
00855             {
00856                 IRecordInfo* pRecInfo = NULL;
00857 
00858                 hr = SafeArrayGetRecordInfo(psa, &pRecInfo);
00859                 if (FAILED(hr))
00860                     RpcRaiseException(hr);
00861 
00862                 if (pRecInfo)
00863                 {
00864                     FIXME("size record info %p\n", pRecInfo);
00865 
00866                     IRecordInfo_Release(pRecInfo);
00867                 }
00868                 break;
00869             }
00870             case SF_I8:
00871                 ALIGN_LENGTH(size, 7);
00872                 /* fallthrough */
00873             case SF_I1:
00874             case SF_I2:
00875             case SF_I4:
00876                 size += ulCellCount * psa->cbElements;
00877                 break;
00878             default:
00879                 break;
00880         }
00881 
00882     }
00883 
00884     return size;
00885 }
00886 
00887 unsigned char * WINAPI LPSAFEARRAY_UserMarshal(ULONG *pFlags, unsigned char *Buffer, LPSAFEARRAY *ppsa)
00888 {
00889     HRESULT hr;
00890 
00891     TRACE("("); dump_user_flags(pFlags); TRACE(", %p, &%p\n", Buffer, *ppsa);
00892 
00893     ALIGN_POINTER(Buffer, 3);
00894     *(ULONG *)Buffer = *ppsa ? 0x1 : 0x0;
00895     Buffer += sizeof(ULONG);
00896     if (*ppsa)
00897     {
00898         VARTYPE vt;
00899         SAFEARRAY *psa = *ppsa;
00900         ULONG ulCellCount = SAFEARRAY_GetCellCount(psa);
00901         SF_TYPE sftype;
00902         GUID guid;
00903 
00904         sftype = SAFEARRAY_GetUnionType(psa);
00905 
00906         *(ULONG *)Buffer = psa->cDims;
00907         Buffer += sizeof(ULONG);
00908         *(USHORT *)Buffer = psa->cDims;
00909         Buffer += sizeof(USHORT);
00910         *(USHORT *)Buffer = psa->fFeatures;
00911         Buffer += sizeof(USHORT);
00912         *(ULONG *)Buffer = elem_wire_size(psa, sftype);
00913         Buffer += sizeof(ULONG);
00914 
00915         hr = SafeArrayGetVartype(psa, &vt);
00916         if (FAILED(hr)) vt = 0;
00917 
00918         *(ULONG *)Buffer = (USHORT)psa->cLocks | (vt << 16);
00919         Buffer += sizeof(ULONG);
00920 
00921         *(ULONG *)Buffer = sftype;
00922         Buffer += sizeof(ULONG);
00923 
00924         *(ULONG *)Buffer = ulCellCount;
00925         Buffer += sizeof(ULONG);
00926         *(ULONG *)Buffer = psa->pvData ? 0x2 : 0x0;
00927         Buffer += sizeof(ULONG);
00928         if (sftype == SF_HAVEIID)
00929         {
00930             SafeArrayGetIID(psa, &guid);
00931             memcpy(Buffer, &guid, sizeof(guid));
00932             Buffer += sizeof(guid);
00933         }
00934 
00935         memcpy(Buffer, psa->rgsabound, sizeof(psa->rgsabound[0]) * psa->cDims);
00936         Buffer += sizeof(psa->rgsabound[0]) * psa->cDims;
00937 
00938         *(ULONG *)Buffer = ulCellCount;
00939         Buffer += sizeof(ULONG);
00940 
00941         if (psa->pvData)
00942         {
00943             switch (sftype)
00944             {
00945                 case SF_BSTR:
00946                 {
00947                     BSTR* lpBstr;
00948 
00949                     for (lpBstr = psa->pvData; ulCellCount; ulCellCount--, lpBstr++)
00950                         Buffer = BSTR_UserMarshal(pFlags, Buffer, lpBstr);
00951 
00952                     break;
00953                 }
00954                 case SF_DISPATCH:
00955                 case SF_UNKNOWN:
00956                 case SF_HAVEIID:
00957                     FIXME("marshal interfaces\n");
00958                     break;
00959                 case SF_VARIANT:
00960                 {
00961                     VARIANT* lpVariant;
00962 
00963                     for (lpVariant = psa->pvData; ulCellCount; ulCellCount--, lpVariant++)
00964                         Buffer = VARIANT_UserMarshal(pFlags, Buffer, lpVariant);
00965 
00966                     break;
00967                 }
00968                 case SF_RECORD:
00969                 {
00970                     IRecordInfo* pRecInfo = NULL;
00971 
00972                     hr = SafeArrayGetRecordInfo(psa, &pRecInfo);
00973                     if (FAILED(hr))
00974                         RpcRaiseException(hr);
00975 
00976                     if (pRecInfo)
00977                     {
00978                         FIXME("write record info %p\n", pRecInfo);
00979 
00980                         IRecordInfo_Release(pRecInfo);
00981                     }
00982                     break;
00983                 }
00984 
00985                 case SF_I8:
00986                     ALIGN_POINTER(Buffer, 7);
00987                     /* fallthrough */
00988                 case SF_I1:
00989                 case SF_I2:
00990                 case SF_I4:
00991                     /* Just copy the data over */
00992                     memcpy(Buffer, psa->pvData, ulCellCount * psa->cbElements);
00993                     Buffer += ulCellCount * psa->cbElements;
00994                     break;
00995                 default:
00996                     break;
00997             }
00998         }
00999 
01000     }
01001     return Buffer;
01002 }
01003 
01004 #define FADF_AUTOSETFLAGS (FADF_HAVEIID | FADF_RECORD | FADF_HAVEVARTYPE | \
01005                            FADF_BSTR | FADF_UNKNOWN | FADF_DISPATCH | \
01006                            FADF_VARIANT | FADF_CREATEVECTOR)
01007 
01008 unsigned char * WINAPI LPSAFEARRAY_UserUnmarshal(ULONG *pFlags, unsigned char *Buffer, LPSAFEARRAY *ppsa)
01009 {
01010     ULONG ptr;
01011     wireSAFEARRAY wiresa;
01012     ULONG cDims;
01013     HRESULT hr;
01014     SF_TYPE sftype;
01015     ULONG cell_count;
01016     GUID guid;
01017     VARTYPE vt;
01018     SAFEARRAYBOUND *wiresab;
01019 
01020     TRACE("("); dump_user_flags(pFlags); TRACE(", %p, %p\n", Buffer, ppsa);
01021 
01022     ALIGN_POINTER(Buffer, 3);
01023     ptr = *(ULONG *)Buffer;
01024     Buffer += sizeof(ULONG);
01025 
01026     if (!ptr)
01027     {
01028         *ppsa = NULL;
01029 
01030         TRACE("NULL safe array unmarshaled\n");
01031 
01032         return Buffer;
01033     }
01034 
01035     cDims = *(ULONG *)Buffer;
01036     Buffer += sizeof(ULONG);
01037 
01038     wiresa = (wireSAFEARRAY)Buffer;
01039     Buffer += 2 * sizeof(USHORT) + 2 * sizeof(ULONG);
01040 
01041     if (cDims != wiresa->cDims)
01042         RpcRaiseException(RPC_S_INVALID_BOUND);
01043 
01044     /* FIXME: there should be a limit on how large cDims can be */
01045 
01046     vt = HIWORD(wiresa->cLocks);
01047 
01048     sftype = *(ULONG *)Buffer;
01049     Buffer += sizeof(ULONG);
01050 
01051     cell_count = *(ULONG *)Buffer;
01052     Buffer += sizeof(ULONG);
01053     ptr = *(ULONG *)Buffer;
01054     Buffer += sizeof(ULONG);
01055     if (sftype == SF_HAVEIID)
01056     {
01057         memcpy(&guid, Buffer, sizeof(guid));
01058         Buffer += sizeof(guid);
01059     }
01060 
01061     wiresab = (SAFEARRAYBOUND *)Buffer;
01062     Buffer += sizeof(wiresab[0]) * wiresa->cDims;
01063 
01064     if(vt)
01065         *ppsa = SafeArrayCreateEx(vt, wiresa->cDims, wiresab, NULL);
01066     else
01067     {
01068         SafeArrayAllocDescriptor(wiresa->cDims, ppsa);
01069         if(*ppsa)
01070             memcpy((*ppsa)->rgsabound, wiresab, sizeof(SAFEARRAYBOUND) * wiresa->cDims);
01071     }
01072     if (!*ppsa)
01073         RpcRaiseException(E_OUTOFMEMORY);
01074 
01075     /* be careful about which flags we set since they could be a security
01076      * risk */
01077     (*ppsa)->fFeatures &= FADF_AUTOSETFLAGS;
01078     (*ppsa)->fFeatures |= (wiresa->fFeatures & ~(FADF_AUTOSETFLAGS));
01079     /* FIXME: there should be a limit on how large wiresa->cbElements can be */
01080     (*ppsa)->cbElements = elem_mem_size(wiresa, sftype);
01081     (*ppsa)->cLocks = LOWORD(wiresa->cLocks);
01082 
01083     /* SafeArrayCreateEx allocates the data for us, but
01084      * SafeArrayAllocDescriptor doesn't */
01085     if(!vt)
01086     {
01087         hr = SafeArrayAllocData(*ppsa);
01088         if (FAILED(hr))
01089             RpcRaiseException(hr);
01090     }
01091 
01092     if ((*(ULONG *)Buffer != cell_count) || (SAFEARRAY_GetCellCount(*ppsa) != cell_count))
01093         RpcRaiseException(RPC_S_INVALID_BOUND);
01094     Buffer += sizeof(ULONG);
01095 
01096     if (ptr)
01097     {
01098         switch (sftype)
01099         {
01100             case SF_BSTR:
01101             {
01102                 BSTR* lpBstr;
01103 
01104                 for (lpBstr = (*ppsa)->pvData; cell_count; cell_count--, lpBstr++)
01105                     Buffer = BSTR_UserUnmarshal(pFlags, Buffer, lpBstr);
01106 
01107                 break;
01108             }
01109             case SF_DISPATCH:
01110             case SF_UNKNOWN:
01111             case SF_HAVEIID:
01112                 FIXME("marshal interfaces\n");
01113                 break;
01114             case SF_VARIANT:
01115             {
01116                 VARIANT* lpVariant;
01117 
01118                 for (lpVariant = (*ppsa)->pvData; cell_count; cell_count--, lpVariant++)
01119                     Buffer = VARIANT_UserUnmarshal(pFlags, Buffer, lpVariant);
01120 
01121                 break;
01122             }
01123             case SF_RECORD:
01124             {
01125                 FIXME("set record info\n");
01126 
01127                 break;
01128             }
01129 
01130             case SF_I8:
01131                 ALIGN_POINTER(Buffer, 7);
01132                 /* fallthrough */
01133             case SF_I1:
01134             case SF_I2:
01135             case SF_I4:
01136                 /* Just copy the data over */
01137                 memcpy((*ppsa)->pvData, Buffer, cell_count * (*ppsa)->cbElements);
01138                 Buffer += cell_count * (*ppsa)->cbElements;
01139                 break;
01140             default:
01141                 break;
01142         }
01143     }
01144 
01145     TRACE("safe array unmarshaled: %p\n", *ppsa);
01146 
01147     return Buffer;
01148 }
01149 
01150 void WINAPI LPSAFEARRAY_UserFree(ULONG *pFlags, LPSAFEARRAY *ppsa)
01151 {
01152     TRACE("("); dump_user_flags(pFlags); TRACE(", &%p\n", *ppsa);
01153 
01154     SafeArrayDestroy(*ppsa);
01155 }
01156 
01157 
01158 ULONG WINAPI HFONT_UserSize(ULONG *pFlags, ULONG Start, HFONT *phfont)
01159 {
01160     FIXME(":stub\n");
01161     return 0;
01162 }
01163 
01164 unsigned char * WINAPI HFONT_UserMarshal(ULONG *pFlags, unsigned char *Buffer, HFONT *phfont)
01165 {
01166     FIXME(":stub\n");
01167     return NULL;
01168 }
01169 
01170 unsigned char * WINAPI HFONT_UserUnmarshal(ULONG *pFlags, unsigned char *Buffer, HFONT *phfont)
01171 {
01172     FIXME(":stub\n");
01173     return NULL;
01174 }
01175 
01176 void WINAPI HFONT_UserFree(ULONG *pFlags, HFONT *phfont)
01177 {
01178     FIXME(":stub\n");
01179     return;
01180 }
01181 
01182 
01183 /* IDispatch */
01184 /* exactly how Invoke is marshalled is not very clear to me yet,
01185  * but the way I've done it seems to work for me */
01186 
01187 HRESULT CALLBACK IDispatch_Invoke_Proxy(
01188     IDispatch* This,
01189     DISPID dispIdMember,
01190     REFIID riid,
01191     LCID lcid,
01192     WORD wFlags,
01193     DISPPARAMS* pDispParams,
01194     VARIANT* pVarResult,
01195     EXCEPINFO* pExcepInfo,
01196     UINT* puArgErr)
01197 {
01198   HRESULT hr;
01199   VARIANT VarResult;
01200   UINT* rgVarRefIdx = NULL;
01201   VARIANTARG* rgVarRef = NULL;
01202   UINT u, cVarRef;
01203   UINT uArgErr;
01204   EXCEPINFO ExcepInfo;
01205 
01206   TRACE("(%p)->(%d,%s,%x,%x,%p,%p,%p,%p)\n", This,
01207         dispIdMember, debugstr_guid(riid),
01208         lcid, wFlags, pDispParams, pVarResult,
01209         pExcepInfo, puArgErr);
01210 
01211   /* [out] args can't be null, use dummy vars if needed */
01212   if (!pVarResult) pVarResult = &VarResult;
01213   if (!puArgErr) puArgErr = &uArgErr;
01214   if (!pExcepInfo) pExcepInfo = &ExcepInfo;
01215 
01216   /* count by-ref args */
01217   for (cVarRef=0,u=0; u<pDispParams->cArgs; u++) {
01218     VARIANTARG* arg = &pDispParams->rgvarg[u];
01219     if (V_ISBYREF(arg)) {
01220       cVarRef++;
01221     }
01222   }
01223   if (cVarRef) {
01224     rgVarRefIdx = CoTaskMemAlloc(sizeof(UINT)*cVarRef);
01225     rgVarRef = CoTaskMemAlloc(sizeof(VARIANTARG)*cVarRef);
01226     /* make list of by-ref args */
01227     for (cVarRef=0,u=0; u<pDispParams->cArgs; u++) {
01228       VARIANTARG* arg = &pDispParams->rgvarg[u];
01229       if (V_ISBYREF(arg)) {
01230     rgVarRefIdx[cVarRef] = u;
01231     VariantInit(&rgVarRef[cVarRef]);
01232     VariantCopy(&rgVarRef[cVarRef], arg);
01233     VariantClear(arg);
01234     cVarRef++;
01235       }
01236     }
01237   } else {
01238     /* [out] args still can't be null,
01239      * but we can point these anywhere in this case,
01240      * since they won't be written to when cVarRef is 0 */
01241     rgVarRefIdx = puArgErr;
01242     rgVarRef = pVarResult;
01243   }
01244   TRACE("passed by ref: %d args\n", cVarRef);
01245   hr = IDispatch_RemoteInvoke_Proxy(This,
01246                     dispIdMember,
01247                     riid,
01248                     lcid,
01249                     wFlags,
01250                     pDispParams,
01251                     pVarResult,
01252                     pExcepInfo,
01253                     puArgErr,
01254                     cVarRef,
01255                     rgVarRefIdx,
01256                     rgVarRef);
01257   if (cVarRef) {
01258     for (u=0; u<cVarRef; u++) {
01259       unsigned i = rgVarRefIdx[u];
01260       VariantCopy(&pDispParams->rgvarg[i],
01261           &rgVarRef[u]);
01262       VariantClear(&rgVarRef[u]);
01263     }
01264     CoTaskMemFree(rgVarRef);
01265     CoTaskMemFree(rgVarRefIdx);
01266   }
01267 
01268   if(pExcepInfo == &ExcepInfo)
01269   {
01270     SysFreeString(pExcepInfo->bstrSource);
01271     SysFreeString(pExcepInfo->bstrDescription);
01272     SysFreeString(pExcepInfo->bstrHelpFile);
01273   }
01274   return hr;
01275 }
01276 
01277 HRESULT __RPC_STUB IDispatch_Invoke_Stub(
01278     IDispatch* This,
01279     DISPID dispIdMember,
01280     REFIID riid,
01281     LCID lcid,
01282     DWORD dwFlags,
01283     DISPPARAMS* pDispParams,
01284     VARIANT* pVarResult,
01285     EXCEPINFO* pExcepInfo,
01286     UINT* pArgErr,
01287     UINT cVarRef,
01288     UINT* rgVarRefIdx,
01289     VARIANTARG* rgVarRef)
01290 {
01291   HRESULT hr = S_OK;
01292   VARIANTARG *rgvarg, *arg;
01293   UINT u;
01294 
01295   /* initialize out parameters, so that they can be marshalled
01296    * in case the real Invoke doesn't initialize them */
01297   VariantInit(pVarResult);
01298   memset(pExcepInfo, 0, sizeof(*pExcepInfo));
01299   *pArgErr = 0;
01300 
01301   /* let the real Invoke operate on a copy of the in parameters,
01302    * so we don't risk losing pointers to allocated memory */
01303   rgvarg = pDispParams->rgvarg;
01304   arg = CoTaskMemAlloc(sizeof(VARIANTARG)*pDispParams->cArgs);
01305   if (!arg) return E_OUTOFMEMORY;
01306 
01307   /* init all args so we can call VariantClear on all the args if the copy
01308    * below fails */
01309   for (u = 0; u < pDispParams->cArgs; u++)
01310     VariantInit(&arg[u]);
01311 
01312   for (u = 0; u < pDispParams->cArgs; u++) {
01313     hr = VariantCopy(&arg[u], &rgvarg[u]);
01314     if (FAILED(hr))
01315         break;
01316   }
01317 
01318   if (SUCCEEDED(hr)) {
01319     /* copy ref args to arg array */
01320     for (u=0; u<cVarRef; u++) {
01321       unsigned i = rgVarRefIdx[u];
01322       VariantCopy(&arg[i], &rgVarRef[u]);
01323     }
01324 
01325     pDispParams->rgvarg = arg;
01326 
01327     hr = IDispatch_Invoke(This,
01328               dispIdMember,
01329               riid,
01330               lcid,
01331               dwFlags,
01332               pDispParams,
01333               pVarResult,
01334               pExcepInfo,
01335               pArgErr);
01336 
01337     /* copy ref args from arg array */
01338     for (u=0; u<cVarRef; u++) {
01339       unsigned i = rgVarRefIdx[u];
01340       VariantCopy(&rgVarRef[u], &arg[i]);
01341     }
01342   }
01343 
01344   /* clear the duplicate argument list */
01345   for (u=0; u<pDispParams->cArgs; u++)
01346     VariantClear(&arg[u]);
01347 
01348   pDispParams->rgvarg = rgvarg;
01349   CoTaskMemFree(arg);
01350 
01351   return hr;
01352 }
01353 
01354 /* IEnumVARIANT */
01355 
01356 HRESULT CALLBACK IEnumVARIANT_Next_Proxy(
01357     IEnumVARIANT* This,
01358     ULONG celt,
01359     VARIANT* rgVar,
01360     ULONG* pCeltFetched)
01361 {
01362   ULONG fetched;
01363   if (!pCeltFetched)
01364     pCeltFetched = &fetched;
01365   return IEnumVARIANT_RemoteNext_Proxy(This,
01366                        celt,
01367                        rgVar,
01368                        pCeltFetched);
01369 }
01370 
01371 HRESULT __RPC_STUB IEnumVARIANT_Next_Stub(
01372     IEnumVARIANT* This,
01373     ULONG celt,
01374     VARIANT* rgVar,
01375     ULONG* pCeltFetched)
01376 {
01377   HRESULT hr;
01378   *pCeltFetched = 0;
01379   hr = IEnumVARIANT_Next(This,
01380              celt,
01381              rgVar,
01382              pCeltFetched);
01383   if (hr == S_OK) *pCeltFetched = celt;
01384   return hr;
01385 }
01386 
01387 /* TypeInfo related freers */
01388 
01389 static void free_embedded_typedesc(TYPEDESC *tdesc);
01390 static void free_embedded_arraydesc(ARRAYDESC *adesc)
01391 {
01392     switch(adesc->tdescElem.vt)
01393     {
01394     case VT_PTR:
01395     case VT_SAFEARRAY:
01396         free_embedded_typedesc(adesc->tdescElem.u.lptdesc);
01397         CoTaskMemFree(adesc->tdescElem.u.lptdesc);
01398         break;
01399     case VT_CARRAY:
01400         free_embedded_arraydesc(adesc->tdescElem.u.lpadesc);
01401         CoTaskMemFree(adesc->tdescElem.u.lpadesc);
01402         break;
01403     }
01404 }
01405 
01406 static void free_embedded_typedesc(TYPEDESC *tdesc)
01407 {
01408     switch(tdesc->vt)
01409     {
01410     case VT_PTR:
01411     case VT_SAFEARRAY:
01412         free_embedded_typedesc(tdesc->u.lptdesc);
01413         CoTaskMemFree(tdesc->u.lptdesc);
01414         break;
01415     case VT_CARRAY:
01416         free_embedded_arraydesc(tdesc->u.lpadesc);
01417         CoTaskMemFree(tdesc->u.lpadesc);
01418         break;
01419     }
01420 }
01421 
01422 static void free_embedded_elemdesc(ELEMDESC *edesc)
01423 {
01424     free_embedded_typedesc(&edesc->tdesc);
01425     if(edesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
01426         CoTaskMemFree(edesc->u.paramdesc.pparamdescex);
01427 }
01428 
01429 /* ITypeComp */
01430 
01431 HRESULT CALLBACK ITypeComp_Bind_Proxy(
01432     ITypeComp* This,
01433     LPOLESTR szName,
01434     ULONG lHashVal,
01435     WORD wFlags,
01436     ITypeInfo** ppTInfo,
01437     DESCKIND* pDescKind,
01438     BINDPTR* pBindPtr)
01439 {
01440   FIXME("not implemented\n");
01441   return E_FAIL;
01442 }
01443 
01444 HRESULT __RPC_STUB ITypeComp_Bind_Stub(
01445     ITypeComp* This,
01446     LPOLESTR szName,
01447     ULONG lHashVal,
01448     WORD wFlags,
01449     ITypeInfo** ppTInfo,
01450     DESCKIND* pDescKind,
01451     LPFUNCDESC* ppFuncDesc,
01452     LPVARDESC* ppVarDesc,
01453     ITypeComp** ppTypeComp,
01454     CLEANLOCALSTORAGE* pDummy)
01455 {
01456   FIXME("not implemented\n");
01457   return E_FAIL;
01458 }
01459 
01460 HRESULT CALLBACK ITypeComp_BindType_Proxy(
01461     ITypeComp* This,
01462     LPOLESTR szName,
01463     ULONG lHashVal,
01464     ITypeInfo** ppTInfo,
01465     ITypeComp** ppTComp)
01466 {
01467   FIXME("not implemented\n");
01468   return E_FAIL;
01469 }
01470 
01471 HRESULT __RPC_STUB ITypeComp_BindType_Stub(
01472     ITypeComp* This,
01473     LPOLESTR szName,
01474     ULONG lHashVal,
01475     ITypeInfo** ppTInfo)
01476 {
01477   FIXME("not implemented\n");
01478   return E_FAIL;
01479 }
01480 
01481 /* ITypeInfo */
01482 
01483 HRESULT CALLBACK ITypeInfo_GetTypeAttr_Proxy(
01484     ITypeInfo* This,
01485     TYPEATTR** ppTypeAttr)
01486 
01487 {
01488     CLEANLOCALSTORAGE stg;
01489     TRACE("(%p, %p)\n", This, ppTypeAttr);
01490 
01491     stg.flags = 0;
01492     stg.pStorage = NULL;
01493     stg.pInterface = NULL;
01494 
01495     return ITypeInfo_RemoteGetTypeAttr_Proxy(This, ppTypeAttr, &stg);
01496 }
01497 
01498 HRESULT __RPC_STUB ITypeInfo_GetTypeAttr_Stub(
01499     ITypeInfo* This,
01500     LPTYPEATTR* ppTypeAttr,
01501     CLEANLOCALSTORAGE* pDummy)
01502 {
01503     HRESULT hr;
01504     TRACE("(%p, %p)\n", This, ppTypeAttr);
01505 
01506     hr = ITypeInfo_GetTypeAttr(This, ppTypeAttr);
01507     if(hr != S_OK)
01508         return hr;
01509 
01510     pDummy->flags = CLS_TYPEATTR;
01511     ITypeInfo_AddRef(This);
01512     pDummy->pInterface = (IUnknown*)This;
01513     pDummy->pStorage = ppTypeAttr;
01514     return hr;
01515 }
01516 
01517 HRESULT CALLBACK ITypeInfo_GetFuncDesc_Proxy(
01518     ITypeInfo* This,
01519     UINT index,
01520     FUNCDESC** ppFuncDesc)
01521 {
01522     CLEANLOCALSTORAGE stg;
01523     TRACE("(%p, %d, %p)\n", This, index, ppFuncDesc);
01524 
01525     stg.flags = 0;
01526     stg.pStorage = NULL;
01527     stg.pInterface = NULL;
01528 
01529     return ITypeInfo_RemoteGetFuncDesc_Proxy(This, index, ppFuncDesc, &stg);
01530 }
01531 
01532 HRESULT __RPC_STUB ITypeInfo_GetFuncDesc_Stub(
01533     ITypeInfo* This,
01534     UINT index,
01535     LPFUNCDESC* ppFuncDesc,
01536     CLEANLOCALSTORAGE* pDummy)
01537 {
01538     HRESULT hr;
01539     TRACE("(%p, %d, %p)\n", This, index, ppFuncDesc);
01540 
01541     hr = ITypeInfo_GetFuncDesc(This, index, ppFuncDesc);
01542     if(hr != S_OK)
01543         return hr;
01544 
01545     pDummy->flags = CLS_FUNCDESC;
01546     ITypeInfo_AddRef(This);
01547     pDummy->pInterface = (IUnknown*)This;
01548     pDummy->pStorage = ppFuncDesc;
01549     return hr;
01550 }
01551 
01552 HRESULT CALLBACK ITypeInfo_GetVarDesc_Proxy(
01553     ITypeInfo* This,
01554     UINT index,
01555     VARDESC** ppVarDesc)
01556 {
01557     CLEANLOCALSTORAGE stg;
01558     TRACE("(%p, %d, %p)\n", This, index, ppVarDesc);
01559 
01560     stg.flags = 0;
01561     stg.pStorage = NULL;
01562     stg.pInterface = NULL;
01563 
01564     return ITypeInfo_RemoteGetVarDesc_Proxy(This, index, ppVarDesc, &stg);
01565 }
01566 
01567 HRESULT __RPC_STUB ITypeInfo_GetVarDesc_Stub(
01568     ITypeInfo* This,
01569     UINT index,
01570     LPVARDESC* ppVarDesc,
01571     CLEANLOCALSTORAGE* pDummy)
01572 {
01573     HRESULT hr;
01574     TRACE("(%p, %d, %p)\n", This, index, ppVarDesc);
01575 
01576     hr = ITypeInfo_GetVarDesc(This, index, ppVarDesc);
01577     if(hr != S_OK)
01578         return hr;
01579 
01580     pDummy->flags = CLS_VARDESC;
01581     ITypeInfo_AddRef(This);
01582     pDummy->pInterface = (IUnknown*)This;
01583     pDummy->pStorage = ppVarDesc;
01584     return hr;
01585 }
01586 
01587 HRESULT CALLBACK ITypeInfo_GetNames_Proxy(
01588     ITypeInfo* This,
01589     MEMBERID memid,
01590     BSTR* rgBstrNames,
01591     UINT cMaxNames,
01592     UINT* pcNames)
01593 {
01594   FIXME("not implemented\n");
01595   return E_FAIL;
01596 }
01597 
01598 HRESULT __RPC_STUB ITypeInfo_GetNames_Stub(
01599     ITypeInfo* This,
01600     MEMBERID memid,
01601     BSTR* rgBstrNames,
01602     UINT cMaxNames,
01603     UINT* pcNames)
01604 {
01605   FIXME("not implemented\n");
01606   return E_FAIL;
01607 }
01608 
01609 HRESULT CALLBACK ITypeInfo_GetIDsOfNames_Proxy(
01610     ITypeInfo* This,
01611     LPOLESTR* rgszNames,
01612     UINT cNames,
01613     MEMBERID* pMemId)
01614 {
01615   FIXME("not implemented\n");
01616   return E_FAIL;
01617 }
01618 
01619 HRESULT __RPC_STUB ITypeInfo_GetIDsOfNames_Stub(
01620     ITypeInfo* This)
01621 {
01622   FIXME("not implemented\n");
01623   return E_FAIL;
01624 }
01625 
01626 HRESULT CALLBACK ITypeInfo_Invoke_Proxy(
01627     ITypeInfo* This,
01628     PVOID pvInstance,
01629     MEMBERID memid,
01630     WORD wFlags,
01631     DISPPARAMS* pDispParams,
01632     VARIANT* pVarResult,
01633     EXCEPINFO* pExcepInfo,
01634     UINT* puArgErr)
01635 {
01636   FIXME("not implemented\n");
01637   return E_FAIL;
01638 }
01639 
01640 HRESULT __RPC_STUB ITypeInfo_Invoke_Stub(
01641     ITypeInfo* This)
01642 {
01643   FIXME("not implemented\n");
01644   return E_FAIL;
01645 }
01646 
01647 HRESULT CALLBACK ITypeInfo_GetDocumentation_Proxy(
01648     ITypeInfo* This,
01649     MEMBERID memid,
01650     BSTR* pBstrName,
01651     BSTR* pBstrDocString,
01652     DWORD* pdwHelpContext,
01653     BSTR* pBstrHelpFile)
01654 {
01655     DWORD help_context;
01656     BSTR name, doc_string, help_file;
01657     HRESULT hr;
01658     TRACE("(%p, %08x, %p, %p, %p, %p)\n", This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
01659 
01660     /* FIXME: presumably refPtrFlags is supposed to be a bitmask of which ptrs we actually want? */
01661     hr = ITypeInfo_RemoteGetDocumentation_Proxy(This, memid, 0, &name, &doc_string, &help_context, &help_file);
01662     if(SUCCEEDED(hr))
01663     {
01664         if(pBstrName) *pBstrName = name;
01665         else SysFreeString(name);
01666 
01667         if(pBstrDocString) *pBstrDocString = doc_string;
01668         else SysFreeString(doc_string);
01669 
01670         if(pBstrHelpFile) *pBstrHelpFile = help_file;
01671         else SysFreeString(help_file);
01672 
01673         if(pdwHelpContext) *pdwHelpContext = help_context;
01674     }
01675     return hr;
01676 }
01677 
01678 HRESULT __RPC_STUB ITypeInfo_GetDocumentation_Stub(
01679     ITypeInfo* This,
01680     MEMBERID memid,
01681     DWORD refPtrFlags,
01682     BSTR* pBstrName,
01683     BSTR* pBstrDocString,
01684     DWORD* pdwHelpContext,
01685     BSTR* pBstrHelpFile)
01686 {
01687     TRACE("(%p, %08x, %08x, %p, %p, %p, %p)\n", This, memid, refPtrFlags, pBstrName, pBstrDocString,
01688           pdwHelpContext, pBstrHelpFile);
01689     return ITypeInfo_GetDocumentation(This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
01690 }
01691 
01692 HRESULT CALLBACK ITypeInfo_GetDllEntry_Proxy(
01693     ITypeInfo* This,
01694     MEMBERID memid,
01695     INVOKEKIND invKind,
01696     BSTR* pBstrDllName,
01697     BSTR* pBstrName,
01698     WORD* pwOrdinal)
01699 {
01700   FIXME("not implemented\n");
01701   return E_FAIL;
01702 }
01703 
01704 HRESULT __RPC_STUB ITypeInfo_GetDllEntry_Stub(
01705     ITypeInfo* This,
01706     MEMBERID memid,
01707     INVOKEKIND invKind,
01708     DWORD refPtrFlags,
01709     BSTR* pBstrDllName,
01710     BSTR* pBstrName,
01711     WORD* pwOrdinal)
01712 {
01713   FIXME("not implemented\n");
01714   return E_FAIL;
01715 }
01716 
01717 HRESULT CALLBACK ITypeInfo_AddressOfMember_Proxy(
01718     ITypeInfo* This,
01719     MEMBERID memid,
01720     INVOKEKIND invKind,
01721     PVOID* ppv)
01722 {
01723   FIXME("not implemented\n");
01724   return E_FAIL;
01725 }
01726 
01727 HRESULT __RPC_STUB ITypeInfo_AddressOfMember_Stub(
01728     ITypeInfo* This)
01729 {
01730   FIXME("not implemented\n");
01731   return E_FAIL;
01732 }
01733 
01734 HRESULT CALLBACK ITypeInfo_CreateInstance_Proxy(
01735     ITypeInfo* This,
01736     IUnknown* pUnkOuter,
01737     REFIID riid,
01738     PVOID* ppvObj)
01739 {
01740   FIXME("not implemented\n");
01741   return E_FAIL;
01742 }
01743 
01744 HRESULT __RPC_STUB ITypeInfo_CreateInstance_Stub(
01745     ITypeInfo* This,
01746     REFIID riid,
01747     IUnknown** ppvObj)
01748 {
01749   FIXME("not implemented\n");
01750   return E_FAIL;
01751 }
01752 
01753 HRESULT CALLBACK ITypeInfo_GetContainingTypeLib_Proxy(
01754     ITypeInfo* This,
01755     ITypeLib** ppTLib,
01756     UINT* pIndex)
01757 {
01758     ITypeLib *pTL;
01759     UINT index;
01760     HRESULT hr;
01761 
01762     TRACE("(%p, %p, %p)\n", This, ppTLib, pIndex );
01763     
01764     hr = ITypeInfo_RemoteGetContainingTypeLib_Proxy(This, &pTL, &index);
01765     if(SUCCEEDED(hr))
01766     {
01767         if(pIndex)
01768             *pIndex = index;
01769 
01770         if(ppTLib)
01771             *ppTLib = pTL;
01772         else
01773             ITypeLib_Release(pTL);
01774     }
01775     return hr;
01776 }
01777 
01778 HRESULT __RPC_STUB ITypeInfo_GetContainingTypeLib_Stub(
01779     ITypeInfo* This,
01780     ITypeLib** ppTLib,
01781     UINT* pIndex)
01782 {
01783     TRACE("(%p, %p, %p)\n", This, ppTLib, pIndex );
01784     return ITypeInfo_GetContainingTypeLib(This, ppTLib, pIndex);
01785 }
01786 
01787 void CALLBACK ITypeInfo_ReleaseTypeAttr_Proxy(
01788     ITypeInfo* This,
01789     TYPEATTR* pTypeAttr)
01790 {
01791     TRACE("(%p, %p)\n", This, pTypeAttr);
01792     free_embedded_typedesc(&pTypeAttr->tdescAlias);
01793     CoTaskMemFree(pTypeAttr);
01794 }
01795 
01796 HRESULT __RPC_STUB ITypeInfo_ReleaseTypeAttr_Stub(
01797     ITypeInfo* This)
01798 {
01799     TRACE("nothing to do\n");
01800     return S_OK;
01801 }
01802 
01803 void CALLBACK ITypeInfo_ReleaseFuncDesc_Proxy(
01804     ITypeInfo* This,
01805     FUNCDESC* pFuncDesc)
01806 {
01807     SHORT param;
01808     TRACE("(%p, %p)\n", This, pFuncDesc);
01809 
01810     for(param = 0; param < pFuncDesc->cParams; param++)
01811         free_embedded_elemdesc(pFuncDesc->lprgelemdescParam + param);
01812     if(param)
01813         CoTaskMemFree(pFuncDesc->lprgelemdescParam);
01814 
01815     free_embedded_elemdesc(&pFuncDesc->elemdescFunc);
01816 
01817     if(pFuncDesc->cScodes != 0 && pFuncDesc->cScodes != -1)
01818         CoTaskMemFree(pFuncDesc->lprgscode);
01819 
01820     CoTaskMemFree(pFuncDesc);
01821 }
01822 
01823 HRESULT __RPC_STUB ITypeInfo_ReleaseFuncDesc_Stub(
01824     ITypeInfo* This)
01825 {
01826     TRACE("nothing to do\n");
01827     return S_OK;
01828 }
01829 
01830 void CALLBACK ITypeInfo_ReleaseVarDesc_Proxy(
01831     ITypeInfo* This,
01832     VARDESC* pVarDesc)
01833 {
01834     TRACE("(%p, %p)\n", This, pVarDesc);
01835 
01836     CoTaskMemFree(pVarDesc->lpstrSchema);
01837 
01838     if(pVarDesc->varkind == VAR_CONST)
01839         CoTaskMemFree(pVarDesc->u.lpvarValue);
01840 
01841     free_embedded_elemdesc(&pVarDesc->elemdescVar);
01842     CoTaskMemFree(pVarDesc);
01843 }
01844 
01845 HRESULT __RPC_STUB ITypeInfo_ReleaseVarDesc_Stub(
01846     ITypeInfo* This)
01847 {
01848     TRACE("nothing to do\n");
01849     return S_OK;
01850 }
01851 
01852 
01853 /* ITypeInfo2 */
01854 
01855 HRESULT CALLBACK ITypeInfo2_GetDocumentation2_Proxy(
01856     ITypeInfo2* This,
01857     MEMBERID memid,
01858     LCID lcid,
01859     BSTR* pbstrHelpString,
01860     DWORD* pdwHelpStringContext,
01861     BSTR* pbstrHelpStringDll)
01862 {
01863   FIXME("not implemented\n");
01864   return E_FAIL;
01865 }
01866 
01867 HRESULT __RPC_STUB ITypeInfo2_GetDocumentation2_Stub(
01868     ITypeInfo2* This,
01869     MEMBERID memid,
01870     LCID lcid,
01871     DWORD refPtrFlags,
01872     BSTR* pbstrHelpString,
01873     DWORD* pdwHelpStringContext,
01874     BSTR* pbstrHelpStringDll)
01875 {
01876   FIXME("not implemented\n");
01877   return E_FAIL;
01878 }
01879 
01880 /* ITypeLib */
01881 
01882 UINT CALLBACK ITypeLib_GetTypeInfoCount_Proxy(
01883     ITypeLib* This)
01884 {
01885     UINT count = 0;
01886     TRACE("(%p)\n", This);
01887 
01888     ITypeLib_RemoteGetTypeInfoCount_Proxy(This, &count);
01889     
01890     return count;
01891 }
01892 
01893 HRESULT __RPC_STUB ITypeLib_GetTypeInfoCount_Stub(
01894     ITypeLib* This,
01895     UINT* pcTInfo)
01896 {
01897     TRACE("(%p, %p)\n", This, pcTInfo);
01898     *pcTInfo = ITypeLib_GetTypeInfoCount(This);
01899     return S_OK;
01900 }
01901 
01902 HRESULT CALLBACK ITypeLib_GetLibAttr_Proxy(
01903     ITypeLib* This,
01904     TLIBATTR** ppTLibAttr)
01905 {
01906     CLEANLOCALSTORAGE stg;
01907     TRACE("(%p, %p)\n", This, ppTLibAttr);
01908 
01909     stg.flags = 0;
01910     stg.pStorage = NULL;
01911     stg.pInterface = NULL;
01912 
01913     return ITypeLib_RemoteGetLibAttr_Proxy(This, ppTLibAttr, &stg);    
01914 }
01915 
01916 HRESULT __RPC_STUB ITypeLib_GetLibAttr_Stub(
01917     ITypeLib* This,
01918     LPTLIBATTR* ppTLibAttr,
01919     CLEANLOCALSTORAGE* pDummy)
01920 {
01921     HRESULT hr;
01922     TRACE("(%p, %p)\n", This, ppTLibAttr);
01923     
01924     hr = ITypeLib_GetLibAttr(This, ppTLibAttr);
01925     if(hr != S_OK)
01926         return hr;
01927 
01928     pDummy->flags = CLS_LIBATTR;
01929     ITypeLib_AddRef(This);
01930     pDummy->pInterface = (IUnknown*)This;
01931     pDummy->pStorage = ppTLibAttr;
01932     return hr;
01933 }
01934 
01935 HRESULT CALLBACK ITypeLib_GetDocumentation_Proxy(
01936     ITypeLib* This,
01937     INT index,
01938     BSTR* pBstrName,
01939     BSTR* pBstrDocString,
01940     DWORD* pdwHelpContext,
01941     BSTR* pBstrHelpFile)
01942 {
01943   FIXME("not implemented\n");
01944   return E_FAIL;
01945 }
01946 
01947 HRESULT __RPC_STUB ITypeLib_GetDocumentation_Stub(
01948     ITypeLib* This,
01949     INT index,
01950     DWORD refPtrFlags,
01951     BSTR* pBstrName,
01952     BSTR* pBstrDocString,
01953     DWORD* pdwHelpContext,
01954     BSTR* pBstrHelpFile)
01955 {
01956   FIXME("not implemented\n");
01957   return E_FAIL;
01958 }
01959 
01960 HRESULT CALLBACK ITypeLib_IsName_Proxy(
01961     ITypeLib* This,
01962     LPOLESTR szNameBuf,
01963     ULONG lHashVal,
01964     BOOL* pfName)
01965 {
01966   FIXME("not implemented\n");
01967   return E_FAIL;
01968 }
01969 
01970 HRESULT __RPC_STUB ITypeLib_IsName_Stub(
01971     ITypeLib* This,
01972     LPOLESTR szNameBuf,
01973     ULONG lHashVal,
01974     BOOL* pfName,
01975     BSTR* pBstrLibName)
01976 {
01977   FIXME("not implemented\n");
01978   return E_FAIL;
01979 }
01980 
01981 HRESULT CALLBACK ITypeLib_FindName_Proxy(
01982     ITypeLib* This,
01983     LPOLESTR szNameBuf,
01984     ULONG lHashVal,
01985     ITypeInfo** ppTInfo,
01986     MEMBERID* rgMemId,
01987     USHORT* pcFound)
01988 {
01989   FIXME("not implemented\n");
01990   return E_FAIL;
01991 }
01992 
01993 HRESULT __RPC_STUB ITypeLib_FindName_Stub(
01994     ITypeLib* This,
01995     LPOLESTR szNameBuf,
01996     ULONG lHashVal,
01997     ITypeInfo** ppTInfo,
01998     MEMBERID* rgMemId,
01999     USHORT* pcFound,
02000     BSTR* pBstrLibName)
02001 {
02002   FIXME("not implemented\n");
02003   return E_FAIL;
02004 }
02005 
02006 void CALLBACK ITypeLib_ReleaseTLibAttr_Proxy(
02007     ITypeLib* This,
02008     TLIBATTR* pTLibAttr)
02009 {
02010     TRACE("(%p, %p)\n", This, pTLibAttr);
02011     CoTaskMemFree(pTLibAttr);
02012 }
02013 
02014 HRESULT __RPC_STUB ITypeLib_ReleaseTLibAttr_Stub(
02015     ITypeLib* This)
02016 {
02017     TRACE("nothing to do\n");
02018     return S_OK;
02019 }
02020 
02021 
02022 /* ITypeLib2 */
02023 
02024 HRESULT CALLBACK ITypeLib2_GetLibStatistics_Proxy(
02025     ITypeLib2* This,
02026     ULONG* pcUniqueNames,
02027     ULONG* pcchUniqueNames)
02028 {
02029   FIXME("not implemented\n");
02030   return E_FAIL;
02031 }
02032 
02033 HRESULT __RPC_STUB ITypeLib2_GetLibStatistics_Stub(
02034     ITypeLib2* This,
02035     ULONG* pcUniqueNames,
02036     ULONG* pcchUniqueNames)
02037 {
02038   FIXME("not implemented\n");
02039   return E_FAIL;
02040 }
02041 
02042 HRESULT CALLBACK ITypeLib2_GetDocumentation2_Proxy(
02043     ITypeLib2* This,
02044     INT index,
02045     LCID lcid,
02046     BSTR* pbstrHelpString,
02047     DWORD* pdwHelpStringContext,
02048     BSTR* pbstrHelpStringDll)
02049 {
02050   FIXME("not implemented\n");
02051   return E_FAIL;
02052 }
02053 
02054 HRESULT __RPC_STUB ITypeLib2_GetDocumentation2_Stub(
02055     ITypeLib2* This,
02056     INT index,
02057     LCID lcid,
02058     DWORD refPtrFlags,
02059     BSTR* pbstrHelpString,
02060     DWORD* pdwHelpStringContext,
02061     BSTR* pbstrHelpStringDll)
02062 {
02063   FIXME("not implemented\n");
02064   return E_FAIL;
02065 }
02066 
02067 HRESULT CALLBACK IPropertyBag_Read_Proxy(
02068     IPropertyBag* This,
02069     LPCOLESTR pszPropName,
02070     VARIANT *pVar,
02071     IErrorLog *pErrorLog)
02072 {
02073   IUnknown *pUnk = NULL;
02074   TRACE("(%p, %s, %p, %p)\n", This, debugstr_w(pszPropName), pVar, pErrorLog);
02075 
02076   if(!pVar)
02077     return E_POINTER;
02078 
02079   if(V_VT(pVar) & (VT_BYREF | VT_ARRAY | VT_VECTOR))
02080   {
02081     FIXME("Variant type %x is byref, array or vector. Not implemented.\n", V_VT(pVar));
02082     return E_NOTIMPL;
02083   }
02084 
02085   switch(V_VT(pVar))
02086   {
02087     case VT_DISPATCH:
02088       pUnk = (IUnknown*)V_DISPATCH(pVar);
02089       break;
02090     case VT_UNKNOWN:
02091       pUnk = V_UNKNOWN(pVar);
02092       break;
02093     case VT_SAFEARRAY:
02094       FIXME("Safearray support not yet implemented.\n");
02095       return E_NOTIMPL;
02096     default:
02097       FIXME("Unknown V_VT %d - support not yet implemented.\n", V_VT(pVar));
02098       return E_NOTIMPL;
02099   }
02100 
02101   return IPropertyBag_RemoteRead_Proxy(This, pszPropName, pVar, pErrorLog,
02102                                        V_VT(pVar), pUnk);
02103 }
02104 
02105 HRESULT __RPC_STUB IPropertyBag_Read_Stub(
02106     IPropertyBag* This,
02107     LPCOLESTR pszPropName,
02108     VARIANT *pVar,
02109     IErrorLog *pErrorLog,
02110     DWORD varType,
02111     IUnknown *pUnkObj)
02112 {
02113   static const WCHAR emptyWstr[1] = {0};
02114   IDispatch *disp;
02115   HRESULT hr;
02116   TRACE("(%p, %s, %p, %p, %x, %p)\n", This, debugstr_w(pszPropName), pVar,
02117                                      pErrorLog, varType, pUnkObj);
02118 
02119   if(varType & (VT_BYREF | VT_ARRAY | VT_VECTOR))
02120   {
02121     FIXME("Variant type %x is byref, array or vector. Not implemented.\n", V_VT(pVar));
02122     return E_NOTIMPL;
02123   }
02124 
02125   V_VT(pVar) = varType;
02126   switch(varType)
02127   {
02128     case VT_DISPATCH:
02129       hr = IUnknown_QueryInterface(pUnkObj, &IID_IDispatch, (LPVOID*)&disp);
02130       if(FAILED(hr))
02131         return hr;
02132       IUnknown_Release(pUnkObj);
02133       V_DISPATCH(pVar) = disp;
02134       break;
02135     case VT_UNKNOWN:
02136       V_UNKNOWN(pVar) = pUnkObj;
02137       break;
02138     case VT_BSTR:
02139       V_BSTR(pVar) = SysAllocString(emptyWstr);
02140       break;
02141     case VT_SAFEARRAY:
02142       FIXME("Safearray support not yet implemented.\n");
02143       return E_NOTIMPL;
02144     default:
02145       break;
02146   }
02147   hr = IPropertyBag_Read(This, pszPropName, pVar, pErrorLog);
02148   if(FAILED(hr))
02149     VariantClear(pVar);
02150 
02151   return hr;
02152 }
02153 
02154 /* call_as/local stubs for ocidl.idl */
02155 
02156 HRESULT CALLBACK IClassFactory2_CreateInstanceLic_Proxy(
02157     IClassFactory2* This,
02158     IUnknown *pUnkOuter,
02159     IUnknown *pUnkReserved,
02160     REFIID riid,
02161     BSTR bstrKey,
02162     PVOID *ppvObj)
02163 {
02164     FIXME("not implemented\n");
02165     return E_NOTIMPL;
02166 }
02167 
02168 HRESULT __RPC_STUB IClassFactory2_CreateInstanceLic_Stub(
02169     IClassFactory2* This,
02170     REFIID riid,
02171     BSTR bstrKey,
02172     IUnknown **ppvObj)
02173 {
02174     FIXME("not implemented\n");
02175     return E_NOTIMPL;
02176 }
02177 
02178 HRESULT CALLBACK IEnumConnections_Next_Proxy(
02179     IEnumConnections* This,
02180     ULONG cConnections,
02181     LPCONNECTDATA rgcd,
02182     ULONG *pcFetched)
02183 {
02184     FIXME("not implemented\n");
02185     return E_NOTIMPL;
02186 }
02187 
02188 HRESULT __RPC_STUB IEnumConnections_Next_Stub(
02189     IEnumConnections* This,
02190     ULONG cConnections,
02191     LPCONNECTDATA rgcd,
02192     ULONG *pcFetched)
02193 {
02194     FIXME("not implemented\n");
02195     return E_NOTIMPL;
02196 }
02197 
02198 HRESULT CALLBACK IEnumConnectionPoints_Next_Proxy(
02199     IEnumConnectionPoints* This,
02200     ULONG cConnections,
02201     LPCONNECTIONPOINT *ppCP,
02202     ULONG *pcFetched)
02203 {
02204     FIXME("not implemented\n");
02205     return E_NOTIMPL;
02206 }
02207 
02208 HRESULT __RPC_STUB IEnumConnectionPoints_Next_Stub(
02209     IEnumConnectionPoints* This,
02210     ULONG cConnections,
02211     LPCONNECTIONPOINT *ppCP,
02212     ULONG *pcFetched)
02213 {
02214     FIXME("not implemented\n");
02215     return E_NOTIMPL;
02216 }
02217 
02218 HRESULT CALLBACK IPersistMemory_Load_Proxy(
02219     IPersistMemory* This,
02220     LPVOID pMem,
02221     ULONG cbSize)
02222 {
02223     FIXME("not implemented\n");
02224     return E_NOTIMPL;
02225 }
02226 
02227 HRESULT __RPC_STUB IPersistMemory_Load_Stub(
02228     IPersistMemory* This,
02229     BYTE *pMem,
02230     ULONG cbSize)
02231 {
02232     FIXME("not implemented\n");
02233     return E_NOTIMPL;
02234 }
02235 
02236 HRESULT CALLBACK IPersistMemory_Save_Proxy(
02237     IPersistMemory* This,
02238     LPVOID pMem,
02239     BOOL fClearDirty,
02240     ULONG cbSize)
02241 {
02242     FIXME("not implemented\n");
02243     return E_NOTIMPL;
02244 }
02245 
02246 HRESULT __RPC_STUB IPersistMemory_Save_Stub(
02247     IPersistMemory* This,
02248     BYTE *pMem,
02249     BOOL fClearDirty,
02250     ULONG cbSize)
02251 {
02252     FIXME("not implemented\n");
02253     return E_NOTIMPL;
02254 }
02255 
02256 void CALLBACK IAdviseSinkEx_OnViewStatusChange_Proxy(
02257     IAdviseSinkEx* This,
02258     DWORD dwViewStatus)
02259 {
02260     FIXME("not implemented\n");
02261 }
02262 
02263 HRESULT __RPC_STUB IAdviseSinkEx_OnViewStatusChange_Stub(
02264     IAdviseSinkEx* This,
02265     DWORD dwViewStatus)
02266 {
02267     FIXME("not implemented\n");
02268     return E_NOTIMPL;
02269 }
02270 
02271 HRESULT CALLBACK IEnumOleUndoUnits_Next_Proxy(
02272     IEnumOleUndoUnits* This,
02273     ULONG cElt,
02274     IOleUndoUnit **rgElt,
02275     ULONG *pcEltFetched)
02276 {
02277     FIXME("not implemented\n");
02278     return E_NOTIMPL;
02279 }
02280 
02281 HRESULT __RPC_STUB IEnumOleUndoUnits_Next_Stub(
02282     IEnumOleUndoUnits* This,
02283     ULONG cElt,
02284     IOleUndoUnit **rgElt,
02285     ULONG *pcEltFetched)
02286 {
02287     FIXME("not implemented\n");
02288     return E_NOTIMPL;
02289 }
02290 
02291 HRESULT CALLBACK IQuickActivate_QuickActivate_Proxy(
02292     IQuickActivate* This,
02293     QACONTAINER *pQaContainer,
02294     QACONTROL *pQaControl)
02295 {
02296     FIXME("not implemented\n");
02297     return E_NOTIMPL;
02298 }
02299 
02300 HRESULT __RPC_STUB IQuickActivate_QuickActivate_Stub(
02301     IQuickActivate* This,
02302     QACONTAINER *pQaContainer,
02303     QACONTROL *pQaControl)
02304 {
02305     FIXME("not implemented\n");
02306     return E_NOTIMPL;
02307 }

Generated on Sat May 26 2012 04:21:08 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.