For React Native.
From: Zhiyi Zhang zzhang@codeweavers.com
--- .../tests/globalization.c | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+)
diff --git a/dlls/windows.globalization/tests/globalization.c b/dlls/windows.globalization/tests/globalization.c index 1abbc161cfd..1b26493b2f3 100644 --- a/dlls/windows.globalization/tests/globalization.c +++ b/dlls/windows.globalization/tests/globalization.c @@ -384,6 +384,75 @@ static void test_GeographicRegion(void) ok( ref == 1, "got ref %ld.\n", ref ); }
+static void test_ApplicationLanguages(void) +{ + static const WCHAR *class_name = RuntimeClass_Windows_Globalization_ApplicationLanguages; + IApplicationLanguagesStatics *application_languages_statics; + WCHAR locale[LOCALE_NAME_MAX_LENGTH]; + IVectorView_HSTRING *languages; + IActivationFactory *factory; + BOOL found = FALSE; + const WCHAR *ptr; + UINT32 size, i; + HSTRING str; + HRESULT hr; + LONG ref; + int ret; + + hr = WindowsCreateString( class_name, wcslen( class_name ), &str ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + + hr = RoGetActivationFactory( str, &IID_IActivationFactory, (void **)&factory ); + WindowsDeleteString( str ); + todo_wine + ok( hr == S_OK || broken( hr == REGDB_E_CLASSNOTREG ), "got hr %#lx.\n", hr ); + if (FAILED( hr )) + { + todo_wine + win_skip( "%s runtimeclass not found, skipping tests.\n", wine_dbgstr_w( class_name ) ); + return; + } + + check_interface( factory, &IID_IUnknown ); + check_interface( factory, &IID_IInspectable ); + check_interface( factory, &IID_IAgileObject ); + check_interface( factory, &IID_IActivationFactory ); + check_interface( factory, &IID_IApplicationLanguagesStatics ); + + hr = IActivationFactory_QueryInterface( factory, &IID_IApplicationLanguagesStatics, (void **)&application_languages_statics ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + + hr = IApplicationLanguagesStatics_get_Languages( application_languages_statics, &languages ); + ok( hr == S_OK || broken( hr == 0x80073d54 ) /* Win8 */, "got hr %#lx.\n", hr ); + if (FAILED( hr )) + goto done; + + hr = IVectorView_HSTRING_get_Size( languages, &size ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + ok( size > 0, "Got unexpected %u.\n", size ); + + ret = GetUserDefaultLocaleName( locale, LOCALE_NAME_MAX_LENGTH ); + ok( ret > 0, "GetUserDefaultLocaleName failed, error %lu.\n", GetLastError() ); + + for (i = 0; i < size; i++) + { + hr = IVectorView_HSTRING_GetAt( languages, i, &str ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + ptr = WindowsGetStringRawBuffer( str, NULL ); + found = !wcscmp( ptr, locale ); + WindowsDeleteString( str ); + if (found) + break; + } + ok( found, "Language not found.\n" ); + +done: + ref = IApplicationLanguagesStatics_Release( application_languages_statics ); + ok( ref == 2, "got ref %ld.\n", ref ); + ref = IActivationFactory_Release( factory ); + ok( ref == 1, "got ref %ld.\n", ref ); +} + START_TEST(globalization) { HMODULE kernel32; @@ -398,6 +467,7 @@ START_TEST(globalization) test_GlobalizationPreferences(); test_Language(); test_GeographicRegion(); + test_ApplicationLanguages();
RoUninitialize(); }
From: Zhiyi Zhang zzhang@codeweavers.com
--- dlls/windows.globalization/main.c | 211 ++++++++++++++++++ .../tests/globalization.c | 2 - 2 files changed, 211 insertions(+), 2 deletions(-)
diff --git a/dlls/windows.globalization/main.c b/dlls/windows.globalization/main.c index 37746ae8d52..a7443bc21b3 100644 --- a/dlls/windows.globalization/main.c +++ b/dlls/windows.globalization/main.c @@ -388,6 +388,13 @@ static const struct IIterable_HSTRINGVtbl iterable_view_hstring_vtbl = iterable_view_hstring_First, };
+struct application_languages +{ + IActivationFactory IActivationFactory_iface; + IApplicationLanguagesStatics IApplicationLanguagesStatics_iface; + LONG ref; +}; + struct windows_globalization { IActivationFactory IActivationFactory_iface; @@ -414,6 +421,16 @@ static inline struct windows_globalization *impl_from_IActivationFactory(IActiva return CONTAINING_RECORD(iface, struct windows_globalization, IActivationFactory_iface); }
+static inline struct application_languages *impl_application_languages_from_IActivationFactory(IActivationFactory *iface) +{ + return CONTAINING_RECORD(iface, struct application_languages, IActivationFactory_iface); +} + +static inline struct application_languages *impl_application_languages_from_IApplicationLanguagesStatics(IApplicationLanguagesStatics *iface) +{ + return CONTAINING_RECORD(iface, struct application_languages, IApplicationLanguagesStatics_iface); +} + static inline struct language_factory *impl_language_factory_from_IActivationFactory(IActivationFactory *iface) { return CONTAINING_RECORD(iface, struct language_factory, IActivationFactory_iface); @@ -902,6 +919,195 @@ static struct language_factory language_factory = 0 };
+static HRESULT STDMETHODCALLTYPE application_languages_activation_factory_QueryInterface( + IActivationFactory *iface, REFIID iid, void **out) +{ + struct application_languages *languages = impl_application_languages_from_IActivationFactory(iface); + + TRACE("iface %p, iid %s, out %p.\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_IApplicationLanguagesStatics)) + { + IUnknown_AddRef(&languages->IApplicationLanguagesStatics_iface); + *out = &languages->IApplicationLanguagesStatics_iface; + return S_OK; + } + + FIXME("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid)); + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG STDMETHODCALLTYPE application_languages_activation_factory_AddRef(IActivationFactory *iface) +{ + struct application_languages *languages = impl_application_languages_from_IActivationFactory(iface); + ULONG ref = InterlockedIncrement(&languages->ref); + TRACE("iface %p, ref %lu.\n", iface, ref); + return ref; +} + +static ULONG STDMETHODCALLTYPE application_languages_activation_factory_Release(IActivationFactory *iface) +{ + struct application_languages *languages = impl_application_languages_from_IActivationFactory(iface); + ULONG ref = InterlockedDecrement(&languages->ref); + TRACE("iface %p, ref %lu.\n", iface, ref); + return ref; +} + +static HRESULT STDMETHODCALLTYPE application_languages_activation_factory_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 application_languages_activation_factory_GetRuntimeClassName( + IActivationFactory *iface, HSTRING *class_name) +{ + FIXME("iface %p, class_name %p stub!\n", iface, class_name); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE application_languages_activation_factory_GetTrustLevel( + IActivationFactory *iface, TrustLevel *trust_level) +{ + FIXME("iface %p, trust_level %p stub!\n", iface, trust_level); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE application_languages_activation_factory_ActivateInstance( + IActivationFactory *iface, IInspectable **instance) +{ + FIXME("iface %p, instance %p stub!\n", iface, instance); + return E_NOTIMPL; +} + +static const struct IActivationFactoryVtbl application_languages_activation_factory_vtbl = +{ + /* IUnknown methods */ + application_languages_activation_factory_QueryInterface, + application_languages_activation_factory_AddRef, + application_languages_activation_factory_Release, + /* IInspectable methods */ + application_languages_activation_factory_GetIids, + application_languages_activation_factory_GetRuntimeClassName, + application_languages_activation_factory_GetTrustLevel, + /* IActivationFactory methods */ + application_languages_activation_factory_ActivateInstance, +}; + +static HRESULT STDMETHODCALLTYPE application_languages_statics_QueryInterface( + IApplicationLanguagesStatics *iface, REFIID iid, void **out) +{ + struct application_languages *languages = impl_application_languages_from_IApplicationLanguagesStatics(iface); + return application_languages_activation_factory_QueryInterface(&languages->IActivationFactory_iface, iid, out); +} + +static ULONG STDMETHODCALLTYPE application_languages_statics_AddRef(IApplicationLanguagesStatics *iface) +{ + struct application_languages *languages = impl_application_languages_from_IApplicationLanguagesStatics(iface); + return application_languages_activation_factory_AddRef(&languages->IActivationFactory_iface); +} + +static ULONG STDMETHODCALLTYPE application_languages_statics_Release(IApplicationLanguagesStatics *iface) +{ + struct application_languages *languages = impl_application_languages_from_IApplicationLanguagesStatics(iface); + return application_languages_activation_factory_Release(&languages->IActivationFactory_iface); +} + +static HRESULT STDMETHODCALLTYPE application_languages_statics_GetIids( + IApplicationLanguagesStatics *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 application_languages_statics_GetRuntimeClassName( + IApplicationLanguagesStatics *iface, HSTRING *class_name) +{ + FIXME("iface %p, class_name %p stub!\n", iface, class_name); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE application_languages_statics_GetTrustLevel( + IApplicationLanguagesStatics *iface, TrustLevel *trust_level) +{ + FIXME("iface %p, trust_level %p stub!\n", iface, trust_level); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE application_languages_statics_get_PrimaryLanguageOverride( + IApplicationLanguagesStatics *iface, HSTRING *value) +{ + FIXME("iface %p, value %p stub!\n", iface, value); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE application_languages_statics_put_PrimaryLanguageOverride( + IApplicationLanguagesStatics *iface, HSTRING value) +{ + FIXME("iface %p, value %s stub!\n", iface, wine_dbgstr_hstring(value)); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE application_languages_statics_get_Languages( + IApplicationLanguagesStatics *iface, IVectorView_HSTRING **value) +{ + WCHAR locale[LOCALE_NAME_MAX_LENGTH]; + HSTRING hstring; + HRESULT hr; + + FIXME("iface %p, out %p stub!\n", iface, value); + + if (!GetUserDefaultLocaleName(locale, LOCALE_NAME_MAX_LENGTH)) + return E_FAIL; + + if (FAILED(hr = WindowsCreateString(locale, wcslen(locale), &hstring))) + return hr; + + return hstring_vector_create(&hstring, 1, value); +} + +static HRESULT STDMETHODCALLTYPE application_languages_statics_get_ManifestLanguages( + IApplicationLanguagesStatics *iface, IVectorView_HSTRING **value) +{ + FIXME("iface %p, value %p stub!\n", iface, value); + return E_NOTIMPL; +} + +static const struct IApplicationLanguagesStaticsVtbl application_languages_statics_vtbl = +{ + /* IUnknown methods */ + application_languages_statics_QueryInterface, + application_languages_statics_AddRef, + application_languages_statics_Release, + /* IInspectable methods */ + application_languages_statics_GetIids, + application_languages_statics_GetRuntimeClassName, + application_languages_statics_GetTrustLevel, + /* IApplicationLanguagesStatics methods */ + application_languages_statics_get_PrimaryLanguageOverride, + application_languages_statics_put_PrimaryLanguageOverride, + application_languages_statics_get_Languages, + application_languages_statics_get_ManifestLanguages +}; + +static struct application_languages application_languages = +{ + {&application_languages_activation_factory_vtbl}, + {&application_languages_statics_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); @@ -931,6 +1137,11 @@ HRESULT WINAPI DllGetActivationFactory(HSTRING classid, IActivationFactory **fac *factory = geographic_region_factory; IUnknown_AddRef(*factory); } + else if (!wcscmp(name, RuntimeClass_Windows_Globalization_ApplicationLanguages)) + { + *factory = &application_languages.IActivationFactory_iface; + IUnknown_AddRef(*factory); + }
if (*factory) return S_OK; return CLASS_E_CLASSNOTAVAILABLE; diff --git a/dlls/windows.globalization/tests/globalization.c b/dlls/windows.globalization/tests/globalization.c index 1b26493b2f3..b1e21c88a47 100644 --- a/dlls/windows.globalization/tests/globalization.c +++ b/dlls/windows.globalization/tests/globalization.c @@ -404,11 +404,9 @@ static void test_ApplicationLanguages(void)
hr = RoGetActivationFactory( str, &IID_IActivationFactory, (void **)&factory ); WindowsDeleteString( str ); - todo_wine ok( hr == S_OK || broken( hr == REGDB_E_CLASSNOTREG ), "got hr %#lx.\n", hr ); if (FAILED( hr )) { - todo_wine win_skip( "%s runtimeclass not found, skipping tests.\n", wine_dbgstr_w( class_name ) ); return; }
From: Zhiyi Zhang zzhang@codeweavers.com
--- .../tests/globalization.c | 45 ++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-)
diff --git a/dlls/windows.globalization/tests/globalization.c b/dlls/windows.globalization/tests/globalization.c index b1e21c88a47..b3d4899a431 100644 --- a/dlls/windows.globalization/tests/globalization.c +++ b/dlls/windows.globalization/tests/globalization.c @@ -236,15 +236,27 @@ static void test_GlobalizationPreferences(void) static void test_Language(void) { static const WCHAR *class_name = L"Windows.Globalization.Language"; - + static const struct + { + const WCHAR *tag; + enum LanguageLayoutDirection direction; + } + lang_layout_direction_tests[] = + { + {L"en-US", LanguageLayoutDirection_Ltr}, + {L"ar-SA", LanguageLayoutDirection_Rtl}, + }; IAgileObject *agile_object, *tmp_agile_object; IInspectable *inspectable, *tmp_inspectable; + enum LanguageLayoutDirection direction; WCHAR buffer[LOCALE_NAME_MAX_LENGTH]; ILanguageFactory *language_factory; IActivationFactory *factory; + ILanguage2 *language2; ILanguage *language; HSTRING tag, str; const WCHAR *buf; + unsigned int i; HRESULT hr;
hr = WindowsCreateString(class_name, wcslen(class_name), &str); @@ -304,6 +316,37 @@ static void test_Language(void)
ILanguage_Release(language);
+ /* ILanguage2 */ + for (i = 0; i < ARRAY_SIZE(lang_layout_direction_tests); i++) + { + winetest_push_context("%s", wine_dbgstr_w(lang_layout_direction_tests[i].tag)); + + hr = WindowsCreateString(lang_layout_direction_tests[i].tag, wcslen(lang_layout_direction_tests[i].tag), &str); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = ILanguageFactory_CreateLanguage(language_factory, str, &language); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + WindowsDeleteString(str); + + hr = ILanguage_QueryInterface(language, &IID_ILanguage2, (void **)&language2); + todo_wine + ok(hr == S_OK || broken(hr == E_NOINTERFACE) /* <= Windows 10 1507 */, "Unexpected hr %#lx.\n", hr); + if (FAILED(hr)) + { + ILanguage_Release(language); + winetest_pop_context(); + break; + } + + hr = ILanguage2_get_LayoutDirection(language2, &direction); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(direction == lang_layout_direction_tests[i].direction, "Expected direction %d, got %d.\n", + lang_layout_direction_tests[i].direction, direction); + + ILanguage2_Release(language2); + ILanguage_Release(language); + winetest_pop_context(); + } + ILanguageFactory_Release(language_factory);
IAgileObject_Release(agile_object);
From: Zhiyi Zhang zzhang@codeweavers.com
--- dlls/windows.globalization/main.c | 79 +++++++++++++++++++ .../tests/globalization.c | 1 - 2 files changed, 79 insertions(+), 1 deletion(-)
diff --git a/dlls/windows.globalization/main.c b/dlls/windows.globalization/main.c index a7443bc21b3..b870c547d2f 100644 --- a/dlls/windows.globalization/main.c +++ b/dlls/windows.globalization/main.c @@ -412,6 +412,7 @@ struct language_factory struct language { ILanguage ILanguage_iface; + ILanguage2 ILanguage2_iface; LONG ref; WCHAR name[LOCALE_NAME_MAX_LENGTH]; }; @@ -451,9 +452,16 @@ static inline struct language *impl_from_ILanguage(ILanguage *iface) return CONTAINING_RECORD(iface, struct language, ILanguage_iface); }
+static inline struct language *impl_from_ILanguage2(ILanguage2 *iface) +{ + return CONTAINING_RECORD(iface, struct language, ILanguage2_iface); +} + static HRESULT STDMETHODCALLTYPE language_QueryInterface( ILanguage *iface, REFIID iid, void **out) { + struct language *language = impl_from_ILanguage(iface); + TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
if (IsEqualGUID(iid, &IID_IUnknown) || @@ -465,6 +473,12 @@ static HRESULT STDMETHODCALLTYPE language_QueryInterface( *out = iface; return S_OK; } + else if (IsEqualGUID(iid, &IID_ILanguage2)) + { + IUnknown_AddRef(&language->ILanguage2_iface); + *out = &language->ILanguage2_iface; + return S_OK; + }
FIXME("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid)); *out = NULL; @@ -562,6 +576,70 @@ static const struct ILanguageVtbl language_vtbl = language_get_Script, };
+static HRESULT STDMETHODCALLTYPE language2_QueryInterface(ILanguage2 *iface, REFIID iid, void **out) +{ + struct language *language = impl_from_ILanguage2(iface); + return language_QueryInterface(&language->ILanguage_iface, iid, out); +} + +static ULONG STDMETHODCALLTYPE language2_AddRef(ILanguage2 *iface) +{ + struct language *language = impl_from_ILanguage2(iface); + return language_AddRef(&language->ILanguage_iface); +} + +static ULONG STDMETHODCALLTYPE language2_Release(ILanguage2 *iface) +{ + struct language *language = impl_from_ILanguage2(iface); + return language_Release(&language->ILanguage_iface); +} + +static HRESULT STDMETHODCALLTYPE language2_GetIids(ILanguage2 *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 language2_GetRuntimeClassName(ILanguage2 *iface, HSTRING *class_name) +{ + FIXME("iface %p, class_name %p stub!\n", iface, class_name); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE language2_GetTrustLevel(ILanguage2 *iface, TrustLevel *trust_level) +{ + FIXME("iface %p, trust_level %p stub!\n", iface, trust_level); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE language2_get_LayoutDirection(ILanguage2 *iface, enum LanguageLayoutDirection *value) +{ + struct language *language = impl_from_ILanguage2(iface); + DWORD reading_layout; + + TRACE("iface %p, value %p.\n", iface, value); + + if (!GetLocaleInfoEx(language->name, LOCALE_IREADINGLAYOUT | LOCALE_RETURN_NUMBER, + (void *)&reading_layout, sizeof(reading_layout))) + return E_FAIL; + + *value = (enum LanguageLayoutDirection)reading_layout; + return S_OK; +} + +static const struct ILanguage2Vtbl language2_vtbl = +{ + language2_QueryInterface, + language2_AddRef, + language2_Release, + /* IInspectable methods */ + language2_GetIids, + language2_GetRuntimeClassName, + language2_GetTrustLevel, + /* ILanguage2 methods */ + language2_get_LayoutDirection, +}; + static HRESULT STDMETHODCALLTYPE windows_globalization_QueryInterface( IActivationFactory *iface, REFIID iid, void **out) { @@ -891,6 +969,7 @@ static HRESULT STDMETHODCALLTYPE language_factory_CreateLanguage( return E_OUTOFMEMORY;
language->ILanguage_iface.lpVtbl = &language_vtbl; + language->ILanguage2_iface.lpVtbl = &language2_vtbl; language->ref = 1; wcscpy(language->name, buffer);
diff --git a/dlls/windows.globalization/tests/globalization.c b/dlls/windows.globalization/tests/globalization.c index b3d4899a431..dd9b7027f7c 100644 --- a/dlls/windows.globalization/tests/globalization.c +++ b/dlls/windows.globalization/tests/globalization.c @@ -328,7 +328,6 @@ static void test_Language(void) WindowsDeleteString(str);
hr = ILanguage_QueryInterface(language, &IID_ILanguage2, (void **)&language2); - todo_wine ok(hr == S_OK || broken(hr == E_NOINTERFACE) /* <= Windows 10 1507 */, "Unexpected hr %#lx.\n", hr); if (FAILED(hr)) {