PyVARDESC::PyVARDESC(const VARDESC *pVD)
{
	ob_type = &PyVARDESC::Type;
	_Py_NewReference(this);

	memid = pVD->memid;
	wVarFlags = pVD->wVarFlags;
	varkind = pVD->varkind;

	if (varkind == VAR_PERINSTANCE)
		value = PyInt_FromLong(pVD->oInst);
	else if (varkind == VAR_CONST) {
		VARIANT varValue;

		// Cast the variant type here to the correct value for this constant
		// so that the correct Python type will be created below.
		// The problem seems to exist for unsigned types (the variant has
		// a signed type, but the typelib has an unsigned one).  However,
		// doing this unconditionally has side-effects, as the typelib
		// has VT_LPWSTR for the type of strings - and VariantChangeType
		// returns a VT_EMPTY variant in that case.
		// So we only perform this conversion for types known to be a problem:
		switch (pVD->elemdescVar.tdesc.vt) {
		case VT_UI1:
		case VT_UI2:
		case VT_UI4:
		case VT_UI8:
		case VT_UINT:
		case VT_UINT_PTR:
			VariantInit(&varValue);
			VariantChangeType(&varValue, pVD->lpvarValue, 0, pVD->elemdescVar.tdesc.vt);

			value  = PyCom_PyObjectFromVariant(&varValue);

			VariantClear(&varValue);
			break;
		default:
			value  = PyCom_PyObjectFromVariant(pVD->lpvarValue);
			break;
		}
	} else if (varkind == VAR_DISPATCH) {
		// all caller needs is memid, which is already setup.
		value = Py_None;
		Py_INCREF(Py_None);
	} else {
		PyCom_LoggerWarning(NULL, "PyVARDESC ctor has unknown varkind (%d) - returning None", varkind);
		value = Py_None;
		Py_INCREF(Py_None);
	}
	elemdescVar = PyObject_FromELEMDESC(&pVD->elemdescVar);
}
Beispiel #2
0
// @pymethod object|PyIADs|Get|Description of Get.
// @rdesc The result is a Python object converted from a COM variant.  It
// may be an array, or any types supported by COM variant.
PyObject *PyIADs::Get(PyObject *self, PyObject *args)
{
	IADs *pIAD = GetI(self);
	if ( pIAD == NULL )
		return NULL;
	VARIANT val;
	VariantInit(&val);
	// @pyparm <o PyUnicode>|prop||The name of the property to fetch
	PyObject *obbstrName;
	BSTR bstrName;
	if ( !PyArg_ParseTuple(args, "O:Get", &obbstrName) )
		return NULL;
	BOOL bPythonIsHappy = TRUE;
	if (bPythonIsHappy && !PyWinObject_AsBstr(obbstrName, &bstrName)) bPythonIsHappy = FALSE;
	if (!bPythonIsHappy) return NULL;
	HRESULT hr;
	PY_INTERFACE_PRECALL;
	hr = pIAD->Get( bstrName, &val );
	SysFreeString(bstrName);
	PY_INTERFACE_POSTCALL;

	if ( FAILED(hr) )
		return PyCom_BuildPyException(hr, pIAD, IID_IADs );
	PyObject *ret = PyCom_PyObjectFromVariant(&val);
	{
	PY_INTERFACE_PRECALL;
	VariantClear(&val);
	PY_INTERFACE_POSTCALL;
	}
	return ret;
}
// DS_SELECTION_LIST helpers
PyObject *PyStringAsDS_SELECTION_LIST(PyObject *self, PyObject *args)
{
	char *sz;
	unsigned int cb;
	if (!PyArg_ParseTuple(args, "s#:PyStringAsDS_SELECTION_LIST", &sz, &cb))
		return NULL;
	if (cb < sizeof(DS_SELECTION_LIST))
		return PyErr_Format(PyExc_ValueError,
							"String must be at least %d bytes (got %d)",
							sizeof(DS_SELECTION_LIST), cb);
	DS_SELECTION_LIST *pSL = (DS_SELECTION_LIST *)sz;
	PyObject *ret = PyList_New(pSL->cItems);
	if (!ret)
		return NULL;
	for (unsigned int i=0;i<pSL->cItems;i++) {
		// get attrs for this item
		DS_SELECTION *pItem = pSL->aDsSelection+i;
		PyObject *obAttr;
		if (pItem->pvarFetchedAttributes) {
			obAttr = PyList_New(pSL->cFetchedAttributes);
			if (!obAttr) {
				Py_DECREF(ret);
				return NULL;
			}
			for (unsigned int ia=0;ia<pSL->cFetchedAttributes;ia++)
				PyList_SET_ITEM(obAttr, ia,
								 PyCom_PyObjectFromVariant(pItem->pvarFetchedAttributes+ia));
		}
		else {
			obAttr = Py_None;
			Py_INCREF(Py_None);
		}
		PyObject *sub = Py_BuildValue("NNNNNl",
									  PyWinObject_FromWCHAR(pItem->pwzName),
									  PyWinObject_FromWCHAR(pItem->pwzADsPath),
									  PyWinObject_FromWCHAR(pItem->pwzClass),
									  PyWinObject_FromWCHAR(pItem->pwzUPN),
									  obAttr,
									  pItem->flScopeType);
		if (!sub) {
			Py_DECREF(ret);
			return NULL;
		}
		PyList_SET_ITEM(ret, i, sub);
	}
	return ret;
}
Beispiel #4
0
// @object ELEMDESC|An ELEMDESC is respresented as a tuple of
PyObject *PyObject_FromELEMDESC(const ELEMDESC *ed)
{
	// @tupleitem 0|<o TYPEDESC>|typeDesc|The type description.
	// @tupleitem 1|int|idlFlags|
	// @tupleitem 2|object|default|If PARAMFLAG_FHASDEFAULT are set, then this is the default value.
	PyObject *defaultValue = NULL;
	if (ed->idldesc.wIDLFlags & PARAMFLAG_FHASDEFAULT && ed->paramdesc.pparamdescex)
		defaultValue = PyCom_PyObjectFromVariant(&ed->paramdesc.pparamdescex->varDefaultValue);
	if (defaultValue==NULL) {
		defaultValue = Py_None;
		Py_INCREF(Py_None);
	}
	PyObject *td = PyObject_FromTYPEDESC(&ed->tdesc);
	PyObject *ret = Py_BuildValue("(OiO)", td, ed->paramdesc.wParamFlags, defaultValue);
	Py_DECREF(td);
	Py_DECREF(defaultValue);
	return ret;
}
// @pymethod |PyIOleCommandTarget|Exec|Description of Exec.
PyObject *PyIOleCommandTarget::Exec(PyObject *self, PyObject *args)
{
	PyObject *ret;
	int cmdid, cmdopt;
	PyObject *obVar;
	PyObject *obGUID;
	VARIANT varIn, varOut;
	IOleCommandTarget *pIOCT = GetI(self);
	if ( pIOCT == NULL )
		return NULL;
	if (!PyArg_ParseTuple(args, "OiiO", &obGUID, &cmdid, &cmdopt, &obVar))
		return NULL;

	GUID guid;
	GUID *pguid;
	if (obGUID == Py_None) {
		pguid = NULL;
	} else {
		if (!PyWinObject_AsIID(obGUID, &guid))
			return FALSE;
		pguid = &guid;
	}
	VariantInit(&varIn);
	VariantInit(&varOut);
	if (!PyCom_VariantFromPyObject(obVar, &varIn))
		return NULL;

	HRESULT hr;
	PY_INTERFACE_PRECALL;
	hr = pIOCT->Exec( pguid, cmdid, cmdopt, &varIn, &varOut);
	PY_INTERFACE_POSTCALL;
	
	VariantClear(&varIn);

	if ( FAILED(hr) ) {
		PyCom_BuildPyException(hr, pIOCT, IID_IOleCommandTarget );
		ret = NULL;
	} else {
		ret = PyCom_PyObjectFromVariant(&varOut);
	}
	VariantClear(&varOut);
	return ret;
}
// @pymethod object|PyIPropertyBag|Read|Called by the control to read a property from the storage provided by the container.
PyObject *PyIPropertyBag::Read(PyObject *self, PyObject *args)
{
	int varType = VT_EMPTY;
	PyObject *obLog = NULL;
	PyObject *obName;
	// @pyparm str|propName||Name of the property to read.
	// @pyparm int|propType||The type of the object to read.  Must be a VT_* Variant Type constant.
	// @pyparm <o PyIErrorLog>|errorLog|None|The caller's <o PyIErrorLog> object in which the property bag stores any errors that occur during reads. Can be None in which case the caller is not interested in errors.
	if ( !PyArg_ParseTuple(args, "O|iO:Read", &obName, &varType, &obLog) )
		return NULL;

	IPropertyBag *pIPB = GetI(self);
	if ( pIPB == NULL )
		return NULL;

	TmpWCHAR Name;
	if (!PyWinObject_AsWCHAR(obName, &Name))
		return NULL;
	IErrorLog *pIEL = NULL;
	if ( obLog != NULL && obLog != Py_None &&
		!PyCom_InterfaceFromPyObject(obLog, IID_IErrorLog, (LPVOID*)&pIEL, FALSE) )
		return NULL;

	VARIANT var;
	VariantInit(&var);
	V_VT(&var) = varType;	// ### do we need to set anything more?

	PY_INTERFACE_PRECALL;
	HRESULT hr = pIPB->Read(Name, &var, pIEL);
	if ( pIEL != NULL )
		pIEL->Release();
	PY_INTERFACE_POSTCALL;
	if ( FAILED(hr) )
		return PyCom_BuildPyException(hr, pIPB, IID_IPropertyBag);

	PyObject *result = PyCom_PyObjectFromVariant(&var);
	VariantClear(&var);
	// @comm The result is a Python object, mapped from a COM VARIANT of type as specified in the propType parameter.
	return result;
}
Beispiel #7
0
STDMETHODIMP PyGPropertyBag::Write(
            /* [in] */ LPCOLESTR pszPropName,
            /* [in] */ VARIANT __RPC_FAR *pVar)
{
	if ( pszPropName == NULL || pVar == NULL )
		return E_POINTER;

	PY_GATEWAY_METHOD;
	PyObject *value = PyCom_PyObjectFromVariant(pVar);
	if ( !value )
		return PyCom_SetCOMErrorFromPyException(GetIID());

	PyObject *obName = PyWinObject_FromWCHAR(pszPropName);
	HRESULT hr = InvokeViaPolicy("Write",
									NULL,
									"OO",
									obName,
									value);
	Py_DECREF(value);
	Py_XDECREF(obName);
	return hr;
}
STDMETHODIMP PyGOleCommandTarget::Exec(
		/* [unique][in] */ const GUID * pguidCmdGroup,
		/* [in] */ DWORD nCmdID,
		/* [in] */ DWORD nCmdexecopt,
		/* [unique][in] */ VARIANT * pvaIn,
		/* [unique][out][in] */ VARIANT * pvaOut)
{
	PY_GATEWAY_METHOD;
	PyObject *obGUID;
	if (pguidCmdGroup == NULL) {
		obGUID = Py_None;
		Py_INCREF(obGUID);
	} else {
		obGUID = PyWinObject_FromIID(*pguidCmdGroup);
	}
	PyObject *obpvaIn = PyCom_PyObjectFromVariant(pvaIn);
	PyObject *result;
	HRESULT hr=InvokeViaPolicy("Exec", &result, "NllN", obGUID, nCmdID, nCmdexecopt, obpvaIn);
	if (FAILED(hr)) return hr;
	hr = pvaOut ? PyCom_VariantFromPyObject(result, pvaOut) : S_OK;
	Py_DECREF(result);
	return hr;
}
Beispiel #9
0
PyObject * dataconv_ReadFromInTuple(PyObject *self, PyObject *args)
{
	PyObject *obArgTypes;
	PyObject *obArgType;
	PyObject *obPtr;
	BYTE *pb;
	BYTE *pbArg;
	Py_ssize_t cArgs, i;
	PyObject *obArgs = NULL;
	PyObject *obArg;
	VARTYPE vtArgType;
	UINT cb;
	VARIANT var;
	BOOL bIsByRef;
	

	if (!PyArg_ParseTuple(args, "OO:ReadFromInTuple", &obArgTypes, &obPtr))
		return NULL;
	
	pbArg = (BYTE *)PyLong_AsVoidPtr(obPtr);
	assert(pbArg);
	if (!pbArg)
		return NULL;

	pb = pbArg;

	if (!PyTuple_Check(obArgTypes))
	{
		PyErr_SetString(PyExc_TypeError, "OLE type description - expecting a tuple");
		return NULL;
	}
	
	cArgs = PyTuple_Size(obArgTypes);
	obArgs = PyTuple_New(cArgs);
	if (!obArgs)
		return NULL;

	for(i = 0 ; i < cArgs; i++)
	{
		// (<type tuple>, argPtr offset, arg size)
		if (PyTuple_Size(PyTuple_GET_ITEM(obArgTypes, i)) != 3)
		{
			PyErr_SetString(PyExc_TypeError, "OLE type description - expecting an arg desc tuple of size 3");
			goto Error;
		}
		
		obArgType = PyTuple_GET_ITEM(PyTuple_GET_ITEM(obArgTypes, i), 0);

		// Position pb to point to the current argument.
		pb = pbArg + PyInt_AS_LONG(PyTuple_GET_ITEM(PyTuple_GET_ITEM(obArgTypes, i), 1));
		vtArgType = (VARTYPE)PyInt_AS_LONG(obArgType);
#ifdef _M_IX86
		bIsByRef = vtArgType & VT_BYREF;
#elif _M_X64
		// params > 64bits always passed by address - and the only
		// arg we support > 64 bits is a VARIANT structure.
		bIsByRef = (vtArgType==VT_VARIANT) || (vtArgType & VT_BYREF);
#else
#error Unknown platform
#endif
		VARTYPE vtConversionType = vtArgType & VT_TYPEMASK;
		if (vtArgType & VT_ARRAY) {
			SAFEARRAY FAR *psa = *((SAFEARRAY **)pb);
			if (psa==NULL) { // A NULL array
				Py_INCREF(Py_None);
				obArg = Py_None;
			} else {
				if (vtArgType & VT_BYREF) // one more level of indirection
					psa = *((SAFEARRAY FAR **)psa);
				if (psa==NULL) { // A NULL array
					Py_INCREF(Py_None);
					obArg = Py_None;
				} else 
					obArg = PyCom_PyObjectFromSAFEARRAY(psa, (VARENUM)vtConversionType);
			}
		} else {
			switch (vtConversionType)
			{
			// If they can fit in a VARIANT, cheat and make that code do all of the work...
			case VT_I2:
			case VT_I4:
			case VT_R4:
			case VT_R8:
			case VT_CY:
			case VT_DATE:
			case VT_BSTR:
			case VT_ERROR:
			case VT_BOOL:
			case VT_I1:
			case VT_UI1:
			case VT_UI2:
			case VT_UI4:
			case VT_INT:
			case VT_UINT:
			case VT_UNKNOWN:
			case VT_DISPATCH:
			case VT_HRESULT:
				VariantInit(&var);
				if (vtConversionType == VT_HRESULT ||
					vtConversionType == VT_INT)
				{
					// Preserve VT_BYREF or VT_ARRAY
					vtArgType = VT_I4 | (vtArgType & VT_TYPEMASK);
				}
				if (vtArgType == VT_UINT) 
				{
					// Preserve VT_BYREF or VT_ARRAY
					vtArgType = VT_UI4 | (vtArgType & VT_TYPEMASK);
				}
				V_VT(&var) = vtArgType;
				// Copy the data into the variant...
				if (!SizeOfVT(V_VT(&var), (int *)&cb, NULL))
					goto Error;
				memcpy(&V_I4(&var), pb, cb);
				// Convert it into a PyObject:
				obArg = PyCom_PyObjectFromVariant(&var);
				break;
			case VT_VARIANT:
				// A _real_ variant.
				if (bIsByRef)
					obArg = PyCom_PyObjectFromVariant(*(VARIANT**)pb);
				else
					obArg = PyCom_PyObjectFromVariant((VARIANT*)pb);
				break;
			case VT_LPSTR:
				obArg = PyString_FromString(*(CHAR **)pb);
				break;
			case VT_LPWSTR:
				obArg = PyWinObject_FromOLECHAR(*(OLECHAR **)pb);
				break;
			// Special cases:
			case VT_UI8:
				if (bIsByRef)
				{
					obArg = PyWinObject_FromULARGE_INTEGER(*(ULARGE_INTEGER *)pb);
				}
				else
				{
					obArg = PyWinObject_FromULARGE_INTEGER(**(ULARGE_INTEGER **)pb);
				}
				break;
			case VT_I8:
				if (bIsByRef)
				{
					obArg = PyWinObject_FromLARGE_INTEGER(*(LARGE_INTEGER *)pb);
				}
				else
				{
					obArg = PyWinObject_FromLARGE_INTEGER(**(LARGE_INTEGER **)pb);
				}
				break;
			// Pointers to unhandled arguments:
			// neither of these will be VT_BYREF'd.
			case VT_RECORD:
			case VT_PTR:
				obArg = PyLong_FromVoidPtr((void *)pb);
				break;
			// None of these should ever happen:
			case VT_USERDEFINED:
			// Should have been coerced into VT_PTR.
			case VT_CARRAY:
			default:
				obArg = NULL;
				PyErr_SetString(PyExc_TypeError, "Unknown/bad type description type!");
				// barf here, we don't wtf they were thinking...
				break;
			} // switch
		} // if ARRAY

		if (obArg == NULL)
		{
			goto Error;
		}
		PyTuple_SET_ITEM(obArgs, i, obArg);
	}

	return obArgs;
	
Error:
	Py_XDECREF(obArgs);
	return NULL;
}
Beispiel #10
0
PyObject *PyRecord::getattro(PyObject *self, PyObject *obname)
{
	PyObject *res;
	PyRecord *pyrec = (PyRecord *)self;
	char *name=PYWIN_ATTR_CONVERT(obname);
	if (name==NULL)
		return NULL;
	if (strcmp(name, "__members__")==0) {
		ULONG cnames = 0;
		HRESULT hr = pyrec->pri->GetFieldNames(&cnames, NULL);
		if (FAILED(hr))
			return PyCom_BuildPyException(hr, pyrec->pri, IID_IRecordInfo);
		BSTR *strs = (BSTR *)malloc(sizeof(BSTR) * cnames);
		if (strs==NULL)
			return PyErr_NoMemory();
		hr = pyrec->pri->GetFieldNames(&cnames, strs);
		if (FAILED(hr)) {
			free(strs);
			return PyCom_BuildPyException(hr, pyrec->pri, IID_IRecordInfo);
		}
		res = PyList_New(cnames);
		for (ULONG i=0;i<cnames && res != NULL;i++) {
			PyObject *item = PyWinCoreString_FromString(strs[i]);
			SysFreeString(strs[i]);
			if (item==NULL) {
				Py_DECREF(res);
				res = NULL;
			} else
				PyList_SET_ITEM(res, i, item); // ref count swallowed.
		}
		free(strs);
		return res;
	}

	res = PyObject_GenericGetAttr(self, obname);
	if (res != NULL)
		return res;

	PyErr_Clear();
	WCHAR *wname;
	if (!PyWinObject_AsWCHAR(obname, &wname))
		return NULL;

	VARIANT vret;
	VariantInit(&vret);
	void *sub_data = NULL;

	PY_INTERFACE_PRECALL;
	HRESULT hr = pyrec->pri->GetFieldNoCopy(pyrec->pdata, wname, &vret, &sub_data);
	PyWinObject_FreeWCHAR(wname);
	PY_INTERFACE_POSTCALL;

	if (FAILED(hr)) {
		if (hr == TYPE_E_FIELDNOTFOUND){
			// This is slightly suspect - throwing a unicode
			// object for an AttributeError in py2k - but this
			// is the value we asked COM for, so it makes sense...
			// (and PyErr_Format doesn't handle unicode in py2x)
			PyErr_SetObject(PyExc_AttributeError, obname);
			return NULL;
			}
		return PyCom_BuildPyException(hr, pyrec->pri, IID_IRecordInfo);
	}

	// Short-circuit sub-structs and arrays here, so we dont allocate a new chunk
	// of memory and copy it - we need sub-structs to persist.
	if (V_VT(&vret)==(VT_BYREF | VT_RECORD))
		return new PyRecord(V_RECORDINFO(&vret), V_RECORD(&vret), pyrec->owner);
	else if (V_VT(&vret)==(VT_BYREF | VT_ARRAY | VT_RECORD)) {
		SAFEARRAY *psa = *V_ARRAYREF(&vret);
		int d = SafeArrayGetDim(psa);
		if (sub_data==NULL)
			return PyErr_Format(PyExc_RuntimeError, "Did not get a buffer for the array!");
		if (SafeArrayGetDim(psa) != 1)
			return PyErr_Format(PyExc_TypeError, "Only support single dimensional arrays of records");
		IRecordInfo *sub = NULL;
		long ubound, lbound, nelems;
		int i;
		BYTE *this_data;
		PyObject *ret_tuple = NULL;
		ULONG element_size = 0;
		hr = SafeArrayGetUBound(psa, 1, &ubound);
		if (FAILED(hr)) goto array_end;
		hr = SafeArrayGetLBound(psa, 1, &lbound);
		if (FAILED(hr)) goto array_end;
		hr = SafeArrayGetRecordInfo(psa, &sub);
		if (FAILED(hr)) goto array_end;
		hr = sub->GetSize(&element_size);
		if (FAILED(hr)) goto array_end;
		nelems = ubound-lbound;
		ret_tuple = PyTuple_New(nelems);
		if (ret_tuple==NULL) goto array_end;
		this_data = (BYTE *)sub_data;
		for (i=0;i<nelems;i++) {
			PyTuple_SET_ITEM(ret_tuple, i, new PyRecord(sub, this_data, pyrec->owner));
			this_data += element_size;
		}
array_end:
		if (sub)
			sub->Release();
		if (FAILED(hr)) 
			return PyCom_BuildPyException(hr, pyrec->pri, IID_IRecordInfo);
		return ret_tuple;
	}

	// This default conversion we use is a little slow (but it will do!)
	// For arrays, the pparray->pvData member is *not* set, since the actual data
	// pointer from the record is returned in sub_data, so set it here.
	if (V_ISARRAY(&vret) && V_ISBYREF(&vret))
		(*V_ARRAYREF(&vret))->pvData = sub_data;
	PyObject *ret = PyCom_PyObjectFromVariant(&vret);

//	VariantClear(&vret);
	return ret;
}
Beispiel #11
0
// @pymethod object|PyIDispatchEx|InvokeEx|Provides access to properties and methods exposed by a <o PyIDispatchEx> object. 
PyObject *PyIDispatchEx::InvokeEx(PyObject *self, PyObject *args)
{
	long dispid;
	long lcid;
	int flags;
	PyObject *invokeArgs;
	PyObject *types = Py_None;
	PyObject *obReturnDesc = Py_None;
	PyObject *obCaller = Py_None;
	if (!PyArg_ParseTuple(args, "lliO|OOO:InvokeEx",
		&dispid, // @pyparm int|dispid||
		&lcid,  // @pyparm int|lcid||
		&flags, // @pyparm int|flags||
		&invokeArgs,  // @pyparm [object, ...]|args||The arguments.
		&types, // @pyparm [object, ...]|types|None|A tuple of type description object, or None if type descriptions are not available.
		&obReturnDesc, // @pyparm object\|int|returnDesc|1|If types==None, should be a BOOL indicating if the result is needed.  If types is a tuple, then should a be type description.
		&obCaller)) // @pyparm <o PyIServiceProvider>|serviceProvider|None|A service provider object supplied by the caller which allows the object to obtain services from the caller. Can be None.
		return NULL;

	if (!PyTuple_Check(invokeArgs)) {
		PyErr_SetString(PyExc_TypeError, "The arguments must be a tuple.");
		return NULL;
	}

	// TODO - We do not yet support the Type Description here
	// (Im not even sure if we need it!)
	if (types != Py_None || obReturnDesc != Py_None) {
		PyErr_SetString(PyExc_TypeError, "Type descriptions are not yet supported.");
		return NULL;
	}
	// TODO - Add support for PyIServiceProvider
	if (obCaller != Py_None) {
		PyErr_SetString(PyExc_TypeError, "If you really need IServiceProvider support, you are going to have to add it!.");
		return NULL;
	}
	BOOL bResultWanted = TRUE;

	IDispatchEx *pMyDispatch = GetI(self);
	if ( pMyDispatch==NULL )
		return NULL;

	DISPPARAMS dispparams;
	PythonOleArgHelper *helpers;
	if (!PyCom_MakeUntypedDISPPARAMS(invokeArgs, PyObject_Length(invokeArgs), flags, &dispparams, &helpers ))
		return NULL;

	VARIANT varResult;
	VARIANT *pVarResultUse;
	if ( bResultWanted ) {
		VariantInit(&varResult);
		pVarResultUse = &varResult;
	} else
		pVarResultUse = NULL;

	// initialize EXCEPINFO struct
	EXCEPINFO excepInfo;
	memset(&excepInfo, 0, sizeof excepInfo);

	PY_INTERFACE_PRECALL;
	HRESULT hr = pMyDispatch->InvokeEx((DISPID)dispid, (LCID)lcid, (WORD)flags, &dispparams, pVarResultUse, &excepInfo, NULL);
	PY_INTERFACE_POSTCALL;

	if (!PyCom_FinishUntypedDISPPARAMS(&dispparams, helpers) ||
	    HandledDispatchFailure(hr, &excepInfo, (UINT)-1, dispparams.cArgs) ) {
		if ( pVarResultUse )
			VariantClear(pVarResultUse);
		return NULL;
	}

	PyObject *result;
	if (pVarResultUse) {
		result = PyCom_PyObjectFromVariant(pVarResultUse);
		VariantClear(pVarResultUse);
	} else {
		result = Py_None;
		Py_INCREF(result);
	}
	return result;
}
Beispiel #12
0
// @pymethod object|PyIDispatch|Invoke|Invokes a DISPID, using the passed arguments.
PyObject * PyIDispatch::Invoke(PyObject *self, PyObject *args)
{
	/* Invoke(dispid, lcid, wflags, bResultWanted, arg1, arg2...) */
	// should be no need to clear this error - but for the next few release
	// I will keep it in place for release builds, and assert in debug
#ifdef _DEBUG
	assert(!PyErr_Occurred());
#else
	PyErr_Clear();
#endif
	int argc = PyObject_Length(args);
	if ( argc == -1 )
		return NULL;
	if ( argc < 4 )
		return PyErr_Format(PyExc_TypeError, "not enough arguments (at least 4 needed)");

	// @pyparm int|dispid||The dispid to use.  Typically this value will come from <om PyIDispatch.GetIDsOfNames> or from a type library.
	DISPID dispid = PyInt_AsLong(PyTuple_GET_ITEM(args, 0));
	// @pyparm int|lcid||The locale id to use.
	LCID lcid = PyInt_AsLong(PyTuple_GET_ITEM(args, 1));
	// @pyparm int|flags||The flags for the call.  The following flags can be used.
	// @flagh Flag|Description
	// @flag DISPATCH_METHOD|The member is invoked as a method. If a property has the same name, both this and the DISPATCH_PROPERTYGET flag may be set. 
	// @flag DISPATCH_PROPERTYGET|The member is retrieved as a property or data member.
	// @flag DISPATCH_PROPERTYPUT|The member is changed as a property or data member. 
	// @flag DISPATCH_PROPERTYPUTREF|The member is changed by a reference assignment, rather than a value assignment. This flag is valid only when the property accepts a reference to an object. 
	UINT wFlags = PyInt_AsLong(PyTuple_GET_ITEM(args, 2));
	// @pyparm int|bResultWanted||Indicates if the result of the call should be requested.
	// @pyparm object, ...|params, ...||The parameters to pass.
	BOOL bResultWanted = (BOOL)PyInt_AsLong(PyTuple_GET_ITEM(args, 3));
	if ( PyErr_Occurred() )
		return NULL;

	IDispatch *pMyDispatch = GetI(self);
	if ( pMyDispatch==NULL )
		return NULL;

	DISPPARAMS dispparams;
	PythonOleArgHelper *helpers;
	if (!PyCom_MakeUntypedDISPPARAMS(args, argc-4, wFlags, &dispparams, &helpers ))
		return NULL;

	VARIANT varResult;
	VARIANT *pVarResultUse;
	if ( bResultWanted ) {
		VariantInit(&varResult);
		pVarResultUse = &varResult;
	} else
		pVarResultUse = NULL;

	// initialize EXCEPINFO struct
	EXCEPINFO excepInfo;
	memset(&excepInfo, 0, sizeof excepInfo);

	UINT nArgErr = (UINT)-1;  // initialize to invalid arg
	PY_INTERFACE_PRECALL;
	HRESULT hr = pMyDispatch->Invoke(dispid, IID_NULL, lcid, wFlags, &dispparams, pVarResultUse, &excepInfo, &nArgErr);
	PY_INTERFACE_POSTCALL;

	if (!PyCom_FinishUntypedDISPPARAMS(&dispparams, helpers) ||
	    HandledDispatchFailure(hr, &excepInfo, nArgErr, dispparams.cArgs) )	{
		if ( pVarResultUse )
			VariantClear(pVarResultUse);
		return NULL;
	}
	// @rdesc If the bResultWanted parameter is False, then the result will be None.
	// Otherwise, the result is determined by the COM object itself (and may still be None)
	PyObject *result;
	if (pVarResultUse) {
		result = PyCom_PyObjectFromVariant(pVarResultUse);
		VariantClear(pVarResultUse);
	} else {
		result = Py_None;
		Py_INCREF(result);
	}
	return result;
}