Rémi Bernon : windows.globalization: Implement IGlobalizationPreferencesStatics::Languages.

Alexandre Julliard julliard at winehq.org
Fri Mar 26 16:03:31 CDT 2021


Module: wine
Branch: master
Commit: 6302df9dc7b277ec30fd12c5a0fe2e4b8f933b1b
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=6302df9dc7b277ec30fd12c5a0fe2e4b8f933b1b

Author: Rémi Bernon <rbernon at codeweavers.com>
Date:   Fri Mar 26 10:24:58 2021 +0100

windows.globalization: Implement IGlobalizationPreferencesStatics::Languages.

Returning user default language in a 1-element HSTRING vector.

Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
Signed-off-by: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/windows.globalization/main.c                | 194 ++++++++++++++++++++++-
 dlls/windows.globalization/tests/globalization.c |  33 +++-
 2 files changed, 222 insertions(+), 5 deletions(-)

diff --git a/dlls/windows.globalization/main.c b/dlls/windows.globalization/main.c
index 84813152047..9aa07700310 100644
--- a/dlls/windows.globalization/main.c
+++ b/dlls/windows.globalization/main.c
@@ -48,6 +48,183 @@ static const char *debugstr_hstring(HSTRING hstr)
     return wine_dbgstr_wn(str, len);
 }
 
