comtypes icon indicating copy to clipboard operation
comtypes copied to clipboard

Error setting a value on VARIANT out param

Open feerrenrut opened this issue 5 years ago • 0 comments

Some VARIANT out params are not initialised before being passed to a callback, setting these to a value results in WindowsError: [Error -2147352568] Bad variable type because comtypes attempts to clear the variant before setting the value.

Our situation:

  • Setting up an accPropServer, with method GetPropValue
  • the VARIANT out param pVarValue has not been initialised (at least on my version of Windows Version 1903 Build 18362.239).
  • Setting a value on this VARIANT results in automation.py calling _VariantClear prior to setting the value. This leads to the "bad variable type" error and then also the issue fixed with https://github.com/enthought/comtypes/pull/187.
  • When using a high level callback function, returning the out params, there is no way to initialise the out params before setting a value.

We have worked around this issue with https://github.com/nvaccess/nvda/pull/9900

Our work around is to use a low level callback, and initialise the out param VARIANT before assigning a value. Note this is what the Microsoft sample does.

Setting the accPropServer:

from IAccessibleHandler import accPropServices
accPropServices.SetHwndPropServer(
			hwnd=self.hwnd,
			idObject=winUser.OBJID_CLIENT,
			idChild=0,
			paProps=self.properties_GUIDPTR,
			cProps=len(self.properties_GUIDPTR),
			pServer=self,
			AnnoScope=ANNO_CONTAINER if annotateChildren else ANNO_THIS
		)

Initialise the VARIANT before setting a value in the GetPropValue.

def GetPropValue(
			self, this, # unused "this" used to indicate to comTypes we want a low level implementation
			pIDString: str,
			dwIDStringLen: int,
			idProp: GUID,
			pvarValue: POINTER(VARIANT),
			pfGotProp: POINTER(BOOL)
	) -> int:
		try:
			# Preset values for "no prop value", in case we return early.
			pfGotProp.contents.value = self.DOES_NOT_HAVE_PROP
			_VariantInit(pvarValue)

To fix this in comtypes, inspect the code in _comobjec.py in functions hack, call_with_this, and call_without_this. Out params of type VARIANT should be initialised with _VariantInit. Note: inout params should not be initialised, as it is expected that they contain valid arguments.

feerrenrut avatar Jul 19 '19 13:07 feerrenrut