[PATCH v2 1/3] uiautomationcore: Implement UiaGetReservedNotSupportedValue.
Nikolay Sivov
nsivov at codeweavers.com
Thu Oct 28 13:02:40 CDT 2021
On 10/28/21 6:17 PM, Connor McAdams wrote:
> Signed-off-by: Connor McAdams <cmcadams at codeweavers.com>
> ---
> dlls/uiautomationcore/Makefile.in | 1 +
> dlls/uiautomationcore/uia_main.c | 147 +++++++++++++++++++++++++++++-
> 2 files changed, 146 insertions(+), 2 deletions(-)
>
> diff --git a/dlls/uiautomationcore/Makefile.in b/dlls/uiautomationcore/Makefile.in
> index 71ea7b99c94..5a72ea144c4 100644
> --- a/dlls/uiautomationcore/Makefile.in
> +++ b/dlls/uiautomationcore/Makefile.in
> @@ -1,5 +1,6 @@
> MODULE = uiautomationcore.dll
> IMPORTLIB = uiautomationcore
> +IMPORTS = uuid ole32
>
> EXTRADLLFLAGS = -Wb,--prefer-native
>
> diff --git a/dlls/uiautomationcore/uia_main.c b/dlls/uiautomationcore/uia_main.c
> index 2dada95af80..51c220c6041 100644
> --- a/dlls/uiautomationcore/uia_main.c
> +++ b/dlls/uiautomationcore/uia_main.c
> @@ -16,12 +16,150 @@
> * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
> */
>
> +#define COBJMACROS
> +
> #include "uiautomation.h"
>
> #include "wine/debug.h"
> +#include "wine/heap.h"
>
> WINE_DEFAULT_DEBUG_CHANNEL(uiautomation);
>
> +struct uia_rsrv_ftmarshaler
> +{
> + IUnknown IUnknown_iface;
> + LONG refcount;
> +
> + IUnknown *inner;
> + IUnknown *rsrv_val;
> +};
I think naming is confusing. 'inner' here really means marshaler,
rsrv_val is the object marshaler is associated with, and the whole thing
is not an ftmarshaler, but something like a host or a wrapper.
> +
> +static struct uia_rsrv_ftmarshaler *uia_rsrv_ns_val_ftmarshaler = NULL;
I thought you said that new instances are created every time?
> +
> +static struct uia_rsrv_ftmarshaler *impl_uia_rsrv_ftmarshaler_from_IUnknown(IUnknown *iface)
> +{
> + return CONTAINING_RECORD(iface, struct uia_rsrv_ftmarshaler, IUnknown_iface);
> +}
> +
> +static HRESULT WINAPI uia_rsrv_ftmarshaler_QueryInterface(IUnknown *iface,
> + REFIID riid, void **ppv)
> +{
> + struct uia_rsrv_ftmarshaler *marshaler = impl_uia_rsrv_ftmarshaler_from_IUnknown(iface);
> +
> + return IUnknown_QueryInterface(marshaler->rsrv_val, riid, ppv);
> +}
> +
> +static ULONG WINAPI uia_rsrv_ftmarshaler_AddRef(IUnknown *iface)
> +{
> + struct uia_rsrv_ftmarshaler *marshaler = impl_uia_rsrv_ftmarshaler_from_IUnknown(iface);
> + ULONG refcount = InterlockedIncrement(&marshaler->refcount);
> +
> + TRACE("%p, refcount %d\n", iface, refcount);
> +
> + return refcount;
> +}
> +
> +static ULONG WINAPI uia_rsrv_ftmarshaler_Release(IUnknown *iface)
> +{
> + struct uia_rsrv_ftmarshaler *marshaler = impl_uia_rsrv_ftmarshaler_from_IUnknown(iface);
> + ULONG refcount = InterlockedDecrement(&marshaler->refcount);
> +
> + TRACE("%p, refcount %d\n", iface, refcount);
> + if (!refcount)
> + {
> + if (marshaler == uia_rsrv_ns_val_ftmarshaler)
> + uia_rsrv_ns_val_ftmarshaler = NULL;
> +
> + IUnknown_Release(marshaler->inner);
> + heap_free(marshaler);
> + }
> +
> + return refcount;
> +}
> +
> +static const IUnknownVtbl uia_rsrv_ftmarshaler_vtbl = {
> + uia_rsrv_ftmarshaler_QueryInterface,
> + uia_rsrv_ftmarshaler_AddRef,
> + uia_rsrv_ftmarshaler_Release,
> +};
> +
> +/*
> + * When passing the ReservedNotSupportedValue/ReservedMixedAttributeValue
> + * interface pointers across apartments within the same process, create a free
> + * threaded marshaler so that the pointer value is preserved.
> + */
> +static HRESULT uia_rsrv_val_create_ftmarshaler(IUnknown *reserved, struct uia_rsrv_ftmarshaler **marshaler)
> +{
> + struct uia_rsrv_ftmarshaler *object;
> + HRESULT hr;
> +
> + TRACE("%p, %p\n", reserved, marshaler);
> +
> + object = heap_alloc(sizeof(*object));
> + if (!object)
> + return E_OUTOFMEMORY;
> +
> + object->IUnknown_iface.lpVtbl = &uia_rsrv_ftmarshaler_vtbl;
> + object->refcount = 1;
> +
> + hr = CoCreateFreeThreadedMarshaler(&object->IUnknown_iface, &object->inner);
> + if (FAILED(hr = CoCreateFreeThreadedMarshaler(&object->IUnknown_iface, &object->inner)))
> + {
> + heap_free(object);
> + return hr;
> + }
This one is obviously copy-paste typo.
> +
> + *marshaler = object;
> +
> + return hr;
> +}
> +
> +/*
> + * UiaReservedNotSupported object.
> + */
> +static HRESULT WINAPI uia_reserved_ns_QueryInterface(IUnknown *iface,
> + REFIID riid, void **ppv)
> +{
> + *ppv = NULL;
> + if (IsEqualIID(riid, &IID_IUnknown))
> + *ppv = iface;
> + else if (IsEqualIID(riid, &IID_IMarshal))
> + {
> + if (!uia_rsrv_ns_val_ftmarshaler)
> + {
> + if (FAILED(uia_rsrv_val_create_ftmarshaler(iface, &uia_rsrv_ns_val_ftmarshaler)))
> + return E_NOINTERFACE;
> + }
> +
> + if (FAILED(IUnknown_QueryInterface(uia_rsrv_ns_val_ftmarshaler->inner, riid, ppv)))
> + return E_NOINTERFACE;
> +
> + IUnknown_Release(&uia_rsrv_ns_val_ftmarshaler->IUnknown_iface);
> + }
> + else
> + return E_NOINTERFACE;
> +
> + return S_OK;
> +}
It's not safe to handle shared pointer like that, when you know you're
going to run in multithreaded environment.
I think creating that helper wrapper/host object, and then creating
marshaler on every call should be fine.
> +
> +static ULONG WINAPI uia_reserved_ns_AddRef(IUnknown *iface)
> +{
> + return 1;
> +}
> +
> +static ULONG WINAPI uia_reserved_ns_Release(IUnknown *iface)
> +{
> + return 1;
> +}
That probably doesn't matter, but I'll mentioned it anyway, occasionally
for such singleton objects they still maintain refcount field, that
doesn't do anything, expect changing its value.
> +
> +static const IUnknownVtbl uia_reserved_ns_vtbl = {
> + uia_reserved_ns_QueryInterface,
> + uia_reserved_ns_AddRef,
> + uia_reserved_ns_Release,
> +};
> +
> +static IUnknown uia_reserved_ns_iface = {&uia_reserved_ns_vtbl};
> +
> /***********************************************************************
> * UiaClientsAreListening (uiautomationcore.@)
> */
> @@ -46,8 +184,13 @@ HRESULT WINAPI UiaGetReservedMixedAttributeValue(IUnknown **value)
> */
> HRESULT WINAPI UiaGetReservedNotSupportedValue(IUnknown **value)
> {
> - FIXME("(%p) stub!\n", value);
> - *value = NULL;
> + TRACE("(%p)\n", value);
> +
> + if (!value)
> + return E_INVALIDARG;
> +
> + *value = &uia_reserved_ns_iface;
> +
> return S_OK;
> }
>
More information about the wine-devel
mailing list