/** * This is the core of the old Save method. * It copies this variant to a byte stream. * The unmarshalling part of this doesn't work but it was left in * with the hope that someone will want to fix this later **/ JNIEXPORT jbyteArray JNICALL Java_com_tangram_Variant_SerializationWriteToBytes(JNIEnv *env, jobject _this) { VARIANT *v = extractVariant(env, _this); if (v) { DWORD flags = MSHCTX_LOCAL; jint size = VARIANT_UserSize(&flags, 0L, v); // allocate a byte array of the right length jbyte* pBuf = new jbyte[size]; // clear it out ZeroMemory(pBuf, size); // marshall the Variant into the buffer VARIANT_UserMarshal(&flags, (unsigned char *)pBuf, v); // need to convert the buffer to a java byte ba[] jbyteArray ba = env->NewByteArray(size); env->SetByteArrayRegion(ba, 0, size, pBuf); // and delete the original memory delete[] pBuf; return ba; } else { jbyteArray ba = env->NewByteArray(0); return ba; } }
unsigned char * WINAPI LPSAFEARRAY_UserMarshal(unsigned long *pFlags, unsigned char *Buffer, LPSAFEARRAY *ppsa) { HRESULT hr; TRACE("("); dump_user_flags(pFlags); TRACE(", %p, &%p\n", Buffer, *ppsa); ALIGN_POINTER(Buffer, 3); *(ULONG_PTR *)Buffer = *ppsa ? TRUE : FALSE; Buffer += sizeof(ULONG_PTR); if (*ppsa) { VARTYPE vt; SAFEARRAY *psa = *ppsa; ULONG ulCellCount = SAFEARRAY_GetCellCount(psa); wireSAFEARRAY wiresa; SF_TYPE sftype; GUID guid; *(ULONG *)Buffer = psa->cDims; Buffer += sizeof(ULONG); wiresa = (wireSAFEARRAY)Buffer; wiresa->cDims = psa->cDims; wiresa->fFeatures = psa->fFeatures; wiresa->cbElements = psa->cbElements; hr = SafeArrayGetVartype(psa, &vt); if (FAILED(hr)) RpcRaiseException(hr); wiresa->cLocks = (USHORT)psa->cLocks | (vt << 16); Buffer += FIELD_OFFSET(struct _wireSAFEARRAY, uArrayStructs); sftype = SAFEARRAY_GetUnionType(psa); *(ULONG *)Buffer = sftype; Buffer += sizeof(ULONG); *(ULONG *)Buffer = ulCellCount; Buffer += sizeof(ULONG); *(ULONG_PTR *)Buffer = (ULONG_PTR)psa->pvData; Buffer += sizeof(ULONG_PTR); if (sftype == SF_HAVEIID) { SafeArrayGetIID(psa, &guid); memcpy(Buffer, &guid, sizeof(guid)); Buffer += sizeof(guid); } memcpy(Buffer, psa->rgsabound, sizeof(psa->rgsabound[0]) * psa->cDims); Buffer += sizeof(psa->rgsabound[0]) * psa->cDims; *(ULONG *)Buffer = ulCellCount; Buffer += sizeof(ULONG); if (psa->pvData) { switch (sftype) { case SF_BSTR: { BSTR* lpBstr; for (lpBstr = (BSTR*)psa->pvData; ulCellCount; ulCellCount--, lpBstr++) Buffer = BSTR_UserMarshal(pFlags, Buffer, lpBstr); break; } case SF_DISPATCH: case SF_UNKNOWN: case SF_HAVEIID: FIXME("marshal interfaces\n"); break; case SF_VARIANT: { VARIANT* lpVariant; for (lpVariant = (VARIANT*)psa->pvData; ulCellCount; ulCellCount--, lpVariant++) Buffer = VARIANT_UserMarshal(pFlags, Buffer, lpVariant); break; } case SF_RECORD: { IRecordInfo* pRecInfo = NULL; hr = SafeArrayGetRecordInfo(psa, &pRecInfo); if (FAILED(hr)) RpcRaiseException(hr); if (pRecInfo) { FIXME("write record info %p\n", pRecInfo); IRecordInfo_Release(pRecInfo); } break; } case SF_I8: ALIGN_POINTER(Buffer, 7); /* fallthrough */ case SF_I1: case SF_I2: case SF_I4: /* Just copy the data over */ memcpy(Buffer, psa->pvData, ulCellCount * psa->cbElements); Buffer += ulCellCount * psa->cbElements; break; default: break; } } } return Buffer; }
unsigned char * WINAPI VARIANT_UserMarshal(unsigned long *pFlags, unsigned char *Buffer, VARIANT *pvar) { variant_wire_t *header; unsigned long type_size; int align; unsigned char *Pos; TRACE("(%lx,%p,%p)\n", *pFlags, Buffer, pvar); TRACE("vt=%04x\n", V_VT(pvar)); ALIGN_POINTER(Buffer, 7); header = (variant_wire_t *)Buffer; header->clSize = 0; /* fixed up at the end */ header->rpcReserverd = 0; header->vt = pvar->n1.n2.vt; header->wReserved1 = pvar->n1.n2.wReserved1; header->wReserved2 = pvar->n1.n2.wReserved2; header->wReserved3 = pvar->n1.n2.wReserved3; header->switch_is = pvar->n1.n2.vt; if(header->switch_is & VT_ARRAY) header->switch_is &= ~VT_TYPEMASK; Pos = (unsigned char*)(header + 1); type_size = get_type_size(pFlags, pvar); align = get_type_alignment(pFlags, pvar); ALIGN_POINTER(Pos, align); if(header->vt & VT_BYREF) { *(DWORD *)Pos = max(type_size, 4); Pos += 4; if((header->vt & VT_TYPEMASK) != VT_VARIANT) { memcpy(Pos, pvar->n1.n2.n3.byref, type_size); Pos += type_size; } else { *(DWORD*)Pos = 'U' | 's' << 8 | 'e' << 16 | 'r' << 24; Pos += 4; } } else { if((header->vt & VT_TYPEMASK) == VT_DECIMAL) memcpy(Pos, pvar, type_size); else memcpy(Pos, &pvar->n1.n2.n3, type_size); Pos += type_size; } if(header->vt & VT_ARRAY) { if(header->vt & VT_BYREF) Pos = LPSAFEARRAY_UserMarshal(pFlags, Pos, V_ARRAYREF(pvar)); else Pos = LPSAFEARRAY_UserMarshal(pFlags, Pos, &V_ARRAY(pvar)); } else { switch (header->vt) { case VT_BSTR: Pos = BSTR_UserMarshal(pFlags, Pos, &V_BSTR(pvar)); break; case VT_BSTR | VT_BYREF: Pos = BSTR_UserMarshal(pFlags, Pos, V_BSTRREF(pvar)); break; case VT_VARIANT | VT_BYREF: Pos = VARIANT_UserMarshal(pFlags, Pos, V_VARIANTREF(pvar)); break; case VT_DISPATCH | VT_BYREF: FIXME("handle DISPATCH by ref\n"); break; case VT_UNKNOWN: /* this should probably call WdtpInterfacePointer_UserMarshal in ole32.dll */ Pos = interface_variant_marshal(pFlags, Pos, &IID_IUnknown, pvar); break; case VT_DISPATCH: /* this should probably call WdtpInterfacePointer_UserMarshal in ole32.dll */ Pos = interface_variant_marshal(pFlags, Pos, &IID_IDispatch, pvar); break; case VT_RECORD: FIXME("handle BRECORD by val\n"); break; case VT_RECORD | VT_BYREF: FIXME("handle BRECORD by ref\n"); break; } } header->clSize = ((Pos - Buffer) + 7) >> 3; TRACE("marshalled size=%ld\n", header->clSize); return Pos; }