2 * Misc marshalling routines
4 * Copyright 2002 Ove Kaaven
5 * Copyright 2003 Mike Hearn
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 #define NONAMELESSUNION
27 #define NONAMELESSSTRUCT
38 #include "wine/debug.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(ole);
42 /* FIXME: not supposed to be here */
44 const CLSID CLSID_PSDispatch = {
45 0x20420, 0, 0, {0xC0, 0, 0, 0, 0, 0, 0, 0x46}
48 static CStdPSFactoryBuffer PSFactoryBuffer;
50 CSTDSTUBBUFFERRELEASE(&PSFactoryBuffer)
52 extern const ExtendedProxyFileInfo oaidl_ProxyFileInfo;
54 const ProxyFileInfo* OLEAUT32_ProxyFileList[] = {
59 HRESULT OLEAUTPS_DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
61 return NdrDllGetClassObject(rclsid, riid, ppv, OLEAUT32_ProxyFileList,
62 &CLSID_PSDispatch, &PSFactoryBuffer);
65 static void dump_user_flags(unsigned long *pFlags)
67 if (HIWORD(*pFlags) == NDR_LOCAL_DATA_REPRESENTATION)
68 TRACE("MAKELONG(NDR_LOCAL_REPRESENTATION, ");
70 TRACE("MAKELONG(0x%04x, ", HIWORD(*pFlags));
71 switch (LOWORD(*pFlags))
73 case MSHCTX_LOCAL: TRACE("MSHCTX_LOCAL)"); break;
74 case MSHCTX_NOSHAREDMEM: TRACE("MSHCTX_NOSHAREDMEM)"); break;
75 case MSHCTX_DIFFERENTMACHINE: TRACE("MSHCTX_DIFFERENTMACHINE)"); break;
76 case MSHCTX_INPROC: TRACE("MSHCTX_INPROC)"); break;
77 default: TRACE("%d)", LOWORD(*pFlags));
81 /* CLEANLOCALSTORAGE */
82 /* I'm not sure how this is supposed to work yet */
84 unsigned long WINAPI CLEANLOCALSTORAGE_UserSize(unsigned long *pFlags, unsigned long Start, CLEANLOCALSTORAGE *pstg)
86 return Start + sizeof(DWORD);
89 unsigned char * WINAPI CLEANLOCALSTORAGE_UserMarshal(unsigned long *pFlags, unsigned char *Buffer, CLEANLOCALSTORAGE *pstg)
92 return Buffer + sizeof(DWORD);
95 unsigned char * WINAPI CLEANLOCALSTORAGE_UserUnmarshal(unsigned long *pFlags, unsigned char *Buffer, CLEANLOCALSTORAGE *pstr)
97 return Buffer + sizeof(DWORD);
100 void WINAPI CLEANLOCALSTORAGE_UserFree(unsigned long *pFlags, CLEANLOCALSTORAGE *pstr)
106 unsigned long WINAPI BSTR_UserSize(unsigned long *pFlags, unsigned long Start, BSTR *pstr)
108 TRACE("(%lx,%ld,%p) => %p\n", *pFlags, Start, pstr, *pstr);
109 if (*pstr) TRACE("string=%s\n", debugstr_w(*pstr));
110 Start += sizeof(FLAGGED_WORD_BLOB) + sizeof(OLECHAR) * (SysStringLen(*pstr) - 1);
111 TRACE("returning %ld\n", Start);
115 unsigned char * WINAPI BSTR_UserMarshal(unsigned long *pFlags, unsigned char *Buffer, BSTR *pstr)
117 wireBSTR str = (wireBSTR)Buffer;
119 TRACE("(%lx,%p,%p) => %p\n", *pFlags, Buffer, pstr, *pstr);
120 if (*pstr) TRACE("string=%s\n", debugstr_w(*pstr));
122 str->clSize = SysStringLen(*pstr);
124 memcpy(&str->asData, *pstr, sizeof(OLECHAR) * str->clSize);
125 return Buffer + sizeof(FLAGGED_WORD_BLOB) + sizeof(OLECHAR) * (str->clSize - 1);
128 unsigned char * WINAPI BSTR_UserUnmarshal(unsigned long *pFlags, unsigned char *Buffer, BSTR *pstr)
130 wireBSTR str = (wireBSTR)Buffer;
131 TRACE("(%lx,%p,%p) => %p\n", *pFlags, Buffer, pstr, *pstr);
133 SysReAllocStringLen(pstr, (OLECHAR*)&str->asData, str->clSize);
136 SysFreeString(*pstr);
139 if (*pstr) TRACE("string=%s\n", debugstr_w(*pstr));
140 return Buffer + sizeof(FLAGGED_WORD_BLOB) + sizeof(OLECHAR) * (str->clSize - 1);
143 void WINAPI BSTR_UserFree(unsigned long *pFlags, BSTR *pstr)
145 TRACE("(%lx,%p) => %p\n", *pFlags, pstr, *pstr);
147 SysFreeString(*pstr);
153 /* I'm not too sure how to do this yet */
155 #define VARIANT_wiresize sizeof(struct _wireVARIANT)
157 static unsigned wire_size(VARTYPE vt)
159 if (vt & VT_ARRAY) return 0;
161 switch (vt & ~VT_BYREF) {
170 return sizeof(SHORT);
178 return sizeof(FLOAT);
180 return sizeof(DOUBLE);
182 return sizeof(VARIANT_BOOL);
184 return sizeof(SCODE);
190 return sizeof(DECIMAL);
199 FIXME("unhandled VT %d\n", vt);
204 static unsigned interface_variant_size(unsigned long *pFlags, REFIID riid, VARIANT *pvar)
208 /* find the buffer size of the marshalled dispatch interface */
209 hr = CoGetMarshalSizeMax(&size, riid, V_UNKNOWN(pvar), LOWORD(*pFlags), NULL, MSHLFLAGS_NORMAL);
211 if (!V_DISPATCH(pvar))
212 WARN("NULL dispatch pointer\n");
214 ERR("Dispatch variant buffer size calculation failed, HRESULT=0x%lx\n", hr);
217 size += sizeof(ULONG); /* we have to store the buffersize in the stream */
218 TRACE("wire-size extra of dispatch variant is %ld\n", size);
222 static unsigned wire_extra(unsigned long *pFlags, VARIANT *pvar)
224 if (V_ISARRAY(pvar)) {
225 FIXME("wire-size safearray\n");
228 switch (V_VT(pvar)) {
230 return BSTR_UserSize(pFlags, 0, &V_BSTR(pvar));
231 case VT_BSTR | VT_BYREF:
232 return BSTR_UserSize(pFlags, 0, V_BSTRREF(pvar));
234 case VT_SAFEARRAY | VT_BYREF:
235 FIXME("wire-size safearray\n");
237 case VT_VARIANT | VT_BYREF:
238 return VARIANT_UserSize(pFlags, 0, V_VARIANTREF(pvar));
240 return interface_variant_size(pFlags, &IID_IUnknown, pvar);
242 return interface_variant_size(pFlags, &IID_IDispatch, pvar);
244 FIXME("wire-size record\n");
251 /* helper: called for VT_DISPATCH variants to marshal the IDispatch* into the buffer. returns Buffer on failure, new position otherwise */
252 static unsigned char* interface_variant_marshal(unsigned long *pFlags, unsigned char *Buffer, REFIID riid, VARIANT *pvar)
256 void *working_memlocked;
257 unsigned char *oldpos;
261 TRACE("pFlags=%ld, Buffer=%p, pvar=%p\n", *pFlags, Buffer, pvar);
265 /* CoMarshalInterface needs a stream, whereas at this level we are operating in terms of buffers.
266 * We create a stream on an HGLOBAL, so we can simply do a memcpy to move it to the buffer.
267 * in rpcrt4/ndr_ole.c, a simple IStream implementation is wrapped around the buffer object,
268 * but that would be overkill here, hence this implementation. We save the size because the unmarshal
269 * code has no way to know how long the marshalled buffer is. */
271 size = wire_extra(pFlags, pvar);
273 working_mem = GlobalAlloc(0, size);
274 if (!working_mem) return oldpos;
276 hr = CreateStreamOnHGlobal(working_mem, TRUE, &working);
278 GlobalFree(working_mem);
282 hr = CoMarshalInterface(working, riid, V_UNKNOWN(pvar), LOWORD(*pFlags), NULL, MSHLFLAGS_NORMAL);
284 IStream_Release(working); /* this also releases the hglobal */
288 working_memlocked = GlobalLock(working_mem);
289 memcpy(Buffer, &size, sizeof(ULONG)); /* copy the buffersize */
290 Buffer += sizeof(ULONG);
291 memcpy(Buffer, working_memlocked, size);
292 GlobalUnlock(working_mem);
294 IStream_Release(working);
296 TRACE("done, size=%ld\n", sizeof(ULONG) + size);
297 return Buffer + sizeof(ULONG) + size;
300 /* helper: called for VT_DISPATCH / VT_UNKNOWN variants to unmarshal the buffer. returns Buffer on failure, new position otherwise */
301 static unsigned char *interface_variant_unmarshal(unsigned long *pFlags, unsigned char *Buffer, REFIID riid, VARIANT *pvar)
305 void *working_memlocked;
306 unsigned char *oldpos;
310 TRACE("pFlags=%ld, Buffer=%p, pvar=%p\n", *pFlags, Buffer, pvar);
314 /* get the buffersize */
315 memcpy(&size, Buffer, sizeof(ULONG));
316 TRACE("buffersize=%ld\n", size);
317 Buffer += sizeof(ULONG);
319 working_mem = GlobalAlloc(0, size);
320 if (!working_mem) return oldpos;
322 hr = CreateStreamOnHGlobal(working_mem, TRUE, &working);
324 GlobalFree(working_mem);
328 working_memlocked = GlobalLock(working_mem);
330 /* now we copy the contents of the marshalling buffer to working_memlocked, unlock it, and demarshal the stream */
331 memcpy(working_memlocked, Buffer, size);
332 GlobalUnlock(working_mem);
334 hr = CoUnmarshalInterface(working, riid, (void**)&V_UNKNOWN(pvar));
336 IStream_Release(working);
340 IStream_Release(working); /* this also frees the underlying hglobal */
342 TRACE("done, processed=%ld bytes\n", sizeof(ULONG) + size);
343 return Buffer + sizeof(ULONG) + size;
347 unsigned long WINAPI VARIANT_UserSize(unsigned long *pFlags, unsigned long Start, VARIANT *pvar)
349 TRACE("(%lx,%ld,%p)\n", *pFlags, Start, pvar);
350 TRACE("vt=%04x\n", V_VT(pvar));
351 Start += VARIANT_wiresize + wire_extra(pFlags, pvar);
352 TRACE("returning %ld\n", Start);
356 unsigned char * WINAPI VARIANT_UserMarshal(unsigned long *pFlags, unsigned char *Buffer, VARIANT *pvar)
358 wireVARIANT var = (wireVARIANT)Buffer;
359 unsigned size, extra;
360 unsigned char *Pos = Buffer + VARIANT_wiresize;
362 TRACE("(%lx,%p,%p)\n", *pFlags, Buffer, pvar);
363 TRACE("vt=%04x\n", V_VT(pvar));
365 memset(var, 0, sizeof(*var));
366 var->clSize = sizeof(*var);
367 var->vt = pvar->n1.n2.vt;
369 var->rpcReserved = var->vt;
370 if ((var->vt & VT_ARRAY) ||
371 ((var->vt & VT_TYPEMASK) == VT_SAFEARRAY))
372 var->vt = VT_ARRAY | (var->vt & VT_BYREF);
374 if (var->vt == VT_DECIMAL) {
375 /* special case because decVal is on a different level */
376 var->u.decVal = pvar->n1.decVal;
380 size = wire_size(V_VT(pvar));
381 extra = wire_extra(pFlags, pvar);
382 var->wReserved1 = pvar->n1.n2.wReserved1;
383 var->wReserved2 = pvar->n1.n2.wReserved2;
384 var->wReserved3 = pvar->n1.n2.wReserved3;
386 if (var->vt & VT_BYREF)
387 memcpy(&var->u.cVal, pvar->n1.n2.n3.byref, size);
389 memcpy(&var->u.cVal, &pvar->n1.n2.n3, size);
391 if (!extra) return Pos;
395 Pos = BSTR_UserMarshal(pFlags, Pos, &V_BSTR(pvar));
397 case VT_BSTR | VT_BYREF:
398 Pos = BSTR_UserMarshal(pFlags, Pos, V_BSTRREF(pvar));
400 case VT_VARIANT | VT_BYREF:
401 Pos = VARIANT_UserMarshal(pFlags, Pos, V_VARIANTREF(pvar));
403 case VT_DISPATCH | VT_BYREF:
404 FIXME("handle DISPATCH by ref\n");
407 /* this should probably call WdtpInterfacePointer_UserMarshal in ole32.dll */
408 Pos = interface_variant_marshal(pFlags, Pos, &IID_IUnknown, pvar);
411 /* this should probably call WdtpInterfacePointer_UserMarshal in ole32.dll */
412 Pos = interface_variant_marshal(pFlags, Pos, &IID_IDispatch, pvar);
415 FIXME("handle BRECORD by val\n");
417 case VT_RECORD | VT_BYREF:
418 FIXME("handle BRECORD by ref\n");
421 FIXME("handle unknown complex type\n");
424 var->clSize = Pos - Buffer;
425 TRACE("marshalled size=%ld\n", var->clSize);
429 unsigned char * WINAPI VARIANT_UserUnmarshal(unsigned long *pFlags, unsigned char *Buffer, VARIANT *pvar)
431 wireVARIANT var = (wireVARIANT)Buffer;
433 unsigned char *Pos = Buffer + VARIANT_wiresize;
435 TRACE("(%lx,%p,%p)\n", *pFlags, Buffer, pvar);
437 pvar->n1.n2.vt = var->rpcReserved;
438 TRACE("marshalled: clSize=%ld, vt=%04x\n", var->clSize, var->vt);
439 TRACE("vt=%04x\n", V_VT(pvar));
440 TRACE("reserved: %d, %d, %d\n", var->wReserved1, var->wReserved2, var->wReserved3);
441 TRACE("val: %ld\n", var->u.lVal);
443 if (var->vt == VT_DECIMAL) {
444 /* special case because decVal is on a different level */
445 pvar->n1.decVal = var->u.decVal;
449 size = wire_size(V_VT(pvar));
450 pvar->n1.n2.wReserved1 = var->wReserved1;
451 pvar->n1.n2.wReserved2 = var->wReserved2;
452 pvar->n1.n2.wReserved3 = var->wReserved3;
454 if (var->vt & VT_BYREF) {
455 pvar->n1.n2.n3.byref = CoTaskMemAlloc(size);
456 memcpy(pvar->n1.n2.n3.byref, &var->u.cVal, size);
459 memcpy(&pvar->n1.n2.n3, &var->u.cVal, size);
461 if (var->clSize <= VARIANT_wiresize) return Pos;
465 Pos = BSTR_UserUnmarshal(pFlags, Pos, &V_BSTR(pvar));
467 case VT_BSTR | VT_BYREF:
468 pvar->n1.n2.n3.byref = CoTaskMemAlloc(sizeof(BSTR));
469 *(BSTR*)pvar->n1.n2.n3.byref = NULL;
470 Pos = BSTR_UserUnmarshal(pFlags, Pos, V_BSTRREF(pvar));
472 case VT_VARIANT | VT_BYREF:
473 pvar->n1.n2.n3.byref = CoTaskMemAlloc(sizeof(VARIANT));
474 Pos = VARIANT_UserUnmarshal(pFlags, Pos, V_VARIANTREF(pvar));
477 FIXME("handle BRECORD by val\n");
479 case VT_RECORD | VT_BYREF:
480 FIXME("handle BRECORD by ref\n");
483 Pos = interface_variant_unmarshal(pFlags, Pos, &IID_IUnknown, pvar);
486 Pos = interface_variant_unmarshal(pFlags, Pos, &IID_IDispatch, pvar);
488 case VT_DISPATCH | VT_BYREF:
489 FIXME("handle DISPATCH by ref\n");
491 FIXME("handle unknown complex type\n");
494 if (Pos != Buffer + var->clSize) {
495 ERR("size difference during unmarshal\n");
497 return Buffer + var->clSize;
500 void WINAPI VARIANT_UserFree(unsigned long *pFlags, VARIANT *pvar)
502 VARTYPE vt = V_VT(pvar);
505 TRACE("(%lx,%p)\n", *pFlags, pvar);
506 TRACE("vt=%04x\n", V_VT(pvar));
508 if (vt & VT_BYREF) ref = pvar->n1.n2.n3.byref;
514 case VT_BSTR | VT_BYREF:
515 BSTR_UserFree(pFlags, ref);
517 case VT_VARIANT | VT_BYREF:
518 VARIANT_UserFree(pFlags, ref);
520 case VT_RECORD | VT_BYREF:
521 FIXME("handle BRECORD by ref\n");
525 IUnknown_Release(V_UNKNOWN(pvar));
528 FIXME("handle unknown complex type\n");
537 /* Get the number of cells in a SafeArray */
538 static ULONG SAFEARRAY_GetCellCount(const SAFEARRAY *psa)
540 const SAFEARRAYBOUND* psab = psa->rgsabound;
541 USHORT cCount = psa->cDims;
542 ULONG ulNumCells = 1;
546 /* This is a valid bordercase. See testcases. -Marcus */
547 if (!psab->cElements)
549 ulNumCells *= psab->cElements;
555 static inline SF_TYPE SAFEARRAY_GetUnionType(SAFEARRAY *psa)
560 hr = SafeArrayGetVartype(psa, &vt);
562 RpcRaiseException(hr);
564 if (psa->fFeatures & FADF_HAVEIID)
570 case VT_UI1: return SF_I1;
573 case VT_UI2: return SF_I2;
578 case VT_R4: return SF_I4;
583 case VT_UI8: return SF_I8;
585 case VT_UINT_PTR: return (sizeof(UINT_PTR) == 4 ? SF_I4 : SF_I8);
586 case VT_BSTR: return SF_BSTR;
587 case VT_DISPATCH: return SF_DISPATCH;
588 case VT_VARIANT: return SF_VARIANT;
589 case VT_UNKNOWN: return SF_UNKNOWN;
590 /* Note: Return a non-zero size to indicate vt is valid. The actual size
591 * of a UDT is taken from the result of IRecordInfo_GetSize().
593 case VT_RECORD: return SF_RECORD;
594 default: return SF_ERROR;
598 unsigned long WINAPI LPSAFEARRAY_UserSize(unsigned long *pFlags, unsigned long StartingSize, LPSAFEARRAY *ppsa)
600 unsigned long size = StartingSize;
602 TRACE("("); dump_user_flags(pFlags); TRACE(", %ld, %p\n", StartingSize, *ppsa);
604 size += sizeof(ULONG_PTR);
607 SAFEARRAY *psa = *ppsa;
608 ULONG ulCellCount = SAFEARRAY_GetCellCount(psa);
612 size += sizeof(ULONG);
613 size += FIELD_OFFSET(struct _wireSAFEARRAY, uArrayStructs);
615 sftype = SAFEARRAY_GetUnionType(psa);
616 size += sizeof(ULONG);
618 size += sizeof(ULONG);
619 size += sizeof(ULONG_PTR);
620 if (sftype == SF_HAVEIID)
623 size += sizeof(psa->rgsabound[0]) * psa->cDims;
625 size += sizeof(ULONG);
633 for (lpBstr = (BSTR*)psa->pvData; ulCellCount; ulCellCount--, lpBstr++)
634 size = BSTR_UserSize(pFlags, size, lpBstr);
641 FIXME("size interfaces\n");
647 for (lpVariant = (VARIANT*)psa->pvData; ulCellCount; ulCellCount--, lpVariant++)
648 size = VARIANT_UserSize(pFlags, size, lpVariant);
654 IRecordInfo* pRecInfo = NULL;
656 hr = SafeArrayGetRecordInfo(psa, &pRecInfo);
658 RpcRaiseException(hr);
662 FIXME("size record info %p\n", pRecInfo);
664 IRecordInfo_Release(pRecInfo);
672 size += ulCellCount * psa->cbElements;
683 unsigned char * WINAPI LPSAFEARRAY_UserMarshal(unsigned long *pFlags, unsigned char *Buffer, LPSAFEARRAY *ppsa)
687 TRACE("("); dump_user_flags(pFlags); TRACE(", %p, &%p\n", Buffer, *ppsa);
689 *(ULONG_PTR *)Buffer = *ppsa ? TRUE : FALSE;
690 Buffer += sizeof(ULONG_PTR);
694 SAFEARRAY *psa = *ppsa;
695 ULONG ulCellCount = SAFEARRAY_GetCellCount(psa);
696 wireSAFEARRAY wiresa;
700 *(ULONG *)Buffer = psa->cDims;
701 Buffer += sizeof(ULONG);
702 wiresa = (wireSAFEARRAY)Buffer;
703 wiresa->cDims = psa->cDims;
704 wiresa->fFeatures = psa->fFeatures;
705 wiresa->cbElements = psa->cbElements;
707 hr = SafeArrayGetVartype(psa, &vt);
709 RpcRaiseException(hr);
710 wiresa->cLocks = (USHORT)psa->cLocks | (vt << 16);
712 Buffer += FIELD_OFFSET(struct _wireSAFEARRAY, uArrayStructs);
714 sftype = SAFEARRAY_GetUnionType(psa);
715 *(ULONG *)Buffer = sftype;
716 Buffer += sizeof(ULONG);
718 *(ULONG *)Buffer = ulCellCount;
719 Buffer += sizeof(ULONG);
720 *(ULONG_PTR *)Buffer = (ULONG_PTR)psa->pvData;
721 Buffer += sizeof(ULONG_PTR);
722 if (sftype == SF_HAVEIID)
724 SafeArrayGetIID(psa, &guid);
725 memcpy(Buffer, &guid, sizeof(guid));
726 Buffer += sizeof(guid);
729 memcpy(Buffer, psa->rgsabound, sizeof(psa->rgsabound[0]) * psa->cDims);
730 Buffer += sizeof(psa->rgsabound[0]) * psa->cDims;
732 *(ULONG *)Buffer = ulCellCount;
733 Buffer += sizeof(ULONG);
743 for (lpBstr = (BSTR*)psa->pvData; ulCellCount; ulCellCount--, lpBstr++)
744 Buffer = BSTR_UserMarshal(pFlags, Buffer, lpBstr);
751 FIXME("marshal interfaces\n");
757 for (lpVariant = (VARIANT*)psa->pvData; ulCellCount; ulCellCount--, lpVariant++)
758 Buffer = VARIANT_UserMarshal(pFlags, Buffer, lpVariant);
764 IRecordInfo* pRecInfo = NULL;
766 hr = SafeArrayGetRecordInfo(psa, &pRecInfo);
768 RpcRaiseException(hr);
772 FIXME("write record info %p\n", pRecInfo);
774 IRecordInfo_Release(pRecInfo);
782 /* Just copy the data over */
783 memcpy(Buffer, psa->pvData, ulCellCount * psa->cbElements);
784 Buffer += ulCellCount * psa->cbElements;
795 #define FADF_AUTOSETFLAGS (FADF_HAVEIID | FADF_RECORD | FADF_HAVEVARTYPE | \
796 FADF_BSTR | FADF_UNKNOWN | FADF_DISPATCH | \
797 FADF_VARIANT | FADF_CREATEVECTOR)
799 unsigned char * WINAPI LPSAFEARRAY_UserUnmarshal(unsigned long *pFlags, unsigned char *Buffer, LPSAFEARRAY *ppsa)
802 wireSAFEARRAY wiresa;
809 SAFEARRAYBOUND *wiresab;
811 TRACE("("); dump_user_flags(pFlags); TRACE(", %p, %p\n", Buffer, ppsa);
813 ptr = *(ULONG_PTR *)Buffer;
814 Buffer += sizeof(ULONG_PTR);
820 TRACE("NULL safe array unmarshaled\n");
825 cDims = *(ULONG *)Buffer;
826 Buffer += sizeof(ULONG);
828 wiresa = (wireSAFEARRAY)Buffer;
829 Buffer += FIELD_OFFSET(struct _wireSAFEARRAY, uArrayStructs);
831 if (cDims != wiresa->cDims)
832 RpcRaiseException(RPC_S_INVALID_BOUND);
834 /* FIXME: there should be a limit on how large cDims can be */
836 vt = HIWORD(wiresa->cLocks);
838 sftype = *(ULONG *)Buffer;
839 Buffer += sizeof(ULONG);
841 cell_count = *(ULONG *)Buffer;
842 Buffer += sizeof(ULONG);
843 ptr = *(ULONG_PTR *)Buffer;
844 Buffer += sizeof(ULONG_PTR);
845 if (sftype == SF_HAVEIID)
847 memcpy(&guid, Buffer, sizeof(guid));
848 Buffer += sizeof(guid);
851 wiresab = (SAFEARRAYBOUND *)Buffer;
852 Buffer += sizeof(wiresab[0]) * wiresa->cDims;
854 *ppsa = SafeArrayCreateEx(vt, wiresa->cDims, wiresab, NULL);
856 RpcRaiseException(E_OUTOFMEMORY);
858 /* be careful about which flags we set since they could be a security
860 (*ppsa)->fFeatures = wiresa->fFeatures & ~(FADF_AUTOSETFLAGS);
861 /* FIXME: there should be a limit on how large wiresa->cbElements can be */
862 (*ppsa)->cbElements = wiresa->cbElements;
863 (*ppsa)->cLocks = LOWORD(wiresa->cLocks);
865 hr = SafeArrayAllocData(*ppsa);
867 RpcRaiseException(hr);
869 if ((*(ULONG *)Buffer != cell_count) || (SAFEARRAY_GetCellCount(*ppsa) != cell_count))
870 RpcRaiseException(RPC_S_INVALID_BOUND);
871 Buffer += sizeof(ULONG);
881 for (lpBstr = (BSTR*)(*ppsa)->pvData; cell_count; cell_count--, lpBstr++)
882 Buffer = BSTR_UserUnmarshal(pFlags, Buffer, lpBstr);
889 FIXME("marshal interfaces\n");
895 for (lpVariant = (VARIANT*)(*ppsa)->pvData; cell_count; cell_count--, lpVariant++)
896 Buffer = VARIANT_UserUnmarshal(pFlags, Buffer, lpVariant);
902 FIXME("set record info\n");
910 /* Just copy the data over */
911 memcpy((*ppsa)->pvData, Buffer, cell_count * (*ppsa)->cbElements);
912 Buffer += cell_count * (*ppsa)->cbElements;
919 TRACE("safe array unmarshaled: %p\n", *ppsa);
924 void WINAPI LPSAFEARRAY_UserFree(unsigned long *pFlags, LPSAFEARRAY *ppsa)
926 TRACE("("); dump_user_flags(pFlags); TRACE(", &%p\n", *ppsa);
928 SafeArrayDestroy(*ppsa);
932 /* exactly how Invoke is marshalled is not very clear to me yet,
933 * but the way I've done it seems to work for me */
935 HRESULT CALLBACK IDispatch_Invoke_Proxy(
941 DISPPARAMS* pDispParams,
943 EXCEPINFO* pExcepInfo,
948 UINT* rgVarRefIdx = NULL;
949 VARIANTARG* rgVarRef = NULL;
954 TRACE("(%p)->(%ld,%s,%lx,%x,%p,%p,%p,%p)\n", This,
955 dispIdMember, debugstr_guid(riid),
956 lcid, wFlags, pDispParams, pVarResult,
957 pExcepInfo, puArgErr);
959 /* [out] args can't be null, use dummy vars if needed */
960 if (!pVarResult) pVarResult = &VarResult;
961 if (!puArgErr) puArgErr = &uArgErr;
962 if (!pExcepInfo) pExcepInfo = &ExcepInfo;
964 /* count by-ref args */
965 for (cVarRef=0,u=0; u<pDispParams->cArgs; u++) {
966 VARIANTARG* arg = &pDispParams->rgvarg[u];
967 if (V_ISBYREF(arg)) {
972 rgVarRefIdx = CoTaskMemAlloc(sizeof(UINT)*cVarRef);
973 rgVarRef = CoTaskMemAlloc(sizeof(VARIANTARG)*cVarRef);
974 /* make list of by-ref args */
975 for (cVarRef=0,u=0; u<pDispParams->cArgs; u++) {
976 VARIANTARG* arg = &pDispParams->rgvarg[u];
977 if (V_ISBYREF(arg)) {
978 rgVarRefIdx[cVarRef] = u;
979 VariantInit(&rgVarRef[cVarRef]);
984 /* [out] args still can't be null,
985 * but we can point these anywhere in this case,
986 * since they won't be written to when cVarRef is 0 */
987 rgVarRefIdx = puArgErr;
988 rgVarRef = pVarResult;
990 TRACE("passed by ref: %d args\n", cVarRef);
991 hr = IDispatch_RemoteInvoke_Proxy(This,
1004 for (u=0; u<cVarRef; u++) {
1005 unsigned i = rgVarRefIdx[u];
1006 VariantCopy(&pDispParams->rgvarg[i],
1008 VariantClear(&rgVarRef[u]);
1010 CoTaskMemFree(rgVarRef);
1011 CoTaskMemFree(rgVarRefIdx);
1014 if(pExcepInfo == &ExcepInfo)
1016 SysFreeString(pExcepInfo->bstrSource);
1017 SysFreeString(pExcepInfo->bstrDescription);
1018 SysFreeString(pExcepInfo->bstrHelpFile);
1023 HRESULT __RPC_STUB IDispatch_Invoke_Stub(
1025 DISPID dispIdMember,
1029 DISPPARAMS* pDispParams,
1030 VARIANT* pVarResult,
1031 EXCEPINFO* pExcepInfo,
1035 VARIANTARG* rgVarRef)
1038 VARIANTARG *rgvarg, *arg;
1041 /* initialize out parameters, so that they can be marshalled
1042 * in case the real Invoke doesn't initialize them */
1043 VariantInit(pVarResult);
1044 memset(pExcepInfo, 0, sizeof(*pExcepInfo));
1047 /* let the real Invoke operate on a copy of the in parameters,
1048 * so we don't risk losing pointers to allocated memory */
1049 rgvarg = pDispParams->rgvarg;
1050 arg = CoTaskMemAlloc(sizeof(VARIANTARG)*pDispParams->cArgs);
1051 if (!arg) return E_OUTOFMEMORY;
1053 /* init all args so we can call VariantClear on all the args if the copy
1055 for (u = 0; u < pDispParams->cArgs; u++)
1056 VariantInit(&arg[u]);
1058 for (u = 0; u < pDispParams->cArgs; u++) {
1059 hr = VariantCopy(&arg[u], &rgvarg[u]);
1064 if (SUCCEEDED(hr)) {
1065 pDispParams->rgvarg = arg;
1067 hr = IDispatch_Invoke(This,
1077 /* copy ref args to out list */
1078 for (u=0; u<cVarRef; u++) {
1079 unsigned i = rgVarRefIdx[u];
1080 VariantInit(&rgVarRef[u]);
1081 VariantCopy(&rgVarRef[u], &arg[i]);
1082 /* clear original if equal, to avoid double-free */
1083 if (V_BYREF(&rgVarRef[u]) == V_BYREF(&rgvarg[i]))
1084 VariantClear(&rgvarg[i]);
1088 /* clear the duplicate argument list */
1089 for (u=0; u<pDispParams->cArgs; u++)
1090 VariantClear(&arg[u]);
1092 pDispParams->rgvarg = rgvarg;
1100 HRESULT CALLBACK IEnumVARIANT_Next_Proxy(
1104 ULONG* pCeltFetched)
1108 pCeltFetched = &fetched;
1109 return IEnumVARIANT_RemoteNext_Proxy(This,
1115 HRESULT __RPC_STUB IEnumVARIANT_Next_Stub(
1119 ULONG* pCeltFetched)
1123 hr = IEnumVARIANT_Next(This,
1127 if (hr == S_OK) *pCeltFetched = celt;
1133 HRESULT CALLBACK ITypeComp_Bind_Proxy(
1138 ITypeInfo** ppTInfo,
1139 DESCKIND* pDescKind,
1142 FIXME("not implemented\n");
1146 HRESULT __RPC_STUB ITypeComp_Bind_Stub(
1151 ITypeInfo** ppTInfo,
1152 DESCKIND* pDescKind,
1153 LPFUNCDESC* ppFuncDesc,
1154 LPVARDESC* ppVarDesc,
1155 ITypeComp** ppTypeComp,
1156 CLEANLOCALSTORAGE* pDummy)
1158 FIXME("not implemented\n");
1162 HRESULT CALLBACK ITypeComp_BindType_Proxy(
1166 ITypeInfo** ppTInfo,
1167 ITypeComp** ppTComp)
1169 FIXME("not implemented\n");
1173 HRESULT __RPC_STUB ITypeComp_BindType_Stub(
1177 ITypeInfo** ppTInfo)
1179 FIXME("not implemented\n");
1185 HRESULT CALLBACK ITypeInfo_GetTypeAttr_Proxy(
1187 TYPEATTR** ppTypeAttr)
1189 FIXME("not implemented\n");
1193 HRESULT __RPC_STUB ITypeInfo_GetTypeAttr_Stub(
1195 LPTYPEATTR* ppTypeAttr,
1196 CLEANLOCALSTORAGE* pDummy)
1198 FIXME("not implemented\n");
1202 HRESULT CALLBACK ITypeInfo_GetFuncDesc_Proxy(
1205 FUNCDESC** ppFuncDesc)
1207 FIXME("not implemented\n");
1211 HRESULT __RPC_STUB ITypeInfo_GetFuncDesc_Stub(
1214 LPFUNCDESC* ppFuncDesc,
1215 CLEANLOCALSTORAGE* pDummy)
1217 FIXME("not implemented\n");
1221 HRESULT CALLBACK ITypeInfo_GetVarDesc_Proxy(
1224 VARDESC** ppVarDesc)
1226 FIXME("not implemented\n");
1230 HRESULT __RPC_STUB ITypeInfo_GetVarDesc_Stub(
1233 LPVARDESC* ppVarDesc,
1234 CLEANLOCALSTORAGE* pDummy)
1236 FIXME("not implemented\n");
1240 HRESULT CALLBACK ITypeInfo_GetNames_Proxy(
1247 FIXME("not implemented\n");
1251 HRESULT __RPC_STUB ITypeInfo_GetNames_Stub(
1258 FIXME("not implemented\n");
1262 HRESULT CALLBACK ITypeInfo_GetIDsOfNames_Proxy(
1264 LPOLESTR* rgszNames,
1268 FIXME("not implemented\n");
1272 HRESULT __RPC_STUB ITypeInfo_GetIDsOfNames_Stub(
1275 FIXME("not implemented\n");
1279 HRESULT CALLBACK ITypeInfo_Invoke_Proxy(
1284 DISPPARAMS* pDispParams,
1285 VARIANT* pVarResult,
1286 EXCEPINFO* pExcepInfo,
1289 FIXME("not implemented\n");
1293 HRESULT __RPC_STUB ITypeInfo_Invoke_Stub(
1296 FIXME("not implemented\n");
1300 HRESULT CALLBACK ITypeInfo_GetDocumentation_Proxy(
1304 BSTR* pBstrDocString,
1305 DWORD* pdwHelpContext,
1306 BSTR* pBstrHelpFile)
1308 FIXME("not implemented\n");
1312 HRESULT __RPC_STUB ITypeInfo_GetDocumentation_Stub(
1317 BSTR* pBstrDocString,
1318 DWORD* pdwHelpContext,
1319 BSTR* pBstrHelpFile)
1321 FIXME("not implemented\n");
1325 HRESULT CALLBACK ITypeInfo_GetDllEntry_Proxy(
1333 FIXME("not implemented\n");
1337 HRESULT __RPC_STUB ITypeInfo_GetDllEntry_Stub(
1346 FIXME("not implemented\n");
1350 HRESULT CALLBACK ITypeInfo_AddressOfMember_Proxy(
1356 FIXME("not implemented\n");
1360 HRESULT __RPC_STUB ITypeInfo_AddressOfMember_Stub(
1363 FIXME("not implemented\n");
1367 HRESULT CALLBACK ITypeInfo_CreateInstance_Proxy(
1369 IUnknown* pUnkOuter,
1373 FIXME("not implemented\n");
1377 HRESULT __RPC_STUB ITypeInfo_CreateInstance_Stub(
1382 FIXME("not implemented\n");
1386 HRESULT CALLBACK ITypeInfo_GetContainingTypeLib_Proxy(
1395 TRACE("(%p, %p, %p)\n", This, ppTLib, pIndex );
1397 hr = ITypeInfo_RemoteGetContainingTypeLib_Proxy(This, &pTL, &index);
1406 ITypeLib_Release(pTL);
1411 HRESULT __RPC_STUB ITypeInfo_GetContainingTypeLib_Stub(
1416 TRACE("(%p, %p, %p)\n", This, ppTLib, pIndex );
1417 return ITypeInfo_GetContainingTypeLib(This, ppTLib, pIndex);
1420 void CALLBACK ITypeInfo_ReleaseTypeAttr_Proxy(
1422 TYPEATTR* pTypeAttr)
1424 FIXME("not implemented\n");
1427 HRESULT __RPC_STUB ITypeInfo_ReleaseTypeAttr_Stub(
1430 FIXME("not implemented\n");
1434 void CALLBACK ITypeInfo_ReleaseFuncDesc_Proxy(
1436 FUNCDESC* pFuncDesc)
1438 FIXME("not implemented\n");
1441 HRESULT __RPC_STUB ITypeInfo_ReleaseFuncDesc_Stub(
1444 FIXME("not implemented\n");
1448 void CALLBACK ITypeInfo_ReleaseVarDesc_Proxy(
1452 FIXME("not implemented\n");
1455 HRESULT __RPC_STUB ITypeInfo_ReleaseVarDesc_Stub(
1458 FIXME("not implemented\n");
1465 HRESULT CALLBACK ITypeInfo2_GetDocumentation2_Proxy(
1469 BSTR* pbstrHelpString,
1470 DWORD* pdwHelpStringContext,
1471 BSTR* pbstrHelpStringDll)
1473 FIXME("not implemented\n");
1477 HRESULT __RPC_STUB ITypeInfo2_GetDocumentation2_Stub(
1482 BSTR* pbstrHelpString,
1483 DWORD* pdwHelpStringContext,
1484 BSTR* pbstrHelpStringDll)
1486 FIXME("not implemented\n");
1492 UINT CALLBACK ITypeLib_GetTypeInfoCount_Proxy(
1496 TRACE("(%p)\n", This);
1498 ITypeLib_RemoteGetTypeInfoCount_Proxy(This, &count);
1503 HRESULT __RPC_STUB ITypeLib_GetTypeInfoCount_Stub(
1507 TRACE("(%p, %p)\n", This, pcTInfo);
1508 *pcTInfo = ITypeLib_GetTypeInfoCount(This);
1512 HRESULT CALLBACK ITypeLib_GetLibAttr_Proxy(
1514 TLIBATTR** ppTLibAttr)
1516 CLEANLOCALSTORAGE stg;
1517 TRACE("(%p, %p)\n", This, ppTLibAttr);
1518 return ITypeLib_RemoteGetLibAttr_Proxy(This, ppTLibAttr, &stg);
1521 HRESULT __RPC_STUB ITypeLib_GetLibAttr_Stub(
1523 LPTLIBATTR* ppTLibAttr,
1524 CLEANLOCALSTORAGE* pDummy)
1526 TRACE("(%p, %p)\n", This, ppTLibAttr);
1527 return ITypeLib_GetLibAttr(This, ppTLibAttr);
1530 HRESULT CALLBACK ITypeLib_GetDocumentation_Proxy(
1534 BSTR* pBstrDocString,
1535 DWORD* pdwHelpContext,
1536 BSTR* pBstrHelpFile)
1538 FIXME("not implemented\n");
1542 HRESULT __RPC_STUB ITypeLib_GetDocumentation_Stub(
1547 BSTR* pBstrDocString,
1548 DWORD* pdwHelpContext,
1549 BSTR* pBstrHelpFile)
1551 FIXME("not implemented\n");
1555 HRESULT CALLBACK ITypeLib_IsName_Proxy(
1561 FIXME("not implemented\n");
1565 HRESULT __RPC_STUB ITypeLib_IsName_Stub(
1572 FIXME("not implemented\n");
1576 HRESULT CALLBACK ITypeLib_FindName_Proxy(
1580 ITypeInfo** ppTInfo,
1584 FIXME("not implemented\n");
1588 HRESULT __RPC_STUB ITypeLib_FindName_Stub(
1592 ITypeInfo** ppTInfo,
1597 FIXME("not implemented\n");
1601 void CALLBACK ITypeLib_ReleaseTLibAttr_Proxy(
1603 TLIBATTR* pTLibAttr)
1605 TRACE("(%p, %p)\n", This, pTLibAttr);
1606 CoTaskMemFree(pTLibAttr);
1609 HRESULT __RPC_STUB ITypeLib_ReleaseTLibAttr_Stub(
1612 TRACE("nothing to do\n");
1619 HRESULT CALLBACK ITypeLib2_GetLibStatistics_Proxy(
1621 ULONG* pcUniqueNames,
1622 ULONG* pcchUniqueNames)
1624 FIXME("not implemented\n");
1628 HRESULT __RPC_STUB ITypeLib2_GetLibStatistics_Stub(
1630 ULONG* pcUniqueNames,
1631 ULONG* pcchUniqueNames)
1633 FIXME("not implemented\n");
1637 HRESULT CALLBACK ITypeLib2_GetDocumentation2_Proxy(
1641 BSTR* pbstrHelpString,
1642 DWORD* pdwHelpStringContext,
1643 BSTR* pbstrHelpStringDll)
1645 FIXME("not implemented\n");
1649 HRESULT __RPC_STUB ITypeLib2_GetDocumentation2_Stub(
1654 BSTR* pbstrHelpString,
1655 DWORD* pdwHelpStringContext,
1656 BSTR* pbstrHelpStringDll)
1658 FIXME("not implemented\n");