+struct hstring_vector
+{
+    IVectorView_HSTRING IVectorView_HSTRING_iface;
+    LONG ref;
+
+    ULONG count;
+    HSTRING values[1];
+};
+
+static inline struct hstring_vector *impl_from_IVectorView_HSTRING(IVectorView_HSTRING *iface)
+{
+    return CONTAINING_RECORD(iface, struct hstring_vector, IVectorView_HSTRING_iface);
+}
+
+static HRESULT STDMETHODCALLTYPE hstring_vector_QueryInterface(IVectorView_HSTRING *iface,
+        REFIID iid, void **out)
+{
+    struct hstring_vector *impl = impl_from_IVectorView_HSTRING(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_IVectorView_HSTRING))
+    {
+        IUnknown_AddRef(iface);
+        *out = &impl->IVectorView_HSTRING_iface;
+        return S_OK;
+    }
+
+    FIXME("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
+    *out = NULL;
+    return E_NOINTERFACE;
+}
+
+static ULONG STDMETHODCALLTYPE hstring_vector_AddRef(IVectorView_HSTRING *iface)
+{
+    struct hstring_vector *impl = impl_from_IVectorView_HSTRING(iface);
+    ULONG ref = InterlockedIncrement(&impl->ref);
+    TRACE("iface %p, ref %u.\n", iface, ref);
+    return ref;
+}
+
+static ULONG STDMETHODCALLTYPE hstring_vector_Release(IVectorView_HSTRING *iface)
+{
+    struct hstring_vector *impl = impl_from_IVectorView_HSTRING(iface);
+    ULONG ref = InterlockedDecrement(&impl->ref);
+    TRACE("iface %p, ref %u.\n", iface, ref);
+    if (ref == 0)
+    {
+        while (impl->count--) WindowsDeleteString(impl->values[impl->count]);
+        free(impl);
+    }
+    return ref;
+}
+
+static HRESULT STDMETHODCALLTYPE hstring_vector_GetIids(IVectorView_HSTRING *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 hstring_vector_GetRuntimeClassName(IVectorView_HSTRING *iface,
+        HSTRING *class_name)
+{
+    FIXME("iface %p, class_name %p stub!\n", iface, class_name);
+    return E_NOTIMPL;
+}
+
+static HRESULT STDMETHODCALLTYPE hstring_vector_GetTrustLevel(IVectorView_HSTRING *iface,
+        TrustLevel *trust_level)
+{
+    FIXME("iface %p, trust_level %p stub!\n", iface, trust_level);
+    return E_NOTIMPL;
+}
+
+static HRESULT STDMETHODCALLTYPE hstring_vector_GetAt(IVectorView_HSTRING *iface,
+        ULONG index, HSTRING *value)
+{
+    struct hstring_vector *impl = impl_from_IVectorView_HSTRING(iface);
+
+    TRACE("iface %p, index %#x, value %p.\n", iface, index, value);
+
+    *value = NULL;
+    if (index >= impl->count) return E_BOUNDS;
+    return WindowsDuplicateString(impl->values[index], value);
+}
+
+static HRESULT STDMETHODCALLTYPE hstring_vector_get_Size(IVectorView_HSTRING *iface,
+        ULONG *value)
+{
+    struct hstring_vector *impl = impl_from_IVectorView_HSTRING(iface);
+
+    TRACE("iface %p, value %p.\n", iface, value);
+
+    *value = impl->count;
+    return S_OK;
+}
+
+static HRESULT STDMETHODCALLTYPE hstring_vector_IndexOf(IVectorView_HSTRING *iface,
+        HSTRING element, ULONG *index, BOOLEAN *found)
+{
+    struct hstring_vector *impl = impl_from_IVectorView_HSTRING(iface);
+    INT32 i, order;
+
+    TRACE("iface %p, element %p, index %p, found %p.\n", iface, element, index, found);
+
+    for (i = 0; i < impl->count; ++i)
+        if (SUCCEEDED(WindowsCompareStringOrdinal(impl->values[i], element, &order)) && order == 0)
+            break;
+
+    if (i < impl->count)
+    {
+        *found = TRUE;
+        *index = i;
+    }
+    else
+    {
+        *found = FALSE;
+        *index = 0;
+    }
+
+    return S_OK;
+}
+
+static HRESULT STDMETHODCALLTYPE hstring_vector_GetMany(IVectorView_HSTRING *iface,
+        ULONG start_index, ULONG items_size, HSTRING *items, UINT *count)
+{
+    struct hstring_vector *impl = impl_from_IVectorView_HSTRING(iface);
+    HRESULT hr = S_OK;
+    ULONG i;
+
+    TRACE("iface %p, start_index %#x, items %p, count %p.\n", iface, start_index, items, count);
+
+    memset(items, 0, items_size * sizeof(HSTRING *));
+
+    for (i = start_index; i < impl->count && i < start_index + items_size; ++i)
+        if (FAILED(hr = WindowsDuplicateString(impl->values[i], items + i - start_index)))
+            break;
+
+    if (FAILED(hr)) while (i-- > start_index) WindowsDeleteString(items[i - start_index]);
+    *count = i - start_index;
+    return hr;
+}
+
+static const struct IVectorView_HSTRINGVtbl hstring_vector_vtbl =
+{
+    hstring_vector_QueryInterface,
+    hstring_vector_AddRef,
+    hstring_vector_Release,
+    /* IInspectable methods */
+    hstring_vector_GetIids,
+    hstring_vector_GetRuntimeClassName,
+    hstring_vector_GetTrustLevel,
+    /* IVectorView<HSTRING> methods */
+    hstring_vector_GetAt,
+    hstring_vector_get_Size,
+    hstring_vector_IndexOf,
+    hstring_vector_GetMany,
+};
+
+static HRESULT hstring_vector_create(HSTRING *values, SIZE_T count, IVectorView_HSTRING **out)
+{
+    struct hstring_vector *impl;
+
+    if (!(impl = malloc(offsetof(struct hstring_vector, values[count])))) return E_OUTOFMEMORY;
+    impl->ref = 1;
+
+    impl->IVectorView_HSTRING_iface.lpVtbl = &hstring_vector_vtbl;
+    impl->count = count;
+    memcpy(impl->values, values, count * sizeof(HSTRING));
+
+    *out = &impl->IVectorView_HSTRING_iface;
+    return S_OK;
+}
+
 struct windows_globalization
 {
     IActivationFactory IActivationFactory_iface;
@@ -218,8 +395,21 @@ static HRESULT STDMETHODCALLTYPE globalization_preferences_get_Currencies(
 static HRESULT STDMETHODCALLTYPE globalization_preferences_get_Languages(
         IGlobalizationPreferencesStatics *iface, IVectorView_HSTRING **out)
 {
-    FIXME("iface %p, out %p stub!\n", iface, out);
-    return E_NOTIMPL;
+    HSTRING hstring;
+    HRESULT hr;
+    WCHAR locale[LOCALE_NAME_MAX_LENGTH];
+
+    TRACE("iface %p, out %p.\n", iface, out);
+
+    if (!GetUserDefaultLocaleName(locale, LOCALE_NAME_MAX_LENGTH))
+        return E_FAIL;
+
+    TRACE("returning language %s\n", debugstr_w(locale));
+
+    if (FAILED(hr = WindowsCreateString(locale, wcslen(locale), &hstring)))
+        return hr;
+
+    return hstring_vector_create(&hstring, 1, out);
 }
 
 static HRESULT STDMETHODCALLTYPE globalization_preferences_get_HomeGeographicRegion(
diff --git a/dlls/windows.globalization/tests/globalization.c b/dlls/windows.globalization/tests/globalization.c
index 00d9cee5b0d..a2b47e53be5 100644
--- a/dlls/windows.globalization/tests/globalization.c
+++ b/dlls/windows.globalization/tests/globalization.c
@@ -108,8 +108,7 @@ static void test_GlobalizationPreferences(void)
     pWindowsDeleteString(tmp_str);
 
     hr = IGlobalizationPreferencesStatics_get_Languages(preferences_statics, &languages);
-    todo_wine ok(hr == S_OK, "IGlobalizationPreferencesStatics_get_Languages failed, hr %#x\n", hr);
-    if (FAILED(hr)) goto done;
+    ok(hr == S_OK, "IGlobalizationPreferencesStatics_get_Languages failed, hr %#x\n", hr);
 
     hr = IVectorView_HSTRING_QueryInterface(languages, &IID_IInspectable, (void **)&tmp_inspectable);
     ok(hr == S_OK, "IVectorView_HSTRING_QueryInterface failed, hr %#x\n", hr);
@@ -143,14 +142,42 @@ static void test_GlobalizationPreferences(void)
 
     pWindowsDeleteString(tmp_str);
 
+    hr = pWindowsCreateString(L"deadbeef", 8, &tmp_str);
+    ok(hr == S_OK, "WindowsCreateString failed, hr %#x\n", hr);
+
+    i = 0xdeadbeef;
+    found = TRUE;
+    hr = IVectorView_HSTRING_IndexOf(languages, tmp_str, &i, &found);
+    ok(hr == S_OK, "IVectorView_HSTRING_IndexOf failed, hr %#x\n", hr);
+    ok(i == 0 && found == FALSE, "IVectorView_HSTRING_IndexOf returned size %d, found %d\n", size, found);
+
+    pWindowsDeleteString(tmp_str);
+
     tmp_str = (HSTRING)0xdeadbeef;
     hr = IVectorView_HSTRING_GetAt(languages, size, &tmp_str);
     ok(hr == E_BOUNDS, "IVectorView_HSTRING_GetAt failed, hr %#x\n", hr);
     ok(tmp_str == NULL, "IVectorView_HSTRING_GetAt returned %p\n", tmp_str);
 
+    tmp_str = (HSTRING)0xdeadbeef;
+    hr = IVectorView_HSTRING_GetMany(languages, size, 1, &tmp_str, &i);
+    ok(hr == S_OK, "IVectorView_HSTRING_GetAt failed, hr %#x\n", hr);
+    ok(i == 0 && tmp_str == NULL, "IVectorView_HSTRING_GetMany returned count %u, str %p\n", i, tmp_str);
+
+    hr = IVectorView_HSTRING_GetMany(languages, 0, 1, &tmp_str, &i);
+    ok(hr == S_OK, "IVectorView_HSTRING_GetAt failed, hr %#x\n", hr);
+    ok(i == 1, "IVectorView_HSTRING_GetMany returned count %u, expected 1\n", i);
+
+    buf = pWindowsGetStringRawBuffer(tmp_str, &len);
+    ok(buf != NULL && len > 0, "WindowsGetStringRawBuffer returned buf %p, len %u\n", buf, len);
+
+    ok(wcslen(locale) == len && !memcmp(buf, locale, len),
+       "IGlobalizationPreferencesStatics_get_Languages 0 returned len %u, str %s, expected %s\n",
+       len, wine_dbgstr_w(buf), wine_dbgstr_w(locale));
+
+    pWindowsDeleteString(tmp_str);
+
     IVectorView_HSTRING_Release(languages);
 
-done:
     IGlobalizationPreferencesStatics_Release(preferences_statics);
 
     IAgileObject_Release(agile_object);




More information about the wine-cvs mailing list