Use raw URI as absolute URI for now. To make it fully compliant with RFC 3986 and 3987, we need to implement a parser and reconstruct the absolute URI from parts.
For React Native.
From: Zhiyi Zhang zzhang@codeweavers.com
--- configure.ac | 1 + dlls/iertutil/Makefile.in | 6 ++ dlls/iertutil/classes.idl | 28 ++++++ dlls/iertutil/iertutil.spec | 3 + dlls/iertutil/main.c | 172 +++++++++++++++++++++++++++++++++ dlls/iertutil/private.h | 75 ++++++++++++++ dlls/wintypes/classes.idl | 1 + include/windows.foundation.idl | 14 +++ 8 files changed, 300 insertions(+) create mode 100644 dlls/iertutil/Makefile.in create mode 100644 dlls/iertutil/classes.idl create mode 100644 dlls/iertutil/iertutil.spec create mode 100644 dlls/iertutil/main.c create mode 100644 dlls/iertutil/private.h
diff --git a/configure.ac b/configure.ac index f1a951807ec..5ae7890c89a 100644 --- a/configure.ac +++ b/configure.ac @@ -2700,6 +2700,7 @@ WINE_CONFIG_MAKEFILE(dlls/icmp) WINE_CONFIG_MAKEFILE(dlls/ieframe) WINE_CONFIG_MAKEFILE(dlls/ieframe/tests) WINE_CONFIG_MAKEFILE(dlls/ieproxy) +WINE_CONFIG_MAKEFILE(dlls/iertutil) WINE_CONFIG_MAKEFILE(dlls/ifsmgr.vxd,enable_win16) WINE_CONFIG_MAKEFILE(dlls/imaadp32.acm) WINE_CONFIG_MAKEFILE(dlls/imagehlp) diff --git a/dlls/iertutil/Makefile.in b/dlls/iertutil/Makefile.in new file mode 100644 index 00000000000..ba633d5ee72 --- /dev/null +++ b/dlls/iertutil/Makefile.in @@ -0,0 +1,6 @@ +MODULE = iertutil.dll +IMPORTS = combase + +SOURCES = \ + classes.idl \ + main.c diff --git a/dlls/iertutil/classes.idl b/dlls/iertutil/classes.idl new file mode 100644 index 00000000000..7124283e229 --- /dev/null +++ b/dlls/iertutil/classes.idl @@ -0,0 +1,28 @@ +/* + * Runtime Classes for iertutil.dll + * + * Copyright 2024 Zhiyi Zhang for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#pragma makedep register + +#ifdef __WIDL__ +#pragma winrt ns_prefix +#endif + +#define DO_NO_IMPORTS +#include "windows.foundation.idl" diff --git a/dlls/iertutil/iertutil.spec b/dlls/iertutil/iertutil.spec new file mode 100644 index 00000000000..20a8bfa98ea --- /dev/null +++ b/dlls/iertutil/iertutil.spec @@ -0,0 +1,3 @@ +@ stdcall -private DllCanUnloadNow() +@ stdcall -private DllGetActivationFactory(ptr ptr) +@ stdcall -private DllGetClassObject(ptr ptr ptr) diff --git a/dlls/iertutil/main.c b/dlls/iertutil/main.c new file mode 100644 index 00000000000..c0c5f96db43 --- /dev/null +++ b/dlls/iertutil/main.c @@ -0,0 +1,172 @@ +/* + * Copyright 2024 Zhiyi Zhang for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "private.h" + +WINE_DEFAULT_DEBUG_CHANNEL(iertutil); + +struct iertutil +{ + IActivationFactory IActivationFactory_iface; + IUriRuntimeClassFactory IUriRuntimeClassFactory_iface; + LONG ref; +}; + +static inline struct iertutil *impl_from_IActivationFactory(IActivationFactory *iface) +{ + return CONTAINING_RECORD(iface, struct iertutil, IActivationFactory_iface); +} + +static HRESULT STDMETHODCALLTYPE iertutil_QueryInterface(IActivationFactory *iface, REFIID iid, + void **out) +{ + struct iertutil *impl = impl_from_IActivationFactory(iface); + + TRACE("iface %p, iid %s, out %p stub!\n", iface, debugstr_guid(iid), out); + + if (IsEqualGUID(iid, &IID_IUnknown) + || IsEqualGUID(iid, &IID_IInspectable) + || IsEqualGUID(iid, &IID_IAgileObject) + || IsEqualGUID(iid, &IID_IActivationFactory)) + { + IUnknown_AddRef(iface); + *out = iface; + return S_OK; + } + else if (IsEqualGUID(iid, &IID_IUriRuntimeClassFactory)) + { + IUriRuntimeClassFactory_AddRef(&impl->IUriRuntimeClassFactory_iface); + *out = &impl->IUriRuntimeClassFactory_iface; + return S_OK; + } + + FIXME("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid)); + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG STDMETHODCALLTYPE iertutil_AddRef(IActivationFactory *iface) +{ + struct iertutil *impl = impl_from_IActivationFactory(iface); + ULONG ref = InterlockedIncrement(&impl->ref); + TRACE("iface %p, ref %lu.\n", iface, ref); + return ref; +} + +static ULONG STDMETHODCALLTYPE iertutil_Release(IActivationFactory *iface) +{ + struct iertutil *impl = impl_from_IActivationFactory(iface); + ULONG ref = InterlockedDecrement(&impl->ref); + TRACE("iface %p, ref %lu.\n", iface, ref); + return ref; +} + +static HRESULT STDMETHODCALLTYPE iertutil_GetIids(IActivationFactory *iface, ULONG *iid_count, + IID **iids) +{ + FIXME("iface %p, iid_count %p, iids %p stub!\n", iface, iid_count, iids); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE iertutil_GetRuntimeClassName(IActivationFactory *iface, + HSTRING *class_name) +{ + FIXME("iface %p, class_name %p stub!\n", iface, class_name); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE iertutil_GetTrustLevel(IActivationFactory *iface, + TrustLevel *trust_level) +{ + FIXME("iface %p, trust_level %p stub!\n", iface, trust_level); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE iertutil_ActivateInstance(IActivationFactory *iface, + IInspectable **instance) +{ + FIXME("iface %p, instance %p stub!\n", iface, instance); + return E_NOTIMPL; +} + +static const struct IActivationFactoryVtbl activation_factory_vtbl = +{ + iertutil_QueryInterface, + iertutil_AddRef, + iertutil_Release, + /* IInspectable methods */ + iertutil_GetIids, + iertutil_GetRuntimeClassName, + iertutil_GetTrustLevel, + /* IActivationFactory methods */ + iertutil_ActivateInstance, +}; + +DEFINE_IINSPECTABLE(uri_factory, IUriRuntimeClassFactory, struct iertutil, IActivationFactory_iface) + +static HRESULT STDMETHODCALLTYPE uri_factory_CreateUri(IUriRuntimeClassFactory *iface, HSTRING uri, + IUriRuntimeClass **instance) +{ + FIXME("iface %p, uri %s, instance %p stub!\n", iface, debugstr_hstring(uri), instance); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE uri_factory_CreateWithRelativeUri(IUriRuntimeClassFactory *iface, + HSTRING base_uri, + HSTRING relative_uri, + IUriRuntimeClass **instance) +{ + FIXME("iface %p, base_uri %s, relative_uri %s, instance %p stub!\n", iface, + debugstr_hstring(base_uri), debugstr_hstring(relative_uri), instance); + return E_NOTIMPL; +} + +static const struct IUriRuntimeClassFactoryVtbl uri_factory_vtbl = +{ + uri_factory_QueryInterface, + uri_factory_AddRef, + uri_factory_Release, + /* IInspectable methods */ + uri_factory_GetIids, + uri_factory_GetRuntimeClassName, + uri_factory_GetTrustLevel, + /* IUriRuntimeClassFactory methods */ + uri_factory_CreateUri, + uri_factory_CreateWithRelativeUri, +}; + +static struct iertutil iertutil = +{ + {&activation_factory_vtbl}, + {&uri_factory_vtbl}, + 1 +}; + +HRESULT WINAPI DllGetClassObject(REFCLSID clsid, REFIID riid, void **out) +{ + FIXME("clsid %s, riid %s, out %p stub!\n", debugstr_guid(clsid), debugstr_guid(riid), out); + return CLASS_E_CLASSNOTAVAILABLE; +} + +HRESULT WINAPI DllGetActivationFactory(HSTRING classid, IActivationFactory **factory) +{ + TRACE("classid %s, factory %p.\n", debugstr_hstring(classid), factory); + *factory = &iertutil.IActivationFactory_iface; + IUnknown_AddRef(*factory); + return S_OK; +} diff --git a/dlls/iertutil/private.h b/dlls/iertutil/private.h new file mode 100644 index 00000000000..80b36886a7a --- /dev/null +++ b/dlls/iertutil/private.h @@ -0,0 +1,75 @@ +/* + * Copyright 2024 Zhiyi Zhang for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef __WINE_IERTUTIL_PRIVATE_H +#define __WINE_IERTUTIL_PRIVATE_H + +#include <stdarg.h> + +#define COBJMACROS +#include "initguid.h" +#include "windef.h" +#include "winbase.h" +#include "winstring.h" +#include "wine/debug.h" +#include "activation.h" + +#define WIDL_using_Windows_Foundation +#include "windows.foundation.h" + +#define DEFINE_IINSPECTABLE_(pfx, iface_type, impl_type, impl_from, iface_mem, expr) \ + static inline impl_type *impl_from(iface_type *iface) \ + { \ + return CONTAINING_RECORD(iface, impl_type, iface_mem); \ + } \ + static HRESULT WINAPI pfx##_QueryInterface(iface_type *iface, REFIID iid, void **out) \ + { \ + impl_type *impl = impl_from(iface); \ + return IInspectable_QueryInterface((IInspectable *)(expr), iid, out); \ + } \ + static ULONG WINAPI pfx##_AddRef(iface_type *iface) \ + { \ + impl_type *impl = impl_from(iface); \ + return IInspectable_AddRef((IInspectable *)(expr)); \ + } \ + static ULONG WINAPI pfx##_Release(iface_type *iface) \ + { \ + impl_type *impl = impl_from(iface); \ + return IInspectable_Release((IInspectable *)(expr)); \ + } \ + static HRESULT WINAPI pfx##_GetIids(iface_type *iface, ULONG *iid_count, IID **iids) \ + { \ + impl_type *impl = impl_from(iface); \ + return IInspectable_GetIids((IInspectable *)(expr), iid_count, iids); \ + } \ + static HRESULT WINAPI pfx##_GetRuntimeClassName(iface_type *iface, HSTRING *class_name) \ + { \ + impl_type *impl = impl_from(iface); \ + return IInspectable_GetRuntimeClassName((IInspectable *)(expr), class_name); \ + } \ + static HRESULT WINAPI pfx##_GetTrustLevel(iface_type *iface, TrustLevel *trust_level) \ + { \ + impl_type *impl = impl_from(iface); \ + return IInspectable_GetTrustLevel((IInspectable *)(expr), trust_level); \ + } + +#define DEFINE_IINSPECTABLE(pfx, iface_type, impl_type, base_iface) \ + DEFINE_IINSPECTABLE_(pfx, iface_type, impl_type, impl_from_##iface_type, iface_type##_iface, \ + &impl->base_iface) + +#endif /* __WINE_IERTUTIL_PRIVATE_H */ diff --git a/dlls/wintypes/classes.idl b/dlls/wintypes/classes.idl index daf3fc62f66..116c764fe6e 100644 --- a/dlls/wintypes/classes.idl +++ b/dlls/wintypes/classes.idl @@ -25,5 +25,6 @@ #endif
#define DO_NO_IMPORTS +#define _WINTYPES #include "windows.foundation.idl" #include "windows.foundation.metadata.idl" diff --git a/include/windows.foundation.idl b/include/windows.foundation.idl index 88a9f576f40..9e3b656d8a3 100644 --- a/include/windows.foundation.idl +++ b/include/windows.foundation.idl @@ -109,32 +109,44 @@ namespace Windows.Foundation { interface Windows.Foundation.Collections.IIterable<HSTRING>; interface Windows.Foundation.Collections.IIterable<IInspectable *>; interface Windows.Foundation.Collections.IIterable<IWwwFormUrlDecoderEntry *>; +#ifndef _WINTYPES interface Windows.Foundation.Collections.IIterable<Uri *>; +#endif interface Windows.Foundation.Collections.IIterator<HSTRING>; interface Windows.Foundation.Collections.IIterator<IInspectable *>; interface Windows.Foundation.Collections.IIterator<IWwwFormUrlDecoderEntry *>; +#ifndef _WINTYPES interface Windows.Foundation.Collections.IIterator<Uri *>; +#endif interface Windows.Foundation.Collections.IVectorView<BYTE>; interface Windows.Foundation.Collections.IVectorView<HSTRING>; interface Windows.Foundation.Collections.IVectorView<IInspectable *>; interface Windows.Foundation.Collections.IVectorView<IWwwFormUrlDecoderEntry *>; +#ifndef _WINTYPES interface Windows.Foundation.Collections.IVectorView<Windows.Foundation.Uri *>; +#endif interface Windows.Foundation.Collections.IVector<HSTRING>; interface Windows.Foundation.Collections.IVector<IInspectable *>; interface Windows.Foundation.Collections.IMapView<HSTRING, Windows.Foundation.Collections.IVectorView<HSTRING> *>; interface Windows.Foundation.EventHandler<IInspectable *>; + interface Windows.Foundation.AsyncOperationCompletedHandler<HSTRING>; interface Windows.Foundation.AsyncOperationCompletedHandler<IInspectable *>; interface Windows.Foundation.AsyncOperationCompletedHandler<boolean>; interface Windows.Foundation.AsyncOperationCompletedHandler<HSTRING>; interface Windows.Foundation.AsyncOperationCompletedHandler<UINT32>; +#ifndef _WINTYPES interface Windows.Foundation.AsyncOperationCompletedHandler<Windows.Foundation.Uri *>; +#endif interface Windows.Foundation.AsyncOperationProgressHandler<UINT32, UINT32>; interface Windows.Foundation.AsyncOperationWithProgressCompletedHandler<UINT32, UINT32>; + interface Windows.Foundation.IAsyncOperation<HSTRING>; interface Windows.Foundation.IAsyncOperation<IInspectable *>; interface Windows.Foundation.IAsyncOperation<boolean>; interface Windows.Foundation.IAsyncOperation<HSTRING>; interface Windows.Foundation.IAsyncOperation<UINT32>; +#ifndef _WINTYPES interface Windows.Foundation.IAsyncOperation<Windows.Foundation.Uri *>; +#endif interface Windows.Foundation.IAsyncOperationWithProgress<UINT32, UINT32>; interface Windows.Foundation.IReference<BYTE>; interface Windows.Foundation.IReference<DOUBLE>; @@ -561,6 +573,7 @@ namespace Windows.Foundation { { }
+#ifndef _WINTYPES [ activatable(Windows.Foundation.IUriRuntimeClassFactory, Windows.Foundation.UniversalApiContract, 1.0), contract(Windows.Foundation.UniversalApiContract, 1.0), @@ -587,6 +600,7 @@ namespace Windows.Foundation { interface Windows.Foundation.Collections.IVectorView<Windows.Foundation.IWwwFormUrlDecoderEntry *>; interface Windows.Foundation.Collections.IIterable<Windows.Foundation.IWwwFormUrlDecoderEntry *>; } +#endif
[ contract(Windows.Foundation.UniversalApiContract, 1.0),
From: Zhiyi Zhang zzhang@codeweavers.com
--- dlls/iertutil/main.c | 232 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 230 insertions(+), 2 deletions(-)
diff --git a/dlls/iertutil/main.c b/dlls/iertutil/main.c index c0c5f96db43..9a63cfadf84 100644 --- a/dlls/iertutil/main.c +++ b/dlls/iertutil/main.c @@ -20,6 +20,214 @@
WINE_DEFAULT_DEBUG_CHANNEL(iertutil);
+struct uri +{ + IUriRuntimeClass IUriRuntimeClass_iface; + HSTRING raw_uri; + LONG ref; +}; + +static inline struct uri *impl_from_IUriRuntimeClass(IUriRuntimeClass *iface) +{ + return CONTAINING_RECORD(iface, struct uri, IUriRuntimeClass_iface); +} + +static HRESULT STDMETHODCALLTYPE uri_QueryInterface(IUriRuntimeClass *iface, REFIID iid, void **out) +{ + TRACE("iface %p, iid %s, out %p stub!\n", iface, debugstr_guid(iid), out); + + if (IsEqualGUID(iid, &IID_IUnknown) + || IsEqualGUID(iid, &IID_IInspectable) + || IsEqualGUID(iid, &IID_IUriRuntimeClass)) + { + IUnknown_AddRef(iface); + *out = iface; + return S_OK; + } + + FIXME("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid)); + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG STDMETHODCALLTYPE uri_AddRef(IUriRuntimeClass *iface) +{ + struct uri *impl = impl_from_IUriRuntimeClass(iface); + ULONG ref = InterlockedIncrement(&impl->ref); + TRACE("iface %p, ref %lu.\n", iface, ref); + return ref; +} + +static ULONG STDMETHODCALLTYPE uri_Release(IUriRuntimeClass *iface) +{ + struct uri *impl = impl_from_IUriRuntimeClass(iface); + ULONG ref = InterlockedDecrement(&impl->ref); + + TRACE("iface %p, ref %lu.\n", iface, ref); + + if (!ref) + { + WindowsDeleteString(impl->raw_uri); + free(impl); + } + + return ref; +} + +static HRESULT STDMETHODCALLTYPE uri_GetIids(IUriRuntimeClass *iface, ULONG *iid_count, + IID **iids) +{ + FIXME("iface %p, iid_count %p, iids %p stub!\n", iface, iid_count, iids); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE uri_GetRuntimeClassName(IUriRuntimeClass *iface, + HSTRING *class_name) +{ + FIXME("iface %p, class_name %p stub!\n", iface, class_name); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE uri_GetTrustLevel(IUriRuntimeClass *iface, TrustLevel *trust_level) +{ + FIXME("iface %p, trust_level %p stub!\n", iface, trust_level); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE uri_AbsoluteUri(IUriRuntimeClass *iface, HSTRING *value) +{ + FIXME("iface %p, value %p stub!\n", iface, value); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE uri_DisplayUri(IUriRuntimeClass *iface, HSTRING *value) +{ + FIXME("iface %p, value %p stub!\n", iface, value); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE uri_Domain(IUriRuntimeClass *iface, HSTRING *value) +{ + FIXME("iface %p, value %p stub!\n", iface, value); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE uri_Extension(IUriRuntimeClass *iface, HSTRING *value) +{ + FIXME("iface %p, value %p stub!\n", iface, value); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE uri_Fragment(IUriRuntimeClass *iface, HSTRING *value) +{ + FIXME("iface %p, value %p stub!\n", iface, value); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE uri_Host(IUriRuntimeClass *iface, HSTRING *value) +{ + FIXME("iface %p, value %p stub!\n", iface, value); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE uri_Password(IUriRuntimeClass *iface, HSTRING *value) +{ + FIXME("iface %p, value %p stub!\n", iface, value); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE uri_Path(IUriRuntimeClass *iface, HSTRING *value) +{ + FIXME("iface %p, value %p stub!\n", iface, value); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE uri_Query(IUriRuntimeClass *iface, HSTRING *value) +{ + FIXME("iface %p, value %p stub!\n", iface, value); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE uri_QueryParsed(IUriRuntimeClass *iface, + IWwwFormUrlDecoderRuntimeClass **decoder) +{ + FIXME("iface %p, decoder %p stub!\n", iface, decoder); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE uri_RawUri(IUriRuntimeClass *iface, HSTRING *value) +{ + FIXME("iface %p, value %p stub!\n", iface, value); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE uri_SchemeName(IUriRuntimeClass *iface, HSTRING *value) +{ + FIXME("iface %p, value %p stub!\n", iface, value); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE uri_UserName(IUriRuntimeClass *iface, HSTRING *value) +{ + FIXME("iface %p, value %p stub!\n", iface, value); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE uri_Port(IUriRuntimeClass *iface, INT32 *value) +{ + FIXME("iface %p, value %p stub!\n", iface, value); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE uri_Suspicious(IUriRuntimeClass *iface, boolean *value) +{ + FIXME("iface %p, value %p stub!\n", iface, value); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE uri_Equals(IUriRuntimeClass *iface, IUriRuntimeClass *uri, + boolean *value) +{ + FIXME("iface %p, uri %p, value %p stub!\n", iface, uri, value); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE uri_CombineUri(IUriRuntimeClass *iface, HSTRING relative_uri, + IUriRuntimeClass **instance) +{ + FIXME("iface %p, relative_uri %s, instance %p stub!\n", iface, debugstr_hstring(relative_uri), instance); + return E_NOTIMPL; +} + +static const struct IUriRuntimeClassVtbl uri_vtbl = +{ + uri_QueryInterface, + uri_AddRef, + uri_Release, + /* IInspectable methods */ + uri_GetIids, + uri_GetRuntimeClassName, + uri_GetTrustLevel, + /* IUriRuntimeClass methods */ + uri_AbsoluteUri, + uri_DisplayUri, + uri_Domain, + uri_Extension, + uri_Fragment, + uri_Host, + uri_Password, + uri_Path, + uri_Query, + uri_QueryParsed, + uri_RawUri, + uri_SchemeName, + uri_UserName, + uri_Port, + uri_Suspicious, + uri_Equals, + uri_CombineUri, +}; + struct iertutil { IActivationFactory IActivationFactory_iface; @@ -122,8 +330,28 @@ DEFINE_IINSPECTABLE(uri_factory, IUriRuntimeClassFactory, struct iertutil, IActi static HRESULT STDMETHODCALLTYPE uri_factory_CreateUri(IUriRuntimeClassFactory *iface, HSTRING uri, IUriRuntimeClass **instance) { - FIXME("iface %p, uri %s, instance %p stub!\n", iface, debugstr_hstring(uri), instance); - return E_NOTIMPL; + const WCHAR *raw_buffer; + struct uri *uri_impl; + + FIXME("iface %p, uri %s, instance %p semi-stub!\n", iface, debugstr_hstring(uri), instance); + + if (!uri) + return E_POINTER; + + uri_impl = calloc(1, sizeof(*uri_impl)); + if (!uri_impl) + return E_OUTOFMEMORY; + + uri_impl->IUriRuntimeClass_iface.lpVtbl = &uri_vtbl; + uri_impl->ref = 1; + + raw_buffer = WindowsGetStringRawBuffer(uri, NULL); + WindowsCreateString(raw_buffer, wcslen(raw_buffer), &uri_impl->raw_uri); + + /* TODO: Parse the URI according to RFC 3986 and RFC 3987 */ + + *instance = &uri_impl->IUriRuntimeClass_iface; + return S_OK; }
static HRESULT STDMETHODCALLTYPE uri_factory_CreateWithRelativeUri(IUriRuntimeClassFactory *iface,
From: Zhiyi Zhang zzhang@codeweavers.com
--- dlls/iertutil/main.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/dlls/iertutil/main.c b/dlls/iertutil/main.c index 9a63cfadf84..6847b4bd6e9 100644 --- a/dlls/iertutil/main.c +++ b/dlls/iertutil/main.c @@ -157,8 +157,11 @@ static HRESULT STDMETHODCALLTYPE uri_QueryParsed(IUriRuntimeClass *iface,
static HRESULT STDMETHODCALLTYPE uri_RawUri(IUriRuntimeClass *iface, HSTRING *value) { - FIXME("iface %p, value %p stub!\n", iface, value); - return E_NOTIMPL; + struct uri *impl = impl_from_IUriRuntimeClass(iface); + + TRACE("iface %p, value %p.\n", iface, value); + + return WindowsDuplicateString(impl->raw_uri, value); }
static HRESULT STDMETHODCALLTYPE uri_SchemeName(IUriRuntimeClass *iface, HSTRING *value)
From: Zhiyi Zhang zzhang@codeweavers.com
Use raw URI as absolute URI for now. To make it fully compliant with RFC 3986 and 3987, we need to implement a parser and reconstruct the absolute URI from parts. --- dlls/iertutil/main.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/dlls/iertutil/main.c b/dlls/iertutil/main.c index 6847b4bd6e9..70f8d4dcb99 100644 --- a/dlls/iertutil/main.c +++ b/dlls/iertutil/main.c @@ -96,8 +96,10 @@ static HRESULT STDMETHODCALLTYPE uri_GetTrustLevel(IUriRuntimeClass *iface, Trus
static HRESULT STDMETHODCALLTYPE uri_AbsoluteUri(IUriRuntimeClass *iface, HSTRING *value) { - FIXME("iface %p, value %p stub!\n", iface, value); - return E_NOTIMPL; + FIXME("iface %p, value %p semi-stub!\n", iface, value); + + /* TODO: Parse the raw URI and reconstruct it from parts according to RFC 3986 or RFC 3987 */ + return IUriRuntimeClass_get_RawUri(iface, value); }
static HRESULT STDMETHODCALLTYPE uri_DisplayUri(IUriRuntimeClass *iface, HSTRING *value)
From: Zhiyi Zhang zzhang@codeweavers.com
--- configure.ac | 1 + dlls/iertutil/tests/Makefile.in | 5 ++ dlls/iertutil/tests/iertutil.c | 100 ++++++++++++++++++++++++++++++++ 3 files changed, 106 insertions(+) create mode 100644 dlls/iertutil/tests/Makefile.in create mode 100644 dlls/iertutil/tests/iertutil.c
diff --git a/configure.ac b/configure.ac index 5ae7890c89a..8edfce44d6e 100644 --- a/configure.ac +++ b/configure.ac @@ -2701,6 +2701,7 @@ WINE_CONFIG_MAKEFILE(dlls/ieframe) WINE_CONFIG_MAKEFILE(dlls/ieframe/tests) WINE_CONFIG_MAKEFILE(dlls/ieproxy) WINE_CONFIG_MAKEFILE(dlls/iertutil) +WINE_CONFIG_MAKEFILE(dlls/iertutil/tests) WINE_CONFIG_MAKEFILE(dlls/ifsmgr.vxd,enable_win16) WINE_CONFIG_MAKEFILE(dlls/imaadp32.acm) WINE_CONFIG_MAKEFILE(dlls/imagehlp) diff --git a/dlls/iertutil/tests/Makefile.in b/dlls/iertutil/tests/Makefile.in new file mode 100644 index 00000000000..8726739cddf --- /dev/null +++ b/dlls/iertutil/tests/Makefile.in @@ -0,0 +1,5 @@ +TESTDLL = iertutil.dll +IMPORTS = combase uuid + +SOURCES = \ + iertutil.c diff --git a/dlls/iertutil/tests/iertutil.c b/dlls/iertutil/tests/iertutil.c new file mode 100644 index 00000000000..659b209dac8 --- /dev/null +++ b/dlls/iertutil/tests/iertutil.c @@ -0,0 +1,100 @@ +/* + * Copyright 2024 Zhiyi Zhang for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ +#define COBJMACROS +#include <stdarg.h> +#include "initguid.h" +#include "roapi.h" +#include "winbase.h" +#include "winstring.h" +#include "wine/debug.h" +#include "wine/test.h" + +#define WIDL_using_Windows_Foundation +#include "windows.foundation.h" + +static void test_IUriRuntimeClassFactory(void) +{ + static const WCHAR *class_name = L"Windows.Foundation.Uri"; + IAgileObject *agile_object = NULL, *tmp_agile_object = NULL; + IInspectable *inspectable = NULL, *tmp_inspectable = NULL; + IUriRuntimeClassFactory *uri_factory = NULL; + IActivationFactory *factory = NULL; + IUriRuntimeClass *uri_class = NULL; + HSTRING str, uri; + HRESULT hr; + + hr = RoInitialize(RO_INIT_MULTITHREADED); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + hr = WindowsCreateString(class_name, wcslen(class_name), &str); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + hr = RoGetActivationFactory(str, &IID_IActivationFactory, (void **)&factory); + ok(hr == S_OK || broken(hr == REGDB_E_CLASSNOTREG), "RoGetActivationFactory failed, hr %#lx.\n", hr); + WindowsDeleteString(str); + if (hr == REGDB_E_CLASSNOTREG) + { + win_skip("%s runtimeclass not registered, skipping tests.\n", wine_dbgstr_w(class_name)); + RoUninitialize(); + return; + } + + hr = IActivationFactory_QueryInterface(factory, &IID_IInspectable, (void **)&inspectable); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + hr = IActivationFactory_QueryInterface(factory, &IID_IAgileObject, (void **)&agile_object); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + hr = IActivationFactory_QueryInterface(factory, &IID_IUriRuntimeClassFactory, (void **)&uri_factory); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + hr = IUriRuntimeClassFactory_QueryInterface(uri_factory, &IID_IInspectable, (void **)&tmp_inspectable); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + ok(tmp_inspectable == inspectable, "QueryInterface IID_IInspectable returned %p, expected %p.\n", + tmp_inspectable, inspectable); + IInspectable_Release(tmp_inspectable); + IInspectable_Release(inspectable); + + hr = IUriRuntimeClassFactory_QueryInterface(uri_factory, &IID_IAgileObject, (void **)&tmp_agile_object); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + ok(tmp_agile_object == agile_object, "QueryInterface IID_IAgileObject returned %p, expected %p.\n", + tmp_agile_object, agile_object); + IAgileObject_Release(tmp_agile_object); + IAgileObject_Release(agile_object); + + /* Test IUriRuntimeClassFactory_CreateUri() */ + hr = WindowsCreateString(L"https://www.winehq.org", wcslen(L"https://www.winehq.org"), &uri); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + hr = IUriRuntimeClassFactory_CreateUri(uri_factory, NULL, &uri_class); + ok(hr == E_POINTER, "Got unexpected hr %#lx.\n", hr); + + hr = IUriRuntimeClassFactory_CreateUri(uri_factory, uri, &uri_class); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + IUriRuntimeClass_Release(uri_class); + + WindowsDeleteString(uri); + + IUriRuntimeClassFactory_Release(uri_factory); + IActivationFactory_Release(factory); + RoUninitialize(); +} + +START_TEST(iertutil) +{ + test_IUriRuntimeClassFactory(); +}
From: Zhiyi Zhang zzhang@codeweavers.com
--- dlls/iertutil/tests/iertutil.c | 71 ++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+)
diff --git a/dlls/iertutil/tests/iertutil.c b/dlls/iertutil/tests/iertutil.c index 659b209dac8..0f77b8a7f28 100644 --- a/dlls/iertutil/tests/iertutil.c +++ b/dlls/iertutil/tests/iertutil.c @@ -94,7 +94,78 @@ static void test_IUriRuntimeClassFactory(void) RoUninitialize(); }
+static void test_IUriRuntimeClass(void) +{ + static const WCHAR *class_name = L"Windows.Foundation.Uri"; + IActivationFactory *activation_factory = NULL; + IUriRuntimeClassFactory *uri_factory = NULL; + IUriRuntimeClass *uri_class = NULL; + IInspectable *inspectable = NULL; + IPropertyValue *value; + HSTRING str, uri; + HRESULT hr; + INT32 res; + + hr = RoInitialize(RO_INIT_MULTITHREADED); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + hr = WindowsCreateString(class_name, wcslen(class_name), &str); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + hr = RoGetActivationFactory(str, &IID_IActivationFactory, (void **)&activation_factory); + ok(hr == S_OK || broken(hr == REGDB_E_CLASSNOTREG), "RoGetActivationFactory failed, hr %#lx.\n", hr); + WindowsDeleteString(str); + if (hr == REGDB_E_CLASSNOTREG) + { + win_skip("%s runtimeclass not registered, skipping tests.\n", wine_dbgstr_w(class_name)); + RoUninitialize(); + return; + } + + hr = IActivationFactory_QueryInterface(activation_factory, &IID_IUriRuntimeClassFactory, (void **)&uri_factory); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + hr = WindowsCreateString(L"https://www.winehq.org/", wcslen(L"https://www.winehq.org/"), &uri); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + hr = IUriRuntimeClassFactory_CreateUri(uri_factory, uri, &uri_class); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + hr = IUriRuntimeClass_QueryInterface(uri_class, &IID_IInspectable, (void **)&inspectable); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + ok(uri_class == (void *)inspectable, "QueryInterface IID_IInspectable returned %p, expected %p.\n", + inspectable, uri_factory); + IInspectable_Release(inspectable); + + hr = IUriRuntimeClass_QueryInterface(uri_class, &IID_IPropertyValue, (void **)&value); + ok(hr == E_NOINTERFACE, "Got unexpected hr %#lx.\n", hr); + + /* Test IUriRuntimeClass_get_RawUri() */ + hr = IUriRuntimeClass_get_RawUri(uri_class, &str); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + ok(str != uri, "Expected a different pointer.\n"); + hr = WindowsCompareStringOrdinal(uri, str, &res); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + ok(res == 0, "Expected %s, got %s.\n", debugstr_hstring(uri), debugstr_hstring(str)); + WindowsDeleteString(str); + + /* Test IUriRuntimeClass_get_AbsoluteUri() */ + hr = IUriRuntimeClass_get_AbsoluteUri(uri_class, &str); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + ok(str != uri, "Expected a different pointer.\n"); + hr = WindowsCompareStringOrdinal(uri, str, &res); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + ok(res == 0, "Expected %s, got %s.\n", debugstr_hstring(uri), debugstr_hstring(str)); + WindowsDeleteString(str); + + WindowsDeleteString(uri); + IUriRuntimeClass_Release(uri_class); + IUriRuntimeClassFactory_Release(uri_factory); + IActivationFactory_Release(activation_factory); + RoUninitialize(); +} + + START_TEST(iertutil) { test_IUriRuntimeClassFactory(); + test_IUriRuntimeClass(); }