enthought / enthought/comtypes

Error setting a value on VARIANT out param

Open
#188 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Python
Stars
345
Forks
105
PR merge metrics
No merged PRs in 30d

Description

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`](https://docs.microsoft.com/en-us/windows/win32/api/oleacc/nf-oleacc-iaccpropserver-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.](https://docs.microsoft.com/en-us/windows/win32/winauto/server-annotation-sample)

Setting the accPropServer:
``` Python
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`.

``` Python
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.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.