// @pymethod int|PyIActiveScriptSite|OnScriptTerminate|
PyObject *PyIActiveScriptSite::OnScriptTerminate(PyObject *self, PyObject *args)
{
	PY_INTERFACE_METHOD;
	PyObject *obResult, *obException;
	if (!PyArg_ParseTuple(args, "OO:OnScriptTerminate", &obResult, &obException))
		return NULL;

	IActiveScriptSite *pMySite = GetI(self);
	if (pMySite==NULL) return NULL;

	VARIANT varResult;
	VARIANT *pVarResult = NULL;
	if (obResult!=Py_None) {
		pVarResult = &varResult;
		VariantInit(&varResult);
		if (!PyCom_VariantFromPyObject(obResult, pVarResult))
			return NULL;
	}
	EXCEPINFO excep;
	EXCEPINFO *pExcep = NULL;
	if (obException!=Py_None) {
		pExcep = &excep;
		memset(pExcep, 0, sizeof(EXCEPINFO));
		if (!PyCom_ExcepInfoFromPyObject(obException, pExcep))
			return NULL;
	}
	PY_INTERFACE_PRECALL;
	SCODE sc = pMySite->OnScriptTerminate(pVarResult, pExcep);
	PY_INTERFACE_POSTCALL;
	if (pVarResult)
		VariantClear(pVarResult);
	if (FAILED(sc))
		return SetPythonCOMError(self, sc);
	return PyInt_FromLong(sc);
}
// @pymethod |PyIPropertyBag|Write|Called by the control to write each property in turn to the storage provided by the container.
PyObject *PyIPropertyBag::Write(PyObject *self, PyObject *args)
{
	PyObject *obName;
	PyObject *obValue;
	// @pyparm str|propName||Name of the property to read.
	// @pyparm object|value||The value for the property.  The value must be able to be converted to a COM VARIANT.
	if ( !PyArg_ParseTuple(args, "OO:Write", &obName, &obValue) )
		return NULL;

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

	TmpWCHAR Name;
	if ( !PyWinObject_AsWCHAR(obName, &Name))
		return NULL;
	VARIANT var;
	if ( !PyCom_VariantFromPyObject(obValue, &var) )
		return NULL;

	PY_INTERFACE_PRECALL;
	HRESULT hr = pIPB->Write(Name, &var);
	VariantClear(&var);
	PY_INTERFACE_POSTCALL;
	if ( FAILED(hr) )
		return PyCom_BuildPyException(hr, pIPB, IID_IPropertyBag);

	Py_INCREF(Py_None);
	return Py_None;
}
Example #3
0
// @pymethod |PyIADs|Put|Description of Put.
PyObject *PyIADs::Put(PyObject *self, PyObject *args)
{
	IADs *pIAD = GetI(self);
	if ( pIAD == NULL )
		return NULL;
	// @pyparm <o PyUnicode>|property||The property name to set
	// @pyparm object|val||The value to set.
	PyObject *obbstrName;
	PyObject *obvProp;
	BSTR bstrName;
	VARIANT vProp;
	VariantInit(&vProp);
	if ( !PyArg_ParseTuple(args, "OO:Put", &obbstrName, &obvProp) )
		return NULL;
	BOOL bPythonIsHappy = TRUE;
	if (bPythonIsHappy && !PyWinObject_AsBstr(obbstrName, &bstrName)) bPythonIsHappy = FALSE;
	if ( !PyCom_VariantFromPyObject(obvProp, &vProp) )
		bPythonIsHappy = FALSE;
	if (!bPythonIsHappy) return NULL;
	HRESULT hr;
	PY_INTERFACE_PRECALL;
	hr = pIAD->Put( bstrName, vProp );
	SysFreeString(bstrName);
	VariantClear(&vProp);
	PY_INTERFACE_POSTCALL;

	if ( FAILED(hr) )
		return PyCom_BuildPyException(hr, pIAD, IID_IADs );
	Py_INCREF(Py_None);
	return Py_None;

}
Example #4
0
BOOL PyObject_AsVARDESC(PyObject *ob, VARDESC *v, void *pMore)
{
	if (ob->ob_type != &PyVARDESC::Type) {
		PyErr_SetString(PyExc_TypeError, "Object is not a VARDESC.");
		return FALSE;
	}
	PyVARDESC *pyv = (PyVARDESC *)ob;
	v->memid = pyv->memid;
	v->wVarFlags = pyv->wVarFlags;
	v->varkind = (VARKIND)pyv->varkind;
	if (!PyObject_AsELEMDESC(pyv->elemdescVar, &v->elemdescVar, pMore))
		return FALSE;

	if (v->varkind == VAR_PERINSTANCE) {
		if (!PyInt_Check(pyv->value)) {
			PyErr_SetString(PyExc_TypeError, "If varkind==VAR_PERINSTANCE, value attribute must be an integer");
			return FALSE;
		}
		v->oInst = PyInt_AsLong(pyv->value);
	}  else if (v->varkind == VAR_CONST) {
		VARIANT *pVar = (VARIANT *)AllocMore(pMore, sizeof(VARIANT), TRUE);
		if (pVar==NULL) return NULL;
		VariantInit(pVar);
		if (!PyCom_VariantFromPyObject(pyv->value, pVar))
			return NULL;
		v->lpvarValue = pVar;
	}  else if (v->varkind == VAR_DISPATCH) {
		// nothing to do - memid is all that is needed by the caller.
		;
	} else {
		PyCom_LoggerWarning(NULL, "PyObject_AsVARDESC has unknown varkind (%d) - None will be used", v->varkind);
	}
	// else ignore value.
	return TRUE;
}
STDMETHODIMP PyGEnumVARIANT::Next( 
            /* [in] */ ULONG celt,
            /* [length_is][size_is][out] */ VARIANT __RPC_FAR *rgVar,
            /* [out] */ ULONG __RPC_FAR *pCeltFetched)
{
	PY_GATEWAY_METHOD;
	PyObject *result;
	HRESULT hr = InvokeViaPolicy("Next", &result, "i", celt);
	if ( FAILED(hr) )
		return hr;

	if ( !PySequence_Check(result) )
		goto error;
	int len;
	len = PyObject_Length(result);
	if ( len == -1 )
		goto error;
	if ( len > (int)celt)
		len = celt;

	if ( pCeltFetched )
		*pCeltFetched = len;

	int i;
	for ( i = 0; i < len; ++i )
	{
		PyObject *ob = PySequence_GetItem(result, i);
		if ( ob == NULL )
			goto error;

		if ( !PyCom_VariantFromPyObject(ob, &rgVar[i]) )
		{
			Py_DECREF(ob);
			Py_DECREF(result);
			return PyCom_SetCOMErrorFromPyException(IID_IEnumVARIANT);
		}
		Py_DECREF(ob);
	}

	Py_DECREF(result);

	return len < (int)celt ? S_FALSE : S_OK;

  error:
	PyErr_Clear();	// just in case
	PyCom_LogF("PyGEnumVariant::Next got a bad return value");
	Py_DECREF(result);
	return PyCom_SetCOMErrorFromSimple(E_FAIL, IID_IEnumVARIANT, "Next() did not return a sequence of objects");
}
Example #6
0
// @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;
}
Example #7
0
STDMETHODIMP PyGPropertyBag::Read(
            /* [in] */ LPCOLESTR pszPropName,
            /* [out][in] */ VARIANT __RPC_FAR *pVar,
            /* [in] */ IErrorLog __RPC_FAR *pErrorLog)
{
	if ( pszPropName == NULL || pVar == NULL )
		return E_POINTER;

	PY_GATEWAY_METHOD;
	PyObject *obLog;
	if ( pErrorLog )
	{
		obLog = PyCom_PyObjectFromIUnknown(pErrorLog, IID_IErrorLog, TRUE);
		if ( !obLog )
			return PyCom_SetCOMErrorFromPyException(GetIID());
	}
	else
	{
		Py_INCREF(Py_None);
		obLog = Py_None;
	}

	PyObject *obName = PyWinObject_FromWCHAR(pszPropName);
	PyObject *result;
	HRESULT hr = InvokeViaPolicy("Read",
									&result,
									"OiO",
									obName,
									(int)V_VT(pVar),
									obLog);

	Py_DECREF(obLog);
	Py_XDECREF(obName);
	if (FAILED(hr)) return hr;
	if (!PyCom_VariantFromPyObject(result, pVar))
		hr = PyCom_SetCOMErrorFromPyException(GetIID());

	Py_DECREF(result);
	return hr;
}
Example #8
0
/////////////////////////////////////////////////////////////////////////////
//
// ELEMDESC support
//
/////////////////////////////////////////////////////////////////////////////
BOOL PyObject_AsELEMDESC( PyObject *ob, ELEMDESC *pDesc, void *pMore )
{
	// pMore must have come from AllocateMoreBlock()
	BOOL rc = FALSE;
	if (!PySequence_Check(ob) || PySequence_Length(ob)!=3) {
		PyErr_SetString(PyExc_TypeError, "The object is not an ELEMDESC");
		return FALSE;
	}
	PyObject *obtd = PySequence_GetItem(ob, 0);
	PyObject *obParamFlags = PySequence_GetItem(ob, 1);
	PyObject *obDefaultVal = PySequence_GetItem(ob, 2);

	if (!PyInt_Check(obParamFlags)) {
		PyErr_SetString(PyExc_TypeError, "The second sequence item must be an integer");
		goto done;
	}
	pDesc->paramdesc.wParamFlags = (WORD)PyInt_AsLong(obParamFlags);

	if (obDefaultVal != Py_None) {
		pDesc->paramdesc.wParamFlags |= PARAMFLAG_FHASDEFAULT;
		pDesc->paramdesc.pparamdescex = (LPPARAMDESCEX)AllocMore( pMore, sizeof(PARAMDESCEX), TRUE);
		pDesc->paramdesc.pparamdescex->cBytes = sizeof(PARAMDESCEX);
		/// XXX - this leaks this variant :-(
		// To avoid, we could maybe alloc a new More block with VARIANT set
		// to True, then memcpy this variant into it??
		// Or have PyObject_FreeFUNCDESC() do the right thing, looking down
		// each elemdesc freeing the variant?
		// However, this is very very rarely used (possibly never in the real world!)
		VariantInit(&pDesc->paramdesc.pparamdescex->varDefaultValue);
		if (!PyCom_VariantFromPyObject(obDefaultVal, &pDesc->paramdesc.pparamdescex->varDefaultValue))
			goto done;
	}
	rc = PyObject_AsTYPEDESC( obtd, &pDesc->tdesc, pMore );
done:
	Py_XDECREF(obtd);
	Py_XDECREF(obParamFlags);
	Py_XDECREF(obDefaultVal);
	return rc;
}
Example #9
0
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;
}
Example #10
0
int PyRecord::setattro(PyObject *self, PyObject *obname, PyObject *v)
{
	VARIANT val;
	VariantInit(&val);
	PyRecord *pyrec = (PyRecord *)self;

	if (!PyCom_VariantFromPyObject(v, &val))
		return -1;

	WCHAR *wname;
	if (!PyWinObject_AsWCHAR(obname, &wname, FALSE))
		return -1;

	PY_INTERFACE_PRECALL;
	HRESULT hr = pyrec->pri->PutField(INVOKE_PROPERTYPUT, pyrec->pdata, wname, &val);
	PY_INTERFACE_POSTCALL;
	PyWinObject_FreeWCHAR(wname);
	VariantClear(&val);
	if (FAILED(hr)) {
		PyCom_BuildPyException(hr, pyrec->pri, IID_IRecordInfo);
		return -1;
	}
	return 0;
}
Example #11
0
PyObject * dataconv_WriteFromOutTuple(PyObject *self, PyObject *args)
{
	PyObject *obArgTypes;
	PyObject *obArgType;
	PyObject *obRetValues;
	PyObject *obPtr;
	PyObject *obOutValue;
	VARTYPE vtArgType;
	BYTE *pbArgs;
	BYTE *pbArg;
	Py_ssize_t cArgs;
	UINT uiIndirectionLevel = 0;
	Py_ssize_t i;
	
	if (!PyArg_ParseTuple(args, "OOO:WriteFromOutTuple", &obRetValues, &obArgTypes, &obPtr))
		return NULL;

	pbArgs = (BYTE *)PyLong_AsVoidPtr(obPtr);
	assert(pbArgs);
	if (!pbArgs)
		return NULL;

	// Nothing to do, oh darn.
	if (obRetValues == Py_None || obArgTypes == Py_None)
	{
		Py_INCREF(Py_None);
		return Py_None;
	}

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

	cArgs = PyTuple_Size(obArgTypes);
	if (!PyTuple_Check(obRetValues) && (UINT)PyTuple_Size(obRetValues) != cArgs)
	{
		PyErr_Format(PyExc_TypeError, "Expecting a tuple of length %d or None.", cArgs);
		return NULL;
	}
	
	for(i = 0 ; i < cArgs; i++)
	{
		obArgType = PyTuple_GET_ITEM(PyTuple_GET_ITEM(obArgTypes, i), 0);
		vtArgType = (VARTYPE)PyInt_AS_LONG(obArgType);


		// The following types aren't supported:
		// SAFEARRAY *: This requires support for SAFEARRAYs as a
		//              Python extensions type so we can update the SAFEARRAY
		//              in place.
		// VT_LPWSTR:   This just hasn't been written yet.
		// VT_LPSTR:    This just hasn't been written yet.
		// VT_LPWSTR | VT_BYREF:
		// VT_LPSTR  | VT_BYREF:
		//              These can't be supported since we don't know the correct
		//              memory allocation policy.

		// Find the start of the argument.
		pbArg = pbArgs + PyInt_AS_LONG(PyTuple_GET_ITEM(PyTuple_GET_ITEM(obArgTypes, i), 1));
		obOutValue = PyTuple_GET_ITEM(obRetValues, i);
	
		if (vtArgType & VT_ARRAY)
		{
			VARENUM rawVT = (VARENUM)(vtArgType & VT_TYPEMASK);
			if (vtArgType & VT_BYREF)
			{
				SAFEARRAY **ppsa = *(SAFEARRAY ***)pbArg;
				SAFEARRAY *psa;
				if (!VALID_BYREF_MISSING(obOutValue))
				{
					if (!PyCom_SAFEARRAYFromPyObject(obOutValue, ppsa, rawVT))
					{
						goto Error;
					}
				}
				else
				{
					SAFEARRAYBOUND rgsabound[1];
					rgsabound[0].lLbound = 0;
					rgsabound[0].cElements = 1;
					psa = SafeArrayCreate(rawVT, 1, rgsabound);
					*ppsa = psa;
				}
			}
			else
			{
				// We can't convert this in place... Ack...
				PyErr_SetString(
					PyExc_TypeError,
					"Inplace SAFEARRAY mucking isn't allowed, doh!");
				goto Error;
				
				SAFEARRAY *psa = *(SAFEARRAY **)pbArg;
				// Here we're updating an existing SafeArray.
				// so we need to handle it very carefully....
				SafeArrayDestroy(psa);
				if (!PyCom_SAFEARRAYFromPyObject(obOutValue, &psa, rawVT))
					return NULL;
			}
		}
			
		// All done with safe array handling.

		PyObject *obUse = NULL;

		switch (vtArgType) {
		case VT_VARIANT | VT_BYREF:
		{
			VARIANT *pvar = *(VARIANT **)pbArg;
			VariantClear(pvar);
			if (!VALID_BYREF_MISSING(obOutValue)) {
				PyCom_VariantFromPyObject(obOutValue, pvar);
			}
			else
			{
				V_VT(pvar) = VT_NULL;
			}
			break;
		}
		case VT_BSTR:
		{
			// This is the normal "BSTR" case, we can't
			// allocate a new BSTR we have to back patch the one
			// thats already there...
			BSTR bstr = *(BSTR *)pbArg;
			BSTR bstrT;
			UINT cch = SysStringLen(bstr);
			if ( PyString_Check(obOutValue) || PyUnicode_Check(obOutValue) )
			{
				if ( !PyWinObject_AsBstr(obOutValue, &bstrT) )
				{
					goto Error;
				}
			}
			else
			{
				// Use str(object) instead!
				obUse = PyObject_Str(obOutValue);
				if (obUse == NULL)
				{
					goto Error;
				}
				if ( !PyWinObject_AsBstr(obUse, &bstrT) )
				{
					goto Error;
				}
			}
			
			if (SysStringLen(bstrT) > cch)
			{
				PyErr_Format(
					PyExc_ValueError,
					"Return value[%d] with type BSTR was "
					"longer than the input value: %d",
					i,
					cch);
				goto Error;
			}
				
			// Ok, now we know theres enough room in the source BSTR to
			// modify the sucker in place.
			wcscpy(bstr, bstrT);

			// Free the temp BSTR.
			SysFreeString(bstrT);
			break;
		}
		case VT_BSTR | VT_BYREF:
		{
			BSTR *pbstr = *(BSTR **)pbArg;
			BSTR bstrT = NULL;
			SysFreeString(*pbstr);

			*pbstr = NULL;
			
			if ( PyString_Check(obOutValue) || PyUnicode_Check(obOutValue) )
			{
				if ( !PyWinObject_AsBstr(obOutValue, &bstrT) )
				{
					goto Error;
				}
			}
			else
			{
				// Use str(object) instead!
				obUse = PyObject_Str(obOutValue);
				if (obUse == NULL)
				{
					goto Error;
				}
				if (!PyWinObject_AsBstr(obUse, &bstrT) )
				{
					goto Error;
				}
			}
			*pbstr = bstrT;
			break;
		}
		case VT_ERROR | VT_BYREF:
		case VT_HRESULT | VT_BYREF:
		case VT_I4 | VT_BYREF:
		{
			INT *pi = *(INT **)pbArg;
			obUse = PyNumber_Int(obOutValue);
			if (obUse == NULL)
			{
				goto Error;
			}
			*pi = PyInt_AsLong(obUse);
			if (*pi == (UINT)-1 && PyErr_Occurred())
				goto Error;
			break;
		}
		case VT_UI4 | VT_BYREF:
		{
			UINT *pui = *(UINT **)pbArg;
			// special care here as we could be > sys.maxint,
			// in which case we must work with longs.
			// Avoiding PyInt_AsUnsignedLongMask as it doesn't
			// exist in 2.2.
			if (PyLong_Check(obOutValue)) {
				*pui = PyLong_AsUnsignedLong(obOutValue);
			} else {
				// just do the generic "number" thing.
				obUse = PyNumber_Int(obOutValue);
				if (obUse == NULL)
				{
					goto Error;
				}
				*pui = (UINT)PyInt_AsLong(obUse);
			}
			if (*pui == (UINT)-1 && PyErr_Occurred())
				goto Error;
			break;
		}
		case VT_I2 | VT_BYREF:
		{
			short *ps = *(short **)pbArg;
			obUse = PyNumber_Int(obOutValue);
			if (obUse == NULL)
			{
				goto Error;
			}
			*ps = (short)PyInt_AsLong(obUse);
			if (*ps == (UINT)-1 && PyErr_Occurred())
				goto Error;
			break;
		}
		case VT_UI2 | VT_BYREF:
		{
			unsigned short *pus = *(unsigned short **)pbArg;
			obUse = PyNumber_Int(obOutValue);
			if (obUse == NULL)
			{
				goto Error;
			}
			*pus = (unsigned short)PyInt_AsLong(obUse);
			if (*pus == (UINT)-1 && PyErr_Occurred())
				goto Error;
			break;
		}
		case VT_I1 | VT_BYREF:
		{
			signed char *pb = *(signed char **)pbArg;
			obUse = PyNumber_Int(obOutValue);
			if (obUse == NULL)
			{
				goto Error;
			}
			*pb = (signed char)PyInt_AsLong(obUse);
			if (*pb == (UINT)-1 && PyErr_Occurred())
				goto Error;
			break;
		}
		case VT_UI1 | VT_BYREF:
		{
			BYTE *pb = *(BYTE **)pbArg;
			BYTE *pbOutBuffer = NULL;
			if (PyString_Check(obOutValue))
			{
				pbOutBuffer = (BYTE *)PyString_AS_STRING(obOutValue);
				Py_ssize_t cb = PyString_GET_SIZE(obOutValue);
				memcpy(pb, pbOutBuffer, cb);
			}
			// keep this after string check since string can act as buffers
			else if (obOutValue->ob_type->tp_as_buffer)
			{
				DWORD cb;
				if (!PyWinObject_AsReadBuffer(obOutValue, (void **)&pbOutBuffer, &cb))
					goto Error;
				memcpy(pb, pbOutBuffer, cb);
			}
			else
			{
				obUse = PyNumber_Int(obOutValue);
				if (obUse == NULL)
				{
					goto Error;
				}
				*pb = (BYTE)PyInt_AsLong(obUse);
				if (*pb == (UINT)-1 && PyErr_Occurred())
					goto Error;
			}
			break;
		}
		case VT_BOOL | VT_BYREF:
		{
			VARIANT_BOOL *pbool = *(VARIANT_BOOL **)pbArg;
			obUse = PyNumber_Int(obOutValue);
			if (obUse == NULL)
			{
				goto Error;
			}
			*pbool = PyInt_AsLong(obUse) ? VARIANT_TRUE : VARIANT_FALSE;
			if (*pbool == (UINT)-1 && PyErr_Occurred())
				goto Error;
			break;
		}
		case VT_R8 | VT_BYREF:
		{
			double *pdbl = *(double **)pbArg;
			obUse = PyNumber_Float(obOutValue);
			if (obUse == NULL)
			{
				goto Error;
			}
			*pdbl = PyFloat_AsDouble(obUse);
			break;
		}
		case VT_R4 | VT_BYREF:
		{
			float *pfloat = *(float **)pbArg;
			obUse = PyNumber_Float(obOutValue);
			if (obUse == NULL)
			{
				goto Error;
			}
			*pfloat = (float)PyFloat_AsDouble(obUse);
			break;
		}
		case VT_DISPATCH | VT_BYREF:
		{
			PyObject *obIID = PyTuple_GET_ITEM(PyTuple_GET_ITEM(obArgTypes, i), 3);
			IID iid = IID_IDispatch;
			if (obIID != NULL && obIID!=Py_None)
				PyWinObject_AsIID(obIID, &iid);
			IDispatch **pdisp = *(IDispatch ***)pbArg;
			if (!PyCom_InterfaceFromPyInstanceOrObject(
				obOutValue,
				iid,
				(void **)pdisp,
				TRUE))
			{
				goto Error;
			}
			// COM Reference added by InterfaceFrom...
			break;
		}
		case VT_UNKNOWN | VT_BYREF:
		{
			PyObject *obIID = PyTuple_GET_ITEM(PyTuple_GET_ITEM(obArgTypes, i), 3);
			IID iid = IID_IUnknown;
			if (obIID != NULL && obIID!=Py_None)
				PyWinObject_AsIID(obIID, &iid);
			IUnknown **punk = *(IUnknown ***)pbArg;
			if (!PyCom_InterfaceFromPyInstanceOrObject(
				obOutValue,
				iid,
				(void **)punk, TRUE))
			{
				goto Error;
			}
			// COM Reference added by InterfaceFrom...
			break;
		}
		case VT_DATE | VT_BYREF:
		{
			DATE *pdbl = *(DATE **)pbArg;
			if ( !PyWinObject_AsDATE(obOutValue, pdbl) )
			{
				goto Error;
			}
			break;
		}
		case VT_CY | VT_BYREF:
		{
			CY *pcy = *(CY **)pbArg;
			if (!PyObject_AsCurrency(obOutValue, pcy))
				goto Error;
			break;
		}
		case VT_I8 | VT_BYREF:
		{
			LARGE_INTEGER *pi64 = *(LARGE_INTEGER **)pbArg;
			if (!PyWinObject_AsLARGE_INTEGER(obOutValue, pi64))
			{
				goto Error;
			}
			break;
		}
		case VT_UI8 | VT_BYREF:
		{
			ULARGE_INTEGER *pui64 = *(ULARGE_INTEGER **)pbArg;
			if (!PyWinObject_AsULARGE_INTEGER(obOutValue, pui64))
			{
				goto Error;
			}
			break;
		}
		default:
			// could try default, but this error indicates we need to
			// beef up the VARIANT support, rather than default.
			PyErr_Format(PyExc_TypeError, "The VARIANT type is unknown (0x%x).",
			             vtArgType);
			goto Error;
		}
		
		Py_XDECREF(obUse);
	}

	Py_INCREF(Py_None);
	return Py_None;
Error:
	return NULL;
}