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");