/************************************************************************ * SafeArrayCopy (OLEAUT32.27) * * Make a duplicate of a SafeArray. * * PARAMS * psa [I] Source for copy * ppsaOut [O] Destination for new copy * * RETURNS * Success: S_OK. ppsaOut contains a copy of the array. * Failure: An HRESULT error code indicating the error. * * NOTES * See SafeArray. */ HRESULT WINAPI SafeArrayCopy(SAFEARRAY *psa, SAFEARRAY **ppsaOut) { HRESULT hRet; TRACE("(%p,%p)\n", psa, ppsaOut); if (!ppsaOut) return E_INVALIDARG; *ppsaOut = NULL; if (!psa) return S_OK; /* Handles copying of NULL arrays */ if (!psa->cbElements) return E_INVALIDARG; if (psa->fFeatures & (FADF_RECORD|FADF_HAVEIID|FADF_HAVEVARTYPE)) { VARTYPE vt; hRet = SafeArrayGetVartype(psa, &vt); if (SUCCEEDED(hRet)) hRet = SafeArrayAllocDescriptorEx(vt, psa->cDims, ppsaOut); } else { hRet = SafeArrayAllocDescriptor(psa->cDims, ppsaOut); if (SUCCEEDED(hRet)) { (*ppsaOut)->fFeatures = psa->fFeatures & ~ignored_copy_features; (*ppsaOut)->cbElements = psa->cbElements; } } if (SUCCEEDED(hRet)) { /* Copy dimension bounds */ memcpy((*ppsaOut)->rgsabound, psa->rgsabound, psa->cDims * sizeof(SAFEARRAYBOUND)); (*ppsaOut)->pvData = SAFEARRAY_Malloc(SAFEARRAY_GetCellCount(psa) * psa->cbElements); if (!(*ppsaOut)->pvData) { SafeArrayDestroyDescriptor(*ppsaOut); *ppsaOut = NULL; return E_OUTOFMEMORY; } hRet = SAFEARRAY_CopyData(psa, *ppsaOut); if (FAILED(hRet)) { SAFEARRAY_Free((*ppsaOut)->pvData); SafeArrayDestroyDescriptor(*ppsaOut); *ppsaOut = NULL; return hRet; } } return hRet; }
STDMETHODIMP Profile::put_Languages(SAFEARRAY * newVal) { try { VARTYPE vt = VT_UNKNOWN; SafeArrayGetVartype(newVal, & vt); UINT uiDim = SafeArrayGetDim(newVal); if((uiDim != 1) || (vt != VT_BSTR)) { return AtlReportError(GetObjectCLSID(), L"Array of languages must be single dimension array of strings", GUID_NULL, E_INVALIDARG); } HRESULT hr = SafeArrayLock(newVal); if(FAILED(hr)) { return AtlReportError(GetObjectCLSID(), L"Unable to lock array", GUID_NULL, E_FAIL); } BSTR * pItems = (BSTR *) newVal->pvData; wstring wstrItems; for(ULONG l = 0; l < newVal->rgsabound[0].cElements; l++) { if(l > 0) wstrItems += L" "; wstrItems += pItems[l]; } SafeArrayUnlock(newVal); gSkypeQueue.SetProperty(L"PROFILE", L"", L"LANGUAGES", wstrItems.c_str()); return S_OK; } catch (const WCHAR * err) { return AtlReportError(GetObjectCLSID(), err, GUID_NULL, E_FAIL); } }
static zval* saproxy_iter_get_data(zend_object_iterator *iter) { php_com_saproxy_iter *I = (php_com_saproxy_iter*)Z_PTR(iter->data); VARIANT v; VARTYPE vt; SAFEARRAY *sa; I->indices[I->proxy->dimensions-1] = I->key; sa = V_ARRAY(&I->proxy->obj->v); if (FAILED(SafeArrayGetVartype(sa, &vt)) || vt == VT_EMPTY) { vt = V_VT(&I->proxy->obj->v) & ~VT_ARRAY; } VariantInit(&v); if (vt == VT_VARIANT) { SafeArrayGetElement(sa, I->indices, &v); } else { V_VT(&v) = vt; SafeArrayGetElement(sa, I->indices, &v.lVal); } ZVAL_NULL(&I->data); php_com_wrap_variant(&I->data, &v, I->proxy->obj->code_page); VariantClear(&v); return &I->data; }
STDMETHODIMP CMTDoubleVector::setValueVector(SAFEARRAY * pValues) { VARTYPE varType; if( FAILED(SafeArrayGetVartype(pValues, &varType)) ) { return Error( _T("setValueVector: Invalid result array") , __uuidof( IMTDoubleVector ), E_FAIL ); } if( varType != VT_R8 ) { return Error( _T("setValueVector: Invalid result array type. Must be double") , __uuidof( IMTDoubleVector ), E_FAIL ); } if( (pValues)->cDims != 1 ) { return Error( _T("setValueVector: The array must have only one dimension") , __uuidof( IMTDoubleVector ), E_FAIL ); } clear(); m_nbValues = pValues->rgsabound[0].cElements; m_pValues = new double[m_nbValues]; CopyMemory(m_pValues, pValues->pvData, sizeof(double)*m_nbValues); updateListeners(); return S_OK; }
static void com_write_dimension(zval *object, zval *offset, zval *value) { php_com_dotnet_object *obj; zval args[2]; VARIANT v; HRESULT res; obj = CDNO_FETCH(object); if (V_VT(&obj->v) == VT_DISPATCH) { ZVAL_COPY_VALUE(&args[0], offset); ZVAL_COPY_VALUE(&args[1], value); VariantInit(&v); if (SUCCESS == php_com_do_invoke_by_id(obj, DISPID_VALUE, DISPATCH_METHOD|DISPATCH_PROPERTYPUT, &v, 2, args, 0, 0)) { VariantClear(&v); } } else if (V_ISARRAY(&obj->v)) { LONG indices = 0; VARTYPE vt; if (SafeArrayGetDim(V_ARRAY(&obj->v)) == 1) { if (FAILED(SafeArrayGetVartype(V_ARRAY(&obj->v), &vt)) || vt == VT_EMPTY) { vt = V_VT(&obj->v) & ~VT_ARRAY; } convert_to_long(offset); indices = (LONG)Z_LVAL_P(offset); VariantInit(&v); php_com_variant_from_zval(&v, value, obj->code_page); if (V_VT(&v) != vt) { VariantChangeType(&v, &v, 0, vt); } if (vt == VT_VARIANT) { res = SafeArrayPutElement(V_ARRAY(&obj->v), &indices, &v); } else { res = SafeArrayPutElement(V_ARRAY(&obj->v), &indices, &v.lVal); } VariantClear(&v); if (FAILED(res)) { php_com_throw_exception(res, NULL); } } else { php_com_throw_exception(DISP_E_BADINDEX, "this variant has multiple dimensions; you can't set a new value without specifying *all* dimensions"); } } else { php_com_throw_exception(E_INVALIDARG, "this variant is not an array type"); } }
//============================================================================== // 1D array of ints, dim unspecified, allow Nx1 or 1xN arrays int g_CheckVariantArray( int * pnDim1, VARIANT vMtx, int ** ppiMtx ){ SAFEARRAY * psaMtx; int nDims; long iDim1, iDim2; VARTYPE tSaType; psaMtx = vMtx.parray; *pnDim1 = 0; if( vMtx.vt != (VT_ARRAY|VT_I4)){ CP_printf("\ng_CheckVariantArray(): wrong VARIANT type, expecting array of ints!\n"); return 1; } SafeArrayGetVartype( psaMtx, &tSaType ); if( tSaType != VT_I4 ){ CP_printf("\ng_CheckVariantArray(): wrong array type, expecting array of ints!\n"); return 1; } nDims = SafeArrayGetDim( psaMtx ); if( nDims !=2 && nDims !=1 ) { // Allow Nx1 or 1xN arrays CP_printf("\ng_CheckVariantArray(): wrong array dimensions, expecting 1xN, or Nx1 array!\n"); return 1; } SafeArrayGetLBound( psaMtx, 1, &iDim1 ); if( iDim1 != 0) { CP_printf("\ng_CheckVariantArray(): wrong array dimensions, expecting 1xN, or Nx1 array!\n"); return 1; } SafeArrayGetUBound( psaMtx, 1, &iDim1 ); if( nDims == 2 ) { SafeArrayGetLBound( psaMtx, 2, &iDim2 ); if( iDim2 != 0) { CP_printf("\ng_CheckVariantArray(): wrong array dimensions, expecting 1xN, or Nx1 array!\n"); return 1; } SafeArrayGetUBound( psaMtx, 2, &iDim2 ); } else iDim2 = 0; // stupid Matlab hack allowing any 2D array with one redundant dim if( (iDim2 != 0) && (iDim1 != 0)) { CP_printf("\ng_CheckVariantArray(): wrong array dimensions, expecting 1xN, or Nx1 array!\n"); return 1; } *pnDim1 = iDim1 + iDim2 + 1; // if we get here, one size is always zero SafeArrayAccessData(psaMtx, (void **) ppiMtx); // Get data pointer return 0; }
//============================================================================== // 2D array of doubles int g_CheckVariantArray( int nDim1, int nDim2, VARIANT vMtx, double ** ppdMtx ){ SAFEARRAY * psaMtx; int nDims; long iDim; VARTYPE tSaType; psaMtx = vMtx.parray; if( vMtx.vt != (VT_ARRAY|VT_R8)){ CP_printf("\ng_CheckVariantArray(): wrong VARIANT type, expecting array of doubles!\n"); return 1; } SafeArrayGetVartype( psaMtx, &tSaType ); if( tSaType != VT_R8 ){ CP_printf("\ng_CheckVariantArray(): wrong array type, expecting array of doubles!\n"); return 1; } nDims = SafeArrayGetDim( psaMtx ); if( nDims !=2 ) { CP_printf("\ng_CheckVariantArray(): wrong array dimensions, expecting %dx%d array!\n", nDim1, nDim2 ); return 1; } SafeArrayGetLBound( psaMtx, 1, &iDim ); if( iDim != 0) { CP_printf("\ng_CheckVariantArray(): wrong array dimensions, expecting %dx%d array!\n", nDim1, nDim2 ); return 1; } SafeArrayGetUBound( psaMtx, 1, &iDim ); if( iDim+1 != nDim1) { CP_printf("\ng_CheckVariantArray(): wrong array dimensions, expecting %dx%d array!\n", nDim1, nDim2 ); return 1; } SafeArrayGetLBound( psaMtx, 2, &iDim ); if( iDim != 0) { CP_printf("\ng_CheckVariantArray(): wrong array dimensions, expecting %dx%d array!\n", nDim1, nDim2 ); return 1; } SafeArrayGetUBound( psaMtx, 2, &iDim ); if( iDim+1 != nDim2) { CP_printf("\ng_CheckVariantArray(): wrong array dimensions, expecting %dx%d array!\n", nDim1, nDim2 ); return 1; } SafeArrayAccessData(psaMtx, (void **) ppdMtx); // Get data pointer return 0; }
/* this is a convenience function for fetching a particular * element from a (possibly multi-dimensional) safe array */ PHP_COM_DOTNET_API int php_com_safearray_get_elem(VARIANT *array, VARIANT *dest, LONG dim1) { UINT dims; LONG lbound, ubound; LONG indices[1]; VARTYPE vt; if (!V_ISARRAY(array)) { return 0; } dims = SafeArrayGetDim(V_ARRAY(array)); if (dims != 1) { php_error_docref(NULL, E_WARNING, "Can only handle single dimension variant arrays (this array has %d)", dims); return 0; } if (FAILED(SafeArrayGetVartype(V_ARRAY(array), &vt)) || vt == VT_EMPTY) { vt = V_VT(array) & ~VT_ARRAY; } /* determine the bounds */ SafeArrayGetLBound(V_ARRAY(array), 1, &lbound); SafeArrayGetUBound(V_ARRAY(array), 1, &ubound); /* check bounds */ if (dim1 < lbound || dim1 > ubound) { php_com_throw_exception(DISP_E_BADINDEX, "index out of bounds"); return 0; } /* now fetch that element */ VariantInit(dest); indices[0] = dim1; if (vt == VT_VARIANT) { SafeArrayGetElement(V_ARRAY(array), indices, dest); } else { V_VT(dest) = vt; /* store the value into "lVal" member of the variant. * This works because it is a union; since we know the variant * type, we end up with a working variant */ SafeArrayGetElement(V_ARRAY(array), indices, &dest->lVal); } return 1; }
//============================================================================== // 2D array of ints, both dims unspecified int g_CheckVariantArray( int * pnDim1, int * pnDim2, VARIANT vMtx, int ** ppiMtx ){ SAFEARRAY * psaMtx; int nDims; long iDim; VARTYPE tSaType; psaMtx = vMtx.parray; *pnDim1 = 0; *pnDim2 = 0; if( vMtx.vt != (VT_ARRAY|VT_I4)){ CP_printf("\ng_CheckVariantArray(): wrong VARIANT type, expecting array of ints!\n"); return 1; } SafeArrayGetVartype( psaMtx, &tSaType ); if( tSaType != VT_I4 ){ CP_printf("\ng_CheckVariantArray(): wrong array type, expecting array of 4-byte integers!\n"); return 1; } nDims = SafeArrayGetDim( psaMtx ); if( nDims !=2 ) { CP_printf("\ng_CheckVariantArray(): wrong array dimensions\n" ); return 1; } SafeArrayGetLBound( psaMtx, 1, &iDim ); if( iDim != 0) { CP_printf("\ng_CheckVariantArray(): wrong array dimensions!\n" ); return 1; } SafeArrayGetLBound( psaMtx, 2, &iDim ); if( iDim != 0) { CP_printf("\ng_CheckVariantArray(): wrong array dimensions\n" ); return 1; } SafeArrayGetUBound( psaMtx, 1, &iDim ); iDim++; // we return the size, which is upperbound +1 * pnDim1 = iDim; SafeArrayGetUBound( psaMtx, 2, &iDim ); iDim++; // we return the size, which is upperbound +1 * pnDim2 = iDim; SafeArrayAccessData(psaMtx, (void **) ppiMtx); // Get data pointer return 0; }
JNIEXPORT void JNICALL Java_com_tangram_Variant_putVariantSafeArray(JNIEnv *env, jobject _this, jobject sa) { SAFEARRAY *psa = extractSA(env, sa); if (psa) { VARIANT *v = extractVariant(env, _this); if (v) { VARTYPE vt; SafeArrayGetVartype(psa, &vt); V_VT(v) = VT_ARRAY | vt; V_ARRAY(v) = copySA(psa); return; } ThrowComFail(env, "Can't get variant pointer", -1); return; } ThrowComFail(env, "Can't get sa pointer", -1); return; }
//============================================================================== // 2D array of doubles, second dim unspecified int g_CheckVariantArray( int nDim1, int * pnDim2, VARIANT vMtx, double ** ppdMtx ){ SAFEARRAY * psaMtx; int nDims; long iDim; VARTYPE tSaType; psaMtx = vMtx.parray; *pnDim2 = 0; SafeArrayGetVartype( psaMtx, &tSaType ); if( tSaType != VT_R8 ){ CP_printf("\ng_CheckVariantArray(): wrong array type, expecting array of doubles!\n"); return 1; } nDims = SafeArrayGetDim( psaMtx ); if( nDims !=2 ) { CP_printf("\ng_CheckVariantArray(): wrong number of dimensions, expecting 2D array!\n" ); return 1; } SafeArrayGetLBound( psaMtx, 1, &iDim ); if( iDim != 0) { CP_printf("\ng_CheckVariantArray(): wrong array dimensions, expecting %dxN array!\n", nDim1 ); return 1; } SafeArrayGetUBound( psaMtx, 1, &iDim ); if( iDim+1 != nDim1) { CP_printf("\ng_CheckVariantArray(): wrong array dimensions, expecting %dxN array!\n", nDim1 ); return 1; } SafeArrayGetLBound( psaMtx, 2, &iDim ); if( iDim != 0) { CP_printf("\ng_CheckVariantArray(): wrong array dimensions, expecting %dxN array!\n", nDim1 ); return 1; } SafeArrayGetUBound( psaMtx, 2, &iDim ); iDim++; // we return the size, which is upperbound +1 * pnDim2 = iDim; SafeArrayAccessData(psaMtx, (void **) ppdMtx); // Get data pointer return 0; }
static inline SF_TYPE SAFEARRAY_GetUnionType(SAFEARRAY *psa) { VARTYPE vt; HRESULT hr; hr = SafeArrayGetVartype(psa, &vt); if (FAILED(hr)) RpcRaiseException(hr); if (psa->fFeatures & FADF_HAVEIID) return SF_HAVEIID; switch (vt) { case VT_I1: case VT_UI1: return SF_I1; case VT_BOOL: case VT_I2: case VT_UI2: return SF_I2; case VT_INT: case VT_UINT: case VT_I4: case VT_UI4: case VT_R4: return SF_I4; case VT_DATE: case VT_CY: case VT_R8: case VT_I8: case VT_UI8: return SF_I8; case VT_INT_PTR: case VT_UINT_PTR: return (sizeof(UINT_PTR) == 4 ? SF_I4 : SF_I8); case VT_BSTR: return SF_BSTR; case VT_DISPATCH: return SF_DISPATCH; case VT_VARIANT: return SF_VARIANT; case VT_UNKNOWN: return SF_UNKNOWN; /* Note: Return a non-zero size to indicate vt is valid. The actual size * of a UDT is taken from the result of IRecordInfo_GetSize(). */ case VT_RECORD: return SF_RECORD; default: return SF_ERROR; } }
HRESULT _SetArrayHelper(VARTYPE expectedType, SAFEARRAY *vals, int *resultSize) { VARTYPE gotType; HRESULT hr = SafeArrayGetVartype(vals, &gotType); if (FAILED(hr)) { return hr; } if (gotType != expectedType) { return E_UNEXPECTED; } UINT cDims = SafeArrayGetDim(vals); *resultSize = 0; long ub=0, lb=0; if (cDims) { SafeArrayGetUBound(vals, 1, &ub); SafeArrayGetLBound(vals, 1, &lb); *resultSize = ub - lb + 1; } return S_OK; }
JNIEXPORT void JNICALL Java_com_tangram_Variant_putVariantSafeArrayRef(JNIEnv *env, jobject _this, jobject sa) { SAFEARRAY *psa = extractSA(env, sa); if (psa) { VARIANT *v = extractVariant(env, _this); if (v) { VARTYPE vt; SAFEARRAY **sa = (SAFEARRAY **)CoTaskMemAlloc(sizeof(SAFEARRAY*)); *sa = psa; SafeArrayGetVartype(psa, &vt); V_VT(v) = VT_ARRAY | vt | VT_BYREF; V_ARRAYREF(v) = sa; return; } ThrowComFail(env, "Can't get variant pointer", -1); return; } ThrowComFail(env, "Can't get sa pointer", -1); return; }
STDMETHODIMP Profile::put_ForwardingRules(SAFEARRAY * newVal) { try { VARTYPE vt = VT_UNKNOWN; SafeArrayGetVartype(newVal, & vt); UINT uiDim = SafeArrayGetDim(newVal); if((uiDim != 1) || (vt != VT_RECORD)) { return AtlReportError(GetObjectCLSID(), L"Array of rules must be single dimension array of strings", GUID_NULL, E_INVALIDARG); } HRESULT hr = SafeArrayLock(newVal); if(FAILED(hr)) { return AtlReportError(GetObjectCLSID(), L"Unable to lock array", GUID_NULL, E_FAIL); } wstring wstrItems; ForwardingRule * pItems = (ForwardingRule *) newVal->pvData; for(ULONG l = 0; l < newVal->rgsabound[0].cElements; l++) { WCHAR start[32], end[32]; _ltow_s(pItems[l].StartTime, start, sizeof(start)/sizeof(start[0]), 10); _ltow_s(pItems[l].EndTime, end, sizeof(end)/sizeof(end[0]), 10); if(l > 0) { wstrItems += L" "; } wstrItems += start; wstrItems += L","; wstrItems += end; wstrItems += L","; wstrItems += pItems[l].Handle; } SafeArrayUnlock(newVal); gSkypeQueue.SetProperty(L"PROFILE", L"", L"CALL_FORWARD_RULES", wstrItems.c_str()); return S_OK; } catch (const WCHAR * err) { return AtlReportError(GetObjectCLSID(), err, GUID_NULL, E_FAIL); } }
WXDLLEXPORT bool wxConvertVariantToOle(const wxVariant& variant, VARIANTARG& oleVariant) { VariantInit(&oleVariant); if (variant.IsNull()) { oleVariant.vt = VT_NULL; return true; } wxString type(variant.GetType()); if (type == wxT("errorcode")) { wxVariantDataErrorCode* const ec = wxStaticCastVariantData(variant.GetData(), wxVariantDataErrorCode); oleVariant.vt = VT_ERROR; oleVariant.scode = ec->GetValue(); } else if (type == wxT("currency")) { wxVariantDataCurrency* const c = wxStaticCastVariantData(variant.GetData(), wxVariantDataCurrency); oleVariant.vt = VT_CY; oleVariant.cyVal = c->GetValue(); } else if (type == wxT("safearray")) { wxVariantDataSafeArray* const vsa = wxStaticCastVariantData(variant.GetData(), wxVariantDataSafeArray); SAFEARRAY* psa = vsa->GetValue(); VARTYPE vt; wxCHECK(psa, false); HRESULT hr = SafeArrayGetVartype(psa, &vt); if ( FAILED(hr) ) { wxLogApiError(wxS("SafeArrayGetVartype()"), hr); SafeArrayDestroy(psa); return false; } oleVariant.vt = vt | VT_ARRAY; oleVariant.parray = psa; } else if (type == wxT("long")) { oleVariant.vt = VT_I4; oleVariant.lVal = variant.GetLong() ; } // Original VC6 came with SDK too old to contain VARIANT::llVal declaration // and there doesn't seem to be any way to test for it as Microsoft simply // added it to the later version of oaidl.h without changing anything else. // So assume it's not present for VC6, even though it might be if an // updated SDK is used. In this case the user would need to disable this // check himself. #if wxUSE_LONGLONG && !defined(__VISUALC6__) else if (type == wxT("longlong")) { oleVariant.vt = VT_I8; oleVariant.llVal = variant.GetLongLong().GetValue(); } #endif else if (type == wxT("char")) { oleVariant.vt=VT_I1; // Signed Char oleVariant.cVal=variant.GetChar(); } else if (type == wxT("double")) { oleVariant.vt = VT_R8; oleVariant.dblVal = variant.GetDouble(); } else if (type == wxT("bool")) { oleVariant.vt = VT_BOOL; oleVariant.boolVal = variant.GetBool() ? VARIANT_TRUE : VARIANT_FALSE; } else if (type == wxT("string")) { wxString str( variant.GetString() ); oleVariant.vt = VT_BSTR; oleVariant.bstrVal = wxConvertStringToOle(str); } #if wxUSE_DATETIME else if (type == wxT("datetime")) { wxDateTime date( variant.GetDateTime() ); oleVariant.vt = VT_DATE; SYSTEMTIME st; date.GetAsMSWSysTime(&st); SystemTimeToVariantTime(&st, &oleVariant.date); } #endif else if (type == wxT("void*")) { oleVariant.vt = VT_DISPATCH; oleVariant.pdispVal = (IDispatch*) variant.GetVoidPtr(); } else if (type == wxT("list")) { wxSafeArray<VT_VARIANT> safeArray; if (!safeArray.CreateFromListVariant(variant)) return false; oleVariant.vt = VT_VARIANT | VT_ARRAY; oleVariant.parray = safeArray.Detach(); } else if (type == wxT("arrstring")) { wxSafeArray<VT_BSTR> safeArray; if (!safeArray.CreateFromArrayString(variant.GetArrayString())) return false; oleVariant.vt = VT_BSTR | VT_ARRAY; oleVariant.parray = safeArray.Detach(); } else { oleVariant.vt = VT_NULL; return false; } return true; }
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; }
NDArray *roper::getData() { NDArray *pArray = NULL; VARIANT varData, varResult; short result; SAFEARRAY *pData; int dim; LONG lbound, ubound; size_t dims[ND_ARRAY_MAX_DIMS]; int nDims; VARTYPE varType; NDDataType_t dataType; int docDataType; NDArrayInfo arrayInfo; void HUGEP *pVarData; bool typeMismatch; const char *functionName = "getData"; VariantInit(&varData); VariantInit(&varResult); try { this->pDocFile->GetFrame(1, &varData); varResult = this->pDocFile->GetParam(DM_DATATYPE, &result); docDataType = varResult.lVal; pData = varData.parray; nDims = SafeArrayGetDim(pData); for (dim=0; dim<nDims; dim++) { SafeArrayGetLBound(pData, dim+1, &lbound); SafeArrayGetUBound(pData, dim+1, &ubound); dims[dim] = ubound - lbound + 1; } SafeArrayGetVartype(pData, &varType); typeMismatch = TRUE; switch (docDataType) { case X_BYTE: dataType = NDUInt8; typeMismatch = (varType != VT_UI1); break; case X_SHORT: dataType = NDInt16; typeMismatch = (varType != VT_I2); break; case X_UINT16: dataType = NDUInt16; typeMismatch = (varType != VT_I2); break; case X_LONG: dataType = NDInt32; typeMismatch = (varType != VT_I4); break; case X_ULONG: dataType = NDUInt32; typeMismatch = (varType != VT_I4); break; case X_FLOAT: dataType = NDFloat32; typeMismatch = (varType != VT_R4); break; case X_DOUBLE: dataType = NDFloat64; typeMismatch = (varType != VT_R8); break; default: asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, "%s:%s: unknown data type = %d\n", driverName, functionName, docDataType); return(NULL); } if (typeMismatch) { asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, "%s:%s: data type mismatch: docDataType=%d, varType=%d\n", driverName, functionName, docDataType, varType); return(NULL); } pArray = this->pNDArrayPool->alloc(nDims, dims, dataType, 0, NULL); pArray->getInfo(&arrayInfo); SafeArrayAccessData(pData, &pVarData); memcpy(pArray->pData, pVarData, arrayInfo.totalBytes); SafeArrayUnaccessData(pData); SafeArrayDestroy(pData); setIntegerParam(NDArraySize, arrayInfo.totalBytes); setIntegerParam(NDArraySizeX, (int)dims[0]); setIntegerParam(NDArraySizeY, (int)dims[1]); setIntegerParam(NDDataType, dataType); } catch(CException *pEx) { pEx->GetErrorMessage(this->errorMessage, sizeof(this->errorMessage)); asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, "%s:%s: exception = %s\n", driverName, functionName, this->errorMessage); pEx->Delete(); return(NULL); } return(pArray); }
static void saproxy_write_dimension(zend_object *object, zval *offset, zval *value) { php_com_saproxy *proxy = (php_com_saproxy*) object; UINT dims, i; HRESULT res; VARIANT v; if (V_VT(&proxy->obj->v) == VT_DISPATCH) { /* We do a prop-set using the first dimension as the property name, * all subsequent dimensions and offset as parameters, with value as * the final value */ zval *args = safe_emalloc(proxy->dimensions + 2, sizeof(zval), 0); for (i = 1; i < (UINT) proxy->dimensions; i++) { ZVAL_COPY_VALUE(&args[i-1], &proxy->indices[i]); } ZVAL_COPY_VALUE(&args[i-1], offset); ZVAL_COPY_VALUE(&args[i], value); convert_to_string(&proxy->indices[0]); VariantInit(&v); if (SUCCESS == php_com_do_invoke(proxy->obj, Z_STRVAL(proxy->indices[0]), Z_STRLEN(proxy->indices[0]), DISPATCH_PROPERTYPUT, &v, proxy->dimensions + 1, args, 0)) { VariantClear(&v); } efree(args); } else if (V_ISARRAY(&proxy->obj->v)) { LONG *indices; VARTYPE vt; dims = SafeArrayGetDim(V_ARRAY(&proxy->obj->v)); indices = safe_emalloc(dims, sizeof(LONG), 0); /* copy indices from proxy */ for (i = 0; i < dims; i++) { convert_to_long(&proxy->indices[i]); indices[i] = (LONG)Z_LVAL(proxy->indices[i]); } /* add user-supplied index */ convert_to_long(offset); indices[dims-1] = (LONG)Z_LVAL_P(offset); if (FAILED(SafeArrayGetVartype(V_ARRAY(&proxy->obj->v), &vt)) || vt == VT_EMPTY) { vt = V_VT(&proxy->obj->v) & ~VT_ARRAY; } VariantInit(&v); php_com_variant_from_zval(&v, value, proxy->obj->code_page); if (V_VT(&v) != vt) { VariantChangeType(&v, &v, 0, vt); } if (vt == VT_VARIANT) { res = SafeArrayPutElement(V_ARRAY(&proxy->obj->v), indices, &v); } else { res = SafeArrayPutElement(V_ARRAY(&proxy->obj->v), indices, &v.lVal); } efree(indices); VariantClear(&v); if (FAILED(res)) { php_com_throw_exception(res, NULL); } } else { php_com_throw_exception(E_NOTIMPL, "invalid write to com proxy object"); } }
int main() { CoInitializeEx(0, COINIT_MULTITHREADED); HRESULT hr = S_OK; //GUID guid; //hr = CLSIDFromString(L"MyNamespace.MyClass", &guid); //hr = CLSIDFromString(L"{7884998B-0504-4CBE-9FF9-6BBAA9776188}", &guid); //hr = CoCreateInstance(guid, NULL, CLSCTX_ALL, IID_IUnknown, reinterpret_cast<void**>(&p)); NetCom::IMyClassPtr ptr; hr = ptr.CreateInstance(__uuidof(NetCom::Class1)); long l; hr = ptr->GetData(&l); SAFEARRAY *ppData = NULL; hr = ptr->GetStructs(&ppData); if (SUCCEEDED(hr) && ppData) { #pragma region Validate received datatype VARTYPE vt; hr = SafeArrayGetVartype(ppData, &vt); if (SUCCEEDED(hr) && (vt != VT_RECORD)) { //Not a sturcture hr = E_POINTER; } if (SUCCEEDED(hr)) { IRecordInfoPtr spIRecordInfo = NULL; hr = SafeArrayGetRecordInfo(ppData, &spIRecordInfo); if (SUCCEEDED(hr) && spIRecordInfo) { GUID guid; hr = spIRecordInfo->GetGuid(&guid); if (guid != __uuidof(NetCom::TICKSTRUCT)) { //Invalid record type hr = E_POINTER; } } } #pragma endregion NetCom::TICKSTRUCT *pVals = NULL; hr = SafeArrayAccessData(ppData, (void**)&pVals); if (SUCCEEDED(hr)) { long lowerBound, upperBound; // get array bounds SafeArrayGetLBound(ppData, 1, &lowerBound); SafeArrayGetUBound(ppData, 1, &upperBound); long count = upperBound - lowerBound + 1; for (int i = 0; i < count; ++i) // iterate through returned values { printf("[%d] Date: %f Price: %f Volume: %d\n", i, pVals->Date, pVals->Price, pVals->Volume); pVals++; } hr = SafeArrayUnaccessData(ppData); } hr = SafeArrayDestroy(ppData); } //Control safearray lifetime by _variant_t wrapper _variant_t vt; if (SUCCEEDED(ptr->GetStructs(&vt.parray))) { vt.vt = VT_ARRAY | VT_RECORD; SAFEARRAY* ppData2 = vt.parray; //ppData2 can be used in same way as ppData above with exception: //1. Do not call SafeArrayDestroy. array will be destroyed by VariantClear function //2. Make sure ppData2 is not locked (SafeArrayAccessData) before vt.Clear or ~vt will be called. // In this case VariantClear will not able to clean locked data } return 0; }
static zval *saproxy_read_dimension(zend_object *object, zval *offset, int type, zval *rv) { php_com_saproxy *proxy = (php_com_saproxy*) object; UINT dims, i; SAFEARRAY *sa; LONG ubound, lbound; HRESULT res; ZVAL_NULL(rv); if (V_VT(&proxy->obj->v) == VT_DISPATCH) { VARIANT v; zval *args; /* prop-get using first dimension as the property name, * all subsequent dimensions and the offset as parameters */ args = safe_emalloc(proxy->dimensions + 1, sizeof(zval), 0); for (i = 1; i < (UINT) proxy->dimensions; i++) { args[i-1] = proxy->indices[i]; } ZVAL_COPY_VALUE(&args[i-1], offset); convert_to_string(&proxy->indices[0]); VariantInit(&v); res = php_com_do_invoke(proxy->obj, Z_STRVAL(proxy->indices[0]), Z_STRLEN(proxy->indices[0]), DISPATCH_METHOD|DISPATCH_PROPERTYGET, &v, proxy->dimensions, args, 0); if (res == SUCCESS) { php_com_zval_from_variant(rv, &v, proxy->obj->code_page); VariantClear(&v); } else if (res == DISP_E_BADPARAMCOUNT) { /* return another proxy */ php_com_saproxy_create(object, rv, offset); } return rv; } else if (!V_ISARRAY(&proxy->obj->v)) { php_com_throw_exception(E_INVALIDARG, "invalid read from com proxy object"); return rv; } /* the SafeArray case */ /* offset/index must be an integer */ convert_to_long(offset); sa = V_ARRAY(&proxy->obj->v); dims = SafeArrayGetDim(sa); if ((UINT) proxy->dimensions >= dims) { /* too many dimensions */ php_com_throw_exception(E_INVALIDARG, "too many dimensions!"); return rv; } /* bounds check */ SafeArrayGetLBound(sa, proxy->dimensions, &lbound); SafeArrayGetUBound(sa, proxy->dimensions, &ubound); if (Z_LVAL_P(offset) < lbound || Z_LVAL_P(offset) > ubound) { php_com_throw_exception(DISP_E_BADINDEX, "index out of bounds"); return rv; } if (dims - 1 == proxy->dimensions) { LONG *indices; VARTYPE vt; VARIANT v; VariantInit(&v); /* we can return a real value */ indices = safe_emalloc(dims, sizeof(LONG), 0); /* copy indices from proxy */ for (i = 0; i < dims; i++) { convert_to_long(&proxy->indices[i]); indices[i] = (LONG)Z_LVAL(proxy->indices[i]); } /* add user-supplied index */ indices[dims-1] = (LONG)Z_LVAL_P(offset); /* now fetch the value */ if (FAILED(SafeArrayGetVartype(sa, &vt)) || vt == VT_EMPTY) { vt = V_VT(&proxy->obj->v) & ~VT_ARRAY; } if (vt == VT_VARIANT) { res = SafeArrayGetElement(sa, indices, &v); } else { V_VT(&v) = vt; res = SafeArrayGetElement(sa, indices, &v.lVal); } efree(indices); if (SUCCEEDED(res)) { php_com_wrap_variant(rv, &v, proxy->obj->code_page); } else { php_com_throw_exception(res, NULL); } VariantClear(&v); } else { /* return another proxy */ php_com_saproxy_create(object, rv, offset); } return rv; }
/*! * @brief Convert a variant type to a string and write it to the given buffer. * @param v The variant to convert. * @param buffer Pointer to the buffer to write the value to. * @param bufferSize size of the buffer. * @returns Pointer to the next location in the buffer. * @remarks This attempts to "flatten" a variant, including array types. The implementation is * not 100% complete, but is good enough for the sake of this requirement. Only arrays * of BSTR are currenty supported, more types can be added later if needed. Arbitrary * array depth has been attempted, but no tests have yet found a nested array in the * result set. There's probably bugs in that bit. */ char* variant_to_string(_variant_t& v, char* buffer, DWORD bufferSize) { dprintf("[WMI] preparing to parse variant of type %u (%x), buffer size %u", v.vt, v.vt, bufferSize); switch (v.vt) { case VT_EMPTY: strncpy_s(buffer, bufferSize, "(EMPTY)", bufferSize - 1); break; case VT_NULL: strncpy_s(buffer, bufferSize, "(NULL)", bufferSize - 1); break; case VT_BOOL: strncpy_s(buffer, bufferSize, v.boolVal == VARIANT_TRUE ? "true" : "false", bufferSize - 1); break; case VT_I1: _snprintf_s(buffer, bufferSize, bufferSize - 1, "%"PRId8, (CHAR)v); break; case VT_I2: _snprintf_s(buffer, bufferSize, bufferSize - 1, "%"PRId16, (SHORT)v); break; case VT_INT: case VT_I4: _snprintf_s(buffer, bufferSize, bufferSize - 1, "%"PRId32, (INT)v); break; case VT_INT_PTR: case VT_I8: _snprintf_s(buffer, bufferSize, bufferSize - 1, "%"PRId64, (INT_PTR)v); break; case VT_UI1: _snprintf_s(buffer, bufferSize, bufferSize - 1, "%"PRIu8, (BYTE)v); break; case VT_UI2: _snprintf_s(buffer, bufferSize, bufferSize - 1, "%"PRIu16, (SHORT)v); break; case VT_UINT: case VT_UI4: _snprintf_s(buffer, bufferSize, bufferSize - 1, "%"PRIu32, (UINT)v); break; case VT_UINT_PTR: case VT_UI8: _snprintf_s(buffer, bufferSize, bufferSize - 1, "%"PRIu64, (UINT_PTR)v); break; case VT_BSTR: case VT_LPSTR: case VT_LPWSTR: // not sure if this is correct strncpy_s(buffer, bufferSize, (char*)(_bstr_t)v.bstrVal, bufferSize - 1); break; // TODO more types, such as floats, dates, etc. default: if ((v.vt & VT_ARRAY) == VT_ARRAY) { // nested array type, great. dprintf("[WMI] array type found!"); LPSAFEARRAY array = v.parray; HRESULT hResult; if (FAILED(hResult = SafeArrayLock(array))) { dprintf("[WMI] Failed to get array dimension: %x", hResult); break; } dprintf("[WMI] Field name array locked."); LONG* indices = NULL; LONG* bounds = NULL; do { VARTYPE varType; SafeArrayGetVartype(array, &varType); dprintf("[WMI] Array type %u (%x)", (ULONG)varType, (ULONG)varType); dprintf("[WMI] Array dimensions: %u", SafeArrayGetDim(array)); LONG iterations = 1; LONG dim = SafeArrayGetDim(array); indices = (LONG*)malloc(dim * sizeof(LONG)); bounds = (LONG*)malloc(dim * sizeof(LONG) * 2); memset(indices, 0, dim * sizeof(LONG)); memset(bounds, 0, dim * sizeof(LONG) * 2); for (LONG i = 0; i < dim; ++i) { LONG* lBound = bounds + i * 2; LONG* uBound = lBound + 1; if (FAILED(hResult = SafeArrayGetLBound(array, i + 1, lBound)) || FAILED(hResult = SafeArrayGetUBound(array, i + 1, uBound))) { dprintf("[WMI] Failed to get array dimensions: %x", hResult); break; } dprintf("[WMI] Array bounds: %u to %u", *lBound, *uBound); iterations *= *uBound - *lBound; indices[i] = *lBound; } dprintf("[WMI] Array requires %u iterations", iterations); // we're going to wrap our array elements in brackets, and separate with pipes // because we need some kind of array visualisation and this is the best I could // come up with at this time of night. Each dimension nests in a new set of brackets while (iterations-- > 0) { for (LONG i = 0; i < dim; ++i) { if (indices[i] == 0) { // save space for the closing bracket as well bufferSize -= 2; *buffer++ = '{'; dprintf("[WMI] opening bracket for dimension %u", i); } else if(*(buffer - 1) != '|') { --bufferSize; *buffer++ = '|'; } } dprintf("[WMI] extracting value for iteration %u", iterations); switch (varType) { case VT_BSTR: BSTR val; if (SUCCEEDED(SafeArrayGetElement(array, indices, (void*)&val))) { dprintf("[WMI] Value extracted for iteration %u", iterations); char* newBuf = variant_to_string(_variant_t(val), buffer, bufferSize); bufferSize -= (LONG)(newBuf - buffer + 1); buffer = newBuf; dprintf("[WMI] Value added", iterations); } break; default: dprintf("[WMI] Unsupported nested array type %u", (LONG)varType); break; } ++indices[dim - 1]; for (LONG i = dim - 1; i >= 0; --i) { if (indices[i] == bounds[i * 2 + 1]) { dprintf("[WMI] closing bracket for dimension %u", i); *buffer++ = '}'; indices[i] = bounds[i * 2]; if (i > 0) { ++indices[i - 1]; } } } } } while (0); if (indices) { free(indices); } if (bounds) { free(bounds); } SafeArrayUnlock(array); } else { dprintf("[WMI] Unhandled type: %u (%x)", v.vt, v.vt); } // ignore the buffer for other types break; } // return wherever we go to. return buffer + strlen(buffer); }
STDMETHODIMP CGraphElement::Plot(VARIANT newXVals, VARIANT newYVals) { LONG lXBound, uXBound, lYBound, uYBound; SAFEARRAY* psaXVals, *psaYVals; HRESULT hr; //usually from VBScript the arrays are coming packed in by ref variants hr = GetArrayFromVariant(&newXVals, &psaXVals); if(FAILED(hr)) { return hr; } hr = GetArrayFromVariant(&newYVals, &psaYVals); if(FAILED(hr)) { return hr; } hr = SafeArrayGetLBound(psaXVals, 1, &lXBound); if(FAILED(hr)) { return hr; } hr = SafeArrayGetUBound(psaYVals, 1, &uXBound); if(FAILED(hr)) { return hr; } hr = SafeArrayGetLBound(psaXVals, 1, &lYBound); if(FAILED(hr)) { return hr; } hr = SafeArrayGetUBound(psaYVals, 1, &uYBound); if(FAILED(hr)) { return hr; } if(uXBound - lXBound != uYBound - lYBound) { return AtlReportError(GUID_NULL, L"Array with same size expected", IID_NULL, E_INVALIDARG); } int i, nCount; min = max = CElementPoint(0,0); nCount = m_PointList.GetSize(); EnterCriticalSection(&m_CritSectionForPlot); m_PointList.RemoveAll(); LeaveCriticalSection(&m_CritSectionForPlot); if(m_pCtrl && nCount) { m_pCtrl->OnPlotDeleted(); //current element does not have any points anymore } nCount = uXBound - lXBound + 1; VARTYPE typeX, typeY; SafeArrayGetVartype(psaXVals, &typeX); SafeArrayGetVartype(psaYVals, &typeY); for(i=0; i< nCount; i++) { double x ,y; hr = GetDoubleElement(typeX, psaXVals, i, &x); if(FAILED(hr)) { break; } hr = GetDoubleElement(typeY, psaYVals, i, &y); if(FAILED(hr)) { break; } CElementPoint point(x, y); m_PointList.Add(point); if(min.x > point.x) { min.x = point.x ; } if(min.y > point.y) { min.y = point.y ; } if(max.x < point.x) { max.x = point.x ; } if(max.y < point.y) { max.y = point.y ; } if(m_pCtrl) { m_pCtrl->UpdateAutoRange(x, y, i == 0); //TRUE only for first added point } } if(m_pCtrl) //redraw once for all added points { m_pCtrl->Refresh(FALSE); } return hr; }
static void test_registry(void) { static const WCHAR keypathW[] = {'H','K','E','Y','_','C','U','R','R','E','N','T','_','U','S','E','R','\\', 'S','o','f','t','w','a','r','e','\\','W','i','n','e','\\','T','e','s','t','\\',0}; static const WCHAR regsz2W[] = {'r','e','g','s','z','2',0}; static const WCHAR regszW[] = {'r','e','g','s','z',0}; static const WCHAR regdwordW[] = {'r','e','g','d','w','o','r','d',0}; static const WCHAR regbinaryW[] = {'r','e','g','b','i','n','a','r','y',0}; static const WCHAR regmultiszW[] = {'r','e','g','m','u','l','t','i','s','z',0}; static const WCHAR regsz1W[] = {'H','K','E','Y','_','C','U','R','R','E','N','T','_','U','S','E','R','\\', 'S','o','f','t','w','a','r','e','\\','W','i','n','e','\\','T','e','s','t','\\','r','e','g','s','z','1',0}; static const WCHAR foobarW[] = {'f','o','o','b','a','r',0}; static const WCHAR fooW[] = {'f','o','o',0}; static const WCHAR brokenW[] = {'H','K','E','Y','_','b','r','o','k','e','n','_','k','e','y',0}; static const WCHAR broken2W[] = {'H','K','E','Y','_','C','U','R','R','E','N','T','_','U','S','E','R','a',0}; WCHAR pathW[MAX_PATH]; DWORD dwvalue, type; VARIANT value, v; IWshShell3 *sh3; VARTYPE vartype; LONG bound; HRESULT hr; BSTR name; HKEY root; LONG ret; UINT dim; hr = CoCreateInstance(&CLSID_WshShell, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER, &IID_IWshShell3, (void**)&sh3); ok(hr == S_OK, "got 0x%08x\n", hr); /* RegRead() */ V_VT(&value) = VT_I2; hr = IWshShell3_RegRead(sh3, NULL, &value); ok(hr == E_POINTER, "got 0x%08x\n", hr); ok(V_VT(&value) == VT_I2, "got %d\n", V_VT(&value)); name = SysAllocString(brokenW); hr = IWshShell3_RegRead(sh3, name, NULL); ok(hr == E_POINTER, "got 0x%08x\n", hr); V_VT(&value) = VT_I2; hr = IWshShell3_RegRead(sh3, name, &value); ok(hr == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND), "got 0x%08x\n", hr); ok(V_VT(&value) == VT_I2, "got %d\n", V_VT(&value)); SysFreeString(name); name = SysAllocString(broken2W); V_VT(&value) = VT_I2; hr = IWshShell3_RegRead(sh3, name, &value); ok(hr == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND), "got 0x%08x\n", hr); ok(V_VT(&value) == VT_I2, "got %d\n", V_VT(&value)); SysFreeString(name); ret = RegCreateKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Test", &root); ok(ret == 0, "got %d\n", ret); ret = RegSetValueExA(root, "regsz", 0, REG_SZ, (const BYTE*)"foobar", 7); ok(ret == 0, "got %d\n", ret); ret = RegSetValueExA(root, "regsz2", 0, REG_SZ, (const BYTE*)"foobar\0f", 9); ok(ret == 0, "got %d\n", ret); ret = RegSetValueExA(root, "regmultisz", 0, REG_MULTI_SZ, (const BYTE*)"foo\0bar\0", 9); ok(ret == 0, "got %d\n", ret); dwvalue = 10; ret = RegSetValueExA(root, "regdword", 0, REG_DWORD, (const BYTE*)&dwvalue, sizeof(dwvalue)); ok(ret == 0, "got %d\n", ret); dwvalue = 11; ret = RegSetValueExA(root, "regbinary", 0, REG_BINARY, (const BYTE*)&dwvalue, sizeof(dwvalue)); ok(ret == 0, "got %d\n", ret); /* REG_SZ */ lstrcpyW(pathW, keypathW); lstrcatW(pathW, regszW); name = SysAllocString(pathW); VariantInit(&value); hr = IWshShell3_RegRead(sh3, name, &value); ok(hr == S_OK, "got 0x%08x\n", hr); ok(V_VT(&value) == VT_BSTR, "got %d\n", V_VT(&value)); ok(!lstrcmpW(V_BSTR(&value), foobarW), "got %s\n", wine_dbgstr_w(V_BSTR(&value))); VariantClear(&value); SysFreeString(name); /* REG_SZ with embedded NULL */ lstrcpyW(pathW, keypathW); lstrcatW(pathW, regsz2W); name = SysAllocString(pathW); VariantInit(&value); hr = IWshShell3_RegRead(sh3, name, &value); ok(hr == S_OK, "got 0x%08x\n", hr); ok(V_VT(&value) == VT_BSTR, "got %d\n", V_VT(&value)); ok(SysStringLen(V_BSTR(&value)) == 6, "len %d\n", SysStringLen(V_BSTR(&value))); VariantClear(&value); SysFreeString(name); /* REG_DWORD */ lstrcpyW(pathW, keypathW); lstrcatW(pathW, regdwordW); name = SysAllocString(pathW); VariantInit(&value); hr = IWshShell3_RegRead(sh3, name, &value); ok(hr == S_OK, "got 0x%08x\n", hr); ok(V_VT(&value) == VT_I4, "got %d\n", V_VT(&value)); ok(V_I4(&value) == 10, "got %d\n", V_I4(&value)); SysFreeString(name); /* REG_BINARY */ lstrcpyW(pathW, keypathW); lstrcatW(pathW, regbinaryW); name = SysAllocString(pathW); VariantInit(&value); hr = IWshShell3_RegRead(sh3, name, &value); ok(hr == S_OK, "got 0x%08x\n", hr); ok(V_VT(&value) == (VT_ARRAY|VT_VARIANT), "got 0x%x\n", V_VT(&value)); dim = SafeArrayGetDim(V_ARRAY(&value)); ok(dim == 1, "got %u\n", dim); hr = SafeArrayGetLBound(V_ARRAY(&value), 1, &bound); ok(hr == S_OK, "got 0x%08x\n", hr); ok(bound == 0, "got %u\n", bound); hr = SafeArrayGetUBound(V_ARRAY(&value), 1, &bound); ok(hr == S_OK, "got 0x%08x\n", hr); ok(bound == 3, "got %u\n", bound); hr = SafeArrayGetVartype(V_ARRAY(&value), &vartype); ok(hr == S_OK, "got 0x%08x\n", hr); ok(vartype == VT_VARIANT, "got %d\n", vartype); bound = 0; hr = SafeArrayGetElement(V_ARRAY(&value), &bound, &v); ok(hr == S_OK, "got 0x%08x\n", hr); ok(V_VT(&v) == VT_UI1, "got %d\n", V_VT(&v)); ok(V_UI1(&v) == 11, "got %u\n", V_UI1(&v)); VariantClear(&v); VariantClear(&value); SysFreeString(name); /* REG_MULTI_SZ */ lstrcpyW(pathW, keypathW); lstrcatW(pathW, regmultiszW); name = SysAllocString(pathW); VariantInit(&value); hr = IWshShell3_RegRead(sh3, name, &value); ok(hr == S_OK, "got 0x%08x\n", hr); ok(V_VT(&value) == (VT_ARRAY|VT_VARIANT), "got 0x%x\n", V_VT(&value)); SysFreeString(name); dim = SafeArrayGetDim(V_ARRAY(&value)); ok(dim == 1, "got %u\n", dim); hr = SafeArrayGetLBound(V_ARRAY(&value), 1, &bound); ok(hr == S_OK, "got 0x%08x\n", hr); ok(bound == 0, "got %u\n", bound); hr = SafeArrayGetUBound(V_ARRAY(&value), 1, &bound); ok(hr == S_OK, "got 0x%08x\n", hr); ok(bound == 1, "got %u\n", bound); hr = SafeArrayGetVartype(V_ARRAY(&value), &vartype); ok(hr == S_OK, "got 0x%08x\n", hr); ok(vartype == VT_VARIANT, "got %d\n", vartype); bound = 0; hr = SafeArrayGetElement(V_ARRAY(&value), &bound, &v); ok(hr == S_OK, "got 0x%08x\n", hr); ok(V_VT(&v) == VT_BSTR, "got %d\n", V_VT(&v)); ok(!lstrcmpW(V_BSTR(&v), fooW), "got %s\n", wine_dbgstr_w(V_BSTR(&v))); VariantClear(&v); VariantClear(&value); name = SysAllocString(regsz1W); V_VT(&value) = VT_I2; hr = IWshShell3_RegRead(sh3, name, &value); ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "got 0x%08x\n", hr); ok(V_VT(&value) == VT_I2, "got %d\n", V_VT(&value)); VariantClear(&value); SysFreeString(name); delete_key(root); /* RegWrite() */ ret = RegCreateKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Test", &root); ok(ret == 0, "got %d\n", ret); hr = IWshShell3_RegWrite(sh3, NULL, NULL, NULL); ok(hr == E_POINTER, "got 0x%08x\n", hr); lstrcpyW(pathW, keypathW); lstrcatW(pathW, regszW); name = SysAllocString(pathW); hr = IWshShell3_RegWrite(sh3, name, NULL, NULL); ok(hr == E_POINTER, "got 0x%08x\n", hr); VariantInit(&value); hr = IWshShell3_RegWrite(sh3, name, &value, NULL); ok(hr == E_POINTER, "got 0x%08x\n", hr); hr = IWshShell3_RegWrite(sh3, name, &value, &value); ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); /* type is optional */ V_VT(&v) = VT_ERROR; V_ERROR(&v) = DISP_E_PARAMNOTFOUND; hr = IWshShell3_RegWrite(sh3, name, &value, &v); ok(hr == S_OK, "got 0x%08x\n", hr); /* default type is REG_SZ */ V_VT(&value) = VT_I4; V_I4(&value) = 12; hr = IWshShell3_RegWrite(sh3, name, &value, &v); ok(hr == S_OK, "got 0x%08x\n", hr); type = REG_NONE; ret = RegGetValueA(root, NULL, "regsz", RRF_RT_ANY, &type, NULL, NULL); ok(ret == ERROR_SUCCESS, "got %d\n", ret); ok(type == REG_SZ, "got %d\n", type); ret = RegDeleteValueA(root, "regsz"); ok(ret == ERROR_SUCCESS, "got %d\n", ret); V_VT(&value) = VT_BSTR; V_BSTR(&value) = SysAllocString(regszW); hr = IWshShell3_RegWrite(sh3, name, &value, &v); ok(hr == S_OK, "got 0x%08x\n", hr); VariantClear(&value); type = REG_NONE; ret = RegGetValueA(root, NULL, "regsz", RRF_RT_ANY, &type, NULL, NULL); ok(ret == ERROR_SUCCESS, "got %d\n", ret); ok(type == REG_SZ, "got %d\n", type); ret = RegDeleteValueA(root, "regsz"); ok(ret == ERROR_SUCCESS, "got %d\n", ret); V_VT(&value) = VT_R4; V_R4(&value) = 1.2; hr = IWshShell3_RegWrite(sh3, name, &value, &v); ok(hr == S_OK, "got 0x%08x\n", hr); VariantClear(&value); type = REG_NONE; ret = RegGetValueA(root, NULL, "regsz", RRF_RT_ANY, &type, NULL, NULL); ok(ret == ERROR_SUCCESS, "got %d\n", ret); ok(type == REG_SZ, "got %d\n", type); ret = RegDeleteValueA(root, "regsz"); ok(ret == ERROR_SUCCESS, "got %d\n", ret); V_VT(&value) = VT_R4; V_R4(&value) = 1.2; V_VT(&v) = VT_I2; V_I2(&v) = 1; hr = IWshShell3_RegWrite(sh3, name, &value, &v); ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); VariantClear(&value); SysFreeString(name); delete_key(root); IWshShell3_Release(sh3); }
int __declspec(dllexport) __stdcall vbSafeArrayToPtr( VARIANT *vArray, GDALDataType *peDataType, int *pnXSize, int *pnYSize ) { char **papszResult = NULL; SAFEARRAY *psSA; long nLBound, nUBound; VARTYPE eVartype; /* -------------------------------------------------------------------- */ /* Get and verify info about safe array. */ /* -------------------------------------------------------------------- */ if( vArray == NULL ) { CPLError( CE_Failure, CPLE_AppDefined, "VARIANT is NULL in SafeArrayToPtr()." ); return NULL; } if( (vArray->vt & (VT_ARRAY | VT_BYREF)) == (VT_ARRAY | VT_BYREF) ) psSA = *(vArray->pparray); else if( (vArray->vt & VT_ARRAY) == VT_ARRAY ) psSA = vArray->parray; else { CPLError( CE_Failure, CPLE_AppDefined, "VARIANT is wrong type (%x).", vArray->vt ); return NULL; } if( SafeArrayGetDim(psSA) < 1 || SafeArrayGetDim(psSA) > 2 ) { CPLError( CE_Failure, CPLE_AppDefined, "Wrong dimension in array (%d)", SafeArrayGetDim(psSA) ); return NULL; } /* -------------------------------------------------------------------- */ /* Get XSize */ /* -------------------------------------------------------------------- */ if( FAILED(SafeArrayGetLBound( psSA, 1, &nLBound )) || FAILED(SafeArrayGetUBound( psSA, 1, &nUBound)) ) { CPLError( CE_Failure, CPLE_AppDefined, "SafeARrayGet{L,U}Bound() failed." ); return NULL; } if( nUBound <= nLBound ) { CPLError( CE_Failure, CPLE_AppDefined, "Crazy L/U Bound (L=%d, U=%d)", nLBound, nUBound ); return NULL; } *pnXSize = nUBound - nLBound + 1; /* -------------------------------------------------------------------- */ /* Get YSize */ /* -------------------------------------------------------------------- */ if( SafeArrayGetDim(psSA) == 1 ) *pnYSize = 1; else { if( FAILED(SafeArrayGetLBound( psSA, 1, &nLBound )) || FAILED(SafeArrayGetUBound( psSA, 1, &nUBound)) ) { CPLError( CE_Failure, CPLE_AppDefined, "SafeARrayGet{L,U}Bound() failed." ); return NULL; } if( nUBound <= nLBound ) { CPLError( CE_Failure, CPLE_AppDefined, "Crazy L/U Bound (L=%d, U=%d)", nLBound, nUBound ); return NULL; } *pnYSize = nUBound - nLBound + 1; } /* -------------------------------------------------------------------- */ /* Translate the type. */ /* -------------------------------------------------------------------- */ SafeArrayGetVartype(psSA, &eVartype ); if( eVartype == VT_UI1 ) *peDataType = GDT_Byte; else if( eVartype == VT_UI2 ) *peDataType = GDT_UInt16; else if( eVartype == VT_I2 ) *peDataType = GDT_Int16; else if( eVartype == VT_I4 || eVartype == VT_INT ) *peDataType = GDT_Int32; else if( eVartype == VT_UI4 || eVartype == VT_UINT ) *peDataType = GDT_UInt32; else if( eVartype == VT_R4 ) *peDataType = GDT_Float32; else if( eVartype == VT_R8 ) *peDataType = GDT_Float64; else { CPLError( CE_Failure, CPLE_AppDefined, "SafeArray contains type %d which is not supported.", eVartype ); return NULL; } /* -------------------------------------------------------------------- */ /* Return the raw data pointer cast to an int. */ /* -------------------------------------------------------------------- */ return (int) psSA->pvData; }
char __declspec(dllexport) ** __stdcall vbVariantToCSL( VARIANT *vList ) { char **papszResult = NULL; SAFEARRAY *psSA; long nLBound, nUBound; VARTYPE eVartype; /* -------------------------------------------------------------------- */ /* Get and verify info about safe array. */ /* -------------------------------------------------------------------- */ if( vList == NULL ) { CPLError( CE_Failure, CPLE_AppDefined, "VARIANT is NULL in VariantToCSL()." ); return NULL; } if( vList->vt == (VT_BSTR | VT_ARRAY | VT_BYREF) ) psSA = *(vList->pparray); else if( vList->vt == (VT_BSTR | VT_ARRAY) ) psSA = vList->parray; else { CPLError( CE_Failure, CPLE_AppDefined, "VARIANT is wrong type (%x).", vList->vt ); return NULL; } if( SafeArrayGetDim(psSA) != 1 ) { CPLError( CE_Failure, CPLE_AppDefined, "Wrong dimension in array (%d)", SafeArrayGetDim(psSA) ); return NULL; } if( FAILED(SafeArrayGetLBound( psSA, 1, &nLBound )) || FAILED(SafeArrayGetUBound( psSA, 1, &nUBound)) ) { CPLError( CE_Failure, CPLE_AppDefined, "SafeARrayGet{L,U}Bound() failed." ); return NULL; } if( nUBound < nLBound ) { CPLError( CE_Failure, CPLE_AppDefined, "Crazy L/U Bound (L=%d, U=%d)", nLBound, nUBound ); return NULL; } SafeArrayGetVartype(psSA, &eVartype ); if( eVartype != VT_BSTR ) { CPLError( CE_Failure, CPLE_AppDefined, "SafeArray contains type %d instead of VT_BSTR.", eVartype ); return NULL; } /* -------------------------------------------------------------------- */ /* Create string list from safe array BSTRings. */ /* -------------------------------------------------------------------- */ papszResult = (char **) CPLCalloc(sizeof(char *),(nUBound-nLBound+2)); for( long iElement = nLBound; iElement <= nUBound; iElement++ ) { BSTR bstrValue; char szValue[5000]; if( FAILED(SafeArrayGetElement(psSA, &iElement, &bstrValue)) ) { CPLError( CE_Failure, CPLE_AppDefined, "SafeArrayGetElement(%d) failed.", iElement ); CSLDestroy( papszResult ); return NULL; } sprintf( szValue, "%S", bstrValue ); papszResult[iElement - nLBound] = CPLStrdup( szValue ); } return papszResult; }
static int cmdfunc_ctrlcmd( int cmd ) { // cmdfunc : TYPE_DLLCTRL // (拡張DLLコントロールコマンド) // code_next(); // 次のコードを取得(最初に必ず必要です) if ( cmd >= TYPE_OFFSET_COMOBJ ) { #ifdef HSP_COM_UNSUPPORTED throw ( HSPERR_UNSUPPORTED_FUNCTION ); #else // COM インターフェースメソッドの呼び出し STRUCTDAT *st; st = GetPRM( cmd - TYPE_OFFSET_COMOBJ ); hspctx->stat = code_expand_and_call( st ); return RUNMODE_RUN; #endif } switch( cmd ) { // サブコマンドごとの分岐 case 0x00: // newcom #ifdef HSP_COM_UNSUPPORTED throw ( HSPERR_UNSUPPORTED_FUNCTION ); #else { PVal *pval; APTR aptr; IUnknown **ppunkNew, *punkDef; CLSID clsid; char *clsid_name; const IID *piid, *piid2; void *iptr; LIBDAT *lib; STRUCTDAT *st; int inimode; // 第1パラメータ:新しいインターフェースポインタを格納する変数 // (変数にNULLポインタを格納) aptr = code_getva( &pval ); iptr = NULL; code_setva( pval, aptr, TYPE_COMOBJ, &iptr ); ppunkNew = (IUnknown **)HspVarCorePtrAPTR( pval, aptr ); // CLSID / IID 情報を取得 if ( !code_getexflg() && *type == TYPE_DLLCTRL ) { // 第2パラメータ:#usecom 登録情報 st = code_getcomst(); if ( st->otindex != -1 ) throw HSPERR_TYPE_MISMATCH; lib = &hspctx->mem_linfo[ st->index ]; if ( lib->clsid == -1 ) throw HSPERR_INVALID_PARAMETER; clsid_name = strp(lib->clsid); piid = (IID *)strp( lib->nameidx ); piid2 = NULL; } else { // 第2パラメータ:文字列 CLSID // (IID はデフォルトで IID_IDispatch, サポートされていなければ IID_IUnknown ) clsid_name = code_getds(""); piid = &IID_IDispatch; piid2 = &IID_IUnknown; } inimode = code_getdi(0); // 初期化モード punkDef = (IUnknown *)code_getdi(0); // デフォルトオブジェクト // 新規CLSIDからインスタンスを作成 hspctx->stat = 0; switch ( inimode ) { case 0: // 新規にロード if ( clsid_name[0]!='\0' ) { if ( GetIIDFromString(&clsid,clsid_name,true) != FALSE && SUCCEEDED( CoCreateInstance( clsid, NULL, CLSCTX_SERVER, *piid, (void**)ppunkNew )) && *ppunkNew != NULL ) { break; } if ( piid2 != NULL && SUCCEEDED( CoCreateInstance( clsid, NULL, CLSCTX_SERVER, *piid2, (void**)ppunkNew )) && *ppunkNew != NULL ) { break; } hspctx->stat = 1; } break; case -2: // オブジェクトを明示的に指定する場合 ( AddRef() あり) if ( punkDef != NULL ) punkDef->AddRef(); case -1: // オブジェクトを明示的に指定する場合 ( AddRef() なし) *ppunkNew = punkDef; break; default: throw HSPERR_UNSUPPORTED_FUNCTION; } #ifdef HSP_COMOBJ_DEBUG COM_DBG_MSG( "newcom : pObj=%p : &pObj=%p\n", *ppunkNew, ppunkNew); #endif break; } #endif // HSP_COM_UNSUPPORTED case 0x01: // querycom #ifdef HSP_COM_UNSUPPORTED throw HSPERR_UNSUPPORTED_FUNCTION; #else { PVal *pval, *pvalNew; APTR aptr, aptrNew; IUnknown **ppunkDst, **ppunkSrc; IID iid; const IID *piid; void *iptr; STRUCTDAT *st; LIBDAT *lib; // 第1パラメータ:新しいインターフェースポインタを格納する変数 aptrNew = code_getva( &pvalNew ); // 第2パラメータ:既存のCOMオブジェクト aptr = code_getva( &pval ); if ( pval->flag != TYPE_COMOBJ ) throw ( HSPERR_TYPE_MISMATCH ); ppunkSrc = (IUnknown **)HspVarCorePtrAPTR( pval, aptr ); if ( ! IsVaridComPtr(ppunkSrc) ) throw ( HSPERR_COMDLL_ERROR ); // IID 情報を取得 if ( *type == TYPE_DLLCTRL ) { // 第3パラメータ:#usecom 登録情報 st = code_getcomst(); if ( st->otindex != -1 ) throw ( HSPERR_TYPE_MISMATCH ); lib = &hspctx->mem_linfo[ st->index ]; piid = (IID *)strp( lib->nameidx ); } else { // 第3パラメータ:文字列 IID GetIIDFromString( &iid, code_gets() ); piid = &iid; } if ( pvalNew->flag != TYPE_COMOBJ ) { // 代入により型変換 iptr = NULL; code_setva( pvalNew, aptrNew, TYPE_COMOBJ, &iptr ); } ppunkDst = (IUnknown **)HspVarCorePtrAPTR( pvalNew, aptrNew ); // query によりインスタンスを得る QueryComPtr( ppunkDst, *ppunkSrc, piid ); if ( IsVaridComPtr(ppunkSrc) ) hspctx->stat = 0; else hspctx->stat = 1; break; } #endif // HSP_COM_UNSUPPORTED case 0x02: // delcom #ifdef HSP_COM_UNSUPPORTED throw ( HSPERR_UNSUPPORTED_FUNCTION ); #else { PVal *pval; APTR aptr; IUnknown **ppunk; VARIANT *var; void *ptr; // 第1パラメータ:解放するCOMオブジェクト変数 aptr = code_getva( &pval ); ptr = HspVarCorePtrAPTR( pval, aptr ); switch ( pval->flag ) { case TYPE_COMOBJ: ppunk = (IUnknown **)ptr; ReleaseComPtr( ppunk ); break; case TYPE_VARIANT: var = (VARIANT *)ptr; VariantClear( var ); break; default: throw HSPERR_TYPE_MISMATCH; } // このタイミングで一時オブジェクトも削除しちゃう if ( comconv_var.vt != VT_EMPTY ) VariantClear( &comconv_var ); break; } #endif // HSP_COM_UNSUPPORTED case 0x03: // cnvstow { PVal *pval; char *ptr; char *ps; int size; ptr = code_getvptr( &pval, &size ); ps = code_gets(); cnvwstr( ptr, ps, size/2 ); break; } case 0x04: // comres #ifdef HSP_COM_UNSUPPORTED throw ( HSPERR_UNSUPPORTED_FUNCTION ); #else if ( code_getexflg() ) { comres_pval = NULL; comres_aptr = 0; } else { comres_aptr = code_getva( &comres_pval ); } break; #endif // HSP_COM_UNSUPPORTED case 0x05: // axobj #ifdef HSP_COM_UNSUPPORTED throw ( HSPERR_UNSUPPORTED_FUNCTION ); #else { PVal *pval; APTR aptr; const IID *piid; void *iptr; BMSCR *bm; HWND hwnd; int id,sx,sy; char clsid_name[1024]; IUnknown **ppunk, *punkObj, *punkObj2; STRUCTDAT *st; LIBDAT *lib; HRESULT hr; bm = GetBMSCR(); // 第1パラメータ:新しいインターフェースポインタを格納する変数 // (あらかじめ変数にNULLを格納) aptr = code_getva( &pval ); iptr = NULL; code_setva( pval, aptr, TYPE_COMOBJ, &iptr ); ppunk = (IUnknown **)HspVarCorePtrAPTR( pval, aptr ); // オブジェクトの CLSID, ProgID, etc. if ( *type == TYPE_DLLCTRL ) { // 第2パラメータ:#usecom 登録情報から取得 st = code_getcomst(); if ( st->otindex != -1 ) throw ( HSPERR_TYPE_MISMATCH ); lib = &hspctx->mem_linfo[ st->index ]; piid = (IID *)strp( lib->nameidx ); if ( lib->clsid == -1 ) throw ( HSPERR_INVALID_PARAMETER ); strncpy( clsid_name, strp(lib->clsid), sizeof(clsid_name)-1 ); } else { // 第2パラメータ:文字列 CLSID or ProgID を取得 (IID は IDispatch) piid = &IID_IDispatch; strncpy( clsid_name, code_gets(), sizeof(clsid_name)-1 ); } // コントロールのサイズ sx = code_getdi( bm->sx ); sy = code_getdi( bm->sy ); // ActiveXとしてロード // if ( fn_atxinit == NULL ) throw ( HSPERR_UNSUPPORTED_FUNCTION ); hwnd = CreateWindow( atxwndclass, clsid_name, WS_CHILD, // 最初は WS_VISIBLE なし (後で ShowWindow() ) bm->cx, bm->cy, sx, sy, bm->hwnd, (HMENU)0, (HINSTANCE)hspctx->instance, NULL ); punkObj2 = NULL; if ( hwnd ) { punkObj = NULL; fn_atxgetctrl( hwnd, (void**)&punkObj ); if ( punkObj ) { // 指定 IID が存在するかどうか hr = punkObj->QueryInterface( *piid, (void**)&punkObj2 ); punkObj->Release(); } } if ( punkObj2 == NULL ) { // 目的オブジェクトではないときコントロールを削除 if (hwnd) { DestroyWindow( hwnd ); } hspctx->stat = -1; break; } // COM 型変数に格納 *ppunk = punkObj2; // HSPのウインドゥオブジェクトとして登録する ShowWindow( hwnd, SW_SHOW ); id = AddHSPObject( hwnd, HSPOBJ_TAB_SKIP, sy ); #ifdef HSP_COMOBJ_DEBUG Alertf( "axobj : pObj=%p : &pObj=%p\n", *ppunk, ppunk); #endif break; } #endif // HSP_COM_UNSUPPORTED case 0x06: // winobj { #ifdef HSPDISH throw ( HSPERR_UNSUPPORTED_FUNCTION ); #else char clsname[1024]; char winname[1024]; HWND hwnd; char *ps; BMSCR *bm; int i; int prm[6]; ps = code_gets(); strncpy( clsname, ps, 1023 ); ps = code_gets(); strncpy( winname, ps, 1023 ); bm = GetBMSCR(); for(i=0;i<6;i++) { prm[i] = code_getdi(0); } if ( prm[2] <= 0 ) prm[2] = bm->ox; if ( prm[3] <= 0 ) prm[3] = bm->oy; hwnd = CreateWindowEx( (DWORD) prm[0], // 拡張ウィンドウスタイル clsname, // ウィンドウクラス名 winname, // ウィンドウ名 (DWORD) prm[1], // ウィンドウスタイル bm->cx, bm->cy, prm[2], prm[3], // X,Y,SIZEX,SIZEY bm->hwnd, // 親ウィンドウのハンドル (HMENU) prm[4], // メニューハンドルまたは子ウィンドウID bm->hInst, // インスタンスハンドル (PVOID) prm[5] // ウィンドウ作成データ ); // AddHSPObject( hwnd, HSPOBJ_TAB_SKIP, prm[3], NULL, 0 ); // HSPのウインドゥオブジェクトとして登録する AddHSPObject( hwnd, HSPOBJ_TAB_SKIP, prm[3] ); break; #endif // HSPDISH } case 0x07: // sendmsg { int hw,p1,p2,p3,p4,fl,sz; char *vptr; hw = code_getdi(0); p1 = code_getdi(0); vptr = code_getsptr( &fl ); if ( fl == TYPE_STRING ) { p2 = (int)code_stmpstr( vptr ); } else { p2 = *(int *)vptr; } vptr = code_getsptr( &fl ); if ( fl == TYPE_STRING ) { p3 = (int)vptr; } else { p3 = *(int *)vptr; } //Alertf( "SEND[%x][%x][%x]",p1,p2,p3 ); hspctx->stat = (int)SendMessage( (HWND)hw, p1, p2, p3 ); break; } case 0x08: // comevent #ifdef HSP_COM_UNSUPPORTED throw ( HSPERR_UNSUPPORTED_FUNCTION ); #else { PVal *pval; APTR aptr; void* iptr; char *ps; IID iid, *piid; unsigned short *subr; IUnknown **ppunk, **ppunkEvent; // 第1パラメータ:イベントハンドラオブジェクト (IEventHandler) を格納する変数 // (あらかじめ NULL で初期化) aptr = code_getva( &pval ); iptr = NULL; code_setva( pval, aptr, TYPE_COMOBJ, &iptr ); ppunkEvent = (IUnknown **)HspVarCorePtrAPTR( pval, aptr ); // 第2パラメータ:COMオブジェクトを格納した変数 aptr = code_getva( &pval ); if ( pval->flag != TYPE_COMOBJ ) throw ( HSPERR_TYPE_MISMATCH ); ppunk = (IUnknown **)HspVarCorePtrAPTR( pval, aptr ); if ( ! IsVaridComPtr(ppunk) ) throw ( HSPERR_COMDLL_ERROR ); // 第3パラメータ:コネクションポイントIID (文字列形式) ps = code_getds(""); if ( ps[0] != '\0' ) { piid = &iid; GetIIDFromString( piid, ps ); } else { piid = NULL; // NULL のときデフォルトIID が自動的に取得される } // 第4パラメータ:コールバック用のサブルーチンラベル subr = code_getlb2(); // イベントハンドラ作成・接続 SetComEvent( ppunkEvent, ppunk, piid, subr ); #ifdef HSP_COMOBJ_DEBUG COM_DBG_MSG( "comevent : pEvent=%p : pObj=%p\n", *ppunkEvent, *ppunk); #endif break; } #endif // HSP_COM_UNSUPPORTED case 0x09: // comevarg #ifdef HSP_COM_UNSUPPORTED throw ( HSPERR_UNSUPPORTED_FUNCTION ); #else { PVal *pval, *pval2; APTR aptr, aptr2; VARIANT *v; void *ptr; int p1,p2; int res; IUnknown **ppunk; VARIANT varTemp; // 第1パラメータ:イベントのパラメータを格納する変数 aptr = code_getva( &pval ); // 第2パラメータ:イベントハンドラオブジェクト変数 aptr2 = code_getva( &pval2 ); if ( pval2->flag != TYPE_COMOBJ ) throw ( HSPERR_TYPE_MISMATCH ); ppunk = (IUnknown **)HspVarCorePtrAPTR( pval2, aptr2 ); if ( ! IsVaridComPtr(ppunk) ) throw ( HSPERR_COMDLL_ERROR ); // 第3パラメータ:パラメータインデックス p1 = code_getdi(0); // 第4パラメータ:文字列変換フラグ p2 = code_getdi(0); // イベントのパラメータ取得 v = GetEventArg( *ppunk, p1 ); if ( v == NULL ) throw ( HSPERR_ILLEGAL_FUNCTION ); switch ( p2 ) { case 0: VariantInit( &varTemp ); VariantCopyInd( &varTemp, v ); ptr = comget_variant( &varTemp, &res ); VariantClear( &varTemp ); break; case 1: VariantInit( &varTemp ); if FAILED( VariantChangeType( &varTemp, v, VARIANT_ALPHABOOL, VT_BSTR ) ) throw ( HSPERR_TYPE_INITALIZATION_FAILED ); ptr = comget_variant( &varTemp, &res ); VariantClear( &varTemp ); break; case 2: ptr = v; res = HSPVAR_FLAG_VARIANT; break; default: throw ( HSPERR_ILLEGAL_FUNCTION ); } code_setva( pval, aptr, res, ptr ); hspctx->stat = res; break; } #endif // HSP_COM_UNSUPPORTED case 0x0a: // sarrayconv #ifdef HSP_COM_UNSUPPORTED throw ( HSPERR_UNSUPPORTED_FUNCTION ); #else { PVal *pval1, *pval2; APTR aptr1, aptr2; int convdir, size; VARIANT *variant, varTemp; VARTYPE vt; SAFEARRAY *psa; long lbound, ubound; HRESULT hr; aptr1 = code_getva( &pval1 ); aptr2 = code_getva( &pval2 ); convdir = code_getdi(0); size = code_getdi(0); switch ( convdir ) { case 0: case 2: case 4: // 配列変数から SafeArray に変換 VariantInit( &varTemp ); code_setva( pval1, aptr1, HSPVAR_FLAG_VARIANT, &varTemp ); variant = (VARIANT *)HspVarCorePtrAPTR( pval1, aptr1 ); VariantClear( variant ); // 一応 if ( convdir == 2 ) { // バイナリデータ(一次元のみ) void *ptr = HspVarCorePtrAPTR( pval2, aptr2 ); psa = CreateBinarySafeArray( ptr, size, &vt ); } else { BOOL bVariant = ( convdir == 4 ); psa = ConvVar2SafeArray( pval2, bVariant, &vt ); } variant->vt = vt | VT_ARRAY; variant->parray = psa; break; case 1: case 3: // SafeArray から配列変数に変換 if ( pval2->flag != HSPVAR_FLAG_VARIANT ) throw HSPERR_INVALID_TYPE; variant = (VARIANT *)HspVarCorePtrAPTR( pval2, aptr2 ); if ( (variant->vt & VT_ARRAY) == 0 ) throw HSPERR_INVALID_TYPE; psa = variant->parray; if ( psa == NULL ) throw HSPERR_ARRAY_OVERFLOW; vt = variant->vt & VT_TYPEMASK; if ( vt == VT_EMPTY ) { hr = SafeArrayGetVartype( psa, &vt ); if ( FAILED(hr) || vt == VT_EMPTY ) throw HSPERR_INVALID_ARRAYSTORE; } if ( convdir == 1 ) { ConvSafeArray2Var( pval1, psa, vt ); } else { // バイナリデータ(一次元のみ) int varsize; void *ptr = HspVarCorePtrAPTR( pval1, aptr1 ); if ( vt != VT_UI1 && vt != VT_I1 ) throw HSPERR_INVALID_TYPE; SafeArrayGetLBound( psa, 1, &lbound ); hr = SafeArrayGetUBound( psa, 1, &ubound ); if ( FAILED(hr) ) throw HSPERR_ARRAY_OVERFLOW; size = ubound - lbound + 1; HspVarCoreGetBlockSize( pval1, (PDAT*)ptr, &varsize ); if ( varsize < size ) throw HSPERR_BUFFER_OVERFLOW; GetBinarySafeArray( ptr, size, psa ); } break; default: throw ( HSPERR_UNSUPPORTED_FUNCTION ); } break; } #endif // HSP_COM_UNSUPPORTED default: throw ( HSPERR_SYNTAX ); } return RUNMODE_RUN; }
WXDLLEXPORT bool wxConvertVariantToOle(const wxVariant& variant, VARIANTARG& oleVariant) { VariantInit(&oleVariant); if (variant.IsNull()) { oleVariant.vt = VT_NULL; return true; } wxString type(variant.GetType()); if (type == wxT("errorcode")) { wxVariantDataErrorCode* const ec = wxStaticCastVariantData(variant.GetData(), wxVariantDataErrorCode); oleVariant.vt = VT_ERROR; oleVariant.scode = ec->GetValue(); } else if (type == wxT("currency")) { wxVariantDataCurrency* const c = wxStaticCastVariantData(variant.GetData(), wxVariantDataCurrency); oleVariant.vt = VT_CY; oleVariant.cyVal = c->GetValue(); } else if (type == wxT("safearray")) { wxVariantDataSafeArray* const vsa = wxStaticCastVariantData(variant.GetData(), wxVariantDataSafeArray); SAFEARRAY* psa = vsa->GetValue(); VARTYPE vt; wxCHECK(psa, false); HRESULT hr = SafeArrayGetVartype(psa, &vt); if ( FAILED(hr) ) { wxLogApiError(wxS("SafeArrayGetVartype()"), hr); SafeArrayDestroy(psa); return false; } oleVariant.vt = vt | VT_ARRAY; oleVariant.parray = psa; } else if (type == wxT("long")) { oleVariant.vt = VT_I4; oleVariant.lVal = variant.GetLong() ; } #if wxUSE_LONGLONG else if (type == wxT("longlong")) { oleVariant.vt = VT_I8; oleVariant.llVal = variant.GetLongLong().GetValue(); } #endif else if (type == wxT("char")) { oleVariant.vt=VT_I1; // Signed Char oleVariant.cVal=variant.GetChar(); } else if (type == wxT("double")) { oleVariant.vt = VT_R8; oleVariant.dblVal = variant.GetDouble(); } else if (type == wxT("bool")) { oleVariant.vt = VT_BOOL; oleVariant.boolVal = variant.GetBool() ? VARIANT_TRUE : VARIANT_FALSE; } else if (type == wxT("string")) { wxString str( variant.GetString() ); oleVariant.vt = VT_BSTR; oleVariant.bstrVal = wxConvertStringToOle(str); } #if wxUSE_DATETIME else if (type == wxT("datetime")) { wxDateTime date( variant.GetDateTime() ); oleVariant.vt = VT_DATE; SYSTEMTIME st; date.GetAsMSWSysTime(&st); SystemTimeToVariantTime(&st, &oleVariant.date); } #endif else if (type == wxT("void*")) { oleVariant.vt = VT_DISPATCH; oleVariant.pdispVal = (IDispatch*) variant.GetVoidPtr(); } else if (type == wxT("list")) { wxSafeArray<VT_VARIANT> safeArray; if (!safeArray.CreateFromListVariant(variant)) return false; oleVariant.vt = VT_VARIANT | VT_ARRAY; oleVariant.parray = safeArray.Detach(); } else if (type == wxT("arrstring")) { wxSafeArray<VT_BSTR> safeArray; if (!safeArray.CreateFromArrayString(variant.GetArrayString())) return false; oleVariant.vt = VT_BSTR | VT_ARRAY; oleVariant.parray = safeArray.Detach(); } else { oleVariant.vt = VT_NULL; return false; } return true; }
JSBool XPCDispConvert::COMArrayToJSArray(XPCCallContext& ccx, const VARIANT & src, jsval & dest, nsresult& err) { err = NS_OK; // We only support one dimensional arrays for now if(SafeArrayGetDim(src.parray) != 1) { err = NS_ERROR_FAILURE; return JS_FALSE; } // Get the upper bound; long ubound; if(FAILED(SafeArrayGetUBound(src.parray, 1, &ubound))) { err = NS_ERROR_FAILURE; return JS_FALSE; } // Get the lower bound long lbound; if(FAILED(SafeArrayGetLBound(src.parray, 1, &lbound))) { err = NS_ERROR_FAILURE; return JS_FALSE; } // Create the JS Array JSObject * array = JS_NewArrayObject(ccx, ubound - lbound + 1, nsnull); if(!array) { err = NS_ERROR_OUT_OF_MEMORY; return JS_FALSE; } AUTO_MARK_JSVAL(ccx, OBJECT_TO_JSVAL(array)); // Divine the type of our array VARTYPE vartype; if((src.vt & VT_ARRAY) != 0) { vartype = src.vt & ~VT_ARRAY; } else // This was maybe a VT_SAFEARRAY { #ifndef WINCE if(FAILED(SafeArrayGetVartype(src.parray, &vartype))) return JS_FALSE; #else return JS_FALSE; #endif } jsval val = JSVAL_NULL; AUTO_MARK_JSVAL(ccx, &val); for(long index = lbound; index <= ubound; ++index) { HRESULT hr; _variant_t var; if(vartype == VT_VARIANT) { hr = SafeArrayGetElement(src.parray, &index, &var); } else { var.vt = vartype; hr = SafeArrayGetElement(src.parray, &index, &var.byref); } if(FAILED(hr)) { err = NS_ERROR_FAILURE; return JS_FALSE; } if(!COMToJS(ccx, var, val, err)) return JS_FALSE; JS_SetElement(ccx, array, index, &val); } dest = OBJECT_TO_JSVAL(array); return JS_TRUE; }