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
23 #define NONAMELESSUNION
24 #define NONAMELESSSTRUCT
34 #include "wine/debug.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(ole);
38 /* FIXME: not supposed to be here */
40 const CLSID CLSID_PSDispatch = {
41 0x20420, 0, 0, {0xC0, 0, 0, 0, 0, 0, 0, 0x46}
44 static CStdPSFactoryBuffer PSFactoryBuffer;
46 CSTDSTUBBUFFERRELEASE(&PSFactoryBuffer)
48 extern const ExtendedProxyFileInfo oaidl_ProxyFileInfo;
50 const ProxyFileInfo* OLEAUT32_ProxyFileList[] = {
55 HRESULT OLEAUTPS_DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
57 return NdrDllGetClassObject(rclsid, riid, ppv, OLEAUT32_ProxyFileList,
58 &CLSID_PSDispatch, &PSFactoryBuffer);
61 /* CLEANLOCALSTORAGE */
62 /* I'm not sure how this is supposed to work yet */
64 unsigned long WINAPI CLEANLOCALSTORAGE_UserSize(unsigned long *pFlags, unsigned long Start, CLEANLOCALSTORAGE *pstg)
66 return Start + sizeof(DWORD);
69 unsigned char * WINAPI CLEANLOCALSTORAGE_UserMarshal(unsigned long *pFlags, unsigned char *Buffer, CLEANLOCALSTORAGE *pstg)
72 return Buffer + sizeof(DWORD);
75 unsigned char * WINAPI CLEANLOCALSTORAGE_UserUnmarshal(unsigned long *pFlags, unsigned char *Buffer, CLEANLOCALSTORAGE *pstr)
77 return Buffer + sizeof(DWORD);
80 void WINAPI CLEANLOCALSTORAGE_UserFree(unsigned long *pFlags, CLEANLOCALSTORAGE *pstr)
86 unsigned long WINAPI BSTR_UserSize(unsigned long *pFlags, unsigned long Start, BSTR *pstr)
88 TRACE("(%lx,%ld,%p) => %p\n", *pFlags, Start, pstr, *pstr);
89 if (*pstr) TRACE("string=%s\n", debugstr_w(*pstr));
90 Start += sizeof(FLAGGED_WORD_BLOB) + sizeof(OLECHAR) * (SysStringLen(*pstr) - 1);
91 TRACE("returning %ld\n", Start);
95 unsigned char * WINAPI BSTR_UserMarshal(unsigned long *pFlags, unsigned char *Buffer, BSTR *pstr)
97 wireBSTR str = (wireBSTR)Buffer;
99 TRACE("(%lx,%p,%p) => %p\n", *pFlags, Buffer, pstr, *pstr);
100 if (*pstr) TRACE("string=%s\n", debugstr_w(*pstr));
102 str->clSize = SysStringLen(*pstr);
104 memcpy(&str->asData, *pstr, sizeof(OLECHAR) * str->clSize);
105 return Buffer + sizeof(FLAGGED_WORD_BLOB) + sizeof(OLECHAR) * (str->clSize - 1);
108 unsigned char * WINAPI BSTR_UserUnmarshal(unsigned long *pFlags, unsigned char *Buffer, BSTR *pstr)
110 wireBSTR str = (wireBSTR)Buffer;
111 TRACE("(%lx,%p,%p) => %p\n", *pFlags, Buffer, pstr, *pstr);
113 SysReAllocStringLen(pstr, (OLECHAR*)&str->asData, str->clSize);
116 SysFreeString(*pstr);
119 if (*pstr) TRACE("string=%s\n", debugstr_w(*pstr));
120 return Buffer + sizeof(FLAGGED_WORD_BLOB) + sizeof(OLECHAR) * (str->clSize - 1);
123 void WINAPI BSTR_UserFree(unsigned long *pFlags, BSTR *pstr)
125 TRACE("(%lx,%p) => %p\n", *pFlags, pstr, *pstr);
127 SysFreeString(*pstr);
133 /* I'm not too sure how to do this yet */
135 #define VARIANT_wiresize sizeof(struct _wireVARIANT)
137 static unsigned wire_size(VARTYPE vt)
139 if (vt & VT_ARRAY) return 0;
141 switch (vt & ~VT_BYREF) {
150 return sizeof(SHORT);
158 return sizeof(FLOAT);
160 return sizeof(DOUBLE);
162 return sizeof(VARIANT_BOOL);
164 return sizeof(SCODE);
170 return sizeof(DECIMAL);
179 FIXME("unhandled VT %d\n", vt);
184 static unsigned wire_extra(unsigned long *pFlags, VARIANT *pvar)
186 if (V_VT(pvar) & VT_ARRAY) {
187 FIXME("wire-size safearray\n");
190 switch (V_VT(pvar)) {
192 return BSTR_UserSize(pFlags, 0, &V_BSTR(pvar));
193 case VT_BSTR | VT_BYREF:
194 return BSTR_UserSize(pFlags, 0, V_BSTRREF(pvar));
196 case VT_SAFEARRAY | VT_BYREF:
197 FIXME("wire-size safearray\n");
199 case VT_VARIANT | VT_BYREF:
200 return VARIANT_UserSize(pFlags, 0, V_VARIANTREF(pvar));
203 FIXME("wire-size interfaces\n");
206 FIXME("wire-size record\n");
213 unsigned long WINAPI VARIANT_UserSize(unsigned long *pFlags, unsigned long Start, VARIANT *pvar)
215 TRACE("(%lx,%ld,%p)\n", *pFlags, Start, pvar);
216 TRACE("vt=%04x\n", V_VT(pvar));
217 Start += VARIANT_wiresize + wire_extra(pFlags, pvar);
218 TRACE("returning %ld\n", Start);
222 unsigned char * WINAPI VARIANT_UserMarshal(unsigned long *pFlags, unsigned char *Buffer, VARIANT *pvar)
224 wireVARIANT var = (wireVARIANT)Buffer;
225 unsigned size, extra;
226 unsigned char *Pos = Buffer + VARIANT_wiresize;
228 TRACE("(%lx,%p,%p)\n", *pFlags, Buffer, pvar);
229 TRACE("vt=%04x\n", V_VT(pvar));
231 memset(var, 0, sizeof(*var));
232 var->clSize = sizeof(*var);
233 var->vt = pvar->n1.n2.vt;
235 var->rpcReserved = var->vt;
236 if ((var->vt & VT_ARRAY) ||
237 ((var->vt & VT_TYPEMASK) == VT_SAFEARRAY))
238 var->vt = VT_ARRAY | (var->vt & VT_BYREF);
240 if (var->vt == VT_DECIMAL) {
241 /* special case because decVal is on a different level */
242 var->u.decVal = pvar->n1.decVal;
246 size = wire_size(V_VT(pvar));
247 extra = wire_extra(pFlags, pvar);
248 var->wReserved1 = pvar->n1.n2.wReserved1;
249 var->wReserved2 = pvar->n1.n2.wReserved2;
250 var->wReserved3 = pvar->n1.n2.wReserved3;
252 if (var->vt & VT_BYREF)
253 memcpy(&var->u.cVal, pvar->n1.n2.n3.byref, size);
255 memcpy(&var->u.cVal, &pvar->n1.n2.n3, size);
257 if (!extra) return Pos;
261 Pos = BSTR_UserMarshal(pFlags, Pos, &V_BSTR(pvar));
263 case VT_BSTR | VT_BYREF:
264 Pos = BSTR_UserMarshal(pFlags, Pos, V_BSTRREF(pvar));
266 case VT_VARIANT | VT_BYREF:
267 Pos = VARIANT_UserMarshal(pFlags, Pos, V_VARIANTREF(pvar));
270 FIXME("handle BRECORD by val\n");
272 case VT_RECORD | VT_BYREF:
273 FIXME("handle BRECORD by ref\n");
276 FIXME("handle unknown complex type\n");
279 var->clSize = Pos - Buffer;
280 TRACE("marshalled size=%ld\n", var->clSize);
284 unsigned char * WINAPI VARIANT_UserUnmarshal(unsigned long *pFlags, unsigned char *Buffer, VARIANT *pvar)
286 wireVARIANT var = (wireVARIANT)Buffer;
288 unsigned char *Pos = Buffer + VARIANT_wiresize;
290 TRACE("(%lx,%p,%p)\n", *pFlags, Buffer, pvar);
292 pvar->n1.n2.vt = var->rpcReserved;
293 TRACE("marshalled: clSize=%ld, vt=%04x\n", var->clSize, var->vt);
294 TRACE("vt=%04x\n", V_VT(pvar));
295 TRACE("reserved: %d, %d, %d\n", var->wReserved1, var->wReserved2, var->wReserved3);
296 TRACE("val: %ld\n", var->u.lVal);
298 if (var->vt == VT_DECIMAL) {
299 /* special case because decVal is on a different level */
300 pvar->n1.decVal = var->u.decVal;
304 size = wire_size(V_VT(pvar));
305 pvar->n1.n2.wReserved1 = var->wReserved1;
306 pvar->n1.n2.wReserved2 = var->wReserved2;
307 pvar->n1.n2.wReserved3 = var->wReserved3;
309 if (var->vt & VT_BYREF) {
310 pvar->n1.n2.n3.byref = CoTaskMemAlloc(size);
311 memcpy(pvar->n1.n2.n3.byref, &var->u.cVal, size);
314 memcpy(&pvar->n1.n2.n3, &var->u.cVal, size);
316 if (var->clSize <= VARIANT_wiresize) return Pos;
320 Pos = BSTR_UserUnmarshal(pFlags, Pos, &V_BSTR(pvar));
322 case VT_BSTR | VT_BYREF:
323 pvar->n1.n2.n3.byref = CoTaskMemAlloc(sizeof(BSTR));
324 *(BSTR*)pvar->n1.n2.n3.byref = NULL;
325 Pos = BSTR_UserUnmarshal(pFlags, Pos, V_BSTRREF(pvar));
327 case VT_VARIANT | VT_BYREF:
328 pvar->n1.n2.n3.byref = CoTaskMemAlloc(sizeof(VARIANT));
329 Pos = VARIANT_UserUnmarshal(pFlags, Pos, V_VARIANTREF(pvar));
332 FIXME("handle BRECORD by val\n");
334 case VT_RECORD | VT_BYREF:
335 FIXME("handle BRECORD by ref\n");
338 FIXME("handle unknown complex type\n");
341 if (Pos != Buffer + var->clSize) {
342 ERR("size difference during unmarshal\n");
344 return Buffer + var->clSize;
347 void WINAPI VARIANT_UserFree(unsigned long *pFlags, VARIANT *pvar)
349 VARTYPE vt = V_VT(pvar);
352 TRACE("(%lx,%p)\n", *pFlags, pvar);
353 TRACE("vt=%04x\n", V_VT(pvar));
355 if (vt & VT_BYREF) ref = pvar->n1.n2.n3.byref;
361 case VT_BSTR | VT_BYREF:
362 BSTR_UserFree(pFlags, ref);
364 case VT_VARIANT | VT_BYREF:
365 VARIANT_UserFree(pFlags, ref);
367 case VT_RECORD | VT_BYREF:
368 FIXME("handle BRECORD by ref\n");
371 FIXME("handle unknown complex type\n");
379 /* exactly how Invoke is marshalled is not very clear to me yet,
380 * but the way I've done it seems to work for me */
382 HRESULT CALLBACK IDispatch_Invoke_Proxy(
388 DISPPARAMS* pDispParams,
390 EXCEPINFO* pExcepInfo,
395 UINT* rgVarRefIdx = NULL;
396 VARIANTARG* rgVarRef = NULL;
399 TRACE("(%p)->(%ld,%s,%lx,%x,%p,%p,%p,%p)\n", This,
400 dispIdMember, debugstr_guid(riid),
401 lcid, wFlags, pDispParams, pVarResult,
402 pExcepInfo, puArgErr);
404 /* [out] args can't be null, use dummy vars if needed */
405 if (!pVarResult) pVarResult = &VarResult;
407 /* count by-ref args */
408 for (cVarRef=0,u=0; u<pDispParams->cArgs; u++) {
409 VARIANTARG* arg = &pDispParams->rgvarg[u];
410 if (V_VT(arg) & VT_BYREF) {
415 rgVarRefIdx = CoTaskMemAlloc(sizeof(UINT)*cVarRef);
416 rgVarRef = CoTaskMemAlloc(sizeof(VARIANTARG)*cVarRef);
417 /* make list of by-ref args */
418 for (cVarRef=0,u=0; u<pDispParams->cArgs; u++) {
419 VARIANTARG* arg = &pDispParams->rgvarg[u];
420 if (V_VT(arg) & VT_BYREF) {
421 rgVarRefIdx[cVarRef] = u;
422 VariantInit(&rgVarRef[cVarRef]);
427 /* [out] args still can't be null,
428 * but we can point these anywhere in this case,
429 * since they won't be written to when cVarRef is 0 */
430 rgVarRefIdx = puArgErr;
431 rgVarRef = pVarResult;
433 TRACE("passed by ref: %d args\n", cVarRef);
434 hr = IDispatch_RemoteInvoke_Proxy(This,
447 for (u=0; u<cVarRef; u++) {
448 unsigned i = rgVarRefIdx[u];
449 VariantCopy(&pDispParams->rgvarg[i],
451 VariantClear(&rgVarRef[u]);
453 CoTaskMemFree(rgVarRef);
454 CoTaskMemFree(rgVarRefIdx);
459 HRESULT __RPC_STUB IDispatch_Invoke_Stub(
465 DISPPARAMS* pDispParams,
467 EXCEPINFO* pExcepInfo,
471 VARIANTARG* rgVarRef)
474 VARIANTARG *rgvarg, *arg;
477 /* let the real Invoke operate on a copy of the in parameters,
478 * so we don't risk losing pointers to allocated memory */
479 rgvarg = pDispParams->rgvarg;
480 arg = CoTaskMemAlloc(sizeof(VARIANTARG)*pDispParams->cArgs);
481 for (u=0; u<pDispParams->cArgs; u++) {
482 VariantInit(&arg[u]);
483 VariantCopy(&arg[u], &rgvarg[u]);
485 pDispParams->rgvarg = arg;
487 /* initialize out parameters, so that they can be marshalled
488 * in case the real Invoke doesn't initialize them */
489 VariantInit(pVarResult);
490 memset(pExcepInfo, 0, sizeof(*pExcepInfo));
493 hr = IDispatch_Invoke(This,
503 /* copy ref args to out list */
504 for (u=0; u<cVarRef; u++) {
505 unsigned i = rgVarRefIdx[u];
506 VariantInit(&rgVarRef[u]);
507 VariantCopy(&rgVarRef[u], &arg[i]);
508 /* clear original if equal, to avoid double-free */
509 if (V_BYREF(&rgVarRef[u]) == V_BYREF(&rgvarg[i]))
510 VariantClear(&rgvarg[i]);
512 /* clear the duplicate argument list */
513 for (u=0; u<pDispParams->cArgs; u++) {
514 VariantClear(&arg[u]);
516 pDispParams->rgvarg = rgvarg;
524 HRESULT CALLBACK IEnumVARIANT_Next_Proxy(
532 pCeltFetched = &fetched;
533 return IEnumVARIANT_RemoteNext_Proxy(This,
539 HRESULT __RPC_STUB IEnumVARIANT_Next_Stub(
547 hr = IEnumVARIANT_Next(This,
551 if (hr == S_OK) *pCeltFetched = celt;
557 HRESULT CALLBACK ITypeComp_Bind_Proxy(
566 FIXME("not implemented\n");
570 HRESULT __RPC_STUB ITypeComp_Bind_Stub(
577 LPFUNCDESC* ppFuncDesc,
578 LPVARDESC* ppVarDesc,
579 ITypeComp** ppTypeComp,
580 CLEANLOCALSTORAGE* pDummy)
582 FIXME("not implemented\n");
586 HRESULT CALLBACK ITypeComp_BindType_Proxy(
593 FIXME("not implemented\n");
597 HRESULT __RPC_STUB ITypeComp_BindType_Stub(
603 FIXME("not implemented\n");
609 HRESULT CALLBACK ITypeInfo_GetTypeAttr_Proxy(
611 TYPEATTR** ppTypeAttr)
613 FIXME("not implemented\n");
617 HRESULT __RPC_STUB ITypeInfo_GetTypeAttr_Stub(
619 LPTYPEATTR* ppTypeAttr,
620 CLEANLOCALSTORAGE* pDummy)
622 FIXME("not implemented\n");
626 HRESULT CALLBACK ITypeInfo_GetFuncDesc_Proxy(
629 FUNCDESC** ppFuncDesc)
631 FIXME("not implemented\n");
635 HRESULT __RPC_STUB ITypeInfo_GetFuncDesc_Stub(
638 LPFUNCDESC* ppFuncDesc,
639 CLEANLOCALSTORAGE* pDummy)
641 FIXME("not implemented\n");
645 HRESULT CALLBACK ITypeInfo_GetVarDesc_Proxy(
650 FIXME("not implemented\n");
654 HRESULT __RPC_STUB ITypeInfo_GetVarDesc_Stub(
657 LPVARDESC* ppVarDesc,
658 CLEANLOCALSTORAGE* pDummy)
660 FIXME("not implemented\n");
664 HRESULT CALLBACK ITypeInfo_GetNames_Proxy(
671 FIXME("not implemented\n");
675 HRESULT __RPC_STUB ITypeInfo_GetNames_Stub(
682 FIXME("not implemented\n");
686 HRESULT CALLBACK ITypeInfo_GetIDsOfNames_Proxy(
692 FIXME("not implemented\n");
696 HRESULT __RPC_STUB ITypeInfo_GetIDsOfNames_Stub(
699 FIXME("not implemented\n");
703 HRESULT CALLBACK ITypeInfo_Invoke_Proxy(
708 DISPPARAMS* pDispParams,
710 EXCEPINFO* pExcepInfo,
713 FIXME("not implemented\n");
717 HRESULT __RPC_STUB ITypeInfo_Invoke_Stub(
720 FIXME("not implemented\n");
724 HRESULT CALLBACK ITypeInfo_GetDocumentation_Proxy(
728 BSTR* pBstrDocString,
729 DWORD* pdwHelpContext,
732 FIXME("not implemented\n");
736 HRESULT __RPC_STUB ITypeInfo_GetDocumentation_Stub(
741 BSTR* pBstrDocString,
742 DWORD* pdwHelpContext,
745 FIXME("not implemented\n");
749 HRESULT CALLBACK ITypeInfo_GetDllEntry_Proxy(
757 FIXME("not implemented\n");
761 HRESULT __RPC_STUB ITypeInfo_GetDllEntry_Stub(
770 FIXME("not implemented\n");
774 HRESULT CALLBACK ITypeInfo_AddressOfMember_Proxy(
780 FIXME("not implemented\n");
784 HRESULT __RPC_STUB ITypeInfo_AddressOfMember_Stub(
787 FIXME("not implemented\n");
791 HRESULT CALLBACK ITypeInfo_CreateInstance_Proxy(
797 FIXME("not implemented\n");
801 HRESULT __RPC_STUB ITypeInfo_CreateInstance_Stub(
806 FIXME("not implemented\n");
810 HRESULT CALLBACK ITypeInfo_GetContainingTypeLib_Proxy(
815 FIXME("not implemented\n");
819 HRESULT __RPC_STUB ITypeInfo_GetContainingTypeLib_Stub(
824 FIXME("not implemented\n");
828 void CALLBACK ITypeInfo_ReleaseTypeAttr_Proxy(
832 FIXME("not implemented\n");
835 HRESULT __RPC_STUB ITypeInfo_ReleaseTypeAttr_Stub(
838 FIXME("not implemented\n");
842 void CALLBACK ITypeInfo_ReleaseFuncDesc_Proxy(
846 FIXME("not implemented\n");
849 HRESULT __RPC_STUB ITypeInfo_ReleaseFuncDesc_Stub(
852 FIXME("not implemented\n");
856 void CALLBACK ITypeInfo_ReleaseVarDesc_Proxy(
860 FIXME("not implemented\n");
863 HRESULT __RPC_STUB ITypeInfo_ReleaseVarDesc_Stub(
866 FIXME("not implemented\n");
873 HRESULT CALLBACK ITypeInfo2_GetDocumentation2_Proxy(
877 BSTR* pbstrHelpString,
878 DWORD* pdwHelpStringContext,
879 BSTR* pbstrHelpStringDll)
881 FIXME("not implemented\n");
885 HRESULT __RPC_STUB ITypeInfo2_GetDocumentation2_Stub(
890 BSTR* pbstrHelpString,
891 DWORD* pdwHelpStringContext,
892 BSTR* pbstrHelpStringDll)
894 FIXME("not implemented\n");
900 UINT CALLBACK ITypeLib_GetTypeInfoCount_Proxy(
903 FIXME("not implemented\n");
907 HRESULT __RPC_STUB ITypeLib_GetTypeInfoCount_Stub(
911 FIXME("not implemented\n");
915 HRESULT CALLBACK ITypeLib_GetLibAttr_Proxy(
917 TLIBATTR** ppTLibAttr)
919 FIXME("not implemented\n");
923 HRESULT __RPC_STUB ITypeLib_GetLibAttr_Stub(
925 LPTLIBATTR* ppTLibAttr,
926 CLEANLOCALSTORAGE* pDummy)
928 FIXME("not implemented\n");
932 HRESULT CALLBACK ITypeLib_GetDocumentation_Proxy(
936 BSTR* pBstrDocString,
937 DWORD* pdwHelpContext,
940 FIXME("not implemented\n");
944 HRESULT __RPC_STUB ITypeLib_GetDocumentation_Stub(
949 BSTR* pBstrDocString,
950 DWORD* pdwHelpContext,
953 FIXME("not implemented\n");
957 HRESULT CALLBACK ITypeLib_IsName_Proxy(
963 FIXME("not implemented\n");
967 HRESULT __RPC_STUB ITypeLib_IsName_Stub(
974 FIXME("not implemented\n");
978 HRESULT CALLBACK ITypeLib_FindName_Proxy(
986 FIXME("not implemented\n");
990 HRESULT __RPC_STUB ITypeLib_FindName_Stub(
999 FIXME("not implemented\n");
1003 void CALLBACK ITypeLib_ReleaseTLibAttr_Proxy(
1005 TLIBATTR* pTLibAttr)
1007 FIXME("not implemented\n");
1010 HRESULT __RPC_STUB ITypeLib_ReleaseTLibAttr_Stub(
1013 FIXME("not implemented\n");
1020 HRESULT CALLBACK ITypeLib2_GetLibStatistics_Proxy(
1022 ULONG* pcUniqueNames,
1023 ULONG* pcchUniqueNames)
1025 FIXME("not implemented\n");
1029 HRESULT __RPC_STUB ITypeLib2_GetLibStatistics_Stub(
1031 ULONG* pcUniqueNames,
1032 ULONG* pcchUniqueNames)
1034 FIXME("not implemented\n");
1038 HRESULT CALLBACK ITypeLib2_GetDocumentation2_Proxy(
1042 BSTR* pbstrHelpString,
1043 DWORD* pdwHelpStringContext,
1044 BSTR* pbstrHelpStringDll)
1046 FIXME("not implemented\n");
1050 HRESULT __RPC_STUB ITypeLib2_GetDocumentation2_Stub(
1055 BSTR* pbstrHelpString,
1056 DWORD* pdwHelpStringContext,
1057 BSTR* pbstrHelpStringDll)
1059 FIXME("not implemented\n");