Signed-off-by: Connor McAdams cmcadams@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; +}; + +static struct uia_rsrv_ftmarshaler *uia_rsrv_ns_val_ftmarshaler = NULL; + +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; + } + + *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; +} + +static ULONG WINAPI uia_reserved_ns_AddRef(IUnknown *iface) +{ + return 1; +} + +static ULONG WINAPI uia_reserved_ns_Release(IUnknown *iface) +{ + return 1; +} + +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; }