2 * Misc marshalling routines
4 * Copyright 2002 Ove Kaaven
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #define NONAMELESSUNION
25 #define NONAMELESSSTRUCT
35 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(ole);
39 /* FIXME: not supposed to be here */
41 const CLSID CLSID_PSDispatch = {
42 0x20420, 0, 0, {0xC0, 0, 0, 0, 0, 0, 0, 0x46}
45 static CStdPSFactoryBuffer PSFactoryBuffer;
47 CSTDSTUBBUFFERRELEASE(&PSFactoryBuffer)
49 extern const ExtendedProxyFileInfo oaidl_ProxyFileInfo;
51 const ProxyFileInfo* OLEAUT32_ProxyFileList[] = {
56 HRESULT OLEAUTPS_DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
58 return NdrDllGetClassObject(rclsid, riid, ppv, OLEAUT32_ProxyFileList,
59 &CLSID_PSDispatch, &PSFactoryBuffer);
62 /* CLEANLOCALSTORAGE */
63 /* I'm not sure how this is supposed to work yet */
65 unsigned long WINAPI CLEANLOCALSTORAGE_UserSize(unsigned long *pFlags, unsigned long Start, CLEANLOCALSTORAGE *pstg)
67 return Start + sizeof(DWORD);
70 unsigned char * WINAPI CLEANLOCALSTORAGE_UserMarshal(unsigned long *pFlags, unsigned char *Buffer, CLEANLOCALSTORAGE *pstg)
73 return Buffer + sizeof(DWORD);
76 unsigned char * WINAPI CLEANLOCALSTORAGE_UserUnmarshal(unsigned long *pFlags, unsigned char *Buffer, CLEANLOCALSTORAGE *pstr)
78 return Buffer + sizeof(DWORD);
81 void WINAPI CLEANLOCALSTORAGE_UserFree(unsigned long *pFlags, CLEANLOCALSTORAGE *pstr)
87 unsigned long WINAPI BSTR_UserSize(unsigned long *pFlags, unsigned long Start, BSTR *pstr)
89 TRACE("(%lx,%ld,%p) => %p\n", *pFlags, Start, pstr, *pstr);
90 if (*pstr) TRACE("string=%s\n", debugstr_w(*pstr));
91 Start += sizeof(FLAGGED_WORD_BLOB) + sizeof(OLECHAR) * (SysStringLen(*pstr) - 1);
92 TRACE("returning %ld\n", Start);
96 unsigned char * WINAPI BSTR_UserMarshal(unsigned long *pFlags, unsigned char *Buffer, BSTR *pstr)
98 wireBSTR str = (wireBSTR)Buffer;
100 TRACE("(%lx,%p,%p) => %p\n", *pFlags, Buffer, pstr, *pstr);
101 if (*pstr) TRACE("string=%s\n", debugstr_w(*pstr));
103 str->clSize = SysStringLen(*pstr);
105 memcpy(&str->asData, *pstr, sizeof(OLECHAR) * str->clSize);
106 return Buffer + sizeof(FLAGGED_WORD_BLOB) + sizeof(OLECHAR) * (str->clSize - 1);
109 unsigned char * WINAPI BSTR_UserUnmarshal(unsigned long *pFlags, unsigned char *Buffer, BSTR *pstr)
111 wireBSTR str = (wireBSTR)Buffer;
112 TRACE("(%lx,%p,%p) => %p\n", *pFlags, Buffer, pstr, *pstr);
114 SysReAllocStringLen(pstr, (OLECHAR*)&str->asData, str->clSize);
117 SysFreeString(*pstr);
120 if (*pstr) TRACE("string=%s\n", debugstr_w(*pstr));
121 return Buffer + sizeof(FLAGGED_WORD_BLOB) + sizeof(OLECHAR) * (str->clSize - 1);
124 void WINAPI BSTR_UserFree(unsigned long *pFlags, BSTR *pstr)
126 TRACE("(%lx,%p) => %p\n", *pFlags, pstr, *pstr);
128 SysFreeString(*pstr);
134 /* I'm not too sure how to do this yet */
136 #define VARIANT_wiresize sizeof(struct _wireVARIANT)
138 static unsigned wire_size(VARTYPE vt)
140 if (vt & VT_ARRAY) return 0;
142 switch (vt & ~VT_BYREF) {
151 return sizeof(SHORT);
159 return sizeof(FLOAT);
161 return sizeof(DOUBLE);
163 return sizeof(VARIANT_BOOL);
165 return sizeof(SCODE);
171 return sizeof(DECIMAL);
180 FIXME("unhandled VT %d\n", vt);
185 static unsigned wire_extra(unsigned long *pFlags, VARIANT *pvar)
187 if (V_VT(pvar) & VT_ARRAY) {
188 FIXME("wire-size safearray\n");
191 switch (V_VT(pvar)) {
193 return BSTR_UserSize(pFlags, 0, &V_BSTR(pvar));
194 case VT_BSTR | VT_BYREF:
195 return BSTR_UserSize(pFlags, 0, V_BSTRREF(pvar));
197 case VT_SAFEARRAY | VT_BYREF:
198 FIXME("wire-size safearray\n");
200 case VT_VARIANT | VT_BYREF:
201 return VARIANT_UserSize(pFlags, 0, V_VARIANTREF(pvar));
204 FIXME("wire-size interfaces\n");
207 FIXME("wire-size record\n");
214 unsigned long WINAPI VARIANT_UserSize(unsigned long *pFlags, unsigned long Start, VARIANT *pvar)
216 TRACE("(%lx,%ld,%p)\n", *pFlags, Start, pvar);
217 TRACE("vt=%04x\n", V_VT(pvar));
218 Start += VARIANT_wiresize + wire_extra(pFlags, pvar);
219 TRACE("returning %ld\n", Start);
223 unsigned char * WINAPI VARIANT_UserMarshal(unsigned long *pFlags, unsigned char *Buffer, VARIANT *pvar)
225 wireVARIANT var = (wireVARIANT)Buffer;
226 unsigned size, extra;
227 unsigned char *Pos = Buffer + VARIANT_wiresize;
229 TRACE("(%lx,%p,%p)\n", *pFlags, Buffer, pvar);
230 TRACE("vt=%04x\n", V_VT(pvar));
232 memset(var, 0, sizeof(*var));
233 var->clSize = sizeof(*var);
234 var->vt = pvar->n1.n2.vt;
236 var->rpcReserved = var->vt;
237 if ((var->vt & VT_ARRAY) ||
238 ((var->vt & VT_TYPEMASK) == VT_SAFEARRAY))
239 var->vt = VT_ARRAY | (var->vt & VT_BYREF);
241 if (var->vt == VT_DECIMAL) {
242 /* special case because decVal is on a different level */
243 var->u.decVal = pvar->n1.decVal;
247 size = wire_size(V_VT(pvar));
248 extra = wire_extra(pFlags, pvar);
249 var->wReserved1 = pvar->n1.n2.wReserved1;
250 var->wReserved2 = pvar->n1.n2.wReserved2;
251 var->wReserved3 = pvar->n1.n2.wReserved3;
253 if (var->vt & VT_BYREF)
254 memcpy(&var->u.cVal, pvar->n1.n2.n3.byref, size);
256 memcpy(&var->u.cVal, &pvar->n1.n2.n3, size);
258 if (!extra) return Pos;
262 Pos = BSTR_UserMarshal(pFlags, Pos, &V_BSTR(pvar));
264 case VT_BSTR | VT_BYREF:
265 Pos = BSTR_UserMarshal(pFlags, Pos, V_BSTRREF(pvar));
267 case VT_VARIANT | VT_BYREF:
268 Pos = VARIANT_UserMarshal(pFlags, Pos, V_VARIANTREF(pvar));
271 FIXME("handle BRECORD by val\n");
273 case VT_RECORD | VT_BYREF:
274 FIXME("handle BRECORD by ref\n");
277 FIXME("handle unknown complex type\n");
280 var->clSize = Pos - Buffer;
281 TRACE("marshalled size=%ld\n", var->clSize);
285 unsigned char * WINAPI VARIANT_UserUnmarshal(unsigned long *pFlags, unsigned char *Buffer, VARIANT *pvar)
287 wireVARIANT var = (wireVARIANT)Buffer;
289 unsigned char *Pos = Buffer + VARIANT_wiresize;
291 TRACE("(%lx,%p,%p)\n", *pFlags, Buffer, pvar);
293 pvar->n1.n2.vt = var->rpcReserved;
294 TRACE("marshalled: clSize=%ld, vt=%04x\n", var->clSize, var->vt);
295 TRACE("vt=%04x\n", V_VT(pvar));
296 TRACE("reserved: %d, %d, %d\n", var->wReserved1, var->wReserved2, var->wReserved3);
297 TRACE("val: %ld\n", var->u.lVal);
299 if (var->vt == VT_DECIMAL) {
300 /* special case because decVal is on a different level */
301 pvar->n1.decVal = var->u.decVal;
305 size = wire_size(V_VT(pvar));
306 pvar->n1.n2.wReserved1 = var->wReserved1;
307 pvar->n1.n2.wReserved2 = var->wReserved2;
308 pvar->n1.n2.wReserved3 = var->wReserved3;
310 if (var->vt & VT_BYREF) {
311 pvar->n1.n2.n3.byref = CoTaskMemAlloc(size);
312 memcpy(pvar->n1.n2.n3.byref, &var->u.cVal, size);
315 memcpy(&pvar->n1.n2.n3, &var->u.cVal, size);
317 if (var->clSize <= VARIANT_wiresize) return Pos;
321 Pos = BSTR_UserUnmarshal(pFlags, Pos, &V_BSTR(pvar));
323 case VT_BSTR | VT_BYREF:
324 pvar->n1.n2.n3.byref = CoTaskMemAlloc(sizeof(BSTR));
325 *(BSTR*)pvar->n1.n2.n3.byref = NULL;
326 Pos = BSTR_UserUnmarshal(pFlags, Pos, V_BSTRREF(pvar));
328 case VT_VARIANT | VT_BYREF:
329 pvar->n1.n2.n3.byref = CoTaskMemAlloc(sizeof(VARIANT));
330 Pos = VARIANT_UserUnmarshal(pFlags, Pos, V_VARIANTREF(pvar));
333 FIXME("handle BRECORD by val\n");
335 case VT_RECORD | VT_BYREF:
336 FIXME("handle BRECORD by ref\n");
339 FIXME("handle unknown complex type\n");
342 if (Pos != Buffer + var->clSize) {
343 ERR("size difference during unmarshal\n");
345 return Buffer + var->clSize;
348 void WINAPI VARIANT_UserFree(unsigned long *pFlags, VARIANT *pvar)
350 VARTYPE vt = V_VT(pvar);
353 TRACE("(%lx,%p)\n", *pFlags, pvar);
354 TRACE("vt=%04x\n", V_VT(pvar));
356 if (vt & VT_BYREF) ref = pvar->n1.n2.n3.byref;
362 case VT_BSTR | VT_BYREF:
363 BSTR_UserFree(pFlags, ref);
365 case VT_VARIANT | VT_BYREF:
366 VARIANT_UserFree(pFlags, ref);
368 case VT_RECORD | VT_BYREF:
369 FIXME("handle BRECORD by ref\n");
372 FIXME("handle unknown complex type\n");
380 /* exactly how Invoke is marshalled is not very clear to me yet,
381 * but the way I've done it seems to work for me */
383 HRESULT CALLBACK IDispatch_Invoke_Proxy(
389 DISPPARAMS* pDispParams,
391 EXCEPINFO* pExcepInfo,
396 UINT* rgVarRefIdx = NULL;
397 VARIANTARG* rgVarRef = NULL;
400 TRACE("(%p)->(%ld,%s,%lx,%x,%p,%p,%p,%p)\n", This,
401 dispIdMember, debugstr_guid(riid),
402 lcid, wFlags, pDispParams, pVarResult,
403 pExcepInfo, puArgErr);
405 /* [out] args can't be null, use dummy vars if needed */
406 if (!pVarResult) pVarResult = &VarResult;
408 /* count by-ref args */
409 for (cVarRef=0,u=0; u<pDispParams->cArgs; u++) {
410 VARIANTARG* arg = &pDispParams->rgvarg[u];
411 if (V_VT(arg) & VT_BYREF) {
416 rgVarRefIdx = CoTaskMemAlloc(sizeof(UINT)*cVarRef);
417 rgVarRef = CoTaskMemAlloc(sizeof(VARIANTARG)*cVarRef);
418 /* make list of by-ref args */
419 for (cVarRef=0,u=0; u<pDispParams->cArgs; u++) {
420 VARIANTARG* arg = &pDispParams->rgvarg[u];
421 if (V_VT(arg) & VT_BYREF) {
422 rgVarRefIdx[cVarRef] = u;
423 VariantInit(&rgVarRef[cVarRef]);
428 /* [out] args still can't be null,
429 * but we can point these anywhere in this case,
430 * since they won't be written to when cVarRef is 0 */
431 rgVarRefIdx = puArgErr;
432 rgVarRef = pVarResult;
434 TRACE("passed by ref: %d args\n", cVarRef);
435 hr = IDispatch_RemoteInvoke_Proxy(This,
448 for (u=0; u<cVarRef; u++) {
449 unsigned i = rgVarRefIdx[u];
450 VariantCopy(&pDispParams->rgvarg[i],
452 VariantClear(&rgVarRef[u]);
454 CoTaskMemFree(rgVarRef);
455 CoTaskMemFree(rgVarRefIdx);
460 HRESULT __RPC_STUB IDispatch_Invoke_Stub(
466 DISPPARAMS* pDispParams,
468 EXCEPINFO* pExcepInfo,
472 VARIANTARG* rgVarRef)
475 VARIANTARG *rgvarg, *arg;
478 /* let the real Invoke operate on a copy of the in parameters,
479 * so we don't risk losing pointers to allocated memory */
480 rgvarg = pDispParams->rgvarg;
481 arg = CoTaskMemAlloc(sizeof(VARIANTARG)*pDispParams->cArgs);
482 for (u=0; u<pDispParams->cArgs; u++) {
483 VariantInit(&arg[u]);
484 VariantCopy(&arg[u], &rgvarg[u]);
486 pDispParams->rgvarg = arg;
488 /* initialize out parameters, so that they can be marshalled
489 * in case the real Invoke doesn't initialize them */
490 VariantInit(pVarResult);
491 memset(pExcepInfo, 0, sizeof(*pExcepInfo));
494 hr = IDispatch_Invoke(This,
504 /* copy ref args to out list */
505 for (u=0; u<cVarRef; u++) {
506 unsigned i = rgVarRefIdx[u];
507 VariantInit(&rgVarRef[u]);
508 VariantCopy(&rgVarRef[u], &arg[i]);
509 /* clear original if equal, to avoid double-free */
510 if (V_BYREF(&rgVarRef[u]) == V_BYREF(&rgvarg[i]))
511 VariantClear(&rgvarg[i]);
513 /* clear the duplicate argument list */
514 for (u=0; u<pDispParams->cArgs; u++) {
515 VariantClear(&arg[u]);
517 pDispParams->rgvarg = rgvarg;
525 HRESULT CALLBACK IEnumVARIANT_Next_Proxy(
533 pCeltFetched = &fetched;
534 return IEnumVARIANT_RemoteNext_Proxy(This,
540 HRESULT __RPC_STUB IEnumVARIANT_Next_Stub(
548 hr = IEnumVARIANT_Next(This,
552 if (hr == S_OK) *pCeltFetched = celt;
558 HRESULT CALLBACK ITypeComp_Bind_Proxy(
567 FIXME("not implemented\n");
571 HRESULT __RPC_STUB ITypeComp_Bind_Stub(
578 LPFUNCDESC* ppFuncDesc,
579 LPVARDESC* ppVarDesc,
580 ITypeComp** ppTypeComp,
581 CLEANLOCALSTORAGE* pDummy)
583 FIXME("not implemented\n");
587 HRESULT CALLBACK ITypeComp_BindType_Proxy(
594 FIXME("not implemented\n");
598 HRESULT __RPC_STUB ITypeComp_BindType_Stub(
604 FIXME("not implemented\n");
610 HRESULT CALLBACK ITypeInfo_GetTypeAttr_Proxy(
612 TYPEATTR** ppTypeAttr)
614 FIXME("not implemented\n");
618 HRESULT __RPC_STUB ITypeInfo_GetTypeAttr_Stub(
620 LPTYPEATTR* ppTypeAttr,
621 CLEANLOCALSTORAGE* pDummy)
623 FIXME("not implemented\n");
627 HRESULT CALLBACK ITypeInfo_GetFuncDesc_Proxy(
630 FUNCDESC** ppFuncDesc)
632 FIXME("not implemented\n");
636 HRESULT __RPC_STUB ITypeInfo_GetFuncDesc_Stub(
639 LPFUNCDESC* ppFuncDesc,
640 CLEANLOCALSTORAGE* pDummy)
642 FIXME("not implemented\n");
646 HRESULT CALLBACK ITypeInfo_GetVarDesc_Proxy(
651 FIXME("not implemented\n");
655 HRESULT __RPC_STUB ITypeInfo_GetVarDesc_Stub(
658 LPVARDESC* ppVarDesc,
659 CLEANLOCALSTORAGE* pDummy)
661 FIXME("not implemented\n");
665 HRESULT CALLBACK ITypeInfo_GetNames_Proxy(
672 FIXME("not implemented\n");
676 HRESULT __RPC_STUB ITypeInfo_GetNames_Stub(
683 FIXME("not implemented\n");
687 HRESULT CALLBACK ITypeInfo_GetIDsOfNames_Proxy(
693 FIXME("not implemented\n");
697 HRESULT __RPC_STUB ITypeInfo_GetIDsOfNames_Stub(
700 FIXME("not implemented\n");
704 HRESULT CALLBACK ITypeInfo_Invoke_Proxy(
709 DISPPARAMS* pDispParams,
711 EXCEPINFO* pExcepInfo,
714 FIXME("not implemented\n");
718 HRESULT __RPC_STUB ITypeInfo_Invoke_Stub(
721 FIXME("not implemented\n");
725 HRESULT CALLBACK ITypeInfo_GetDocumentation_Proxy(
729 BSTR* pBstrDocString,
730 DWORD* pdwHelpContext,
733 FIXME("not implemented\n");
737 HRESULT __RPC_STUB ITypeInfo_GetDocumentation_Stub(
742 BSTR* pBstrDocString,
743 DWORD* pdwHelpContext,
746 FIXME("not implemented\n");
750 HRESULT CALLBACK ITypeInfo_GetDllEntry_Proxy(
758 FIXME("not implemented\n");
762 HRESULT __RPC_STUB ITypeInfo_GetDllEntry_Stub(
771 FIXME("not implemented\n");
775 HRESULT CALLBACK ITypeInfo_AddressOfMember_Proxy(
781 FIXME("not implemented\n");
785 HRESULT __RPC_STUB ITypeInfo_AddressOfMember_Stub(
788 FIXME("not implemented\n");
792 HRESULT CALLBACK ITypeInfo_CreateInstance_Proxy(
798 FIXME("not implemented\n");
802 HRESULT __RPC_STUB ITypeInfo_CreateInstance_Stub(
807 FIXME("not implemented\n");
811 HRESULT CALLBACK ITypeInfo_GetContainingTypeLib_Proxy(
816 FIXME("not implemented\n");
820 HRESULT __RPC_STUB ITypeInfo_GetContainingTypeLib_Stub(
825 FIXME("not implemented\n");
829 void CALLBACK ITypeInfo_ReleaseTypeAttr_Proxy(
833 FIXME("not implemented\n");
836 HRESULT __RPC_STUB ITypeInfo_ReleaseTypeAttr_Stub(
839 FIXME("not implemented\n");
843 void CALLBACK ITypeInfo_ReleaseFuncDesc_Proxy(
847 FIXME("not implemented\n");
850 HRESULT __RPC_STUB ITypeInfo_ReleaseFuncDesc_Stub(
853 FIXME("not implemented\n");
857 void CALLBACK ITypeInfo_ReleaseVarDesc_Proxy(
861 FIXME("not implemented\n");
864 HRESULT __RPC_STUB ITypeInfo_ReleaseVarDesc_Stub(
867 FIXME("not implemented\n");
874 HRESULT CALLBACK ITypeInfo2_GetDocumentation2_Proxy(
878 BSTR* pbstrHelpString,
879 DWORD* pdwHelpStringContext,
880 BSTR* pbstrHelpStringDll)
882 FIXME("not implemented\n");
886 HRESULT __RPC_STUB ITypeInfo2_GetDocumentation2_Stub(
891 BSTR* pbstrHelpString,
892 DWORD* pdwHelpStringContext,
893 BSTR* pbstrHelpStringDll)
895 FIXME("not implemented\n");
901 UINT CALLBACK ITypeLib_GetTypeInfoCount_Proxy(
904 FIXME("not implemented\n");
908 HRESULT __RPC_STUB ITypeLib_GetTypeInfoCount_Stub(
912 FIXME("not implemented\n");
916 HRESULT CALLBACK ITypeLib_GetLibAttr_Proxy(
918 TLIBATTR** ppTLibAttr)
920 FIXME("not implemented\n");
924 HRESULT __RPC_STUB ITypeLib_GetLibAttr_Stub(
926 LPTLIBATTR* ppTLibAttr,
927 CLEANLOCALSTORAGE* pDummy)
929 FIXME("not implemented\n");
933 HRESULT CALLBACK ITypeLib_GetDocumentation_Proxy(
937 BSTR* pBstrDocString,
938 DWORD* pdwHelpContext,
941 FIXME("not implemented\n");
945 HRESULT __RPC_STUB ITypeLib_GetDocumentation_Stub(
950 BSTR* pBstrDocString,
951 DWORD* pdwHelpContext,
954 FIXME("not implemented\n");
958 HRESULT CALLBACK ITypeLib_IsName_Proxy(
964 FIXME("not implemented\n");
968 HRESULT __RPC_STUB ITypeLib_IsName_Stub(
975 FIXME("not implemented\n");
979 HRESULT CALLBACK ITypeLib_FindName_Proxy(
987 FIXME("not implemented\n");
991 HRESULT __RPC_STUB ITypeLib_FindName_Stub(
1000 FIXME("not implemented\n");
1004 void CALLBACK ITypeLib_ReleaseTLibAttr_Proxy(
1006 TLIBATTR* pTLibAttr)
1008 FIXME("not implemented\n");
1011 HRESULT __RPC_STUB ITypeLib_ReleaseTLibAttr_Stub(
1014 FIXME("not implemented\n");
1021 HRESULT CALLBACK ITypeLib2_GetLibStatistics_Proxy(
1023 ULONG* pcUniqueNames,
1024 ULONG* pcchUniqueNames)
1026 FIXME("not implemented\n");
1030 HRESULT __RPC_STUB ITypeLib2_GetLibStatistics_Stub(
1032 ULONG* pcUniqueNames,
1033 ULONG* pcchUniqueNames)
1035 FIXME("not implemented\n");
1039 HRESULT CALLBACK ITypeLib2_GetDocumentation2_Proxy(
1043 BSTR* pbstrHelpString,
1044 DWORD* pdwHelpStringContext,
1045 BSTR* pbstrHelpStringDll)
1047 FIXME("not implemented\n");
1051 HRESULT __RPC_STUB ITypeLib2_GetDocumentation2_Stub(
1056 BSTR* pbstrHelpString,
1057 DWORD* pdwHelpStringContext,
1058 BSTR* pbstrHelpStringDll)
1060 FIXME("not implemented\n");