[PATCH v2 1/3] uiautomationcore: Implement UiaGetReservedNotSupportedValue.

Connor McAdams cmcadams at codeweavers.com
Thu Oct 28 13:19:32 CDT 2021


On Thu, Oct 28, 2021 at 09:02:40PM +0300, Nikolay Sivov wrote:
> 
> 
> 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.
>

Yeah, I agree the naming is a bit confusing. I was having trouble with
that, but I'll use the name you've suggested in the next version.

> > +
> > +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.

Oof, yeah, good catch.

> > +
> > +    *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.

Ah, okay. In our last discussion you had asked if it was really that
important that QI returns a new instance each time, so I assumed you
wanted a shared instance across each call. I can go back to creating a
unique one each time though like I was doing before.

> > +
> > +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;
> >  }
> >  
> 
> 

Thanks for the review.



More information about the wine-devel mailing list